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