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