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