github.com/miolini/go@v0.0.0-20160405192216-fca68c8cb408/src/cmd/compile/internal/gc/bexport.go (about)

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