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