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	"go/constant"
10	"go/token"
11	"go/version"
12	"internal/buildcfg"
13	"internal/pkgbits"
14	"os"
15	"strings"
16
17	"cmd/compile/internal/base"
18	"cmd/compile/internal/ir"
19	"cmd/compile/internal/syntax"
20	"cmd/compile/internal/types"
21	"cmd/compile/internal/types2"
22)
23
24// This file implements the Unified IR package writer and defines the
25// Unified IR export data format.
26//
27// Low-level coding details (e.g., byte-encoding of individual
28// primitive values, or handling element bitstreams and
29// cross-references) are handled by internal/pkgbits, so here we only
30// concern ourselves with higher-level worries like mapping Go
31// language constructs into elements.
32
33// There are two central types in the writing process: the "writer"
34// type handles writing out individual elements, while the "pkgWriter"
35// type keeps track of which elements have already been created.
36//
37// For each sort of "thing" (e.g., position, package, object, type)
38// that can be written into the export data, there are generally
39// several methods that work together:
40//
41// - writer.thing handles writing out a *use* of a thing, which often
42//   means writing a relocation to that thing's encoded index.
43//
44// - pkgWriter.thingIdx handles reserving an index for a thing, and
45//   writing out any elements needed for the thing.
46//
47// - writer.doThing handles writing out the *definition* of a thing,
48//   which in general is a mix of low-level coding primitives (e.g.,
49//   ints and strings) or uses of other things.
50//
51// A design goal of Unified IR is to have a single, canonical writer
52// implementation, but multiple reader implementations each tailored
53// to their respective needs. For example, within cmd/compile's own
54// backend, inlining is implemented largely by just re-running the
55// function body reading code.
56
57// TODO(mdempsky): Add an importer for Unified IR to the x/tools repo,
58// and better document the file format boundary between public and
59// private data.
60
61// A pkgWriter constructs Unified IR export data from the results of
62// running the types2 type checker on a Go compilation unit.
63type pkgWriter struct {
64	pkgbits.PkgEncoder
65
66	m                     posMap
67	curpkg                *types2.Package
68	info                  *types2.Info
69	rangeFuncBodyClosures map[*syntax.FuncLit]bool // non-public information, e.g., which functions are closures range function bodies?
70
71	// Indices for previously written syntax and types2 things.
72
73	posBasesIdx map[*syntax.PosBase]pkgbits.Index
74	pkgsIdx     map[*types2.Package]pkgbits.Index
75	typsIdx     map[types2.Type]pkgbits.Index
76	objsIdx     map[types2.Object]pkgbits.Index
77
78	// Maps from types2.Objects back to their syntax.Decl.
79
80	funDecls map[*types2.Func]*syntax.FuncDecl
81	typDecls map[*types2.TypeName]typeDeclGen
82
83	// linknames maps package-scope objects to their linker symbol name,
84	// if specified by a //go:linkname directive.
85	linknames map[types2.Object]string
86
87	// cgoPragmas accumulates any //go:cgo_* pragmas that need to be
88	// passed through to cmd/link.
89	cgoPragmas [][]string
90}
91
92// newPkgWriter returns an initialized pkgWriter for the specified
93// package.
94func newPkgWriter(m posMap, pkg *types2.Package, info *types2.Info, otherInfo map[*syntax.FuncLit]bool) *pkgWriter {
95	return &pkgWriter{
96		PkgEncoder: pkgbits.NewPkgEncoder(base.Debug.SyncFrames),
97
98		m:                     m,
99		curpkg:                pkg,
100		info:                  info,
101		rangeFuncBodyClosures: otherInfo,
102
103		pkgsIdx: make(map[*types2.Package]pkgbits.Index),
104		objsIdx: make(map[types2.Object]pkgbits.Index),
105		typsIdx: make(map[types2.Type]pkgbits.Index),
106
107		posBasesIdx: make(map[*syntax.PosBase]pkgbits.Index),
108
109		funDecls: make(map[*types2.Func]*syntax.FuncDecl),
110		typDecls: make(map[*types2.TypeName]typeDeclGen),
111
112		linknames: make(map[types2.Object]string),
113	}
114}
115
116// errorf reports a user error about thing p.
117func (pw *pkgWriter) errorf(p poser, msg string, args ...interface{}) {
118	base.ErrorfAt(pw.m.pos(p), 0, msg, args...)
119}
120
121// fatalf reports an internal compiler error about thing p.
122func (pw *pkgWriter) fatalf(p poser, msg string, args ...interface{}) {
123	base.FatalfAt(pw.m.pos(p), msg, args...)
124}
125
126// unexpected reports a fatal error about a thing of unexpected
127// dynamic type.
128func (pw *pkgWriter) unexpected(what string, p poser) {
129	pw.fatalf(p, "unexpected %s: %v (%T)", what, p, p)
130}
131
132func (pw *pkgWriter) typeAndValue(x syntax.Expr) syntax.TypeAndValue {
133	tv, ok := pw.maybeTypeAndValue(x)
134	if !ok {
135		pw.fatalf(x, "missing Types entry: %v", syntax.String(x))
136	}
137	return tv
138}
139
140func (pw *pkgWriter) maybeTypeAndValue(x syntax.Expr) (syntax.TypeAndValue, bool) {
141	tv := x.GetTypeInfo()
142
143	// If x is a generic function whose type arguments are inferred
144	// from assignment context, then we need to find its inferred type
145	// in Info.Instances instead.
146	if name, ok := x.(*syntax.Name); ok {
147		if inst, ok := pw.info.Instances[name]; ok {
148			tv.Type = inst.Type
149		}
150	}
151
152	return tv, tv.Type != nil
153}
154
155// typeOf returns the Type of the given value expression.
156func (pw *pkgWriter) typeOf(expr syntax.Expr) types2.Type {
157	tv := pw.typeAndValue(expr)
158	if !tv.IsValue() {
159		pw.fatalf(expr, "expected value: %v", syntax.String(expr))
160	}
161	return tv.Type
162}
163
164// A writer provides APIs for writing out an individual element.
165type writer struct {
166	p *pkgWriter
167
168	pkgbits.Encoder
169
170	// sig holds the signature for the current function body, if any.
171	sig *types2.Signature
172
173	// TODO(mdempsky): We should be able to prune localsIdx whenever a
174	// scope closes, and then maybe we can just use the same map for
175	// storing the TypeParams too (as their TypeName instead).
176
177	// localsIdx tracks any local variables declared within this
178	// function body. It's unused for writing out non-body things.
179	localsIdx map[*types2.Var]int
180
181	// closureVars tracks any free variables that are referenced by this
182	// function body. It's unused for writing out non-body things.
183	closureVars    []posVar
184	closureVarsIdx map[*types2.Var]int // index of previously seen free variables
185
186	dict *writerDict
187
188	// derived tracks whether the type being written out references any
189	// type parameters. It's unused for writing non-type things.
190	derived bool
191}
192
193// A writerDict tracks types and objects that are used by a declaration.
194type writerDict struct {
195	// implicits is a slice of type parameters from the enclosing
196	// declarations.
197	implicits []*types2.TypeParam
198
199	// derived is a slice of type indices for computing derived types
200	// (i.e., types that depend on the declaration's type parameters).
201	derived []derivedInfo
202
203	// derivedIdx maps a Type to its corresponding index within the
204	// derived slice, if present.
205	derivedIdx map[types2.Type]pkgbits.Index
206
207	// These slices correspond to entries in the runtime dictionary.
208	typeParamMethodExprs []writerMethodExprInfo
209	subdicts             []objInfo
210	rtypes               []typeInfo
211	itabs                []itabInfo
212}
213
214type itabInfo struct {
215	typ   typeInfo
216	iface typeInfo
217}
218
219// typeParamIndex returns the index of the given type parameter within
220// the dictionary. This may differ from typ.Index() when there are
221// implicit type parameters due to defined types declared within a
222// generic function or method.
223func (dict *writerDict) typeParamIndex(typ *types2.TypeParam) int {
224	for idx, implicit := range dict.implicits {
225		if implicit == typ {
226			return idx
227		}
228	}
229
230	return len(dict.implicits) + typ.Index()
231}
232
233// A derivedInfo represents a reference to an encoded generic Go type.
234type derivedInfo struct {
235	idx    pkgbits.Index
236	needed bool // TODO(mdempsky): Remove.
237}
238
239// A typeInfo represents a reference to an encoded Go type.
240//
241// If derived is true, then the typeInfo represents a generic Go type
242// that contains type parameters. In this case, idx is an index into
243// the readerDict.derived{,Types} arrays.
244//
245// Otherwise, the typeInfo represents a non-generic Go type, and idx
246// is an index into the reader.typs array instead.
247type typeInfo struct {
248	idx     pkgbits.Index
249	derived bool
250}
251
252// An objInfo represents a reference to an encoded, instantiated (if
253// applicable) Go object.
254type objInfo struct {
255	idx       pkgbits.Index // index for the generic function declaration
256	explicits []typeInfo    // info for the type arguments
257}
258
259// A selectorInfo represents a reference to an encoded field or method
260// name (i.e., objects that can only be accessed using selector
261// expressions).
262type selectorInfo struct {
263	pkgIdx  pkgbits.Index
264	nameIdx pkgbits.Index
265}
266
267// anyDerived reports whether any of info's explicit type arguments
268// are derived types.
269func (info objInfo) anyDerived() bool {
270	for _, explicit := range info.explicits {
271		if explicit.derived {
272			return true
273		}
274	}
275	return false
276}
277
278// equals reports whether info and other represent the same Go object
279// (i.e., same base object and identical type arguments, if any).
280func (info objInfo) equals(other objInfo) bool {
281	if info.idx != other.idx {
282		return false
283	}
284	assert(len(info.explicits) == len(other.explicits))
285	for i, targ := range info.explicits {
286		if targ != other.explicits[i] {
287			return false
288		}
289	}
290	return true
291}
292
293type writerMethodExprInfo struct {
294	typeParamIdx int
295	methodInfo   selectorInfo
296}
297
298// typeParamMethodExprIdx returns the index where the given encoded
299// method expression function pointer appears within this dictionary's
300// type parameters method expressions section, adding it if necessary.
301func (dict *writerDict) typeParamMethodExprIdx(typeParamIdx int, methodInfo selectorInfo) int {
302	newInfo := writerMethodExprInfo{typeParamIdx, methodInfo}
303
304	for idx, oldInfo := range dict.typeParamMethodExprs {
305		if oldInfo == newInfo {
306			return idx
307		}
308	}
309
310	idx := len(dict.typeParamMethodExprs)
311	dict.typeParamMethodExprs = append(dict.typeParamMethodExprs, newInfo)
312	return idx
313}
314
315// subdictIdx returns the index where the given encoded object's
316// runtime dictionary appears within this dictionary's subdictionary
317// section, adding it if necessary.
318func (dict *writerDict) subdictIdx(newInfo objInfo) int {
319	for idx, oldInfo := range dict.subdicts {
320		if oldInfo.equals(newInfo) {
321			return idx
322		}
323	}
324
325	idx := len(dict.subdicts)
326	dict.subdicts = append(dict.subdicts, newInfo)
327	return idx
328}
329
330// rtypeIdx returns the index where the given encoded type's
331// *runtime._type value appears within this dictionary's rtypes
332// section, adding it if necessary.
333func (dict *writerDict) rtypeIdx(newInfo typeInfo) int {
334	for idx, oldInfo := range dict.rtypes {
335		if oldInfo == newInfo {
336			return idx
337		}
338	}
339
340	idx := len(dict.rtypes)
341	dict.rtypes = append(dict.rtypes, newInfo)
342	return idx
343}
344
345// itabIdx returns the index where the given encoded type pair's
346// *runtime.itab value appears within this dictionary's itabs section,
347// adding it if necessary.
348func (dict *writerDict) itabIdx(typInfo, ifaceInfo typeInfo) int {
349	newInfo := itabInfo{typInfo, ifaceInfo}
350
351	for idx, oldInfo := range dict.itabs {
352		if oldInfo == newInfo {
353			return idx
354		}
355	}
356
357	idx := len(dict.itabs)
358	dict.itabs = append(dict.itabs, newInfo)
359	return idx
360}
361
362func (pw *pkgWriter) newWriter(k pkgbits.RelocKind, marker pkgbits.SyncMarker) *writer {
363	return &writer{
364		Encoder: pw.NewEncoder(k, marker),
365		p:       pw,
366	}
367}
368
369// @@@ Positions
370
371// pos writes the position of p into the element bitstream.
372func (w *writer) pos(p poser) {
373	w.Sync(pkgbits.SyncPos)
374	pos := p.Pos()
375
376	// TODO(mdempsky): Track down the remaining cases here and fix them.
377	if !w.Bool(pos.IsKnown()) {
378		return
379	}
380
381	// TODO(mdempsky): Delta encoding.
382	w.posBase(pos.Base())
383	w.Uint(pos.Line())
384	w.Uint(pos.Col())
385}
386
387// posBase writes a reference to the given PosBase into the element
388// bitstream.
389func (w *writer) posBase(b *syntax.PosBase) {
390	w.Reloc(pkgbits.RelocPosBase, w.p.posBaseIdx(b))
391}
392
393// posBaseIdx returns the index for the given PosBase.
394func (pw *pkgWriter) posBaseIdx(b *syntax.PosBase) pkgbits.Index {
395	if idx, ok := pw.posBasesIdx[b]; ok {
396		return idx
397	}
398
399	w := pw.newWriter(pkgbits.RelocPosBase, pkgbits.SyncPosBase)
400	w.p.posBasesIdx[b] = w.Idx
401
402	w.String(trimFilename(b))
403
404	if !w.Bool(b.IsFileBase()) {
405		w.pos(b)
406		w.Uint(b.Line())
407		w.Uint(b.Col())
408	}
409
410	return w.Flush()
411}
412
413// @@@ Packages
414
415// pkg writes a use of the given Package into the element bitstream.
416func (w *writer) pkg(pkg *types2.Package) {
417	w.pkgRef(w.p.pkgIdx(pkg))
418}
419
420func (w *writer) pkgRef(idx pkgbits.Index) {
421	w.Sync(pkgbits.SyncPkg)
422	w.Reloc(pkgbits.RelocPkg, idx)
423}
424
425// pkgIdx returns the index for the given package, adding it to the
426// package export data if needed.
427func (pw *pkgWriter) pkgIdx(pkg *types2.Package) pkgbits.Index {
428	if idx, ok := pw.pkgsIdx[pkg]; ok {
429		return idx
430	}
431
432	w := pw.newWriter(pkgbits.RelocPkg, pkgbits.SyncPkgDef)
433	pw.pkgsIdx[pkg] = w.Idx
434
435	// The universe and package unsafe need to be handled specially by
436	// importers anyway, so we serialize them using just their package
437	// path. This ensures that readers don't confuse them for
438	// user-defined packages.
439	switch pkg {
440	case nil: // universe
441		w.String("builtin") // same package path used by godoc
442	case types2.Unsafe:
443		w.String("unsafe")
444	default:
445		// TODO(mdempsky): Write out pkg.Path() for curpkg too.
446		var path string
447		if pkg != w.p.curpkg {
448			path = pkg.Path()
449		}
450		base.Assertf(path != "builtin" && path != "unsafe", "unexpected path for user-defined package: %q", path)
451		w.String(path)
452		w.String(pkg.Name())
453
454		w.Len(len(pkg.Imports()))
455		for _, imp := range pkg.Imports() {
456			w.pkg(imp)
457		}
458	}
459
460	return w.Flush()
461}
462
463// @@@ Types
464
465var (
466	anyTypeName        = types2.Universe.Lookup("any").(*types2.TypeName)
467	comparableTypeName = types2.Universe.Lookup("comparable").(*types2.TypeName)
468	runeTypeName       = types2.Universe.Lookup("rune").(*types2.TypeName)
469)
470
471// typ writes a use of the given type into the bitstream.
472func (w *writer) typ(typ types2.Type) {
473	w.typInfo(w.p.typIdx(typ, w.dict))
474}
475
476// typInfo writes a use of the given type (specified as a typeInfo
477// instead) into the bitstream.
478func (w *writer) typInfo(info typeInfo) {
479	w.Sync(pkgbits.SyncType)
480	if w.Bool(info.derived) {
481		w.Len(int(info.idx))
482		w.derived = true
483	} else {
484		w.Reloc(pkgbits.RelocType, info.idx)
485	}
486}
487
488// typIdx returns the index where the export data description of type
489// can be read back in. If no such index exists yet, it's created.
490//
491// typIdx also reports whether typ is a derived type; that is, whether
492// its identity depends on type parameters.
493func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo {
494	// Strip non-global aliases, because they only appear in inline
495	// bodies anyway. Otherwise, they can cause types.Sym collisions
496	// (e.g., "main.C" for both of the local type aliases in
497	// test/fixedbugs/issue50190.go).
498	for {
499		if alias, ok := typ.(*types2.Alias); ok && !isGlobal(alias.Obj()) {
500			typ = alias.Rhs()
501		} else {
502			break
503		}
504	}
505
506	if idx, ok := pw.typsIdx[typ]; ok {
507		return typeInfo{idx: idx, derived: false}
508	}
509	if dict != nil {
510		if idx, ok := dict.derivedIdx[typ]; ok {
511			return typeInfo{idx: idx, derived: true}
512		}
513	}
514
515	w := pw.newWriter(pkgbits.RelocType, pkgbits.SyncTypeIdx)
516	w.dict = dict
517
518	switch typ := typ.(type) {
519	default:
520		base.Fatalf("unexpected type: %v (%T)", typ, typ)
521
522	case *types2.Basic:
523		switch kind := typ.Kind(); {
524		case kind == types2.Invalid:
525			base.Fatalf("unexpected types2.Invalid")
526
527		case types2.Typ[kind] == typ:
528			w.Code(pkgbits.TypeBasic)
529			w.Len(int(kind))
530
531		default:
532			// Handle "byte" and "rune" as references to their TypeNames.
533			obj := types2.Universe.Lookup(typ.Name()).(*types2.TypeName)
534			assert(obj.Type() == typ)
535
536			w.Code(pkgbits.TypeNamed)
537			w.namedType(obj, nil)
538		}
539
540	case *types2.Named:
541		w.Code(pkgbits.TypeNamed)
542		w.namedType(splitNamed(typ))
543
544	case *types2.Alias:
545		w.Code(pkgbits.TypeNamed)
546		w.namedType(splitAlias(typ))
547
548	case *types2.TypeParam:
549		w.derived = true
550		w.Code(pkgbits.TypeTypeParam)
551		w.Len(w.dict.typeParamIndex(typ))
552
553	case *types2.Array:
554		w.Code(pkgbits.TypeArray)
555		w.Uint64(uint64(typ.Len()))
556		w.typ(typ.Elem())
557
558	case *types2.Chan:
559		w.Code(pkgbits.TypeChan)
560		w.Len(int(typ.Dir()))
561		w.typ(typ.Elem())
562
563	case *types2.Map:
564		w.Code(pkgbits.TypeMap)
565		w.typ(typ.Key())
566		w.typ(typ.Elem())
567
568	case *types2.Pointer:
569		w.Code(pkgbits.TypePointer)
570		w.typ(typ.Elem())
571
572	case *types2.Signature:
573		base.Assertf(typ.TypeParams() == nil, "unexpected type params: %v", typ)
574		w.Code(pkgbits.TypeSignature)
575		w.signature(typ)
576
577	case *types2.Slice:
578		w.Code(pkgbits.TypeSlice)
579		w.typ(typ.Elem())
580
581	case *types2.Struct:
582		w.Code(pkgbits.TypeStruct)
583		w.structType(typ)
584
585	case *types2.Interface:
586		// Handle "any" as reference to its TypeName.
587		// The underlying "any" interface is canonical, so this logic handles both
588		// GODEBUG=gotypesalias=1 (when any is represented as a types2.Alias), and
589		// gotypesalias=0.
590		if types2.Unalias(typ) == types2.Unalias(anyTypeName.Type()) {
591			w.Code(pkgbits.TypeNamed)
592			w.obj(anyTypeName, nil)
593			break
594		}
595
596		w.Code(pkgbits.TypeInterface)
597		w.interfaceType(typ)
598
599	case *types2.Union:
600		w.Code(pkgbits.TypeUnion)
601		w.unionType(typ)
602	}
603
604	if w.derived {
605		idx := pkgbits.Index(len(dict.derived))
606		dict.derived = append(dict.derived, derivedInfo{idx: w.Flush()})
607		dict.derivedIdx[typ] = idx
608		return typeInfo{idx: idx, derived: true}
609	}
610
611	pw.typsIdx[typ] = w.Idx
612	return typeInfo{idx: w.Flush(), derived: false}
613}
614
615// namedType writes a use of the given named type into the bitstream.
616func (w *writer) namedType(obj *types2.TypeName, targs *types2.TypeList) {
617	// Named types that are declared within a generic function (and
618	// thus have implicit type parameters) are always derived types.
619	if w.p.hasImplicitTypeParams(obj) {
620		w.derived = true
621	}
622
623	w.obj(obj, targs)
624}
625
626func (w *writer) structType(typ *types2.Struct) {
627	w.Len(typ.NumFields())
628	for i := 0; i < typ.NumFields(); i++ {
629		f := typ.Field(i)
630		w.pos(f)
631		w.selector(f)
632		w.typ(f.Type())
633		w.String(typ.Tag(i))
634		w.Bool(f.Embedded())
635	}
636}
637
638func (w *writer) unionType(typ *types2.Union) {
639	w.Len(typ.Len())
640	for i := 0; i < typ.Len(); i++ {
641		t := typ.Term(i)
642		w.Bool(t.Tilde())
643		w.typ(t.Type())
644	}
645}
646
647func (w *writer) interfaceType(typ *types2.Interface) {
648	// If typ has no embedded types but it's not a basic interface, then
649	// the natural description we write out below will fail to
650	// reconstruct it.
651	if typ.NumEmbeddeds() == 0 && !typ.IsMethodSet() {
652		// Currently, this can only happen for the underlying Interface of
653		// "comparable", which is needed to handle type declarations like
654		// "type C comparable".
655		assert(typ == comparableTypeName.Type().(*types2.Named).Underlying())
656
657		// Export as "interface{ comparable }".
658		w.Len(0)                         // NumExplicitMethods
659		w.Len(1)                         // NumEmbeddeds
660		w.Bool(false)                    // IsImplicit
661		w.typ(comparableTypeName.Type()) // EmbeddedType(0)
662		return
663	}
664
665	w.Len(typ.NumExplicitMethods())
666	w.Len(typ.NumEmbeddeds())
667
668	if typ.NumExplicitMethods() == 0 && typ.NumEmbeddeds() == 1 {
669		w.Bool(typ.IsImplicit())
670	} else {
671		// Implicit interfaces always have 0 explicit methods and 1
672		// embedded type, so we skip writing out the implicit flag
673		// otherwise as a space optimization.
674		assert(!typ.IsImplicit())
675	}
676
677	for i := 0; i < typ.NumExplicitMethods(); i++ {
678		m := typ.ExplicitMethod(i)
679		sig := m.Type().(*types2.Signature)
680		assert(sig.TypeParams() == nil)
681
682		w.pos(m)
683		w.selector(m)
684		w.signature(sig)
685	}
686
687	for i := 0; i < typ.NumEmbeddeds(); i++ {
688		w.typ(typ.EmbeddedType(i))
689	}
690}
691
692func (w *writer) signature(sig *types2.Signature) {
693	w.Sync(pkgbits.SyncSignature)
694	w.params(sig.Params())
695	w.params(sig.Results())
696	w.Bool(sig.Variadic())
697}
698
699func (w *writer) params(typ *types2.Tuple) {
700	w.Sync(pkgbits.SyncParams)
701	w.Len(typ.Len())
702	for i := 0; i < typ.Len(); i++ {
703		w.param(typ.At(i))
704	}
705}
706
707func (w *writer) param(param *types2.Var) {
708	w.Sync(pkgbits.SyncParam)
709	w.pos(param)
710	w.localIdent(param)
711	w.typ(param.Type())
712}
713
714// @@@ Objects
715
716// obj writes a use of the given object into the bitstream.
717//
718// If obj is a generic object, then explicits are the explicit type
719// arguments used to instantiate it (i.e., used to substitute the
720// object's own declared type parameters).
721func (w *writer) obj(obj types2.Object, explicits *types2.TypeList) {
722	w.objInfo(w.p.objInstIdx(obj, explicits, w.dict))
723}
724
725// objInfo writes a use of the given encoded object into the
726// bitstream.
727func (w *writer) objInfo(info objInfo) {
728	w.Sync(pkgbits.SyncObject)
729	w.Bool(false) // TODO(mdempsky): Remove; was derived func inst.
730	w.Reloc(pkgbits.RelocObj, info.idx)
731
732	w.Len(len(info.explicits))
733	for _, info := range info.explicits {
734		w.typInfo(info)
735	}
736}
737
738// objInstIdx returns the indices for an object and a corresponding
739// list of type arguments used to instantiate it, adding them to the
740// export data as needed.
741func (pw *pkgWriter) objInstIdx(obj types2.Object, explicits *types2.TypeList, dict *writerDict) objInfo {
742	explicitInfos := make([]typeInfo, explicits.Len())
743	for i := range explicitInfos {
744		explicitInfos[i] = pw.typIdx(explicits.At(i), dict)
745	}
746	return objInfo{idx: pw.objIdx(obj), explicits: explicitInfos}
747}
748
749// objIdx returns the index for the given Object, adding it to the
750// export data as needed.
751func (pw *pkgWriter) objIdx(obj types2.Object) pkgbits.Index {
752	// TODO(mdempsky): Validate that obj is a global object (or a local
753	// defined type, which we hoist to global scope anyway).
754
755	if idx, ok := pw.objsIdx[obj]; ok {
756		return idx
757	}
758
759	dict := &writerDict{
760		derivedIdx: make(map[types2.Type]pkgbits.Index),
761	}
762
763	if isDefinedType(obj) && obj.Pkg() == pw.curpkg {
764		decl, ok := pw.typDecls[obj.(*types2.TypeName)]
765		assert(ok)
766		dict.implicits = decl.implicits
767	}
768
769	// We encode objects into 4 elements across different sections, all
770	// sharing the same index:
771	//
772	// - RelocName has just the object's qualified name (i.e.,
773	//   Object.Pkg and Object.Name) and the CodeObj indicating what
774	//   specific type of Object it is (Var, Func, etc).
775	//
776	// - RelocObj has the remaining public details about the object,
777	//   relevant to go/types importers.
778	//
779	// - RelocObjExt has additional private details about the object,
780	//   which are only relevant to cmd/compile itself. This is
781	//   separated from RelocObj so that go/types importers are
782	//   unaffected by internal compiler changes.
783	//
784	// - RelocObjDict has public details about the object's type
785	//   parameters and derived type's used by the object. This is
786	//   separated to facilitate the eventual introduction of
787	//   shape-based stenciling.
788	//
789	// TODO(mdempsky): Re-evaluate whether RelocName still makes sense
790	// to keep separate from RelocObj.
791
792	w := pw.newWriter(pkgbits.RelocObj, pkgbits.SyncObject1)
793	wext := pw.newWriter(pkgbits.RelocObjExt, pkgbits.SyncObject1)
794	wname := pw.newWriter(pkgbits.RelocName, pkgbits.SyncObject1)
795	wdict := pw.newWriter(pkgbits.RelocObjDict, pkgbits.SyncObject1)
796
797	pw.objsIdx[obj] = w.Idx // break cycles
798	assert(wext.Idx == w.Idx)
799	assert(wname.Idx == w.Idx)
800	assert(wdict.Idx == w.Idx)
801
802	w.dict = dict
803	wext.dict = dict
804
805	code := w.doObj(wext, obj)
806	w.Flush()
807	wext.Flush()
808
809	wname.qualifiedIdent(obj)
810	wname.Code(code)
811	wname.Flush()
812
813	wdict.objDict(obj, w.dict)
814	wdict.Flush()
815
816	return w.Idx
817}
818
819// doObj writes the RelocObj definition for obj to w, and the
820// RelocObjExt definition to wext.
821func (w *writer) doObj(wext *writer, obj types2.Object) pkgbits.CodeObj {
822	if obj.Pkg() != w.p.curpkg {
823		return pkgbits.ObjStub
824	}
825
826	switch obj := obj.(type) {
827	default:
828		w.p.unexpected("object", obj)
829		panic("unreachable")
830
831	case *types2.Const:
832		w.pos(obj)
833		w.typ(obj.Type())
834		w.Value(obj.Val())
835		return pkgbits.ObjConst
836
837	case *types2.Func:
838		decl, ok := w.p.funDecls[obj]
839		assert(ok)
840		sig := obj.Type().(*types2.Signature)
841
842		w.pos(obj)
843		w.typeParamNames(sig.TypeParams())
844		w.signature(sig)
845		w.pos(decl)
846		wext.funcExt(obj)
847		return pkgbits.ObjFunc
848
849	case *types2.TypeName:
850		if obj.IsAlias() {
851			w.pos(obj)
852			t := obj.Type()
853			if alias, ok := t.(*types2.Alias); ok { // materialized alias
854				t = alias.Rhs()
855			}
856			w.typ(t)
857			return pkgbits.ObjAlias
858		}
859
860		named := obj.Type().(*types2.Named)
861		assert(named.TypeArgs() == nil)
862
863		w.pos(obj)
864		w.typeParamNames(named.TypeParams())
865		wext.typeExt(obj)
866		w.typ(named.Underlying())
867
868		w.Len(named.NumMethods())
869		for i := 0; i < named.NumMethods(); i++ {
870			w.method(wext, named.Method(i))
871		}
872
873		return pkgbits.ObjType
874
875	case *types2.Var:
876		w.pos(obj)
877		w.typ(obj.Type())
878		wext.varExt(obj)
879		return pkgbits.ObjVar
880	}
881}
882
883// objDict writes the dictionary needed for reading the given object.
884func (w *writer) objDict(obj types2.Object, dict *writerDict) {
885	// TODO(mdempsky): Split objDict into multiple entries? reader.go
886	// doesn't care about the type parameter bounds, and reader2.go
887	// doesn't care about referenced functions.
888
889	w.dict = dict // TODO(mdempsky): This is a bit sketchy.
890
891	w.Len(len(dict.implicits))
892
893	tparams := objTypeParams(obj)
894	ntparams := tparams.Len()
895	w.Len(ntparams)
896	for i := 0; i < ntparams; i++ {
897		w.typ(tparams.At(i).Constraint())
898	}
899
900	nderived := len(dict.derived)
901	w.Len(nderived)
902	for _, typ := range dict.derived {
903		w.Reloc(pkgbits.RelocType, typ.idx)
904		w.Bool(typ.needed)
905	}
906
907	// Write runtime dictionary information.
908	//
909	// N.B., the go/types importer reads up to the section, but doesn't
910	// read any further, so it's safe to change. (See TODO above.)
911
912	// For each type parameter, write out whether the constraint is a
913	// basic interface. This is used to determine how aggressively we
914	// can shape corresponding type arguments.
915	//
916	// This is somewhat redundant with writing out the full type
917	// parameter constraints above, but the compiler currently skips
918	// over those. Also, we don't care about the *declared* constraints,
919	// but how the type parameters are actually *used*. E.g., if a type
920	// parameter is constrained to `int | uint` but then never used in
921	// arithmetic/conversions/etc, we could shape those together.
922	for _, implicit := range dict.implicits {
923		w.Bool(implicit.Underlying().(*types2.Interface).IsMethodSet())
924	}
925	for i := 0; i < ntparams; i++ {
926		tparam := tparams.At(i)
927		w.Bool(tparam.Underlying().(*types2.Interface).IsMethodSet())
928	}
929
930	w.Len(len(dict.typeParamMethodExprs))
931	for _, info := range dict.typeParamMethodExprs {
932		w.Len(info.typeParamIdx)
933		w.selectorInfo(info.methodInfo)
934	}
935
936	w.Len(len(dict.subdicts))
937	for _, info := range dict.subdicts {
938		w.objInfo(info)
939	}
940
941	w.Len(len(dict.rtypes))
942	for _, info := range dict.rtypes {
943		w.typInfo(info)
944	}
945
946	w.Len(len(dict.itabs))
947	for _, info := range dict.itabs {
948		w.typInfo(info.typ)
949		w.typInfo(info.iface)
950	}
951
952	assert(len(dict.derived) == nderived)
953}
954
955func (w *writer) typeParamNames(tparams *types2.TypeParamList) {
956	w.Sync(pkgbits.SyncTypeParamNames)
957
958	ntparams := tparams.Len()
959	for i := 0; i < ntparams; i++ {
960		tparam := tparams.At(i).Obj()
961		w.pos(tparam)
962		w.localIdent(tparam)
963	}
964}
965
966func (w *writer) method(wext *writer, meth *types2.Func) {
967	decl, ok := w.p.funDecls[meth]
968	assert(ok)
969	sig := meth.Type().(*types2.Signature)
970
971	w.Sync(pkgbits.SyncMethod)
972	w.pos(meth)
973	w.selector(meth)
974	w.typeParamNames(sig.RecvTypeParams())
975	w.param(sig.Recv())
976	w.signature(sig)
977
978	w.pos(decl) // XXX: Hack to workaround linker limitations.
979	wext.funcExt(meth)
980}
981
982// qualifiedIdent writes out the name of an object declared at package
983// scope. (For now, it's also used to refer to local defined types.)
984func (w *writer) qualifiedIdent(obj types2.Object) {
985	w.Sync(pkgbits.SyncSym)
986
987	name := obj.Name()
988	if isDefinedType(obj) && obj.Pkg() == w.p.curpkg {
989		decl, ok := w.p.typDecls[obj.(*types2.TypeName)]
990		assert(ok)
991		if decl.gen != 0 {
992			// For local defined types, we embed a scope-disambiguation
993			// number directly into their name. types.SplitVargenSuffix then
994			// knows to look for this.
995			//
996			// TODO(mdempsky): Find a better solution; this is terrible.
997			name = fmt.Sprintf("%s·%v", name, decl.gen)
998		}
999	}
1000
1001	w.pkg(obj.Pkg())
1002	w.String(name)
1003}
1004
1005// TODO(mdempsky): We should be able to omit pkg from both localIdent
1006// and selector, because they should always be known from context.
1007// However, past frustrations with this optimization in iexport make
1008// me a little nervous to try it again.
1009
1010// localIdent writes the name of a locally declared object (i.e.,
1011// objects that can only be accessed by non-qualified name, within the
1012// context of a particular function).
1013func (w *writer) localIdent(obj types2.Object) {
1014	assert(!isGlobal(obj))
1015	w.Sync(pkgbits.SyncLocalIdent)
1016	w.pkg(obj.Pkg())
1017	w.String(obj.Name())
1018}
1019
1020// selector writes the name of a field or method (i.e., objects that
1021// can only be accessed using selector expressions).
1022func (w *writer) selector(obj types2.Object) {
1023	w.selectorInfo(w.p.selectorIdx(obj))
1024}
1025
1026func (w *writer) selectorInfo(info selectorInfo) {
1027	w.Sync(pkgbits.SyncSelector)
1028	w.pkgRef(info.pkgIdx)
1029	w.StringRef(info.nameIdx)
1030}
1031
1032func (pw *pkgWriter) selectorIdx(obj types2.Object) selectorInfo {
1033	pkgIdx := pw.pkgIdx(obj.Pkg())
1034	nameIdx := pw.StringIdx(obj.Name())
1035	return selectorInfo{pkgIdx: pkgIdx, nameIdx: nameIdx}
1036}
1037
1038// @@@ Compiler extensions
1039
1040func (w *writer) funcExt(obj *types2.Func) {
1041	decl, ok := w.p.funDecls[obj]
1042	assert(ok)
1043
1044	// TODO(mdempsky): Extend these pragma validation flags to account
1045	// for generics. E.g., linkname probably doesn't make sense at
1046	// least.
1047
1048	pragma := asPragmaFlag(decl.Pragma)
1049	if pragma&ir.Systemstack != 0 && pragma&ir.Nosplit != 0 {
1050		w.p.errorf(decl, "go:nosplit and go:systemstack cannot be combined")
1051	}
1052	wi := asWasmImport(decl.Pragma)
1053
1054	if decl.Body != nil {
1055		if pragma&ir.Noescape != 0 {
1056			w.p.errorf(decl, "can only use //go:noescape with external func implementations")
1057		}
1058		if wi != nil {
1059			w.p.errorf(decl, "can only use //go:wasmimport with external func implementations")
1060		}
1061		if (pragma&ir.UintptrKeepAlive != 0 && pragma&ir.UintptrEscapes == 0) && pragma&ir.Nosplit == 0 {
1062			// Stack growth can't handle uintptr arguments that may
1063			// be pointers (as we don't know which are pointers
1064			// when creating the stack map). Thus uintptrkeepalive
1065			// functions (and all transitive callees) must be
1066			// nosplit.
1067			//
1068			// N.B. uintptrescapes implies uintptrkeepalive but it
1069			// is OK since the arguments must escape to the heap.
1070			//
1071			// TODO(prattmic): Add recursive nosplit check of callees.
1072			// TODO(prattmic): Functions with no body (i.e.,
1073			// assembly) must also be nosplit, but we can't check
1074			// that here.
1075			w.p.errorf(decl, "go:uintptrkeepalive requires go:nosplit")
1076		}
1077	} else {
1078		if base.Flag.Complete || decl.Name.Value == "init" {
1079			// Linknamed functions are allowed to have no body. Hopefully
1080			// the linkname target has a body. See issue 23311.
1081			// Wasmimport functions are also allowed to have no body.
1082			if _, ok := w.p.linknames[obj]; !ok && wi == nil {
1083				w.p.errorf(decl, "missing function body")
1084			}
1085		}
1086	}
1087
1088	sig, block := obj.Type().(*types2.Signature), decl.Body
1089	body, closureVars := w.p.bodyIdx(sig, block, w.dict)
1090	if len(closureVars) > 0 {
1091		fmt.Fprintln(os.Stderr, "CLOSURE", closureVars)
1092	}
1093	assert(len(closureVars) == 0)
1094
1095	w.Sync(pkgbits.SyncFuncExt)
1096	w.pragmaFlag(pragma)
1097	w.linkname(obj)
1098
1099	if buildcfg.GOARCH == "wasm" {
1100		if wi != nil {
1101			w.String(wi.Module)
1102			w.String(wi.Name)
1103		} else {
1104			w.String("")
1105			w.String("")
1106		}
1107	}
1108
1109	w.Bool(false) // stub extension
1110	w.Reloc(pkgbits.RelocBody, body)
1111	w.Sync(pkgbits.SyncEOF)
1112}
1113
1114func (w *writer) typeExt(obj *types2.TypeName) {
1115	decl, ok := w.p.typDecls[obj]
1116	assert(ok)
1117
1118	w.Sync(pkgbits.SyncTypeExt)
1119
1120	w.pragmaFlag(asPragmaFlag(decl.Pragma))
1121
1122	// No LSym.SymIdx info yet.
1123	w.Int64(-1)
1124	w.Int64(-1)
1125}
1126
1127func (w *writer) varExt(obj *types2.Var) {
1128	w.Sync(pkgbits.SyncVarExt)
1129	w.linkname(obj)
1130}
1131
1132func (w *writer) linkname(obj types2.Object) {
1133	w.Sync(pkgbits.SyncLinkname)
1134	w.Int64(-1)
1135	w.String(w.p.linknames[obj])
1136}
1137
1138func (w *writer) pragmaFlag(p ir.PragmaFlag) {
1139	w.Sync(pkgbits.SyncPragma)
1140	w.Int(int(p))
1141}
1142
1143// @@@ Function bodies
1144
1145// bodyIdx returns the index for the given function body (specified by
1146// block), adding it to the export data
1147func (pw *pkgWriter) bodyIdx(sig *types2.Signature, block *syntax.BlockStmt, dict *writerDict) (idx pkgbits.Index, closureVars []posVar) {
1148	w := pw.newWriter(pkgbits.RelocBody, pkgbits.SyncFuncBody)
1149	w.sig = sig
1150	w.dict = dict
1151
1152	w.declareParams(sig)
1153	if w.Bool(block != nil) {
1154		w.stmts(block.List)
1155		w.pos(block.Rbrace)
1156	}
1157
1158	return w.Flush(), w.closureVars
1159}
1160
1161func (w *writer) declareParams(sig *types2.Signature) {
1162	addLocals := func(params *types2.Tuple) {
1163		for i := 0; i < params.Len(); i++ {
1164			w.addLocal(params.At(i))
1165		}
1166	}
1167
1168	if recv := sig.Recv(); recv != nil {
1169		w.addLocal(recv)
1170	}
1171	addLocals(sig.Params())
1172	addLocals(sig.Results())
1173}
1174
1175// addLocal records the declaration of a new local variable.
1176func (w *writer) addLocal(obj *types2.Var) {
1177	idx := len(w.localsIdx)
1178
1179	w.Sync(pkgbits.SyncAddLocal)
1180	if w.p.SyncMarkers() {
1181		w.Int(idx)
1182	}
1183	w.varDictIndex(obj)
1184
1185	if w.localsIdx == nil {
1186		w.localsIdx = make(map[*types2.Var]int)
1187	}
1188	w.localsIdx[obj] = idx
1189}
1190
1191// useLocal writes a reference to the given local or free variable
1192// into the bitstream.
1193func (w *writer) useLocal(pos syntax.Pos, obj *types2.Var) {
1194	w.Sync(pkgbits.SyncUseObjLocal)
1195
1196	if idx, ok := w.localsIdx[obj]; w.Bool(ok) {
1197		w.Len(idx)
1198		return
1199	}
1200
1201	idx, ok := w.closureVarsIdx[obj]
1202	if !ok {
1203		if w.closureVarsIdx == nil {
1204			w.closureVarsIdx = make(map[*types2.Var]int)
1205		}
1206		idx = len(w.closureVars)
1207		w.closureVars = append(w.closureVars, posVar{pos, obj})
1208		w.closureVarsIdx[obj] = idx
1209	}
1210	w.Len(idx)
1211}
1212
1213func (w *writer) openScope(pos syntax.Pos) {
1214	w.Sync(pkgbits.SyncOpenScope)
1215	w.pos(pos)
1216}
1217
1218func (w *writer) closeScope(pos syntax.Pos) {
1219	w.Sync(pkgbits.SyncCloseScope)
1220	w.pos(pos)
1221	w.closeAnotherScope()
1222}
1223
1224func (w *writer) closeAnotherScope() {
1225	w.Sync(pkgbits.SyncCloseAnotherScope)
1226}
1227
1228// @@@ Statements
1229
1230// stmt writes the given statement into the function body bitstream.
1231func (w *writer) stmt(stmt syntax.Stmt) {
1232	var stmts []syntax.Stmt
1233	if stmt != nil {
1234		stmts = []syntax.Stmt{stmt}
1235	}
1236	w.stmts(stmts)
1237}
1238
1239func (w *writer) stmts(stmts []syntax.Stmt) {
1240	dead := false
1241	w.Sync(pkgbits.SyncStmts)
1242	var lastLabel = -1
1243	for i, stmt := range stmts {
1244		if _, ok := stmt.(*syntax.LabeledStmt); ok {
1245			lastLabel = i
1246		}
1247	}
1248	for i, stmt := range stmts {
1249		if dead && i > lastLabel {
1250			// Any statements after a terminating and last label statement are safe to omit.
1251			// Otherwise, code after label statement may refer to dead stmts between terminating
1252			// and label statement, see issue #65593.
1253			if _, ok := stmt.(*syntax.LabeledStmt); !ok {
1254				continue
1255			}
1256		}
1257		w.stmt1(stmt)
1258		dead = w.p.terminates(stmt)
1259	}
1260	w.Code(stmtEnd)
1261	w.Sync(pkgbits.SyncStmtsEnd)
1262}
1263
1264func (w *writer) stmt1(stmt syntax.Stmt) {
1265	switch stmt := stmt.(type) {
1266	default:
1267		w.p.unexpected("statement", stmt)
1268
1269	case nil, *syntax.EmptyStmt:
1270		return
1271
1272	case *syntax.AssignStmt:
1273		switch {
1274		case stmt.Rhs == nil:
1275			w.Code(stmtIncDec)
1276			w.op(binOps[stmt.Op])
1277			w.expr(stmt.Lhs)
1278			w.pos(stmt)
1279
1280		case stmt.Op != 0 && stmt.Op != syntax.Def:
1281			w.Code(stmtAssignOp)
1282			w.op(binOps[stmt.Op])
1283			w.expr(stmt.Lhs)
1284			w.pos(stmt)
1285
1286			var typ types2.Type
1287			if stmt.Op != syntax.Shl && stmt.Op != syntax.Shr {
1288				typ = w.p.typeOf(stmt.Lhs)
1289			}
1290			w.implicitConvExpr(typ, stmt.Rhs)
1291
1292		default:
1293			w.assignStmt(stmt, stmt.Lhs, stmt.Rhs)
1294		}
1295
1296	case *syntax.BlockStmt:
1297		w.Code(stmtBlock)
1298		w.blockStmt(stmt)
1299
1300	case *syntax.BranchStmt:
1301		w.Code(stmtBranch)
1302		w.pos(stmt)
1303		w.op(branchOps[stmt.Tok])
1304		w.optLabel(stmt.Label)
1305
1306	case *syntax.CallStmt:
1307		w.Code(stmtCall)
1308		w.pos(stmt)
1309		w.op(callOps[stmt.Tok])
1310		w.expr(stmt.Call)
1311		if stmt.Tok == syntax.Defer {
1312			w.optExpr(stmt.DeferAt)
1313		}
1314
1315	case *syntax.DeclStmt:
1316		for _, decl := range stmt.DeclList {
1317			w.declStmt(decl)
1318		}
1319
1320	case *syntax.ExprStmt:
1321		w.Code(stmtExpr)
1322		w.expr(stmt.X)
1323
1324	case *syntax.ForStmt:
1325		w.Code(stmtFor)
1326		w.forStmt(stmt)
1327
1328	case *syntax.IfStmt:
1329		w.Code(stmtIf)
1330		w.ifStmt(stmt)
1331
1332	case *syntax.LabeledStmt:
1333		w.Code(stmtLabel)
1334		w.pos(stmt)
1335		w.label(stmt.Label)
1336		w.stmt1(stmt.Stmt)
1337
1338	case *syntax.ReturnStmt:
1339		w.Code(stmtReturn)
1340		w.pos(stmt)
1341
1342		resultTypes := w.sig.Results()
1343		dstType := func(i int) types2.Type {
1344			return resultTypes.At(i).Type()
1345		}
1346		w.multiExpr(stmt, dstType, syntax.UnpackListExpr(stmt.Results))
1347
1348	case *syntax.SelectStmt:
1349		w.Code(stmtSelect)
1350		w.selectStmt(stmt)
1351
1352	case *syntax.SendStmt:
1353		chanType := types2.CoreType(w.p.typeOf(stmt.Chan)).(*types2.Chan)
1354
1355		w.Code(stmtSend)
1356		w.pos(stmt)
1357		w.expr(stmt.Chan)
1358		w.implicitConvExpr(chanType.Elem(), stmt.Value)
1359
1360	case *syntax.SwitchStmt:
1361		w.Code(stmtSwitch)
1362		w.switchStmt(stmt)
1363	}
1364}
1365
1366func (w *writer) assignList(expr syntax.Expr) {
1367	exprs := syntax.UnpackListExpr(expr)
1368	w.Len(len(exprs))
1369
1370	for _, expr := range exprs {
1371		w.assign(expr)
1372	}
1373}
1374
1375func (w *writer) assign(expr syntax.Expr) {
1376	expr = syntax.Unparen(expr)
1377
1378	if name, ok := expr.(*syntax.Name); ok {
1379		if name.Value == "_" {
1380			w.Code(assignBlank)
1381			return
1382		}
1383
1384		if obj, ok := w.p.info.Defs[name]; ok {
1385			obj := obj.(*types2.Var)
1386
1387			w.Code(assignDef)
1388			w.pos(obj)
1389			w.localIdent(obj)
1390			w.typ(obj.Type())
1391
1392			// TODO(mdempsky): Minimize locals index size by deferring
1393			// this until the variables actually come into scope.
1394			w.addLocal(obj)
1395			return
1396		}
1397	}
1398
1399	w.Code(assignExpr)
1400	w.expr(expr)
1401}
1402
1403func (w *writer) declStmt(decl syntax.Decl) {
1404	switch decl := decl.(type) {
1405	default:
1406		w.p.unexpected("declaration", decl)
1407
1408	case *syntax.ConstDecl, *syntax.TypeDecl:
1409
1410	case *syntax.VarDecl:
1411		w.assignStmt(decl, namesAsExpr(decl.NameList), decl.Values)
1412	}
1413}
1414
1415// assignStmt writes out an assignment for "lhs = rhs".
1416func (w *writer) assignStmt(pos poser, lhs0, rhs0 syntax.Expr) {
1417	lhs := syntax.UnpackListExpr(lhs0)
1418	rhs := syntax.UnpackListExpr(rhs0)
1419
1420	w.Code(stmtAssign)
1421	w.pos(pos)
1422
1423	// As if w.assignList(lhs0).
1424	w.Len(len(lhs))
1425	for _, expr := range lhs {
1426		w.assign(expr)
1427	}
1428
1429	dstType := func(i int) types2.Type {
1430		dst := lhs[i]
1431
1432		// Finding dstType is somewhat involved, because for VarDecl
1433		// statements, the Names are only added to the info.{Defs,Uses}
1434		// maps, not to info.Types.
1435		if name, ok := syntax.Unparen(dst).(*syntax.Name); ok {
1436			if name.Value == "_" {
1437				return nil // ok: no implicit conversion
1438			} else if def, ok := w.p.info.Defs[name].(*types2.Var); ok {
1439				return def.Type()
1440			} else if use, ok := w.p.info.Uses[name].(*types2.Var); ok {
1441				return use.Type()
1442			} else {
1443				w.p.fatalf(dst, "cannot find type of destination object: %v", dst)
1444			}
1445		}
1446
1447		return w.p.typeOf(dst)
1448	}
1449
1450	w.multiExpr(pos, dstType, rhs)
1451}
1452
1453func (w *writer) blockStmt(stmt *syntax.BlockStmt) {
1454	w.Sync(pkgbits.SyncBlockStmt)
1455	w.openScope(stmt.Pos())
1456	w.stmts(stmt.List)
1457	w.closeScope(stmt.Rbrace)
1458}
1459
1460func (w *writer) forStmt(stmt *syntax.ForStmt) {
1461	w.Sync(pkgbits.SyncForStmt)
1462	w.openScope(stmt.Pos())
1463
1464	if rang, ok := stmt.Init.(*syntax.RangeClause); w.Bool(ok) {
1465		w.pos(rang)
1466		w.assignList(rang.Lhs)
1467		w.expr(rang.X)
1468
1469		xtyp := w.p.typeOf(rang.X)
1470		if _, isMap := types2.CoreType(xtyp).(*types2.Map); isMap {
1471			w.rtype(xtyp)
1472		}
1473		{
1474			lhs := syntax.UnpackListExpr(rang.Lhs)
1475			assign := func(i int, src types2.Type) {
1476				if i >= len(lhs) {
1477					return
1478				}
1479				dst := syntax.Unparen(lhs[i])
1480				if name, ok := dst.(*syntax.Name); ok && name.Value == "_" {
1481					return
1482				}
1483
1484				var dstType types2.Type
1485				if rang.Def {
1486					// For `:=` assignments, the LHS names only appear in Defs,
1487					// not Types (as used by typeOf).
1488					dstType = w.p.info.Defs[dst.(*syntax.Name)].(*types2.Var).Type()
1489				} else {
1490					dstType = w.p.typeOf(dst)
1491				}
1492
1493				w.convRTTI(src, dstType)
1494			}
1495
1496			keyType, valueType := types2.RangeKeyVal(w.p.typeOf(rang.X))
1497			assign(0, keyType)
1498			assign(1, valueType)
1499		}
1500
1501	} else {
1502		if stmt.Cond != nil && w.p.staticBool(&stmt.Cond) < 0 { // always false
1503			stmt.Post = nil
1504			stmt.Body.List = nil
1505		}
1506
1507		w.pos(stmt)
1508		w.stmt(stmt.Init)
1509		w.optExpr(stmt.Cond)
1510		w.stmt(stmt.Post)
1511	}
1512
1513	w.blockStmt(stmt.Body)
1514	w.Bool(w.distinctVars(stmt))
1515	w.closeAnotherScope()
1516}
1517
1518func (w *writer) distinctVars(stmt *syntax.ForStmt) bool {
1519	lv := base.Debug.LoopVar
1520	fileVersion := w.p.info.FileVersions[stmt.Pos().Base()]
1521	is122 := fileVersion == "" || version.Compare(fileVersion, "go1.22") >= 0
1522
1523	// Turning off loopvar for 1.22 is only possible with loopvarhash=qn
1524	//
1525	// Debug.LoopVar values to be preserved for 1.21 compatibility are 1 and 2,
1526	// which are also set (=1) by GOEXPERIMENT=loopvar.  The knobs for turning on
1527	// the new, unshared, loopvar behavior apply to versions less than 1.21 because
1528	// (1) 1.21 also did that and (2) this is believed to be the likely use case;
1529	// anyone checking to see if it affects their code will just run the GOEXPERIMENT
1530	// but will not also update all their go.mod files to 1.21.
1531	//
1532	// -gcflags=-d=loopvar=3 enables logging for 1.22 but does not turn loopvar on for <= 1.21.
1533
1534	return is122 || lv > 0 && lv != 3
1535}
1536
1537func (w *writer) ifStmt(stmt *syntax.IfStmt) {
1538	cond := w.p.staticBool(&stmt.Cond)
1539
1540	w.Sync(pkgbits.SyncIfStmt)
1541	w.openScope(stmt.Pos())
1542	w.pos(stmt)
1543	w.stmt(stmt.Init)
1544	w.expr(stmt.Cond)
1545	w.Int(cond)
1546	if cond >= 0 {
1547		w.blockStmt(stmt.Then)
1548	} else {
1549		w.pos(stmt.Then.Rbrace)
1550	}
1551	if cond <= 0 {
1552		w.stmt(stmt.Else)
1553	}
1554	w.closeAnotherScope()
1555}
1556
1557func (w *writer) selectStmt(stmt *syntax.SelectStmt) {
1558	w.Sync(pkgbits.SyncSelectStmt)
1559
1560	w.pos(stmt)
1561	w.Len(len(stmt.Body))
1562	for i, clause := range stmt.Body {
1563		if i > 0 {
1564			w.closeScope(clause.Pos())
1565		}
1566		w.openScope(clause.Pos())
1567
1568		w.pos(clause)
1569		w.stmt(clause.Comm)
1570		w.stmts(clause.Body)
1571	}
1572	if len(stmt.Body) > 0 {
1573		w.closeScope(stmt.Rbrace)
1574	}
1575}
1576
1577func (w *writer) switchStmt(stmt *syntax.SwitchStmt) {
1578	w.Sync(pkgbits.SyncSwitchStmt)
1579
1580	w.openScope(stmt.Pos())
1581	w.pos(stmt)
1582	w.stmt(stmt.Init)
1583
1584	var iface, tagType types2.Type
1585	var tagTypeIsChan bool
1586	if guard, ok := stmt.Tag.(*syntax.TypeSwitchGuard); w.Bool(ok) {
1587		iface = w.p.typeOf(guard.X)
1588
1589		w.pos(guard)
1590		if tag := guard.Lhs; w.Bool(tag != nil) {
1591			w.pos(tag)
1592
1593			// Like w.localIdent, but we don't have a types2.Object.
1594			w.Sync(pkgbits.SyncLocalIdent)
1595			w.pkg(w.p.curpkg)
1596			w.String(tag.Value)
1597		}
1598		w.expr(guard.X)
1599	} else {
1600		tag := stmt.Tag
1601
1602		var tagValue constant.Value
1603		if tag != nil {
1604			tv := w.p.typeAndValue(tag)
1605			tagType = tv.Type
1606			tagValue = tv.Value
1607			_, tagTypeIsChan = tagType.Underlying().(*types2.Chan)
1608		} else {
1609			tagType = types2.Typ[types2.Bool]
1610			tagValue = constant.MakeBool(true)
1611		}
1612
1613		if tagValue != nil {
1614			// If the switch tag has a constant value, look for a case
1615			// clause that we always branch to.
1616			func() {
1617				var target *syntax.CaseClause
1618			Outer:
1619				for _, clause := range stmt.Body {
1620					if clause.Cases == nil {
1621						target = clause
1622					}
1623					for _, cas := range syntax.UnpackListExpr(clause.Cases) {
1624						tv := w.p.typeAndValue(cas)
1625						if tv.Value == nil {
1626							return // non-constant case; give up
1627						}
1628						if constant.Compare(tagValue, token.EQL, tv.Value) {
1629							target = clause
1630							break Outer
1631						}
1632					}
1633				}
1634				// We've found the target clause, if any.
1635
1636				if target != nil {
1637					if hasFallthrough(target.Body) {
1638						return // fallthrough is tricky; give up
1639					}
1640
1641					// Rewrite as single "default" case.
1642					target.Cases = nil
1643					stmt.Body = []*syntax.CaseClause{target}
1644				} else {
1645					stmt.Body = nil
1646				}
1647
1648				// Clear switch tag (i.e., replace with implicit "true").
1649				tag = nil
1650				stmt.Tag = nil
1651				tagType = types2.Typ[types2.Bool]
1652			}()
1653		}
1654
1655		// Walk is going to emit comparisons between the tag value and
1656		// each case expression, and we want these comparisons to always
1657		// have the same type. If there are any case values that can't be
1658		// converted to the tag value's type, then convert everything to
1659		// `any` instead.
1660		//
1661		// Except that we need to keep comparisons of channel values from
1662		// being wrapped in any(). See issue #67190.
1663
1664		if !tagTypeIsChan {
1665		Outer:
1666			for _, clause := range stmt.Body {
1667				for _, cas := range syntax.UnpackListExpr(clause.Cases) {
1668					if casType := w.p.typeOf(cas); !types2.AssignableTo(casType, tagType) {
1669						tagType = types2.NewInterfaceType(nil, nil)
1670						break Outer
1671					}
1672				}
1673			}
1674		}
1675
1676		if w.Bool(tag != nil) {
1677			w.implicitConvExpr(tagType, tag)
1678		}
1679	}
1680
1681	w.Len(len(stmt.Body))
1682	for i, clause := range stmt.Body {
1683		if i > 0 {
1684			w.closeScope(clause.Pos())
1685		}
1686		w.openScope(clause.Pos())
1687
1688		w.pos(clause)
1689
1690		cases := syntax.UnpackListExpr(clause.Cases)
1691		if iface != nil {
1692			w.Len(len(cases))
1693			for _, cas := range cases {
1694				if w.Bool(isNil(w.p, cas)) {
1695					continue
1696				}
1697				w.exprType(iface, cas)
1698			}
1699		} else {
1700			// As if w.exprList(clause.Cases),
1701			// but with implicit conversions to tagType.
1702
1703			w.Sync(pkgbits.SyncExprList)
1704			w.Sync(pkgbits.SyncExprs)
1705			w.Len(len(cases))
1706			for _, cas := range cases {
1707				typ := tagType
1708				if tagTypeIsChan {
1709					typ = nil
1710				}
1711				w.implicitConvExpr(typ, cas)
1712			}
1713		}
1714
1715		if obj, ok := w.p.info.Implicits[clause]; ok {
1716			// TODO(mdempsky): These pos details are quirkish, but also
1717			// necessary so the variable's position is correct for DWARF
1718			// scope assignment later. It would probably be better for us to
1719			// instead just set the variable's DWARF scoping info earlier so
1720			// we can give it the correct position information.
1721			pos := clause.Pos()
1722			if typs := syntax.UnpackListExpr(clause.Cases); len(typs) != 0 {
1723				pos = typeExprEndPos(typs[len(typs)-1])
1724			}
1725			w.pos(pos)
1726
1727			obj := obj.(*types2.Var)
1728			w.typ(obj.Type())
1729			w.addLocal(obj)
1730		}
1731
1732		w.stmts(clause.Body)
1733	}
1734	if len(stmt.Body) > 0 {
1735		w.closeScope(stmt.Rbrace)
1736	}
1737
1738	w.closeScope(stmt.Rbrace)
1739}
1740
1741func (w *writer) label(label *syntax.Name) {
1742	w.Sync(pkgbits.SyncLabel)
1743
1744	// TODO(mdempsky): Replace label strings with dense indices.
1745	w.String(label.Value)
1746}
1747
1748func (w *writer) optLabel(label *syntax.Name) {
1749	w.Sync(pkgbits.SyncOptLabel)
1750	if w.Bool(label != nil) {
1751		w.label(label)
1752	}
1753}
1754
1755// @@@ Expressions
1756
1757// expr writes the given expression into the function body bitstream.
1758func (w *writer) expr(expr syntax.Expr) {
1759	base.Assertf(expr != nil, "missing expression")
1760
1761	expr = syntax.Unparen(expr) // skip parens; unneeded after typecheck
1762
1763	obj, inst := lookupObj(w.p, expr)
1764	targs := inst.TypeArgs
1765
1766	if tv, ok := w.p.maybeTypeAndValue(expr); ok {
1767		if tv.IsRuntimeHelper() {
1768			if pkg := obj.Pkg(); pkg != nil && pkg.Name() == "runtime" {
1769				objName := obj.Name()
1770				w.Code(exprRuntimeBuiltin)
1771				w.String(objName)
1772				return
1773			}
1774		}
1775
1776		if tv.IsType() {
1777			w.p.fatalf(expr, "unexpected type expression %v", syntax.String(expr))
1778		}
1779
1780		if tv.Value != nil {
1781			w.Code(exprConst)
1782			w.pos(expr)
1783			typ := idealType(tv)
1784			assert(typ != nil)
1785			w.typ(typ)
1786			w.Value(tv.Value)
1787			return
1788		}
1789
1790		if _, isNil := obj.(*types2.Nil); isNil {
1791			w.Code(exprZero)
1792			w.pos(expr)
1793			w.typ(tv.Type)
1794			return
1795		}
1796
1797		// With shape types (and particular pointer shaping), we may have
1798		// an expression of type "go.shape.*uint8", but need to reshape it
1799		// to another shape-identical type to allow use in field
1800		// selection, indexing, etc.
1801		if typ := tv.Type; !tv.IsBuiltin() && !isTuple(typ) && !isUntyped(typ) {
1802			w.Code(exprReshape)
1803			w.typ(typ)
1804			// fallthrough
1805		}
1806	}
1807
1808	if obj != nil {
1809		if targs.Len() != 0 {
1810			obj := obj.(*types2.Func)
1811
1812			w.Code(exprFuncInst)
1813			w.pos(expr)
1814			w.funcInst(obj, targs)
1815			return
1816		}
1817
1818		if isGlobal(obj) {
1819			w.Code(exprGlobal)
1820			w.obj(obj, nil)
1821			return
1822		}
1823
1824		obj := obj.(*types2.Var)
1825		assert(!obj.IsField())
1826
1827		w.Code(exprLocal)
1828		w.useLocal(expr.Pos(), obj)
1829		return
1830	}
1831
1832	switch expr := expr.(type) {
1833	default:
1834		w.p.unexpected("expression", expr)
1835
1836	case *syntax.CompositeLit:
1837		w.Code(exprCompLit)
1838		w.compLit(expr)
1839
1840	case *syntax.FuncLit:
1841		w.Code(exprFuncLit)
1842		w.funcLit(expr)
1843
1844	case *syntax.SelectorExpr:
1845		sel, ok := w.p.info.Selections[expr]
1846		assert(ok)
1847
1848		switch sel.Kind() {
1849		default:
1850			w.p.fatalf(expr, "unexpected selection kind: %v", sel.Kind())
1851
1852		case types2.FieldVal:
1853			w.Code(exprFieldVal)
1854			w.expr(expr.X)
1855			w.pos(expr)
1856			w.selector(sel.Obj())
1857
1858		case types2.MethodVal:
1859			w.Code(exprMethodVal)
1860			typ := w.recvExpr(expr, sel)
1861			w.pos(expr)
1862			w.methodExpr(expr, typ, sel)
1863
1864		case types2.MethodExpr:
1865			w.Code(exprMethodExpr)
1866
1867			tv := w.p.typeAndValue(expr.X)
1868			assert(tv.IsType())
1869
1870			index := sel.Index()
1871			implicits := index[:len(index)-1]
1872
1873			typ := tv.Type
1874			w.typ(typ)
1875
1876			w.Len(len(implicits))
1877			for _, ix := range implicits {
1878				w.Len(ix)
1879				typ = deref2(typ).Underlying().(*types2.Struct).Field(ix).Type()
1880			}
1881
1882			recv := sel.Obj().(*types2.Func).Type().(*types2.Signature).Recv().Type()
1883			if w.Bool(isPtrTo(typ, recv)) { // need deref
1884				typ = recv
1885			} else if w.Bool(isPtrTo(recv, typ)) { // need addr
1886				typ = recv
1887			}
1888
1889			w.pos(expr)
1890			w.methodExpr(expr, typ, sel)
1891		}
1892
1893	case *syntax.IndexExpr:
1894		_ = w.p.typeOf(expr.Index) // ensure this is an index expression, not an instantiation
1895
1896		xtyp := w.p.typeOf(expr.X)
1897
1898		var keyType types2.Type
1899		if mapType, ok := types2.CoreType(xtyp).(*types2.Map); ok {
1900			keyType = mapType.Key()
1901		}
1902
1903		w.Code(exprIndex)
1904		w.expr(expr.X)
1905		w.pos(expr)
1906		w.implicitConvExpr(keyType, expr.Index)
1907		if keyType != nil {
1908			w.rtype(xtyp)
1909		}
1910
1911	case *syntax.SliceExpr:
1912		w.Code(exprSlice)
1913		w.expr(expr.X)
1914		w.pos(expr)
1915		for _, n := range &expr.Index {
1916			w.optExpr(n)
1917		}
1918
1919	case *syntax.AssertExpr:
1920		iface := w.p.typeOf(expr.X)
1921
1922		w.Code(exprAssert)
1923		w.expr(expr.X)
1924		w.pos(expr)
1925		w.exprType(iface, expr.Type)
1926		w.rtype(iface)
1927
1928	case *syntax.Operation:
1929		if expr.Y == nil {
1930			w.Code(exprUnaryOp)
1931			w.op(unOps[expr.Op])
1932			w.pos(expr)
1933			w.expr(expr.X)
1934			break
1935		}
1936
1937		var commonType types2.Type
1938		switch expr.Op {
1939		case syntax.Shl, syntax.Shr:
1940			// ok: operands are allowed to have different types
1941		default:
1942			xtyp := w.p.typeOf(expr.X)
1943			ytyp := w.p.typeOf(expr.Y)
1944			switch {
1945			case types2.AssignableTo(xtyp, ytyp):
1946				commonType = ytyp
1947			case types2.AssignableTo(ytyp, xtyp):
1948				commonType = xtyp
1949			default:
1950				w.p.fatalf(expr, "failed to find common type between %v and %v", xtyp, ytyp)
1951			}
1952		}
1953
1954		w.Code(exprBinaryOp)
1955		w.op(binOps[expr.Op])
1956		w.implicitConvExpr(commonType, expr.X)
1957		w.pos(expr)
1958		w.implicitConvExpr(commonType, expr.Y)
1959
1960	case *syntax.CallExpr:
1961		tv := w.p.typeAndValue(expr.Fun)
1962		if tv.IsType() {
1963			assert(len(expr.ArgList) == 1)
1964			assert(!expr.HasDots)
1965			w.convertExpr(tv.Type, expr.ArgList[0], false)
1966			break
1967		}
1968
1969		var rtype types2.Type
1970		if tv.IsBuiltin() {
1971			switch obj, _ := lookupObj(w.p, syntax.Unparen(expr.Fun)); obj.Name() {
1972			case "make":
1973				assert(len(expr.ArgList) >= 1)
1974				assert(!expr.HasDots)
1975
1976				w.Code(exprMake)
1977				w.pos(expr)
1978				w.exprType(nil, expr.ArgList[0])
1979				w.exprs(expr.ArgList[1:])
1980
1981				typ := w.p.typeOf(expr)
1982				switch coreType := types2.CoreType(typ).(type) {
1983				default:
1984					w.p.fatalf(expr, "unexpected core type: %v", coreType)
1985				case *types2.Chan:
1986					w.rtype(typ)
1987				case *types2.Map:
1988					w.rtype(typ)
1989				case *types2.Slice:
1990					w.rtype(sliceElem(typ))
1991				}
1992
1993				return
1994
1995			case "new":
1996				assert(len(expr.ArgList) == 1)
1997				assert(!expr.HasDots)
1998
1999				w.Code(exprNew)
2000				w.pos(expr)
2001				w.exprType(nil, expr.ArgList[0])
2002				return
2003
2004			case "Sizeof":
2005				assert(len(expr.ArgList) == 1)
2006				assert(!expr.HasDots)
2007
2008				w.Code(exprSizeof)
2009				w.pos(expr)
2010				w.typ(w.p.typeOf(expr.ArgList[0]))
2011				return
2012
2013			case "Alignof":
2014				assert(len(expr.ArgList) == 1)
2015				assert(!expr.HasDots)
2016
2017				w.Code(exprAlignof)
2018				w.pos(expr)
2019				w.typ(w.p.typeOf(expr.ArgList[0]))
2020				return
2021
2022			case "Offsetof":
2023				assert(len(expr.ArgList) == 1)
2024				assert(!expr.HasDots)
2025				selector := syntax.Unparen(expr.ArgList[0]).(*syntax.SelectorExpr)
2026				index := w.p.info.Selections[selector].Index()
2027
2028				w.Code(exprOffsetof)
2029				w.pos(expr)
2030				w.typ(deref2(w.p.typeOf(selector.X)))
2031				w.Len(len(index) - 1)
2032				for _, idx := range index {
2033					w.Len(idx)
2034				}
2035				return
2036
2037			case "append":
2038				rtype = sliceElem(w.p.typeOf(expr))
2039			case "copy":
2040				typ := w.p.typeOf(expr.ArgList[0])
2041				if tuple, ok := typ.(*types2.Tuple); ok { // "copy(g())"
2042					typ = tuple.At(0).Type()
2043				}
2044				rtype = sliceElem(typ)
2045			case "delete":
2046				typ := w.p.typeOf(expr.ArgList[0])
2047				if tuple, ok := typ.(*types2.Tuple); ok { // "delete(g())"
2048					typ = tuple.At(0).Type()
2049				}
2050				rtype = typ
2051			case "Slice":
2052				rtype = sliceElem(w.p.typeOf(expr))
2053			}
2054		}
2055
2056		writeFunExpr := func() {
2057			fun := syntax.Unparen(expr.Fun)
2058
2059			if selector, ok := fun.(*syntax.SelectorExpr); ok {
2060				if sel, ok := w.p.info.Selections[selector]; ok && sel.Kind() == types2.MethodVal {
2061					w.Bool(true) // method call
2062					typ := w.recvExpr(selector, sel)
2063					w.methodExpr(selector, typ, sel)
2064					return
2065				}
2066			}
2067
2068			w.Bool(false) // not a method call (i.e., normal function call)
2069
2070			if obj, inst := lookupObj(w.p, fun); w.Bool(obj != nil && inst.TypeArgs.Len() != 0) {
2071				obj := obj.(*types2.Func)
2072
2073				w.pos(fun)
2074				w.funcInst(obj, inst.TypeArgs)
2075				return
2076			}
2077
2078			w.expr(fun)
2079		}
2080
2081		sigType := types2.CoreType(tv.Type).(*types2.Signature)
2082		paramTypes := sigType.Params()
2083
2084		w.Code(exprCall)
2085		writeFunExpr()
2086		w.pos(expr)
2087
2088		paramType := func(i int) types2.Type {
2089			if sigType.Variadic() && !expr.HasDots && i >= paramTypes.Len()-1 {
2090				return paramTypes.At(paramTypes.Len() - 1).Type().(*types2.Slice).Elem()
2091			}
2092			return paramTypes.At(i).Type()
2093		}
2094
2095		w.multiExpr(expr, paramType, expr.ArgList)
2096		w.Bool(expr.HasDots)
2097		if rtype != nil {
2098			w.rtype(rtype)
2099		}
2100	}
2101}
2102
2103func sliceElem(typ types2.Type) types2.Type {
2104	return types2.CoreType(typ).(*types2.Slice).Elem()
2105}
2106
2107func (w *writer) optExpr(expr syntax.Expr) {
2108	if w.Bool(expr != nil) {
2109		w.expr(expr)
2110	}
2111}
2112
2113// recvExpr writes out expr.X, but handles any implicit addressing,
2114// dereferencing, and field selections appropriate for the method
2115// selection.
2116func (w *writer) recvExpr(expr *syntax.SelectorExpr, sel *types2.Selection) types2.Type {
2117	index := sel.Index()
2118	implicits := index[:len(index)-1]
2119
2120	w.Code(exprRecv)
2121	w.expr(expr.X)
2122	w.pos(expr)
2123	w.Len(len(implicits))
2124
2125	typ := w.p.typeOf(expr.X)
2126	for _, ix := range implicits {
2127		typ = deref2(typ).Underlying().(*types2.Struct).Field(ix).Type()
2128		w.Len(ix)
2129	}
2130
2131	recv := sel.Obj().(*types2.Func).Type().(*types2.Signature).Recv().Type()
2132	if w.Bool(isPtrTo(typ, recv)) { // needs deref
2133		typ = recv
2134	} else if w.Bool(isPtrTo(recv, typ)) { // needs addr
2135		typ = recv
2136	}
2137
2138	return typ
2139}
2140
2141// funcInst writes a reference to an instantiated function.
2142func (w *writer) funcInst(obj *types2.Func, targs *types2.TypeList) {
2143	info := w.p.objInstIdx(obj, targs, w.dict)
2144
2145	// Type arguments list contains derived types; we can emit a static
2146	// call to the shaped function, but need to dynamically compute the
2147	// runtime dictionary pointer.
2148	if w.Bool(info.anyDerived()) {
2149		w.Len(w.dict.subdictIdx(info))
2150		return
2151	}
2152
2153	// Type arguments list is statically known; we can emit a static
2154	// call with a statically reference to the respective runtime
2155	// dictionary.
2156	w.objInfo(info)
2157}
2158
2159// methodExpr writes out a reference to the method selected by
2160// expr. sel should be the corresponding types2.Selection, and recv
2161// the type produced after any implicit addressing, dereferencing, and
2162// field selection. (Note: recv might differ from sel.Obj()'s receiver
2163// parameter in the case of interface types, and is needed for
2164// handling type parameter methods.)
2165func (w *writer) methodExpr(expr *syntax.SelectorExpr, recv types2.Type, sel *types2.Selection) {
2166	fun := sel.Obj().(*types2.Func)
2167	sig := fun.Type().(*types2.Signature)
2168
2169	w.typ(recv)
2170	w.typ(sig)
2171	w.pos(expr)
2172	w.selector(fun)
2173
2174	// Method on a type parameter. These require an indirect call
2175	// through the current function's runtime dictionary.
2176	if typeParam, ok := types2.Unalias(recv).(*types2.TypeParam); w.Bool(ok) {
2177		typeParamIdx := w.dict.typeParamIndex(typeParam)
2178		methodInfo := w.p.selectorIdx(fun)
2179
2180		w.Len(w.dict.typeParamMethodExprIdx(typeParamIdx, methodInfo))
2181		return
2182	}
2183
2184	if isInterface(recv) != isInterface(sig.Recv().Type()) {
2185		w.p.fatalf(expr, "isInterface inconsistency: %v and %v", recv, sig.Recv().Type())
2186	}
2187
2188	if !isInterface(recv) {
2189		if named, ok := types2.Unalias(deref2(recv)).(*types2.Named); ok {
2190			obj, targs := splitNamed(named)
2191			info := w.p.objInstIdx(obj, targs, w.dict)
2192
2193			// Method on a derived receiver type. These can be handled by a
2194			// static call to the shaped method, but require dynamically
2195			// looking up the appropriate dictionary argument in the current
2196			// function's runtime dictionary.
2197			if w.p.hasImplicitTypeParams(obj) || info.anyDerived() {
2198				w.Bool(true) // dynamic subdictionary
2199				w.Len(w.dict.subdictIdx(info))
2200				return
2201			}
2202
2203			// Method on a fully known receiver type. These can be handled
2204			// by a static call to the shaped method, and with a static
2205			// reference to the receiver type's dictionary.
2206			if targs.Len() != 0 {
2207				w.Bool(false) // no dynamic subdictionary
2208				w.Bool(true)  // static dictionary
2209				w.objInfo(info)
2210				return
2211			}
2212		}
2213	}
2214
2215	w.Bool(false) // no dynamic subdictionary
2216	w.Bool(false) // no static dictionary
2217}
2218
2219// multiExpr writes a sequence of expressions, where the i'th value is
2220// implicitly converted to dstType(i). It also handles when exprs is a
2221// single, multi-valued expression (e.g., the multi-valued argument in
2222// an f(g()) call, or the RHS operand in a comma-ok assignment).
2223func (w *writer) multiExpr(pos poser, dstType func(int) types2.Type, exprs []syntax.Expr) {
2224	w.Sync(pkgbits.SyncMultiExpr)
2225
2226	if len(exprs) == 1 {
2227		expr := exprs[0]
2228		if tuple, ok := w.p.typeOf(expr).(*types2.Tuple); ok {
2229			assert(tuple.Len() > 1)
2230			w.Bool(true) // N:1 assignment
2231			w.pos(pos)
2232			w.expr(expr)
2233
2234			w.Len(tuple.Len())
2235			for i := 0; i < tuple.Len(); i++ {
2236				src := tuple.At(i).Type()
2237				// TODO(mdempsky): Investigate not writing src here. I think
2238				// the reader should be able to infer it from expr anyway.
2239				w.typ(src)
2240				if dst := dstType(i); w.Bool(dst != nil && !types2.Identical(src, dst)) {
2241					if src == nil || dst == nil {
2242						w.p.fatalf(pos, "src is %v, dst is %v", src, dst)
2243					}
2244					if !types2.AssignableTo(src, dst) {
2245						w.p.fatalf(pos, "%v is not assignable to %v", src, dst)
2246					}
2247					w.typ(dst)
2248					w.convRTTI(src, dst)
2249				}
2250			}
2251			return
2252		}
2253	}
2254
2255	w.Bool(false) // N:N assignment
2256	w.Len(len(exprs))
2257	for i, expr := range exprs {
2258		w.implicitConvExpr(dstType(i), expr)
2259	}
2260}
2261
2262// implicitConvExpr is like expr, but if dst is non-nil and different
2263// from expr's type, then an implicit conversion operation is inserted
2264// at expr's position.
2265func (w *writer) implicitConvExpr(dst types2.Type, expr syntax.Expr) {
2266	w.convertExpr(dst, expr, true)
2267}
2268
2269func (w *writer) convertExpr(dst types2.Type, expr syntax.Expr, implicit bool) {
2270	src := w.p.typeOf(expr)
2271
2272	// Omit implicit no-op conversions.
2273	identical := dst == nil || types2.Identical(src, dst)
2274	if implicit && identical {
2275		w.expr(expr)
2276		return
2277	}
2278
2279	if implicit && !types2.AssignableTo(src, dst) {
2280		w.p.fatalf(expr, "%v is not assignable to %v", src, dst)
2281	}
2282
2283	w.Code(exprConvert)
2284	w.Bool(implicit)
2285	w.typ(dst)
2286	w.pos(expr)
2287	w.convRTTI(src, dst)
2288	w.Bool(isTypeParam(dst))
2289	w.Bool(identical)
2290	w.expr(expr)
2291}
2292
2293func (w *writer) compLit(lit *syntax.CompositeLit) {
2294	typ := w.p.typeOf(lit)
2295
2296	w.Sync(pkgbits.SyncCompLit)
2297	w.pos(lit)
2298	w.typ(typ)
2299
2300	if ptr, ok := types2.CoreType(typ).(*types2.Pointer); ok {
2301		typ = ptr.Elem()
2302	}
2303	var keyType, elemType types2.Type
2304	var structType *types2.Struct
2305	switch typ0 := typ; typ := types2.CoreType(typ).(type) {
2306	default:
2307		w.p.fatalf(lit, "unexpected composite literal type: %v", typ)
2308	case *types2.Array:
2309		elemType = typ.Elem()
2310	case *types2.Map:
2311		w.rtype(typ0)
2312		keyType, elemType = typ.Key(), typ.Elem()
2313	case *types2.Slice:
2314		elemType = typ.Elem()
2315	case *types2.Struct:
2316		structType = typ
2317	}
2318
2319	w.Len(len(lit.ElemList))
2320	for i, elem := range lit.ElemList {
2321		elemType := elemType
2322		if structType != nil {
2323			if kv, ok := elem.(*syntax.KeyValueExpr); ok {
2324				// use position of expr.Key rather than of elem (which has position of ':')
2325				w.pos(kv.Key)
2326				i = fieldIndex(w.p.info, structType, kv.Key.(*syntax.Name))
2327				elem = kv.Value
2328			} else {
2329				w.pos(elem)
2330			}
2331			elemType = structType.Field(i).Type()
2332			w.Len(i)
2333		} else {
2334			if kv, ok := elem.(*syntax.KeyValueExpr); w.Bool(ok) {
2335				// use position of expr.Key rather than of elem (which has position of ':')
2336				w.pos(kv.Key)
2337				w.implicitConvExpr(keyType, kv.Key)
2338				elem = kv.Value
2339			}
2340		}
2341		w.implicitConvExpr(elemType, elem)
2342	}
2343}
2344
2345func (w *writer) funcLit(expr *syntax.FuncLit) {
2346	sig := w.p.typeOf(expr).(*types2.Signature)
2347
2348	body, closureVars := w.p.bodyIdx(sig, expr.Body, w.dict)
2349
2350	w.Sync(pkgbits.SyncFuncLit)
2351	w.pos(expr)
2352	w.signature(sig)
2353	w.Bool(w.p.rangeFuncBodyClosures[expr])
2354
2355	w.Len(len(closureVars))
2356	for _, cv := range closureVars {
2357		w.pos(cv.pos)
2358		w.useLocal(cv.pos, cv.var_)
2359	}
2360
2361	w.Reloc(pkgbits.RelocBody, body)
2362}
2363
2364type posVar struct {
2365	pos  syntax.Pos
2366	var_ *types2.Var
2367}
2368
2369func (p posVar) String() string {
2370	return p.pos.String() + ":" + p.var_.String()
2371}
2372
2373func (w *writer) exprList(expr syntax.Expr) {
2374	w.Sync(pkgbits.SyncExprList)
2375	w.exprs(syntax.UnpackListExpr(expr))
2376}
2377
2378func (w *writer) exprs(exprs []syntax.Expr) {
2379	w.Sync(pkgbits.SyncExprs)
2380	w.Len(len(exprs))
2381	for _, expr := range exprs {
2382		w.expr(expr)
2383	}
2384}
2385
2386// rtype writes information so that the reader can construct an
2387// expression of type *runtime._type representing typ.
2388func (w *writer) rtype(typ types2.Type) {
2389	typ = types2.Default(typ)
2390
2391	info := w.p.typIdx(typ, w.dict)
2392	w.rtypeInfo(info)
2393}
2394
2395func (w *writer) rtypeInfo(info typeInfo) {
2396	w.Sync(pkgbits.SyncRType)
2397
2398	if w.Bool(info.derived) {
2399		w.Len(w.dict.rtypeIdx(info))
2400	} else {
2401		w.typInfo(info)
2402	}
2403}
2404
2405// varDictIndex writes out information for populating DictIndex for
2406// the ir.Name that will represent obj.
2407func (w *writer) varDictIndex(obj *types2.Var) {
2408	info := w.p.typIdx(obj.Type(), w.dict)
2409	if w.Bool(info.derived) {
2410		w.Len(w.dict.rtypeIdx(info))
2411	}
2412}
2413
2414// isUntyped reports whether typ is an untyped type.
2415func isUntyped(typ types2.Type) bool {
2416	// Note: types2.Unalias is unnecessary here, since untyped types can't be aliased.
2417	basic, ok := typ.(*types2.Basic)
2418	return ok && basic.Info()&types2.IsUntyped != 0
2419}
2420
2421// isTuple reports whether typ is a tuple type.
2422func isTuple(typ types2.Type) bool {
2423	// Note: types2.Unalias is unnecessary here, since tuple types can't be aliased.
2424	_, ok := typ.(*types2.Tuple)
2425	return ok
2426}
2427
2428func (w *writer) itab(typ, iface types2.Type) {
2429	typ = types2.Default(typ)
2430	iface = types2.Default(iface)
2431
2432	typInfo := w.p.typIdx(typ, w.dict)
2433	ifaceInfo := w.p.typIdx(iface, w.dict)
2434
2435	w.rtypeInfo(typInfo)
2436	w.rtypeInfo(ifaceInfo)
2437	if w.Bool(typInfo.derived || ifaceInfo.derived) {
2438		w.Len(w.dict.itabIdx(typInfo, ifaceInfo))
2439	}
2440}
2441
2442// convRTTI writes information so that the reader can construct
2443// expressions for converting from src to dst.
2444func (w *writer) convRTTI(src, dst types2.Type) {
2445	w.Sync(pkgbits.SyncConvRTTI)
2446	w.itab(src, dst)
2447}
2448
2449func (w *writer) exprType(iface types2.Type, typ syntax.Expr) {
2450	base.Assertf(iface == nil || isInterface(iface), "%v must be nil or an interface type", iface)
2451
2452	tv := w.p.typeAndValue(typ)
2453	assert(tv.IsType())
2454
2455	w.Sync(pkgbits.SyncExprType)
2456	w.pos(typ)
2457
2458	if w.Bool(iface != nil && !iface.Underlying().(*types2.Interface).Empty()) {
2459		w.itab(tv.Type, iface)
2460	} else {
2461		w.rtype(tv.Type)
2462
2463		info := w.p.typIdx(tv.Type, w.dict)
2464		w.Bool(info.derived)
2465	}
2466}
2467
2468// isInterface reports whether typ is known to be an interface type.
2469// If typ is a type parameter, then isInterface reports an internal
2470// compiler error instead.
2471func isInterface(typ types2.Type) bool {
2472	if _, ok := types2.Unalias(typ).(*types2.TypeParam); ok {
2473		// typ is a type parameter and may be instantiated as either a
2474		// concrete or interface type, so the writer can't depend on
2475		// knowing this.
2476		base.Fatalf("%v is a type parameter", typ)
2477	}
2478
2479	_, ok := typ.Underlying().(*types2.Interface)
2480	return ok
2481}
2482
2483// op writes an Op into the bitstream.
2484func (w *writer) op(op ir.Op) {
2485	// TODO(mdempsky): Remove in favor of explicit codes? Would make
2486	// export data more stable against internal refactorings, but low
2487	// priority at the moment.
2488	assert(op != 0)
2489	w.Sync(pkgbits.SyncOp)
2490	w.Len(int(op))
2491}
2492
2493// @@@ Package initialization
2494
2495// Caution: This code is still clumsy, because toolstash -cmp is
2496// particularly sensitive to it.
2497
2498type typeDeclGen struct {
2499	*syntax.TypeDecl
2500	gen int
2501
2502	// Implicit type parameters in scope at this type declaration.
2503	implicits []*types2.TypeParam
2504}
2505
2506type fileImports struct {
2507	importedEmbed, importedUnsafe bool
2508}
2509
2510// declCollector is a visitor type that collects compiler-needed
2511// information about declarations that types2 doesn't track.
2512//
2513// Notably, it maps declared types and functions back to their
2514// declaration statement, keeps track of implicit type parameters, and
2515// assigns unique type "generation" numbers to local defined types.
2516type declCollector struct {
2517	pw         *pkgWriter
2518	typegen    *int
2519	file       *fileImports
2520	withinFunc bool
2521	implicits  []*types2.TypeParam
2522}
2523
2524func (c *declCollector) withTParams(obj types2.Object) *declCollector {
2525	tparams := objTypeParams(obj)
2526	n := tparams.Len()
2527	if n == 0 {
2528		return c
2529	}
2530
2531	copy := *c
2532	copy.implicits = copy.implicits[:len(copy.implicits):len(copy.implicits)]
2533	for i := 0; i < n; i++ {
2534		copy.implicits = append(copy.implicits, tparams.At(i))
2535	}
2536	return &copy
2537}
2538
2539func (c *declCollector) Visit(n syntax.Node) syntax.Visitor {
2540	pw := c.pw
2541
2542	switch n := n.(type) {
2543	case *syntax.File:
2544		pw.checkPragmas(n.Pragma, ir.GoBuildPragma, false)
2545
2546	case *syntax.ImportDecl:
2547		pw.checkPragmas(n.Pragma, 0, false)
2548
2549		switch pw.info.PkgNameOf(n).Imported().Path() {
2550		case "embed":
2551			c.file.importedEmbed = true
2552		case "unsafe":
2553			c.file.importedUnsafe = true
2554		}
2555
2556	case *syntax.ConstDecl:
2557		pw.checkPragmas(n.Pragma, 0, false)
2558
2559	case *syntax.FuncDecl:
2560		pw.checkPragmas(n.Pragma, funcPragmas, false)
2561
2562		obj := pw.info.Defs[n.Name].(*types2.Func)
2563		pw.funDecls[obj] = n
2564
2565		return c.withTParams(obj)
2566
2567	case *syntax.TypeDecl:
2568		obj := pw.info.Defs[n.Name].(*types2.TypeName)
2569		d := typeDeclGen{TypeDecl: n, implicits: c.implicits}
2570
2571		if n.Alias {
2572			pw.checkPragmas(n.Pragma, 0, false)
2573		} else {
2574			pw.checkPragmas(n.Pragma, 0, false)
2575
2576			// Assign a unique ID to function-scoped defined types.
2577			if c.withinFunc {
2578				*c.typegen++
2579				d.gen = *c.typegen
2580			}
2581		}
2582
2583		pw.typDecls[obj] = d
2584
2585		// TODO(mdempsky): Omit? Not strictly necessary; only matters for
2586		// type declarations within function literals within parameterized
2587		// type declarations, but types2 the function literals will be
2588		// constant folded away.
2589		return c.withTParams(obj)
2590
2591	case *syntax.VarDecl:
2592		pw.checkPragmas(n.Pragma, 0, true)
2593
2594		if p, ok := n.Pragma.(*pragmas); ok && len(p.Embeds) > 0 {
2595			if err := checkEmbed(n, c.file.importedEmbed, c.withinFunc); err != nil {
2596				pw.errorf(p.Embeds[0].Pos, "%s", err)
2597			}
2598		}
2599
2600	case *syntax.BlockStmt:
2601		if !c.withinFunc {
2602			copy := *c
2603			copy.withinFunc = true
2604			return &copy
2605		}
2606	}
2607
2608	return c
2609}
2610
2611func (pw *pkgWriter) collectDecls(noders []*noder) {
2612	var typegen int
2613	for _, p := range noders {
2614		var file fileImports
2615
2616		syntax.Walk(p.file, &declCollector{
2617			pw:      pw,
2618			typegen: &typegen,
2619			file:    &file,
2620		})
2621
2622		pw.cgoPragmas = append(pw.cgoPragmas, p.pragcgobuf...)
2623
2624		for _, l := range p.linknames {
2625			if !file.importedUnsafe {
2626				pw.errorf(l.pos, "//go:linkname only allowed in Go files that import \"unsafe\"")
2627				continue
2628			}
2629			if strings.Contains(l.remote, "[") && strings.Contains(l.remote, "]") {
2630				pw.errorf(l.pos, "//go:linkname reference of an instantiation is not allowed")
2631				continue
2632			}
2633
2634			switch obj := pw.curpkg.Scope().Lookup(l.local).(type) {
2635			case *types2.Func, *types2.Var:
2636				if _, ok := pw.linknames[obj]; !ok {
2637					pw.linknames[obj] = l.remote
2638				} else {
2639					pw.errorf(l.pos, "duplicate //go:linkname for %s", l.local)
2640				}
2641
2642			default:
2643				if types.AllowsGoVersion(1, 18) {
2644					pw.errorf(l.pos, "//go:linkname must refer to declared function or variable")
2645				}
2646			}
2647		}
2648	}
2649}
2650
2651func (pw *pkgWriter) checkPragmas(p syntax.Pragma, allowed ir.PragmaFlag, embedOK bool) {
2652	if p == nil {
2653		return
2654	}
2655	pragma := p.(*pragmas)
2656
2657	for _, pos := range pragma.Pos {
2658		if pos.Flag&^allowed != 0 {
2659			pw.errorf(pos.Pos, "misplaced compiler directive")
2660		}
2661	}
2662
2663	if !embedOK {
2664		for _, e := range pragma.Embeds {
2665			pw.errorf(e.Pos, "misplaced go:embed directive")
2666		}
2667	}
2668}
2669
2670func (w *writer) pkgInit(noders []*noder) {
2671	w.Len(len(w.p.cgoPragmas))
2672	for _, cgoPragma := range w.p.cgoPragmas {
2673		w.Strings(cgoPragma)
2674	}
2675
2676	w.pkgInitOrder()
2677
2678	w.Sync(pkgbits.SyncDecls)
2679	for _, p := range noders {
2680		for _, decl := range p.file.DeclList {
2681			w.pkgDecl(decl)
2682		}
2683	}
2684	w.Code(declEnd)
2685
2686	w.Sync(pkgbits.SyncEOF)
2687}
2688
2689func (w *writer) pkgInitOrder() {
2690	// TODO(mdempsky): Write as a function body instead?
2691	w.Len(len(w.p.info.InitOrder))
2692	for _, init := range w.p.info.InitOrder {
2693		w.Len(len(init.Lhs))
2694		for _, v := range init.Lhs {
2695			w.obj(v, nil)
2696		}
2697		w.expr(init.Rhs)
2698	}
2699}
2700
2701func (w *writer) pkgDecl(decl syntax.Decl) {
2702	switch decl := decl.(type) {
2703	default:
2704		w.p.unexpected("declaration", decl)
2705
2706	case *syntax.ImportDecl:
2707
2708	case *syntax.ConstDecl:
2709		w.Code(declOther)
2710		w.pkgObjs(decl.NameList...)
2711
2712	case *syntax.FuncDecl:
2713		if decl.Name.Value == "_" {
2714			break // skip blank functions
2715		}
2716
2717		obj := w.p.info.Defs[decl.Name].(*types2.Func)
2718		sig := obj.Type().(*types2.Signature)
2719
2720		if sig.RecvTypeParams() != nil || sig.TypeParams() != nil {
2721			break // skip generic functions
2722		}
2723
2724		if recv := sig.Recv(); recv != nil {
2725			w.Code(declMethod)
2726			w.typ(recvBase(recv))
2727			w.selector(obj)
2728			break
2729		}
2730
2731		w.Code(declFunc)
2732		w.pkgObjs(decl.Name)
2733
2734	case *syntax.TypeDecl:
2735		if len(decl.TParamList) != 0 {
2736			break // skip generic type decls
2737		}
2738
2739		if decl.Name.Value == "_" {
2740			break // skip blank type decls
2741		}
2742
2743		name := w.p.info.Defs[decl.Name].(*types2.TypeName)
2744		// Skip type declarations for interfaces that are only usable as
2745		// type parameter bounds.
2746		if iface, ok := name.Type().Underlying().(*types2.Interface); ok && !iface.IsMethodSet() {
2747			break
2748		}
2749
2750		w.Code(declOther)
2751		w.pkgObjs(decl.Name)
2752
2753	case *syntax.VarDecl:
2754		w.Code(declVar)
2755		w.pkgObjs(decl.NameList...)
2756
2757		var embeds []pragmaEmbed
2758		if p, ok := decl.Pragma.(*pragmas); ok {
2759			embeds = p.Embeds
2760		}
2761		w.Len(len(embeds))
2762		for _, embed := range embeds {
2763			w.pos(embed.Pos)
2764			w.Strings(embed.Patterns)
2765		}
2766	}
2767}
2768
2769func (w *writer) pkgObjs(names ...*syntax.Name) {
2770	w.Sync(pkgbits.SyncDeclNames)
2771	w.Len(len(names))
2772
2773	for _, name := range names {
2774		obj, ok := w.p.info.Defs[name]
2775		assert(ok)
2776
2777		w.Sync(pkgbits.SyncDeclName)
2778		w.obj(obj, nil)
2779	}
2780}
2781
2782// @@@ Helpers
2783
2784// staticBool analyzes a boolean expression and reports whether it's
2785// always true (positive result), always false (negative result), or
2786// unknown (zero).
2787//
2788// It also simplifies the expression while preserving semantics, if
2789// possible.
2790func (pw *pkgWriter) staticBool(ep *syntax.Expr) int {
2791	if val := pw.typeAndValue(*ep).Value; val != nil {
2792		if constant.BoolVal(val) {
2793			return +1
2794		} else {
2795			return -1
2796		}
2797	}
2798
2799	if e, ok := (*ep).(*syntax.Operation); ok {
2800		switch e.Op {
2801		case syntax.Not:
2802			return pw.staticBool(&e.X)
2803
2804		case syntax.AndAnd:
2805			x := pw.staticBool(&e.X)
2806			if x < 0 {
2807				*ep = e.X
2808				return x
2809			}
2810
2811			y := pw.staticBool(&e.Y)
2812			if x > 0 || y < 0 {
2813				if pw.typeAndValue(e.X).Value != nil {
2814					*ep = e.Y
2815				}
2816				return y
2817			}
2818
2819		case syntax.OrOr:
2820			x := pw.staticBool(&e.X)
2821			if x > 0 {
2822				*ep = e.X
2823				return x
2824			}
2825
2826			y := pw.staticBool(&e.Y)
2827			if x < 0 || y > 0 {
2828				if pw.typeAndValue(e.X).Value != nil {
2829					*ep = e.Y
2830				}
2831				return y
2832			}
2833		}
2834	}
2835
2836	return 0
2837}
2838
2839// hasImplicitTypeParams reports whether obj is a defined type with
2840// implicit type parameters (e.g., declared within a generic function
2841// or method).
2842func (pw *pkgWriter) hasImplicitTypeParams(obj *types2.TypeName) bool {
2843	if obj.Pkg() == pw.curpkg {
2844		decl, ok := pw.typDecls[obj]
2845		assert(ok)
2846		if len(decl.implicits) != 0 {
2847			return true
2848		}
2849	}
2850	return false
2851}
2852
2853// isDefinedType reports whether obj is a defined type.
2854func isDefinedType(obj types2.Object) bool {
2855	if obj, ok := obj.(*types2.TypeName); ok {
2856		return !obj.IsAlias()
2857	}
2858	return false
2859}
2860
2861// isGlobal reports whether obj was declared at package scope.
2862//
2863// Caveat: blank objects are not declared.
2864func isGlobal(obj types2.Object) bool {
2865	return obj.Parent() == obj.Pkg().Scope()
2866}
2867
2868// lookupObj returns the object that expr refers to, if any. If expr
2869// is an explicit instantiation of a generic object, then the instance
2870// object is returned as well.
2871func lookupObj(p *pkgWriter, expr syntax.Expr) (obj types2.Object, inst types2.Instance) {
2872	if index, ok := expr.(*syntax.IndexExpr); ok {
2873		args := syntax.UnpackListExpr(index.Index)
2874		if len(args) == 1 {
2875			tv := p.typeAndValue(args[0])
2876			if tv.IsValue() {
2877				return // normal index expression
2878			}
2879		}
2880
2881		expr = index.X
2882	}
2883
2884	// Strip package qualifier, if present.
2885	if sel, ok := expr.(*syntax.SelectorExpr); ok {
2886		if !isPkgQual(p.info, sel) {
2887			return // normal selector expression
2888		}
2889		expr = sel.Sel
2890	}
2891
2892	if name, ok := expr.(*syntax.Name); ok {
2893		obj = p.info.Uses[name]
2894		inst = p.info.Instances[name]
2895	}
2896	return
2897}
2898
2899// isPkgQual reports whether the given selector expression is a
2900// package-qualified identifier.
2901func isPkgQual(info *types2.Info, sel *syntax.SelectorExpr) bool {
2902	if name, ok := sel.X.(*syntax.Name); ok {
2903		_, isPkgName := info.Uses[name].(*types2.PkgName)
2904		return isPkgName
2905	}
2906	return false
2907}
2908
2909// isNil reports whether expr is a (possibly parenthesized) reference
2910// to the predeclared nil value.
2911func isNil(p *pkgWriter, expr syntax.Expr) bool {
2912	tv := p.typeAndValue(expr)
2913	return tv.IsNil()
2914}
2915
2916// isBuiltin reports whether expr is a (possibly parenthesized)
2917// referenced to the specified built-in function.
2918func (pw *pkgWriter) isBuiltin(expr syntax.Expr, builtin string) bool {
2919	if name, ok := syntax.Unparen(expr).(*syntax.Name); ok && name.Value == builtin {
2920		return pw.typeAndValue(name).IsBuiltin()
2921	}
2922	return false
2923}
2924
2925// recvBase returns the base type for the given receiver parameter.
2926func recvBase(recv *types2.Var) *types2.Named {
2927	typ := types2.Unalias(recv.Type())
2928	if ptr, ok := typ.(*types2.Pointer); ok {
2929		typ = types2.Unalias(ptr.Elem())
2930	}
2931	return typ.(*types2.Named)
2932}
2933
2934// namesAsExpr returns a list of names as a syntax.Expr.
2935func namesAsExpr(names []*syntax.Name) syntax.Expr {
2936	if len(names) == 1 {
2937		return names[0]
2938	}
2939
2940	exprs := make([]syntax.Expr, len(names))
2941	for i, name := range names {
2942		exprs[i] = name
2943	}
2944	return &syntax.ListExpr{ElemList: exprs}
2945}
2946
2947// fieldIndex returns the index of the struct field named by key.
2948func fieldIndex(info *types2.Info, str *types2.Struct, key *syntax.Name) int {
2949	field := info.Uses[key].(*types2.Var)
2950
2951	for i := 0; i < str.NumFields(); i++ {
2952		if str.Field(i) == field {
2953			return i
2954		}
2955	}
2956
2957	panic(fmt.Sprintf("%s: %v is not a field of %v", key.Pos(), field, str))
2958}
2959
2960// objTypeParams returns the type parameters on the given object.
2961func objTypeParams(obj types2.Object) *types2.TypeParamList {
2962	switch obj := obj.(type) {
2963	case *types2.Func:
2964		sig := obj.Type().(*types2.Signature)
2965		if sig.Recv() != nil {
2966			return sig.RecvTypeParams()
2967		}
2968		return sig.TypeParams()
2969	case *types2.TypeName:
2970		if !obj.IsAlias() {
2971			return obj.Type().(*types2.Named).TypeParams()
2972		}
2973		if alias, ok := obj.Type().(*types2.Alias); ok {
2974			return alias.TypeParams()
2975		}
2976	}
2977	return nil
2978}
2979
2980// splitNamed decomposes a use of a defined type into its original
2981// type definition and the type arguments used to instantiate it.
2982func splitNamed(typ *types2.Named) (*types2.TypeName, *types2.TypeList) {
2983	base.Assertf(typ.TypeParams().Len() == typ.TypeArgs().Len(), "use of uninstantiated type: %v", typ)
2984
2985	orig := typ.Origin()
2986	base.Assertf(orig.TypeArgs() == nil, "origin %v of %v has type arguments", orig, typ)
2987	base.Assertf(typ.Obj() == orig.Obj(), "%v has object %v, but %v has object %v", typ, typ.Obj(), orig, orig.Obj())
2988
2989	return typ.Obj(), typ.TypeArgs()
2990}
2991
2992// splitAlias is like splitNamed, but for an alias type.
2993func splitAlias(typ *types2.Alias) (*types2.TypeName, *types2.TypeList) {
2994	orig := typ.Origin()
2995	base.Assertf(typ.Obj() == orig.Obj(), "alias type %v has object %v, but %v has object %v", typ, typ.Obj(), orig, orig.Obj())
2996
2997	return typ.Obj(), typ.TypeArgs()
2998}
2999
3000func asPragmaFlag(p syntax.Pragma) ir.PragmaFlag {
3001	if p == nil {
3002		return 0
3003	}
3004	return p.(*pragmas).Flag
3005}
3006
3007func asWasmImport(p syntax.Pragma) *WasmImport {
3008	if p == nil {
3009		return nil
3010	}
3011	return p.(*pragmas).WasmImport
3012}
3013
3014// isPtrTo reports whether from is the type *to.
3015func isPtrTo(from, to types2.Type) bool {
3016	ptr, ok := types2.Unalias(from).(*types2.Pointer)
3017	return ok && types2.Identical(ptr.Elem(), to)
3018}
3019
3020// hasFallthrough reports whether stmts ends in a fallthrough
3021// statement.
3022func hasFallthrough(stmts []syntax.Stmt) bool {
3023	last, ok := lastNonEmptyStmt(stmts).(*syntax.BranchStmt)
3024	return ok && last.Tok == syntax.Fallthrough
3025}
3026
3027// lastNonEmptyStmt returns the last non-empty statement in list, if
3028// any.
3029func lastNonEmptyStmt(stmts []syntax.Stmt) syntax.Stmt {
3030	for i := len(stmts) - 1; i >= 0; i-- {
3031		stmt := stmts[i]
3032		if _, ok := stmt.(*syntax.EmptyStmt); !ok {
3033			return stmt
3034		}
3035	}
3036	return nil
3037}
3038
3039// terminates reports whether stmt terminates normal control flow
3040// (i.e., does not merely advance to the following statement).
3041func (pw *pkgWriter) terminates(stmt syntax.Stmt) bool {
3042	switch stmt := stmt.(type) {
3043	case *syntax.BranchStmt:
3044		if stmt.Tok == syntax.Goto {
3045			return true
3046		}
3047	case *syntax.ReturnStmt:
3048		return true
3049	case *syntax.ExprStmt:
3050		if call, ok := syntax.Unparen(stmt.X).(*syntax.CallExpr); ok {
3051			if pw.isBuiltin(call.Fun, "panic") {
3052				return true
3053			}
3054		}
3055
3056		// The handling of BlockStmt here is approximate, but it serves to
3057		// allow dead-code elimination for:
3058		//
3059		//	if true {
3060		//		return x
3061		//	}
3062		//	unreachable
3063	case *syntax.IfStmt:
3064		cond := pw.staticBool(&stmt.Cond)
3065		return (cond < 0 || pw.terminates(stmt.Then)) && (cond > 0 || pw.terminates(stmt.Else))
3066	case *syntax.BlockStmt:
3067		return pw.terminates(lastNonEmptyStmt(stmt.List))
3068	}
3069
3070	return false
3071}
3072