Source file src/cmd/compile/internal/noder/irgen.go

     1  // Copyright 2021 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package noder
     6  
     7  import (
     8  	"fmt"
     9  	"os"
    10  
    11  	"cmd/compile/internal/base"
    12  	"cmd/compile/internal/dwarfgen"
    13  	"cmd/compile/internal/ir"
    14  	"cmd/compile/internal/syntax"
    15  	"cmd/compile/internal/typecheck"
    16  	"cmd/compile/internal/types"
    17  	"cmd/compile/internal/types2"
    18  	"cmd/internal/src"
    19  )
    20  
    21  // checkFiles configures and runs the types2 checker on the given
    22  // parsed source files and then returns the result.
    23  func checkFiles(noders []*noder) (posMap, *types2.Package, *types2.Info) {
    24  	if base.SyntaxErrors() != 0 {
    25  		base.ErrorExit()
    26  	}
    27  
    28  	// setup and syntax error reporting
    29  	var m posMap
    30  	files := make([]*syntax.File, len(noders))
    31  	for i, p := range noders {
    32  		m.join(&p.posMap)
    33  		files[i] = p.file
    34  	}
    35  
    36  	// typechecking
    37  	ctxt := types2.NewContext()
    38  	importer := gcimports{
    39  		ctxt:     ctxt,
    40  		packages: map[string]*types2.Package{"unsafe": types2.Unsafe},
    41  	}
    42  	conf := types2.Config{
    43  		Context:               ctxt,
    44  		GoVersion:             base.Flag.Lang,
    45  		IgnoreLabels:          true, // parser already checked via syntax.CheckBranches mode
    46  		CompilerErrorMessages: true, // use error strings matching existing compiler errors
    47  		Error: func(err error) {
    48  			terr := err.(types2.Error)
    49  			base.ErrorfAt(m.makeXPos(terr.Pos), "%s", terr.Msg)
    50  		},
    51  		Importer: &importer,
    52  		Sizes:    &gcSizes{},
    53  	}
    54  	info := &types2.Info{
    55  		Types:      make(map[syntax.Expr]types2.TypeAndValue),
    56  		Defs:       make(map[*syntax.Name]types2.Object),
    57  		Uses:       make(map[*syntax.Name]types2.Object),
    58  		Selections: make(map[*syntax.SelectorExpr]*types2.Selection),
    59  		Implicits:  make(map[syntax.Node]types2.Object),
    60  		Scopes:     make(map[syntax.Node]*types2.Scope),
    61  		Instances:  make(map[*syntax.Name]types2.Instance),
    62  		// expand as needed
    63  	}
    64  
    65  	pkg, err := conf.Check(base.Ctxt.Pkgpath, files, info)
    66  
    67  	base.ExitIfErrors()
    68  	if err != nil {
    69  		base.FatalfAt(src.NoXPos, "conf.Check error: %v", err)
    70  	}
    71  
    72  	return m, pkg, info
    73  }
    74  
    75  // check2 type checks a Go package using types2, and then generates IR
    76  // using the results.
    77  func check2(noders []*noder) {
    78  	m, pkg, info := checkFiles(noders)
    79  
    80  	if base.Flag.G < 2 {
    81  		os.Exit(0)
    82  	}
    83  
    84  	g := irgen{
    85  		target: typecheck.Target,
    86  		self:   pkg,
    87  		info:   info,
    88  		posMap: m,
    89  		objs:   make(map[types2.Object]*ir.Name),
    90  		typs:   make(map[types2.Type]*types.Type),
    91  	}
    92  	g.generate(noders)
    93  
    94  	if base.Flag.G < 3 {
    95  		os.Exit(0)
    96  	}
    97  }
    98  
    99  // Information about sub-dictionary entries in a dictionary
   100  type subDictInfo struct {
   101  	// Call or XDOT node that requires a dictionary.
   102  	callNode ir.Node
   103  	// Saved CallExpr.X node (*ir.SelectorExpr or *InstExpr node) for a generic
   104  	// method or function call, since this node will get dropped when the generic
   105  	// method/function call is transformed to a call on the instantiated shape
   106  	// function. Nil for other kinds of calls or XDOTs.
   107  	savedXNode ir.Node
   108  }
   109  
   110  // dictInfo is the dictionary format for an instantiation of a generic function with
   111  // particular shapes. shapeParams, derivedTypes, subDictCalls, and itabConvs describe
   112  // the actual dictionary entries in order, and the remaining fields are other info
   113  // needed in doing dictionary processing during compilation.
   114  type dictInfo struct {
   115  	// Types substituted for the type parameters, which are shape types.
   116  	shapeParams []*types.Type
   117  	// All types derived from those typeparams used in the instantiation.
   118  	derivedTypes []*types.Type
   119  	// Nodes in the instantiation that requires a subdictionary. Includes
   120  	// method and function calls (OCALL), function values (OFUNCINST), method
   121  	// values/expressions (OXDOT).
   122  	subDictCalls []subDictInfo
   123  	// Nodes in the instantiation that are a conversion from a typeparam/derived
   124  	// type to a specific interface.
   125  	itabConvs []ir.Node
   126  
   127  	// Mapping from each shape type that substitutes a type param, to its
   128  	// type bound (which is also substituted with shapes if it is parameterized)
   129  	shapeToBound map[*types.Type]*types.Type
   130  
   131  	// For type switches on nonempty interfaces, a map from OTYPE entries of
   132  	// HasShape type, to the interface type we're switching from.
   133  	type2switchType map[ir.Node]*types.Type
   134  
   135  	startSubDict  int // Start of dict entries for subdictionaries
   136  	startItabConv int // Start of dict entries for itab conversions
   137  	dictLen       int // Total number of entries in dictionary
   138  }
   139  
   140  // instInfo is information gathered on an shape instantiation of a function.
   141  type instInfo struct {
   142  	fun       *ir.Func // The instantiated function (with body)
   143  	dictParam *ir.Name // The node inside fun that refers to the dictionary param
   144  
   145  	dictInfo *dictInfo
   146  }
   147  
   148  type irgen struct {
   149  	target *ir.Package
   150  	self   *types2.Package
   151  	info   *types2.Info
   152  
   153  	posMap
   154  	objs   map[types2.Object]*ir.Name
   155  	typs   map[types2.Type]*types.Type
   156  	marker dwarfgen.ScopeMarker
   157  
   158  	// laterFuncs records tasks that need to run after all declarations
   159  	// are processed.
   160  	laterFuncs []func()
   161  	// haveEmbed indicates whether the current node belongs to file that
   162  	// imports "embed" package.
   163  	haveEmbed bool
   164  
   165  	// exprStmtOK indicates whether it's safe to generate expressions or
   166  	// statements yet.
   167  	exprStmtOK bool
   168  
   169  	// types which we need to finish, by doing g.fillinMethods.
   170  	typesToFinalize []*typeDelayInfo
   171  
   172  	// True when we are compiling a top-level generic function or method. Use to
   173  	// avoid adding closures of generic functions/methods to the target.Decls
   174  	// list.
   175  	topFuncIsGeneric bool
   176  
   177  	// The context during type/function/method declarations that is used to
   178  	// uniquely name type parameters. We need unique names for type params so we
   179  	// can be sure they match up correctly between types2-to-types1 translation
   180  	// and types1 importing.
   181  	curDecl string
   182  }
   183  
   184  // genInst has the information for creating needed instantiations and modifying
   185  // functions to use instantiations.
   186  type genInst struct {
   187  	dnum int // for generating unique dictionary variables
   188  
   189  	// Map from the names of all instantiations to information about the
   190  	// instantiations.
   191  	instInfoMap map[*types.Sym]*instInfo
   192  
   193  	// Dictionary syms which we need to finish, by writing out any itabconv
   194  	// entries.
   195  	dictSymsToFinalize []*delayInfo
   196  
   197  	// New instantiations created during this round of buildInstantiations().
   198  	newInsts []ir.Node
   199  }
   200  
   201  func (g *irgen) later(fn func()) {
   202  	g.laterFuncs = append(g.laterFuncs, fn)
   203  }
   204  
   205  type delayInfo struct {
   206  	gf     *ir.Name
   207  	targs  []*types.Type
   208  	sym    *types.Sym
   209  	off    int
   210  	isMeth bool
   211  }
   212  
   213  type typeDelayInfo struct {
   214  	typ  *types2.Named
   215  	ntyp *types.Type
   216  }
   217  
   218  func (g *irgen) generate(noders []*noder) {
   219  	types.LocalPkg.Name = g.self.Name()
   220  	types.LocalPkg.Height = g.self.Height()
   221  	typecheck.TypecheckAllowed = true
   222  
   223  	// Prevent size calculations until we set the underlying type
   224  	// for all package-block defined types.
   225  	types.DeferCheckSize()
   226  
   227  	// At this point, types2 has already handled name resolution and
   228  	// type checking. We just need to map from its object and type
   229  	// representations to those currently used by the rest of the
   230  	// compiler. This happens in a few passes.
   231  
   232  	// 1. Process all import declarations. We use the compiler's own
   233  	// importer for this, rather than types2's gcimporter-derived one,
   234  	// to handle extensions and inline function bodies correctly.
   235  	//
   236  	// Also, we need to do this in a separate pass, because mappings are
   237  	// instantiated on demand. If we interleaved processing import
   238  	// declarations with other declarations, it's likely we'd end up
   239  	// wanting to map an object/type from another source file, but not
   240  	// yet have the import data it relies on.
   241  	declLists := make([][]syntax.Decl, len(noders))
   242  Outer:
   243  	for i, p := range noders {
   244  		g.pragmaFlags(p.file.Pragma, ir.GoBuildPragma)
   245  		for j, decl := range p.file.DeclList {
   246  			switch decl := decl.(type) {
   247  			case *syntax.ImportDecl:
   248  				g.importDecl(p, decl)
   249  			default:
   250  				declLists[i] = p.file.DeclList[j:]
   251  				continue Outer // no more ImportDecls
   252  			}
   253  		}
   254  	}
   255  
   256  	// 2. Process all package-block type declarations. As with imports,
   257  	// we need to make sure all types are properly instantiated before
   258  	// trying to map any expressions that utilize them. In particular,
   259  	// we need to make sure type pragmas are already known (see comment
   260  	// in irgen.typeDecl).
   261  	//
   262  	// We could perhaps instead defer processing of package-block
   263  	// variable initializers and function bodies, like noder does, but
   264  	// special-casing just package-block type declarations minimizes the
   265  	// differences between processing package-block and function-scoped
   266  	// declarations.
   267  	for _, declList := range declLists {
   268  		for _, decl := range declList {
   269  			switch decl := decl.(type) {
   270  			case *syntax.TypeDecl:
   271  				g.typeDecl((*ir.Nodes)(&g.target.Decls), decl)
   272  			}
   273  		}
   274  	}
   275  	types.ResumeCheckSize()
   276  
   277  	// 3. Process all remaining declarations.
   278  	for i, declList := range declLists {
   279  		old := g.haveEmbed
   280  		g.haveEmbed = noders[i].importedEmbed
   281  		g.decls((*ir.Nodes)(&g.target.Decls), declList)
   282  		g.haveEmbed = old
   283  	}
   284  	g.exprStmtOK = true
   285  
   286  	// 4. Run any "later" tasks. Avoid using 'range' so that tasks can
   287  	// recursively queue further tasks. (Not currently utilized though.)
   288  	for len(g.laterFuncs) > 0 {
   289  		fn := g.laterFuncs[0]
   290  		g.laterFuncs = g.laterFuncs[1:]
   291  		fn()
   292  	}
   293  
   294  	if base.Flag.W > 1 {
   295  		for _, n := range g.target.Decls {
   296  			s := fmt.Sprintf("\nafter noder2 %v", n)
   297  			ir.Dump(s, n)
   298  		}
   299  	}
   300  
   301  	for _, p := range noders {
   302  		// Process linkname and cgo pragmas.
   303  		p.processPragmas()
   304  
   305  		// Double check for any type-checking inconsistencies. This can be
   306  		// removed once we're confident in IR generation results.
   307  		syntax.Crawl(p.file, func(n syntax.Node) bool {
   308  			g.validate(n)
   309  			return false
   310  		})
   311  	}
   312  
   313  	if base.Flag.Complete {
   314  		for _, n := range g.target.Decls {
   315  			if fn, ok := n.(*ir.Func); ok {
   316  				if fn.Body == nil && fn.Nname.Sym().Linkname == "" {
   317  					base.ErrorfAt(fn.Pos(), "missing function body")
   318  				}
   319  			}
   320  		}
   321  	}
   322  
   323  	// Check for unusual case where noder2 encounters a type error that types2
   324  	// doesn't check for (e.g. notinheap incompatibility).
   325  	base.ExitIfErrors()
   326  
   327  	typecheck.DeclareUniverse()
   328  
   329  	// Create any needed instantiations of generic functions and transform
   330  	// existing and new functions to use those instantiations.
   331  	BuildInstantiations()
   332  
   333  	// Remove all generic functions from g.target.Decl, since they have been
   334  	// used for stenciling, but don't compile. Generic functions will already
   335  	// have been marked for export as appropriate.
   336  	j := 0
   337  	for i, decl := range g.target.Decls {
   338  		if decl.Op() != ir.ODCLFUNC || !decl.Type().HasTParam() {
   339  			g.target.Decls[j] = g.target.Decls[i]
   340  			j++
   341  		}
   342  	}
   343  	g.target.Decls = g.target.Decls[:j]
   344  
   345  	base.Assertf(len(g.laterFuncs) == 0, "still have %d later funcs", len(g.laterFuncs))
   346  }
   347  
   348  func (g *irgen) unhandled(what string, p poser) {
   349  	base.FatalfAt(g.pos(p), "unhandled %s: %T", what, p)
   350  	panic("unreachable")
   351  }
   352  
   353  // delayTransform returns true if we should delay all transforms, because we are
   354  // creating the nodes for a generic function/method.
   355  func (g *irgen) delayTransform() bool {
   356  	return g.topFuncIsGeneric
   357  }
   358  

View as plain text