// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Indexed package export.
//
// The indexed export data format is an evolution of the previous
// binary export data format. Its chief contribution is introducing an
// index table, which allows efficient random access of individual
// declarations and inline function bodies. In turn, this allows
// avoiding unnecessary work for compilation units that import large
// packages.
//
//
// The top-level data format is structured as:
//
//     Header struct {
//         Tag        byte   // 'i'
//         Version    uvarint
//         StringSize uvarint
//         DataSize   uvarint
//     }
//
//     Strings [StringSize]byte
//     Data    [DataSize]byte
//
//     MainIndex []struct{
//         PkgPath   stringOff
//         PkgName   stringOff
//         PkgHeight uvarint
//
//         Decls []struct{
//             Name   stringOff
//             Offset declOff
//         }
//     }
//
// uvarint means a uint64 written out using uvarint encoding.
//
// []T means a uvarint followed by that many T objects. In other
// words:
//
//     Len   uvarint
//     Elems [Len]T
//
// stringOff means a uvarint that indicates an offset within the
// Strings section. At that offset is another uvarint, followed by
// that many bytes, which form the string value.
//
// declOff means a uvarint that indicates an offset within the Data
// section where the associated declaration can be found.
//
//
// There are five kinds of declarations, distinguished by their first
// byte:
//
//     type Var struct {
//         Tag  byte // 'V'
//         Pos  Pos
//         Type typeOff
//     }
//
//     type Func struct {
//         Tag       byte // 'F'
//         Pos       Pos
//         Signature Signature
//     }
//
//     type Const struct {
//         Tag   byte // 'C'
//         Pos   Pos
//         Value Value
//     }
//
//     type Type struct {
//         Tag        byte // 'T'
//         Pos        Pos
//         Underlying typeOff
//
//         Methods []struct{  // omitted if Underlying is an interface type
//             Pos       Pos
//             Name      stringOff
//             Recv      Param
//             Signature Signature
//         }
//     }
//
//     type Alias struct {
//         Tag  byte // 'A'
//         Pos  Pos
//         Type typeOff
//     }
//
//
// typeOff means a uvarint that either indicates a predeclared type,
// or an offset into the Data section. If the uvarint is less than
// predeclReserved, then it indicates the index into the predeclared
// types list (see predeclared in bexport.go for order). Otherwise,
// subtracting predeclReserved yields the offset of a type descriptor.
//
// Value means a type and type-specific value. See
// (*exportWriter).value for details.
//
//
// There are nine kinds of type descriptors, distinguished by an itag:
//
//     type DefinedType struct {
//         Tag     itag // definedType
//         Name    stringOff
//         PkgPath stringOff
//     }
//
//     type PointerType struct {
//         Tag  itag // pointerType
//         Elem typeOff
//     }
//
//     type SliceType struct {
//         Tag  itag // sliceType
//         Elem typeOff
//     }
//
//     type ArrayType struct {
//         Tag  itag // arrayType
//         Len  uint64
//         Elem typeOff
//     }
//
//     type ChanType struct {
//         Tag  itag   // chanType
//         Dir  uint64 // 1 RecvOnly; 2 SendOnly; 3 SendRecv
//         Elem typeOff
//     }
//
//     type MapType struct {
//         Tag  itag // mapType
//         Key  typeOff
//         Elem typeOff
//     }
//
//     type FuncType struct {
//         Tag       itag // signatureType
//         PkgPath   stringOff
//         Signature Signature
//     }
//
//     type StructType struct {
//         Tag     itag // structType
//         PkgPath stringOff
//         Fields []struct {
//             Pos      Pos
//             Name     stringOff
//             Type     typeOff
//             Embedded bool
//             Note     stringOff
//         }
//     }
//
//     type InterfaceType struct {
//         Tag     itag // interfaceType
//         PkgPath stringOff
//         Embeddeds []struct {
//             Pos  Pos
//             Type typeOff
//         }
//         Methods []struct {
//             Pos       Pos
//             Name      stringOff
//             Signature Signature
//         }
//     }
//
//
//     type Signature struct {
//         Params   []Param
//         Results  []Param
//         Variadic bool  // omitted if Results is empty
//     }
//
//     type Param struct {
//         Pos  Pos
//         Name stringOff
//         Type typOff
//     }
//
//
// Pos encodes a file:line pair, incorporating a simple delta encoding
// scheme within a data object. See exportWriter.pos for details.
//
//
// Compiler-specific details.
//
// cmd/compile writes out a second index for inline bodies and also
// appends additional compiler-specific details after declarations.
// Third-party tools are not expected to depend on these details and
// they're expected to change much more rapidly, so they're omitted
// here. See exportWriter's varExt/funcExt/etc methods for details.

package gc

import (
	"bufio"
	"bytes"
	"cmd/compile/internal/types"
	"cmd/internal/obj"
	"cmd/internal/src"
	"encoding/binary"
	"fmt"
	"go/ast"
	"io"
	"math/big"
	"strings"
)

