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