1 // Copyright 2018 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.
5 // Indexed package export.
7 // The indexed export data format is an evolution of the previous
8 // binary export data format. Its chief contribution is introducing an
9 // index table, which allows efficient random access of individual
10 // declarations and inline function bodies. In turn, this allows
11 // avoiding unnecessary work for compilation units that import large
15 // The top-level data format is structured as:
24 // Strings [StringSize]byte
25 // Data [DataSize]byte
27 // MainIndex []struct{
38 // Fingerprint [8]byte
40 // uvarint means a uint64 written out using uvarint encoding.
42 // []T means a uvarint followed by that many T objects. In other
48 // stringOff means a uvarint that indicates an offset within the
49 // Strings section. At that offset is another uvarint, followed by
50 // that many bytes, which form the string value.
52 // declOff means a uvarint that indicates an offset within the Data
53 // section where the associated declaration can be found.
56 // There are five kinds of declarations, distinguished by their first
66 // Tag byte // 'F' or 'G'
68 // TypeParams []typeOff // only present if Tag == 'G'
69 // Signature Signature
72 // type Const struct {
79 // Tag byte // 'T' or 'U'
81 // TypeParams []typeOff // only present if Tag == 'U'
84 // Methods []struct{ // omitted if Underlying is an interface type
88 // Signature Signature
92 // type Alias struct {
98 // // "Automatic" declaration of each typeparam
99 // type TypeParam struct {
103 // Constraint typeOff
106 // typeOff means a uvarint that either indicates a predeclared type,
107 // or an offset into the Data section. If the uvarint is less than
108 // predeclReserved, then it indicates the index into the predeclared
109 // types list (see predeclared in bexport.go for order). Otherwise,
110 // subtracting predeclReserved yields the offset of a type descriptor.
112 // Value means a type, kind, and type-specific value. See
113 // (*exportWriter).value for details.
116 // There are twelve kinds of type descriptors, distinguished by an itag:
118 // type DefinedType struct {
119 // Tag itag // definedType
124 // type PointerType struct {
125 // Tag itag // pointerType
129 // type SliceType struct {
130 // Tag itag // sliceType
134 // type ArrayType struct {
135 // Tag itag // arrayType
140 // type ChanType struct {
141 // Tag itag // chanType
142 // Dir uint64 // 1 RecvOnly; 2 SendOnly; 3 SendRecv
146 // type MapType struct {
147 // Tag itag // mapType
152 // type FuncType struct {
153 // Tag itag // signatureType
155 // Signature Signature
158 // type StructType struct {
159 // Tag itag // structType
170 // type InterfaceType struct {
171 // Tag itag // interfaceType
173 // Embeddeds []struct {
177 // Methods []struct {
180 // Signature Signature
184 // // Reference to a type param declaration
185 // type TypeParamType struct {
186 // Tag itag // typeParamType
191 // // Instantiation of a generic type (like List[T2] or List[int])
192 // type InstanceType struct {
193 // Tag itag // instanceType
195 // TypeArgs []typeOff
199 // type UnionType struct {
200 // Tag itag // interfaceType
209 // type Signature struct {
212 // Variadic bool // omitted if Results is empty
215 // type Param struct {
222 // Pos encodes a file:line:column triple, incorporating a simple delta
223 // encoding scheme within a data object. See exportWriter.pos for
227 // Compiler-specific details.
229 // cmd/compile writes out a second index for inline bodies and also
230 // appends additional compiler-specific details after declarations.
231 // Third-party tools are not expected to depend on these details and
232 // they're expected to change much more rapidly, so they're omitted
233 // here. See exportWriter's varExt/funcExt/etc methods for details.
248 "cmd/compile/internal/base"
249 "cmd/compile/internal/ir"
250 "cmd/compile/internal/types"
252 "cmd/internal/notsha256"
256 // Current indexed export format version. Increase with each format change.
257 // 0: Go1.11 encoding
258 // 1: added column details to Pos
259 // 2: added information for generic function/types. The export of non-generic
260 // functions/types remains largely backward-compatible. Breaking changes include:
261 // - a 'kind' byte is added to constant values
263 iexportVersionGo1_11 = 0
264 iexportVersionPosCol = 1
265 iexportVersionGenerics = 2
266 iexportVersionGo1_18 = 2
268 iexportVersionCurrent = 2
271 // predeclReserved is the number of type offsets reserved for types
272 // implicitly declared in the universe block.
273 const predeclReserved = 32
275 // An itag distinguishes the kind of type that was written into the
276 // indexed export format.
281 definedType itag = iota
291 instanceType // Instantiation of a generic type
297 magic = 0x6742937dc293105
300 // WriteExports writes the indexed export format to out. If extensions
301 // is true, then the compiler-only extensions are included.
302 func WriteExports(out io.Writer, extensions bool) {
304 // If we're exporting inline bodies, invoke the crawler to mark
305 // which bodies to include.
306 crawlExports(Target.Exports)
310 allPkgs: map[*types.Pkg]bool{},
311 stringIndex: map[string]uint64{},
312 declIndex: map[*types.Sym]uint64{},
313 inlineIndex: map[*types.Sym]uint64{},
314 typIndex: map[*types.Type]uint64{},
315 extensions: extensions,
318 for i, pt := range predeclared() {
319 p.typIndex[pt] = uint64(i)
321 if len(p.typIndex) > predeclReserved {
322 base.Fatalf("too many predeclared types: %d > %d", len(p.typIndex), predeclReserved)
325 // Initialize work queue with exported declarations.
326 for _, n := range Target.Exports {
330 // Loop until no more work. We use a queue because while
331 // writing out inline bodies, we may discover additional
332 // declarations that are needed.
333 for !p.declTodo.Empty() {
334 p.doDecl(p.declTodo.PopLeft())
337 // Append indices to data0 section.
338 dataLen := uint64(p.data0.Len())
340 w.writeIndex(p.declIndex, true)
341 w.writeIndex(p.inlineIndex, false)
344 if *base.Flag.LowerV {
345 fmt.Printf("export: hdr strings %v, data %v, index %v\n", p.strings.Len(), dataLen, p.data0.Len())
351 hdr.uint64(iexportVersionCurrent)
352 hdr.uint64(uint64(p.strings.Len()))
357 wr := io.MultiWriter(out, h)
359 io.Copy(wr, &p.strings)
360 io.Copy(wr, &p.data0)
362 // Add fingerprint (used by linker object file).
363 // Attach this to the end, so tools (e.g. gcimporter) don't care.
364 copy(base.Ctxt.Fingerprint[:], h.Sum(nil)[:])
365 out.Write(base.Ctxt.Fingerprint[:])
368 // writeIndex writes out a symbol index. mainIndex indicates whether
369 // we're writing out the main index, which is also read by
370 // non-compiler tools and includes a complete package description
371 // (i.e., name and height).
372 func (w *exportWriter) writeIndex(index map[*types.Sym]uint64, mainIndex bool) {
373 // Build a map from packages to symbols from that package.
374 pkgSyms := map[*types.Pkg][]*types.Sym{}
376 // For the main index, make sure to include every package that
377 // we reference, even if we're not exporting (or reexporting)
378 // any symbols from it.
380 pkgSyms[types.LocalPkg] = nil
381 for pkg := range w.p.allPkgs {
386 // Group symbols by package.
387 for sym := range index {
388 pkgSyms[sym.Pkg] = append(pkgSyms[sym.Pkg], sym)
391 // Sort packages by path.
392 var pkgs []*types.Pkg
393 for pkg := range pkgSyms {
394 pkgs = append(pkgs, pkg)
396 sort.Slice(pkgs, func(i, j int) bool {
397 return pkgs[i].Path < pkgs[j].Path
400 w.uint64(uint64(len(pkgs)))
401 for _, pkg := range pkgs {
405 w.uint64(uint64(pkg.Height))
408 // Sort symbols within a package by name.
410 sort.Slice(syms, func(i, j int) bool {
411 return syms[i].Name < syms[j].Name
414 w.uint64(uint64(len(syms)))
415 for _, sym := range syms {
422 type iexporter struct {
423 // allPkgs tracks all packages that have been referenced by
424 // the export data, so we can ensure to include them in the
426 allPkgs map[*types.Pkg]bool
428 declTodo ir.NameQueue
431 stringIndex map[string]uint64
434 declIndex map[*types.Sym]uint64
435 inlineIndex map[*types.Sym]uint64
436 typIndex map[*types.Type]uint64
441 // stringOff returns the offset of s within the string section.
442 // If not already present, it's added to the end.
443 func (p *iexporter) stringOff(s string) uint64 {
444 off, ok := p.stringIndex[s]
446 off = uint64(p.strings.Len())
447 p.stringIndex[s] = off
449 if *base.Flag.LowerV {
450 fmt.Printf("export: str %v %.40q\n", off, s)
453 p.strings.uint64(uint64(len(s)))
454 p.strings.WriteString(s)
459 // pushDecl adds n to the declaration work queue, if not already present.
460 func (p *iexporter) pushDecl(n *ir.Name) {
461 if n.Sym() == nil || n.Sym().Def != n && n.Op() != ir.OTYPE {
462 base.Fatalf("weird Sym: %v, %v", n, n.Sym())
465 // Don't export predeclared declarations.
466 if n.Sym().Pkg == types.BuiltinPkg || n.Sym().Pkg == types.UnsafePkg {
470 if _, ok := p.declIndex[n.Sym()]; ok {
474 p.declIndex[n.Sym()] = ^uint64(0) // mark n present in work queue
475 p.declTodo.PushRight(n)
478 // exportWriter handles writing out individual data section chunks.
479 type exportWriter struct {
488 // dclIndex maps function-scoped declarations to an int used to refer to
489 // them later in the function. For local variables/params, the int is
490 // non-negative and in order of the appearance in the Func's Dcl list. For
491 // closure variables, the index is negative starting at -2.
492 dclIndex map[*ir.Name]int
494 maxClosureVarIndex int
497 func (p *iexporter) doDecl(n *ir.Name) {
499 w.setPkg(n.Sym().Pkg, false)
515 base.Fatalf("unexpected method: %v", n)
519 if n.Type().TParams().NumFields() == 0 {
525 // The tparam list of the function type is the
526 // declaration of the type params. So, write out the type
527 // params right now. Then those type params will be
528 // referenced via their type offset (via typOff) in all
529 // other places in the signature and function that they
531 if n.Type().TParams().NumFields() > 0 {
532 w.tparamList(n.Type().TParams().FieldSlice())
534 w.signature(n.Type())
540 base.Fatalf("unexpected class: %v, %v", n, n.Class)
544 // TODO(mdempsky): Extend check to all declarations.
545 if n.Typecheck() == 0 {
546 base.FatalfAt(n.Pos(), "missed typecheck: %v", n)
552 w.value(n.Type(), n.Val())
558 if n.Type().IsTypeParam() && n.Type().Underlying() == n.Type() {
559 // Even though it has local scope, a typeparam requires a
560 // declaration via its package and unique name, because it
561 // may be referenced within its type bound during its own
564 // A typeparam has a name, and has a type bound rather
565 // than an underlying type.
567 if iexportVersionCurrent >= iexportVersionGo1_18 {
568 implicit := n.Type().Bound().IsImplicit()
571 w.typ(n.Type().Bound())
584 if len(n.Type().RParams()) == 0 {
591 if len(n.Type().RParams()) > 0 {
592 // Export type parameters, if any, needed for this type
593 w.typeList(n.Type().RParams())
596 underlying := n.Type().Underlying()
597 if underlying == types.ErrorType.Underlying() {
598 // For "type T error", use error as the
599 // underlying type instead of error's own
600 // underlying anonymous interface. This
601 // ensures consistency with how importers may
602 // declare error (e.g., go/types uses nil Pkg
603 // for predeclared objects).
604 underlying = types.ErrorType
606 if underlying == types.ComparableType.Underlying() {
607 // Do same for ComparableType as for ErrorType.
608 underlying = types.ComparableType
610 if underlying == types.AnyType.Underlying() {
611 // Do same for AnyType as for ErrorType.
612 underlying = types.AnyType
624 methods := t.Methods().Slice()
625 w.uint64(uint64(len(methods)))
626 for _, m := range methods {
629 w.param(m.Type.Recv())
635 for _, m := range methods {
641 base.Fatalf("unexpected node: %v", n)
644 w.finish("dcl", p.declIndex, n.Sym())
647 func (w *exportWriter) tag(tag byte) {
648 w.data.WriteByte(tag)
651 func (w *exportWriter) finish(what string, index map[*types.Sym]uint64, sym *types.Sym) {
653 if *base.Flag.LowerV {
654 fmt.Printf("export: %v %v %v\n", what, off, sym)
659 func (p *iexporter) doInline(f *ir.Name) {
661 w.setPkg(fnpkg(f), false)
663 w.dclIndex = make(map[*ir.Name]int, len(f.Func.Inl.Dcl))
666 w.finish("inl", p.inlineIndex, f.Sym())
669 func (w *exportWriter) pos(pos src.XPos) {
670 p := base.Ctxt.PosTable.Pos(pos)
671 file := p.Base().AbsFilename()
672 line := int64(p.RelLine())
673 column := int64(p.RelCol())
675 // Encode position relative to the last position: column
676 // delta, then line delta, then file name. We reserve the
677 // bottom bit of the column and line deltas to encode whether
678 // the remaining fields are present.
680 // Note: Because data objects may be read out of order (or not
681 // at all), we can only apply delta encoding within a single
682 // object. This is handled implicitly by tracking prevFile,
683 // prevLine, and prevColumn as fields of exportWriter.
685 deltaColumn := (column - w.prevColumn) << 1
686 deltaLine := (line - w.prevLine) << 1
688 if file != w.prevFile {
696 if deltaColumn&1 != 0 {
698 if deltaLine&1 != 0 {
705 w.prevColumn = column
708 func (w *exportWriter) pkg(pkg *types.Pkg) {
709 // TODO(mdempsky): Add flag to types.Pkg to mark pseudo-packages.
710 if pkg == ir.Pkgs.Go {
711 base.Fatalf("export of pseudo-package: %q", pkg.Path)
714 // Ensure any referenced packages are declared in the main index.
715 w.p.allPkgs[pkg] = true
720 func (w *exportWriter) qualifiedIdent(n *ir.Name) {
721 // Ensure any referenced declarations are written out too.
729 const blankMarker = "$"
731 // TparamExportName creates a unique name for type param in a method or a generic
732 // type, using the specified unique prefix and the index of the type param. The index
733 // is only used if the type param is blank, in which case the blank is replace by
734 // "$<index>". A unique name is needed for later substitution in the compiler and
735 // export/import that keeps blank type params associated with the correct constraint.
736 func TparamExportName(prefix string, name string, index int) string {
738 name = blankMarker + strconv.Itoa(index)
740 return prefix + "." + name
743 // TparamName returns the real name of a type parameter, after stripping its
744 // qualifying prefix and reverting blank-name encoding. See TparamExportName
746 func TparamName(exportName string) string {
747 // Remove the "path" from the type param name that makes it unique.
748 ix := strings.LastIndex(exportName, ".")
752 name := exportName[ix+1:]
753 if strings.HasPrefix(name, blankMarker) {
759 func (w *exportWriter) selector(s *types.Sym) {
760 if w.currPkg == nil {
761 base.Fatalf("missing currPkg")
764 // If the selector being written is unexported, it comes with a package qualifier.
765 // If the selector being written is exported, it is not package-qualified.
766 // See the spec: https://golang.org/ref/spec#Uniqueness_of_identifiers
767 // As an optimization, we don't actually write the package every time - instead we
768 // call setPkg before a group of selectors (all of which must have the same package qualifier).
770 if types.IsExported(s.Name) {
774 base.Fatalf("package mismatch in selector: %v in package %q, but want %q", s, s.Pkg.Path, pkg.Path)
780 func (w *exportWriter) typ(t *types.Type) {
781 w.data.uint64(w.p.typOff(t))
784 // The "exotic" functions in this section encode a wider range of
785 // items than the standard encoding functions above. These include
786 // types that do not appear in declarations, only in code, such as
787 // method types. These methods need to be separate from the standard
788 // encoding functions because we don't want to modify the encoding
789 // generated by the standard functions (because that exported
790 // information is read by tools besides the compiler).
792 // exoticType exports a type to the writer.
793 func (w *exportWriter) exoticType(t *types.Type) {
796 // Calls-as-statements have no type.
797 w.data.uint64(exoticTypeNil)
798 case t.IsStruct() && t.StructType().Funarg != types.FunargNone:
799 // These are weird structs for representing tuples of types returned
800 // by multi-return functions.
801 // They don't fit the standard struct type mold. For instance,
802 // they don't have any package info.
803 w.data.uint64(exoticTypeTuple)
804 w.uint64(uint64(t.StructType().Funarg))
805 w.uint64(uint64(t.NumFields()))
806 for _, f := range t.FieldSlice() {
811 } else if s.Pkg == nil {
812 w.uint64(exoticTypeSymNoPkg)
815 w.uint64(exoticTypeSymWithPkg)
820 if f.Embedded != 0 || f.Note != "" {
821 panic("extra info in funarg struct field")
824 case t.Kind() == types.TFUNC && t.Recv() != nil:
825 w.data.uint64(exoticTypeRecv)
826 // interface method types have a fake receiver type.
827 isFakeRecv := t.Recv().Type == types.FakeRecvType()
830 w.exoticParam(t.Recv())
836 w.data.uint64(exoticTypeRegular)
848 exoticTypeSymNil = iota
853 // Export a selector, but one whose package may not match
854 // the package being compiled. This is a separate function
855 // because the standard selector() serialization format is fixed
856 // by the go/types reader. This one can only be used during
857 // inline/generic body exporting.
858 func (w *exportWriter) exoticSelector(s *types.Sym) {
860 if types.IsExported(s.Name) {
873 func (w *exportWriter) exoticSignature(t *types.Type) {
874 hasPkg := t.Pkg() != nil
879 w.exoticParamList(t.Params().FieldSlice())
880 w.exoticParamList(t.Results().FieldSlice())
883 func (w *exportWriter) exoticParamList(fs []*types.Field) {
884 w.uint64(uint64(len(fs)))
885 for _, f := range fs {
890 func (w *exportWriter) exoticParam(f *types.Field) {
893 w.uint64(uint64(f.Offset))
898 func (w *exportWriter) exoticField(f *types.Field) {
901 w.uint64(uint64(f.Offset))
906 func (w *exportWriter) exoticSym(s *types.Sym) {
912 base.Fatalf("empty symbol name")
915 if !types.IsExported(s.Name) {
920 func (p *iexporter) newWriter() *exportWriter {
921 return &exportWriter{p: p}
924 func (w *exportWriter) flush() uint64 {
925 off := uint64(w.p.data0.Len())
926 io.Copy(&w.p.data0, &w.data)
930 func (p *iexporter) typOff(t *types.Type) uint64 {
931 off, ok := p.typIndex[t]
936 if *base.Flag.LowerV {
937 fmt.Printf("export: typ %v %v\n", rawOff, t)
939 off = predeclReserved + rawOff
945 func (w *exportWriter) startType(k itag) {
946 w.data.uint64(uint64(k))
949 func (w *exportWriter) doTyp(t *types.Type) {
951 if s != nil && t.OrigType() != nil {
952 // This is an instantiated type - could be a re-instantiation like
953 // Value[T2] or a full instantiation like Value[int].
954 if strings.Index(s.Name, "[") < 0 {
955 base.Fatalf("incorrect name for instantiated type")
957 w.startType(instanceType)
959 // Export the type arguments for the instantiated type. The
960 // instantiated type could be in a method header (e.g. "func (v
961 // *Value[T2]) set (...) { ... }"), so the type args are "new"
962 // typeparams. Or the instantiated type could be in a
963 // function/method body, so the type args are either concrete
964 // types or existing typeparams from the function/method header.
965 w.typeList(t.RParams())
966 // Export a reference to the base type.
967 baseType := t.OrigType()
972 // The 't.Underlying() == t' check is to confirm this is a base typeparam
973 // type, rather than a defined type with typeparam underlying type, like:
974 // type orderedAbs[T any] T
975 if t.IsTypeParam() && t.Underlying() == t {
976 if s.Pkg == types.BuiltinPkg || s.Pkg == types.UnsafePkg {
977 base.Fatalf("builtin type missing from typIndex: %v", t)
979 // Write out the first use of a type param as a qualified ident.
980 // This will force a "declaration" of the type param.
981 w.startType(typeParamType)
982 w.qualifiedIdent(t.Obj().(*ir.Name))
987 if s.Pkg == types.BuiltinPkg || s.Pkg == types.UnsafePkg {
988 base.Fatalf("builtin type missing from typIndex: %v", t)
991 w.startType(definedType)
992 w.qualifiedIdent(t.Obj().(*ir.Name))
998 w.startType(pointerType)
1002 w.startType(sliceType)
1006 w.startType(arrayType)
1007 w.uint64(uint64(t.NumElem()))
1011 w.startType(chanType)
1012 w.uint64(uint64(t.ChanDir()))
1016 w.startType(mapType)
1021 w.startType(signatureType)
1022 w.setPkg(t.Pkg(), true)
1026 w.startType(structType)
1027 w.setPkg(t.Pkg(), true)
1029 w.uint64(uint64(t.NumFields()))
1030 for _, f := range t.FieldSlice() {
1034 w.bool(f.Embedded != 0)
1039 var embeddeds, methods []*types.Field
1040 for _, m := range t.Methods().Slice() {
1042 methods = append(methods, m)
1044 embeddeds = append(embeddeds, m)
1048 w.startType(interfaceType)
1049 w.setPkg(t.Pkg(), true)
1051 w.uint64(uint64(len(embeddeds)))
1052 for _, f := range embeddeds {
1057 w.uint64(uint64(len(methods)))
1058 for _, f := range methods {
1065 // TODO(danscales): possibly put out the tilde bools in more
1067 w.startType(unionType)
1069 w.uint64(uint64(nt))
1070 for i := 0; i < nt; i++ {
1071 typ, tilde := t.Term(i)
1077 base.Fatalf("unexpected type: %v", t)
1081 func (w *exportWriter) setPkg(pkg *types.Pkg, write bool) {
1082 if pkg == types.NoPkg {
1083 base.Fatalf("missing pkg")
1093 func (w *exportWriter) signature(t *types.Type) {
1094 w.paramList(t.Params().FieldSlice())
1095 w.paramList(t.Results().FieldSlice())
1096 if n := t.Params().NumFields(); n > 0 {
1097 w.bool(t.Params().Field(n - 1).IsDDD())
1101 func (w *exportWriter) typeList(ts []*types.Type) {
1102 w.uint64(uint64(len(ts)))
1103 for _, rparam := range ts {
1108 func (w *exportWriter) tparamList(fs []*types.Field) {
1109 w.uint64(uint64(len(fs)))
1110 for _, f := range fs {
1111 if !f.Type.IsTypeParam() {
1112 base.Fatalf("unexpected non-typeparam")
1118 func (w *exportWriter) paramList(fs []*types.Field) {
1119 w.uint64(uint64(len(fs)))
1120 for _, f := range fs {
1125 func (w *exportWriter) param(f *types.Field) {
1127 w.localIdent(types.OrigSym(f.Sym))
1131 func constTypeOf(typ *types.Type) constant.Kind {
1133 case types.UntypedInt, types.UntypedRune:
1135 case types.UntypedFloat:
1136 return constant.Float
1137 case types.UntypedComplex:
1138 return constant.Complex
1143 return constant.Bool
1145 return constant.String
1146 case types.TINT, types.TINT8, types.TINT16, types.TINT32, types.TINT64,
1147 types.TUINT, types.TUINT8, types.TUINT16, types.TUINT32, types.TUINT64, types.TUINTPTR:
1149 case types.TFLOAT32, types.TFLOAT64:
1150 return constant.Float
1151 case types.TCOMPLEX64, types.TCOMPLEX128:
1152 return constant.Complex
1155 base.Fatalf("unexpected constant type: %v", typ)
1159 func (w *exportWriter) value(typ *types.Type, v constant.Value) {
1162 if iexportVersionCurrent >= iexportVersionGo1_18 {
1163 w.int64(int64(v.Kind()))
1166 var kind constant.Kind
1167 var valType *types.Type
1169 if typ.IsTypeParam() {
1171 if iexportVersionCurrent < iexportVersionGo1_18 {
1172 // A constant will have a TYPEPARAM type if it appears in a place
1173 // where it must match that typeparam type (e.g. in a binary
1174 // operation with a variable of that typeparam type). If so, then
1175 // we must write out its actual constant kind as well, so its
1176 // constant val can be read in properly during import.
1177 w.int64(int64(kind))
1182 valType = types.Types[types.TINT64]
1183 case constant.Float:
1184 valType = types.Types[types.TFLOAT64]
1185 case constant.Complex:
1186 valType = types.Types[types.TCOMPLEX128]
1189 ir.AssertValidTypeForConst(typ, v)
1190 kind = constTypeOf(typ)
1194 // Each type has only one admissible constant representation, so we could
1195 // type switch directly on v.Kind() here. However, switching on the type
1196 // (in the non-typeparam case) increases symmetry with import logic and
1197 // provides a useful consistency check.
1201 w.bool(constant.BoolVal(v))
1202 case constant.String:
1203 w.string(constant.StringVal(v))
1206 case constant.Float:
1207 w.mpfloat(v, valType)
1208 case constant.Complex:
1209 w.mpfloat(constant.Real(v), valType)
1210 w.mpfloat(constant.Imag(v), valType)
1214 func intSize(typ *types.Type) (signed bool, maxBytes uint) {
1215 if typ.IsUntyped() {
1216 return true, ir.ConstPrec / 8
1220 case types.TFLOAT32, types.TCOMPLEX64:
1222 case types.TFLOAT64, types.TCOMPLEX128:
1226 signed = typ.IsSigned()
1227 maxBytes = uint(typ.Size())
1229 // The go/types API doesn't expose sizes to importers, so they
1230 // don't know how big these types are.
1232 case types.TINT, types.TUINT, types.TUINTPTR:
1239 // mpint exports a multi-precision integer.
1241 // For unsigned types, small values are written out as a single
1242 // byte. Larger values are written out as a length-prefixed big-endian
1243 // byte string, where the length prefix is encoded as its complement.
1244 // For example, bytes 0, 1, and 2 directly represent the integer
1245 // values 0, 1, and 2; while bytes 255, 254, and 253 indicate a 1-,
1246 // 2-, and 3-byte big-endian string follow.
1248 // Encoding for signed types use the same general approach as for
1249 // unsigned types, except small values use zig-zag encoding and the
1250 // bottom bit of length prefix byte for large values is reserved as a
1253 // The exact boundary between small and large encodings varies
1254 // according to the maximum number of bytes needed to encode a value
1255 // of type typ. As a special case, 8-bit types are always encoded as a
1257 func (w *exportWriter) mpint(x constant.Value, typ *types.Type) {
1258 signed, maxBytes := intSize(typ)
1260 negative := constant.Sign(x) < 0
1261 if !signed && negative {
1262 base.Fatalf("negative unsigned integer; type %v, value %v", typ, x)
1265 b := constant.Bytes(x) // little endian
1266 for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
1267 b[i], b[j] = b[j], b[i]
1270 if len(b) > 0 && b[0] == 0 {
1271 base.Fatalf("leading zeros")
1273 if uint(len(b)) > maxBytes {
1274 base.Fatalf("bad mpint length: %d > %d (type %v, value %v)", len(b), maxBytes, typ, x)
1277 maxSmall := 256 - maxBytes
1279 maxSmall = 256 - 2*maxBytes
1285 // Check if x can use small value encoding.
1298 w.data.WriteByte(byte(ux))
1303 n := 256 - uint(len(b))
1305 n = 256 - 2*uint(len(b))
1310 if n < maxSmall || n >= 256 {
1311 base.Fatalf("encoding mistake: %d, %v, %v => %d", len(b), signed, negative, n)
1314 w.data.WriteByte(byte(n))
1318 // mpfloat exports a multi-precision floating point number.
1320 // The number's value is decomposed into mantissa × 2**exponent, where
1321 // mantissa is an integer. The value is written out as mantissa (as a
1322 // multi-precision integer) and then the exponent, except exponent is
1323 // omitted if mantissa is zero.
1324 func (w *exportWriter) mpfloat(v constant.Value, typ *types.Type) {
1327 base.Fatalf("infinite constant")
1330 // Break into f = mant × 2**exp, with 0.5 <= mant < 1.
1332 exp := int64(f.MantExp(&mant))
1334 // Scale so that mant is an integer.
1335 prec := mant.MinPrec()
1336 mant.SetMantExp(&mant, int(prec))
1339 manti, acc := mant.Int(nil)
1340 if acc != big.Exact {
1341 base.Fatalf("mantissa scaling failed for %f (%s)", f, acc)
1343 w.mpint(constant.Make(manti), typ)
1344 if manti.Sign() != 0 {
1349 func (w *exportWriter) mprat(v constant.Value) {
1350 r, ok := constant.Val(v).(*big.Rat)
1354 // TODO(mdempsky): Come up with a more efficient binary
1355 // encoding before bumping iexportVersion to expose to
1357 w.string(r.String())
1360 func (w *exportWriter) bool(b bool) bool {
1369 func (w *exportWriter) int64(x int64) { w.data.int64(x) }
1370 func (w *exportWriter) uint64(x uint64) { w.data.uint64(x) }
1371 func (w *exportWriter) string(s string) { w.uint64(w.p.stringOff(s)) }
1373 // Compiler-specific extensions.
1375 func (w *exportWriter) constExt(n *ir.Name) {
1376 // Internally, we now represent untyped float and complex
1377 // constants with infinite-precision rational numbers using
1378 // go/constant, but the "public" export data format known to
1379 // gcimporter only supports 512-bit floating point constants.
1380 // In case rationals turn out to be a bad idea and we want to
1381 // switch back to fixed-precision constants, for now we
1382 // continue writing out the 512-bit truncation in the public
1383 // data section, and write the exact, rational constant in the
1384 // compiler's extension data. Also, we only need to worry
1385 // about exporting rationals for declared constants, because
1386 // constants that appear in an expression will already have
1387 // been coerced to a concrete, fixed-precision type.
1389 // Eventually, assuming we stick with using rationals, we
1390 // should bump iexportVersion to support rationals, and do the
1391 // whole gcimporter update song-and-dance.
1393 // TODO(mdempsky): Prepare vocals for that.
1396 case types.UntypedFloat:
1398 case types.UntypedComplex:
1400 w.mprat(constant.Real(v))
1401 w.mprat(constant.Imag(v))
1405 func (w *exportWriter) varExt(n *ir.Name) {
1410 func (w *exportWriter) funcExt(n *ir.Name) {
1414 // Record definition ABI so cross-ABI calls can be direct.
1415 // This is important for the performance of calling some
1416 // common functions implemented in assembly (e.g., bytealg).
1417 w.uint64(uint64(n.Func.ABI))
1419 w.uint64(uint64(n.Func.Pragma))
1422 for _, fs := range &types.RecvsParams {
1423 for _, f := range fs(n.Type()).FieldSlice() {
1428 // Write out inline body or body of a generic function/method.
1429 if n.Type().HasTParam() && n.Func.Body != nil && n.Func.Inl == nil {
1430 base.FatalfAt(n.Pos(), "generic function is not marked inlineable")
1432 if n.Func.Inl != nil {
1433 w.uint64(1 + uint64(n.Func.Inl.Cost))
1434 w.bool(n.Func.Inl.CanDelayResults)
1435 if n.Func.ExportInline() || n.Type().HasTParam() {
1436 if n.Type().HasTParam() {
1437 // If this generic function/method is from another
1438 // package, but we didn't use for instantiation in
1439 // this package, we may not yet have imported it.
1440 ImportedBody(n.Func)
1445 // Endlineno for inlined function.
1446 w.pos(n.Func.Endlineno)
1452 func (w *exportWriter) methExt(m *types.Field) {
1453 w.bool(m.Nointerface())
1454 w.funcExt(m.Nname.(*ir.Name))
1457 func (w *exportWriter) linkname(s *types.Sym) {
1458 w.string(s.Linkname)
1461 func (w *exportWriter) symIdx(s *types.Sym) {
1463 if lsym.PkgIdx > goobj.PkgIdxSelf || (lsym.PkgIdx == goobj.PkgIdxInvalid && !lsym.Indexed()) || s.Linkname != "" {
1464 // Don't export index for non-package symbols, linkname'd symbols,
1465 // and symbols without an index. They can only be referenced by
1469 // For a defined symbol, export its index.
1470 // For re-exporting an imported symbol, pass its index through.
1471 w.int64(int64(lsym.SymIdx))
1475 func (w *exportWriter) typeExt(t *types.Type) {
1476 // Export whether this type is marked notinheap.
1477 w.bool(t.NotInHeap())
1478 // For type T, export the index of type descriptor symbols of T and *T.
1479 if i, ok := typeSymIdx[t]; ok {
1484 w.symIdx(types.TypeSym(t))
1485 w.symIdx(types.TypeSym(t.PtrTo()))
1490 func (w *exportWriter) writeNames(dcl []*ir.Name) {
1491 w.int64(int64(len(dcl)))
1492 for i, n := range dcl {
1494 w.localIdent(n.Sym())
1496 w.dclIndex[n] = w.maxDclIndex + i
1498 w.maxDclIndex += len(dcl)
1501 func (w *exportWriter) funcBody(fn *ir.Func) {
1502 //fmt.Printf("Exporting %s\n", fn.Nname.Sym().Name)
1503 w.writeNames(fn.Inl.Dcl)
1505 w.stmtList(fn.Inl.Body)
1508 func (w *exportWriter) stmtList(list []ir.Node) {
1509 for _, n := range list {
1515 func (w *exportWriter) node(n ir.Node) {
1516 if ir.OpPrec[n.Op()] < 0 {
1523 func isNonEmptyAssign(n ir.Node) bool {
1526 if n.(*ir.AssignStmt).Y != nil {
1529 case ir.OAS2, ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2RECV:
1535 // Caution: stmt will emit more than one node for statement nodes n that have a
1536 // non-empty n.Ninit and where n is not a non-empty assignment or a node with a natural init
1537 // section (such as in "if", "for", etc.).
1538 func (w *exportWriter) stmt(n ir.Node) {
1539 if len(n.Init()) > 0 && !ir.StmtWithInit(n.Op()) && !isNonEmptyAssign(n) && n.Op() != ir.ORANGE {
1540 // can't use stmtList here since we don't want the final OEND
1541 for _, n := range n.Init() {
1548 // No OBLOCK in export data.
1549 // Inline content into this statement list,
1550 // like the init list above.
1551 // (At the moment neither the parser nor the typechecker
1552 // generate OBLOCK nodes except to denote an empty
1553 // function body, although that may change.)
1554 n := n.(*ir.BlockStmt)
1555 for _, n := range n.List {
1561 if ir.IsBlank(n.X) {
1562 return // blank declarations not useful to importers
1568 // Don't export "v = <N>" initializing statements, hope they're always
1569 // preceded by the DCL which will be re-parsed and typecheck to reproduce
1570 // the "v = <N>" again.
1571 n := n.(*ir.AssignStmt)
1575 w.stmtList(n.Init())
1582 n := n.(*ir.AssignOpStmt)
1587 if w.bool(!n.IncDec) {
1591 case ir.OAS2, ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2RECV:
1592 n := n.(*ir.AssignListStmt)
1595 w.stmtList(n.Init())
1601 n := n.(*ir.ReturnStmt)
1604 w.exprList(n.Results)
1607 // unreachable - generated by compiler for trampoline routines
1609 case ir.OGO, ir.ODEFER:
1610 n := n.(*ir.GoDeferStmt)
1619 w.stmtList(n.Init())
1625 n := n.(*ir.ForStmt)
1628 w.stmtList(n.Init())
1629 w.exprsOrNil(n.Cond, n.Post)
1633 n := n.(*ir.RangeStmt)
1636 w.stmtList(n.Init())
1637 w.exprsOrNil(n.Key, n.Value)
1642 n := n.(*ir.SelectStmt)
1645 w.stmtList(n.Init())
1649 n := n.(*ir.SwitchStmt)
1652 w.stmtList(n.Init())
1653 w.exprsOrNil(n.Tag, nil)
1654 w.caseList(n.Cases, isNamedTypeSwitch(n.Tag))
1657 // handled by caseList
1660 n := n.(*ir.BranchStmt)
1664 case ir.OBREAK, ir.OCONTINUE, ir.OGOTO, ir.OLABEL:
1668 if sym := n.Sym(); sym != nil {
1674 base.Fatalf("exporter: CANNOT EXPORT: %v\nPlease notify gri@\n", n.Op())
1678 func isNamedTypeSwitch(x ir.Node) bool {
1679 guard, ok := x.(*ir.TypeSwitchGuard)
1680 return ok && guard.Tag != nil
1683 func (w *exportWriter) caseList(cases []*ir.CaseClause, namedTypeSwitch bool) {
1684 w.uint64(uint64(len(cases)))
1685 for _, cas := range cases {
1687 w.stmtList(cas.List)
1688 if namedTypeSwitch {
1689 w.localName(cas.Var)
1691 w.stmtList(cas.Body)
1695 func (w *exportWriter) commList(cases []*ir.CommClause) {
1696 w.uint64(uint64(len(cases)))
1697 for _, cas := range cases {
1699 defaultCase := cas.Comm == nil
1702 // Only call w.node for non-default cause (cas.Comm is non-nil)
1705 w.stmtList(cas.Body)
1709 func (w *exportWriter) exprList(list ir.Nodes) {
1710 for _, n := range list {
1716 func simplifyForExport(n ir.Node) ir.Node {
1719 n := n.(*ir.ParenExpr)
1720 return simplifyForExport(n.X)
1725 func (w *exportWriter) expr(n ir.Node) {
1726 n = simplifyForExport(n)
1729 // (somewhat closely following the structure of exprfmt in fmt.go)
1731 n := n.(*ir.NilExpr)
1732 // If n is a typeparam, it will have already been checked
1733 // for proper use by the types2 typechecker.
1734 if !n.Type().IsTypeParam() && !n.Type().HasNil() {
1735 base.Fatalf("unexpected type for nil: %v", n.Type())
1743 if ir.HasUniquePos(n) {
1748 w.value(n.Type(), n.Val())
1751 // Package scope name.
1753 if (n.Class == ir.PEXTERN || n.Class == ir.PFUNC) && !ir.IsBlank(n) {
1755 // Indicate that this is not an OKEY entry.
1762 // Function scope name.
1763 // We don't need a type here, as the type will be provided at the
1764 // declaration of n.
1767 // This handles the case where we haven't yet transformed a call
1768 // to a builtin, so we must write out the builtin as a name in the
1770 isBuiltin := n.BuiltinOp != ir.OXXX
1773 w.bool(n.Sym().Pkg == types.UnsafePkg)
1774 w.string(n.Sym().Name)
1781 // This can only be for OKEY nodes in generic functions. Mark it
1790 // should have been resolved by typechecking - handled by default case
1796 case ir.ODYNAMICTYPE:
1797 n := n.(*ir.DynamicType)
1798 w.op(ir.ODYNAMICTYPE)
1810 n := n.(*ir.TypeSwitchGuard)
1815 if n.Tag.Op() != ir.ONONAME {
1816 base.Fatalf("expected ONONAME, got %v", n.Tag)
1820 w.localIdent(s) // declared pseudo-variable, if any
1823 // case OTARRAY, OTMAP, OTCHAN, OTSTRUCT, OTINTER, OTFUNC:
1824 // should have been resolved by typechecking - handled by default case
1827 n := n.(*ir.ClosureExpr)
1831 w.setPkg(n.Type().Pkg(), true)
1832 w.signature(n.Type())
1835 // Write out id for the Outer of each conditional variable. The
1836 // conditional variable itself for this closure will be re-created
1838 w.int64(int64(len(n.Func.ClosureVars)))
1839 for i, cv := range n.Func.ClosureVars {
1841 w.localName(cv.Outer)
1842 // Closure variable (which will be re-created during
1843 // import) is given via a negative id, starting at -2,
1844 // which is used to refer to it later in the function
1845 // during export. -1 represents blanks.
1846 w.dclIndex[cv] = -(i + 2) - w.maxClosureVarIndex
1848 w.maxClosureVarIndex += len(n.Func.ClosureVars)
1850 // like w.funcBody(n.Func), but not for .Inl
1851 w.writeNames(n.Func.Dcl)
1852 w.stmtList(n.Func.Body)
1855 // should have been resolved by typechecking - handled by default case
1858 n := n.(*ir.AddrExpr)
1865 n := n.(*ir.CompLitExpr)
1869 w.fieldList(n.List) // special handling of field names
1871 case ir.OCOMPLIT, ir.OARRAYLIT, ir.OSLICELIT, ir.OMAPLIT:
1872 n := n.(*ir.CompLitExpr)
1877 if n.Op() == ir.OSLICELIT {
1878 w.uint64(uint64(n.Len))
1881 n := n.(*ir.KeyExpr)
1888 // unreachable - handled in case OSTRUCTLIT by elemList
1890 case ir.OXDOT, ir.ODOT, ir.ODOTPTR, ir.ODOTINTER, ir.ODOTMETH, ir.OMETHVALUE, ir.OMETHEXPR:
1891 n := n.(*ir.SelectorExpr)
1895 w.exoticSelector(n.Sel)
1896 w.exoticType(n.Type())
1897 if n.Op() == ir.OXDOT {
1898 // n.Selection for method references will be
1899 // reconstructed during import.
1900 w.bool(n.Selection != nil)
1901 } else if n.Op() == ir.ODOT || n.Op() == ir.ODOTPTR || n.Op() == ir.ODOTINTER {
1902 w.exoticField(n.Selection)
1904 // n.Selection is not required for OMETHEXPR, ODOTMETH, and OMETHVALUE. It will
1905 // be reconstructed during import. n.Selection is computed during
1906 // transformDot() for OXDOT.
1908 case ir.ODOTTYPE, ir.ODOTTYPE2:
1909 n := n.(*ir.TypeAssertExpr)
1915 case ir.ODYNAMICDOTTYPE, ir.ODYNAMICDOTTYPE2:
1916 n := n.(*ir.DynamicTypeAssertExpr)
1923 case ir.OINDEX, ir.OINDEXMAP:
1924 n := n.(*ir.IndexExpr)
1929 w.exoticType(n.Type())
1930 if n.Op() == ir.OINDEXMAP {
1934 case ir.OSLICE, ir.OSLICESTR, ir.OSLICEARR:
1935 n := n.(*ir.SliceExpr)
1939 w.exprsOrNil(n.Low, n.High)
1942 case ir.OSLICE3, ir.OSLICE3ARR:
1943 n := n.(*ir.SliceExpr)
1947 w.exprsOrNil(n.Low, n.High)
1951 case ir.OCOPY, ir.OCOMPLEX, ir.OUNSAFEADD, ir.OUNSAFESLICE:
1952 // treated like other builtin calls (see e.g., OREAL)
1953 n := n.(*ir.BinaryExpr)
1956 w.stmtList(n.Init())
1961 case ir.OCONV, ir.OCONVIFACE, ir.OCONVIDATA, ir.OCONVNOP, ir.OBYTES2STR, ir.ORUNES2STR, ir.OSTR2BYTES, ir.OSTR2RUNES, ir.ORUNESTR, ir.OSLICE2ARRPTR:
1962 n := n.(*ir.ConvExpr)
1968 case ir.OREAL, ir.OIMAG, ir.OCAP, ir.OCLOSE, ir.OLEN, ir.ONEW, ir.OPANIC:
1969 n := n.(*ir.UnaryExpr)
1973 if n.Op() != ir.OPANIC {
1977 case ir.OAPPEND, ir.ODELETE, ir.ORECOVER, ir.OPRINT, ir.OPRINTN:
1978 n := n.(*ir.CallExpr)
1981 w.stmtList(n.Init())
1982 w.exprList(n.Args) // emits terminating OEND
1983 // only append() calls may contain '...' arguments
1984 if n.Op() == ir.OAPPEND {
1987 base.Fatalf("exporter: unexpected '...' with %v call", n.Op())
1989 if n.Op() != ir.ODELETE && n.Op() != ir.OPRINT && n.Op() != ir.OPRINTN {
1993 case ir.OCALL, ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER, ir.OGETG:
1994 n := n.(*ir.CallExpr)
1997 w.stmtList(n.Init())
2001 w.exoticType(n.Type())
2003 case ir.OMAKEMAP, ir.OMAKECHAN, ir.OMAKESLICE:
2004 n := n.(*ir.MakeExpr)
2005 w.op(n.Op()) // must keep separate from OMAKE for importer
2016 case n.Len != nil && (n.Op() == ir.OMAKESLICE || !n.Len.Type().IsUntyped()):
2017 // Note: the extra conditional exists because make(T) for
2018 // T a map or chan type, gets an untyped zero added as
2019 // an argument. Don't serialize that argument here.
2027 case ir.OLINKSYMOFFSET:
2028 n := n.(*ir.LinksymOffsetExpr)
2029 w.op(ir.OLINKSYMOFFSET)
2031 w.string(n.Linksym.Name)
2032 w.uint64(uint64(n.Offset_))
2035 // unary expressions
2036 case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT, ir.ORECV, ir.OIDATA:
2037 n := n.(*ir.UnaryExpr)
2044 n := n.(*ir.AddrExpr)
2051 n := n.(*ir.StarExpr)
2058 n := n.(*ir.SendStmt)
2064 // binary expressions
2065 case ir.OADD, ir.OAND, ir.OANDNOT, ir.ODIV, ir.OEQ, ir.OGE, ir.OGT, ir.OLE, ir.OLT,
2066 ir.OLSH, ir.OMOD, ir.OMUL, ir.ONE, ir.OOR, ir.ORSH, ir.OSUB, ir.OXOR, ir.OEFACE:
2067 n := n.(*ir.BinaryExpr)
2074 case ir.OANDAND, ir.OOROR:
2075 n := n.(*ir.LogicalExpr)
2083 n := n.(*ir.AddStringExpr)
2090 // if exporting, DCLCONST should just be removed as its usage
2091 // has already been replaced with literals
2094 n := n.(*ir.InstExpr)
2098 w.uint64(uint64(len(n.Targs)))
2099 for _, targ := range n.Targs {
2105 n := n.(*ir.AssignListStmt)
2108 w.stmtList(n.Init())
2114 base.Fatalf("cannot export %v (%d) node\n"+
2115 "\t==> please file an issue and assign to gri@", n.Op(), int(n.Op()))
2119 func (w *exportWriter) op(op ir.Op) {
2123 w.uint64(uint64(op))
2126 func (w *exportWriter) exprsOrNil(a, b ir.Node) {
2134 w.uint64(uint64(ab))
2143 func (w *exportWriter) fieldList(list ir.Nodes) {
2144 w.uint64(uint64(len(list)))
2145 for _, n := range list {
2146 n := n.(*ir.StructKeyExpr)
2148 w.exoticField(n.Field)
2153 func (w *exportWriter) localName(n *ir.Name) {
2159 i, ok := w.dclIndex[n]
2161 base.FatalfAt(n.Pos(), "missing from dclIndex: %+v", n)
2166 func (w *exportWriter) localIdent(s *types.Sym) {
2167 if w.currPkg == nil {
2168 base.Fatalf("missing currPkg")
2171 // Anonymous parameters.
2183 // The name of autotmp variables isn't important; they just need to
2184 // be unique. To stabilize the export data, simply write out "$" as
2185 // a marker and let the importer generate its own unique name.
2186 if strings.HasPrefix(name, ".autotmp_") {
2187 w.string("$autotmp")
2191 if i := strings.LastIndex(name, "."); i >= 0 && !strings.HasPrefix(name, LocalDictName) {
2192 base.Fatalf("unexpected dot in identifier: %v", name)
2195 if s.Pkg != w.currPkg {
2196 base.Fatalf("weird package in name: %v => %v from %q, not %q", s, name, s.Pkg.Path, w.currPkg.Path)
2202 type intWriter struct {
2206 func (w *intWriter) int64(x int64) {
2207 var buf [binary.MaxVarintLen64]byte
2208 n := binary.PutVarint(buf[:], x)
2212 func (w *intWriter) uint64(x uint64) {
2213 var buf [binary.MaxVarintLen64]byte
2214 n := binary.PutUvarint(buf[:], x)
2218 // The name used for dictionary parameters or local variables.
2219 const LocalDictName = ".dict"