// Current indexed export format version. Increase with each format change.
// 0: Go1.11 encoding
const iexportVersion = 0

// predeclReserved is the number of type offsets reserved for types
// implicitly declared in the universe block.
const predeclReserved = 32

// An itag distinguishes the kind of type that was written into the
// indexed export format.
type itag uint64

const (
	// Types
	definedType itag = iota
	pointerType
	sliceType
	arrayType
	chanType
	mapType
	signatureType
	structType
	interfaceType
)

func iexport(out *bufio.Writer) {
	// Mark inline bodies that are reachable through exported types.
	// (Phase 0 of bexport.go.)
	{
		// TODO(mdempsky): Separate from bexport logic.
		p := &exporter{marked: make(map[*types.Type]bool)}
		for _, n := range exportlist {
			sym := n.Sym
			p.markType(asNode(sym.Def).Type)
		}
	}

	p := iexporter{
		allPkgs:     map[*types.Pkg]bool{},
		stringIndex: map[string]uint64{},
		declIndex:   map[*Node]uint64{},
		inlineIndex: map[*Node]uint64{},
		typIndex:    map[*types.Type]uint64{},
	}

	for i, pt := range predeclared() {
		p.typIndex[pt] = uint64(i)
	}
	if len(p.typIndex) > predeclReserved {
		Fatalf("too many predeclared types: %d > %d", len(p.typIndex), predeclReserved)
	}

	// Initialize work queue with exported declarations.
	for _, n := range exportlist {
		p.pushDecl(n)
	}

	// Loop until no more work. We use a queue because while
	// writing out inline bodies, we may discover additional
	// declarations that are needed.
	for !p.declTodo.empty() {
		p.doDecl(p.declTodo.popLeft())
	}

	// Append indices to data0 section.
	dataLen := uint64(p.data0.Len())
	w := p.newWriter()
	w.writeIndex(p.declIndex, true)
	w.writeIndex(p.inlineIndex, false)
	w.flush()

	// Assemble header.
	var hdr intWriter
	hdr.WriteByte('i')
	hdr.uint64(iexportVersion)
	hdr.uint64(uint64(p.strings.Len()))
	hdr.uint64(dataLen)

	// Flush output.
	io.Copy(out, &hdr)
	io.Copy(out, &p.strings)
	io.Copy(out, &p.data0)
}

// writeIndex writes out an object index. mainIndex indicates whether
// we're writing out the main index, which is also read by
// non-compiler tools and includes a complete package description
// (i.e., name and height).
func (w *exportWriter) writeIndex(index map[*Node]uint64, mainIndex bool) {
	// Build a map from packages to objects from that package.
	pkgObjs := map[*types.Pkg][]*Node{}

	// For the main index, make sure to include every package that
	// we reference, even if we're not exporting (or reexporting)
	// any symbols from it.
	if mainIndex {
		pkgObjs[localpkg] = nil
		for pkg := range w.p.allPkgs {
			pkgObjs[pkg] = nil
		}
	}

	for n := range index {
		pkgObjs[n.Sym.Pkg] = append(pkgObjs[n.Sym.Pkg], n)
	}

	var pkgs []*types.Pkg
	for pkg, objs := range pkgObjs {
		pkgs = append(pkgs, pkg)

		obj.SortSlice(objs, func(i, j int) bool {
			return objs[i].Sym.Name < objs[j].Sym.Name
		})
	}

	obj.SortSlice(pkgs, func(i, j int) bool {
		return pkgs[i].Path < pkgs[j].Path
	})

	w.uint64(uint64(len(pkgs)))
	for _, pkg := range pkgs {
		w.string(pkg.Path)
		if mainIndex {
			w.string(pkg.Name)
			w.uint64(uint64(pkg.Height))
		}

		objs := pkgObjs[pkg]
		w.uint64(uint64(len(objs)))
		for _, n := range objs {
			w.string(n.Sym.Name)
			w.uint64(index[n])
		}
	}
}

type iexporter struct {
	// allPkgs tracks all packages that have been referenced by
	// the export data, so we can ensure to include them in the
	// main index.
	allPkgs map[*types.Pkg]bool

	declTodo nodeQueue

	strings     intWriter
	stringIndex map[string]uint64

	data0       intWriter
	declIndex   map[*Node]uint64
	inlineIndex map[*Node]uint64
	typIndex    map[*types.Type]uint64
}

// stringOff returns the offset of s within the string section.
// If not already present, it's added to the end.
func (p *iexporter) stringOff(s string) uint64 {
	off, ok := p.stringIndex[s]
	if !ok {
		off = uint64(p.strings.Len())
		p.stringIndex[s] = off

		p.strings.uint64(uint64(len(s)))
		p.strings.WriteString(s)
	}
	return off
}

