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