github.com/sanprasirt/go@v0.0.0-20170607001320-a027466e4b6d/src/cmd/compile/internal/gc/bexport.go (about)

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