// pushDecl adds n to the declaration work queue, if not already present.
func (p *iexporter) pushDecl(n *Node) {
	if n.Sym == nil || asNode(n.Sym.Def) != n && n.Op != OTYPE {
		Fatalf("weird Sym: %v, %v", n, n.Sym)
	}

	// Don't export predeclared declarations.
	if n.Sym.Pkg == builtinpkg || n.Sym.Pkg == unsafepkg {
		return
	}

	if _, ok := p.declIndex[n]; ok {
		return
	}

	p.declIndex[n] = ^uint64(0) // mark n present in work queue
	p.declTodo.pushRight(n)
}

// exportWriter handles writing out individual data section chunks.
type exportWriter struct {
	p *iexporter

	data     intWriter
	currPkg  *types.Pkg
	prevFile string
	prevLine int64
}

func (p *iexporter) doDecl(n *Node) {
	w := p.newWriter()
	w.setPkg(n.Sym.Pkg, false)

	switch n.Op {
	case ONAME:
		switch n.Class() {
		case PEXTERN:
			// Variable.
			w.tag('V')
			w.pos(n.Pos)
			w.typ(n.Type)
			w.varExt(n)

		case PFUNC:
			if n.IsMethod() {
				Fatalf("unexpected method: %v", n)
			}

			// Function.
			w.tag('F')
			w.pos(n.Pos)
			w.signature(n.Type)
			w.funcExt(n)

		default:
			Fatalf("unexpected class: %v, %v", n, n.Class())
		}

	case OLITERAL:
		// Constant.
		n = typecheck(n, ctxExpr)
		w.tag('C')
		w.pos(n.Pos)
		w.value(n.Type, n.Val())

	case OTYPE:
		if IsAlias(n.Sym) {
			// Alias.
			w.tag('A')
			w.pos(n.Pos)
			w.typ(n.Type)
			break
		}

		// Defined type.
		w.tag('T')
		w.pos(n.Pos)

		underlying := n.Type.Orig
		if underlying == types.Errortype.Orig {
			// For "type T error", use error as the
			// underlying type instead of error's own
			// underlying anonymous interface. This
			// ensures consistency with how importers may
			// declare error (e.g., go/types uses nil Pkg
			// for predeclared objects).
			underlying = types.Errortype
		}
		w.typ(underlying)

		t := n.Type
		if t.IsInterface() {
			break
		}

		ms := t.Methods()
		w.uint64(uint64(ms.Len()))
		for _, m := range ms.Slice() {
			w.pos(m.Pos)
			w.selector(m.Sym)
			w.param(m.Type.Recv())
			w.signature(m.Type)
		}

		for _, m := range ms.Slice() {
			w.methExt(m)
		}

	default:
		Fatalf("unexpected node: %v", n)
	}

	p.declIndex[n] = w.flush()
}

func (w *exportWriter) tag(tag byte) {
	w.data.WriteByte(tag)
}

func (p *iexporter) doInline(f *Node) {
	w := p.newWriter()
	w.setPkg(fnpkg(f), false)

	w.stmtList(asNodes(f.Func.Inl.Body))

	p.inlineIndex[f] = w.flush()
}

func (w *exportWriter) pos(pos src.XPos) {
	p := Ctxt.PosTable.Pos(pos)
	file := p.Base().AbsFilename()
	line := int64(p.RelLine())

	// When file is the same as the last position (common case),
	// we can save a few bytes by delta encoding just the line
	// number.
	//
	// Note: Because data objects may be read out of order (or not
	// at all), we can only apply delta encoding within a single
	// object. This is handled implicitly by tracking prevFile and
	// prevLine as fields of exportWriter.

	if file == w.prevFile {
		delta := line - w.prevLine
		w.int64(delta)
		if delta == deltaNewFile {
			w.int64(-1)
		}
	} else {
		w.int64(deltaNewFile)
		w.int64(line) // line >= 0
		w.string(file)
		w.prevFile = file
	}
	w.prevLine = line
}

func (w *exportWriter) pkg(pkg *types.Pkg) {
	// Ensure any referenced packages are declared in the main index.
	w.p.allPkgs[pkg] = true

	w.string(pkg.Path)
}

func (w *exportWriter) qualifiedIdent(n *Node) {
	// Ensure any referenced declarations are written out too.
	w.p.pushDecl(n)

	s := n.Sym
	w.string(s.Name)
	w.pkg(s.Pkg)
}

func (w *exportWriter) selector(s *types.Sym) {
	if w.currPkg == nil {
		Fatalf("missing currPkg")
	}

	// Method selectors are rewritten into method symbols (of the
	// form T.M) during typechecking, but we want to write out
	// just the bare method name.
	name := s.Name
	if i := strings.LastIndex(name, "."); i >= 0 {
		name = name[i+1:]
	} else {
		pkg := w.currPkg
		if types.IsExported(name) {
			pkg = localpkg
		}
		if s.Pkg != pkg {
			Fatalf("package mismatch in selector: %v in package %q, but want %q", s, s.Pkg.Path, pkg.Path)
		}
	}

	w.string(name)
}

