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 }