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