func (w *exportWriter) typ(t *types.Type) {
	w.data.uint64(w.p.typOff(t))
}

func (p *iexporter) newWriter() *exportWriter {
	return &exportWriter{p: p}
}

func (w *exportWriter) flush() uint64 {
	off := uint64(w.p.data0.Len())
	io.Copy(&w.p.data0, &w.data)
	return off
}

func (p *iexporter) typOff(t *types.Type) uint64 {
	off, ok := p.typIndex[t]
	if !ok {
		w := p.newWriter()
		w.doTyp(t)
		off = predeclReserved + w.flush()
		p.typIndex[t] = off
	}
	return off
}

func (w *exportWriter) startType(k itag) {
	w.data.uint64(uint64(k))
}

func (w *exportWriter) doTyp(t *types.Type) {
	if t.Sym != nil {
		if t.Sym.Pkg == builtinpkg || t.Sym.Pkg == unsafepkg {
			Fatalf("builtin type missing from typIndex: %v", t)
		}

		w.startType(definedType)
		w.qualifiedIdent(typenod(t))
		return
	}

	switch t.Etype {
	case TPTR:
		w.startType(pointerType)
		w.typ(t.Elem())

	case TSLICE:
		w.startType(sliceType)
		w.typ(t.Elem())

	case TARRAY:
		w.startType(arrayType)
		w.uint64(uint64(t.NumElem()))
		w.typ(t.Elem())

	case TCHAN:
		w.startType(chanType)
		w.uint64(uint64(t.ChanDir()))
		w.typ(t.Elem())

	case TMAP:
		w.startType(mapType)
		w.typ(t.Key())
		w.typ(t.Elem())

	case TFUNC:
		w.startType(signatureType)
		w.setPkg(t.Pkg(), true)
		w.signature(t)

	case TSTRUCT:
		w.startType(structType)
		w.setPkg(t.Pkg(), true)

		w.uint64(uint64(t.NumFields()))
		for _, f := range t.FieldSlice() {
			w.pos(f.Pos)
			w.selector(f.Sym)
			w.typ(f.Type)
			w.bool(f.Embedded != 0)
			w.string(f.Note)
		}

	case TINTER:
		var embeddeds, methods []*types.Field
		for _, m := range t.Methods().Slice() {
			if m.Sym != nil {
				methods = append(methods, m)
			} else {
				embeddeds = append(embeddeds, m)
			}
		}

		w.startType(interfaceType)
		w.setPkg(t.Pkg(), true)

		w.uint64(uint64(len(embeddeds)))
		for _, f := range embeddeds {
			w.pos(f.Pos)
			w.typ(f.Type)
		}

		w.uint64(uint64(len(methods)))
		for _, f := range methods {
			w.pos(f.Pos)
			w.selector(f.Sym)
			w.signature(f.Type)
		}

	default:
		Fatalf("unexpected type: %v", t)
	}
}

func (w *exportWriter) setPkg(pkg *types.Pkg, write bool) {
	if pkg == nil {
		// TODO(mdempsky): Proactively set Pkg for types and
		// remove this fallback logic.
		pkg = localpkg
	}

	if write {
		w.pkg(pkg)
	}

	w.currPkg = pkg
}

func (w *exportWriter) signature(t *types.Type) {
	w.paramList(t.Params().FieldSlice())
	w.paramList(t.Results().FieldSlice())
	if n := t.Params().NumFields(); n > 0 {
		w.bool(t.Params().Field(n - 1).IsDDD())
	}
}

func (w *exportWriter) paramList(fs []*types.Field) {
	w.uint64(uint64(len(fs)))
	for _, f := range fs {
		w.param(f)
	}
}

func (w *exportWriter) param(f *types.Field) {
	w.pos(f.Pos)
	w.localIdent(origSym(f.Sym), 0)
	w.typ(f.Type)
}

func constTypeOf(typ *types.Type) Ctype {
	switch typ {
	case types.Idealint, types.Idealrune:
		return CTINT
	case types.Idealfloat:
		return CTFLT
	case types.Idealcomplex:
		return CTCPLX
	}

	switch typ.Etype {
	case TCHAN, TFUNC, TMAP, TNIL, TINTER, TSLICE:
		return CTNIL
	case TBOOL:
		return CTBOOL
	case TSTRING:
		return CTSTR
	case TINT, TINT8, TINT16, TINT32, TINT64,
		TUINT, TUINT8, TUINT16, TUINT32, TUINT64, TUINTPTR,
		TPTR, TUNSAFEPTR:
		return CTINT
	case TFLOAT32, TFLOAT64:
		return CTFLT
	case TCOMPLEX64, TCOMPLEX128:
		return CTCPLX
	}

	Fatalf("unexpected constant type: %v", typ)
	return 0
}

