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.
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"
19 // This file implements the Unified IR package writer and defines the
20 // Unified IR export data format.
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.
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.
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:
36 // - writer.thing handles writing out a *use* of a thing, which often
37 // means writing a relocation to that thing's encoded index.
39 // - pkgWriter.thingIdx handles reserving an index for a thing, and
40 // writing out any elements needed for the thing.
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.
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.
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
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 {
62 curpkg *types2.Package
65 // Indices for previously written syntax and types2 things.
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
72 // Maps from types2.Objects back to their syntax.Decl.
74 funDecls map[*types2.Func]*syntax.FuncDecl
75 typDecls map[*types2.TypeName]typeDeclGen
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
81 // cgoPragmas accumulates any //go:cgo_* pragmas that need to be
82 // passed through to cmd/link.
86 // newPkgWriter returns an initialized pkgWriter for the specified
88 func newPkgWriter(m posMap, pkg *types2.Package, info *types2.Info) *pkgWriter {
90 PkgEncoder: pkgbits.NewPkgEncoder(base.Debug.SyncFrames),
96 pkgsIdx: make(map[*types2.Package]pkgbits.Index),
97 objsIdx: make(map[types2.Object]pkgbits.Index),
98 typsIdx: make(map[types2.Type]pkgbits.Index),
100 posBasesIdx: make(map[*syntax.PosBase]pkgbits.Index),
102 funDecls: make(map[*types2.Func]*syntax.FuncDecl),
103 typDecls: make(map[*types2.TypeName]typeDeclGen),
105 linknames: make(map[types2.Object]string),
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...)
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...)
119 // unexpected reports a fatal error about a thing of unexpected
121 func (pw *pkgWriter) unexpected(what string, p poser) {
122 pw.fatalf(p, "unexpected %s: %v (%T)", what, p, p)
125 func (pw *pkgWriter) typeAndValue(x syntax.Expr) syntax.TypeAndValue {
126 tv := x.GetTypeInfo()
128 pw.fatalf(x, "missing Types entry: %v", syntax.String(x))
132 func (pw *pkgWriter) maybeTypeAndValue(x syntax.Expr) (syntax.TypeAndValue, bool) {
133 tv := x.GetTypeInfo()
134 return tv, tv.Type != nil
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)
141 pw.fatalf(expr, "expected value: %v", syntax.String(expr))
146 // A writer provides APIs for writing out an individual element.
152 // sig holds the signature for the current function body, if any.
153 sig *types2.Signature
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).
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
163 // closureVars tracks any free variables that are referenced by this
164 // function body. It's unused for writing out non-body things.
166 closureVarsIdx map[*types2.Var]int // index of previously seen free variables
170 // derived tracks whether the type being written out references any
171 // type parameters. It's unused for writing non-type things.
175 // A writerDict tracks types and objects that are used by a declaration.
176 type writerDict struct {
177 implicits []*types2.TypeName
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
183 // derivedIdx maps a Type to its corresponding index within the
184 // derived slice, if present.
185 derivedIdx map[types2.Type]pkgbits.Index
187 // These slices correspond to entries in the runtime dictionary.
188 typeParamMethodExprs []writerMethodExprInfo
194 type itabInfo struct {
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 {
210 return len(dict.implicits) + typ.Index()
213 // A derivedInfo represents a reference to an encoded generic Go type.
214 type derivedInfo struct {
216 needed bool // TODO(mdempsky): Remove.
219 // A typeInfo represents a reference to an encoded Go type.
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.
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 {
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
239 // A selectorInfo represents a reference to an encoded field or method
240 // name (i.e., objects that can only be accessed using selector
242 type selectorInfo struct {
244 nameIdx pkgbits.Index
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 {
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 {
264 assert(len(info.explicits) == len(other.explicits))
265 for i, targ := range info.explicits {
266 if targ != other.explicits[i] {
273 type writerMethodExprInfo struct {
275 methodInfo selectorInfo
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}
284 for idx, oldInfo := range dict.typeParamMethodExprs {
285 if oldInfo == newInfo {
290 idx := len(dict.typeParamMethodExprs)
291 dict.typeParamMethodExprs = append(dict.typeParamMethodExprs, newInfo)
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) {
305 idx := len(dict.subdicts)
306 dict.subdicts = append(dict.subdicts, newInfo)
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 {
320 idx := len(dict.rtypes)
321 dict.rtypes = append(dict.rtypes, newInfo)
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}
331 for idx, oldInfo := range dict.itabs {
332 if oldInfo == newInfo {
337 idx := len(dict.itabs)
338 dict.itabs = append(dict.itabs, newInfo)
342 func (pw *pkgWriter) newWriter(k pkgbits.RelocKind, marker pkgbits.SyncMarker) *writer {
344 Encoder: pw.NewEncoder(k, marker),
351 // pos writes the position of p into the element bitstream.
352 func (w *writer) pos(p poser) {
353 w.Sync(pkgbits.SyncPos)
356 // TODO(mdempsky): Track down the remaining cases here and fix them.
357 if !w.Bool(pos.IsKnown()) {
361 // TODO(mdempsky): Delta encoding.
362 w.posBase(pos.Base())
367 // posBase writes a reference to the given PosBase into the element
369 func (w *writer) posBase(b *syntax.PosBase) {
370 w.Reloc(pkgbits.RelocPosBase, w.p.posBaseIdx(b))
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 {
379 w := pw.newWriter(pkgbits.RelocPosBase, pkgbits.SyncPosBase)
380 w.p.posBasesIdx[b] = w.Idx
382 w.String(trimFilename(b))
384 if !w.Bool(b.IsFileBase()) {
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))
400 func (w *writer) pkgRef(idx pkgbits.Index) {
401 w.Sync(pkgbits.SyncPkg)
402 w.Reloc(pkgbits.RelocPkg, idx)
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 {
412 w := pw.newWriter(pkgbits.RelocPkg, pkgbits.SyncPkgDef)
413 pw.pkgsIdx[pkg] = w.Idx
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.
420 case nil: // universe
421 w.String("builtin") // same package path used by godoc
425 // TODO(mdempsky): Write out pkg.Path() for curpkg too.
427 if pkg != w.p.curpkg {
430 base.Assertf(path != "builtin" && path != "unsafe", "unexpected path for user-defined package: %q", path)
434 w.Len(len(pkg.Imports()))
435 for _, imp := range pkg.Imports() {
446 anyTypeName = types2.Universe.Lookup("any").(*types2.TypeName)
447 comparableTypeName = types2.Universe.Lookup("comparable").(*types2.TypeName)
448 runeTypeName = types2.Universe.Lookup("rune").(*types2.TypeName)
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))
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) {
464 w.Reloc(pkgbits.RelocType, info.idx)
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.
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}
478 if idx, ok := dict.derivedIdx[typ]; ok {
479 return typeInfo{idx: idx, derived: true}
483 w := pw.newWriter(pkgbits.RelocType, pkgbits.SyncTypeIdx)
486 switch typ := typ.(type) {
488 base.Fatalf("unexpected type: %v (%T)", typ, typ)
491 switch kind := typ.Kind(); {
492 case kind == types2.Invalid:
493 base.Fatalf("unexpected types2.Invalid")
495 case types2.Typ[kind] == typ:
496 w.Code(pkgbits.TypeBasic)
500 // Handle "byte" and "rune" as references to their TypeNames.
501 obj := types2.Universe.Lookup(typ.Name())
502 assert(obj.Type() == typ)
504 w.Code(pkgbits.TypeNamed)
509 obj, targs := splitNamed(typ)
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) {
517 w.Code(pkgbits.TypeNamed)
520 case *types2.TypeParam:
522 w.Code(pkgbits.TypeTypeParam)
523 w.Len(w.dict.typeParamIndex(typ))
526 w.Code(pkgbits.TypeArray)
527 w.Uint64(uint64(typ.Len()))
531 w.Code(pkgbits.TypeChan)
532 w.Len(int(typ.Dir()))
536 w.Code(pkgbits.TypeMap)
540 case *types2.Pointer:
541 w.Code(pkgbits.TypePointer)
544 case *types2.Signature:
545 base.Assertf(typ.TypeParams() == nil, "unexpected type params: %v", typ)
546 w.Code(pkgbits.TypeSignature)
550 w.Code(pkgbits.TypeSlice)
554 w.Code(pkgbits.TypeStruct)
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)
565 w.Code(pkgbits.TypeInterface)
569 w.Code(pkgbits.TypeUnion)
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}
580 pw.typsIdx[typ] = w.Idx
581 return typeInfo{idx: w.Flush(), derived: false}
584 func (w *writer) structType(typ *types2.Struct) {
585 w.Len(typ.NumFields())
586 for i := 0; i < typ.NumFields(); i++ {
596 func (w *writer) unionType(typ *types2.Union) {
598 for i := 0; i < typ.Len(); i++ {
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
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())
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)
623 w.Len(typ.NumExplicitMethods())
624 w.Len(typ.NumEmbeddeds())
626 if typ.NumExplicitMethods() == 0 && typ.NumEmbeddeds() == 1 {
627 w.Bool(typ.IsImplicit())
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())
635 for i := 0; i < typ.NumExplicitMethods(); i++ {
636 m := typ.ExplicitMethod(i)
637 sig := m.Type().(*types2.Signature)
638 assert(sig.TypeParams() == nil)
645 for i := 0; i < typ.NumEmbeddeds(); i++ {
646 w.typ(typ.EmbeddedType(i))
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())
657 func (w *writer) params(typ *types2.Tuple) {
658 w.Sync(pkgbits.SyncParams)
660 for i := 0; i < typ.Len(); i++ {
665 func (w *writer) param(param *types2.Var) {
666 w.Sync(pkgbits.SyncParam)
674 // obj writes a use of the given object into the bitstream.
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))
683 // objInfo writes a use of the given encoded object into the
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)
690 w.Len(len(info.explicits))
691 for _, info := range info.explicits {
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)
704 return objInfo{idx: pw.objIdx(obj), explicits: explicitInfos}
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).
713 if idx, ok := pw.objsIdx[obj]; ok {
718 derivedIdx: make(map[types2.Type]pkgbits.Index),
721 if isDefinedType(obj) && obj.Pkg() == pw.curpkg {
722 decl, ok := pw.typDecls[obj.(*types2.TypeName)]
724 dict.implicits = decl.implicits
727 // We encode objects into 4 elements across different sections, all
728 // sharing the same index:
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).
734 // - RelocObj has the remaining public details about the object,
735 // relevant to go/types importers.
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.
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.
747 // TODO(mdempsky): Re-evaluate whether RelocName still makes sense
748 // to keep separate from RelocObj.
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)
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)
763 code := w.doObj(wext, obj)
767 wname.qualifiedIdent(obj)
771 wdict.objDict(obj, w.dict)
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
784 switch obj := obj.(type) {
786 w.p.unexpected("object", obj)
793 return pkgbits.ObjConst
796 decl, ok := w.p.funDecls[obj]
798 sig := obj.Type().(*types2.Signature)
801 w.typeParamNames(sig.TypeParams())
805 return pkgbits.ObjFunc
807 case *types2.TypeName:
811 return pkgbits.ObjAlias
814 named := obj.Type().(*types2.Named)
815 assert(named.TypeArgs() == nil)
818 w.typeParamNames(named.TypeParams())
820 w.typ(named.Underlying())
822 w.Len(named.NumMethods())
823 for i := 0; i < named.NumMethods(); i++ {
824 w.method(wext, named.Method(i))
827 return pkgbits.ObjType
833 return pkgbits.ObjVar
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.
843 w.dict = dict // TODO(mdempsky): This is a bit sketchy.
845 w.Len(len(dict.implicits))
847 tparams := objTypeParams(obj)
848 ntparams := tparams.Len()
850 for i := 0; i < ntparams; i++ {
851 w.typ(tparams.At(i).Constraint())
854 nderived := len(dict.derived)
856 for _, typ := range dict.derived {
857 w.Reloc(pkgbits.RelocType, typ.idx)
861 // Write runtime dictionary information.
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.)
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.
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())
880 for i := 0; i < ntparams; i++ {
881 tparam := tparams.At(i)
882 w.Bool(tparam.Underlying().(*types2.Interface).IsMethodSet())
885 w.Len(len(dict.typeParamMethodExprs))
886 for _, info := range dict.typeParamMethodExprs {
887 w.Len(info.typeParamIdx)
888 w.selectorInfo(info.methodInfo)
891 w.Len(len(dict.subdicts))
892 for _, info := range dict.subdicts {
896 w.Len(len(dict.rtypes))
897 for _, info := range dict.rtypes {
901 w.Len(len(dict.itabs))
902 for _, info := range dict.itabs {
904 w.typInfo(info.iface)
907 assert(len(dict.derived) == nderived)
910 func (w *writer) typeParamNames(tparams *types2.TypeParamList) {
911 w.Sync(pkgbits.SyncTypeParamNames)
913 ntparams := tparams.Len()
914 for i := 0; i < ntparams; i++ {
915 tparam := tparams.At(i).Obj()
921 func (w *writer) method(wext *writer, meth *types2.Func) {
922 decl, ok := w.p.funDecls[meth]
924 sig := meth.Type().(*types2.Signature)
926 w.Sync(pkgbits.SyncMethod)
929 w.typeParamNames(sig.RecvTypeParams())
933 w.pos(decl) // XXX: Hack to workaround linker limitations.
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)
943 if isDefinedType(obj) && obj.Pkg() == w.p.curpkg {
944 decl, ok := w.p.typDecls[obj.(*types2.TypeName)]
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.
951 // TODO(mdempsky): Find a better solution; this is terrible.
952 name = fmt.Sprintf("%s·%v", name, decl.gen)
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.
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)
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))
981 func (w *writer) selectorInfo(info selectorInfo) {
982 w.Sync(pkgbits.SyncSelector)
983 w.pkgRef(info.pkgIdx)
984 w.StringRef(info.nameIdx)
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}
993 // @@@ Compiler extensions
995 func (w *writer) funcExt(obj *types2.Func) {
996 decl, ok := w.p.funDecls[obj]
999 // TODO(mdempsky): Extend these pragma validation flags to account
1000 // for generics. E.g., linkname probably doesn't make sense at
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")
1007 wi := asWasmImport(decl.Pragma)
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")
1014 w.p.errorf(decl, "can only use //go:wasmimport with external func implementations")
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
1023 // N.B. uintptrescapes implies uintptrkeepalive but it
1024 // is OK since the arguments must escape to the heap.
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
1030 w.p.errorf(decl, "go:uintptrkeepalive requires go:nosplit")
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")
1043 sig, block := obj.Type().(*types2.Signature), decl.Body
1044 body, closureVars := w.p.bodyIdx(sig, block, w.dict)
1045 assert(len(closureVars) == 0)
1047 w.Sync(pkgbits.SyncFuncExt)
1048 w.pragmaFlag(pragma)
1051 if buildcfg.GOARCH == "wasm" {
1061 w.Bool(false) // stub extension
1062 w.Reloc(pkgbits.RelocBody, body)
1063 w.Sync(pkgbits.SyncEOF)
1066 func (w *writer) typeExt(obj *types2.TypeName) {
1067 decl, ok := w.p.typDecls[obj]
1070 w.Sync(pkgbits.SyncTypeExt)
1072 w.pragmaFlag(asPragmaFlag(decl.Pragma))
1074 // No LSym.SymIdx info yet.
1079 func (w *writer) varExt(obj *types2.Var) {
1080 w.Sync(pkgbits.SyncVarExt)
1084 func (w *writer) linkname(obj types2.Object) {
1085 w.Sync(pkgbits.SyncLinkname)
1087 w.String(w.p.linknames[obj])
1090 func (w *writer) pragmaFlag(p ir.PragmaFlag) {
1091 w.Sync(pkgbits.SyncPragma)
1095 // @@@ Function bodies
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)
1105 if w.Bool(block != nil) {
1110 return w.Flush(), w.closureVars
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)
1120 if recv := sig.Recv(); recv != nil {
1121 w.funcarg(recv, false)
1123 do(sig.Params(), false)
1124 do(sig.Results(), true)
1127 func (w *writer) funcarg(param *types2.Var, result bool) {
1128 if param.Name() != "" || result {
1133 // addLocal records the declaration of a new local variable.
1134 func (w *writer) addLocal(obj *types2.Var) {
1135 idx := len(w.localsIdx)
1137 w.Sync(pkgbits.SyncAddLocal)
1138 if w.p.SyncMarkers() {
1143 if w.localsIdx == nil {
1144 w.localsIdx = make(map[*types2.Var]int)
1146 w.localsIdx[obj] = idx
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)
1154 if idx, ok := w.localsIdx[obj]; w.Bool(ok) {
1159 idx, ok := w.closureVarsIdx[obj]
1161 if w.closureVarsIdx == nil {
1162 w.closureVarsIdx = make(map[*types2.Var]int)
1164 idx = len(w.closureVars)
1165 w.closureVars = append(w.closureVars, posVar{pos, obj})
1166 w.closureVarsIdx[obj] = idx
1171 func (w *writer) openScope(pos syntax.Pos) {
1172 w.Sync(pkgbits.SyncOpenScope)
1176 func (w *writer) closeScope(pos syntax.Pos) {
1177 w.Sync(pkgbits.SyncCloseScope)
1179 w.closeAnotherScope()
1182 func (w *writer) closeAnotherScope() {
1183 w.Sync(pkgbits.SyncCloseAnotherScope)
1188 // stmt writes the given statement into the function body bitstream.
1189 func (w *writer) stmt(stmt syntax.Stmt) {
1190 var stmts []syntax.Stmt
1192 stmts = []syntax.Stmt{stmt}
1197 func (w *writer) stmts(stmts []syntax.Stmt) {
1198 w.Sync(pkgbits.SyncStmts)
1199 for _, stmt := range stmts {
1203 w.Sync(pkgbits.SyncStmtsEnd)
1206 func (w *writer) stmt1(stmt syntax.Stmt) {
1207 switch stmt := stmt.(type) {
1209 w.p.unexpected("statement", stmt)
1211 case nil, *syntax.EmptyStmt:
1214 case *syntax.AssignStmt:
1216 case stmt.Rhs == nil:
1218 w.op(binOps[stmt.Op])
1222 case stmt.Op != 0 && stmt.Op != syntax.Def:
1223 w.Code(stmtAssignOp)
1224 w.op(binOps[stmt.Op])
1229 if stmt.Op != syntax.Shl && stmt.Op != syntax.Shr {
1230 typ = w.p.typeOf(stmt.Lhs)
1232 w.implicitConvExpr(typ, stmt.Rhs)
1235 w.assignStmt(stmt, stmt.Lhs, stmt.Rhs)
1238 case *syntax.BlockStmt:
1242 case *syntax.BranchStmt:
1245 w.op(branchOps[stmt.Tok])
1246 w.optLabel(stmt.Label)
1248 case *syntax.CallStmt:
1251 w.op(callOps[stmt.Tok])
1254 case *syntax.DeclStmt:
1255 for _, decl := range stmt.DeclList {
1259 case *syntax.ExprStmt:
1263 case *syntax.ForStmt:
1267 case *syntax.IfStmt:
1271 case *syntax.LabeledStmt:
1277 case *syntax.ReturnStmt:
1281 resultTypes := w.sig.Results()
1282 dstType := func(i int) types2.Type {
1283 return resultTypes.At(i).Type()
1285 w.multiExpr(stmt, dstType, unpackListExpr(stmt.Results))
1287 case *syntax.SelectStmt:
1291 case *syntax.SendStmt:
1292 chanType := types2.CoreType(w.p.typeOf(stmt.Chan)).(*types2.Chan)
1297 w.implicitConvExpr(chanType.Elem(), stmt.Value)
1299 case *syntax.SwitchStmt:
1305 func (w *writer) assignList(expr syntax.Expr) {
1306 exprs := unpackListExpr(expr)
1309 for _, expr := range exprs {
1314 func (w *writer) assign(expr syntax.Expr) {
1315 expr = unparen(expr)
1317 if name, ok := expr.(*syntax.Name); ok {
1318 if name.Value == "_" {
1323 if obj, ok := w.p.info.Defs[name]; ok {
1324 obj := obj.(*types2.Var)
1331 // TODO(mdempsky): Minimize locals index size by deferring
1332 // this until the variables actually come into scope.
1342 func (w *writer) declStmt(decl syntax.Decl) {
1343 switch decl := decl.(type) {
1345 w.p.unexpected("declaration", decl)
1347 case *syntax.ConstDecl, *syntax.TypeDecl:
1349 case *syntax.VarDecl:
1350 w.assignStmt(decl, namesAsExpr(decl.NameList), decl.Values)
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)
1362 // As if w.assignList(lhs0).
1364 for _, expr := range lhs {
1368 dstType := func(i int) types2.Type {
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 {
1379 } else if use, ok := w.p.info.Uses[name].(*types2.Var); ok {
1382 w.p.fatalf(dst, "cannot find type of destination object: %v", dst)
1386 return w.p.typeOf(dst)
1389 w.multiExpr(pos, dstType, rhs)
1392 func (w *writer) blockStmt(stmt *syntax.BlockStmt) {
1393 w.Sync(pkgbits.SyncBlockStmt)
1394 w.openScope(stmt.Pos())
1396 w.closeScope(stmt.Rbrace)
1399 func (w *writer) forStmt(stmt *syntax.ForStmt) {
1400 w.Sync(pkgbits.SyncForStmt)
1401 w.openScope(stmt.Pos())
1403 if rang, ok := stmt.Init.(*syntax.RangeClause); w.Bool(ok) {
1405 w.assignList(rang.Lhs)
1408 xtyp := w.p.typeOf(rang.X)
1409 if _, isMap := types2.CoreType(xtyp).(*types2.Map); isMap {
1413 lhs := unpackListExpr(rang.Lhs)
1414 assign := func(i int, src types2.Type) {
1418 dst := unparen(lhs[i])
1419 if name, ok := dst.(*syntax.Name); ok && name.Value == "_" {
1423 var dstType types2.Type
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()
1429 dstType = w.p.typeOf(dst)
1432 w.convRTTI(src, dstType)
1435 keyType, valueType := w.p.rangeTypes(rang.X)
1437 assign(1, valueType)
1443 w.optExpr(stmt.Cond)
1447 w.blockStmt(stmt.Body)
1448 w.closeAnotherScope()
1451 // rangeTypes returns the types of values produced by ranging over
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()
1459 return types2.Typ[types2.Int], typ.Elem()
1461 return types2.Typ[types2.Int], typ.Elem()
1463 if typ.Info()&types2.IsString != 0 {
1464 return types2.Typ[types2.Int], runeTypeName.Type()
1467 return typ.Key(), typ.Elem()
1469 return typ.Elem(), nil
1471 pw.fatalf(expr, "unexpected range type: %v", typ)
1472 panic("unreachable")
1475 func (w *writer) ifStmt(stmt *syntax.IfStmt) {
1476 w.Sync(pkgbits.SyncIfStmt)
1477 w.openScope(stmt.Pos())
1481 w.blockStmt(stmt.Then)
1483 w.closeAnotherScope()
1486 func (w *writer) selectStmt(stmt *syntax.SelectStmt) {
1487 w.Sync(pkgbits.SyncSelectStmt)
1490 w.Len(len(stmt.Body))
1491 for i, clause := range stmt.Body {
1493 w.closeScope(clause.Pos())
1495 w.openScope(clause.Pos())
1499 w.stmts(clause.Body)
1501 if len(stmt.Body) > 0 {
1502 w.closeScope(stmt.Rbrace)
1506 func (w *writer) switchStmt(stmt *syntax.SwitchStmt) {
1507 w.Sync(pkgbits.SyncSwitchStmt)
1509 w.openScope(stmt.Pos())
1513 var iface, tagType types2.Type
1514 if guard, ok := stmt.Tag.(*syntax.TypeSwitchGuard); w.Bool(ok) {
1515 iface = w.p.typeOf(guard.X)
1518 if tag := guard.Lhs; w.Bool(tag != nil) {
1521 // Like w.localIdent, but we don't have a types2.Object.
1522 w.Sync(pkgbits.SyncLocalIdent)
1531 tagType = w.p.typeOf(tag)
1533 tagType = types2.Typ[types2.Bool]
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
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)
1551 if w.Bool(tag != nil) {
1552 w.implicitConvExpr(tagType, tag)
1556 w.Len(len(stmt.Body))
1557 for i, clause := range stmt.Body {
1559 w.closeScope(clause.Pos())
1561 w.openScope(clause.Pos())
1565 cases := unpackListExpr(clause.Cases)
1568 for _, cas := range cases {
1569 if w.Bool(isNil(w.p, cas)) {
1572 w.exprType(iface, cas)
1575 // As if w.exprList(clause.Cases),
1576 // but with implicit conversions to tagType.
1578 w.Sync(pkgbits.SyncExprList)
1579 w.Sync(pkgbits.SyncExprs)
1581 for _, cas := range cases {
1582 w.implicitConvExpr(tagType, cas)
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.
1593 if typs := unpackListExpr(clause.Cases); len(typs) != 0 {
1594 pos = typeExprEndPos(typs[len(typs)-1])
1598 obj := obj.(*types2.Var)
1603 w.stmts(clause.Body)
1605 if len(stmt.Body) > 0 {
1606 w.closeScope(stmt.Rbrace)
1609 w.closeScope(stmt.Rbrace)
1612 func (w *writer) label(label *syntax.Name) {
1613 w.Sync(pkgbits.SyncLabel)
1615 // TODO(mdempsky): Replace label strings with dense indices.
1616 w.String(label.Value)
1619 func (w *writer) optLabel(label *syntax.Name) {
1620 w.Sync(pkgbits.SyncOptLabel)
1621 if w.Bool(label != nil) {
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")
1632 expr = unparen(expr) // skip parens; unneeded after typecheck
1634 obj, inst := lookupObj(w.p, expr)
1635 targs := inst.TypeArgs
1637 if tv, ok := w.p.maybeTypeAndValue(expr); ok {
1639 w.p.fatalf(expr, "unexpected type expression %v", syntax.String(expr))
1642 if tv.Value != nil {
1645 typ := idealType(tv)
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))
1657 if _, isNil := obj.(*types2.Nil); isNil {
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) {
1676 if targs.Len() != 0 {
1677 obj := obj.(*types2.Func)
1679 w.Code(exprFuncInst)
1681 w.funcInst(obj, targs)
1691 obj := obj.(*types2.Var)
1692 assert(!obj.IsField())
1695 w.useLocal(expr.Pos(), obj)
1699 switch expr := expr.(type) {
1701 w.p.unexpected("expression", expr)
1703 case *syntax.CompositeLit:
1707 case *syntax.FuncLit:
1711 case *syntax.SelectorExpr:
1712 sel, ok := w.p.info.Selections[expr]
1717 w.p.fatalf(expr, "unexpected selection kind: %v", sel.Kind())
1719 case types2.FieldVal:
1720 w.Code(exprFieldVal)
1723 w.selector(sel.Obj())
1725 case types2.MethodVal:
1726 w.Code(exprMethodVal)
1727 typ := w.recvExpr(expr, sel)
1729 w.methodExpr(expr, typ, sel)
1731 case types2.MethodExpr:
1732 w.Code(exprMethodExpr)
1734 tv := w.p.typeAndValue(expr.X)
1737 index := sel.Index()
1738 implicits := index[:len(index)-1]
1743 w.Len(len(implicits))
1744 for _, ix := range implicits {
1746 typ = deref2(typ).Underlying().(*types2.Struct).Field(ix).Type()
1749 recv := sel.Obj().(*types2.Func).Type().(*types2.Signature).Recv().Type()
1750 if w.Bool(isPtrTo(typ, recv)) { // need deref
1752 } else if w.Bool(isPtrTo(recv, typ)) { // need addr
1757 w.methodExpr(expr, typ, sel)
1760 case *syntax.IndexExpr:
1761 _ = w.p.typeOf(expr.Index) // ensure this is an index expression, not an instantiation
1763 xtyp := w.p.typeOf(expr.X)
1765 var keyType types2.Type
1766 if mapType, ok := types2.CoreType(xtyp).(*types2.Map); ok {
1767 keyType = mapType.Key()
1773 w.implicitConvExpr(keyType, expr.Index)
1778 case *syntax.SliceExpr:
1782 for _, n := range &expr.Index {
1786 case *syntax.AssertExpr:
1787 iface := w.p.typeOf(expr.X)
1792 w.exprType(iface, expr.Type)
1795 case *syntax.Operation:
1798 w.op(unOps[expr.Op])
1804 var commonType types2.Type
1806 case syntax.Shl, syntax.Shr:
1807 // ok: operands are allowed to have different types
1809 xtyp := w.p.typeOf(expr.X)
1810 ytyp := w.p.typeOf(expr.Y)
1812 case types2.AssignableTo(xtyp, ytyp):
1814 case types2.AssignableTo(ytyp, xtyp):
1817 w.p.fatalf(expr, "failed to find common type between %v and %v", xtyp, ytyp)
1821 w.Code(exprBinaryOp)
1822 w.op(binOps[expr.Op])
1823 w.implicitConvExpr(commonType, expr.X)
1825 w.implicitConvExpr(commonType, expr.Y)
1827 case *syntax.CallExpr:
1828 tv := w.p.typeAndValue(expr.Fun)
1830 assert(len(expr.ArgList) == 1)
1831 assert(!expr.HasDots)
1832 w.convertExpr(tv.Type, expr.ArgList[0], false)
1836 var rtype types2.Type
1838 switch obj, _ := lookupObj(w.p, expr.Fun); obj.Name() {
1840 assert(len(expr.ArgList) >= 1)
1841 assert(!expr.HasDots)
1845 w.exprType(nil, expr.ArgList[0])
1846 w.exprs(expr.ArgList[1:])
1848 typ := w.p.typeOf(expr)
1849 switch coreType := types2.CoreType(typ).(type) {
1851 w.p.fatalf(expr, "unexpected core type: %v", coreType)
1857 w.rtype(sliceElem(typ))
1863 assert(len(expr.ArgList) == 1)
1864 assert(!expr.HasDots)
1868 w.exprType(nil, expr.ArgList[0])
1872 rtype = sliceElem(w.p.typeOf(expr))
1874 typ := w.p.typeOf(expr.ArgList[0])
1875 if tuple, ok := typ.(*types2.Tuple); ok { // "copy(g())"
1876 typ = tuple.At(0).Type()
1878 rtype = sliceElem(typ)
1880 typ := w.p.typeOf(expr.ArgList[0])
1881 if tuple, ok := typ.(*types2.Tuple); ok { // "delete(g())"
1882 typ = tuple.At(0).Type()
1886 rtype = sliceElem(w.p.typeOf(expr))
1890 writeFunExpr := func() {
1891 fun := unparen(expr.Fun)
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)
1902 w.Bool(false) // not a method call (i.e., normal function call)
1904 if obj, inst := lookupObj(w.p, fun); w.Bool(obj != nil && inst.TypeArgs.Len() != 0) {
1905 obj := obj.(*types2.Func)
1908 w.funcInst(obj, inst.TypeArgs)
1915 sigType := types2.CoreType(tv.Type).(*types2.Signature)
1916 paramTypes := sigType.Params()
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()
1926 return paramTypes.At(i).Type()
1929 w.multiExpr(expr, paramType, expr.ArgList)
1930 w.Bool(expr.HasDots)
1937 func sliceElem(typ types2.Type) types2.Type {
1938 return types2.CoreType(typ).(*types2.Slice).Elem()
1941 func (w *writer) optExpr(expr syntax.Expr) {
1942 if w.Bool(expr != nil) {
1947 // recvExpr writes out expr.X, but handles any implicit addressing,
1948 // dereferencing, and field selections appropriate for the method
1950 func (w *writer) recvExpr(expr *syntax.SelectorExpr, sel *types2.Selection) types2.Type {
1951 index := sel.Index()
1952 implicits := index[:len(index)-1]
1957 w.Len(len(implicits))
1959 typ := w.p.typeOf(expr.X)
1960 for _, ix := range implicits {
1961 typ = deref2(typ).Underlying().(*types2.Struct).Field(ix).Type()
1965 recv := sel.Obj().(*types2.Func).Type().(*types2.Signature).Recv().Type()
1966 if w.Bool(isPtrTo(typ, recv)) { // needs deref
1968 } else if w.Bool(isPtrTo(recv, typ)) { // needs addr
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)
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))
1987 // Type arguments list is statically known; we can emit a static
1988 // call with a statically reference to the respective runtime
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)
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)
2014 w.Len(w.dict.typeParamMethodExprIdx(typeParamIdx, methodInfo))
2018 if isInterface(recv) != isInterface(sig.Recv().Type()) {
2019 w.p.fatalf(expr, "isInterface inconsistency: %v and %v", recv, sig.Recv().Type())
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)
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))
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
2049 w.Bool(false) // no dynamic subdictionary
2050 w.Bool(false) // no static dictionary
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)
2060 if len(exprs) == 1 {
2062 if tuple, ok := w.p.typeOf(expr).(*types2.Tuple); ok {
2063 assert(tuple.Len() > 1)
2064 w.Bool(true) // N:1 assignment
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.
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)
2078 if !types2.AssignableTo(src, dst) {
2079 w.p.fatalf(pos, "%v is not assignable to %v", src, dst)
2082 w.convRTTI(src, dst)
2089 w.Bool(false) // N:N assignment
2091 for i, expr := range exprs {
2092 w.implicitConvExpr(dstType(i), expr)
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)
2103 func (w *writer) convertExpr(dst types2.Type, expr syntax.Expr, implicit bool) {
2104 src := w.p.typeOf(expr)
2106 // Omit implicit no-op conversions.
2107 identical := dst == nil || types2.Identical(src, dst)
2108 if implicit && identical {
2113 if implicit && !types2.AssignableTo(src, dst) {
2114 w.p.fatalf(expr, "%v is not assignable to %v", src, dst)
2121 w.convRTTI(src, dst)
2122 w.Bool(isTypeParam(dst))
2127 func (w *writer) compLit(lit *syntax.CompositeLit) {
2128 typ := w.p.typeOf(lit)
2130 w.Sync(pkgbits.SyncCompLit)
2134 if ptr, ok := types2.CoreType(typ).(*types2.Pointer); ok {
2137 var keyType, elemType types2.Type
2138 var structType *types2.Struct
2139 switch typ0 := typ; typ := types2.CoreType(typ).(type) {
2141 w.p.fatalf(lit, "unexpected composite literal type: %v", typ)
2143 elemType = typ.Elem()
2146 keyType, elemType = typ.Key(), typ.Elem()
2148 elemType = typ.Elem()
2149 case *types2.Struct:
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 ':')
2160 i = fieldIndex(w.p.info, structType, kv.Key.(*syntax.Name))
2165 elemType = structType.Field(i).Type()
2168 if kv, ok := elem.(*syntax.KeyValueExpr); w.Bool(ok) {
2169 // use position of expr.Key rather than of elem (which has position of ':')
2171 w.implicitConvExpr(keyType, kv.Key)
2176 w.implicitConvExpr(elemType, elem)
2180 func (w *writer) funcLit(expr *syntax.FuncLit) {
2181 sig := w.p.typeOf(expr).(*types2.Signature)
2183 body, closureVars := w.p.bodyIdx(sig, expr.Body, w.dict)
2185 w.Sync(pkgbits.SyncFuncLit)
2189 w.Len(len(closureVars))
2190 for _, cv := range closureVars {
2192 w.useLocal(cv.pos, cv.var_)
2195 w.Reloc(pkgbits.RelocBody, body)
2198 type posVar struct {
2203 func (w *writer) exprList(expr syntax.Expr) {
2204 w.Sync(pkgbits.SyncExprList)
2205 w.exprs(unpackListExpr(expr))
2208 func (w *writer) exprs(exprs []syntax.Expr) {
2209 w.Sync(pkgbits.SyncExprs)
2211 for _, expr := range exprs {
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)
2221 info := w.p.typIdx(typ, w.dict)
2225 func (w *writer) rtypeInfo(info typeInfo) {
2226 w.Sync(pkgbits.SyncRType)
2228 if w.Bool(info.derived) {
2229 w.Len(w.dict.rtypeIdx(info))
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))
2244 func isUntyped(typ types2.Type) bool {
2245 basic, ok := typ.(*types2.Basic)
2246 return ok && basic.Info()&types2.IsUntyped != 0
2249 func isTuple(typ types2.Type) bool {
2250 _, ok := typ.(*types2.Tuple)
2254 func (w *writer) itab(typ, iface types2.Type) {
2255 typ = types2.Default(typ)
2256 iface = types2.Default(iface)
2258 typInfo := w.p.typIdx(typ, w.dict)
2259 ifaceInfo := w.p.typIdx(iface, w.dict)
2261 w.rtypeInfo(typInfo)
2262 w.rtypeInfo(ifaceInfo)
2263 if w.Bool(typInfo.derived || ifaceInfo.derived) {
2264 w.Len(w.dict.itabIdx(typInfo, ifaceInfo))
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)
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)
2278 tv := w.p.typeAndValue(typ)
2281 w.Sync(pkgbits.SyncExprType)
2284 if w.Bool(iface != nil && !iface.Underlying().(*types2.Interface).Empty()) {
2285 w.itab(tv.Type, iface)
2289 info := w.p.typIdx(tv.Type, w.dict)
2290 w.Bool(info.derived)
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
2302 base.Fatalf("%v is a type parameter", typ)
2305 _, ok := typ.Underlying().(*types2.Interface)
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.
2315 w.Sync(pkgbits.SyncOp)
2319 // @@@ Package initialization
2321 // Caution: This code is still clumsy, because toolstash -cmp is
2322 // particularly sensitive to it.
2324 type typeDeclGen struct {
2328 // Implicit type parameters in scope at this type declaration.
2329 implicits []*types2.TypeName
2332 type fileImports struct {
2333 importedEmbed, importedUnsafe bool
2336 // declCollector is a visitor type that collects compiler-needed
2337 // information about declarations that types2 doesn't track.
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 {
2347 implicits []*types2.TypeName
2350 func (c *declCollector) withTParams(obj types2.Object) *declCollector {
2351 tparams := objTypeParams(obj)
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())
2365 func (c *declCollector) Visit(n syntax.Node) syntax.Visitor {
2368 switch n := n.(type) {
2370 pw.checkPragmas(n.Pragma, ir.GoBuildPragma, false)
2372 case *syntax.ImportDecl:
2373 pw.checkPragmas(n.Pragma, 0, false)
2375 switch pkgNameOf(pw.info, n).Imported().Path() {
2377 c.file.importedEmbed = true
2379 c.file.importedUnsafe = true
2382 case *syntax.ConstDecl:
2383 pw.checkPragmas(n.Pragma, 0, false)
2385 case *syntax.FuncDecl:
2386 pw.checkPragmas(n.Pragma, funcPragmas, false)
2388 obj := pw.info.Defs[n.Name].(*types2.Func)
2389 pw.funDecls[obj] = n
2391 return c.withTParams(obj)
2393 case *syntax.TypeDecl:
2394 obj := pw.info.Defs[n.Name].(*types2.TypeName)
2395 d := typeDeclGen{TypeDecl: n, implicits: c.implicits}
2398 pw.checkPragmas(n.Pragma, 0, false)
2400 pw.checkPragmas(n.Pragma, 0, false)
2402 // Assign a unique ID to function-scoped defined types.
2409 pw.typDecls[obj] = d
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)
2417 case *syntax.VarDecl:
2418 pw.checkPragmas(n.Pragma, 0, true)
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)
2426 case *syntax.BlockStmt:
2429 copy.withinFunc = true
2437 func (pw *pkgWriter) collectDecls(noders []*noder) {
2439 for _, p := range noders {
2440 var file fileImports
2442 syntax.Walk(p.file, &declCollector{
2448 pw.cgoPragmas = append(pw.cgoPragmas, p.pragcgobuf...)
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\"")
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
2461 pw.errorf(l.pos, "duplicate //go:linkname for %s", l.local)
2465 if types.AllowsGoVersion(1, 18) {
2466 pw.errorf(l.pos, "//go:linkname must refer to declared function or variable")
2473 func (pw *pkgWriter) checkPragmas(p syntax.Pragma, allowed ir.PragmaFlag, embedOK bool) {
2477 pragma := p.(*pragmas)
2479 for _, pos := range pragma.Pos {
2480 if pos.Flag&^allowed != 0 {
2481 pw.errorf(pos.Pos, "misplaced compiler directive")
2486 for _, e := range pragma.Embeds {
2487 pw.errorf(e.Pos, "misplaced go:embed directive")
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)
2498 w.Sync(pkgbits.SyncDecls)
2499 for _, p := range noders {
2500 for _, decl := range p.file.DeclList {
2506 w.Sync(pkgbits.SyncEOF)
2509 func (w *writer) pkgDecl(decl syntax.Decl) {
2510 switch decl := decl.(type) {
2512 w.p.unexpected("declaration", decl)
2514 case *syntax.ImportDecl:
2516 case *syntax.ConstDecl:
2518 w.pkgObjs(decl.NameList...)
2520 case *syntax.FuncDecl:
2521 if decl.Name.Value == "_" {
2522 break // skip blank functions
2525 obj := w.p.info.Defs[decl.Name].(*types2.Func)
2526 sig := obj.Type().(*types2.Signature)
2528 if sig.RecvTypeParams() != nil || sig.TypeParams() != nil {
2529 break // skip generic functions
2532 if recv := sig.Recv(); recv != nil {
2534 w.typ(recvBase(recv))
2540 w.pkgObjs(decl.Name)
2542 case *syntax.TypeDecl:
2543 if len(decl.TParamList) != 0 {
2544 break // skip generic type decls
2547 if decl.Name.Value == "_" {
2548 break // skip blank type decls
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() {
2559 w.pkgObjs(decl.Name)
2561 case *syntax.VarDecl:
2564 w.pkgObjs(decl.NameList...)
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)
2573 var embeds []pragmaEmbed
2574 if p, ok := decl.Pragma.(*pragmas); ok {
2578 for _, embed := range embeds {
2580 w.Strings(embed.Patterns)
2585 func (w *writer) pkgObjs(names ...*syntax.Name) {
2586 w.Sync(pkgbits.SyncDeclNames)
2589 for _, name := range names {
2590 obj, ok := w.p.info.Defs[name]
2593 w.Sync(pkgbits.SyncDeclName)
2600 // hasImplicitTypeParams reports whether obj is a defined type with
2601 // implicit type parameters (e.g., declared within a generic function
2603 func (p *pkgWriter) hasImplicitTypeParams(obj *types2.TypeName) bool {
2604 if obj.Pkg() == p.curpkg {
2605 decl, ok := p.typDecls[obj]
2607 if len(decl.implicits) != 0 {
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()
2622 // isGlobal reports whether obj was declared at package scope.
2624 // Caveat: blank objects are not declared.
2625 func isGlobal(obj types2.Object) bool {
2626 return obj.Parent() == obj.Pkg().Scope()
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)
2636 tv := p.typeAndValue(args[0])
2638 return // normal index expression
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
2653 if name, ok := expr.(*syntax.Name); ok {
2654 obj = p.info.Uses[name]
2655 inst = p.info.Instances[name]
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)
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)
2677 // recvBase returns the base type for the given receiver parameter.
2678 func recvBase(recv *types2.Var) *types2.Named {
2680 if ptr, ok := typ.(*types2.Pointer); ok {
2683 return typ.(*types2.Named)
2686 // namesAsExpr returns a list of names as a syntax.Expr.
2687 func namesAsExpr(names []*syntax.Name) syntax.Expr {
2688 if len(names) == 1 {
2692 exprs := make([]syntax.Expr, len(names))
2693 for i, name := range names {
2696 return &syntax.ListExpr{ElemList: exprs}
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)
2703 for i := 0; i < str.NumFields(); i++ {
2704 if str.Field(i) == field {
2709 panic(fmt.Sprintf("%s: %v is not a field of %v", key.Pos(), field, str))
2712 // objTypeParams returns the type parameters on the given object.
2713 func objTypeParams(obj types2.Object) *types2.TypeParamList {
2714 switch obj := obj.(type) {
2716 sig := obj.Type().(*types2.Signature)
2717 if sig.Recv() != nil {
2718 return sig.RecvTypeParams()
2720 return sig.TypeParams()
2721 case *types2.TypeName:
2723 return obj.Type().(*types2.Named).TypeParams()
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)
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())
2738 return typ.Obj(), typ.TypeArgs()
2741 func asPragmaFlag(p syntax.Pragma) ir.PragmaFlag {
2745 return p.(*pragmas).Flag
2748 func asWasmImport(p syntax.Pragma) *WasmImport {
2752 return p.(*pragmas).WasmImport
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)