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