func (w *exportWriter) value(typ *types.Type, v Val) {
	if typ.IsUntyped() {
		typ = untype(v.Ctype())
	}
	w.typ(typ)

	// Each type has only one admissible constant representation,
	// so we could type switch directly on v.U here. However,
	// switching on the type increases symmetry with import logic
	// and provides a useful consistency check.

	switch constTypeOf(typ) {
	case CTNIL:
		// Only one value; nothing to encode.
		_ = v.U.(*NilVal)
	case CTBOOL:
		w.bool(v.U.(bool))
	case CTSTR:
		w.string(v.U.(string))
	case CTINT:
		w.mpint(&v.U.(*Mpint).Val, typ)
	case CTFLT:
		w.mpfloat(&v.U.(*Mpflt).Val, typ)
	case CTCPLX:
		x := v.U.(*Mpcplx)
		w.mpfloat(&x.Real.Val, typ)
		w.mpfloat(&x.Imag.Val, typ)
	}
}

func intSize(typ *types.Type) (signed bool, maxBytes uint) {
	if typ.IsUntyped() {
		return true, Mpprec / 8
	}

	switch typ.Etype {
	case TFLOAT32, TCOMPLEX64:
		return true, 3
	case TFLOAT64, TCOMPLEX128:
		return true, 7
	}

	signed = typ.IsSigned()
	maxBytes = uint(typ.Size())

	// The go/types API doesn't expose sizes to importers, so they
	// don't know how big these types are.
	switch typ.Etype {
	case TINT, TUINT, TUINTPTR:
		maxBytes = 8
	}

	return
}

// mpint exports a multi-precision integer.
//
// For unsigned types, small values are written out as a single
// byte. Larger values are written out as a length-prefixed big-endian
// byte string, where the length prefix is encoded as its complement.
// For example, bytes 0, 1, and 2 directly represent the integer
// values 0, 1, and 2; while bytes 255, 254, and 253 indicate a 1-,
// 2-, and 3-byte big-endian string follow.
//
// Encoding for signed types use the same general approach as for
// unsigned types, except small values use zig-zag encoding and the
// bottom bit of length prefix byte for large values is reserved as a
// sign bit.
//
// The exact boundary between small and large encodings varies
// according to the maximum number of bytes needed to encode a value
// of type typ. As a special case, 8-bit types are always encoded as a
// single byte.
//
// TODO(mdempsky): Is this level of complexity really worthwhile?
func (w *exportWriter) mpint(x *big.Int, typ *types.Type) {
	signed, maxBytes := intSize(typ)

	negative := x.Sign() < 0
	if !signed && negative {
		Fatalf("negative unsigned integer; type %v, value %v", typ, x)
	}

	b := x.Bytes()
	if len(b) > 0 && b[0] == 0 {
		Fatalf("leading zeros")
	}
	if uint(len(b)) > maxBytes {
		Fatalf("bad mpint length: %d > %d (type %v, value %v)", len(b), maxBytes, typ, x)
	}

	maxSmall := 256 - maxBytes
	if signed {
		maxSmall = 256 - 2*maxBytes
	}
	if maxBytes == 1 {
		maxSmall = 256
	}

	// Check if x can use small value encoding.
	if len(b) <= 1 {
		var ux uint
		if len(b) == 1 {
			ux = uint(b[0])
		}
		if signed {
			ux <<= 1
			if negative {
				ux--
			}
		}
		if ux < maxSmall {
			w.data.WriteByte(byte(ux))
			return
		}
	}

	n := 256 - uint(len(b))
	if signed {
		n = 256 - 2*uint(len(b))
		if negative {
			n |= 1
		}
	}
	if n < maxSmall || n >= 256 {
		Fatalf("encoding mistake: %d, %v, %v => %d", len(b), signed, negative, n)
	}

	w.data.WriteByte(byte(n))
	w.data.Write(b)
}

// mpfloat exports a multi-precision floating point number.
//
// The number's value is decomposed into mantissa × 2**exponent, where
// mantissa is an integer. The value is written out as mantissa (as a
// multi-precision integer) and then the exponent, except exponent is
// omitted if mantissa is zero.
func (w *exportWriter) mpfloat(f *big.Float, typ *types.Type) {
	if f.IsInf() {
		Fatalf("infinite constant")
	}

	// Break into f = mant × 2**exp, with 0.5 <= mant < 1.
	var mant big.Float
	exp := int64(f.MantExp(&mant))

	// Scale so that mant is an integer.
	prec := mant.MinPrec()
	mant.SetMantExp(&mant, int(prec))
	exp -= int64(prec)

	manti, acc := mant.Int(nil)
	if acc != big.Exact {
		Fatalf("mantissa scaling failed for %f (%s)", f, acc)
	}
	w.mpint(manti, typ)
	if manti.Sign() != 0 {
		w.int64(exp)
	}
}

func (w *exportWriter) bool(b bool) bool {
	var x uint64
	if b {
		x = 1
	}
	w.uint64(x)
	return b
}

