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