github.com/tidwall/go@v0.0.0-20170415222209-6694a6888b7d/src/cmd/compile/internal/gc/bexport.go (about)

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