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