1// UNREVIEWED
2
3// Copyright 2021 The Go Authors. All rights reserved.
4// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file.
6
7package noder
8
9import (
10	"fmt"
11	"go/constant"
12
13	"cmd/compile/internal/base"
14	"cmd/compile/internal/ir"
15	"cmd/compile/internal/syntax"
16	"cmd/compile/internal/types2"
17)
18
19type pkgWriter struct {
20	pkgEncoder
21
22	m      posMap
23	curpkg *types2.Package
24	info   *types2.Info
25
26	posBasesIdx map[*syntax.PosBase]int
27	pkgsIdx     map[*types2.Package]int
28	typsIdx     map[types2.Type]int
29	globalsIdx  map[types2.Object]int
30
31	funDecls map[*types2.Func]*syntax.FuncDecl
32	typDecls map[*types2.TypeName]typeDeclGen
33
34	linknames  map[types2.Object]string
35	cgoPragmas [][]string
36
37	dups dupTypes
38}
39
40func newPkgWriter(m posMap, pkg *types2.Package, info *types2.Info) *pkgWriter {
41	return &pkgWriter{
42		pkgEncoder: newPkgEncoder(),
43
44		m:      m,
45		curpkg: pkg,
46		info:   info,
47
48		pkgsIdx:    make(map[*types2.Package]int),
49		globalsIdx: make(map[types2.Object]int),
50		typsIdx:    make(map[types2.Type]int),
51
52		posBasesIdx: make(map[*syntax.PosBase]int),
53
54		funDecls: make(map[*types2.Func]*syntax.FuncDecl),
55		typDecls: make(map[*types2.TypeName]typeDeclGen),
56
57		linknames: make(map[types2.Object]string),
58	}
59}
60
61func (pw *pkgWriter) errorf(p poser, msg string, args ...interface{}) {
62	base.ErrorfAt(pw.m.pos(p), msg, args...)
63}
64
65func (pw *pkgWriter) fatalf(p poser, msg string, args ...interface{}) {
66	base.FatalfAt(pw.m.pos(p), msg, args...)
67}
68
69func (pw *pkgWriter) unexpected(what string, p poser) {
70	pw.fatalf(p, "unexpected %s: %v (%T)", what, p, p)
71}
72
73type writer struct {
74	p *pkgWriter
75
76	encoder
77
78	// TODO(mdempsky): We should be able to prune localsIdx whenever a
79	// scope closes, and then maybe we can just use the same map for
80	// storing the TypeParams too (as their TypeName instead).
81
82	// variables declared within this function
83	localsIdx map[*types2.Var]int
84
85	closureVars    []posObj
86	closureVarsIdx map[*types2.Var]int
87
88	dict    *writerDict
89	derived bool
90}
91
92// A writerDict tracks types and objects that are used by a declaration.
93type writerDict struct {
94	implicits []*types2.TypeName
95
96	// derived is a slice of type indices for computing derived types
97	// (i.e., types that depend on the declaration's type parameters).
98	derived []derivedInfo
99
100	// derivedIdx maps a Type to its corresponding index within the
101	// derived slice, if present.
102	derivedIdx map[types2.Type]int
103
104	// funcs lists references to generic functions that were
105	// instantiated with derived types (i.e., that require
106	// sub-dictionaries when called at run time).
107	funcs []objInfo
108}
109
110type derivedInfo struct {
111	idx    int
112	needed bool
113}
114
115type typeInfo struct {
116	idx     int
117	derived bool
118}
119
120type objInfo struct {
121	idx       int        // index for the generic function declaration
122	explicits []typeInfo // info for the type arguments
123}
124
125func (info objInfo) anyDerived() bool {
126	for _, explicit := range info.explicits {
127		if explicit.derived {
128			return true
129		}
130	}
131	return false
132}
133
134func (info objInfo) equals(other objInfo) bool {
135	if info.idx != other.idx {
136		return false
137	}
138	assert(len(info.explicits) == len(other.explicits))
139	for i, targ := range info.explicits {
140		if targ != other.explicits[i] {
141			return false
142		}
143	}
144	return true
145}
146
147func (pw *pkgWriter) newWriter(k reloc, marker syncMarker) *writer {
148	return &writer{
149		encoder: pw.newEncoder(k, marker),
150		p:       pw,
151	}
152}
153
154// @@@ Positions
155
156func (w *writer) pos(p poser) {
157	w.sync(syncPos)
158	pos := p.Pos()
159
160	// TODO(mdempsky): Track down the remaining cases here and fix them.
161	if !w.bool(pos.IsKnown()) {
162		return
163	}
164
165	// TODO(mdempsky): Delta encoding. Also, if there's a b-side, update
166	// its position base too (but not vice versa!).
167	w.posBase(pos.Base())
168	w.uint(pos.Line())
169	w.uint(pos.Col())
170}
171
172func (w *writer) posBase(b *syntax.PosBase) {
173	w.reloc(relocPosBase, w.p.posBaseIdx(b))
174}
175
176func (pw *pkgWriter) posBaseIdx(b *syntax.PosBase) int {
177	if idx, ok := pw.posBasesIdx[b]; ok {
178		return idx
179	}
180
181	w := pw.newWriter(relocPosBase, syncPosBase)
182	w.p.posBasesIdx[b] = w.idx
183
184	w.string(trimFilename(b))
185
186	if !w.bool(b.IsFileBase()) {
187		w.pos(b)
188		w.uint(b.Line())
189		w.uint(b.Col())
190	}
191
192	return w.flush()
193}
194
195// @@@ Packages
196
197func (w *writer) pkg(pkg *types2.Package) {
198	w.sync(syncPkg)
199	w.reloc(relocPkg, w.p.pkgIdx(pkg))
200}
201
202func (pw *pkgWriter) pkgIdx(pkg *types2.Package) int {
203	if idx, ok := pw.pkgsIdx[pkg]; ok {
204		return idx
205	}
206
207	w := pw.newWriter(relocPkg, syncPkgDef)
208	pw.pkgsIdx[pkg] = w.idx
209
210	if pkg == nil {
211		w.string("builtin")
212	} else {
213		var path string
214		if pkg != w.p.curpkg {
215			path = pkg.Path()
216		}
217		w.string(path)
218		w.string(pkg.Name())
219		w.len(pkg.Height())
220
221		w.len(len(pkg.Imports()))
222		for _, imp := range pkg.Imports() {
223			w.pkg(imp)
224		}
225	}
226
227	return w.flush()
228}
229
230// @@@ Types
231
232var anyTypeName = types2.Universe.Lookup("any").(*types2.TypeName)
233
234func (w *writer) typ(typ types2.Type) {
235	w.typInfo(w.p.typIdx(typ, w.dict))
236}
237
238func (w *writer) typInfo(info typeInfo) {
239	w.sync(syncType)
240	if w.bool(info.derived) {
241		w.len(info.idx)
242		w.derived = true
243	} else {
244		w.reloc(relocType, info.idx)
245	}
246}
247
248// typIdx returns the index where the export data description of type
249// can be read back in. If no such index exists yet, it's created.
250//
251// typIdx also reports whether typ is a derived type; that is, whether
252// its identity depends on type parameters.
253func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo {
254	if quirksMode() {
255		typ = pw.dups.orig(typ)
256	}
257
258	if idx, ok := pw.typsIdx[typ]; ok {
259		return typeInfo{idx: idx, derived: false}
260	}
261	if dict != nil {
262		if idx, ok := dict.derivedIdx[typ]; ok {
263			return typeInfo{idx: idx, derived: true}
264		}
265	}
266
267	w := pw.newWriter(relocType, syncTypeIdx)
268	w.dict = dict
269
270	switch typ := typ.(type) {
271	default:
272		base.Fatalf("unexpected type: %v (%T)", typ, typ)
273
274	case *types2.Basic:
275		switch kind := typ.Kind(); {
276		case kind == types2.Invalid:
277			base.Fatalf("unexpected types2.Invalid")
278
279		case types2.Typ[kind] == typ:
280			w.code(typeBasic)
281			w.len(int(kind))
282
283		default:
284			// Handle "byte" and "rune" as references to their TypeName.
285			obj := types2.Universe.Lookup(typ.Name())
286			assert(obj.Type() == typ)
287
288			w.code(typeNamed)
289			w.obj(obj, nil)
290		}
291
292	case *types2.Named:
293		// Type aliases can refer to uninstantiated generic types, so we
294		// might see len(TParams) != 0 && len(TArgs) == 0 here.
295		// TODO(mdempsky): Revisit after #46477 is resolved.
296		assert(typ.TypeParams().Len() == typ.TypeArgs().Len() || typ.TypeArgs().Len() == 0)
297
298		// TODO(mdempsky): Why do we need to loop here?
299		orig := typ
300		for orig.TypeArgs() != nil {
301			orig = orig.Origin()
302		}
303
304		w.code(typeNamed)
305		w.obj(orig.Obj(), typ.TypeArgs())
306
307	case *types2.TypeParam:
308		index := func() int {
309			for idx, name := range w.dict.implicits {
310				if name.Type().(*types2.TypeParam) == typ {
311					return idx
312				}
313			}
314
315			return len(w.dict.implicits) + typ.Index()
316		}()
317
318		w.derived = true
319		w.code(typeTypeParam)
320		w.len(index)
321
322	case *types2.Array:
323		w.code(typeArray)
324		w.uint64(uint64(typ.Len()))
325		w.typ(typ.Elem())
326
327	case *types2.Chan:
328		w.code(typeChan)
329		w.len(int(typ.Dir()))
330		w.typ(typ.Elem())
331
332	case *types2.Map:
333		w.code(typeMap)
334		w.typ(typ.Key())
335		w.typ(typ.Elem())
336
337	case *types2.Pointer:
338		w.code(typePointer)
339		w.typ(typ.Elem())
340
341	case *types2.Signature:
342		base.Assertf(typ.TypeParams() == nil, "unexpected type params: %v", typ)
343		w.code(typeSignature)
344		w.signature(typ)
345
346	case *types2.Slice:
347		w.code(typeSlice)
348		w.typ(typ.Elem())
349
350	case *types2.Struct:
351		w.code(typeStruct)
352		w.structType(typ)
353
354	case *types2.Interface:
355		if typ == anyTypeName.Type() {
356			w.code(typeNamed)
357			w.obj(anyTypeName, nil)
358			break
359		}
360
361		w.code(typeInterface)
362		w.interfaceType(typ)
363
364	case *types2.Union:
365		w.code(typeUnion)
366		w.unionType(typ)
367	}
368
369	if w.derived {
370		idx := len(dict.derived)
371		dict.derived = append(dict.derived, derivedInfo{idx: w.flush()})
372		dict.derivedIdx[typ] = idx
373		return typeInfo{idx: idx, derived: true}
374	}
375
376	pw.typsIdx[typ] = w.idx
377	return typeInfo{idx: w.flush(), derived: false}
378}
379
380func (w *writer) structType(typ *types2.Struct) {
381	w.len(typ.NumFields())
382	for i := 0; i < typ.NumFields(); i++ {
383		f := typ.Field(i)
384		w.pos(f)
385		w.selector(f)
386		w.typ(f.Type())
387		w.string(typ.Tag(i))
388		w.bool(f.Embedded())
389	}
390}
391
392func (w *writer) unionType(typ *types2.Union) {
393	w.len(typ.Len())
394	for i := 0; i < typ.Len(); i++ {
395		t := typ.Term(i)
396		w.bool(t.Tilde())
397		w.typ(t.Type())
398	}
399}
400
401func (w *writer) interfaceType(typ *types2.Interface) {
402	w.len(typ.NumExplicitMethods())
403	w.len(typ.NumEmbeddeds())
404
405	for i := 0; i < typ.NumExplicitMethods(); i++ {
406		m := typ.ExplicitMethod(i)
407		sig := m.Type().(*types2.Signature)
408		assert(sig.TypeParams() == nil)
409
410		w.pos(m)
411		w.selector(m)
412		w.signature(sig)
413	}
414
415	for i := 0; i < typ.NumEmbeddeds(); i++ {
416		w.typ(typ.EmbeddedType(i))
417	}
418}
419
420func (w *writer) signature(sig *types2.Signature) {
421	w.sync(syncSignature)
422	w.params(sig.Params())
423	w.params(sig.Results())
424	w.bool(sig.Variadic())
425}
426
427func (w *writer) params(typ *types2.Tuple) {
428	w.sync(syncParams)
429	w.len(typ.Len())
430	for i := 0; i < typ.Len(); i++ {
431		w.param(typ.At(i))
432	}
433}
434
435func (w *writer) param(param *types2.Var) {
436	w.sync(syncParam)
437	w.pos(param)
438	w.localIdent(param)
439	w.typ(param.Type())
440}
441
442// @@@ Objects
443
444func (w *writer) obj(obj types2.Object, explicits *types2.TypeList) {
445	explicitInfos := make([]typeInfo, explicits.Len())
446	for i := range explicitInfos {
447		explicitInfos[i] = w.p.typIdx(explicits.At(i), w.dict)
448	}
449	info := objInfo{idx: w.p.objIdx(obj), explicits: explicitInfos}
450
451	if _, ok := obj.(*types2.Func); ok && info.anyDerived() {
452		idx := -1
453		for i, prev := range w.dict.funcs {
454			if prev.equals(info) {
455				idx = i
456			}
457		}
458		if idx < 0 {
459			idx = len(w.dict.funcs)
460			w.dict.funcs = append(w.dict.funcs, info)
461		}
462
463		// TODO(mdempsky): Push up into expr; this shouldn't appear
464		// outside of expression context.
465		w.sync(syncObject)
466		w.bool(true)
467		w.len(idx)
468		return
469	}
470
471	// TODO(mdempsky): Push up into typIdx; this shouldn't be needed
472	// except while writing out types.
473	if isDefinedType(obj) && obj.Pkg() == w.p.curpkg {
474		decl, ok := w.p.typDecls[obj.(*types2.TypeName)]
475		assert(ok)
476		if len(decl.implicits) != 0 {
477			w.derived = true
478		}
479	}
480
481	w.sync(syncObject)
482	w.bool(false)
483	w.reloc(relocObj, info.idx)
484
485	w.len(len(info.explicits))
486	for _, info := range info.explicits {
487		w.typInfo(info)
488	}
489}
490
491func (pw *pkgWriter) objIdx(obj types2.Object) int {
492	if idx, ok := pw.globalsIdx[obj]; ok {
493		return idx
494	}
495
496	dict := &writerDict{
497		derivedIdx: make(map[types2.Type]int),
498	}
499
500	if isDefinedType(obj) && obj.Pkg() == pw.curpkg {
501		decl, ok := pw.typDecls[obj.(*types2.TypeName)]
502		assert(ok)
503		dict.implicits = decl.implicits
504	}
505
506	w := pw.newWriter(relocObj, syncObject1)
507	wext := pw.newWriter(relocObjExt, syncObject1)
508	wname := pw.newWriter(relocName, syncObject1)
509	wdict := pw.newWriter(relocObjDict, syncObject1)
510
511	pw.globalsIdx[obj] = w.idx // break cycles
512	assert(wext.idx == w.idx)
513	assert(wname.idx == w.idx)
514	assert(wdict.idx == w.idx)
515
516	w.dict = dict
517	wext.dict = dict
518
519	code := w.doObj(wext, obj)
520	w.flush()
521	wext.flush()
522
523	wname.qualifiedIdent(obj)
524	wname.code(code)
525	wname.flush()
526
527	wdict.objDict(obj, w.dict)
528	wdict.flush()
529
530	return w.idx
531}
532
533func (w *writer) doObj(wext *writer, obj types2.Object) codeObj {
534	if obj.Pkg() != w.p.curpkg {
535		return objStub
536	}
537
538	switch obj := obj.(type) {
539	default:
540		w.p.unexpected("object", obj)
541		panic("unreachable")
542
543	case *types2.Const:
544		w.pos(obj)
545		w.typ(obj.Type())
546		w.value(obj.Val())
547		return objConst
548
549	case *types2.Func:
550		decl, ok := w.p.funDecls[obj]
551		assert(ok)
552		sig := obj.Type().(*types2.Signature)
553
554		w.pos(obj)
555		w.typeParamNames(sig.TypeParams())
556		w.signature(sig)
557		w.pos(decl)
558		wext.funcExt(obj)
559		return objFunc
560
561	case *types2.TypeName:
562		decl, ok := w.p.typDecls[obj]
563		assert(ok)
564
565		if obj.IsAlias() {
566			w.pos(obj)
567			w.typ(obj.Type())
568			return objAlias
569		}
570
571		named := obj.Type().(*types2.Named)
572		assert(named.TypeArgs() == nil)
573
574		w.pos(obj)
575		w.typeParamNames(named.TypeParams())
576		wext.typeExt(obj)
577		w.typExpr(decl.Type)
578
579		w.len(named.NumMethods())
580		for i := 0; i < named.NumMethods(); i++ {
581			w.method(wext, named.Method(i))
582		}
583
584		return objType
585
586	case *types2.Var:
587		w.pos(obj)
588		w.typ(obj.Type())
589		wext.varExt(obj)
590		return objVar
591	}
592}
593
594// typExpr writes the type represented by the given expression.
595func (w *writer) typExpr(expr syntax.Expr) {
596	tv, ok := w.p.info.Types[expr]
597	assert(ok)
598	assert(tv.IsType())
599	w.typ(tv.Type)
600}
601
602// objDict writes the dictionary needed for reading the given object.
603func (w *writer) objDict(obj types2.Object, dict *writerDict) {
604	// TODO(mdempsky): Split objDict into multiple entries? reader.go
605	// doesn't care about the type parameter bounds, and reader2.go
606	// doesn't care about referenced functions.
607
608	w.dict = dict // TODO(mdempsky): This is a bit sketchy.
609
610	w.len(len(dict.implicits))
611
612	tparams := objTypeParams(obj)
613	ntparams := tparams.Len()
614	w.len(ntparams)
615	for i := 0; i < ntparams; i++ {
616		w.typ(tparams.At(i).Constraint())
617	}
618
619	nderived := len(dict.derived)
620	w.len(nderived)
621	for _, typ := range dict.derived {
622		w.reloc(relocType, typ.idx)
623		w.bool(typ.needed)
624	}
625
626	nfuncs := len(dict.funcs)
627	w.len(nfuncs)
628	for _, fn := range dict.funcs {
629		w.reloc(relocObj, fn.idx)
630		w.len(len(fn.explicits))
631		for _, targ := range fn.explicits {
632			w.typInfo(targ)
633		}
634	}
635
636	assert(len(dict.derived) == nderived)
637	assert(len(dict.funcs) == nfuncs)
638}
639
640func (w *writer) typeParamNames(tparams *types2.TypeParamList) {
641	w.sync(syncTypeParamNames)
642
643	ntparams := tparams.Len()
644	for i := 0; i < ntparams; i++ {
645		tparam := tparams.At(i).Obj()
646		w.pos(tparam)
647		w.localIdent(tparam)
648	}
649}
650
651func (w *writer) method(wext *writer, meth *types2.Func) {
652	decl, ok := w.p.funDecls[meth]
653	assert(ok)
654	sig := meth.Type().(*types2.Signature)
655
656	w.sync(syncMethod)
657	w.pos(meth)
658	w.selector(meth)
659	w.typeParamNames(sig.RecvTypeParams())
660	w.param(sig.Recv())
661	w.signature(sig)
662
663	w.pos(decl) // XXX: Hack to workaround linker limitations.
664	wext.funcExt(meth)
665}
666
667// qualifiedIdent writes out the name of an object declared at package
668// scope. (For now, it's also used to refer to local defined types.)
669func (w *writer) qualifiedIdent(obj types2.Object) {
670	w.sync(syncSym)
671
672	name := obj.Name()
673	if isDefinedType(obj) && obj.Pkg() == w.p.curpkg {
674		decl, ok := w.p.typDecls[obj.(*types2.TypeName)]
675		assert(ok)
676		if decl.gen != 0 {
677			// TODO(mdempsky): Find a better solution than embedding middle
678			// dot in the symbol name; this is terrible.
679			name = fmt.Sprintf("%s·%v", name, decl.gen)
680		}
681	}
682
683	w.pkg(obj.Pkg())
684	w.string(name)
685}
686
687// TODO(mdempsky): We should be able to omit pkg from both localIdent
688// and selector, because they should always be known from context.
689// However, past frustrations with this optimization in iexport make
690// me a little nervous to try it again.
691
692// localIdent writes the name of a locally declared object (i.e.,
693// objects that can only be accessed by name, within the context of a
694// particular function).
695func (w *writer) localIdent(obj types2.Object) {
696	assert(!isGlobal(obj))
697	w.sync(syncLocalIdent)
698	w.pkg(obj.Pkg())
699	w.string(obj.Name())
700}
701
702// selector writes the name of a field or method (i.e., objects that
703// can only be accessed using selector expressions).
704func (w *writer) selector(obj types2.Object) {
705	w.sync(syncSelector)
706	w.pkg(obj.Pkg())
707	w.string(obj.Name())
708}
709
710// @@@ Compiler extensions
711
712func (w *writer) funcExt(obj *types2.Func) {
713	decl, ok := w.p.funDecls[obj]
714	assert(ok)
715
716	// TODO(mdempsky): Extend these pragma validation flags to account
717	// for generics. E.g., linkname probably doesn't make sense at
718	// least.
719
720	pragma := asPragmaFlag(decl.Pragma)
721	if pragma&ir.Systemstack != 0 && pragma&ir.Nosplit != 0 {
722		w.p.errorf(decl, "go:nosplit and go:systemstack cannot be combined")
723	}
724
725	if decl.Body != nil {
726		if pragma&ir.Noescape != 0 {
727			w.p.errorf(decl, "can only use //go:noescape with external func implementations")
728		}
729	} else {
730		if base.Flag.Complete || decl.Name.Value == "init" {
731			// Linknamed functions are allowed to have no body. Hopefully
732			// the linkname target has a body. See issue 23311.
733			if _, ok := w.p.linknames[obj]; !ok {
734				w.p.errorf(decl, "missing function body")
735			}
736		}
737	}
738
739	sig, block := obj.Type().(*types2.Signature), decl.Body
740	body, closureVars := w.p.bodyIdx(w.p.curpkg, sig, block, w.dict)
741	assert(len(closureVars) == 0)
742
743	w.sync(syncFuncExt)
744	w.pragmaFlag(pragma)
745	w.linkname(obj)
746	w.bool(false) // stub extension
747	w.reloc(relocBody, body)
748	w.sync(syncEOF)
749}
750
751func (w *writer) typeExt(obj *types2.TypeName) {
752	decl, ok := w.p.typDecls[obj]
753	assert(ok)
754
755	w.sync(syncTypeExt)
756
757	w.pragmaFlag(asPragmaFlag(decl.Pragma))
758
759	// No LSym.SymIdx info yet.
760	w.int64(-1)
761	w.int64(-1)
762}
763
764func (w *writer) varExt(obj *types2.Var) {
765	w.sync(syncVarExt)
766	w.linkname(obj)
767}
768
769func (w *writer) linkname(obj types2.Object) {
770	w.sync(syncLinkname)
771	w.int64(-1)
772	w.string(w.p.linknames[obj])
773}
774
775func (w *writer) pragmaFlag(p ir.PragmaFlag) {
776	w.sync(syncPragma)
777	w.int(int(p))
778}
779
780// @@@ Function bodies
781
782func (pw *pkgWriter) bodyIdx(pkg *types2.Package, sig *types2.Signature, block *syntax.BlockStmt, dict *writerDict) (idx int, closureVars []posObj) {
783	w := pw.newWriter(relocBody, syncFuncBody)
784	w.dict = dict
785
786	w.funcargs(sig)
787	if w.bool(block != nil) {
788		w.stmts(block.List)
789		w.pos(block.Rbrace)
790	}
791
792	return w.flush(), w.closureVars
793}
794
795func (w *writer) funcargs(sig *types2.Signature) {
796	do := func(params *types2.Tuple, result bool) {
797		for i := 0; i < params.Len(); i++ {
798			w.funcarg(params.At(i), result)
799		}
800	}
801
802	if recv := sig.Recv(); recv != nil {
803		w.funcarg(recv, false)
804	}
805	do(sig.Params(), false)
806	do(sig.Results(), true)
807}
808
809func (w *writer) funcarg(param *types2.Var, result bool) {
810	if param.Name() != "" || result {
811		w.addLocal(param)
812	}
813}
814
815func (w *writer) addLocal(obj *types2.Var) {
816	w.sync(syncAddLocal)
817	idx := len(w.localsIdx)
818	if enableSync {
819		w.int(idx)
820	}
821	if w.localsIdx == nil {
822		w.localsIdx = make(map[*types2.Var]int)
823	}
824	w.localsIdx[obj] = idx
825}
826
827func (w *writer) useLocal(pos syntax.Pos, obj *types2.Var) {
828	w.sync(syncUseObjLocal)
829
830	if idx, ok := w.localsIdx[obj]; w.bool(ok) {
831		w.len(idx)
832		return
833	}
834
835	idx, ok := w.closureVarsIdx[obj]
836	if !ok {
837		if w.closureVarsIdx == nil {
838			w.closureVarsIdx = make(map[*types2.Var]int)
839		}
840		idx = len(w.closureVars)
841		w.closureVars = append(w.closureVars, posObj{pos, obj})
842		w.closureVarsIdx[obj] = idx
843	}
844	w.len(idx)
845}
846
847func (w *writer) openScope(pos syntax.Pos) {
848	w.sync(syncOpenScope)
849	w.pos(pos)
850}
851
852func (w *writer) closeScope(pos syntax.Pos) {
853	w.sync(syncCloseScope)
854	w.pos(pos)
855	w.closeAnotherScope()
856}
857
858func (w *writer) closeAnotherScope() {
859	w.sync(syncCloseAnotherScope)
860}
861
862// @@@ Statements
863
864func (w *writer) stmt(stmt syntax.Stmt) {
865	var stmts []syntax.Stmt
866	if stmt != nil {
867		stmts = []syntax.Stmt{stmt}
868	}
869	w.stmts(stmts)
870}
871
872func (w *writer) stmts(stmts []syntax.Stmt) {
873	w.sync(syncStmts)
874	for _, stmt := range stmts {
875		w.stmt1(stmt)
876	}
877	w.code(stmtEnd)
878	w.sync(syncStmtsEnd)
879}
880
881func (w *writer) stmt1(stmt syntax.Stmt) {
882	switch stmt := stmt.(type) {
883	default:
884		w.p.unexpected("statement", stmt)
885
886	case nil, *syntax.EmptyStmt:
887		return
888
889	case *syntax.AssignStmt:
890		switch {
891		case stmt.Rhs == nil:
892			w.code(stmtIncDec)
893			w.op(binOps[stmt.Op])
894			w.expr(stmt.Lhs)
895			w.pos(stmt)
896
897		case stmt.Op != 0 && stmt.Op != syntax.Def:
898			w.code(stmtAssignOp)
899			w.op(binOps[stmt.Op])
900			w.expr(stmt.Lhs)
901			w.pos(stmt)
902			w.expr(stmt.Rhs)
903
904		default:
905			w.code(stmtAssign)
906			w.pos(stmt)
907			w.exprList(stmt.Rhs)
908			w.assignList(stmt.Lhs)
909		}
910
911	case *syntax.BlockStmt:
912		w.code(stmtBlock)
913		w.blockStmt(stmt)
914
915	case *syntax.BranchStmt:
916		w.code(stmtBranch)
917		w.pos(stmt)
918		w.op(branchOps[stmt.Tok])
919		w.optLabel(stmt.Label)
920
921	case *syntax.CallStmt:
922		w.code(stmtCall)
923		w.pos(stmt)
924		w.op(callOps[stmt.Tok])
925		w.expr(stmt.Call)
926
927	case *syntax.DeclStmt:
928		for _, decl := range stmt.DeclList {
929			w.declStmt(decl)
930		}
931
932	case *syntax.ExprStmt:
933		w.code(stmtExpr)
934		w.expr(stmt.X)
935
936	case *syntax.ForStmt:
937		w.code(stmtFor)
938		w.forStmt(stmt)
939
940	case *syntax.IfStmt:
941		w.code(stmtIf)
942		w.ifStmt(stmt)
943
944	case *syntax.LabeledStmt:
945		w.code(stmtLabel)
946		w.pos(stmt)
947		w.label(stmt.Label)
948		w.stmt1(stmt.Stmt)
949
950	case *syntax.ReturnStmt:
951		w.code(stmtReturn)
952		w.pos(stmt)
953		w.exprList(stmt.Results)
954
955	case *syntax.SelectStmt:
956		w.code(stmtSelect)
957		w.selectStmt(stmt)
958
959	case *syntax.SendStmt:
960		w.code(stmtSend)
961		w.pos(stmt)
962		w.expr(stmt.Chan)
963		w.expr(stmt.Value)
964
965	case *syntax.SwitchStmt:
966		w.code(stmtSwitch)
967		w.switchStmt(stmt)
968	}
969}
970
971func (w *writer) assignList(expr syntax.Expr) {
972	exprs := unpackListExpr(expr)
973	w.len(len(exprs))
974
975	for _, expr := range exprs {
976		if name, ok := expr.(*syntax.Name); ok && name.Value != "_" {
977			if obj, ok := w.p.info.Defs[name]; ok {
978				obj := obj.(*types2.Var)
979
980				w.bool(true)
981				w.pos(obj)
982				w.localIdent(obj)
983				w.typ(obj.Type())
984
985				// TODO(mdempsky): Minimize locals index size by deferring
986				// this until the variables actually come into scope.
987				w.addLocal(obj)
988				continue
989			}
990		}
991
992		w.bool(false)
993		w.expr(expr)
994	}
995}
996
997func (w *writer) declStmt(decl syntax.Decl) {
998	switch decl := decl.(type) {
999	default:
1000		w.p.unexpected("declaration", decl)
1001
1002	case *syntax.ConstDecl:
1003
1004	case *syntax.TypeDecl:
1005		// Quirk: The legacy inliner doesn't support inlining functions
1006		// with type declarations. Unified IR doesn't have any need to
1007		// write out type declarations explicitly (they're always looked
1008		// up via global index tables instead), so we just write out a
1009		// marker so the reader knows to synthesize a fake declaration to
1010		// prevent inlining.
1011		if quirksMode() {
1012			w.code(stmtTypeDeclHack)
1013		}
1014
1015	case *syntax.VarDecl:
1016		values := unpackListExpr(decl.Values)
1017
1018		// Quirk: When N variables are declared with N initialization
1019		// values, we need to decompose that into N interleaved
1020		// declarations+initializations, because it leads to different
1021		// (albeit semantically equivalent) code generation.
1022		if quirksMode() && len(decl.NameList) == len(values) {
1023			for i, name := range decl.NameList {
1024				w.code(stmtAssign)
1025				w.pos(decl)
1026				w.exprList(values[i])
1027				w.assignList(name)
1028			}
1029			break
1030		}
1031
1032		w.code(stmtAssign)
1033		w.pos(decl)
1034		w.exprList(decl.Values)
1035		w.assignList(namesAsExpr(decl.NameList))
1036	}
1037}
1038
1039func (w *writer) blockStmt(stmt *syntax.BlockStmt) {
1040	w.sync(syncBlockStmt)
1041	w.openScope(stmt.Pos())
1042	w.stmts(stmt.List)
1043	w.closeScope(stmt.Rbrace)
1044}
1045
1046func (w *writer) forStmt(stmt *syntax.ForStmt) {
1047	w.sync(syncForStmt)
1048	w.openScope(stmt.Pos())
1049
1050	if rang, ok := stmt.Init.(*syntax.RangeClause); w.bool(ok) {
1051		w.pos(rang)
1052		w.expr(rang.X)
1053		w.assignList(rang.Lhs)
1054	} else {
1055		w.pos(stmt)
1056		w.stmt(stmt.Init)
1057		w.expr(stmt.Cond)
1058		w.stmt(stmt.Post)
1059	}
1060
1061	w.blockStmt(stmt.Body)
1062	w.closeAnotherScope()
1063}
1064
1065func (w *writer) ifStmt(stmt *syntax.IfStmt) {
1066	w.sync(syncIfStmt)
1067	w.openScope(stmt.Pos())
1068	w.pos(stmt)
1069	w.stmt(stmt.Init)
1070	w.expr(stmt.Cond)
1071	w.blockStmt(stmt.Then)
1072	w.stmt(stmt.Else)
1073	w.closeAnotherScope()
1074}
1075
1076func (w *writer) selectStmt(stmt *syntax.SelectStmt) {
1077	w.sync(syncSelectStmt)
1078
1079	w.pos(stmt)
1080	w.len(len(stmt.Body))
1081	for i, clause := range stmt.Body {
1082		if i > 0 {
1083			w.closeScope(clause.Pos())
1084		}
1085		w.openScope(clause.Pos())
1086
1087		w.pos(clause)
1088		w.stmt(clause.Comm)
1089		w.stmts(clause.Body)
1090	}
1091	if len(stmt.Body) > 0 {
1092		w.closeScope(stmt.Rbrace)
1093	}
1094}
1095
1096func (w *writer) switchStmt(stmt *syntax.SwitchStmt) {
1097	w.sync(syncSwitchStmt)
1098
1099	w.openScope(stmt.Pos())
1100	w.pos(stmt)
1101	w.stmt(stmt.Init)
1102
1103	if guard, ok := stmt.Tag.(*syntax.TypeSwitchGuard); w.bool(ok) {
1104		w.pos(guard)
1105		if tag := guard.Lhs; w.bool(tag != nil) {
1106			w.pos(tag)
1107			w.string(tag.Value)
1108		}
1109		w.expr(guard.X)
1110	} else {
1111		w.expr(stmt.Tag)
1112	}
1113
1114	w.len(len(stmt.Body))
1115	for i, clause := range stmt.Body {
1116		if i > 0 {
1117			w.closeScope(clause.Pos())
1118		}
1119		w.openScope(clause.Pos())
1120
1121		w.pos(clause)
1122		w.exprList(clause.Cases)
1123
1124		if obj, ok := w.p.info.Implicits[clause]; ok {
1125			// TODO(mdempsky): These pos details are quirkish, but also
1126			// necessary so the variable's position is correct for DWARF
1127			// scope assignment later. It would probably be better for us to
1128			// instead just set the variable's DWARF scoping info earlier so
1129			// we can give it the correct position information.
1130			pos := clause.Pos()
1131			if typs := unpackListExpr(clause.Cases); len(typs) != 0 {
1132				pos = typeExprEndPos(typs[len(typs)-1])
1133			}
1134			w.pos(pos)
1135
1136			obj := obj.(*types2.Var)
1137			w.typ(obj.Type())
1138			w.addLocal(obj)
1139		}
1140
1141		w.stmts(clause.Body)
1142	}
1143	if len(stmt.Body) > 0 {
1144		w.closeScope(stmt.Rbrace)
1145	}
1146
1147	w.closeScope(stmt.Rbrace)
1148}
1149
1150func (w *writer) label(label *syntax.Name) {
1151	w.sync(syncLabel)
1152
1153	// TODO(mdempsky): Replace label strings with dense indices.
1154	w.string(label.Value)
1155}
1156
1157func (w *writer) optLabel(label *syntax.Name) {
1158	w.sync(syncOptLabel)
1159	if w.bool(label != nil) {
1160		w.label(label)
1161	}
1162}
1163
1164// @@@ Expressions
1165
1166func (w *writer) expr(expr syntax.Expr) {
1167	expr = unparen(expr) // skip parens; unneeded after typecheck
1168
1169	obj, inst := lookupObj(w.p.info, expr)
1170	targs := inst.TypeArgs
1171
1172	if tv, ok := w.p.info.Types[expr]; ok {
1173		// TODO(mdempsky): Be more judicious about which types are marked as "needed".
1174		if inst.Type != nil {
1175			w.needType(inst.Type)
1176		} else {
1177			w.needType(tv.Type)
1178		}
1179
1180		if tv.IsType() {
1181			w.code(exprType)
1182			w.typ(tv.Type)
1183			return
1184		}
1185
1186		if tv.Value != nil {
1187			pos := expr.Pos()
1188			if quirksMode() {
1189				if obj != nil {
1190					// Quirk: IR (and thus iexport) doesn't track position
1191					// information for uses of declared objects.
1192					pos = syntax.Pos{}
1193				} else if tv.Value.Kind() == constant.String {
1194					// Quirk: noder.sum picks a particular position for certain
1195					// string concatenations.
1196					pos = sumPos(expr)
1197				}
1198			}
1199
1200			w.code(exprConst)
1201			w.pos(pos)
1202			w.typ(tv.Type)
1203			w.value(tv.Value)
1204
1205			// TODO(mdempsky): These details are only important for backend
1206			// diagnostics. Explore writing them out separately.
1207			w.op(constExprOp(expr))
1208			w.string(syntax.String(expr))
1209			return
1210		}
1211	}
1212
1213	if obj != nil {
1214		if isGlobal(obj) {
1215			w.code(exprName)
1216			w.obj(obj, targs)
1217			return
1218		}
1219
1220		obj := obj.(*types2.Var)
1221		assert(targs.Len() == 0)
1222
1223		w.code(exprLocal)
1224		w.useLocal(expr.Pos(), obj)
1225		return
1226	}
1227
1228	switch expr := expr.(type) {
1229	default:
1230		w.p.unexpected("expression", expr)
1231
1232	case nil: // absent slice index, for condition, or switch tag
1233		w.code(exprNone)
1234
1235	case *syntax.Name:
1236		assert(expr.Value == "_")
1237		w.code(exprBlank)
1238
1239	case *syntax.CompositeLit:
1240		w.code(exprCompLit)
1241		w.compLit(expr)
1242
1243	case *syntax.FuncLit:
1244		w.code(exprFuncLit)
1245		w.funcLit(expr)
1246
1247	case *syntax.SelectorExpr:
1248		sel, ok := w.p.info.Selections[expr]
1249		assert(ok)
1250
1251		w.code(exprSelector)
1252		w.expr(expr.X)
1253		w.pos(expr)
1254		w.selector(sel.Obj())
1255
1256	case *syntax.IndexExpr:
1257		tv, ok := w.p.info.Types[expr.Index]
1258		assert(ok && tv.IsValue())
1259
1260		w.code(exprIndex)
1261		w.expr(expr.X)
1262		w.pos(expr)
1263		w.expr(expr.Index)
1264
1265	case *syntax.SliceExpr:
1266		w.code(exprSlice)
1267		w.expr(expr.X)
1268		w.pos(expr)
1269		for _, n := range &expr.Index {
1270			w.expr(n)
1271		}
1272
1273	case *syntax.AssertExpr:
1274		w.code(exprAssert)
1275		w.expr(expr.X)
1276		w.pos(expr)
1277		w.expr(expr.Type)
1278
1279	case *syntax.Operation:
1280		if expr.Y == nil {
1281			w.code(exprUnaryOp)
1282			w.op(unOps[expr.Op])
1283			w.pos(expr)
1284			w.expr(expr.X)
1285			break
1286		}
1287
1288		w.code(exprBinaryOp)
1289		w.op(binOps[expr.Op])
1290		w.expr(expr.X)
1291		w.pos(expr)
1292		w.expr(expr.Y)
1293
1294	case *syntax.CallExpr:
1295		tv, ok := w.p.info.Types[expr.Fun]
1296		assert(ok)
1297		if tv.IsType() {
1298			assert(len(expr.ArgList) == 1)
1299			assert(!expr.HasDots)
1300
1301			w.code(exprConvert)
1302			w.typ(tv.Type)
1303			w.pos(expr)
1304			w.expr(expr.ArgList[0])
1305			break
1306		}
1307
1308		writeFunExpr := func() {
1309			if selector, ok := unparen(expr.Fun).(*syntax.SelectorExpr); ok {
1310				if sel, ok := w.p.info.Selections[selector]; ok && sel.Kind() == types2.MethodVal {
1311					w.expr(selector.X)
1312					w.bool(true) // method call
1313					w.pos(selector)
1314					w.selector(sel.Obj())
1315					return
1316				}
1317			}
1318
1319			w.expr(expr.Fun)
1320			w.bool(false) // not a method call (i.e., normal function call)
1321		}
1322
1323		w.code(exprCall)
1324		writeFunExpr()
1325		w.pos(expr)
1326		w.exprs(expr.ArgList)
1327		w.bool(expr.HasDots)
1328	}
1329}
1330
1331func (w *writer) compLit(lit *syntax.CompositeLit) {
1332	tv, ok := w.p.info.Types[lit]
1333	assert(ok)
1334
1335	w.sync(syncCompLit)
1336	w.pos(lit)
1337	w.typ(tv.Type)
1338
1339	typ := tv.Type
1340	if ptr, ok := typ.Underlying().(*types2.Pointer); ok {
1341		typ = ptr.Elem()
1342	}
1343	str, isStruct := typ.Underlying().(*types2.Struct)
1344
1345	w.len(len(lit.ElemList))
1346	for i, elem := range lit.ElemList {
1347		if isStruct {
1348			if kv, ok := elem.(*syntax.KeyValueExpr); ok {
1349				// use position of expr.Key rather than of elem (which has position of ':')
1350				w.pos(kv.Key)
1351				w.len(fieldIndex(w.p.info, str, kv.Key.(*syntax.Name)))
1352				elem = kv.Value
1353			} else {
1354				w.pos(elem)
1355				w.len(i)
1356			}
1357		} else {
1358			if kv, ok := elem.(*syntax.KeyValueExpr); w.bool(ok) {
1359				// use position of expr.Key rather than of elem (which has position of ':')
1360				w.pos(kv.Key)
1361				w.expr(kv.Key)
1362				elem = kv.Value
1363			}
1364		}
1365		w.pos(elem)
1366		w.expr(elem)
1367	}
1368}
1369
1370func (w *writer) funcLit(expr *syntax.FuncLit) {
1371	tv, ok := w.p.info.Types[expr]
1372	assert(ok)
1373	sig := tv.Type.(*types2.Signature)
1374
1375	body, closureVars := w.p.bodyIdx(w.p.curpkg, sig, expr.Body, w.dict)
1376
1377	w.sync(syncFuncLit)
1378	w.pos(expr)
1379	w.pos(expr.Type) // for QuirksMode
1380	w.signature(sig)
1381
1382	w.len(len(closureVars))
1383	for _, cv := range closureVars {
1384		w.pos(cv.pos)
1385		if quirksMode() {
1386			cv.pos = expr.Body.Rbrace
1387		}
1388		w.useLocal(cv.pos, cv.obj)
1389	}
1390
1391	w.reloc(relocBody, body)
1392}
1393
1394type posObj struct {
1395	pos syntax.Pos
1396	obj *types2.Var
1397}
1398
1399func (w *writer) exprList(expr syntax.Expr) {
1400	w.sync(syncExprList)
1401	w.exprs(unpackListExpr(expr))
1402}
1403
1404func (w *writer) exprs(exprs []syntax.Expr) {
1405	if len(exprs) == 0 {
1406		assert(exprs == nil)
1407	}
1408
1409	w.sync(syncExprs)
1410	w.len(len(exprs))
1411	for _, expr := range exprs {
1412		w.expr(expr)
1413	}
1414}
1415
1416func (w *writer) op(op ir.Op) {
1417	// TODO(mdempsky): Remove in favor of explicit codes? Would make
1418	// export data more stable against internal refactorings, but low
1419	// priority at the moment.
1420	assert(op != 0)
1421	w.sync(syncOp)
1422	w.len(int(op))
1423}
1424
1425func (w *writer) needType(typ types2.Type) {
1426	// Decompose tuple into component element types.
1427	if typ, ok := typ.(*types2.Tuple); ok {
1428		for i := 0; i < typ.Len(); i++ {
1429			w.needType(typ.At(i).Type())
1430		}
1431		return
1432	}
1433
1434	if info := w.p.typIdx(typ, w.dict); info.derived {
1435		w.dict.derived[info.idx].needed = true
1436	}
1437}
1438
1439// @@@ Package initialization
1440
1441// Caution: This code is still clumsy, because toolstash -cmp is
1442// particularly sensitive to it.
1443
1444type typeDeclGen struct {
1445	*syntax.TypeDecl
1446	gen int
1447
1448	// Implicit type parameters in scope at this type declaration.
1449	implicits []*types2.TypeName
1450}
1451
1452type fileImports struct {
1453	importedEmbed, importedUnsafe bool
1454}
1455
1456type declCollector struct {
1457	pw         *pkgWriter
1458	typegen    *int
1459	file       *fileImports
1460	withinFunc bool
1461	implicits  []*types2.TypeName
1462}
1463
1464func (c *declCollector) withTParams(obj types2.Object) *declCollector {
1465	tparams := objTypeParams(obj)
1466	n := tparams.Len()
1467	if n == 0 {
1468		return c
1469	}
1470
1471	copy := *c
1472	copy.implicits = copy.implicits[:len(copy.implicits):len(copy.implicits)]
1473	for i := 0; i < n; i++ {
1474		copy.implicits = append(copy.implicits, tparams.At(i).Obj())
1475	}
1476	return &copy
1477}
1478
1479func (c *declCollector) Visit(n syntax.Node) syntax.Visitor {
1480	pw := c.pw
1481
1482	switch n := n.(type) {
1483	case *syntax.File:
1484		pw.checkPragmas(n.Pragma, ir.GoBuildPragma, false)
1485
1486	case *syntax.ImportDecl:
1487		pw.checkPragmas(n.Pragma, 0, false)
1488
1489		switch pkgNameOf(pw.info, n).Imported().Path() {
1490		case "embed":
1491			c.file.importedEmbed = true
1492		case "unsafe":
1493			c.file.importedUnsafe = true
1494		}
1495
1496	case *syntax.ConstDecl:
1497		pw.checkPragmas(n.Pragma, 0, false)
1498
1499	case *syntax.FuncDecl:
1500		pw.checkPragmas(n.Pragma, funcPragmas, false)
1501
1502		obj := pw.info.Defs[n.Name].(*types2.Func)
1503		pw.funDecls[obj] = n
1504
1505		return c.withTParams(obj)
1506
1507	case *syntax.TypeDecl:
1508		obj := pw.info.Defs[n.Name].(*types2.TypeName)
1509		d := typeDeclGen{TypeDecl: n, implicits: c.implicits}
1510
1511		if n.Alias {
1512			pw.checkPragmas(n.Pragma, 0, false)
1513		} else {
1514			pw.checkPragmas(n.Pragma, typePragmas, false)
1515
1516			// Assign a unique ID to function-scoped defined types.
1517			if c.withinFunc {
1518				*c.typegen++
1519				d.gen = *c.typegen
1520			}
1521		}
1522
1523		pw.typDecls[obj] = d
1524
1525		// TODO(mdempsky): Omit? Not strictly necessary; only matters for
1526		// type declarations within function literals within parameterized
1527		// type declarations, but types2 the function literals will be
1528		// constant folded away.
1529		return c.withTParams(obj)
1530
1531	case *syntax.VarDecl:
1532		pw.checkPragmas(n.Pragma, 0, true)
1533
1534		if p, ok := n.Pragma.(*pragmas); ok && len(p.Embeds) > 0 {
1535			if err := checkEmbed(n, c.file.importedEmbed, c.withinFunc); err != nil {
1536				pw.errorf(p.Embeds[0].Pos, "%s", err)
1537			}
1538		}
1539
1540		// Workaround for #46208. For variable declarations that
1541		// declare multiple variables and have an explicit type
1542		// expression, the type expression is evaluated multiple
1543		// times. This affects toolstash -cmp, because iexport is
1544		// sensitive to *types.Type pointer identity.
1545		if quirksMode() && n.Type != nil {
1546			tv, ok := pw.info.Types[n.Type]
1547			assert(ok)
1548			assert(tv.IsType())
1549			for _, name := range n.NameList {
1550				obj := pw.info.Defs[name].(*types2.Var)
1551				pw.dups.add(obj.Type(), tv.Type)
1552			}
1553		}
1554
1555	case *syntax.BlockStmt:
1556		if !c.withinFunc {
1557			copy := *c
1558			copy.withinFunc = true
1559			return &copy
1560		}
1561	}
1562
1563	return c
1564}
1565
1566func (pw *pkgWriter) collectDecls(noders []*noder) {
1567	var typegen int
1568	for _, p := range noders {
1569		var file fileImports
1570
1571		syntax.Walk(p.file, &declCollector{
1572			pw:      pw,
1573			typegen: &typegen,
1574			file:    &file,
1575		})
1576
1577		pw.cgoPragmas = append(pw.cgoPragmas, p.pragcgobuf...)
1578
1579		for _, l := range p.linknames {
1580			if !file.importedUnsafe {
1581				pw.errorf(l.pos, "//go:linkname only allowed in Go files that import \"unsafe\"")
1582				continue
1583			}
1584
1585			switch obj := pw.curpkg.Scope().Lookup(l.local).(type) {
1586			case *types2.Func, *types2.Var:
1587				if _, ok := pw.linknames[obj]; !ok {
1588					pw.linknames[obj] = l.remote
1589				} else {
1590					pw.errorf(l.pos, "duplicate //go:linkname for %s", l.local)
1591				}
1592
1593			default:
1594				// TODO(mdempsky): Enable after #42938 is fixed.
1595				if false {
1596					pw.errorf(l.pos, "//go:linkname must refer to declared function or variable")
1597				}
1598			}
1599		}
1600	}
1601}
1602
1603func (pw *pkgWriter) checkPragmas(p syntax.Pragma, allowed ir.PragmaFlag, embedOK bool) {
1604	if p == nil {
1605		return
1606	}
1607	pragma := p.(*pragmas)
1608
1609	for _, pos := range pragma.Pos {
1610		if pos.Flag&^allowed != 0 {
1611			pw.errorf(pos.Pos, "misplaced compiler directive")
1612		}
1613	}
1614
1615	if !embedOK {
1616		for _, e := range pragma.Embeds {
1617			pw.errorf(e.Pos, "misplaced go:embed directive")
1618		}
1619	}
1620}
1621
1622func (w *writer) pkgInit(noders []*noder) {
1623	if quirksMode() {
1624		posBases := posBasesOf(noders)
1625		w.len(len(posBases))
1626		for _, posBase := range posBases {
1627			w.posBase(posBase)
1628		}
1629
1630		objs := importedObjsOf(w.p.curpkg, w.p.info, noders)
1631		w.len(len(objs))
1632		for _, obj := range objs {
1633			w.qualifiedIdent(obj)
1634		}
1635	}
1636
1637	w.len(len(w.p.cgoPragmas))
1638	for _, cgoPragma := range w.p.cgoPragmas {
1639		w.strings(cgoPragma)
1640	}
1641
1642	w.sync(syncDecls)
1643	for _, p := range noders {
1644		for _, decl := range p.file.DeclList {
1645			w.pkgDecl(decl)
1646		}
1647	}
1648	w.code(declEnd)
1649
1650	w.sync(syncEOF)
1651}
1652
1653func (w *writer) pkgDecl(decl syntax.Decl) {
1654	switch decl := decl.(type) {
1655	default:
1656		w.p.unexpected("declaration", decl)
1657
1658	case *syntax.ImportDecl:
1659
1660	case *syntax.ConstDecl:
1661		w.code(declOther)
1662		w.pkgObjs(decl.NameList...)
1663
1664	case *syntax.FuncDecl:
1665		if decl.Name.Value == "_" {
1666			break // skip blank functions
1667		}
1668
1669		obj := w.p.info.Defs[decl.Name].(*types2.Func)
1670		sig := obj.Type().(*types2.Signature)
1671
1672		if sig.RecvTypeParams() != nil || sig.TypeParams() != nil {
1673			break // skip generic functions
1674		}
1675
1676		if recv := sig.Recv(); recv != nil {
1677			w.code(declMethod)
1678			w.typ(recvBase(recv))
1679			w.selector(obj)
1680			break
1681		}
1682
1683		w.code(declFunc)
1684		w.pkgObjs(decl.Name)
1685
1686	case *syntax.TypeDecl:
1687		if len(decl.TParamList) != 0 {
1688			break // skip generic type decls
1689		}
1690
1691		if decl.Name.Value == "_" {
1692			break // skip blank type decls
1693		}
1694
1695		name := w.p.info.Defs[decl.Name].(*types2.TypeName)
1696		// Skip type declarations for interfaces that are only usable as
1697		// type parameter bounds.
1698		if iface, ok := name.Type().Underlying().(*types2.Interface); ok && !iface.IsMethodSet() {
1699			break
1700		}
1701
1702		// Skip aliases to uninstantiated generic types.
1703		// TODO(mdempsky): Revisit after #46477 is resolved.
1704		if name.IsAlias() {
1705			named, ok := name.Type().(*types2.Named)
1706			if ok && named.TypeParams().Len() != 0 && named.TypeArgs().Len() == 0 {
1707				break
1708			}
1709		}
1710
1711		w.code(declOther)
1712		w.pkgObjs(decl.Name)
1713
1714	case *syntax.VarDecl:
1715		w.code(declVar)
1716		w.pos(decl)
1717		w.pkgObjs(decl.NameList...)
1718		w.exprList(decl.Values)
1719
1720		var embeds []pragmaEmbed
1721		if p, ok := decl.Pragma.(*pragmas); ok {
1722			embeds = p.Embeds
1723		}
1724		w.len(len(embeds))
1725		for _, embed := range embeds {
1726			w.pos(embed.Pos)
1727			w.strings(embed.Patterns)
1728		}
1729	}
1730}
1731
1732func (w *writer) pkgObjs(names ...*syntax.Name) {
1733	w.sync(syncDeclNames)
1734	w.len(len(names))
1735
1736	for _, name := range names {
1737		obj, ok := w.p.info.Defs[name]
1738		assert(ok)
1739
1740		w.sync(syncDeclName)
1741		w.obj(obj, nil)
1742	}
1743}
1744
1745// @@@ Helpers
1746
1747// isDefinedType reports whether obj is a defined type.
1748func isDefinedType(obj types2.Object) bool {
1749	if obj, ok := obj.(*types2.TypeName); ok {
1750		return !obj.IsAlias()
1751	}
1752	return false
1753}
1754
1755// isGlobal reports whether obj was declared at package scope.
1756//
1757// Caveat: blank objects are not declared.
1758func isGlobal(obj types2.Object) bool {
1759	return obj.Parent() == obj.Pkg().Scope()
1760}
1761
1762// lookupObj returns the object that expr refers to, if any. If expr
1763// is an explicit instantiation of a generic object, then the instance
1764// object is returned as well.
1765func lookupObj(info *types2.Info, expr syntax.Expr) (obj types2.Object, inst types2.Instance) {
1766	if index, ok := expr.(*syntax.IndexExpr); ok {
1767		args := unpackListExpr(index.Index)
1768		if len(args) == 1 {
1769			tv, ok := info.Types[args[0]]
1770			assert(ok)
1771			if tv.IsValue() {
1772				return // normal index expression
1773			}
1774		}
1775
1776		expr = index.X
1777	}
1778
1779	// Strip package qualifier, if present.
1780	if sel, ok := expr.(*syntax.SelectorExpr); ok {
1781		if !isPkgQual(info, sel) {
1782			return // normal selector expression
1783		}
1784		expr = sel.Sel
1785	}
1786
1787	if name, ok := expr.(*syntax.Name); ok {
1788		obj = info.Uses[name]
1789		inst = info.Instances[name]
1790	}
1791	return
1792}
1793
1794// isPkgQual reports whether the given selector expression is a
1795// package-qualified identifier.
1796func isPkgQual(info *types2.Info, sel *syntax.SelectorExpr) bool {
1797	if name, ok := sel.X.(*syntax.Name); ok {
1798		_, isPkgName := info.Uses[name].(*types2.PkgName)
1799		return isPkgName
1800	}
1801	return false
1802}
1803
1804// recvBase returns the base type for the given receiver parameter.
1805func recvBase(recv *types2.Var) *types2.Named {
1806	typ := recv.Type()
1807	if ptr, ok := typ.(*types2.Pointer); ok {
1808		typ = ptr.Elem()
1809	}
1810	return typ.(*types2.Named)
1811}
1812
1813// namesAsExpr returns a list of names as a syntax.Expr.
1814func namesAsExpr(names []*syntax.Name) syntax.Expr {
1815	if len(names) == 1 {
1816		return names[0]
1817	}
1818
1819	exprs := make([]syntax.Expr, len(names))
1820	for i, name := range names {
1821		exprs[i] = name
1822	}
1823	return &syntax.ListExpr{ElemList: exprs}
1824}
1825
1826// fieldIndex returns the index of the struct field named by key.
1827func fieldIndex(info *types2.Info, str *types2.Struct, key *syntax.Name) int {
1828	field := info.Uses[key].(*types2.Var)
1829
1830	for i := 0; i < str.NumFields(); i++ {
1831		if str.Field(i) == field {
1832			return i
1833		}
1834	}
1835
1836	panic(fmt.Sprintf("%s: %v is not a field of %v", key.Pos(), field, str))
1837}
1838
1839// objTypeParams returns the type parameters on the given object.
1840func objTypeParams(obj types2.Object) *types2.TypeParamList {
1841	switch obj := obj.(type) {
1842	case *types2.Func:
1843		sig := obj.Type().(*types2.Signature)
1844		if sig.Recv() != nil {
1845			return sig.RecvTypeParams()
1846		}
1847		return sig.TypeParams()
1848	case *types2.TypeName:
1849		if !obj.IsAlias() {
1850			return obj.Type().(*types2.Named).TypeParams()
1851		}
1852	}
1853	return nil
1854}
1855
1856func asPragmaFlag(p syntax.Pragma) ir.PragmaFlag {
1857	if p == nil {
1858		return 0
1859	}
1860	return p.(*pragmas).Flag
1861}
1862