func (w *exportWriter) int64(x int64)   { w.data.int64(x) }
func (w *exportWriter) uint64(x uint64) { w.data.uint64(x) }
func (w *exportWriter) string(s string) { w.uint64(w.p.stringOff(s)) }

// Compiler-specific extensions.

func (w *exportWriter) varExt(n *Node) {
	w.linkname(n.Sym)
}

func (w *exportWriter) funcExt(n *Node) {
	w.linkname(n.Sym)

	// Escape analysis.
	for _, fs := range types.RecvsParams {
		for _, f := range fs(n.Type).FieldSlice() {
			w.string(f.Note)
		}
	}

	// Inline body.
	if n.Func.Inl != nil {
		w.uint64(1 + uint64(n.Func.Inl.Cost))
		if n.Func.ExportInline() {
			w.p.doInline(n)
		}

		// Endlineno for inlined function.
		if n.Name.Defn != nil {
			w.pos(n.Name.Defn.Func.Endlineno)
		} else {
			// When the exported node was defined externally,
			// e.g. io exports atomic.(*Value).Load or bytes exports errors.New.
			// Keep it as we don't distinguish this case in iimport.go.
			w.pos(n.Func.Endlineno)
		}
	} else {
		w.uint64(0)
	}
}

func (w *exportWriter) methExt(m *types.Field) {
	w.bool(m.Nointerface())
	w.funcExt(asNode(m.Type.Nname()))
}

func (w *exportWriter) linkname(s *types.Sym) {
	w.string(s.Linkname)
}

// Inline bodies.

func (w *exportWriter) stmtList(list Nodes) {
	for _, n := range list.Slice() {
		w.node(n)
	}
	w.op(OEND)
}

func (w *exportWriter) node(n *Node) {
	if opprec[n.Op] < 0 {
		w.stmt(n)
	} else {
		w.expr(n)
	}
}

// Caution: stmt will emit more than one node for statement nodes n that have a non-empty
// n.Ninit and where n cannot have a natural init section (such as in "if", "for", etc.).
func (w *exportWriter) stmt(n *Node) {
	if n.Ninit.Len() > 0 && !stmtwithinit(n.Op) {
		// can't use stmtList here since we don't want the final OEND
		for _, n := range n.Ninit.Slice() {
			w.stmt(n)
		}
	}

	switch op := n.Op; op {
	case ODCL:
		w.op(ODCL)
		w.pos(n.Left.Pos)
		w.localName(n.Left)
		w.typ(n.Left.Type)

	// case ODCLFIELD:
	//	unimplemented - handled by default case

	case OAS:
		// Don't export "v = <N>" initializing statements, hope they're always
		// preceded by the DCL which will be re-parsed and typecheck to reproduce
		// the "v = <N>" again.
		if n.Right != nil {
			w.op(OAS)
			w.pos(n.Pos)
			w.expr(n.Left)
			w.expr(n.Right)
		}

	case OASOP:
		w.op(OASOP)
		w.pos(n.Pos)
		w.op(n.SubOp())
		w.expr(n.Left)
		if w.bool(!n.Implicit()) {
			w.expr(n.Right)
		}

	case OAS2, OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV:
		w.op(OAS2)
		w.pos(n.Pos)
		w.exprList(n.List)
		w.exprList(n.Rlist)

	case ORETURN:
		w.op(ORETURN)
		w.pos(n.Pos)
		w.exprList(n.List)

	// case ORETJMP:
	// 	unreachable - generated by compiler for trampolin routines

	case OGO, ODEFER:
		w.op(op)
		w.pos(n.Pos)
		w.expr(n.Left)

	case OIF:
		w.op(OIF)
		w.pos(n.Pos)
		w.stmtList(n.Ninit)
		w.expr(n.Left)
		w.stmtList(n.Nbody)
		w.stmtList(n.Rlist)

	case OFOR:
		w.op(OFOR)
		w.pos(n.Pos)
		w.stmtList(n.Ninit)
		w.exprsOrNil(n.Left, n.Right)
		w.stmtList(n.Nbody)

	case ORANGE:
		w.op(ORANGE)
		w.pos(n.Pos)
		w.stmtList(n.List)
		w.expr(n.Right)
		w.stmtList(n.Nbody)

	case OSELECT, OSWITCH:
		w.op(op)
		w.pos(n.Pos)
		w.stmtList(n.Ninit)
		w.exprsOrNil(n.Left, nil)
		w.stmtList(n.List)

	case OCASE, OXCASE:
		w.op(OXCASE)
		w.pos(n.Pos)
		w.stmtList(n.List)
		w.stmtList(n.Nbody)

	case OFALL:
		w.op(OFALL)
		w.pos(n.Pos)

	case OBREAK, OCONTINUE:
		w.op(op)
		w.pos(n.Pos)
		w.exprsOrNil(n.Left, nil)

	case OEMPTY:
		// nothing to emit

	case OGOTO, OLABEL:
		w.op(op)
		w.pos(n.Pos)
		w.string(n.Sym.Name)

	default:
		Fatalf("exporter: CANNOT EXPORT: %v\nPlease notify gri@\n", n.Op)
	}
}

