github.com/bir3/gocompiler@v0.3.205/src/cmd/compile/internal/noder/irgen.go (about)

     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  	"regexp"
    10  	"sort"
    11  
    12  	"github.com/bir3/gocompiler/src/cmd/compile/internal/base"
    13  	"github.com/bir3/gocompiler/src/cmd/compile/internal/dwarfgen"
    14  	"github.com/bir3/gocompiler/src/cmd/compile/internal/ir"
    15  	"github.com/bir3/gocompiler/src/cmd/compile/internal/syntax"
    16  	"github.com/bir3/gocompiler/src/cmd/compile/internal/typecheck"
    17  	"github.com/bir3/gocompiler/src/cmd/compile/internal/types"
    18  	"github.com/bir3/gocompiler/src/cmd/compile/internal/types2"
    19  	"github.com/bir3/gocompiler/src/cmd/internal/src"
    20  )
    21  
    22  var versionErrorRx = regexp.MustCompile(`requires go[0-9]+\.[0-9]+ or later`)
    23  
    24  // checkFiles configures and runs the types2 checker on the given
    25  // parsed source files and then returns the result.
    26  func checkFiles(noders []*noder) (posMap, *types2.Package, *types2.Info) {
    27  	if base.SyntaxErrors() != 0 {
    28  		base.ErrorExit()
    29  	}
    30  
    31  	// setup and syntax error reporting
    32  	var m posMap
    33  	files := make([]*syntax.File, len(noders))
    34  	for i, p := range noders {
    35  		m.join(&p.posMap)
    36  		files[i] = p.file
    37  	}
    38  
    39  	// typechecking
    40  	ctxt := types2.NewContext()
    41  	importer := gcimports{
    42  		ctxt:     ctxt,
    43  		packages: make(map[string]*types2.Package),
    44  	}
    45  	conf := types2.Config{
    46  		Context:            ctxt,
    47  		GoVersion:          base.Flag.Lang,
    48  		IgnoreBranchErrors: true, // parser already checked via syntax.CheckBranches mode
    49  		Error: func(err error) {
    50  			terr := err.(types2.Error)
    51  			msg := terr.Msg
    52  			// if we have a version error, hint at the -lang setting
    53  			if versionErrorRx.MatchString(msg) {
    54  				msg = fmt.Sprintf("%s (-lang was set to %s; check go.mod)", msg, base.Flag.Lang)
    55  			}
    56  			base.ErrorfAt(m.makeXPos(terr.Pos), "%s", msg)
    57  		},
    58  		Importer:               &importer,
    59  		Sizes:                  &gcSizes{},
    60  		OldComparableSemantics: base.Flag.OldComparable, // default is new comparable semantics
    61  	}
    62  	info := &types2.Info{
    63  		StoreTypesInSyntax: true,
    64  		Defs:               make(map[*syntax.Name]types2.Object),
    65  		Uses:               make(map[*syntax.Name]types2.Object),
    66  		Selections:         make(map[*syntax.SelectorExpr]*types2.Selection),
    67  		Implicits:          make(map[syntax.Node]types2.Object),
    68  		Scopes:             make(map[syntax.Node]*types2.Scope),
    69  		Instances:          make(map[*syntax.Name]types2.Instance),
    70  		// expand as needed
    71  	}
    72  
    73  	pkg, err := conf.Check(base.Ctxt.Pkgpath, files, info)
    74  
    75  	// Check for anonymous interface cycles (#56103).
    76  	if base.Debug.InterfaceCycles == 0 {
    77  		var f cycleFinder
    78  		for _, file := range files {
    79  			syntax.Inspect(file, func(n syntax.Node) bool {
    80  				if n, ok := n.(*syntax.InterfaceType); ok {
    81  					if f.hasCycle(n.GetTypeInfo().Type.(*types2.Interface)) {
    82  						base.ErrorfAt(m.makeXPos(n.Pos()), "invalid recursive type: anonymous interface refers to itself (see https://go.dev/issue/56103)")
    83  
    84  						for typ := range f.cyclic {
    85  							f.cyclic[typ] = false // suppress duplicate errors
    86  						}
    87  					}
    88  					return false
    89  				}
    90  				return true
    91  			})
    92  		}
    93  	}
    94  
    95  	// Implementation restriction: we don't allow not-in-heap types to
    96  	// be used as type arguments (#54765).
    97  	{
    98  		type nihTarg struct {
    99  			pos src.XPos
   100  			typ types2.Type
   101  		}
   102  		var nihTargs []nihTarg
   103  
   104  		for name, inst := range info.Instances {
   105  			for i := 0; i < inst.TypeArgs.Len(); i++ {
   106  				if targ := inst.TypeArgs.At(i); isNotInHeap(targ) {
   107  					nihTargs = append(nihTargs, nihTarg{m.makeXPos(name.Pos()), targ})
   108  				}
   109  			}
   110  		}
   111  		sort.Slice(nihTargs, func(i, j int) bool {
   112  			ti, tj := nihTargs[i], nihTargs[j]
   113  			return ti.pos.Before(tj.pos)
   114  		})
   115  		for _, targ := range nihTargs {
   116  			base.ErrorfAt(targ.pos, "cannot use incomplete (or unallocatable) type as a type argument: %v", targ.typ)
   117  		}
   118  	}
   119  
   120  	base.ExitIfErrors()
   121  	if err != nil {
   122  		base.FatalfAt(src.NoXPos, "conf.Check error: %v", err)
   123  	}
   124  
   125  	return m, pkg, info
   126  }
   127  
   128  // check2 type checks a Go package using types2, and then generates IR
   129  // using the results.
   130  func check2(noders []*noder) {
   131  	m, pkg, info := checkFiles(noders)
   132  
   133  	g := irgen{
   134  		target: typecheck.Target,
   135  		self:   pkg,
   136  		info:   info,
   137  		posMap: m,
   138  		objs:   make(map[types2.Object]*ir.Name),
   139  		typs:   make(map[types2.Type]*types.Type),
   140  	}
   141  	g.generate(noders)
   142  }
   143  
   144  // Information about sub-dictionary entries in a dictionary
   145  type subDictInfo struct {
   146  	// Call or XDOT node that requires a dictionary.
   147  	callNode ir.Node
   148  	// Saved CallExpr.X node (*ir.SelectorExpr or *InstExpr node) for a generic
   149  	// method or function call, since this node will get dropped when the generic
   150  	// method/function call is transformed to a call on the instantiated shape
   151  	// function. Nil for other kinds of calls or XDOTs.
   152  	savedXNode ir.Node
   153  }
   154  
   155  // dictInfo is the dictionary format for an instantiation of a generic function with
   156  // particular shapes. shapeParams, derivedTypes, subDictCalls, itabConvs, and methodExprClosures
   157  // describe the actual dictionary entries in order, and the remaining fields are other info
   158  // needed in doing dictionary processing during compilation.
   159  type dictInfo struct {
   160  	// Types substituted for the type parameters, which are shape types.
   161  	shapeParams []*types.Type
   162  	// All types derived from those typeparams used in the instantiation.
   163  	derivedTypes []*types.Type
   164  	// Nodes in the instantiation that requires a subdictionary. Includes
   165  	// method and function calls (OCALL), function values (OFUNCINST), method
   166  	// values/expressions (OXDOT).
   167  	subDictCalls []subDictInfo
   168  	// Nodes in the instantiation that are a conversion from a typeparam/derived
   169  	// type to a specific interface.
   170  	itabConvs []ir.Node
   171  	// Method expression closures. For a generic type T with method M(arg1, arg2) res,
   172  	// these closures are func(rcvr T, arg1, arg2) res.
   173  	// These closures capture no variables, they are just the generic version of ·f symbols
   174  	// that live in the dictionary instead of in the readonly globals section.
   175  	methodExprClosures []methodExprClosure
   176  
   177  	// Mapping from each shape type that substitutes a type param, to its
   178  	// type bound (which is also substituted with shapes if it is parameterized)
   179  	shapeToBound map[*types.Type]*types.Type
   180  
   181  	// For type switches on nonempty interfaces, a map from OTYPE entries of
   182  	// HasShape type, to the interface type we're switching from.
   183  	type2switchType map[ir.Node]*types.Type
   184  
   185  	startSubDict            int // Start of dict entries for subdictionaries
   186  	startItabConv           int // Start of dict entries for itab conversions
   187  	startMethodExprClosures int // Start of dict entries for closures for method expressions
   188  	dictLen                 int // Total number of entries in dictionary
   189  }
   190  
   191  type methodExprClosure struct {
   192  	idx  int    // index in list of shape parameters
   193  	name string // method name
   194  }
   195  
   196  // instInfo is information gathered on an shape instantiation of a function.
   197  type instInfo struct {
   198  	fun       *ir.Func // The instantiated function (with body)
   199  	dictParam *ir.Name // The node inside fun that refers to the dictionary param
   200  
   201  	dictInfo *dictInfo
   202  }
   203  
   204  type irgen struct {
   205  	target *ir.Package
   206  	self   *types2.Package
   207  	info   *types2.Info
   208  
   209  	posMap
   210  	objs   map[types2.Object]*ir.Name
   211  	typs   map[types2.Type]*types.Type
   212  	marker dwarfgen.ScopeMarker
   213  
   214  	// laterFuncs records tasks that need to run after all declarations
   215  	// are processed.
   216  	laterFuncs []func()
   217  	// haveEmbed indicates whether the current node belongs to file that
   218  	// imports "embed" package.
   219  	haveEmbed bool
   220  
   221  	// exprStmtOK indicates whether it's safe to generate expressions or
   222  	// statements yet.
   223  	exprStmtOK bool
   224  
   225  	// types which we need to finish, by doing g.fillinMethods.
   226  	typesToFinalize []*typeDelayInfo
   227  
   228  	// True when we are compiling a top-level generic function or method. Use to
   229  	// avoid adding closures of generic functions/methods to the target.Decls
   230  	// list.
   231  	topFuncIsGeneric bool
   232  
   233  	// The context during type/function/method declarations that is used to
   234  	// uniquely name type parameters. We need unique names for type params so we
   235  	// can be sure they match up correctly between types2-to-types1 translation
   236  	// and types1 importing.
   237  	curDecl string
   238  }
   239  
   240  // genInst has the information for creating needed instantiations and modifying
   241  // functions to use instantiations.
   242  type genInst struct {
   243  	dnum int // for generating unique dictionary variables
   244  
   245  	// Map from the names of all instantiations to information about the
   246  	// instantiations.
   247  	instInfoMap map[*types.Sym]*instInfo
   248  
   249  	// Dictionary syms which we need to finish, by writing out any itabconv
   250  	// or method expression closure entries.
   251  	dictSymsToFinalize []*delayInfo
   252  
   253  	// New instantiations created during this round of buildInstantiations().
   254  	newInsts []ir.Node
   255  }
   256  
   257  func (g *irgen) later(fn func()) {
   258  	g.laterFuncs = append(g.laterFuncs, fn)
   259  }
   260  
   261  type delayInfo struct {
   262  	gf     *ir.Name
   263  	targs  []*types.Type
   264  	sym    *types.Sym
   265  	off    int
   266  	isMeth bool
   267  }
   268  
   269  type typeDelayInfo struct {
   270  	typ  *types2.Named
   271  	ntyp *types.Type
   272  }
   273  
   274  func (g *irgen) generate(noders []*noder) {
   275  	types.LocalPkg.Name = g.self.Name()
   276  	typecheck.TypecheckAllowed = true
   277  
   278  	// Prevent size calculations until we set the underlying type
   279  	// for all package-block defined types.
   280  	types.DeferCheckSize()
   281  
   282  	// At this point, types2 has already handled name resolution and
   283  	// type checking. We just need to map from its object and type
   284  	// representations to those currently used by the rest of the
   285  	// compiler. This happens in a few passes.
   286  
   287  	// 1. Process all import declarations. We use the compiler's own
   288  	// importer for this, rather than types2's gcimporter-derived one,
   289  	// to handle extensions and inline function bodies correctly.
   290  	//
   291  	// Also, we need to do this in a separate pass, because mappings are
   292  	// instantiated on demand. If we interleaved processing import
   293  	// declarations with other declarations, it's likely we'd end up
   294  	// wanting to map an object/type from another source file, but not
   295  	// yet have the import data it relies on.
   296  	declLists := make([][]syntax.Decl, len(noders))
   297  Outer:
   298  	for i, p := range noders {
   299  		g.pragmaFlags(p.file.Pragma, ir.GoBuildPragma)
   300  		for j, decl := range p.file.DeclList {
   301  			switch decl := decl.(type) {
   302  			case *syntax.ImportDecl:
   303  				g.importDecl(p, decl)
   304  			default:
   305  				declLists[i] = p.file.DeclList[j:]
   306  				continue Outer // no more ImportDecls
   307  			}
   308  		}
   309  	}
   310  
   311  	// 2. Process all package-block type declarations. As with imports,
   312  	// we need to make sure all types are properly instantiated before
   313  	// trying to map any expressions that utilize them. In particular,
   314  	// we need to make sure type pragmas are already known (see comment
   315  	// in irgen.typeDecl).
   316  	//
   317  	// We could perhaps instead defer processing of package-block
   318  	// variable initializers and function bodies, like noder does, but
   319  	// special-casing just package-block type declarations minimizes the
   320  	// differences between processing package-block and function-scoped
   321  	// declarations.
   322  	for _, declList := range declLists {
   323  		for _, decl := range declList {
   324  			switch decl := decl.(type) {
   325  			case *syntax.TypeDecl:
   326  				g.typeDecl((*ir.Nodes)(&g.target.Decls), decl)
   327  			}
   328  		}
   329  	}
   330  	types.ResumeCheckSize()
   331  
   332  	// 3. Process all remaining declarations.
   333  	for i, declList := range declLists {
   334  		old := g.haveEmbed
   335  		g.haveEmbed = noders[i].importedEmbed
   336  		g.decls((*ir.Nodes)(&g.target.Decls), declList)
   337  		g.haveEmbed = old
   338  	}
   339  	g.exprStmtOK = true
   340  
   341  	// 4. Run any "later" tasks. Avoid using 'range' so that tasks can
   342  	// recursively queue further tasks. (Not currently utilized though.)
   343  	for len(g.laterFuncs) > 0 {
   344  		fn := g.laterFuncs[0]
   345  		g.laterFuncs = g.laterFuncs[1:]
   346  		fn()
   347  	}
   348  
   349  	if base.Flag.W > 1 {
   350  		for _, n := range g.target.Decls {
   351  			s := fmt.Sprintf("\nafter noder2 %v", n)
   352  			ir.Dump(s, n)
   353  		}
   354  	}
   355  
   356  	for _, p := range noders {
   357  		// Process linkname and cgo pragmas.
   358  		p.processPragmas()
   359  
   360  		// Double check for any type-checking inconsistencies. This can be
   361  		// removed once we're confident in IR generation results.
   362  		syntax.Crawl(p.file, func(n syntax.Node) bool {
   363  			g.validate(n)
   364  			return false
   365  		})
   366  	}
   367  
   368  	if base.Flag.Complete {
   369  		for _, n := range g.target.Decls {
   370  			if fn, ok := n.(*ir.Func); ok {
   371  				if fn.Body == nil && fn.Nname.Sym().Linkname == "" {
   372  					base.ErrorfAt(fn.Pos(), "missing function body")
   373  				}
   374  			}
   375  		}
   376  	}
   377  
   378  	// Check for unusual case where noder2 encounters a type error that types2
   379  	// doesn't check for (e.g. notinheap incompatibility).
   380  	base.ExitIfErrors()
   381  
   382  	typecheck.DeclareUniverse()
   383  
   384  	// Create any needed instantiations of generic functions and transform
   385  	// existing and new functions to use those instantiations.
   386  	BuildInstantiations()
   387  
   388  	// Remove all generic functions from g.target.Decl, since they have been
   389  	// used for stenciling, but don't compile. Generic functions will already
   390  	// have been marked for export as appropriate.
   391  	j := 0
   392  	for i, decl := range g.target.Decls {
   393  		if decl.Op() != ir.ODCLFUNC || !decl.Type().HasTParam() {
   394  			g.target.Decls[j] = g.target.Decls[i]
   395  			j++
   396  		}
   397  	}
   398  	g.target.Decls = g.target.Decls[:j]
   399  
   400  	base.Assertf(len(g.laterFuncs) == 0, "still have %d later funcs", len(g.laterFuncs))
   401  }
   402  
   403  func (g *irgen) unhandled(what string, p poser) {
   404  	base.FatalfAt(g.pos(p), "unhandled %s: %T", what, p)
   405  	panic("unreachable")
   406  }
   407  
   408  // delayTransform returns true if we should delay all transforms, because we are
   409  // creating the nodes for a generic function/method.
   410  func (g *irgen) delayTransform() bool {
   411  	return g.topFuncIsGeneric
   412  }
   413  
   414  func (g *irgen) typeAndValue(x syntax.Expr) syntax.TypeAndValue {
   415  	tv := x.GetTypeInfo()
   416  	if tv.Type == nil {
   417  		base.FatalfAt(g.pos(x), "missing type for %v (%T)", x, x)
   418  	}
   419  	return tv
   420  }
   421  
   422  func (g *irgen) type2(x syntax.Expr) syntax.Type {
   423  	tv := x.GetTypeInfo()
   424  	if tv.Type == nil {
   425  		base.FatalfAt(g.pos(x), "missing type for %v (%T)", x, x)
   426  	}
   427  	return tv.Type
   428  }
   429  
   430  // A cycleFinder detects anonymous interface cycles (go.dev/issue/56103).
   431  type cycleFinder struct {
   432  	cyclic map[*types2.Interface]bool
   433  }
   434  
   435  // hasCycle reports whether typ is part of an anonymous interface cycle.
   436  func (f *cycleFinder) hasCycle(typ *types2.Interface) bool {
   437  	// We use Method instead of ExplicitMethod to implicitly expand any
   438  	// embedded interfaces. Then we just need to walk any anonymous
   439  	// types, keeping track of *types2.Interface types we visit along
   440  	// the way.
   441  	for i := 0; i < typ.NumMethods(); i++ {
   442  		if f.visit(typ.Method(i).Type()) {
   443  			return true
   444  		}
   445  	}
   446  	return false
   447  }
   448  
   449  // visit recursively walks typ0 to check any referenced interface types.
   450  func (f *cycleFinder) visit(typ0 types2.Type) bool {
   451  	for { // loop for tail recursion
   452  		switch typ := typ0.(type) {
   453  		default:
   454  			base.Fatalf("unexpected type: %T", typ)
   455  
   456  		case *types2.Basic, *types2.Named, *types2.TypeParam:
   457  			return false // named types cannot be part of an anonymous cycle
   458  		case *types2.Pointer:
   459  			typ0 = typ.Elem()
   460  		case *types2.Array:
   461  			typ0 = typ.Elem()
   462  		case *types2.Chan:
   463  			typ0 = typ.Elem()
   464  		case *types2.Map:
   465  			if f.visit(typ.Key()) {
   466  				return true
   467  			}
   468  			typ0 = typ.Elem()
   469  		case *types2.Slice:
   470  			typ0 = typ.Elem()
   471  
   472  		case *types2.Struct:
   473  			for i := 0; i < typ.NumFields(); i++ {
   474  				if f.visit(typ.Field(i).Type()) {
   475  					return true
   476  				}
   477  			}
   478  			return false
   479  
   480  		case *types2.Interface:
   481  			// The empty interface (e.g., "any") cannot be part of a cycle.
   482  			if typ.NumExplicitMethods() == 0 && typ.NumEmbeddeds() == 0 {
   483  				return false
   484  			}
   485  
   486  			// As an optimization, we wait to allocate cyclic here, after
   487  			// we've found at least one other (non-empty) anonymous
   488  			// interface. This means when a cycle is present, we need to
   489  			// make an extra recursive call to actually detect it. But for
   490  			// most packages, it allows skipping the map allocation
   491  			// entirely.
   492  			if x, ok := f.cyclic[typ]; ok {
   493  				return x
   494  			}
   495  			if f.cyclic == nil {
   496  				f.cyclic = make(map[*types2.Interface]bool)
   497  			}
   498  			f.cyclic[typ] = true
   499  			if f.hasCycle(typ) {
   500  				return true
   501  			}
   502  			f.cyclic[typ] = false
   503  			return false
   504  
   505  		case *types2.Signature:
   506  			return f.visit(typ.Params()) || f.visit(typ.Results())
   507  		case *types2.Tuple:
   508  			for i := 0; i < typ.Len(); i++ {
   509  				if f.visit(typ.At(i).Type()) {
   510  					return true
   511  				}
   512  			}
   513  			return false
   514  		}
   515  	}
   516  }