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