func (w *exportWriter) exprList(list Nodes) {
	for _, n := range list.Slice() {
		w.expr(n)
	}
	w.op(OEND)
}

func (w *exportWriter) expr(n *Node) {
	// from nodefmt (fmt.go)
	//
	// nodefmt reverts nodes back to their original - we don't need to do
	// it because we are not bound to produce valid Go syntax when exporting
	//
	// if (fmtmode != FExp || n.Op != OLITERAL) && n.Orig != nil {
	// 	n = n.Orig
	// }

	// from exprfmt (fmt.go)
	for n.Op == OPAREN || n.Implicit() && (n.Op == ODEREF || n.Op == OADDR || n.Op == ODOT || n.Op == ODOTPTR) {
		n = n.Left
	}

	switch op := n.Op; op {
	// expressions
	// (somewhat closely following the structure of exprfmt in fmt.go)
	case OLITERAL:
		if n.Val().Ctype() == CTNIL && n.Orig != nil && n.Orig != n {
			w.expr(n.Orig)
			break
		}
		w.op(OLITERAL)
		w.pos(n.Pos)
		w.value(n.Type, n.Val())

	case ONAME:
		// Special case: explicit name of func (*T) method(...) is turned into pkg.(*T).method,
		// but for export, this should be rendered as (*pkg.T).meth.
		// These nodes have the special property that they are names with a left OTYPE and a right ONAME.
		if n.isMethodExpression() {
			w.op(OXDOT)
			w.pos(n.Pos)
			w.expr(n.Left) // n.Left.Op == OTYPE
			w.selector(n.Right.Sym)
			break
		}

		// Package scope name.
		if (n.Class() == PEXTERN || n.Class() == PFUNC) && !n.isBlank() {
			w.op(ONONAME)
			w.qualifiedIdent(n)
			break
		}

		// Function scope name.
		w.op(ONAME)
		w.localName(n)

	// case OPACK, ONONAME:
	// 	should have been resolved by typechecking - handled by default case

	case OTYPE:
		w.op(OTYPE)
		w.typ(n.Type)

	// case OTARRAY, OTMAP, OTCHAN, OTSTRUCT, OTINTER, OTFUNC:
	// 	should have been resolved by typechecking - handled by default case

	// case OCLOSURE:
	//	unimplemented - handled by default case

	// case OCOMPLIT:
	// 	should have been resolved by typechecking - handled by default case

	case OPTRLIT:
		w.op(OPTRLIT)
		w.pos(n.Pos)
		w.expr(n.Left)
		w.bool(n.Implicit())

	case OSTRUCTLIT:
		w.op(OSTRUCTLIT)
		w.pos(n.Pos)
		w.typ(n.Type)
		w.elemList(n.List) // special handling of field names

	case OARRAYLIT, OSLICELIT, OMAPLIT:
		w.op(OCOMPLIT)
		w.pos(n.Pos)
		w.typ(n.Type)
		w.exprList(n.List)

	case OKEY:
		w.op(OKEY)
		w.pos(n.Pos)
		w.exprsOrNil(n.Left, n.Right)

	// case OSTRUCTKEY:
	//	unreachable - handled in case OSTRUCTLIT by elemList

	// case OCALLPART:
	//	unimplemented - handled by default case

	case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
		w.op(OXDOT)
		w.pos(n.Pos)
		w.expr(n.Left)
		w.selector(n.Sym)

	case ODOTTYPE, ODOTTYPE2:
		w.op(ODOTTYPE)
		w.pos(n.Pos)
		w.expr(n.Left)
		w.typ(n.Type)

	case OINDEX, OINDEXMAP:
		w.op(OINDEX)
		w.pos(n.Pos)
		w.expr(n.Left)
		w.expr(n.Right)

	case OSLICE, OSLICESTR, OSLICEARR:
		w.op(OSLICE)
		w.pos(n.Pos)
		w.expr(n.Left)
		low, high, _ := n.SliceBounds()
		w.exprsOrNil(low, high)

	case OSLICE3, OSLICE3ARR:
		w.op(OSLICE3)
		w.pos(n.Pos)
		w.expr(n.Left)
		low, high, max := n.SliceBounds()
		w.exprsOrNil(low, high)
		w.expr(max)

	case OCOPY, OCOMPLEX:
		// treated like other builtin calls (see e.g., OREAL)
		w.op(op)
		w.pos(n.Pos)
		w.expr(n.Left)
		w.expr(n.Right)
		w.op(OEND)

	case OCONV, OCONVIFACE, OCONVNOP, OBYTES2STR, ORUNES2STR, OSTR2BYTES, OSTR2RUNES, ORUNESTR:
		w.op(OCONV)
		w.pos(n.Pos)
		w.expr(n.Left)
		w.typ(n.Type)

	case OREAL, OIMAG, OAPPEND, OCAP, OCLOSE, ODELETE, OLEN, OMAKE, ONEW, OPANIC, ORECOVER, OPRINT, OPRINTN:
		w.op(op)
		w.pos(n.Pos)
		if n.Left != nil {
			w.expr(n.Left)
			w.op(OEND)
		} else {
			w.exprList(n.List) // emits terminating OEND
		}
		// only append() calls may contain '...' arguments
		if op == OAPPEND {
			w.bool(n.IsDDD())
		} else if n.IsDDD() {
			Fatalf("exporter: unexpected '...' with %v call", op)
		}

	case OCALL, OCALLFUNC, OCALLMETH, OCALLINTER, OGETG:
		w.op(OCALL)
		w.pos(n.Pos)
		w.expr(n.Left)
		w.exprList(n.List)
		w.bool(n.IsDDD())

	case OMAKEMAP, OMAKECHAN, OMAKESLICE:
		w.op(op) // must keep separate from OMAKE for importer
		w.pos(n.Pos)
		w.typ(n.Type)
		switch {
		default:
			// empty list
			w.op(OEND)
		case n.List.Len() != 0: // pre-typecheck
			w.exprList(n.List) // emits terminating OEND
		case n.Right != nil:
			w.expr(n.Left)
			w.expr(n.Right)
			w.op(OEND)
		case n.Left != nil && (n.Op == OMAKESLICE || !n.Left.Type.IsUntyped()):
			w.expr(n.Left)
			w.op(OEND)
		}

	// unary expressions
	case OPLUS, ONEG, OADDR, OBITNOT, ODEREF, ONOT, ORECV:
		w.op(op)
		w.pos(n.Pos)
		w.expr(n.Left)

	// binary expressions
	case OADD, OAND, OANDAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE, OLT,
		OLSH, OMOD, OMUL, ONE, OOR, OOROR, ORSH, OSEND, OSUB, OXOR:
		w.op(op)
		w.pos(n.Pos)
		w.expr(n.Left)
		w.expr(n.Right)

	case OADDSTR:
		w.op(OADDSTR)
		w.pos(n.Pos)
		w.exprList(n.List)

	case ODCLCONST:
		// if exporting, DCLCONST should just be removed as its usage
		// has already been replaced with literals

	default:
		Fatalf("cannot export %v (%d) node\n"+
			"==> please file an issue and assign to gri@\n", n.Op, int(n.Op))
	}
}

