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