github.com/mh-cbon/go@v0.0.0-20160603070303-9e112a3fe4c0/src/cmd/compile/internal/gc/bexport.go (about)

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