func (w *exportWriter) op(op Op) {
	w.uint64(uint64(op))
}

func (w *exportWriter) exprsOrNil(a, b *Node) {
	ab := 0
	if a != nil {
		ab |= 1
	}
	if b != nil {
		ab |= 2
	}
	w.uint64(uint64(ab))
	if ab&1 != 0 {
		w.expr(a)
	}
	if ab&2 != 0 {
		w.node(b)
	}
}

func (w *exportWriter) elemList(list Nodes) {
	w.uint64(uint64(list.Len()))
	for _, n := range list.Slice() {
		w.selector(n.Sym)
		w.expr(n.Left)
	}
}

func (w *exportWriter) localName(n *Node) {
	// Escape analysis happens after inline bodies are saved, but
	// we're using the same ONAME nodes, so we might still see
	// PAUTOHEAP here.
	//
	// Check for Stackcopy to identify PAUTOHEAP that came from
	// PPARAM/PPARAMOUT, because we only want to include vargen in
	// non-param names.
	var v int32
	if n.Class() == PAUTO || (n.Class() == PAUTOHEAP && n.Name.Param.Stackcopy == nil) {
		v = n.Name.Vargen
	}

	w.localIdent(n.Sym, v)
}

func (w *exportWriter) localIdent(s *types.Sym, v int32) {
	// Anonymous parameters.
	if s == nil {
		w.string("")
		return
	}

	name := s.Name
	if name == "_" {
		w.string("_")
		return
	}

	if i := strings.LastIndex(name, "."); i >= 0 {
		Fatalf("unexpected dot in identifier: %v", name)
	}

	if v > 0 {
		if strings.Contains(name, "·") {
			Fatalf("exporter: unexpected · in symbol name")
		}
		name = fmt.Sprintf("%s·%d", name, v)
	}

	if !ast.IsExported(name) && s.Pkg != w.currPkg {
		Fatalf("weird package in name: %v => %v, not %q", s, name, w.currPkg.Path)
	}

	w.string(name)
}

type intWriter struct {
	bytes.Buffer
}

func (w *intWriter) int64(x int64) {
	var buf [binary.MaxVarintLen64]byte
	n := binary.PutVarint(buf[:], x)
	w.Write(buf[:n])
}

func (w *intWriter) uint64(x uint64) {
	var buf [binary.MaxVarintLen64]byte
	n := binary.PutUvarint(buf[:], x)
	w.Write(buf[:n])
}
