github.com/mangodowner/go-gm@v0.0.0-20180818020936-8baa2bd4408c/src/cmd/compile/internal/gc/bexport.go (about)

     1  // Copyright 2015 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  // Binary package export.
     6  
     7  /*
     8  1) Export data encoding principles:
     9  
    10  The export data is a serialized description of the graph of exported
    11  "objects": constants, types, variables, and functions. Aliases may be
    12  directly reexported, and unaliased types may be indirectly reexported
    13  (as part of the type of a directly exported object). More generally,
    14  objects referred to from inlined function bodies can be reexported.
    15  We need to know which package declares these reexported objects, and
    16  therefore packages are also part of the export graph.
    17  
    18  The roots of the graph are two lists of objects. The 1st list (phase 1,
    19  see Export) contains all objects that are exported at the package level.
    20  These objects are the full representation of the package's API, and they
    21  are the only information a platform-independent tool (e.g., go/types)
    22  needs to know to type-check against a package.
    23  
    24  The 2nd list of objects contains all objects referred to from exported
    25  inlined function bodies. These objects are needed by the compiler to
    26  make sense of the function bodies; the exact list contents are compiler-
    27  specific.
    28  
    29  Finally, the export data contains a list of representations for inlined
    30  function bodies. The format of this representation is compiler specific.
    31  
    32  The graph is serialized in in-order fashion, starting with the roots.
    33  Each object in the graph is serialized by writing its fields sequentially.
    34  If the field is a pointer to another object, that object is serialized in
    35  place, recursively. Otherwise the field is written in place. Non-pointer
    36  fields are all encoded as integer or string values.
    37  
    38  Some objects (packages, types) may be referred to more than once. When
    39  reaching an object that was not serialized before, an integer _index_
    40  is assigned to it, starting at 0. In this case, the encoding starts
    41  with an integer _tag_ < 0. The tag value indicates the kind of object
    42  that follows and that this is the first time that we see this object.
    43  If the object was already serialized, the encoding is simply the object
    44  index >= 0. An importer can trivially determine if an object needs to
    45  be read in for the first time (tag < 0) and entered into the respective
    46  object table, or if the object was seen already (index >= 0), in which
    47  case the index is used to look up the object in the respective table.
    48  
    49  Before exporting or importing, the type tables are populated with the
    50  predeclared types (int, string, error, unsafe.Pointer, etc.). This way
    51  they are automatically encoded with a known and fixed type index.
    52  
    53  2) Encoding format:
    54  
    55  The export data starts with two newline-terminated strings: a version
    56  string and either an empty string, or "debug", when emitting the debug
    57  format. These strings are followed by version-specific encoding options.
    58  
    59  (The Go1.7 version starts with a couple of bytes specifying the format.
    60  That format encoding is no longer used but is supported to avoid spurious
    61  errors when importing old installed package files.)
    62  
    63  This header is followed by the package object for the exported package,
    64  two lists of objects, and the list of inlined function bodies.
    65  
    66  The encoding of objects is straight-forward: Constants, variables, and
    67  functions start with their name, type, and possibly a value. Named types
    68  record their name and package so that they can be canonicalized: If the
    69  same type was imported before via another import, the importer must use
    70  the previously imported type pointer so that we have exactly one version
    71  (i.e., one pointer) for each named type (and read but discard the current
    72  type encoding). Unnamed types simply encode their respective fields.
    73  Aliases are encoded starting with their name followed by the qualified
    74  identifier denoting the original (aliased) object, which was exported
    75  earlier.
    76  
    77  In the encoding, some lists start with the list length. Some lists are
    78  terminated with an end marker (usually for lists where we may not know
    79  the length a priori).
    80  
    81  Integers use variable-length encoding for compact representation.
    82  
    83  Strings are canonicalized similar to objects that may occur multiple times:
    84  If the string was exported already, it is represented by its index only.
    85  Otherwise, the export data starts with the negative string length (negative,
    86  so we can distinguish from string index), followed by the string bytes.
    87  The empty string is mapped to index 0. (The initial format string is an
    88  exception; it is encoded as the string bytes followed by a newline).
    89  
    90  The exporter and importer are completely symmetric in implementation: For
    91  each encoding routine there is a matching and symmetric decoding routine.
    92  This symmetry makes it very easy to change or extend the format: If a new
    93  field needs to be encoded, a symmetric change can be made to exporter and
    94  importer.
    95  
    96  3) Making changes to the encoding format:
    97  
    98  Any change to the encoding format requires a respective change in the
    99  exporter below and a corresponding symmetric change to the importer in
   100  bimport.go.
   101  
   102  Furthermore, it requires a corresponding change to go/internal/gcimporter
   103  and golang.org/x/tools/go/gcimporter15. Changes to the latter must preserve
   104  compatibility with both the last release of the compiler, and with the
   105  corresponding compiler at tip. That change is necessarily more involved,
   106  as it must switch based on the version number in the export data file.
   107  
   108  It is recommended to turn on debugFormat temporarily when working on format
   109  changes as it will help finding encoding/decoding inconsistencies quickly.
   110  */
   111  
   112  package gc
   113  
   114  import (
   115  	"bufio"
   116  	"bytes"
   117  	"cmd/compile/internal/types"
   118  	"encoding/binary"
   119  	"fmt"
   120  	"math/big"
   121  	"sort"
   122  	"strings"
   123  )
   124  
   125  // If debugFormat is set, each integer and string value is preceded by a marker
   126  // and position information in the encoding. This mechanism permits an importer
   127  // to recognize immediately when it is out of sync. The importer recognizes this
   128  // mode automatically (i.e., it can import export data produced with debugging
   129  // support even if debugFormat is not set at the time of import). This mode will
   130  // lead to massively larger export data (by a factor of 2 to 3) and should only
   131  // be enabled during development and debugging.
   132  //
   133  // NOTE: This flag is the first flag to enable if importing dies because of
   134  // (suspected) format errors, and whenever a change is made to the format.
   135  const debugFormat = false // default: false
   136  
   137  // Current export format version. Increase with each format change.
   138  // 5: improved position encoding efficiency (issue 20080, CL 41619)
   139  // 4: type name objects support type aliases, uses aliasTag
   140  // 3: Go1.8 encoding (same as version 2, aliasTag defined but never used)
   141  // 2: removed unused bool in ODCL export (compiler only)
   142  // 1: header format change (more regular), export package for _ struct fields
   143  // 0: Go1.7 encoding
   144  const exportVersion = 5
   145  
   146  // exportInlined enables the export of inlined function bodies and related
   147  // dependencies. The compiler should work w/o any loss of functionality with
   148  // the flag disabled, but the generated code will lose access to inlined
   149  // function bodies across packages, leading to performance bugs.
   150  // Leave for debugging.
   151  const exportInlined = true // default: true
   152  
   153  // trackAllTypes enables cycle tracking for all types, not just named
   154  // types. The existing compiler invariants assume that unnamed types
   155  // that are not completely set up are not used, or else there are spurious
   156  // errors.
   157  // If disabled, only named types are tracked, possibly leading to slightly
   158  // less efficient encoding in rare cases. It also prevents the export of
   159  // some corner-case type declarations (but those were not handled correctly
   160  // with the former textual export format either).
   161  // Note that when a type is only seen once, as many unnamed types are,
   162  // it is less efficient to track it, since we then also record an index for it.
   163  // See CLs 41622 and 41623 for some data and discussion.
   164  // TODO(gri) enable selectively and remove once issues caused by it are fixed
   165  const trackAllTypes = false
   166  
   167  type exporter struct {
   168  	out *bufio.Writer
   169  
   170  	// object -> index maps, indexed in order of serialization
   171  	strIndex  map[string]int
   172  	pathIndex map[string]int
   173  	pkgIndex  map[*types.Pkg]int
   174  	typIndex  map[*types.Type]int
   175  	funcList  []*Func
   176  
   177  	// position encoding
   178  	posInfoFormat bool
   179  	prevFile      string
   180  	prevLine      int
   181  
   182  	// debugging support
   183  	written int // bytes written
   184  	indent  int // for p.trace
   185  	trace   bool
   186  }
   187  
   188  // export writes the exportlist for localpkg to out and returns the number of bytes written.
   189  func export(out *bufio.Writer, trace bool) int {
   190  	p := exporter{
   191  		out:           out,
   192  		strIndex:      map[string]int{"": 0}, // empty string is mapped to 0
   193  		pathIndex:     map[string]int{"": 0}, // empty path is mapped to 0
   194  		pkgIndex:      make(map[*types.Pkg]int),
   195  		typIndex:      make(map[*types.Type]int),
   196  		posInfoFormat: true,
   197  		trace:         trace,
   198  	}
   199  
   200  	// write version info
   201  	// The version string must start with "version %d" where %d is the version
   202  	// number. Additional debugging information may follow after a blank; that
   203  	// text is ignored by the importer.
   204  	p.rawStringln(fmt.Sprintf("version %d", exportVersion))
   205  	var debug string
   206  	if debugFormat {
   207  		debug = "debug"
   208  	}
   209  	p.rawStringln(debug) // cannot use p.bool since it's affected by debugFormat; also want to see this clearly
   210  	p.bool(trackAllTypes)
   211  	p.bool(p.posInfoFormat)
   212  
   213  	// --- generic export data ---
   214  
   215  	// populate type map with predeclared "known" types
   216  	predecl := predeclared()
   217  	for index, typ := range predecl {
   218  		p.typIndex[typ] = index
   219  	}
   220  	if len(p.typIndex) != len(predecl) {
   221  		Fatalf("exporter: duplicate entries in type map?")
   222  	}
   223  
   224  	// write package data
   225  	if localpkg.Path != "" {
   226  		Fatalf("exporter: local package path not empty: %q", localpkg.Path)
   227  	}
   228  	p.pkg(localpkg)
   229  	if p.trace {
   230  		p.tracef("\n")
   231  	}
   232  
   233  	// export objects
   234  	//
   235  	// First, export all exported (package-level) objects; i.e., all objects
   236  	// in the current exportlist. These objects represent all information
   237  	// required to import this package and type-check against it; i.e., this
   238  	// is the platform-independent export data. The format is generic in the
   239  	// sense that different compilers can use the same representation.
   240  	//
   241  	// During this first phase, more objects may be added to the exportlist
   242  	// (due to inlined function bodies and their dependencies). Export those
   243  	// objects in a second phase. That data is platform-specific as it depends
   244  	// on the inlining decisions of the compiler and the representation of the
   245  	// inlined function bodies.
   246  
   247  	// remember initial exportlist length
   248  	var numglobals = len(exportlist)
   249  
   250  	// Phase 1: Export objects in _current_ exportlist; exported objects at
   251  	//          package level.
   252  	// Use range since we want to ignore objects added to exportlist during
   253  	// this phase.
   254  	objcount := 0
   255  	for _, n := range exportlist {
   256  		sym := n.Sym
   257  
   258  		if sym.Exported() {
   259  			continue
   260  		}
   261  		sym.SetExported(true)
   262  
   263  		// TODO(gri) Closures have dots in their names;
   264  		// e.g., TestFloatZeroValue.func1 in math/big tests.
   265  		if strings.Contains(sym.Name, ".") {
   266  			Fatalf("exporter: unexpected symbol: %v", sym)
   267  		}
   268  
   269  		if sym.Def == nil {
   270  			Fatalf("exporter: unknown export symbol: %v", sym)
   271  		}
   272  
   273  		// TODO(gri) Optimization: Probably worthwhile collecting
   274  		// long runs of constants and export them "in bulk" (saving
   275  		// tags and types, and making import faster).
   276  
   277  		if p.trace {
   278  			p.tracef("\n")
   279  		}
   280  		p.obj(sym)
   281  		objcount++
   282  	}
   283  
   284  	// indicate end of list
   285  	if p.trace {
   286  		p.tracef("\n")
   287  	}
   288  	p.tag(endTag)
   289  
   290  	// for self-verification only (redundant)
   291  	p.int(objcount)
   292  
   293  	// --- compiler-specific export data ---
   294  
   295  	if p.trace {
   296  		p.tracef("\n--- compiler-specific export data ---\n[ ")
   297  		if p.indent != 0 {
   298  			Fatalf("exporter: incorrect indentation")
   299  		}
   300  	}
   301  
   302  	// write compiler-specific flags
   303  	if p.trace {
   304  		p.tracef("\n")
   305  	}
   306  
   307  	// Phase 2: Export objects added to exportlist during phase 1.
   308  	// Don't use range since exportlist may grow during this phase
   309  	// and we want to export all remaining objects.
   310  	objcount = 0
   311  	for i := numglobals; exportInlined && i < len(exportlist); i++ {
   312  		n := exportlist[i]
   313  		sym := n.Sym
   314  
   315  		// TODO(gri) The rest of this loop body is identical with
   316  		// the loop body above. Leave alone for now since there
   317  		// are different optimization opportunities, but factor
   318  		// eventually.
   319  
   320  		if sym.Exported() {
   321  			continue
   322  		}
   323  		sym.SetExported(true)
   324  
   325  		// TODO(gri) Closures have dots in their names;
   326  		// e.g., TestFloatZeroValue.func1 in math/big tests.
   327  		if strings.Contains(sym.Name, ".") {
   328  			Fatalf("exporter: unexpected symbol: %v", sym)
   329  		}
   330  
   331  		if sym.Def == nil {
   332  			Fatalf("exporter: unknown export symbol: %v", sym)
   333  		}
   334  
   335  		// TODO(gri) Optimization: Probably worthwhile collecting
   336  		// long runs of constants and export them "in bulk" (saving
   337  		// tags and types, and making import faster).
   338  
   339  		if p.trace {
   340  			p.tracef("\n")
   341  		}
   342  
   343  		if IsAlias(sym) {
   344  			Fatalf("exporter: unexpected type alias %v in inlined function body", sym)
   345  		}
   346  
   347  		p.obj(sym)
   348  		objcount++
   349  	}
   350  
   351  	// indicate end of list
   352  	if p.trace {
   353  		p.tracef("\n")
   354  	}
   355  	p.tag(endTag)
   356  
   357  	// for self-verification only (redundant)
   358  	p.int(objcount)
   359  
   360  	// --- inlined function bodies ---
   361  
   362  	if p.trace {
   363  		p.tracef("\n--- inlined function bodies ---\n")
   364  		if p.indent != 0 {
   365  			Fatalf("exporter: incorrect indentation")
   366  		}
   367  	}
   368  
   369  	// write inlineable function bodies
   370  	// Don't use range since funcList may grow.
   371  	objcount = 0
   372  	for i := 0; i < len(p.funcList); i++ {
   373  		if f := p.funcList[i]; f != nil {
   374  			// function has inlineable body:
   375  			// write index and body
   376  			if p.trace {
   377  				p.tracef("\n----\nfunc { %#v }\n", f.Inl)
   378  			}
   379  			p.int(i)
   380  			p.stmtList(f.Inl)
   381  			if p.trace {
   382  				p.tracef("\n")
   383  			}
   384  			objcount++
   385  		}
   386  	}
   387  
   388  	// indicate end of list
   389  	if p.trace {
   390  		p.tracef("\n")
   391  	}
   392  	p.int(-1) // invalid index terminates list
   393  
   394  	// for self-verification only (redundant)
   395  	p.int(objcount)
   396  
   397  	if p.trace {
   398  		p.tracef("\n--- end ---\n")
   399  	}
   400  
   401  	// --- end of export data ---
   402  
   403  	return p.written
   404  }
   405  
   406  func (p *exporter) pkg(pkg *types.Pkg) {
   407  	if pkg == nil {
   408  		Fatalf("exporter: unexpected nil pkg")
   409  	}
   410  
   411  	// if we saw the package before, write its index (>= 0)
   412  	if i, ok := p.pkgIndex[pkg]; ok {
   413  		p.index('P', i)
   414  		return
   415  	}
   416  
   417  	// otherwise, remember the package, write the package tag (< 0) and package data
   418  	if p.trace {
   419  		p.tracef("P%d = { ", len(p.pkgIndex))
   420  		defer p.tracef("} ")
   421  	}
   422  	p.pkgIndex[pkg] = len(p.pkgIndex)
   423  
   424  	p.tag(packageTag)
   425  	p.string(pkg.Name)
   426  	p.path(pkg.Path)
   427  }
   428  
   429  func unidealType(typ *types.Type, val Val) *types.Type {
   430  	// Untyped (ideal) constants get their own type. This decouples
   431  	// the constant type from the encoding of the constant value.
   432  	if typ == nil || typ.IsUntyped() {
   433  		typ = untype(val.Ctype())
   434  	}
   435  	return typ
   436  }
   437  
   438  func (p *exporter) obj(sym *types.Sym) {
   439  	// Exported objects may be from different packages because they
   440  	// may be re-exported via an exported alias or as dependencies in
   441  	// exported inlined function bodies. Thus, exported object names
   442  	// must be fully qualified.
   443  	//
   444  	// (This can only happen for aliased objects or during phase 2
   445  	// (exportInlined enabled) of object export. Unaliased Objects
   446  	// exported in phase 1 (compiler-indendepent objects) are by
   447  	// definition only the objects from the current package and not
   448  	// pulled in via inlined function bodies. In that case the package
   449  	// qualifier is not needed. Possible space optimization.)
   450  
   451  	n := asNode(sym.Def)
   452  	switch n.Op {
   453  	case OLITERAL:
   454  		// constant
   455  		// TODO(gri) determine if we need the typecheck call here
   456  		n = typecheck(n, Erv)
   457  		if n == nil || n.Op != OLITERAL {
   458  			Fatalf("exporter: dumpexportconst: oconst nil: %v", sym)
   459  		}
   460  
   461  		p.tag(constTag)
   462  		p.pos(n)
   463  		// TODO(gri) In inlined functions, constants are used directly
   464  		// so they should never occur as re-exported objects. We may
   465  		// not need the qualified name here. See also comment above.
   466  		// Possible space optimization.
   467  		p.qualifiedName(sym)
   468  		p.typ(unidealType(n.Type, n.Val()))
   469  		p.value(n.Val())
   470  
   471  	case OTYPE:
   472  		// named type
   473  		t := n.Type
   474  		if t.Etype == TFORW {
   475  			Fatalf("exporter: export of incomplete type %v", sym)
   476  		}
   477  
   478  		if IsAlias(sym) {
   479  			p.tag(aliasTag)
   480  			p.pos(n)
   481  			p.qualifiedName(sym)
   482  		} else {
   483  			p.tag(typeTag)
   484  		}
   485  		p.typ(t)
   486  
   487  	case ONAME:
   488  		// variable or function
   489  		n = typecheck(n, Erv|Ecall)
   490  		if n == nil || n.Type == nil {
   491  			Fatalf("exporter: variable/function exported but not defined: %v", sym)
   492  		}
   493  
   494  		if n.Type.Etype == TFUNC && n.Class() == PFUNC {
   495  			// function
   496  			p.tag(funcTag)
   497  			p.pos(n)
   498  			p.qualifiedName(sym)
   499  
   500  			sig := asNode(sym.Def).Type
   501  			inlineable := isInlineable(asNode(sym.Def))
   502  
   503  			p.paramList(sig.Params(), inlineable)
   504  			p.paramList(sig.Results(), inlineable)
   505  
   506  			var f *Func
   507  			if inlineable {
   508  				f = asNode(sym.Def).Func
   509  				// TODO(gri) re-examine reexportdeplist:
   510  				// Because we can trivially export types
   511  				// in-place, we don't need to collect types
   512  				// inside function bodies in the exportlist.
   513  				// With an adjusted reexportdeplist used only
   514  				// by the binary exporter, we can also avoid
   515  				// the global exportlist.
   516  				reexportdeplist(f.Inl)
   517  			}
   518  			p.funcList = append(p.funcList, f)
   519  		} else {
   520  			// variable
   521  			p.tag(varTag)
   522  			p.pos(n)
   523  			p.qualifiedName(sym)
   524  			p.typ(asNode(sym.Def).Type)
   525  		}
   526  
   527  	default:
   528  		Fatalf("exporter: unexpected export symbol: %v %v", n.Op, sym)
   529  	}
   530  }
   531  
   532  // deltaNewFile is a magic line delta offset indicating a new file.
   533  // We use -64 because it is rare; see issue 20080 and CL 41619.
   534  // -64 is the smallest int that fits in a single byte as a varint.
   535  const deltaNewFile = -64
   536  
   537  func (p *exporter) pos(n *Node) {
   538  	if !p.posInfoFormat {
   539  		return
   540  	}
   541  
   542  	file, line := fileLine(n)
   543  	if file == p.prevFile {
   544  		// common case: write line delta
   545  		// delta == deltaNewFile means different file
   546  		// if the actual line delta is deltaNewFile,
   547  		// follow up with a negative int to indicate that.
   548  		// only non-negative ints can follow deltaNewFile
   549  		// when writing a new file.
   550  		delta := line - p.prevLine
   551  		p.int(delta)
   552  		if delta == deltaNewFile {
   553  			p.int(-1) // -1 means no file change
   554  		}
   555  	} else {
   556  		// different file
   557  		p.int(deltaNewFile)
   558  		p.int(line) // line >= 0
   559  		p.path(file)
   560  		p.prevFile = file
   561  	}
   562  	p.prevLine = line
   563  }
   564  
   565  func (p *exporter) path(s string) {
   566  	if i, ok := p.pathIndex[s]; ok {
   567  		// Note: Using p.index(i) here requires the use of p.tag(-len(c)) below
   568  		//       to get matching debug markers ('t'). But in trace mode p.tag
   569  		//       assumes that the tag argument is a valid tag that can be looked
   570  		//       up in the tagString list, rather then some arbitrary slice length.
   571  		//       Use p.int instead.
   572  		p.int(i) // i >= 0
   573  		return
   574  	}
   575  	p.pathIndex[s] = len(p.pathIndex)
   576  	c := strings.Split(s, "/")
   577  	p.int(-len(c)) // -len(c) < 0
   578  	for _, x := range c {
   579  		p.string(x)
   580  	}
   581  }
   582  
   583  func fileLine(n *Node) (file string, line int) {
   584  	if n != nil {
   585  		pos := Ctxt.PosTable.Pos(n.Pos)
   586  		file = pos.Base().AbsFilename()
   587  		line = int(pos.RelLine())
   588  	}
   589  	return
   590  }
   591  
   592  func isInlineable(n *Node) bool {
   593  	if exportInlined && n != nil && n.Func != nil && n.Func.Inl.Len() != 0 {
   594  		// when lazily typechecking inlined bodies, some re-exported ones may not have been typechecked yet.
   595  		// currently that can leave unresolved ONONAMEs in import-dot-ed packages in the wrong package
   596  		if Debug['l'] < 2 {
   597  			typecheckinl(n)
   598  		}
   599  		return true
   600  	}
   601  	return false
   602  }
   603  
   604  var errorInterface *types.Type // lazily initialized
   605  
   606  func (p *exporter) typ(t *types.Type) {
   607  	if t == nil {
   608  		Fatalf("exporter: nil type")
   609  	}
   610  
   611  	// Possible optimization: Anonymous pointer types *T where
   612  	// T is a named type are common. We could canonicalize all
   613  	// such types *T to a single type PT = *T. This would lead
   614  	// to at most one *T entry in typIndex, and all future *T's
   615  	// would be encoded as the respective index directly. Would
   616  	// save 1 byte (pointerTag) per *T and reduce the typIndex
   617  	// size (at the cost of a canonicalization map). We can do
   618  	// this later, without encoding format change.
   619  
   620  	// if we saw the type before, write its index (>= 0)
   621  	if i, ok := p.typIndex[t]; ok {
   622  		p.index('T', i)
   623  		return
   624  	}
   625  
   626  	// otherwise, remember the type, write the type tag (< 0) and type data
   627  	if trackAllTypes {
   628  		if p.trace {
   629  			p.tracef("T%d = {>\n", len(p.typIndex))
   630  			defer p.tracef("<\n} ")
   631  		}
   632  		p.typIndex[t] = len(p.typIndex)
   633  	}
   634  
   635  	// pick off named types
   636  	if tsym := t.Sym; tsym != nil {
   637  		if !trackAllTypes {
   638  			// if we don't track all types, track named types now
   639  			p.typIndex[t] = len(p.typIndex)
   640  		}
   641  
   642  		// Predeclared types should have been found in the type map.
   643  		if t.Orig == t {
   644  			Fatalf("exporter: predeclared type missing from type map?")
   645  		}
   646  
   647  		n := typenod(t)
   648  		if n.Type != t {
   649  			Fatalf("exporter: named type definition incorrectly set up")
   650  		}
   651  
   652  		p.tag(namedTag)
   653  		p.pos(n)
   654  		p.qualifiedName(tsym)
   655  
   656  		// write underlying type
   657  		orig := t.Orig
   658  		if orig == types.Errortype {
   659  			// The error type is the only predeclared type which has
   660  			// a composite underlying type. When we encode that type,
   661  			// make sure to encode the underlying interface rather than
   662  			// the named type again. See also the comment in universe.go
   663  			// regarding the errortype and issue #15920.
   664  			if errorInterface == nil {
   665  				errorInterface = makeErrorInterface()
   666  			}
   667  			orig = errorInterface
   668  		}
   669  		p.typ(orig)
   670  
   671  		// interfaces don't have associated methods
   672  		if t.Orig.IsInterface() {
   673  			return
   674  		}
   675  
   676  		// sort methods for reproducible export format
   677  		// TODO(gri) Determine if they are already sorted
   678  		// in which case we can drop this step.
   679  		var methods []*types.Field
   680  		for _, m := range t.Methods().Slice() {
   681  			methods = append(methods, m)
   682  		}
   683  		sort.Sort(methodbyname(methods))
   684  		p.int(len(methods))
   685  
   686  		if p.trace && len(methods) > 0 {
   687  			p.tracef("associated methods {>")
   688  		}
   689  
   690  		for _, m := range methods {
   691  			if p.trace {
   692  				p.tracef("\n")
   693  			}
   694  			if strings.Contains(m.Sym.Name, ".") {
   695  				Fatalf("invalid symbol name: %s (%v)", m.Sym.Name, m.Sym)
   696  			}
   697  
   698  			p.pos(asNode(m.Nname))
   699  			p.fieldSym(m.Sym, false)
   700  
   701  			sig := m.Type
   702  			mfn := asNode(sig.FuncType().Nname)
   703  			inlineable := isInlineable(mfn)
   704  
   705  			p.paramList(sig.Recvs(), inlineable)
   706  			p.paramList(sig.Params(), inlineable)
   707  			p.paramList(sig.Results(), inlineable)
   708  			p.bool(m.Nointerface()) // record go:nointerface pragma value (see also #16243)
   709  
   710  			var f *Func
   711  			if inlineable {
   712  				f = mfn.Func
   713  				reexportdeplist(mfn.Func.Inl)
   714  			}
   715  			p.funcList = append(p.funcList, f)
   716  		}
   717  
   718  		if p.trace && len(methods) > 0 {
   719  			p.tracef("<\n} ")
   720  		}
   721  
   722  		return
   723  	}
   724  
   725  	// otherwise we have a type literal
   726  	switch t.Etype {
   727  	case TARRAY:
   728  		if t.IsDDDArray() {
   729  			Fatalf("array bounds should be known at export time: %v", t)
   730  		}
   731  		p.tag(arrayTag)
   732  		p.int64(t.NumElem())
   733  		p.typ(t.Elem())
   734  
   735  	case TSLICE:
   736  		p.tag(sliceTag)
   737  		p.typ(t.Elem())
   738  
   739  	case TDDDFIELD:
   740  		// see p.param use of TDDDFIELD
   741  		p.tag(dddTag)
   742  		p.typ(t.DDDField())
   743  
   744  	case TSTRUCT:
   745  		p.tag(structTag)
   746  		p.fieldList(t)
   747  
   748  	case TPTR32, TPTR64: // could use Tptr but these are constants
   749  		p.tag(pointerTag)
   750  		p.typ(t.Elem())
   751  
   752  	case TFUNC:
   753  		p.tag(signatureTag)
   754  		p.paramList(t.Params(), false)
   755  		p.paramList(t.Results(), false)
   756  
   757  	case TINTER:
   758  		p.tag(interfaceTag)
   759  		p.methodList(t)
   760  
   761  	case TMAP:
   762  		p.tag(mapTag)
   763  		p.typ(t.Key())
   764  		p.typ(t.Val())
   765  
   766  	case TCHAN:
   767  		p.tag(chanTag)
   768  		p.int(int(t.ChanDir()))
   769  		p.typ(t.Elem())
   770  
   771  	default:
   772  		Fatalf("exporter: unexpected type: %v (Etype = %d)", t, t.Etype)
   773  	}
   774  }
   775  
   776  func (p *exporter) qualifiedName(sym *types.Sym) {
   777  	p.string(sym.Name)
   778  	p.pkg(sym.Pkg)
   779  }
   780  
   781  func (p *exporter) fieldList(t *types.Type) {
   782  	if p.trace && t.NumFields() > 0 {
   783  		p.tracef("fields {>")
   784  		defer p.tracef("<\n} ")
   785  	}
   786  
   787  	p.int(t.NumFields())
   788  	for _, f := range t.Fields().Slice() {
   789  		if p.trace {
   790  			p.tracef("\n")
   791  		}
   792  		p.field(f)
   793  	}
   794  }
   795  
   796  func (p *exporter) field(f *types.Field) {
   797  	p.pos(asNode(f.Nname))
   798  	p.fieldName(f)
   799  	p.typ(f.Type)
   800  	p.string(f.Note)
   801  }
   802  
   803  func (p *exporter) methodList(t *types.Type) {
   804  	var embeddeds, methods []*types.Field
   805  
   806  	for _, m := range t.Methods().Slice() {
   807  		if m.Sym != nil {
   808  			methods = append(methods, m)
   809  		} else {
   810  			embeddeds = append(embeddeds, m)
   811  		}
   812  	}
   813  
   814  	if p.trace && len(embeddeds) > 0 {
   815  		p.tracef("embeddeds {>")
   816  	}
   817  	p.int(len(embeddeds))
   818  	for _, m := range embeddeds {
   819  		if p.trace {
   820  			p.tracef("\n")
   821  		}
   822  		p.pos(asNode(m.Nname))
   823  		p.typ(m.Type)
   824  	}
   825  	if p.trace && len(embeddeds) > 0 {
   826  		p.tracef("<\n} ")
   827  	}
   828  
   829  	if p.trace && len(methods) > 0 {
   830  		p.tracef("methods {>")
   831  	}
   832  	p.int(len(methods))
   833  	for _, m := range methods {
   834  		if p.trace {
   835  			p.tracef("\n")
   836  		}
   837  		p.method(m)
   838  	}
   839  	if p.trace && len(methods) > 0 {
   840  		p.tracef("<\n} ")
   841  	}
   842  }
   843  
   844  func (p *exporter) method(m *types.Field) {
   845  	p.pos(asNode(m.Nname))
   846  	p.methodName(m.Sym)
   847  	p.paramList(m.Type.Params(), false)
   848  	p.paramList(m.Type.Results(), false)
   849  }
   850  
   851  func (p *exporter) fieldName(t *types.Field) {
   852  	name := t.Sym.Name
   853  	if t.Embedded != 0 {
   854  		// anonymous field - we distinguish between 3 cases:
   855  		// 1) field name matches base type name and is exported
   856  		// 2) field name matches base type name and is not exported
   857  		// 3) field name doesn't match base type name (alias name)
   858  		bname := basetypeName(t.Type)
   859  		if name == bname {
   860  			if exportname(name) {
   861  				name = "" // 1) we don't need to know the field name or package
   862  			} else {
   863  				name = "?" // 2) use unexported name "?" to force package export
   864  			}
   865  		} else {
   866  			// 3) indicate alias and export name as is
   867  			// (this requires an extra "@" but this is a rare case)
   868  			p.string("@")
   869  		}
   870  	}
   871  	p.string(name)
   872  	if name != "" && !exportname(name) {
   873  		p.pkg(t.Sym.Pkg)
   874  	}
   875  }
   876  
   877  // methodName is like qualifiedName but it doesn't record the package for exported names.
   878  func (p *exporter) methodName(sym *types.Sym) {
   879  	p.string(sym.Name)
   880  	if !exportname(sym.Name) {
   881  		p.pkg(sym.Pkg)
   882  	}
   883  }
   884  
   885  func basetypeName(t *types.Type) string {
   886  	s := t.Sym
   887  	if s == nil && t.IsPtr() {
   888  		s = t.Elem().Sym // deref
   889  	}
   890  	if s != nil {
   891  		return s.Name
   892  	}
   893  	return "" // unnamed type
   894  }
   895  
   896  func (p *exporter) paramList(params *types.Type, numbered bool) {
   897  	if !params.IsFuncArgStruct() {
   898  		Fatalf("exporter: parameter list expected")
   899  	}
   900  
   901  	// use negative length to indicate unnamed parameters
   902  	// (look at the first parameter only since either all
   903  	// names are present or all are absent)
   904  	//
   905  	// TODO(gri) If we don't have an exported function
   906  	// body, the parameter names are irrelevant for the
   907  	// compiler (though they may be of use for other tools).
   908  	// Possible space optimization.
   909  	n := params.NumFields()
   910  	if n > 0 && parName(params.Field(0), numbered) == "" {
   911  		n = -n
   912  	}
   913  	p.int(n)
   914  	for _, q := range params.Fields().Slice() {
   915  		p.param(q, n, numbered)
   916  	}
   917  }
   918  
   919  func (p *exporter) param(q *types.Field, n int, numbered bool) {
   920  	t := q.Type
   921  	if q.Isddd() {
   922  		// create a fake type to encode ... just for the p.typ call
   923  		t = types.NewDDDField(t.Elem())
   924  	}
   925  	p.typ(t)
   926  	if n > 0 {
   927  		name := parName(q, numbered)
   928  		if name == "" {
   929  			// Sometimes we see an empty name even for n > 0.
   930  			// This appears to happen for interface methods
   931  			// with _ (blank) parameter names. Make sure we
   932  			// have a proper name and package so we don't crash
   933  			// during import (see also issue #15470).
   934  			// (parName uses "" instead of "?" as in fmt.go)
   935  			// TODO(gri) review parameter name encoding
   936  			name = "_"
   937  		}
   938  		p.string(name)
   939  		if name != "_" {
   940  			// Because of (re-)exported inlined functions
   941  			// the importpkg may not be the package to which this
   942  			// function (and thus its parameter) belongs. We need to
   943  			// supply the parameter package here. We need the package
   944  			// when the function is inlined so we can properly resolve
   945  			// the name. The _ (blank) parameter cannot be accessed, so
   946  			// we don't need to export a package.
   947  			//
   948  			// TODO(gri) This is compiler-specific. Try using importpkg
   949  			// here and then update the symbols if we find an inlined
   950  			// body only. Otherwise, the parameter name is ignored and
   951  			// the package doesn't matter. This would remove an int
   952  			// (likely 1 byte) for each named parameter.
   953  			p.pkg(q.Sym.Pkg)
   954  		}
   955  	}
   956  	// TODO(gri) This is compiler-specific (escape info).
   957  	// Move into compiler-specific section eventually?
   958  	// (Not having escape info causes tests to fail, e.g. runtime GCInfoTest)
   959  	p.string(q.Note)
   960  }
   961  
   962  func parName(f *types.Field, numbered bool) string {
   963  	s := f.Sym
   964  	if s == nil {
   965  		return ""
   966  	}
   967  
   968  	// Take the name from the original, lest we substituted it with ~r%d or ~b%d.
   969  	// ~r%d is a (formerly) unnamed result.
   970  	if asNode(f.Nname) != nil {
   971  		if asNode(f.Nname).Orig != nil {
   972  			s = asNode(f.Nname).Orig.Sym
   973  			if s != nil && s.Name[0] == '~' {
   974  				if s.Name[1] == 'r' { // originally an unnamed result
   975  					return "" // s = nil
   976  				} else if s.Name[1] == 'b' { // originally the blank identifier _
   977  					return "_" // belongs to localpkg
   978  				}
   979  			}
   980  		} else {
   981  			return "" // s = nil
   982  		}
   983  	}
   984  
   985  	if s == nil {
   986  		return ""
   987  	}
   988  
   989  	// print symbol with Vargen number or not as desired
   990  	name := s.Name
   991  	if strings.Contains(name, ".") {
   992  		Fatalf("invalid symbol name: %s", name)
   993  	}
   994  
   995  	// Functions that can be inlined use numbered parameters so we can distinguish them
   996  	// from other names in their context after inlining (i.e., the parameter numbering
   997  	// is a form of parameter rewriting). See issue 4326 for an example and test case.
   998  	if numbered {
   999  		if !strings.Contains(name, "·") && asNode(f.Nname) != nil && asNode(f.Nname).Name != nil && asNode(f.Nname).Name.Vargen > 0 {
  1000  			name = fmt.Sprintf("%s·%d", name, asNode(f.Nname).Name.Vargen) // append Vargen
  1001  		}
  1002  	} else {
  1003  		if i := strings.Index(name, "·"); i > 0 {
  1004  			name = name[:i] // cut off Vargen
  1005  		}
  1006  	}
  1007  	return name
  1008  }
  1009  
  1010  func (p *exporter) value(x Val) {
  1011  	if p.trace {
  1012  		p.tracef("= ")
  1013  	}
  1014  
  1015  	switch x := x.U.(type) {
  1016  	case bool:
  1017  		tag := falseTag
  1018  		if x {
  1019  			tag = trueTag
  1020  		}
  1021  		p.tag(tag)
  1022  
  1023  	case *Mpint:
  1024  		if minintval[TINT64].Cmp(x) <= 0 && x.Cmp(maxintval[TINT64]) <= 0 {
  1025  			// common case: x fits into an int64 - use compact encoding
  1026  			p.tag(int64Tag)
  1027  			p.int64(x.Int64())
  1028  			return
  1029  		}
  1030  		// uncommon case: large x - use float encoding
  1031  		// (powers of 2 will be encoded efficiently with exponent)
  1032  		f := newMpflt()
  1033  		f.SetInt(x)
  1034  		p.tag(floatTag)
  1035  		p.float(f)
  1036  
  1037  	case *Mpflt:
  1038  		p.tag(floatTag)
  1039  		p.float(x)
  1040  
  1041  	case *Mpcplx:
  1042  		p.tag(complexTag)
  1043  		p.float(&x.Real)
  1044  		p.float(&x.Imag)
  1045  
  1046  	case string:
  1047  		p.tag(stringTag)
  1048  		p.string(x)
  1049  
  1050  	case *NilVal:
  1051  		// not a constant but used in exported function bodies
  1052  		p.tag(nilTag)
  1053  
  1054  	default:
  1055  		Fatalf("exporter: unexpected value %v (%T)", x, x)
  1056  	}
  1057  }
  1058  
  1059  func (p *exporter) float(x *Mpflt) {
  1060  	// extract sign (there is no -0)
  1061  	f := &x.Val
  1062  	sign := f.Sign()
  1063  	if sign == 0 {
  1064  		// x == 0
  1065  		p.int(0)
  1066  		return
  1067  	}
  1068  	// x != 0
  1069  
  1070  	// extract exponent such that 0.5 <= m < 1.0
  1071  	var m big.Float
  1072  	exp := f.MantExp(&m)
  1073  
  1074  	// extract mantissa as *big.Int
  1075  	// - set exponent large enough so mant satisfies mant.IsInt()
  1076  	// - get *big.Int from mant
  1077  	m.SetMantExp(&m, int(m.MinPrec()))
  1078  	mant, acc := m.Int(nil)
  1079  	if acc != big.Exact {
  1080  		Fatalf("exporter: internal error")
  1081  	}
  1082  
  1083  	p.int(sign)
  1084  	p.int(exp)
  1085  	p.string(string(mant.Bytes()))
  1086  }
  1087  
  1088  // ----------------------------------------------------------------------------
  1089  // Inlined function bodies
  1090  
  1091  // Approach: More or less closely follow what fmt.go is doing for FExp mode
  1092  // but instead of emitting the information textually, emit the node tree in
  1093  // binary form.
  1094  
  1095  // TODO(gri) Improve tracing output. The current format is difficult to read.
  1096  
  1097  // stmtList may emit more (or fewer) than len(list) nodes.
  1098  func (p *exporter) stmtList(list Nodes) {
  1099  	if p.trace {
  1100  		if list.Len() == 0 {
  1101  			p.tracef("{}")
  1102  		} else {
  1103  			p.tracef("{>")
  1104  			defer p.tracef("<\n}")
  1105  		}
  1106  	}
  1107  
  1108  	for _, n := range list.Slice() {
  1109  		if p.trace {
  1110  			p.tracef("\n")
  1111  		}
  1112  		// TODO inlining produces expressions with ninits. we can't export these yet.
  1113  		// (from fmt.go:1461ff)
  1114  		if opprec[n.Op] < 0 {
  1115  			p.stmt(n)
  1116  		} else {
  1117  			p.expr(n)
  1118  		}
  1119  	}
  1120  
  1121  	p.op(OEND)
  1122  }
  1123  
  1124  func (p *exporter) exprList(list Nodes) {
  1125  	if p.trace {
  1126  		if list.Len() == 0 {
  1127  			p.tracef("{}")
  1128  		} else {
  1129  			p.tracef("{>")
  1130  			defer p.tracef("<\n}")
  1131  		}
  1132  	}
  1133  
  1134  	for _, n := range list.Slice() {
  1135  		if p.trace {
  1136  			p.tracef("\n")
  1137  		}
  1138  		p.expr(n)
  1139  	}
  1140  
  1141  	p.op(OEND)
  1142  }
  1143  
  1144  func (p *exporter) elemList(list Nodes) {
  1145  	if p.trace {
  1146  		p.tracef("[ ")
  1147  	}
  1148  	p.int(list.Len())
  1149  	if p.trace {
  1150  		if list.Len() == 0 {
  1151  			p.tracef("] {}")
  1152  		} else {
  1153  			p.tracef("] {>")
  1154  			defer p.tracef("<\n}")
  1155  		}
  1156  	}
  1157  
  1158  	for _, n := range list.Slice() {
  1159  		if p.trace {
  1160  			p.tracef("\n")
  1161  		}
  1162  		p.fieldSym(n.Sym, false)
  1163  		p.expr(n.Left)
  1164  	}
  1165  }
  1166  
  1167  func (p *exporter) expr(n *Node) {
  1168  	if p.trace {
  1169  		p.tracef("( ")
  1170  		defer p.tracef(") ")
  1171  	}
  1172  
  1173  	// from nodefmt (fmt.go)
  1174  	//
  1175  	// nodefmt reverts nodes back to their original - we don't need to do
  1176  	// it because we are not bound to produce valid Go syntax when exporting
  1177  	//
  1178  	// if (fmtmode != FExp || n.Op != OLITERAL) && n.Orig != nil {
  1179  	// 	n = n.Orig
  1180  	// }
  1181  
  1182  	// from exprfmt (fmt.go)
  1183  	for n != nil && n.Implicit() && (n.Op == OIND || n.Op == OADDR) {
  1184  		n = n.Left
  1185  	}
  1186  
  1187  	switch op := n.Op; op {
  1188  	// expressions
  1189  	// (somewhat closely following the structure of exprfmt in fmt.go)
  1190  	case OPAREN:
  1191  		p.expr(n.Left) // unparen
  1192  
  1193  	// case ODDDARG:
  1194  	//	unimplemented - handled by default case
  1195  
  1196  	case OLITERAL:
  1197  		if n.Val().Ctype() == CTNIL && n.Orig != nil && n.Orig != n {
  1198  			p.expr(n.Orig)
  1199  			break
  1200  		}
  1201  		p.op(OLITERAL)
  1202  		p.pos(n)
  1203  		p.typ(unidealType(n.Type, n.Val()))
  1204  		p.value(n.Val())
  1205  
  1206  	case ONAME:
  1207  		// Special case: name used as local variable in export.
  1208  		// _ becomes ~b%d internally; print as _ for export
  1209  		if n.Sym != nil && n.Sym.Name[0] == '~' && n.Sym.Name[1] == 'b' {
  1210  			p.op(ONAME)
  1211  			p.pos(n)
  1212  			p.string("_") // inlined and customized version of p.sym(n)
  1213  			break
  1214  		}
  1215  
  1216  		if n.Sym != nil && !isblank(n) && n.Name.Vargen > 0 {
  1217  			p.op(ONAME)
  1218  			p.pos(n)
  1219  			p.sym(n)
  1220  			break
  1221  		}
  1222  
  1223  		// Special case: explicit name of func (*T) method(...) is turned into pkg.(*T).method,
  1224  		// but for export, this should be rendered as (*pkg.T).meth.
  1225  		// These nodes have the special property that they are names with a left OTYPE and a right ONAME.
  1226  		if n.Left != nil && n.Left.Op == OTYPE && n.Right != nil && n.Right.Op == ONAME {
  1227  			p.op(OXDOT)
  1228  			p.pos(n)
  1229  			p.expr(n.Left) // n.Left.Op == OTYPE
  1230  			p.fieldSym(n.Right.Sym, true)
  1231  			break
  1232  		}
  1233  
  1234  		p.op(ONAME)
  1235  		p.pos(n)
  1236  		p.sym(n)
  1237  
  1238  	// case OPACK, ONONAME:
  1239  	// 	should have been resolved by typechecking - handled by default case
  1240  
  1241  	case OTYPE:
  1242  		p.op(OTYPE)
  1243  		p.pos(n)
  1244  		if p.bool(n.Type == nil) {
  1245  			p.sym(n)
  1246  		} else {
  1247  			p.typ(n.Type)
  1248  		}
  1249  
  1250  	// case OTARRAY, OTMAP, OTCHAN, OTSTRUCT, OTINTER, OTFUNC:
  1251  	// 	should have been resolved by typechecking - handled by default case
  1252  
  1253  	// case OCLOSURE:
  1254  	//	unimplemented - handled by default case
  1255  
  1256  	// case OCOMPLIT:
  1257  	// 	should have been resolved by typechecking - handled by default case
  1258  
  1259  	case OPTRLIT:
  1260  		p.op(OPTRLIT)
  1261  		p.pos(n)
  1262  		p.expr(n.Left)
  1263  		p.bool(n.Implicit())
  1264  
  1265  	case OSTRUCTLIT:
  1266  		p.op(OSTRUCTLIT)
  1267  		p.pos(n)
  1268  		p.typ(n.Type)
  1269  		p.elemList(n.List) // special handling of field names
  1270  
  1271  	case OARRAYLIT, OSLICELIT, OMAPLIT:
  1272  		p.op(OCOMPLIT)
  1273  		p.pos(n)
  1274  		p.typ(n.Type)
  1275  		p.exprList(n.List)
  1276  
  1277  	case OKEY:
  1278  		p.op(OKEY)
  1279  		p.pos(n)
  1280  		p.exprsOrNil(n.Left, n.Right)
  1281  
  1282  	// case OSTRUCTKEY:
  1283  	//	unreachable - handled in case OSTRUCTLIT by elemList
  1284  
  1285  	// case OCALLPART:
  1286  	//	unimplemented - handled by default case
  1287  
  1288  	case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
  1289  		p.op(OXDOT)
  1290  		p.pos(n)
  1291  		p.expr(n.Left)
  1292  		p.fieldSym(n.Sym, true)
  1293  
  1294  	case ODOTTYPE, ODOTTYPE2:
  1295  		p.op(ODOTTYPE)
  1296  		p.pos(n)
  1297  		p.expr(n.Left)
  1298  		p.typ(n.Type)
  1299  
  1300  	case OINDEX, OINDEXMAP:
  1301  		p.op(OINDEX)
  1302  		p.pos(n)
  1303  		p.expr(n.Left)
  1304  		p.expr(n.Right)
  1305  
  1306  	case OSLICE, OSLICESTR, OSLICEARR:
  1307  		p.op(OSLICE)
  1308  		p.pos(n)
  1309  		p.expr(n.Left)
  1310  		low, high, _ := n.SliceBounds()
  1311  		p.exprsOrNil(low, high)
  1312  
  1313  	case OSLICE3, OSLICE3ARR:
  1314  		p.op(OSLICE3)
  1315  		p.pos(n)
  1316  		p.expr(n.Left)
  1317  		low, high, max := n.SliceBounds()
  1318  		p.exprsOrNil(low, high)
  1319  		p.expr(max)
  1320  
  1321  	case OCOPY, OCOMPLEX:
  1322  		// treated like other builtin calls (see e.g., OREAL)
  1323  		p.op(op)
  1324  		p.pos(n)
  1325  		p.expr(n.Left)
  1326  		p.expr(n.Right)
  1327  		p.op(OEND)
  1328  
  1329  	case OCONV, OCONVIFACE, OCONVNOP, OARRAYBYTESTR, OARRAYRUNESTR, OSTRARRAYBYTE, OSTRARRAYRUNE, ORUNESTR:
  1330  		p.op(OCONV)
  1331  		p.pos(n)
  1332  		p.expr(n.Left)
  1333  		p.typ(n.Type)
  1334  
  1335  	case OREAL, OIMAG, OAPPEND, OCAP, OCLOSE, ODELETE, OLEN, OMAKE, ONEW, OPANIC, ORECOVER, OPRINT, OPRINTN:
  1336  		p.op(op)
  1337  		p.pos(n)
  1338  		if n.Left != nil {
  1339  			p.expr(n.Left)
  1340  			p.op(OEND)
  1341  		} else {
  1342  			p.exprList(n.List) // emits terminating OEND
  1343  		}
  1344  		// only append() calls may contain '...' arguments
  1345  		if op == OAPPEND {
  1346  			p.bool(n.Isddd())
  1347  		} else if n.Isddd() {
  1348  			Fatalf("exporter: unexpected '...' with %s call", opnames[op])
  1349  		}
  1350  
  1351  	case OCALL, OCALLFUNC, OCALLMETH, OCALLINTER, OGETG:
  1352  		p.op(OCALL)
  1353  		p.pos(n)
  1354  		p.expr(n.Left)
  1355  		p.exprList(n.List)
  1356  		p.bool(n.Isddd())
  1357  
  1358  	case OMAKEMAP, OMAKECHAN, OMAKESLICE:
  1359  		p.op(op) // must keep separate from OMAKE for importer
  1360  		p.pos(n)
  1361  		p.typ(n.Type)
  1362  		switch {
  1363  		default:
  1364  			// empty list
  1365  			p.op(OEND)
  1366  		case n.List.Len() != 0: // pre-typecheck
  1367  			p.exprList(n.List) // emits terminating OEND
  1368  		case n.Right != nil:
  1369  			p.expr(n.Left)
  1370  			p.expr(n.Right)
  1371  			p.op(OEND)
  1372  		case n.Left != nil && (n.Op == OMAKESLICE || !n.Left.Type.IsUntyped()):
  1373  			p.expr(n.Left)
  1374  			p.op(OEND)
  1375  		}
  1376  
  1377  	// unary expressions
  1378  	case OPLUS, OMINUS, OADDR, OCOM, OIND, ONOT, ORECV:
  1379  		p.op(op)
  1380  		p.pos(n)
  1381  		p.expr(n.Left)
  1382  
  1383  	// binary expressions
  1384  	case OADD, OAND, OANDAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE, OLT,
  1385  		OLSH, OMOD, OMUL, ONE, OOR, OOROR, ORSH, OSEND, OSUB, OXOR:
  1386  		p.op(op)
  1387  		p.pos(n)
  1388  		p.expr(n.Left)
  1389  		p.expr(n.Right)
  1390  
  1391  	case OADDSTR:
  1392  		p.op(OADDSTR)
  1393  		p.pos(n)
  1394  		p.exprList(n.List)
  1395  
  1396  	case OCMPSTR, OCMPIFACE:
  1397  		p.op(Op(n.Etype))
  1398  		p.pos(n)
  1399  		p.expr(n.Left)
  1400  		p.expr(n.Right)
  1401  
  1402  	case ODCLCONST:
  1403  		// if exporting, DCLCONST should just be removed as its usage
  1404  		// has already been replaced with literals
  1405  		// TODO(gri) these should not be exported in the first place
  1406  		// TODO(gri) why is this considered an expression in fmt.go?
  1407  		p.op(ODCLCONST)
  1408  		p.pos(n)
  1409  
  1410  	default:
  1411  		Fatalf("cannot export %v (%d) node\n"+
  1412  			"==> please file an issue and assign to gri@\n", n.Op, int(n.Op))
  1413  	}
  1414  }
  1415  
  1416  // Caution: stmt will emit more than one node for statement nodes n that have a non-empty
  1417  // n.Ninit and where n cannot have a natural init section (such as in "if", "for", etc.).
  1418  func (p *exporter) stmt(n *Node) {
  1419  	if p.trace {
  1420  		p.tracef("( ")
  1421  		defer p.tracef(") ")
  1422  	}
  1423  
  1424  	if n.Ninit.Len() > 0 && !stmtwithinit(n.Op) {
  1425  		if p.trace {
  1426  			p.tracef("( /* Ninits */ ")
  1427  		}
  1428  
  1429  		// can't use stmtList here since we don't want the final OEND
  1430  		for _, n := range n.Ninit.Slice() {
  1431  			p.stmt(n)
  1432  		}
  1433  
  1434  		if p.trace {
  1435  			p.tracef(") ")
  1436  		}
  1437  	}
  1438  
  1439  	switch op := n.Op; op {
  1440  	case ODCL:
  1441  		p.op(ODCL)
  1442  		p.pos(n)
  1443  		p.sym(n.Left)
  1444  		p.typ(n.Left.Type)
  1445  
  1446  	// case ODCLFIELD:
  1447  	//	unimplemented - handled by default case
  1448  
  1449  	case OAS:
  1450  		// Don't export "v = <N>" initializing statements, hope they're always
  1451  		// preceded by the DCL which will be re-parsed and typecheck to reproduce
  1452  		// the "v = <N>" again.
  1453  		if n.Right != nil {
  1454  			p.op(OAS)
  1455  			p.pos(n)
  1456  			p.expr(n.Left)
  1457  			p.expr(n.Right)
  1458  		}
  1459  
  1460  	case OASOP:
  1461  		p.op(OASOP)
  1462  		p.pos(n)
  1463  		p.int(int(n.Etype))
  1464  		p.expr(n.Left)
  1465  		if p.bool(!n.Implicit()) {
  1466  			p.expr(n.Right)
  1467  		}
  1468  
  1469  	case OAS2, OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV:
  1470  		p.op(OAS2)
  1471  		p.pos(n)
  1472  		p.exprList(n.List)
  1473  		p.exprList(n.Rlist)
  1474  
  1475  	case ORETURN:
  1476  		p.op(ORETURN)
  1477  		p.pos(n)
  1478  		p.exprList(n.List)
  1479  
  1480  	// case ORETJMP:
  1481  	// 	unreachable - generated by compiler for trampolin routines
  1482  
  1483  	case OPROC, ODEFER:
  1484  		p.op(op)
  1485  		p.pos(n)
  1486  		p.expr(n.Left)
  1487  
  1488  	case OIF:
  1489  		p.op(OIF)
  1490  		p.pos(n)
  1491  		p.stmtList(n.Ninit)
  1492  		p.expr(n.Left)
  1493  		p.stmtList(n.Nbody)
  1494  		p.stmtList(n.Rlist)
  1495  
  1496  	case OFOR:
  1497  		p.op(OFOR)
  1498  		p.pos(n)
  1499  		p.stmtList(n.Ninit)
  1500  		p.exprsOrNil(n.Left, n.Right)
  1501  		p.stmtList(n.Nbody)
  1502  
  1503  	case ORANGE:
  1504  		p.op(ORANGE)
  1505  		p.pos(n)
  1506  		p.stmtList(n.List)
  1507  		p.expr(n.Right)
  1508  		p.stmtList(n.Nbody)
  1509  
  1510  	case OSELECT, OSWITCH:
  1511  		p.op(op)
  1512  		p.pos(n)
  1513  		p.stmtList(n.Ninit)
  1514  		p.exprsOrNil(n.Left, nil)
  1515  		p.stmtList(n.List)
  1516  
  1517  	case OCASE, OXCASE:
  1518  		p.op(OXCASE)
  1519  		p.pos(n)
  1520  		p.stmtList(n.List)
  1521  		p.stmtList(n.Nbody)
  1522  
  1523  	case OFALL, OXFALL:
  1524  		p.op(OXFALL)
  1525  		p.pos(n)
  1526  
  1527  	case OBREAK, OCONTINUE:
  1528  		p.op(op)
  1529  		p.pos(n)
  1530  		p.exprsOrNil(n.Left, nil)
  1531  
  1532  	case OEMPTY:
  1533  		// nothing to emit
  1534  
  1535  	case OGOTO, OLABEL:
  1536  		p.op(op)
  1537  		p.pos(n)
  1538  		p.expr(n.Left)
  1539  
  1540  	default:
  1541  		Fatalf("exporter: CANNOT EXPORT: %v\nPlease notify gri@\n", n.Op)
  1542  	}
  1543  }
  1544  
  1545  func (p *exporter) exprsOrNil(a, b *Node) {
  1546  	ab := 0
  1547  	if a != nil {
  1548  		ab |= 1
  1549  	}
  1550  	if b != nil {
  1551  		ab |= 2
  1552  	}
  1553  	p.int(ab)
  1554  	if ab&1 != 0 {
  1555  		p.expr(a)
  1556  	}
  1557  	if ab&2 != 0 {
  1558  		p.expr(b)
  1559  	}
  1560  }
  1561  
  1562  func (p *exporter) fieldSym(s *types.Sym, short bool) {
  1563  	name := s.Name
  1564  
  1565  	// remove leading "type." in method names ("(T).m" -> "m")
  1566  	if short {
  1567  		if i := strings.LastIndex(name, "."); i >= 0 {
  1568  			name = name[i+1:]
  1569  		}
  1570  	}
  1571  
  1572  	// we should never see a _ (blank) here - these are accessible ("read") fields
  1573  	// TODO(gri) can we assert this with an explicit check?
  1574  	p.string(name)
  1575  	if !exportname(name) {
  1576  		p.pkg(s.Pkg)
  1577  	}
  1578  }
  1579  
  1580  // sym must encode the _ (blank) identifier as a single string "_" since
  1581  // encoding for some nodes is based on this assumption (e.g. ONAME nodes).
  1582  func (p *exporter) sym(n *Node) {
  1583  	s := n.Sym
  1584  	if s.Pkg != nil {
  1585  		if len(s.Name) > 0 && s.Name[0] == '.' {
  1586  			Fatalf("exporter: exporting synthetic symbol %s", s.Name)
  1587  		}
  1588  	}
  1589  
  1590  	if p.trace {
  1591  		p.tracef("{ SYM ")
  1592  		defer p.tracef("} ")
  1593  	}
  1594  
  1595  	name := s.Name
  1596  
  1597  	// remove leading "type." in method names ("(T).m" -> "m")
  1598  	if i := strings.LastIndex(name, "."); i >= 0 {
  1599  		name = name[i+1:]
  1600  	}
  1601  
  1602  	if strings.Contains(name, "·") && n.Name.Vargen > 0 {
  1603  		Fatalf("exporter: unexpected · in symbol name")
  1604  	}
  1605  
  1606  	if i := n.Name.Vargen; i > 0 {
  1607  		name = fmt.Sprintf("%s·%d", name, i)
  1608  	}
  1609  
  1610  	p.string(name)
  1611  	if name != "_" {
  1612  		p.pkg(s.Pkg)
  1613  	}
  1614  	// Fixes issue #18167.
  1615  	p.string(s.Linkname)
  1616  }
  1617  
  1618  func (p *exporter) bool(b bool) bool {
  1619  	if p.trace {
  1620  		p.tracef("[")
  1621  		defer p.tracef("= %v] ", b)
  1622  	}
  1623  
  1624  	x := 0
  1625  	if b {
  1626  		x = 1
  1627  	}
  1628  	p.int(x)
  1629  	return b
  1630  }
  1631  
  1632  func (p *exporter) op(op Op) {
  1633  	if p.trace {
  1634  		p.tracef("[")
  1635  		defer p.tracef("= %v] ", op)
  1636  	}
  1637  
  1638  	p.int(int(op))
  1639  }
  1640  
  1641  // ----------------------------------------------------------------------------
  1642  // Low-level encoders
  1643  
  1644  func (p *exporter) index(marker byte, index int) {
  1645  	if index < 0 {
  1646  		Fatalf("exporter: invalid index < 0")
  1647  	}
  1648  	if debugFormat {
  1649  		p.marker('t')
  1650  	}
  1651  	if p.trace {
  1652  		p.tracef("%c%d ", marker, index)
  1653  	}
  1654  	p.rawInt64(int64(index))
  1655  }
  1656  
  1657  func (p *exporter) tag(tag int) {
  1658  	if tag >= 0 {
  1659  		Fatalf("exporter: invalid tag >= 0")
  1660  	}
  1661  	if debugFormat {
  1662  		p.marker('t')
  1663  	}
  1664  	if p.trace {
  1665  		p.tracef("%s ", tagString[-tag])
  1666  	}
  1667  	p.rawInt64(int64(tag))
  1668  }
  1669  
  1670  func (p *exporter) int(x int) {
  1671  	p.int64(int64(x))
  1672  }
  1673  
  1674  func (p *exporter) int64(x int64) {
  1675  	if debugFormat {
  1676  		p.marker('i')
  1677  	}
  1678  	if p.trace {
  1679  		p.tracef("%d ", x)
  1680  	}
  1681  	p.rawInt64(x)
  1682  }
  1683  
  1684  func (p *exporter) string(s string) {
  1685  	if debugFormat {
  1686  		p.marker('s')
  1687  	}
  1688  	if p.trace {
  1689  		p.tracef("%q ", s)
  1690  	}
  1691  	// if we saw the string before, write its index (>= 0)
  1692  	// (the empty string is mapped to 0)
  1693  	if i, ok := p.strIndex[s]; ok {
  1694  		p.rawInt64(int64(i))
  1695  		return
  1696  	}
  1697  	// otherwise, remember string and write its negative length and bytes
  1698  	p.strIndex[s] = len(p.strIndex)
  1699  	p.rawInt64(-int64(len(s)))
  1700  	for i := 0; i < len(s); i++ {
  1701  		p.rawByte(s[i])
  1702  	}
  1703  }
  1704  
  1705  // marker emits a marker byte and position information which makes
  1706  // it easy for a reader to detect if it is "out of sync". Used only
  1707  // if debugFormat is set.
  1708  func (p *exporter) marker(m byte) {
  1709  	p.rawByte(m)
  1710  	// Uncomment this for help tracking down the location
  1711  	// of an incorrect marker when running in debugFormat.
  1712  	// if p.trace {
  1713  	// 	p.tracef("#%d ", p.written)
  1714  	// }
  1715  	p.rawInt64(int64(p.written))
  1716  }
  1717  
  1718  // rawInt64 should only be used by low-level encoders.
  1719  func (p *exporter) rawInt64(x int64) {
  1720  	var tmp [binary.MaxVarintLen64]byte
  1721  	n := binary.PutVarint(tmp[:], x)
  1722  	for i := 0; i < n; i++ {
  1723  		p.rawByte(tmp[i])
  1724  	}
  1725  }
  1726  
  1727  // rawStringln should only be used to emit the initial version string.
  1728  func (p *exporter) rawStringln(s string) {
  1729  	for i := 0; i < len(s); i++ {
  1730  		p.rawByte(s[i])
  1731  	}
  1732  	p.rawByte('\n')
  1733  }
  1734  
  1735  // rawByte is the bottleneck interface to write to p.out.
  1736  // rawByte escapes b as follows (any encoding does that
  1737  // hides '$'):
  1738  //
  1739  //	'$'  => '|' 'S'
  1740  //	'|'  => '|' '|'
  1741  //
  1742  // Necessary so other tools can find the end of the
  1743  // export data by searching for "$$".
  1744  // rawByte should only be used by low-level encoders.
  1745  func (p *exporter) rawByte(b byte) {
  1746  	switch b {
  1747  	case '$':
  1748  		// write '$' as '|' 'S'
  1749  		b = 'S'
  1750  		fallthrough
  1751  	case '|':
  1752  		// write '|' as '|' '|'
  1753  		p.out.WriteByte('|')
  1754  		p.written++
  1755  	}
  1756  	p.out.WriteByte(b)
  1757  	p.written++
  1758  }
  1759  
  1760  // tracef is like fmt.Printf but it rewrites the format string
  1761  // to take care of indentation.
  1762  func (p *exporter) tracef(format string, args ...interface{}) {
  1763  	if strings.ContainsAny(format, "<>\n") {
  1764  		var buf bytes.Buffer
  1765  		for i := 0; i < len(format); i++ {
  1766  			// no need to deal with runes
  1767  			ch := format[i]
  1768  			switch ch {
  1769  			case '>':
  1770  				p.indent++
  1771  				continue
  1772  			case '<':
  1773  				p.indent--
  1774  				continue
  1775  			}
  1776  			buf.WriteByte(ch)
  1777  			if ch == '\n' {
  1778  				for j := p.indent; j > 0; j-- {
  1779  					buf.WriteString(".  ")
  1780  				}
  1781  			}
  1782  		}
  1783  		format = buf.String()
  1784  	}
  1785  	fmt.Printf(format, args...)
  1786  }
  1787  
  1788  // ----------------------------------------------------------------------------
  1789  // Export format
  1790  
  1791  // Tags. Must be < 0.
  1792  const (
  1793  	// Objects
  1794  	packageTag = -(iota + 1)
  1795  	constTag
  1796  	typeTag
  1797  	varTag
  1798  	funcTag
  1799  	endTag
  1800  
  1801  	// Types
  1802  	namedTag
  1803  	arrayTag
  1804  	sliceTag
  1805  	dddTag
  1806  	structTag
  1807  	pointerTag
  1808  	signatureTag
  1809  	interfaceTag
  1810  	mapTag
  1811  	chanTag
  1812  
  1813  	// Values
  1814  	falseTag
  1815  	trueTag
  1816  	int64Tag
  1817  	floatTag
  1818  	fractionTag // not used by gc
  1819  	complexTag
  1820  	stringTag
  1821  	nilTag
  1822  	unknownTag // not used by gc (only appears in packages with errors)
  1823  
  1824  	// Type aliases
  1825  	aliasTag
  1826  )
  1827  
  1828  // Debugging support.
  1829  // (tagString is only used when tracing is enabled)
  1830  var tagString = [...]string{
  1831  	// Objects
  1832  	-packageTag: "package",
  1833  	-constTag:   "const",
  1834  	-typeTag:    "type",
  1835  	-varTag:     "var",
  1836  	-funcTag:    "func",
  1837  	-endTag:     "end",
  1838  
  1839  	// Types
  1840  	-namedTag:     "named type",
  1841  	-arrayTag:     "array",
  1842  	-sliceTag:     "slice",
  1843  	-dddTag:       "ddd",
  1844  	-structTag:    "struct",
  1845  	-pointerTag:   "pointer",
  1846  	-signatureTag: "signature",
  1847  	-interfaceTag: "interface",
  1848  	-mapTag:       "map",
  1849  	-chanTag:      "chan",
  1850  
  1851  	// Values
  1852  	-falseTag:    "false",
  1853  	-trueTag:     "true",
  1854  	-int64Tag:    "int64",
  1855  	-floatTag:    "float",
  1856  	-fractionTag: "fraction",
  1857  	-complexTag:  "complex",
  1858  	-stringTag:   "string",
  1859  	-nilTag:      "nil",
  1860  	-unknownTag:  "unknown",
  1861  
  1862  	// Type aliases
  1863  	-aliasTag: "alias",
  1864  }
  1865  
  1866  // untype returns the "pseudo" untyped type for a Ctype (import/export use only).
  1867  // (we can't use an pre-initialized array because we must be sure all types are
  1868  // set up)
  1869  func untype(ctype Ctype) *types.Type {
  1870  	switch ctype {
  1871  	case CTINT:
  1872  		return types.Idealint
  1873  	case CTRUNE:
  1874  		return types.Idealrune
  1875  	case CTFLT:
  1876  		return types.Idealfloat
  1877  	case CTCPLX:
  1878  		return types.Idealcomplex
  1879  	case CTSTR:
  1880  		return types.Idealstring
  1881  	case CTBOOL:
  1882  		return types.Idealbool
  1883  	case CTNIL:
  1884  		return types.Types[TNIL]
  1885  	}
  1886  	Fatalf("exporter: unknown Ctype")
  1887  	return nil
  1888  }
  1889  
  1890  var predecl []*types.Type // initialized lazily
  1891  
  1892  func predeclared() []*types.Type {
  1893  	if predecl == nil {
  1894  		// initialize lazily to be sure that all
  1895  		// elements have been initialized before
  1896  		predecl = []*types.Type{
  1897  			// basic types
  1898  			types.Types[TBOOL],
  1899  			types.Types[TINT],
  1900  			types.Types[TINT8],
  1901  			types.Types[TINT16],
  1902  			types.Types[TINT32],
  1903  			types.Types[TINT64],
  1904  			types.Types[TUINT],
  1905  			types.Types[TUINT8],
  1906  			types.Types[TUINT16],
  1907  			types.Types[TUINT32],
  1908  			types.Types[TUINT64],
  1909  			types.Types[TUINTPTR],
  1910  			types.Types[TFLOAT32],
  1911  			types.Types[TFLOAT64],
  1912  			types.Types[TCOMPLEX64],
  1913  			types.Types[TCOMPLEX128],
  1914  			types.Types[TSTRING],
  1915  
  1916  			// basic type aliases
  1917  			types.Bytetype,
  1918  			types.Runetype,
  1919  
  1920  			// error
  1921  			types.Errortype,
  1922  
  1923  			// untyped types
  1924  			untype(CTBOOL),
  1925  			untype(CTINT),
  1926  			untype(CTRUNE),
  1927  			untype(CTFLT),
  1928  			untype(CTCPLX),
  1929  			untype(CTSTR),
  1930  			untype(CTNIL),
  1931  
  1932  			// package unsafe
  1933  			types.Types[TUNSAFEPTR],
  1934  
  1935  			// invalid type (package contains errors)
  1936  			types.Types[Txxx],
  1937  
  1938  			// any type, for builtin export data
  1939  			types.Types[TANY],
  1940  		}
  1941  	}
  1942  	return predecl
  1943  }