Source file src/cmd/compile/internal/typecheck/iexport.go

     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.
     4  
     5  // Indexed package export.
     6  //
     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
    12  // packages.
    13  //
    14  //
    15  // The top-level data format is structured as:
    16  //
    17  //     Header struct {
    18  //         Tag        byte   // 'i'
    19  //         Version    uvarint
    20  //         StringSize uvarint
    21  //         DataSize   uvarint
    22  //     }
    23  //
    24  //     Strings [StringSize]byte
    25  //     Data    [DataSize]byte
    26  //
    27  //     MainIndex []struct{
    28  //         PkgPath   stringOff
    29  //         PkgName   stringOff
    30  //         PkgHeight uvarint
    31  //
    32  //         Decls []struct{
    33  //             Name   stringOff
    34  //             Offset declOff
    35  //         }
    36  //     }
    37  //
    38  //     Fingerprint [8]byte
    39  //
    40  // uvarint means a uint64 written out using uvarint encoding.
    41  //
    42  // []T means a uvarint followed by that many T objects. In other
    43  // words:
    44  //
    45  //     Len   uvarint
    46  //     Elems [Len]T
    47  //
    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.
    51  //
    52  // declOff means a uvarint that indicates an offset within the Data
    53  // section where the associated declaration can be found.
    54  //
    55  //
    56  // There are five kinds of declarations, distinguished by their first
    57  // byte:
    58  //
    59  //     type Var struct {
    60  //         Tag  byte // 'V'
    61  //         Pos  Pos
    62  //         Type typeOff
    63  //     }
    64  //
    65  //     type Func struct {
    66  //         Tag       byte // 'F' or 'G'
    67  //         Pos       Pos
    68  //         TypeParams []typeOff  // only present if Tag == 'G'
    69  //         Signature Signature
    70  //     }
    71  //
    72  //     type Const struct {
    73  //         Tag   byte // 'C'
    74  //         Pos   Pos
    75  //         Value Value
    76  //     }
    77  //
    78  //     type Type struct {
    79  //         Tag        byte // 'T' or 'U'
    80  //         Pos        Pos
    81  //         TypeParams []typeOff  // only present if Tag == 'U'
    82  //         Underlying typeOff
    83  //
    84  //         Methods []struct{  // omitted if Underlying is an interface type
    85  //             Pos       Pos
    86  //             Name      stringOff
    87  //             Recv      Param
    88  //             Signature Signature
    89  //         }
    90  //     }
    91  //
    92  //     type Alias struct {
    93  //         Tag  byte // 'A'
    94  //         Pos  Pos
    95  //         Type typeOff
    96  //     }
    97  //
    98  //     // "Automatic" declaration of each typeparam
    99  //     type TypeParam struct {
   100  //         Tag        byte // 'P'
   101  //         Pos        Pos
   102  //         Implicit   bool
   103  //         Constraint typeOff
   104  //     }
   105  //
   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.
   111  //
   112  // Value means a type, kind, and type-specific value. See
   113  // (*exportWriter).value for details.
   114  //
   115  //
   116  // There are twelve kinds of type descriptors, distinguished by an itag:
   117  //
   118  //     type DefinedType struct {
   119  //         Tag     itag // definedType
   120  //         Name    stringOff
   121  //         PkgPath stringOff
   122  //     }
   123  //
   124  //     type PointerType struct {
   125  //         Tag  itag // pointerType
   126  //         Elem typeOff
   127  //     }
   128  //
   129  //     type SliceType struct {
   130  //         Tag  itag // sliceType
   131  //         Elem typeOff
   132  //     }
   133  //
   134  //     type ArrayType struct {
   135  //         Tag  itag // arrayType
   136  //         Len  uint64
   137  //         Elem typeOff
   138  //     }
   139  //
   140  //     type ChanType struct {
   141  //         Tag  itag   // chanType
   142  //         Dir  uint64 // 1 RecvOnly; 2 SendOnly; 3 SendRecv
   143  //         Elem typeOff
   144  //     }
   145  //
   146  //     type MapType struct {
   147  //         Tag  itag // mapType
   148  //         Key  typeOff
   149  //         Elem typeOff
   150  //     }
   151  //
   152  //     type FuncType struct {
   153  //         Tag       itag // signatureType
   154  //         PkgPath   stringOff
   155  //         Signature Signature
   156  //     }
   157  //
   158  //     type StructType struct {
   159  //         Tag     itag // structType
   160  //         PkgPath stringOff
   161  //         Fields []struct {
   162  //             Pos      Pos
   163  //             Name     stringOff
   164  //             Type     typeOff
   165  //             Embedded bool
   166  //             Note     stringOff
   167  //         }
   168  //     }
   169  //
   170  //     type InterfaceType struct {
   171  //         Tag     itag // interfaceType
   172  //         PkgPath stringOff
   173  //         Embeddeds []struct {
   174  //             Pos  Pos
   175  //             Type typeOff
   176  //         }
   177  //         Methods []struct {
   178  //             Pos       Pos
   179  //             Name      stringOff
   180  //             Signature Signature
   181  //         }
   182  //     }
   183  //
   184  //     // Reference to a type param declaration
   185  //     type TypeParamType struct {
   186  //         Tag     itag // typeParamType
   187  //         Name    stringOff
   188  //         PkgPath stringOff
   189  //     }
   190  //
   191  //     // Instantiation of a generic type (like List[T2] or List[int])
   192  //     type InstanceType struct {
   193  //         Tag     itag // instanceType
   194  //         Pos     pos
   195  //         TypeArgs []typeOff
   196  //         BaseType typeOff
   197  //     }
   198  //
   199  //     type UnionType struct {
   200  //         Tag     itag // interfaceType
   201  //         Terms   []struct {
   202  //             tilde bool
   203  //             Type  typeOff
   204  //         }
   205  //     }
   206  //
   207  //
   208  //
   209  //     type Signature struct {
   210  //         Params   []Param
   211  //         Results  []Param
   212  //         Variadic bool  // omitted if Results is empty
   213  //     }
   214  //
   215  //     type Param struct {
   216  //         Pos  Pos
   217  //         Name stringOff
   218  //         Type typOff
   219  //     }
   220  //
   221  //
   222  // Pos encodes a file:line:column triple, incorporating a simple delta
   223  // encoding scheme within a data object. See exportWriter.pos for
   224  // details.
   225  //
   226  //
   227  // Compiler-specific details.
   228  //
   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.
   234  
   235  package typecheck
   236  
   237  import (
   238  	"bytes"
   239  	"crypto/md5"
   240  	"encoding/binary"
   241  	"fmt"
   242  	"go/constant"
   243  	"io"
   244  	"math/big"
   245  	"sort"
   246  	"strconv"
   247  	"strings"
   248  
   249  	"cmd/compile/internal/base"
   250  	"cmd/compile/internal/ir"
   251  	"cmd/compile/internal/types"
   252  	"cmd/internal/goobj"
   253  	"cmd/internal/src"
   254  )
   255  
   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
   262  const (
   263  	iexportVersionGo1_11   = 0
   264  	iexportVersionPosCol   = 1
   265  	iexportVersionGenerics = 2
   266  	iexportVersionGo1_18   = 2
   267  
   268  	iexportVersionCurrent = 2
   269  )
   270  
   271  // predeclReserved is the number of type offsets reserved for types
   272  // implicitly declared in the universe block.
   273  const predeclReserved = 32
   274  
   275  // An itag distinguishes the kind of type that was written into the
   276  // indexed export format.
   277  type itag uint64
   278  
   279  const (
   280  	// Types
   281  	definedType itag = iota
   282  	pointerType
   283  	sliceType
   284  	arrayType
   285  	chanType
   286  	mapType
   287  	signatureType
   288  	structType
   289  	interfaceType
   290  	typeParamType
   291  	instanceType // Instantiation of a generic type
   292  	unionType
   293  )
   294  
   295  const (
   296  	debug = false
   297  	magic = 0x6742937dc293105
   298  )
   299  
   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) {
   303  	if extensions {
   304  		// If we're exporting inline bodies, invoke the crawler to mark
   305  		// which bodies to include.
   306  		crawlExports(Target.Exports)
   307  	}
   308  
   309  	p := iexporter{
   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,
   316  	}
   317  
   318  	for i, pt := range predeclared() {
   319  		p.typIndex[pt] = uint64(i)
   320  	}
   321  	if len(p.typIndex) > predeclReserved {
   322  		base.Fatalf("too many predeclared types: %d > %d", len(p.typIndex), predeclReserved)
   323  	}
   324  
   325  	// Initialize work queue with exported declarations.
   326  	for _, n := range Target.Exports {
   327  		p.pushDecl(n)
   328  	}
   329  
   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())
   335  	}
   336  
   337  	// Append indices to data0 section.
   338  	dataLen := uint64(p.data0.Len())
   339  	w := p.newWriter()
   340  	w.writeIndex(p.declIndex, true)
   341  	w.writeIndex(p.inlineIndex, false)
   342  	w.flush()
   343  
   344  	if *base.Flag.LowerV {
   345  		fmt.Printf("export: hdr strings %v, data %v, index %v\n", p.strings.Len(), dataLen, p.data0.Len())
   346  	}
   347  
   348  	// Assemble header.
   349  	var hdr intWriter
   350  	hdr.WriteByte('i')
   351  	hdr.uint64(iexportVersionCurrent)
   352  	hdr.uint64(uint64(p.strings.Len()))
   353  	hdr.uint64(dataLen)
   354  
   355  	// Flush output.
   356  	h := md5.New()
   357  	wr := io.MultiWriter(out, h)
   358  	io.Copy(wr, &hdr)
   359  	io.Copy(wr, &p.strings)
   360  	io.Copy(wr, &p.data0)
   361  
   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[:])
   366  }
   367  
   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{}
   375  
   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.
   379  	if mainIndex {
   380  		pkgSyms[types.LocalPkg] = nil
   381  		for pkg := range w.p.allPkgs {
   382  			pkgSyms[pkg] = nil
   383  		}
   384  	}
   385  
   386  	// Group symbols by package.
   387  	for sym := range index {
   388  		pkgSyms[sym.Pkg] = append(pkgSyms[sym.Pkg], sym)
   389  	}
   390  
   391  	// Sort packages by path.
   392  	var pkgs []*types.Pkg
   393  	for pkg := range pkgSyms {
   394  		pkgs = append(pkgs, pkg)
   395  	}
   396  	sort.Slice(pkgs, func(i, j int) bool {
   397  		return pkgs[i].Path < pkgs[j].Path
   398  	})
   399  
   400  	w.uint64(uint64(len(pkgs)))
   401  	for _, pkg := range pkgs {
   402  		w.string(pkg.Path)
   403  		if mainIndex {
   404  			w.string(pkg.Name)
   405  			w.uint64(uint64(pkg.Height))
   406  		}
   407  
   408  		// Sort symbols within a package by name.
   409  		syms := pkgSyms[pkg]
   410  		sort.Slice(syms, func(i, j int) bool {
   411  			return syms[i].Name < syms[j].Name
   412  		})
   413  
   414  		w.uint64(uint64(len(syms)))
   415  		for _, sym := range syms {
   416  			w.string(sym.Name)
   417  			w.uint64(index[sym])
   418  		}
   419  	}
   420  }
   421  
   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
   425  	// main index.
   426  	allPkgs map[*types.Pkg]bool
   427  
   428  	declTodo ir.NameQueue
   429  
   430  	strings     intWriter
   431  	stringIndex map[string]uint64
   432  
   433  	data0       intWriter
   434  	declIndex   map[*types.Sym]uint64
   435  	inlineIndex map[*types.Sym]uint64
   436  	typIndex    map[*types.Type]uint64
   437  
   438  	extensions bool
   439  }
   440  
   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]
   445  	if !ok {
   446  		off = uint64(p.strings.Len())
   447  		p.stringIndex[s] = off
   448  
   449  		if *base.Flag.LowerV {
   450  			fmt.Printf("export: str %v %.40q\n", off, s)
   451  		}
   452  
   453  		p.strings.uint64(uint64(len(s)))
   454  		p.strings.WriteString(s)
   455  	}
   456  	return off
   457  }
   458  
   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())
   463  	}
   464  
   465  	// Don't export predeclared declarations.
   466  	if n.Sym().Pkg == types.BuiltinPkg || n.Sym().Pkg == types.UnsafePkg {
   467  		return
   468  	}
   469  
   470  	if _, ok := p.declIndex[n.Sym()]; ok {
   471  		return
   472  	}
   473  
   474  	p.declIndex[n.Sym()] = ^uint64(0) // mark n present in work queue
   475  	p.declTodo.PushRight(n)
   476  }
   477  
   478  // exportWriter handles writing out individual data section chunks.
   479  type exportWriter struct {
   480  	p *iexporter
   481  
   482  	data       intWriter
   483  	currPkg    *types.Pkg
   484  	prevFile   string
   485  	prevLine   int64
   486  	prevColumn int64
   487  
   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
   493  	maxDclIndex        int
   494  	maxClosureVarIndex int
   495  }
   496  
   497  func (p *iexporter) doDecl(n *ir.Name) {
   498  	w := p.newWriter()
   499  	w.setPkg(n.Sym().Pkg, false)
   500  
   501  	switch n.Op() {
   502  	case ir.ONAME:
   503  		switch n.Class {
   504  		case ir.PEXTERN:
   505  			// Variable.
   506  			w.tag('V')
   507  			w.pos(n.Pos())
   508  			w.typ(n.Type())
   509  			if w.p.extensions {
   510  				w.varExt(n)
   511  			}
   512  
   513  		case ir.PFUNC:
   514  			if ir.IsMethod(n) {
   515  				base.Fatalf("unexpected method: %v", n)
   516  			}
   517  
   518  			// Function.
   519  			if n.Type().TParams().NumFields() == 0 {
   520  				w.tag('F')
   521  			} else {
   522  				w.tag('G')
   523  			}
   524  			w.pos(n.Pos())
   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
   530  			// are used.
   531  			if n.Type().TParams().NumFields() > 0 {
   532  				w.tparamList(n.Type().TParams().FieldSlice())
   533  			}
   534  			w.signature(n.Type())
   535  			if w.p.extensions {
   536  				w.funcExt(n)
   537  			}
   538  
   539  		default:
   540  			base.Fatalf("unexpected class: %v, %v", n, n.Class)
   541  		}
   542  
   543  	case ir.OLITERAL:
   544  		// TODO(mdempsky): Extend check to all declarations.
   545  		if n.Typecheck() == 0 {
   546  			base.FatalfAt(n.Pos(), "missed typecheck: %v", n)
   547  		}
   548  
   549  		// Constant.
   550  		w.tag('C')
   551  		w.pos(n.Pos())
   552  		w.value(n.Type(), n.Val())
   553  		if w.p.extensions {
   554  			w.constExt(n)
   555  		}
   556  
   557  	case ir.OTYPE:
   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
   562  			// definition.
   563  			w.tag('P')
   564  			// A typeparam has a name, and has a type bound rather
   565  			// than an underlying type.
   566  			w.pos(n.Pos())
   567  			if iexportVersionCurrent >= iexportVersionGo1_18 {
   568  				implicit := n.Type().Bound().IsImplicit()
   569  				w.bool(implicit)
   570  			}
   571  			w.typ(n.Type().Bound())
   572  			break
   573  		}
   574  
   575  		if n.Alias() {
   576  			// Alias.
   577  			w.tag('A')
   578  			w.pos(n.Pos())
   579  			w.typ(n.Type())
   580  			break
   581  		}
   582  
   583  		// Defined type.
   584  		if len(n.Type().RParams()) == 0 {
   585  			w.tag('T')
   586  		} else {
   587  			w.tag('U')
   588  		}
   589  		w.pos(n.Pos())
   590  
   591  		if len(n.Type().RParams()) > 0 {
   592  			// Export type parameters, if any, needed for this type
   593  			w.typeList(n.Type().RParams())
   594  		}
   595  
   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
   605  		}
   606  		if underlying == types.ComparableType.Underlying() {
   607  			// Do same for ComparableType as for ErrorType.
   608  			underlying = types.ComparableType
   609  		}
   610  		if base.Flag.G > 0 && underlying == types.AnyType.Underlying() {
   611  			// Do same for AnyType as for ErrorType.
   612  			underlying = types.AnyType
   613  		}
   614  		w.typ(underlying)
   615  
   616  		t := n.Type()
   617  		if t.IsInterface() {
   618  			if w.p.extensions {
   619  				w.typeExt(t)
   620  			}
   621  			break
   622  		}
   623  
   624  		// Sort methods, for consistency with types2.
   625  		methods := append([]*types.Field(nil), t.Methods().Slice()...)
   626  		if base.Debug.UnifiedQuirks != 0 {
   627  			sort.Sort(types.MethodsByName(methods))
   628  		}
   629  
   630  		w.uint64(uint64(len(methods)))
   631  		for _, m := range methods {
   632  			w.pos(m.Pos)
   633  			w.selector(m.Sym)
   634  			w.param(m.Type.Recv())
   635  			w.signature(m.Type)
   636  		}
   637  
   638  		if w.p.extensions {
   639  			w.typeExt(t)
   640  			for _, m := range methods {
   641  				w.methExt(m)
   642  			}
   643  		}
   644  
   645  	default:
   646  		base.Fatalf("unexpected node: %v", n)
   647  	}
   648  
   649  	w.finish("dcl", p.declIndex, n.Sym())
   650  }
   651  
   652  func (w *exportWriter) tag(tag byte) {
   653  	w.data.WriteByte(tag)
   654  }
   655  
   656  func (w *exportWriter) finish(what string, index map[*types.Sym]uint64, sym *types.Sym) {
   657  	off := w.flush()
   658  	if *base.Flag.LowerV {
   659  		fmt.Printf("export: %v %v %v\n", what, off, sym)
   660  	}
   661  	index[sym] = off
   662  }
   663  
   664  func (p *iexporter) doInline(f *ir.Name) {
   665  	w := p.newWriter()
   666  	w.setPkg(fnpkg(f), false)
   667  
   668  	w.dclIndex = make(map[*ir.Name]int, len(f.Func.Inl.Dcl))
   669  	w.funcBody(f.Func)
   670  
   671  	w.finish("inl", p.inlineIndex, f.Sym())
   672  }
   673  
   674  func (w *exportWriter) pos(pos src.XPos) {
   675  	p := base.Ctxt.PosTable.Pos(pos)
   676  	file := p.Base().AbsFilename()
   677  	line := int64(p.RelLine())
   678  	column := int64(p.RelCol())
   679  
   680  	// Encode position relative to the last position: column
   681  	// delta, then line delta, then file name. We reserve the
   682  	// bottom bit of the column and line deltas to encode whether
   683  	// the remaining fields are present.
   684  	//
   685  	// Note: Because data objects may be read out of order (or not
   686  	// at all), we can only apply delta encoding within a single
   687  	// object. This is handled implicitly by tracking prevFile,
   688  	// prevLine, and prevColumn as fields of exportWriter.
   689  
   690  	deltaColumn := (column - w.prevColumn) << 1
   691  	deltaLine := (line - w.prevLine) << 1
   692  
   693  	if file != w.prevFile {
   694  		deltaLine |= 1
   695  	}
   696  	if deltaLine != 0 {
   697  		deltaColumn |= 1
   698  	}
   699  
   700  	w.int64(deltaColumn)
   701  	if deltaColumn&1 != 0 {
   702  		w.int64(deltaLine)
   703  		if deltaLine&1 != 0 {
   704  			w.string(file)
   705  		}
   706  	}
   707  
   708  	w.prevFile = file
   709  	w.prevLine = line
   710  	w.prevColumn = column
   711  }
   712  
   713  func (w *exportWriter) pkg(pkg *types.Pkg) {
   714  	// TODO(mdempsky): Add flag to types.Pkg to mark pseudo-packages.
   715  	if pkg == ir.Pkgs.Go {
   716  		base.Fatalf("export of pseudo-package: %q", pkg.Path)
   717  	}
   718  
   719  	// Ensure any referenced packages are declared in the main index.
   720  	w.p.allPkgs[pkg] = true
   721  
   722  	w.string(pkg.Path)
   723  }
   724  
   725  func (w *exportWriter) qualifiedIdent(n *ir.Name) {
   726  	// Ensure any referenced declarations are written out too.
   727  	w.p.pushDecl(n)
   728  
   729  	s := n.Sym()
   730  	w.string(s.Name)
   731  	w.pkg(s.Pkg)
   732  }
   733  
   734  const blankMarker = "$"
   735  
   736  // TparamExportName creates a unique name for type param in a method or a generic
   737  // type, using the specified unique prefix and the index of the type param. The index
   738  // is only used if the type param is blank, in which case the blank is replace by
   739  // "$<index>". A unique name is needed for later substitution in the compiler and
   740  // export/import that keeps blank type params associated with the correct constraint.
   741  func TparamExportName(prefix string, name string, index int) string {
   742  	if name == "_" {
   743  		name = blankMarker + strconv.Itoa(index)
   744  	}
   745  	return prefix + "." + name
   746  }
   747  
   748  // TparamName returns the real name of a type parameter, after stripping its
   749  // qualifying prefix and reverting blank-name encoding. See TparamExportName
   750  // for details.
   751  func TparamName(exportName string) string {
   752  	// Remove the "path" from the type param name that makes it unique.
   753  	ix := strings.LastIndex(exportName, ".")
   754  	if ix < 0 {
   755  		return ""
   756  	}
   757  	name := exportName[ix+1:]
   758  	if strings.HasPrefix(name, blankMarker) {
   759  		return "_"
   760  	}
   761  	return name
   762  }
   763  
   764  func (w *exportWriter) selector(s *types.Sym) {
   765  	if w.currPkg == nil {
   766  		base.Fatalf("missing currPkg")
   767  	}
   768  
   769  	// If the selector being written is unexported, it comes with a package qualifier.
   770  	// If the selector being written is exported, it is not package-qualified.
   771  	// See the spec: https://golang.org/ref/spec#Uniqueness_of_identifiers
   772  	// As an optimization, we don't actually write the package every time - instead we
   773  	// call setPkg before a group of selectors (all of which must have the same package qualifier).
   774  	pkg := w.currPkg
   775  	if types.IsExported(s.Name) {
   776  		pkg = types.LocalPkg
   777  	}
   778  	if s.Pkg != pkg {
   779  		base.Fatalf("package mismatch in selector: %v in package %q, but want %q", s, s.Pkg.Path, pkg.Path)
   780  	}
   781  
   782  	w.string(s.Name)
   783  }
   784  
   785  func (w *exportWriter) typ(t *types.Type) {
   786  	w.data.uint64(w.p.typOff(t))
   787  }
   788  
   789  // The "exotic" functions in this section encode a wider range of
   790  // items than the standard encoding functions above. These include
   791  // types that do not appear in declarations, only in code, such as
   792  // method types. These methods need to be separate from the standard
   793  // encoding functions because we don't want to modify the encoding
   794  // generated by the standard functions (because that exported
   795  // information is read by tools besides the compiler).
   796  
   797  // exoticType exports a type to the writer.
   798  func (w *exportWriter) exoticType(t *types.Type) {
   799  	switch {
   800  	case t == nil:
   801  		// Calls-as-statements have no type.
   802  		w.data.uint64(exoticTypeNil)
   803  	case t.IsStruct() && t.StructType().Funarg != types.FunargNone:
   804  		// These are weird structs for representing tuples of types returned
   805  		// by multi-return functions.
   806  		// They don't fit the standard struct type mold. For instance,
   807  		// they don't have any package info.
   808  		w.data.uint64(exoticTypeTuple)
   809  		w.uint64(uint64(t.StructType().Funarg))
   810  		w.uint64(uint64(t.NumFields()))
   811  		for _, f := range t.FieldSlice() {
   812  			w.pos(f.Pos)
   813  			s := f.Sym
   814  			if s == nil {
   815  				w.uint64(0)
   816  			} else if s.Pkg == nil {
   817  				w.uint64(exoticTypeSymNoPkg)
   818  				w.string(s.Name)
   819  			} else {
   820  				w.uint64(exoticTypeSymWithPkg)
   821  				w.pkg(s.Pkg)
   822  				w.string(s.Name)
   823  			}
   824  			w.typ(f.Type)
   825  			if f.Embedded != 0 || f.Note != "" {
   826  				panic("extra info in funarg struct field")
   827  			}
   828  		}
   829  	case t.Kind() == types.TFUNC && t.Recv() != nil:
   830  		w.data.uint64(exoticTypeRecv)
   831  		// interface method types have a fake receiver type.
   832  		isFakeRecv := t.Recv().Type == types.FakeRecvType()
   833  		w.bool(isFakeRecv)
   834  		if !isFakeRecv {
   835  			w.exoticParam(t.Recv())
   836  		}
   837  		w.exoticSignature(t)
   838  
   839  	default:
   840  		// A regular type.
   841  		w.data.uint64(exoticTypeRegular)
   842  		w.typ(t)
   843  	}
   844  }
   845  
   846  const (
   847  	exoticTypeNil = iota
   848  	exoticTypeTuple
   849  	exoticTypeRecv
   850  	exoticTypeRegular
   851  )
   852  const (
   853  	exoticTypeSymNil = iota
   854  	exoticTypeSymNoPkg
   855  	exoticTypeSymWithPkg
   856  )
   857  
   858  // Export a selector, but one whose package may not match
   859  // the package being compiled. This is a separate function
   860  // because the standard selector() serialization format is fixed
   861  // by the go/types reader. This one can only be used during
   862  // inline/generic body exporting.
   863  func (w *exportWriter) exoticSelector(s *types.Sym) {
   864  	pkg := w.currPkg
   865  	if types.IsExported(s.Name) {
   866  		pkg = types.LocalPkg
   867  	}
   868  
   869  	w.string(s.Name)
   870  	if s.Pkg == pkg {
   871  		w.uint64(0)
   872  	} else {
   873  		w.uint64(1)
   874  		w.pkg(s.Pkg)
   875  	}
   876  }
   877  
   878  func (w *exportWriter) exoticSignature(t *types.Type) {
   879  	hasPkg := t.Pkg() != nil
   880  	w.bool(hasPkg)
   881  	if hasPkg {
   882  		w.pkg(t.Pkg())
   883  	}
   884  	w.exoticParamList(t.Params().FieldSlice())
   885  	w.exoticParamList(t.Results().FieldSlice())
   886  }
   887  
   888  func (w *exportWriter) exoticParamList(fs []*types.Field) {
   889  	w.uint64(uint64(len(fs)))
   890  	for _, f := range fs {
   891  		w.exoticParam(f)
   892  	}
   893  
   894  }
   895  func (w *exportWriter) exoticParam(f *types.Field) {
   896  	w.pos(f.Pos)
   897  	w.exoticSym(f.Sym)
   898  	w.uint64(uint64(f.Offset))
   899  	w.exoticType(f.Type)
   900  	w.bool(f.IsDDD())
   901  }
   902  
   903  func (w *exportWriter) exoticField(f *types.Field) {
   904  	w.pos(f.Pos)
   905  	w.exoticSym(f.Sym)
   906  	w.uint64(uint64(f.Offset))
   907  	w.exoticType(f.Type)
   908  	w.string(f.Note)
   909  }
   910  
   911  func (w *exportWriter) exoticSym(s *types.Sym) {
   912  	if s == nil {
   913  		w.string("")
   914  		return
   915  	}
   916  	if s.Name == "" {
   917  		base.Fatalf("empty symbol name")
   918  	}
   919  	w.string(s.Name)
   920  	if !types.IsExported(s.Name) {
   921  		w.pkg(s.Pkg)
   922  	}
   923  }
   924  
   925  func (p *iexporter) newWriter() *exportWriter {
   926  	return &exportWriter{p: p}
   927  }
   928  
   929  func (w *exportWriter) flush() uint64 {
   930  	off := uint64(w.p.data0.Len())
   931  	io.Copy(&w.p.data0, &w.data)
   932  	return off
   933  }
   934  
   935  func (p *iexporter) typOff(t *types.Type) uint64 {
   936  	off, ok := p.typIndex[t]
   937  	if !ok {
   938  		w := p.newWriter()
   939  		w.doTyp(t)
   940  		rawOff := w.flush()
   941  		if *base.Flag.LowerV {
   942  			fmt.Printf("export: typ %v %v\n", rawOff, t)
   943  		}
   944  		off = predeclReserved + rawOff
   945  		p.typIndex[t] = off
   946  	}
   947  	return off
   948  }
   949  
   950  func (w *exportWriter) startType(k itag) {
   951  	w.data.uint64(uint64(k))
   952  }
   953  
   954  func (w *exportWriter) doTyp(t *types.Type) {
   955  	s := t.Sym()
   956  	if s != nil && t.OrigType() != nil {
   957  		assert(base.Flag.G > 0)
   958  		// This is an instantiated type - could be a re-instantiation like
   959  		// Value[T2] or a full instantiation like Value[int].
   960  		if strings.Index(s.Name, "[") < 0 {
   961  			base.Fatalf("incorrect name for instantiated type")
   962  		}
   963  		w.startType(instanceType)
   964  		w.pos(t.Pos())
   965  		// Export the type arguments for the instantiated type. The
   966  		// instantiated type could be in a method header (e.g. "func (v
   967  		// *Value[T2]) set (...) { ... }"), so the type args are "new"
   968  		// typeparams. Or the instantiated type could be in a
   969  		// function/method body, so the type args are either concrete
   970  		// types or existing typeparams from the function/method header.
   971  		w.typeList(t.RParams())
   972  		// Export a reference to the base type.
   973  		baseType := t.OrigType()
   974  		w.typ(baseType)
   975  		return
   976  	}
   977  
   978  	// The 't.Underlying() == t' check is to confirm this is a base typeparam
   979  	// type, rather than a defined type with typeparam underlying type, like:
   980  	// type orderedAbs[T any] T
   981  	if t.IsTypeParam() && t.Underlying() == t {
   982  		assert(base.Flag.G > 0)
   983  		if s.Pkg == types.BuiltinPkg || s.Pkg == types.UnsafePkg {
   984  			base.Fatalf("builtin type missing from typIndex: %v", t)
   985  		}
   986  		// Write out the first use of a type param as a qualified ident.
   987  		// This will force a "declaration" of the type param.
   988  		w.startType(typeParamType)
   989  		w.qualifiedIdent(t.Obj().(*ir.Name))
   990  		return
   991  	}
   992  
   993  	if s != nil {
   994  		if s.Pkg == types.BuiltinPkg || s.Pkg == types.UnsafePkg {
   995  			base.Fatalf("builtin type missing from typIndex: %v", t)
   996  		}
   997  
   998  		w.startType(definedType)
   999  		w.qualifiedIdent(t.Obj().(*ir.Name))
  1000  		return
  1001  	}
  1002  
  1003  	switch t.Kind() {
  1004  	case types.TPTR:
  1005  		w.startType(pointerType)
  1006  		w.typ(t.Elem())
  1007  
  1008  	case types.TSLICE:
  1009  		w.startType(sliceType)
  1010  		w.typ(t.Elem())
  1011  
  1012  	case types.TARRAY:
  1013  		w.startType(arrayType)
  1014  		w.uint64(uint64(t.NumElem()))
  1015  		w.typ(t.Elem())
  1016  
  1017  	case types.TCHAN:
  1018  		w.startType(chanType)
  1019  		w.uint64(uint64(t.ChanDir()))
  1020  		w.typ(t.Elem())
  1021  
  1022  	case types.TMAP:
  1023  		w.startType(mapType)
  1024  		w.typ(t.Key())
  1025  		w.typ(t.Elem())
  1026  
  1027  	case types.TFUNC:
  1028  		w.startType(signatureType)
  1029  		w.setPkg(t.Pkg(), true)
  1030  		w.signature(t)
  1031  
  1032  	case types.TSTRUCT:
  1033  		w.startType(structType)
  1034  		w.setPkg(t.Pkg(), true)
  1035  
  1036  		w.uint64(uint64(t.NumFields()))
  1037  		for _, f := range t.FieldSlice() {
  1038  			w.pos(f.Pos)
  1039  			w.selector(f.Sym)
  1040  			w.typ(f.Type)
  1041  			w.bool(f.Embedded != 0)
  1042  			w.string(f.Note)
  1043  		}
  1044  
  1045  	case types.TINTER:
  1046  		var embeddeds, methods []*types.Field
  1047  		for _, m := range t.Methods().Slice() {
  1048  			if m.Sym != nil {
  1049  				methods = append(methods, m)
  1050  			} else {
  1051  				embeddeds = append(embeddeds, m)
  1052  			}
  1053  		}
  1054  
  1055  		// Sort methods and embedded types, for consistency with types2.
  1056  		// Note: embedded types may be anonymous, and types2 sorts them
  1057  		// with sort.Stable too.
  1058  		if base.Debug.UnifiedQuirks != 0 {
  1059  			sort.Sort(types.MethodsByName(methods))
  1060  			sort.Stable(types.EmbeddedsByName(embeddeds))
  1061  		}
  1062  
  1063  		w.startType(interfaceType)
  1064  		w.setPkg(t.Pkg(), true)
  1065  
  1066  		w.uint64(uint64(len(embeddeds)))
  1067  		for _, f := range embeddeds {
  1068  			w.pos(f.Pos)
  1069  			w.typ(f.Type)
  1070  		}
  1071  
  1072  		w.uint64(uint64(len(methods)))
  1073  		for _, f := range methods {
  1074  			w.pos(f.Pos)
  1075  			w.selector(f.Sym)
  1076  			w.signature(f.Type)
  1077  		}
  1078  
  1079  	case types.TUNION:
  1080  		assert(base.Flag.G > 0)
  1081  		// TODO(danscales): possibly put out the tilde bools in more
  1082  		// compact form.
  1083  		w.startType(unionType)
  1084  		nt := t.NumTerms()
  1085  		w.uint64(uint64(nt))
  1086  		for i := 0; i < nt; i++ {
  1087  			typ, tilde := t.Term(i)
  1088  			w.bool(tilde)
  1089  			w.typ(typ)
  1090  		}
  1091  
  1092  	default:
  1093  		base.Fatalf("unexpected type: %v", t)
  1094  	}
  1095  }
  1096  
  1097  func (w *exportWriter) setPkg(pkg *types.Pkg, write bool) {
  1098  	if pkg == types.NoPkg {
  1099  		base.Fatalf("missing pkg")
  1100  	}
  1101  
  1102  	if write {
  1103  		w.pkg(pkg)
  1104  	}
  1105  
  1106  	w.currPkg = pkg
  1107  }
  1108  
  1109  func (w *exportWriter) signature(t *types.Type) {
  1110  	w.paramList(t.Params().FieldSlice())
  1111  	w.paramList(t.Results().FieldSlice())
  1112  	if n := t.Params().NumFields(); n > 0 {
  1113  		w.bool(t.Params().Field(n - 1).IsDDD())
  1114  	}
  1115  }
  1116  
  1117  func (w *exportWriter) typeList(ts []*types.Type) {
  1118  	w.uint64(uint64(len(ts)))
  1119  	for _, rparam := range ts {
  1120  		w.typ(rparam)
  1121  	}
  1122  }
  1123  
  1124  func (w *exportWriter) tparamList(fs []*types.Field) {
  1125  	w.uint64(uint64(len(fs)))
  1126  	for _, f := range fs {
  1127  		if !f.Type.IsTypeParam() {
  1128  			base.Fatalf("unexpected non-typeparam")
  1129  		}
  1130  		w.typ(f.Type)
  1131  	}
  1132  }
  1133  
  1134  func (w *exportWriter) paramList(fs []*types.Field) {
  1135  	w.uint64(uint64(len(fs)))
  1136  	for _, f := range fs {
  1137  		w.param(f)
  1138  	}
  1139  }
  1140  
  1141  func (w *exportWriter) param(f *types.Field) {
  1142  	w.pos(f.Pos)
  1143  	w.localIdent(types.OrigSym(f.Sym))
  1144  	w.typ(f.Type)
  1145  }
  1146  
  1147  func constTypeOf(typ *types.Type) constant.Kind {
  1148  	switch typ {
  1149  	case types.UntypedInt, types.UntypedRune:
  1150  		return constant.Int
  1151  	case types.UntypedFloat:
  1152  		return constant.Float
  1153  	case types.UntypedComplex:
  1154  		return constant.Complex
  1155  	}
  1156  
  1157  	switch typ.Kind() {
  1158  	case types.TBOOL:
  1159  		return constant.Bool
  1160  	case types.TSTRING:
  1161  		return constant.String
  1162  	case types.TINT, types.TINT8, types.TINT16, types.TINT32, types.TINT64,
  1163  		types.TUINT, types.TUINT8, types.TUINT16, types.TUINT32, types.TUINT64, types.TUINTPTR:
  1164  		return constant.Int
  1165  	case types.TFLOAT32, types.TFLOAT64:
  1166  		return constant.Float
  1167  	case types.TCOMPLEX64, types.TCOMPLEX128:
  1168  		return constant.Complex
  1169  	}
  1170  
  1171  	base.Fatalf("unexpected constant type: %v", typ)
  1172  	return 0
  1173  }
  1174  
  1175  func (w *exportWriter) value(typ *types.Type, v constant.Value) {
  1176  	w.typ(typ)
  1177  
  1178  	if iexportVersionCurrent >= iexportVersionGo1_18 {
  1179  		w.int64(int64(v.Kind()))
  1180  	}
  1181  
  1182  	var kind constant.Kind
  1183  	var valType *types.Type
  1184  
  1185  	if typ.IsTypeParam() {
  1186  		kind = v.Kind()
  1187  		if iexportVersionCurrent < iexportVersionGo1_18 {
  1188  			// A constant will have a TYPEPARAM type if it appears in a place
  1189  			// where it must match that typeparam type (e.g. in a binary
  1190  			// operation with a variable of that typeparam type). If so, then
  1191  			// we must write out its actual constant kind as well, so its
  1192  			// constant val can be read in properly during import.
  1193  			w.int64(int64(kind))
  1194  		}
  1195  
  1196  		switch kind {
  1197  		case constant.Int:
  1198  			valType = types.Types[types.TINT64]
  1199  		case constant.Float:
  1200  			valType = types.Types[types.TFLOAT64]
  1201  		case constant.Complex:
  1202  			valType = types.Types[types.TCOMPLEX128]
  1203  		}
  1204  	} else {
  1205  		ir.AssertValidTypeForConst(typ, v)
  1206  		kind = constTypeOf(typ)
  1207  		valType = typ
  1208  	}
  1209  
  1210  	// Each type has only one admissible constant representation, so we could
  1211  	// type switch directly on v.Kind() here. However, switching on the type
  1212  	// (in the non-typeparam case) increases symmetry with import logic and
  1213  	// provides a useful consistency check.
  1214  
  1215  	switch kind {
  1216  	case constant.Bool:
  1217  		w.bool(constant.BoolVal(v))
  1218  	case constant.String:
  1219  		w.string(constant.StringVal(v))
  1220  	case constant.Int:
  1221  		w.mpint(v, valType)
  1222  	case constant.Float:
  1223  		w.mpfloat(v, valType)
  1224  	case constant.Complex:
  1225  		w.mpfloat(constant.Real(v), valType)
  1226  		w.mpfloat(constant.Imag(v), valType)
  1227  	}
  1228  }
  1229  
  1230  func intSize(typ *types.Type) (signed bool, maxBytes uint) {
  1231  	if typ.IsUntyped() {
  1232  		return true, ir.ConstPrec / 8
  1233  	}
  1234  
  1235  	switch typ.Kind() {
  1236  	case types.TFLOAT32, types.TCOMPLEX64:
  1237  		return true, 3
  1238  	case types.TFLOAT64, types.TCOMPLEX128:
  1239  		return true, 7
  1240  	}
  1241  
  1242  	signed = typ.IsSigned()
  1243  	maxBytes = uint(typ.Size())
  1244  
  1245  	// The go/types API doesn't expose sizes to importers, so they
  1246  	// don't know how big these types are.
  1247  	switch typ.Kind() {
  1248  	case types.TINT, types.TUINT, types.TUINTPTR:
  1249  		maxBytes = 8
  1250  	}
  1251  
  1252  	return
  1253  }
  1254  
  1255  // mpint exports a multi-precision integer.
  1256  //
  1257  // For unsigned types, small values are written out as a single
  1258  // byte. Larger values are written out as a length-prefixed big-endian
  1259  // byte string, where the length prefix is encoded as its complement.
  1260  // For example, bytes 0, 1, and 2 directly represent the integer
  1261  // values 0, 1, and 2; while bytes 255, 254, and 253 indicate a 1-,
  1262  // 2-, and 3-byte big-endian string follow.
  1263  //
  1264  // Encoding for signed types use the same general approach as for
  1265  // unsigned types, except small values use zig-zag encoding and the
  1266  // bottom bit of length prefix byte for large values is reserved as a
  1267  // sign bit.
  1268  //
  1269  // The exact boundary between small and large encodings varies
  1270  // according to the maximum number of bytes needed to encode a value
  1271  // of type typ. As a special case, 8-bit types are always encoded as a
  1272  // single byte.
  1273  func (w *exportWriter) mpint(x constant.Value, typ *types.Type) {
  1274  	signed, maxBytes := intSize(typ)
  1275  
  1276  	negative := constant.Sign(x) < 0
  1277  	if !signed && negative {
  1278  		base.Fatalf("negative unsigned integer; type %v, value %v", typ, x)
  1279  	}
  1280  
  1281  	b := constant.Bytes(x) // little endian
  1282  	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
  1283  		b[i], b[j] = b[j], b[i]
  1284  	}
  1285  
  1286  	if len(b) > 0 && b[0] == 0 {
  1287  		base.Fatalf("leading zeros")
  1288  	}
  1289  	if uint(len(b)) > maxBytes {
  1290  		base.Fatalf("bad mpint length: %d > %d (type %v, value %v)", len(b), maxBytes, typ, x)
  1291  	}
  1292  
  1293  	maxSmall := 256 - maxBytes
  1294  	if signed {
  1295  		maxSmall = 256 - 2*maxBytes
  1296  	}
  1297  	if maxBytes == 1 {
  1298  		maxSmall = 256
  1299  	}
  1300  
  1301  	// Check if x can use small value encoding.
  1302  	if len(b) <= 1 {
  1303  		var ux uint
  1304  		if len(b) == 1 {
  1305  			ux = uint(b[0])
  1306  		}
  1307  		if signed {
  1308  			ux <<= 1
  1309  			if negative {
  1310  				ux--
  1311  			}
  1312  		}
  1313  		if ux < maxSmall {
  1314  			w.data.WriteByte(byte(ux))
  1315  			return
  1316  		}
  1317  	}
  1318  
  1319  	n := 256 - uint(len(b))
  1320  	if signed {
  1321  		n = 256 - 2*uint(len(b))
  1322  		if negative {
  1323  			n |= 1
  1324  		}
  1325  	}
  1326  	if n < maxSmall || n >= 256 {
  1327  		base.Fatalf("encoding mistake: %d, %v, %v => %d", len(b), signed, negative, n)
  1328  	}
  1329  
  1330  	w.data.WriteByte(byte(n))
  1331  	w.data.Write(b)
  1332  }
  1333  
  1334  // mpfloat exports a multi-precision floating point number.
  1335  //
  1336  // The number's value is decomposed into mantissa × 2**exponent, where
  1337  // mantissa is an integer. The value is written out as mantissa (as a
  1338  // multi-precision integer) and then the exponent, except exponent is
  1339  // omitted if mantissa is zero.
  1340  func (w *exportWriter) mpfloat(v constant.Value, typ *types.Type) {
  1341  	f := ir.BigFloat(v)
  1342  	if f.IsInf() {
  1343  		base.Fatalf("infinite constant")
  1344  	}
  1345  
  1346  	// Break into f = mant × 2**exp, with 0.5 <= mant < 1.
  1347  	var mant big.Float
  1348  	exp := int64(f.MantExp(&mant))
  1349  
  1350  	// Scale so that mant is an integer.
  1351  	prec := mant.MinPrec()
  1352  	mant.SetMantExp(&mant, int(prec))
  1353  	exp -= int64(prec)
  1354  
  1355  	manti, acc := mant.Int(nil)
  1356  	if acc != big.Exact {
  1357  		base.Fatalf("mantissa scaling failed for %f (%s)", f, acc)
  1358  	}
  1359  	w.mpint(constant.Make(manti), typ)
  1360  	if manti.Sign() != 0 {
  1361  		w.int64(exp)
  1362  	}
  1363  }
  1364  
  1365  func (w *exportWriter) mprat(v constant.Value) {
  1366  	r, ok := constant.Val(v).(*big.Rat)
  1367  	if !w.bool(ok) {
  1368  		return
  1369  	}
  1370  	// TODO(mdempsky): Come up with a more efficient binary
  1371  	// encoding before bumping iexportVersion to expose to
  1372  	// gcimporter.
  1373  	w.string(r.String())
  1374  }
  1375  
  1376  func (w *exportWriter) bool(b bool) bool {
  1377  	var x uint64
  1378  	if b {
  1379  		x = 1
  1380  	}
  1381  	w.uint64(x)
  1382  	return b
  1383  }
  1384  
  1385  func (w *exportWriter) int64(x int64)   { w.data.int64(x) }
  1386  func (w *exportWriter) uint64(x uint64) { w.data.uint64(x) }
  1387  func (w *exportWriter) string(s string) { w.uint64(w.p.stringOff(s)) }
  1388  
  1389  // Compiler-specific extensions.
  1390  
  1391  func (w *exportWriter) constExt(n *ir.Name) {
  1392  	// Internally, we now represent untyped float and complex
  1393  	// constants with infinite-precision rational numbers using
  1394  	// go/constant, but the "public" export data format known to
  1395  	// gcimporter only supports 512-bit floating point constants.
  1396  	// In case rationals turn out to be a bad idea and we want to
  1397  	// switch back to fixed-precision constants, for now we
  1398  	// continue writing out the 512-bit truncation in the public
  1399  	// data section, and write the exact, rational constant in the
  1400  	// compiler's extension data. Also, we only need to worry
  1401  	// about exporting rationals for declared constants, because
  1402  	// constants that appear in an expression will already have
  1403  	// been coerced to a concrete, fixed-precision type.
  1404  	//
  1405  	// Eventually, assuming we stick with using rationals, we
  1406  	// should bump iexportVersion to support rationals, and do the
  1407  	// whole gcimporter update song-and-dance.
  1408  	//
  1409  	// TODO(mdempsky): Prepare vocals for that.
  1410  
  1411  	switch n.Type() {
  1412  	case types.UntypedFloat:
  1413  		w.mprat(n.Val())
  1414  	case types.UntypedComplex:
  1415  		v := n.Val()
  1416  		w.mprat(constant.Real(v))
  1417  		w.mprat(constant.Imag(v))
  1418  	}
  1419  }
  1420  
  1421  func (w *exportWriter) varExt(n *ir.Name) {
  1422  	w.linkname(n.Sym())
  1423  	w.symIdx(n.Sym())
  1424  }
  1425  
  1426  func (w *exportWriter) funcExt(n *ir.Name) {
  1427  	w.linkname(n.Sym())
  1428  	w.symIdx(n.Sym())
  1429  
  1430  	// Record definition ABI so cross-ABI calls can be direct.
  1431  	// This is important for the performance of calling some
  1432  	// common functions implemented in assembly (e.g., bytealg).
  1433  	w.uint64(uint64(n.Func.ABI))
  1434  
  1435  	w.uint64(uint64(n.Func.Pragma))
  1436  
  1437  	// Escape analysis.
  1438  	for _, fs := range &types.RecvsParams {
  1439  		for _, f := range fs(n.Type()).FieldSlice() {
  1440  			w.string(f.Note)
  1441  		}
  1442  	}
  1443  
  1444  	// Write out inline body or body of a generic function/method.
  1445  	if n.Type().HasTParam() && n.Func.Body != nil && n.Func.Inl == nil {
  1446  		base.FatalfAt(n.Pos(), "generic function is not marked inlineable")
  1447  	}
  1448  	if n.Func.Inl != nil {
  1449  		w.uint64(1 + uint64(n.Func.Inl.Cost))
  1450  		w.bool(n.Func.Inl.CanDelayResults)
  1451  		if n.Func.ExportInline() || n.Type().HasTParam() {
  1452  			if n.Type().HasTParam() {
  1453  				// If this generic function/method is from another
  1454  				// package, but we didn't use for instantiation in
  1455  				// this package, we may not yet have imported it.
  1456  				ImportedBody(n.Func)
  1457  			}
  1458  			w.p.doInline(n)
  1459  		}
  1460  
  1461  		// Endlineno for inlined function.
  1462  		w.pos(n.Func.Endlineno)
  1463  	} else {
  1464  		w.uint64(0)
  1465  	}
  1466  }
  1467  
  1468  func (w *exportWriter) methExt(m *types.Field) {
  1469  	w.bool(m.Nointerface())
  1470  	w.funcExt(m.Nname.(*ir.Name))
  1471  }
  1472  
  1473  func (w *exportWriter) linkname(s *types.Sym) {
  1474  	w.string(s.Linkname)
  1475  }
  1476  
  1477  func (w *exportWriter) symIdx(s *types.Sym) {
  1478  	lsym := s.Linksym()
  1479  	if lsym.PkgIdx > goobj.PkgIdxSelf || (lsym.PkgIdx == goobj.PkgIdxInvalid && !lsym.Indexed()) || s.Linkname != "" {
  1480  		// Don't export index for non-package symbols, linkname'd symbols,
  1481  		// and symbols without an index. They can only be referenced by
  1482  		// name.
  1483  		w.int64(-1)
  1484  	} else {
  1485  		// For a defined symbol, export its index.
  1486  		// For re-exporting an imported symbol, pass its index through.
  1487  		w.int64(int64(lsym.SymIdx))
  1488  	}
  1489  }
  1490  
  1491  func (w *exportWriter) typeExt(t *types.Type) {
  1492  	// Export whether this type is marked notinheap.
  1493  	w.bool(t.NotInHeap())
  1494  	// For type T, export the index of type descriptor symbols of T and *T.
  1495  	if i, ok := typeSymIdx[t]; ok {
  1496  		w.int64(i[0])
  1497  		w.int64(i[1])
  1498  		return
  1499  	}
  1500  	w.symIdx(types.TypeSym(t))
  1501  	w.symIdx(types.TypeSym(t.PtrTo()))
  1502  }
  1503  
  1504  // Inline bodies.
  1505  
  1506  func (w *exportWriter) writeNames(dcl []*ir.Name) {
  1507  	w.int64(int64(len(dcl)))
  1508  	for i, n := range dcl {
  1509  		w.pos(n.Pos())
  1510  		w.localIdent(n.Sym())
  1511  		w.typ(n.Type())
  1512  		w.dclIndex[n] = w.maxDclIndex + i
  1513  	}
  1514  	w.maxDclIndex += len(dcl)
  1515  }
  1516  
  1517  func (w *exportWriter) funcBody(fn *ir.Func) {
  1518  	//fmt.Printf("Exporting %s\n", fn.Nname.Sym().Name)
  1519  	w.writeNames(fn.Inl.Dcl)
  1520  
  1521  	w.stmtList(fn.Inl.Body)
  1522  }
  1523  
  1524  func (w *exportWriter) stmtList(list []ir.Node) {
  1525  	for _, n := range list {
  1526  		w.node(n)
  1527  	}
  1528  	w.op(ir.OEND)
  1529  }
  1530  
  1531  func (w *exportWriter) node(n ir.Node) {
  1532  	if ir.OpPrec[n.Op()] < 0 {
  1533  		w.stmt(n)
  1534  	} else {
  1535  		w.expr(n)
  1536  	}
  1537  }
  1538  
  1539  func isNonEmptyAssign(n ir.Node) bool {
  1540  	switch n.Op() {
  1541  	case ir.OAS:
  1542  		if n.(*ir.AssignStmt).Y != nil {
  1543  			return true
  1544  		}
  1545  	case ir.OAS2, ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2RECV:
  1546  		return true
  1547  	}
  1548  	return false
  1549  }
  1550  
  1551  // Caution: stmt will emit more than one node for statement nodes n that have a
  1552  // non-empty n.Ninit and where n is not a non-empty assignment or a node with a natural init
  1553  // section (such as in "if", "for", etc.).
  1554  func (w *exportWriter) stmt(n ir.Node) {
  1555  	if len(n.Init()) > 0 && !ir.StmtWithInit(n.Op()) && !isNonEmptyAssign(n) && n.Op() != ir.ORANGE {
  1556  		// can't use stmtList here since we don't want the final OEND
  1557  		for _, n := range n.Init() {
  1558  			w.stmt(n)
  1559  		}
  1560  	}
  1561  
  1562  	switch n.Op() {
  1563  	case ir.OBLOCK:
  1564  		// No OBLOCK in export data.
  1565  		// Inline content into this statement list,
  1566  		// like the init list above.
  1567  		// (At the moment neither the parser nor the typechecker
  1568  		// generate OBLOCK nodes except to denote an empty
  1569  		// function body, although that may change.)
  1570  		n := n.(*ir.BlockStmt)
  1571  		for _, n := range n.List {
  1572  			w.stmt(n)
  1573  		}
  1574  
  1575  	case ir.ODCL:
  1576  		n := n.(*ir.Decl)
  1577  		if ir.IsBlank(n.X) {
  1578  			return // blank declarations not useful to importers
  1579  		}
  1580  		w.op(ir.ODCL)
  1581  		w.localName(n.X)
  1582  
  1583  	case ir.OAS:
  1584  		// Don't export "v = <N>" initializing statements, hope they're always
  1585  		// preceded by the DCL which will be re-parsed and typecheck to reproduce
  1586  		// the "v = <N>" again.
  1587  		n := n.(*ir.AssignStmt)
  1588  		if n.Y != nil {
  1589  			w.op(ir.OAS)
  1590  			w.pos(n.Pos())
  1591  			w.stmtList(n.Init())
  1592  			w.expr(n.X)
  1593  			w.expr(n.Y)
  1594  			w.bool(n.Def)
  1595  		}
  1596  
  1597  	case ir.OASOP:
  1598  		n := n.(*ir.AssignOpStmt)
  1599  		w.op(ir.OASOP)
  1600  		w.pos(n.Pos())
  1601  		w.op(n.AsOp)
  1602  		w.expr(n.X)
  1603  		if w.bool(!n.IncDec) {
  1604  			w.expr(n.Y)
  1605  		}
  1606  
  1607  	case ir.OAS2, ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2RECV:
  1608  		n := n.(*ir.AssignListStmt)
  1609  		if go117ExportTypes {
  1610  			w.op(n.Op())
  1611  		} else {
  1612  			w.op(ir.OAS2)
  1613  		}
  1614  		w.pos(n.Pos())
  1615  		w.stmtList(n.Init())
  1616  		w.exprList(n.Lhs)
  1617  		w.exprList(n.Rhs)
  1618  		w.bool(n.Def)
  1619  
  1620  	case ir.ORETURN:
  1621  		n := n.(*ir.ReturnStmt)
  1622  		w.op(ir.ORETURN)
  1623  		w.pos(n.Pos())
  1624  		w.exprList(n.Results)
  1625  
  1626  	// case ORETJMP:
  1627  	// 	unreachable - generated by compiler for trampoline routines
  1628  
  1629  	case ir.OGO, ir.ODEFER:
  1630  		n := n.(*ir.GoDeferStmt)
  1631  		w.op(n.Op())
  1632  		w.pos(n.Pos())
  1633  		w.expr(n.Call)
  1634  
  1635  	case ir.OIF:
  1636  		n := n.(*ir.IfStmt)
  1637  		w.op(ir.OIF)
  1638  		w.pos(n.Pos())
  1639  		w.stmtList(n.Init())
  1640  		w.expr(n.Cond)
  1641  		w.stmtList(n.Body)
  1642  		w.stmtList(n.Else)
  1643  
  1644  	case ir.OFOR:
  1645  		n := n.(*ir.ForStmt)
  1646  		w.op(ir.OFOR)
  1647  		w.pos(n.Pos())
  1648  		w.stmtList(n.Init())
  1649  		w.exprsOrNil(n.Cond, n.Post)
  1650  		w.stmtList(n.Body)
  1651  
  1652  	case ir.ORANGE:
  1653  		n := n.(*ir.RangeStmt)
  1654  		w.op(ir.ORANGE)
  1655  		w.pos(n.Pos())
  1656  		w.stmtList(n.Init())
  1657  		w.exprsOrNil(n.Key, n.Value)
  1658  		w.expr(n.X)
  1659  		w.stmtList(n.Body)
  1660  
  1661  	case ir.OSELECT:
  1662  		n := n.(*ir.SelectStmt)
  1663  		w.op(n.Op())
  1664  		w.pos(n.Pos())
  1665  		w.stmtList(n.Init())
  1666  		w.commList(n.Cases)
  1667  
  1668  	case ir.OSWITCH:
  1669  		n := n.(*ir.SwitchStmt)
  1670  		w.op(n.Op())
  1671  		w.pos(n.Pos())
  1672  		w.stmtList(n.Init())
  1673  		w.exprsOrNil(n.Tag, nil)
  1674  		w.caseList(n.Cases, isNamedTypeSwitch(n.Tag))
  1675  
  1676  	// case OCASE:
  1677  	//	handled by caseList
  1678  
  1679  	case ir.OFALL:
  1680  		n := n.(*ir.BranchStmt)
  1681  		w.op(ir.OFALL)
  1682  		w.pos(n.Pos())
  1683  
  1684  	case ir.OBREAK, ir.OCONTINUE, ir.OGOTO, ir.OLABEL:
  1685  		w.op(n.Op())
  1686  		w.pos(n.Pos())
  1687  		label := ""
  1688  		if sym := n.Sym(); sym != nil {
  1689  			label = sym.Name
  1690  		}
  1691  		w.string(label)
  1692  
  1693  	default:
  1694  		base.Fatalf("exporter: CANNOT EXPORT: %v\nPlease notify gri@\n", n.Op())
  1695  	}
  1696  }
  1697  
  1698  func isNamedTypeSwitch(x ir.Node) bool {
  1699  	guard, ok := x.(*ir.TypeSwitchGuard)
  1700  	return ok && guard.Tag != nil
  1701  }
  1702  
  1703  func (w *exportWriter) caseList(cases []*ir.CaseClause, namedTypeSwitch bool) {
  1704  	w.uint64(uint64(len(cases)))
  1705  	for _, cas := range cases {
  1706  		w.pos(cas.Pos())
  1707  		w.stmtList(cas.List)
  1708  		if namedTypeSwitch {
  1709  			w.localName(cas.Var)
  1710  		}
  1711  		w.stmtList(cas.Body)
  1712  	}
  1713  }
  1714  
  1715  func (w *exportWriter) commList(cases []*ir.CommClause) {
  1716  	w.uint64(uint64(len(cases)))
  1717  	for _, cas := range cases {
  1718  		w.pos(cas.Pos())
  1719  		defaultCase := cas.Comm == nil
  1720  		w.bool(defaultCase)
  1721  		if !defaultCase {
  1722  			// Only call w.node for non-default cause (cas.Comm is non-nil)
  1723  			w.node(cas.Comm)
  1724  		}
  1725  		w.stmtList(cas.Body)
  1726  	}
  1727  }
  1728  
  1729  func (w *exportWriter) exprList(list ir.Nodes) {
  1730  	for _, n := range list {
  1731  		w.expr(n)
  1732  	}
  1733  	w.op(ir.OEND)
  1734  }
  1735  
  1736  func simplifyForExport(n ir.Node) ir.Node {
  1737  	switch n.Op() {
  1738  	case ir.OPAREN:
  1739  		n := n.(*ir.ParenExpr)
  1740  		return simplifyForExport(n.X)
  1741  	}
  1742  	return n
  1743  }
  1744  
  1745  func (w *exportWriter) expr(n ir.Node) {
  1746  	n = simplifyForExport(n)
  1747  	switch n.Op() {
  1748  	// expressions
  1749  	// (somewhat closely following the structure of exprfmt in fmt.go)
  1750  	case ir.ONIL:
  1751  		n := n.(*ir.NilExpr)
  1752  		// If n is a typeparam, it will have already been checked
  1753  		// for proper use by the types2 typechecker.
  1754  		if !n.Type().IsTypeParam() && !n.Type().HasNil() {
  1755  			base.Fatalf("unexpected type for nil: %v", n.Type())
  1756  		}
  1757  		w.op(ir.ONIL)
  1758  		w.pos(n.Pos())
  1759  		w.typ(n.Type())
  1760  
  1761  	case ir.OLITERAL:
  1762  		w.op(ir.OLITERAL)
  1763  		if ir.HasUniquePos(n) {
  1764  			w.pos(n.Pos())
  1765  		} else {
  1766  			w.pos(src.NoXPos)
  1767  		}
  1768  		w.value(n.Type(), n.Val())
  1769  
  1770  	case ir.ONAME:
  1771  		// Package scope name.
  1772  		n := n.(*ir.Name)
  1773  		if (n.Class == ir.PEXTERN || n.Class == ir.PFUNC) && !ir.IsBlank(n) {
  1774  			w.op(ir.ONONAME)
  1775  			// Indicate that this is not an OKEY entry.
  1776  			w.bool(false)
  1777  			w.qualifiedIdent(n)
  1778  			if go117ExportTypes {
  1779  				w.typ(n.Type())
  1780  			}
  1781  			break
  1782  		}
  1783  
  1784  		// Function scope name.
  1785  		// We don't need a type here, as the type will be provided at the
  1786  		// declaration of n.
  1787  		w.op(ir.ONAME)
  1788  
  1789  		// This handles the case where we haven't yet transformed a call
  1790  		// to a builtin, so we must write out the builtin as a name in the
  1791  		// builtin package.
  1792  		isBuiltin := n.BuiltinOp != ir.OXXX
  1793  		w.bool(isBuiltin)
  1794  		if isBuiltin {
  1795  			w.bool(n.Sym().Pkg == types.UnsafePkg)
  1796  			w.string(n.Sym().Name)
  1797  			break
  1798  		}
  1799  		w.localName(n)
  1800  
  1801  	case ir.ONONAME:
  1802  		w.op(ir.ONONAME)
  1803  		// This can only be for OKEY nodes in generic functions. Mark it
  1804  		// as a key entry.
  1805  		w.bool(true)
  1806  		s := n.Sym()
  1807  		w.string(s.Name)
  1808  		w.pkg(s.Pkg)
  1809  		if go117ExportTypes {
  1810  			w.typ(n.Type())
  1811  		}
  1812  
  1813  	// case OPACK:
  1814  	// 	should have been resolved by typechecking - handled by default case
  1815  
  1816  	case ir.OTYPE:
  1817  		w.op(ir.OTYPE)
  1818  		w.typ(n.Type())
  1819  
  1820  	case ir.ODYNAMICTYPE:
  1821  		n := n.(*ir.DynamicType)
  1822  		w.op(ir.ODYNAMICTYPE)
  1823  		w.pos(n.Pos())
  1824  		w.expr(n.X)
  1825  		if n.ITab != nil {
  1826  			w.bool(true)
  1827  			w.expr(n.ITab)
  1828  		} else {
  1829  			w.bool(false)
  1830  		}
  1831  		w.typ(n.Type())
  1832  
  1833  	case ir.OTYPESW:
  1834  		n := n.(*ir.TypeSwitchGuard)
  1835  		w.op(ir.OTYPESW)
  1836  		w.pos(n.Pos())
  1837  		var s *types.Sym
  1838  		if n.Tag != nil {
  1839  			if n.Tag.Op() != ir.ONONAME {
  1840  				base.Fatalf("expected ONONAME, got %v", n.Tag)
  1841  			}
  1842  			s = n.Tag.Sym()
  1843  		}
  1844  		w.localIdent(s) // declared pseudo-variable, if any
  1845  		w.expr(n.X)
  1846  
  1847  	// case OTARRAY, OTMAP, OTCHAN, OTSTRUCT, OTINTER, OTFUNC:
  1848  	// 	should have been resolved by typechecking - handled by default case
  1849  
  1850  	case ir.OCLOSURE:
  1851  		n := n.(*ir.ClosureExpr)
  1852  		w.op(ir.OCLOSURE)
  1853  		w.pos(n.Pos())
  1854  		old := w.currPkg
  1855  		w.setPkg(n.Type().Pkg(), true)
  1856  		w.signature(n.Type())
  1857  		w.setPkg(old, true)
  1858  
  1859  		// Write out id for the Outer of each conditional variable. The
  1860  		// conditional variable itself for this closure will be re-created
  1861  		// during import.
  1862  		w.int64(int64(len(n.Func.ClosureVars)))
  1863  		for i, cv := range n.Func.ClosureVars {
  1864  			w.pos(cv.Pos())
  1865  			w.localName(cv.Outer)
  1866  			// Closure variable (which will be re-created during
  1867  			// import) is given via a negative id, starting at -2,
  1868  			// which is used to refer to it later in the function
  1869  			// during export. -1 represents blanks.
  1870  			w.dclIndex[cv] = -(i + 2) - w.maxClosureVarIndex
  1871  		}
  1872  		w.maxClosureVarIndex += len(n.Func.ClosureVars)
  1873  
  1874  		// like w.funcBody(n.Func), but not for .Inl
  1875  		w.writeNames(n.Func.Dcl)
  1876  		w.stmtList(n.Func.Body)
  1877  
  1878  	// case OCOMPLIT:
  1879  	// 	should have been resolved by typechecking - handled by default case
  1880  
  1881  	case ir.OPTRLIT:
  1882  		n := n.(*ir.AddrExpr)
  1883  		if go117ExportTypes {
  1884  			w.op(ir.OPTRLIT)
  1885  		} else {
  1886  			w.op(ir.OADDR)
  1887  		}
  1888  		w.pos(n.Pos())
  1889  		w.expr(n.X)
  1890  		if go117ExportTypes {
  1891  			w.typ(n.Type())
  1892  		}
  1893  
  1894  	case ir.OSTRUCTLIT:
  1895  		n := n.(*ir.CompLitExpr)
  1896  		w.op(ir.OSTRUCTLIT)
  1897  		w.pos(n.Pos())
  1898  		w.typ(n.Type())
  1899  		w.fieldList(n.List) // special handling of field names
  1900  
  1901  	case ir.OCOMPLIT, ir.OARRAYLIT, ir.OSLICELIT, ir.OMAPLIT:
  1902  		n := n.(*ir.CompLitExpr)
  1903  		if go117ExportTypes {
  1904  			w.op(n.Op())
  1905  		} else {
  1906  			w.op(ir.OCOMPLIT)
  1907  		}
  1908  		w.pos(n.Pos())
  1909  		w.typ(n.Type())
  1910  		w.exprList(n.List)
  1911  		if go117ExportTypes && n.Op() == ir.OSLICELIT {
  1912  			w.uint64(uint64(n.Len))
  1913  		}
  1914  	case ir.OKEY:
  1915  		n := n.(*ir.KeyExpr)
  1916  		w.op(ir.OKEY)
  1917  		w.pos(n.Pos())
  1918  		w.expr(n.Key)
  1919  		w.expr(n.Value)
  1920  
  1921  	// case OSTRUCTKEY:
  1922  	//	unreachable - handled in case OSTRUCTLIT by elemList
  1923  
  1924  	case ir.OXDOT, ir.ODOT, ir.ODOTPTR, ir.ODOTINTER, ir.ODOTMETH, ir.OMETHVALUE, ir.OMETHEXPR:
  1925  		n := n.(*ir.SelectorExpr)
  1926  		if go117ExportTypes {
  1927  			// For go117ExportTypes, we usually see all ops except
  1928  			// OXDOT, but we can see OXDOT for generic functions.
  1929  			w.op(n.Op())
  1930  		} else {
  1931  			w.op(ir.OXDOT)
  1932  		}
  1933  		w.pos(n.Pos())
  1934  		w.expr(n.X)
  1935  		w.exoticSelector(n.Sel)
  1936  		if go117ExportTypes {
  1937  			w.exoticType(n.Type())
  1938  			if n.Op() == ir.OXDOT {
  1939  				// n.Selection for method references will be
  1940  				// reconstructed during import.
  1941  				w.bool(n.Selection != nil)
  1942  			} else if n.Op() == ir.ODOT || n.Op() == ir.ODOTPTR || n.Op() == ir.ODOTINTER {
  1943  				w.exoticField(n.Selection)
  1944  			}
  1945  			// n.Selection is not required for OMETHEXPR, ODOTMETH, and OMETHVALUE. It will
  1946  			// be reconstructed during import.  n.Selection is computed during
  1947  			// transformDot() for OXDOT.
  1948  		}
  1949  
  1950  	case ir.ODOTTYPE, ir.ODOTTYPE2:
  1951  		n := n.(*ir.TypeAssertExpr)
  1952  		if go117ExportTypes {
  1953  			w.op(n.Op())
  1954  		} else {
  1955  			w.op(ir.ODOTTYPE)
  1956  		}
  1957  		w.pos(n.Pos())
  1958  		w.expr(n.X)
  1959  		w.typ(n.Type())
  1960  
  1961  	case ir.ODYNAMICDOTTYPE, ir.ODYNAMICDOTTYPE2:
  1962  		n := n.(*ir.DynamicTypeAssertExpr)
  1963  		w.op(n.Op())
  1964  		w.pos(n.Pos())
  1965  		w.expr(n.X)
  1966  		w.expr(n.T)
  1967  		w.typ(n.Type())
  1968  
  1969  	case ir.OINDEX, ir.OINDEXMAP:
  1970  		n := n.(*ir.IndexExpr)
  1971  		if go117ExportTypes {
  1972  			w.op(n.Op())
  1973  		} else {
  1974  			w.op(ir.OINDEX)
  1975  		}
  1976  		w.pos(n.Pos())
  1977  		w.expr(n.X)
  1978  		w.expr(n.Index)
  1979  		if go117ExportTypes {
  1980  			w.exoticType(n.Type())
  1981  			if n.Op() == ir.OINDEXMAP {
  1982  				w.bool(n.Assigned)
  1983  			}
  1984  		}
  1985  
  1986  	case ir.OSLICE, ir.OSLICESTR, ir.OSLICEARR:
  1987  		n := n.(*ir.SliceExpr)
  1988  		if go117ExportTypes {
  1989  			w.op(n.Op())
  1990  		} else {
  1991  			w.op(ir.OSLICE)
  1992  		}
  1993  		w.pos(n.Pos())
  1994  		w.expr(n.X)
  1995  		w.exprsOrNil(n.Low, n.High)
  1996  		if go117ExportTypes {
  1997  			w.typ(n.Type())
  1998  		}
  1999  
  2000  	case ir.OSLICE3, ir.OSLICE3ARR:
  2001  		n := n.(*ir.SliceExpr)
  2002  		if go117ExportTypes {
  2003  			w.op(n.Op())
  2004  		} else {
  2005  			w.op(ir.OSLICE3)
  2006  		}
  2007  		w.pos(n.Pos())
  2008  		w.expr(n.X)
  2009  		w.exprsOrNil(n.Low, n.High)
  2010  		w.expr(n.Max)
  2011  		if go117ExportTypes {
  2012  			w.typ(n.Type())
  2013  		}
  2014  
  2015  	case ir.OCOPY, ir.OCOMPLEX, ir.OUNSAFEADD, ir.OUNSAFESLICE:
  2016  		// treated like other builtin calls (see e.g., OREAL)
  2017  		n := n.(*ir.BinaryExpr)
  2018  		w.op(n.Op())
  2019  		w.pos(n.Pos())
  2020  		w.expr(n.X)
  2021  		w.expr(n.Y)
  2022  		if go117ExportTypes {
  2023  			w.typ(n.Type())
  2024  		} else {
  2025  			w.op(ir.OEND)
  2026  		}
  2027  
  2028  	case ir.OCONV, ir.OCONVIFACE, ir.OCONVIDATA, ir.OCONVNOP, ir.OBYTES2STR, ir.ORUNES2STR, ir.OSTR2BYTES, ir.OSTR2RUNES, ir.ORUNESTR, ir.OSLICE2ARRPTR:
  2029  		n := n.(*ir.ConvExpr)
  2030  		if go117ExportTypes {
  2031  			w.op(n.Op())
  2032  		} else {
  2033  			w.op(ir.OCONV)
  2034  		}
  2035  		w.pos(n.Pos())
  2036  		w.typ(n.Type())
  2037  		w.expr(n.X)
  2038  
  2039  	case ir.OREAL, ir.OIMAG, ir.OCAP, ir.OCLOSE, ir.OLEN, ir.ONEW, ir.OPANIC:
  2040  		n := n.(*ir.UnaryExpr)
  2041  		w.op(n.Op())
  2042  		w.pos(n.Pos())
  2043  		w.expr(n.X)
  2044  		if go117ExportTypes {
  2045  			if n.Op() != ir.OPANIC {
  2046  				w.typ(n.Type())
  2047  			}
  2048  		} else {
  2049  			w.op(ir.OEND)
  2050  		}
  2051  
  2052  	case ir.OAPPEND, ir.ODELETE, ir.ORECOVER, ir.OPRINT, ir.OPRINTN:
  2053  		n := n.(*ir.CallExpr)
  2054  		w.op(n.Op())
  2055  		w.pos(n.Pos())
  2056  		w.exprList(n.Args) // emits terminating OEND
  2057  		// only append() calls may contain '...' arguments
  2058  		if n.Op() == ir.OAPPEND {
  2059  			w.bool(n.IsDDD)
  2060  		} else if n.IsDDD {
  2061  			base.Fatalf("exporter: unexpected '...' with %v call", n.Op())
  2062  		}
  2063  		if go117ExportTypes {
  2064  			if n.Op() != ir.ODELETE && n.Op() != ir.OPRINT && n.Op() != ir.OPRINTN {
  2065  				w.typ(n.Type())
  2066  			}
  2067  		}
  2068  
  2069  	case ir.OCALL, ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER, ir.OGETG:
  2070  		n := n.(*ir.CallExpr)
  2071  		if go117ExportTypes {
  2072  			w.op(n.Op())
  2073  		} else {
  2074  			w.op(ir.OCALL)
  2075  		}
  2076  		w.pos(n.Pos())
  2077  		w.stmtList(n.Init())
  2078  		w.expr(n.X)
  2079  		w.exprList(n.Args)
  2080  		w.bool(n.IsDDD)
  2081  		if go117ExportTypes {
  2082  			w.exoticType(n.Type())
  2083  		}
  2084  
  2085  	case ir.OMAKEMAP, ir.OMAKECHAN, ir.OMAKESLICE:
  2086  		n := n.(*ir.MakeExpr)
  2087  		w.op(n.Op()) // must keep separate from OMAKE for importer
  2088  		w.pos(n.Pos())
  2089  		w.typ(n.Type())
  2090  		switch {
  2091  		default:
  2092  			// empty list
  2093  			w.op(ir.OEND)
  2094  		case n.Cap != nil:
  2095  			w.expr(n.Len)
  2096  			w.expr(n.Cap)
  2097  			w.op(ir.OEND)
  2098  		case n.Len != nil && (n.Op() == ir.OMAKESLICE || !n.Len.Type().IsUntyped()):
  2099  			// Note: the extra conditional exists because make(T) for
  2100  			// T a map or chan type, gets an untyped zero added as
  2101  			// an argument. Don't serialize that argument here.
  2102  			w.expr(n.Len)
  2103  			w.op(ir.OEND)
  2104  		case n.Len != nil && go117ExportTypes:
  2105  			w.expr(n.Len)
  2106  			w.op(ir.OEND)
  2107  		}
  2108  
  2109  	case ir.OLINKSYMOFFSET:
  2110  		n := n.(*ir.LinksymOffsetExpr)
  2111  		w.op(ir.OLINKSYMOFFSET)
  2112  		w.pos(n.Pos())
  2113  		w.string(n.Linksym.Name)
  2114  		w.uint64(uint64(n.Offset_))
  2115  		w.typ(n.Type())
  2116  
  2117  	// unary expressions
  2118  	case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT, ir.ORECV, ir.OIDATA:
  2119  		n := n.(*ir.UnaryExpr)
  2120  		w.op(n.Op())
  2121  		w.pos(n.Pos())
  2122  		w.expr(n.X)
  2123  		if go117ExportTypes {
  2124  			w.typ(n.Type())
  2125  		}
  2126  
  2127  	case ir.OADDR:
  2128  		n := n.(*ir.AddrExpr)
  2129  		w.op(n.Op())
  2130  		w.pos(n.Pos())
  2131  		w.expr(n.X)
  2132  		if go117ExportTypes {
  2133  			w.typ(n.Type())
  2134  		}
  2135  
  2136  	case ir.ODEREF:
  2137  		n := n.(*ir.StarExpr)
  2138  		w.op(n.Op())
  2139  		w.pos(n.Pos())
  2140  		w.expr(n.X)
  2141  		if go117ExportTypes {
  2142  			w.typ(n.Type())
  2143  		}
  2144  
  2145  	case ir.OSEND:
  2146  		n := n.(*ir.SendStmt)
  2147  		w.op(n.Op())
  2148  		w.pos(n.Pos())
  2149  		w.expr(n.Chan)
  2150  		w.expr(n.Value)
  2151  
  2152  	// binary expressions
  2153  	case ir.OADD, ir.OAND, ir.OANDNOT, ir.ODIV, ir.OEQ, ir.OGE, ir.OGT, ir.OLE, ir.OLT,
  2154  		ir.OLSH, ir.OMOD, ir.OMUL, ir.ONE, ir.OOR, ir.ORSH, ir.OSUB, ir.OXOR, ir.OEFACE:
  2155  		n := n.(*ir.BinaryExpr)
  2156  		w.op(n.Op())
  2157  		w.pos(n.Pos())
  2158  		w.expr(n.X)
  2159  		w.expr(n.Y)
  2160  		if go117ExportTypes {
  2161  			w.typ(n.Type())
  2162  		}
  2163  
  2164  	case ir.OANDAND, ir.OOROR:
  2165  		n := n.(*ir.LogicalExpr)
  2166  		w.op(n.Op())
  2167  		w.pos(n.Pos())
  2168  		w.expr(n.X)
  2169  		w.expr(n.Y)
  2170  		if go117ExportTypes {
  2171  			w.typ(n.Type())
  2172  		}
  2173  
  2174  	case ir.OADDSTR:
  2175  		n := n.(*ir.AddStringExpr)
  2176  		w.op(ir.OADDSTR)
  2177  		w.pos(n.Pos())
  2178  		w.exprList(n.List)
  2179  		if go117ExportTypes {
  2180  			w.typ(n.Type())
  2181  		}
  2182  
  2183  	case ir.ODCLCONST:
  2184  		// if exporting, DCLCONST should just be removed as its usage
  2185  		// has already been replaced with literals
  2186  
  2187  	case ir.OFUNCINST:
  2188  		n := n.(*ir.InstExpr)
  2189  		w.op(ir.OFUNCINST)
  2190  		w.pos(n.Pos())
  2191  		w.expr(n.X)
  2192  		w.uint64(uint64(len(n.Targs)))
  2193  		for _, targ := range n.Targs {
  2194  			w.typ(targ.Type())
  2195  		}
  2196  		if go117ExportTypes {
  2197  			w.typ(n.Type())
  2198  		}
  2199  
  2200  	case ir.OSELRECV2:
  2201  		n := n.(*ir.AssignListStmt)
  2202  		w.op(ir.OSELRECV2)
  2203  		w.pos(n.Pos())
  2204  		w.stmtList(n.Init())
  2205  		w.exprList(n.Lhs)
  2206  		w.exprList(n.Rhs)
  2207  		w.bool(n.Def)
  2208  
  2209  	default:
  2210  		base.Fatalf("cannot export %v (%d) node\n"+
  2211  			"\t==> please file an issue and assign to gri@", n.Op(), int(n.Op()))
  2212  	}
  2213  }
  2214  
  2215  func (w *exportWriter) op(op ir.Op) {
  2216  	if debug {
  2217  		w.uint64(magic)
  2218  	}
  2219  	w.uint64(uint64(op))
  2220  }
  2221  
  2222  func (w *exportWriter) exprsOrNil(a, b ir.Node) {
  2223  	ab := 0
  2224  	if a != nil {
  2225  		ab |= 1
  2226  	}
  2227  	if b != nil {
  2228  		ab |= 2
  2229  	}
  2230  	w.uint64(uint64(ab))
  2231  	if ab&1 != 0 {
  2232  		w.expr(a)
  2233  	}
  2234  	if ab&2 != 0 {
  2235  		w.node(b)
  2236  	}
  2237  }
  2238  
  2239  func (w *exportWriter) fieldList(list ir.Nodes) {
  2240  	w.uint64(uint64(len(list)))
  2241  	for _, n := range list {
  2242  		n := n.(*ir.StructKeyExpr)
  2243  		w.pos(n.Pos())
  2244  		w.exoticField(n.Field)
  2245  		w.expr(n.Value)
  2246  	}
  2247  }
  2248  
  2249  func (w *exportWriter) localName(n *ir.Name) {
  2250  	if ir.IsBlank(n) {
  2251  		w.int64(-1)
  2252  		return
  2253  	}
  2254  
  2255  	i, ok := w.dclIndex[n]
  2256  	if !ok {
  2257  		base.FatalfAt(n.Pos(), "missing from dclIndex: %+v", n)
  2258  	}
  2259  	w.int64(int64(i))
  2260  }
  2261  
  2262  func (w *exportWriter) localIdent(s *types.Sym) {
  2263  	if w.currPkg == nil {
  2264  		base.Fatalf("missing currPkg")
  2265  	}
  2266  
  2267  	// Anonymous parameters.
  2268  	if s == nil {
  2269  		w.string("")
  2270  		return
  2271  	}
  2272  
  2273  	name := s.Name
  2274  	if name == "_" {
  2275  		w.string("_")
  2276  		return
  2277  	}
  2278  
  2279  	// The name of autotmp variables isn't important; they just need to
  2280  	// be unique. To stabilize the export data, simply write out "$" as
  2281  	// a marker and let the importer generate its own unique name.
  2282  	if strings.HasPrefix(name, ".autotmp_") {
  2283  		w.string("$autotmp")
  2284  		return
  2285  	}
  2286  
  2287  	if i := strings.LastIndex(name, "."); i >= 0 && !strings.HasPrefix(name, LocalDictName) && !strings.HasPrefix(name, ".rcvr") {
  2288  		base.Fatalf("unexpected dot in identifier: %v", name)
  2289  	}
  2290  
  2291  	if s.Pkg != w.currPkg {
  2292  		base.Fatalf("weird package in name: %v => %v from %q, not %q", s, name, s.Pkg.Path, w.currPkg.Path)
  2293  	}
  2294  
  2295  	w.string(name)
  2296  }
  2297  
  2298  type intWriter struct {
  2299  	bytes.Buffer
  2300  }
  2301  
  2302  func (w *intWriter) int64(x int64) {
  2303  	var buf [binary.MaxVarintLen64]byte
  2304  	n := binary.PutVarint(buf[:], x)
  2305  	w.Write(buf[:n])
  2306  }
  2307  
  2308  func (w *intWriter) uint64(x uint64) {
  2309  	var buf [binary.MaxVarintLen64]byte
  2310  	n := binary.PutUvarint(buf[:], x)
  2311  	w.Write(buf[:n])
  2312  }
  2313  
  2314  // If go117ExportTypes is true, then we write type information when
  2315  // exporting function bodies, so those function bodies don't need to
  2316  // be re-typechecked on import.
  2317  // This flag adds some other info to the serialized stream as well
  2318  // which was previously recomputed during typechecking, like
  2319  // specializing opcodes (e.g. OXDOT to ODOTPTR) and ancillary
  2320  // information (e.g. length field for OSLICELIT).
  2321  const go117ExportTypes = true
  2322  const Go117ExportTypes = go117ExportTypes
  2323  
  2324  // The name used for dictionary parameters or local variables.
  2325  const LocalDictName = ".dict"
  2326  

View as plain text