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 5package noder 6 7import ( 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. 23func 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. 77func 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// dictInfo is the dictionary format for an instantiation of a generic function with 100// particular shapes. shapeParams, derivedTypes, subDictCalls, and itabConvs describe 101// the actual dictionary entries in order, and the remaining fields are other info 102// needed in doing dictionary processing during compilation. 103type dictInfo struct { 104 // Types substituted for the type parameters, which are shape types. 105 shapeParams []*types.Type 106 // All types derived from those typeparams used in the instantiation. 107 derivedTypes []*types.Type 108 // Nodes in the instantiation that requires a subdictionary. Includes 109 // method and function calls (OCALL), function values (OFUNCINST), method 110 // values/expressions (OXDOT). 111 subDictCalls []ir.Node 112 // Nodes in the instantiation that are a conversion from a typeparam/derived 113 // type to a specific interface. 114 itabConvs []ir.Node 115 116 // Mapping from each shape type that substitutes a type param, to its 117 // type bound (which is also substituted with shapes if it is parameterized) 118 shapeToBound map[*types.Type]*types.Type 119 120 // For type switches on nonempty interfaces, a map from OTYPE entries of 121 // HasShape type, to the interface type we're switching from. 122 type2switchType map[ir.Node]*types.Type 123 124 startSubDict int // Start of dict entries for subdictionaries 125 startItabConv int // Start of dict entries for itab conversions 126 dictLen int // Total number of entries in dictionary 127} 128 129// instInfo is information gathered on an shape instantiation of a function. 130type instInfo struct { 131 fun *ir.Func // The instantiated function (with body) 132 dictParam *ir.Name // The node inside fun that refers to the dictionary param 133 134 dictInfo *dictInfo 135} 136 137type irgen struct { 138 target *ir.Package 139 self *types2.Package 140 info *types2.Info 141 142 posMap 143 objs map[types2.Object]*ir.Name 144 typs map[types2.Type]*types.Type 145 marker dwarfgen.ScopeMarker 146 147 // laterFuncs records tasks that need to run after all declarations 148 // are processed. 149 laterFuncs []func() 150 // haveEmbed indicates whether the current node belongs to file that 151 // imports "embed" package. 152 haveEmbed bool 153 154 // exprStmtOK indicates whether it's safe to generate expressions or 155 // statements yet. 156 exprStmtOK bool 157 158 // types which we need to finish, by doing g.fillinMethods. 159 typesToFinalize []*typeDelayInfo 160 161 // True when we are compiling a top-level generic function or method. Use to 162 // avoid adding closures of generic functions/methods to the target.Decls 163 // list. 164 topFuncIsGeneric bool 165 166 // The context during type/function/method declarations that is used to 167 // uniquely name type parameters. We need unique names for type params so we 168 // can be sure they match up correctly between types2-to-types1 translation 169 // and types1 importing. 170 curDecl string 171} 172 173// genInst has the information for creating needed instantiations and modifying 174// functions to use instantiations. 175type genInst struct { 176 dnum int // for generating unique dictionary variables 177 178 // Map from the names of all instantiations to information about the 179 // instantiations. 180 instInfoMap map[*types.Sym]*instInfo 181 182 // Dictionary syms which we need to finish, by writing out any itabconv 183 // entries. 184 dictSymsToFinalize []*delayInfo 185 186 // New instantiations created during this round of buildInstantiations(). 187 newInsts []ir.Node 188} 189 190func (g *irgen) later(fn func()) { 191 g.laterFuncs = append(g.laterFuncs, fn) 192} 193 194type delayInfo struct { 195 gf *ir.Name 196 targs []*types.Type 197 sym *types.Sym 198 off int 199 isMeth bool 200} 201 202type typeDelayInfo struct { 203 typ *types2.Named 204 ntyp *types.Type 205} 206 207func (g *irgen) generate(noders []*noder) { 208 types.LocalPkg.Name = g.self.Name() 209 types.LocalPkg.Height = g.self.Height() 210 typecheck.TypecheckAllowed = true 211 212 // Prevent size calculations until we set the underlying type 213 // for all package-block defined types. 214 types.DeferCheckSize() 215 216 // At this point, types2 has already handled name resolution and 217 // type checking. We just need to map from its object and type 218 // representations to those currently used by the rest of the 219 // compiler. This happens in a few passes. 220 221 // 1. Process all import declarations. We use the compiler's own 222 // importer for this, rather than types2's gcimporter-derived one, 223 // to handle extensions and inline function bodies correctly. 224 // 225 // Also, we need to do this in a separate pass, because mappings are 226 // instantiated on demand. If we interleaved processing import 227 // declarations with other declarations, it's likely we'd end up 228 // wanting to map an object/type from another source file, but not 229 // yet have the import data it relies on. 230 declLists := make([][]syntax.Decl, len(noders)) 231Outer: 232 for i, p := range noders { 233 g.pragmaFlags(p.file.Pragma, ir.GoBuildPragma) 234 for j, decl := range p.file.DeclList { 235 switch decl := decl.(type) { 236 case *syntax.ImportDecl: 237 g.importDecl(p, decl) 238 default: 239 declLists[i] = p.file.DeclList[j:] 240 continue Outer // no more ImportDecls 241 } 242 } 243 } 244 245 // 2. Process all package-block type declarations. As with imports, 246 // we need to make sure all types are properly instantiated before 247 // trying to map any expressions that utilize them. In particular, 248 // we need to make sure type pragmas are already known (see comment 249 // in irgen.typeDecl). 250 // 251 // We could perhaps instead defer processing of package-block 252 // variable initializers and function bodies, like noder does, but 253 // special-casing just package-block type declarations minimizes the 254 // differences between processing package-block and function-scoped 255 // declarations. 256 for _, declList := range declLists { 257 for _, decl := range declList { 258 switch decl := decl.(type) { 259 case *syntax.TypeDecl: 260 g.typeDecl((*ir.Nodes)(&g.target.Decls), decl) 261 } 262 } 263 } 264 types.ResumeCheckSize() 265 266 // 3. Process all remaining declarations. 267 for i, declList := range declLists { 268 old := g.haveEmbed 269 g.haveEmbed = noders[i].importedEmbed 270 g.decls((*ir.Nodes)(&g.target.Decls), declList) 271 g.haveEmbed = old 272 } 273 g.exprStmtOK = true 274 275 // 4. Run any "later" tasks. Avoid using 'range' so that tasks can 276 // recursively queue further tasks. (Not currently utilized though.) 277 for len(g.laterFuncs) > 0 { 278 fn := g.laterFuncs[0] 279 g.laterFuncs = g.laterFuncs[1:] 280 fn() 281 } 282 283 if base.Flag.W > 1 { 284 for _, n := range g.target.Decls { 285 s := fmt.Sprintf("\nafter noder2 %v", n) 286 ir.Dump(s, n) 287 } 288 } 289 290 for _, p := range noders { 291 // Process linkname and cgo pragmas. 292 p.processPragmas() 293 294 // Double check for any type-checking inconsistencies. This can be 295 // removed once we're confident in IR generation results. 296 syntax.Crawl(p.file, func(n syntax.Node) bool { 297 g.validate(n) 298 return false 299 }) 300 } 301 302 if base.Flag.Complete { 303 for _, n := range g.target.Decls { 304 if fn, ok := n.(*ir.Func); ok { 305 if fn.Body == nil && fn.Nname.Sym().Linkname == "" { 306 base.ErrorfAt(fn.Pos(), "missing function body") 307 } 308 } 309 } 310 } 311 312 // Check for unusual case where noder2 encounters a type error that types2 313 // doesn't check for (e.g. notinheap incompatibility). 314 base.ExitIfErrors() 315 316 typecheck.DeclareUniverse() 317 318 // Create any needed instantiations of generic functions and transform 319 // existing and new functions to use those instantiations. 320 BuildInstantiations(true) 321 322 // Remove all generic functions from g.target.Decl, since they have been 323 // used for stenciling, but don't compile. Generic functions will already 324 // have been marked for export as appropriate. 325 j := 0 326 for i, decl := range g.target.Decls { 327 if decl.Op() != ir.ODCLFUNC || !decl.Type().HasTParam() { 328 g.target.Decls[j] = g.target.Decls[i] 329 j++ 330 } 331 } 332 g.target.Decls = g.target.Decls[:j] 333 334 base.Assertf(len(g.laterFuncs) == 0, "still have %d later funcs", len(g.laterFuncs)) 335} 336 337func (g *irgen) unhandled(what string, p poser) { 338 base.FatalfAt(g.pos(p), "unhandled %s: %T", what, p) 339 panic("unreachable") 340} 341 342// delayTransform returns true if we should delay all transforms, because we are 343// creating the nodes for a generic function/method. 344func (g *irgen) delayTransform() bool { 345 return g.topFuncIsGeneric 346} 347