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