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