// 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 import.
// See iexport.go for the export data format.

package typecheck

import (
	"encoding/binary"
	"fmt"
	"go/constant"
	"math/big"
	"os"
	"strings"

	"cmd/compile/internal/base"
	"cmd/compile/internal/ir"
	"cmd/compile/internal/types"
	"cmd/internal/obj"
	"cmd/internal/src"
)

// An iimporterAndOffset identifies an importer and an offset within
// its data section.
type iimporterAndOffset struct {
	p   *iimporter
	off uint64
}

var (
	// DeclImporter maps from imported identifiers to an importer
	// and offset where that identifier's declaration can be read.
	DeclImporter = map[*types.Sym]iimporterAndOffset{}

	// inlineImporter is like DeclImporter, but for inline bodies
	// for function and method symbols.
	inlineImporter = map[*types.Sym]iimporterAndOffset{}
)

// expandDecl returns immediately if n is already a Name node. Otherwise, n should
// be an Ident node, and expandDecl reads in the definition of the specified
// identifier from the appropriate package.
func expandDecl(n ir.Node) ir.Node {
	if n, ok := n.(*ir.Name); ok {
		return n
	}

	id := n.(*ir.Ident)
	if n := id.Sym().PkgDef(); n != nil {
		return n.(*ir.Name)
	}

	r := importReaderFor(id.Sym(), DeclImporter)
	if r == nil {
		// Can happen if user tries to reference an undeclared name.
		return n
	}

	return r.doDecl(n.Sym())
}

// ImportBody reads in the dcls and body of an imported function (which should not
// yet have been read in).
func ImportBody(fn *ir.Func) {
	if fn.Inl.Body != nil {
		base.Fatalf("%v already has inline body", fn)
	}

	r := importReaderFor(fn.Nname.Sym(), inlineImporter)
	if r == nil {
		base.Fatalf("missing import reader for %v", fn)
	}

	if inimport {
		base.Fatalf("recursive inimport")
	}
	inimport = true
	r.doInline(fn)
	inimport = false
}

func importReaderFor(sym *types.Sym, importers map[*types.Sym]iimporterAndOffset) *importReader {
	x, ok := importers[sym]
	if !ok {
		return nil
	}

	return x.p.newReader(x.off, sym.Pkg)
}

type intReader struct {
	*strings.Reader
	pkg *types.Pkg
}

func (r *intReader) int64() int64 {
	i, err := binary.ReadVarint(r.Reader)
	if err != nil {
		base.Errorf("import %q: read error: %v", r.pkg.Path, err)
		base.ErrorExit()
	}
	return i
}

func (r *intReader) uint64() uint64 {
	i, err := binary.ReadUvarint(r.Reader)
	if err != nil {
		base.Errorf("import %q: read error: %v", r.pkg.Path, err)
		base.ErrorExit()
	}
	return i
}

func ReadImports(pkg *types.Pkg, data string) {
	ird := &intReader{strings.NewReader(data), pkg}

	version := ird.uint64()
	switch version {
	case /* iexportVersionGenerics, */ iexportVersionPosCol, iexportVersionGo1_11:
	default:
		if version > iexportVersionGenerics {
			base.Errorf("import %q: unstable export format version %d, just recompile", pkg.Path, version)
		} else {
			base.Errorf("import %q: unknown export format version %d", pkg.Path, version)
		}
		base.ErrorExit()
	}

	sLen := int64(ird.uint64())
	dLen := int64(ird.uint64())

	// TODO(mdempsky): Replace os.SEEK_CUR with io.SeekCurrent after
	// #44505 is fixed.
	whence, _ := ird.Seek(0, os.SEEK_CUR)
	stringData := data[whence : whence+sLen]
	declData := data[whence+sLen : whence+sLen+dLen]
	ird.Seek(sLen+dLen, os.SEEK_CUR)

	p := &iimporter{
		exportVersion: version,
		ipkg:          pkg,

		pkgCache:     map[uint64]*types.Pkg{},
		posBaseCache: map[uint64]*src.PosBase{},
		typCache:     map[uint64]*types.Type{},

		stringData: stringData,
		declData:   declData,
	}

	for i, pt := range predeclared() {
		p.typCache[uint64(i)] = pt
	}

	// Declaration index.
	for nPkgs := ird.uint64(); nPkgs > 0; nPkgs-- {
		pkg := p.pkgAt(ird.uint64())
		pkgName := p.stringAt(ird.uint64())
		pkgHeight := int(ird.uint64())
		if pkg.Name == "" {
			pkg.Name = pkgName
			pkg.Height = pkgHeight
			types.NumImport[pkgName]++

			// TODO(mdempsky): This belongs somewhere else.
			pkg.Lookup("_").Def = ir.BlankNode
		} else {
			if pkg.Name != pkgName {
				base.Fatalf("conflicting package names %v and %v for path %q", pkg.Name, pkgName, pkg.Path)
			}
			if pkg.Height != pkgHeight {
				base.Fatalf("conflicting package heights %v and %v for path %q", pkg.Height, pkgHeight, pkg.Path)
			}
		}

		for nSyms := ird.uint64(); nSyms > 0; nSyms-- {
			s := pkg.Lookup(p.nameAt(ird.uint64()))
			off := ird.uint64()

			if _, ok := DeclImporter[s]; !ok {
				DeclImporter[s] = iimporterAndOffset{p, off}
			}
		}
	}

	// Inline body index.
	for nPkgs := ird.uint64(); nPkgs > 0; nPkgs-- {
		pkg := p.pkgAt(ird.uint64())

		for nSyms := ird.uint64(); nSyms > 0; nSyms-- {
			s := pkg.Lookup(p.nameAt(ird.uint64()))
			off := ird.uint64()

			if _, ok := inlineImporter[s]; !ok {
				inlineImporter[s] = iimporterAndOffset{p, off}
			}
		}
	}
}

type iimporter struct {
	exportVersion uint64
	ipkg          *types.Pkg

	pkgCache     map[uint64]*types.Pkg
	posBaseCache map[uint64]*src.PosBase
	typCache     map[uint64]*types.Type

	stringData string
	declData   string
}

func (p *iimporter) stringAt(off uint64) string {
	var x [binary.MaxVarintLen64]byte
	n := copy(x[:], p.stringData[off:])

	slen, n := binary.Uvarint(x[:n])
	if n <= 0 {
		base.Fatalf("varint failed")
	}
	spos := off + uint64(n)
	return p.stringData[spos : spos+slen]
}

// nameAt is the same as stringAt, except it replaces instances
// of "" with the path of the package being imported.
func (p *iimporter) nameAt(off uint64) string {
	s := p.stringAt(off)
	// Names of objects (functions, methods, globals) may include ""
	// to represent the path name of the imported package.
	// Replace "" with the imported package prefix. This occurs
	// specifically for generics where the names of instantiations
	// and dictionaries contain package-qualified type names.
	// Include the dot to avoid matching with struct tags ending in '"'.
	if strings.Contains(s, "\"\".") {
		s = strings.Replace(s, "\"\".", p.ipkg.Prefix+".", -1)
	}
	return s
}

func (p *iimporter) posBaseAt(off uint64) *src.PosBase {
	if posBase, ok := p.posBaseCache[off]; ok {
		return posBase
	}

	file := p.stringAt(off)
	posBase := src.NewFileBase(file, file)
	p.posBaseCache[off] = posBase
	return posBase
}

func (p *iimporter) pkgAt(off uint64) *types.Pkg {
	if pkg, ok := p.pkgCache[off]; ok {
		return pkg
	}

	pkg := p.ipkg
	if pkgPath := p.stringAt(off); pkgPath != "" {
		pkg = types.NewPkg(pkgPath, "")
	}
	p.pkgCache[off] = pkg
	return pkg
}

// An importReader keeps state for reading an individual imported
// object (declaration or inline body).
type importReader struct {
	strings.Reader
	p *iimporter

	currPkg    *types.Pkg
	prevBase   *src.PosBase
	prevLine   int64
	prevColumn int64

	// curfn is the current function we're importing into.
	curfn *ir.Func
	// Slice of all dcls for function, including any interior closures
	allDcls        []*ir.Name
	allClosureVars []*ir.Name
	autotmpgen     int
}

func (p *iimporter) newReader(off uint64, pkg *types.Pkg) *importReader {
	r := &importReader{
		p:       p,
		currPkg: pkg,
	}
	// (*strings.Reader).Reset wasn't added until Go 1.7, and we
	// need to build with Go 1.4.
	r.Reader = *strings.NewReader(p.declData[off:])
	return r
}

func (r *importReader) string() string        { return r.p.stringAt(r.uint64()) }
func (r *importReader) name() string          { return r.p.nameAt(r.uint64()) }
func (r *importReader) posBase() *src.PosBase { return r.p.posBaseAt(r.uint64()) }
func (r *importReader) pkg() *types.Pkg       { return r.p.pkgAt(r.uint64()) }

func (r *importReader) setPkg() {
	r.currPkg = r.pkg()
}

func (r *importReader) doDecl(sym *types.Sym) *ir.Name {
	tag := r.byte()
	pos := r.pos()

	switch tag {
	case 'A':
		typ := r.typ()

		return importalias(pos, sym, typ)

	case 'C':
		typ := r.typ()
		val := r.value(typ)

		n := importconst(pos, sym, typ, val)
		r.constExt(n)
		return n

	case 'F', 'G':
		var tparams []*types.Field
		if tag == 'G' {
			tparams = r.tparamList()
		}
		typ := r.signature(nil, tparams)

		n := importfunc(pos, sym, typ)
		r.funcExt(n)
		return n

	case 'T', 'U':
		// Types can be recursive. We need to setup a stub
		// declaration before recursing.
		n := importtype(pos, sym)
		t := n.Type()
		if tag == 'U' {
			rparams := r.typeList()
			t.SetRParams(rparams)
		}

		// We also need to defer width calculations until
		// after the underlying type has been assigned.
		types.DeferCheckSize()
		deferDoInst()
		underlying := r.typ()
		t.SetUnderlying(underlying)

		if underlying.IsInterface() {
			// Finish up all type instantiations and CheckSize calls
			// now that a top-level type is fully constructed.
			resumeDoInst()
			types.ResumeCheckSize()
			r.typeExt(t)
			return n
		}

		ms := make([]*types.Field, r.uint64())
		for i := range ms {
			mpos := r.pos()
			msym := r.selector()
			recv := r.param()
			mtyp := r.signature(recv, nil)

			// MethodSym already marked m.Sym as a function.
			m := ir.NewNameAt(mpos, ir.MethodSym(recv.Type, msym))
			m.Class = ir.PFUNC
			m.SetType(mtyp)

			m.Func = ir.NewFunc(mpos)
			m.Func.Nname = m

			f := types.NewField(mpos, msym, mtyp)
			f.Nname = m
			ms[i] = f
		}
		t.Methods().Set(ms)

		// Finish up all instantiations and CheckSize calls now
		// that a top-level type is fully constructed.
		resumeDoInst()
		types.ResumeCheckSize()

		r.typeExt(t)
		for _, m := range ms {
			r.methExt(m)
		}
		return n

	case 'P':
		if r.p.exportVersion < iexportVersionGenerics {
			base.Fatalf("unexpected type param type")
		}
		if sym.Def != nil {
			// Make sure we use the same type param type for the same
			// name, whether it is created during types1-import or
			// this types2-to-types1 translation.
			return sym.Def.(*ir.Name)
		}
		// The typeparam index is set at the point where the containing type
		// param list is imported.
		t := types.NewTypeParam(sym, 0)
		// Nname needed to save the pos.
		nname := ir.NewDeclNameAt(pos, ir.OTYPE, sym)
		sym.Def = nname
		nname.SetType(t)
		t.SetNod(nname)

		t.SetBound(r.typ())
		return nname

	case 'V':
		typ := r.typ()

		n := importvar(pos, sym, typ)
		r.varExt(n)
		return n

	default:
		base.Fatalf("unexpected tag: %v", tag)
		panic("unreachable")
	}
}

func (r *importReader) value(typ *types.Type) constant.Value {
	var kind constant.Kind
	var valType *types.Type

	if typ.IsTypeParam() {
		// If a constant had a typeparam type, then we wrote out its
		// actual constant kind as well.
		kind = constant.Kind(r.int64())
		switch kind {
		case constant.Int:
			valType = types.Types[types.TINT64]
		case constant.Float:
			valType = types.Types[types.TFLOAT64]
		case constant.Complex:
			valType = types.Types[types.TCOMPLEX128]
		}
	} else {
		kind = constTypeOf(typ)
		valType = typ
	}

	switch kind {
	case constant.Bool:
		return constant.MakeBool(r.bool())
	case constant.String:
		return constant.MakeString(r.string())
	case constant.Int:
		var i big.Int
		r.mpint(&i, valType)
		return constant.Make(&i)
	case constant.Float:
		return r.float(valType)
	case constant.Complex:
		return makeComplex(r.float(valType), r.float(valType))
	}

	base.Fatalf("unexpected value type: %v", typ)
	panic("unreachable")
}

func (r *importReader) mpint(x *big.Int, typ *types.Type) {
	signed, maxBytes := intSize(typ)

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

	n, _ := r.ReadByte()
	if uint(n) < maxSmall {
		v := int64(n)
		if signed {
			v >>= 1
			if n&1 != 0 {
				v = ^v
			}
		}
		x.SetInt64(v)
		return
	}

	v := -n
	if signed {
		v = -(n &^ 1) >> 1
	}
	if v < 1 || uint(v) > maxBytes {
		base.Fatalf("weird decoding: %v, %v => %v", n, signed, v)
	}
	b := make([]byte, v)
	r.Read(b)
	x.SetBytes(b)
	if signed && n&1 != 0 {
		x.Neg(x)
	}
}

func (r *importReader) float(typ *types.Type) constant.Value {
	var mant big.Int
	r.mpint(&mant, typ)
	var f big.Float
	f.SetInt(&mant)
	if f.Sign() != 0 {
		f.SetMantExp(&f, int(r.int64()))
	}
	return constant.Make(&f)
}

func (r *importReader) mprat(orig constant.Value) constant.Value {
	if !r.bool() {
		return orig
	}
	var rat big.Rat
	rat.SetString(r.string())
	return constant.Make(&rat)
}

func (r *importReader) ident(selector bool) *types.Sym {
	name := r.string()
	if name == "" {
		return nil
	}
	pkg := r.currPkg
	if selector {
		if types.IsExported(name) {
			pkg = types.LocalPkg
		}
	} else {
		if name == "$autotmp" {
			name = autotmpname(r.autotmpgen)
			r.autotmpgen++
		}
	}
	return pkg.Lookup(name)
}

func (r *importReader) localIdent() *types.Sym { return r.ident(false) }
func (r *importReader) selector() *types.Sym   { return r.ident(true) }

func (r *importReader) qualifiedIdent() *ir.Ident {
	name := r.name()
	pkg := r.pkg()
	sym := pkg.Lookup(name)
	return ir.NewIdent(src.NoXPos, sym)
}

func (r *importReader) pos() src.XPos {
	delta := r.int64()
	r.prevColumn += delta >> 1
	if delta&1 != 0 {
		delta = r.int64()
		r.prevLine += delta >> 1
		if delta&1 != 0 {
			r.prevBase = r.posBase()
		}
	}

	if (r.prevBase == nil || r.prevBase.AbsFilename() == "") && r.prevLine == 0 && r.prevColumn == 0 {
		// TODO(mdempsky): Remove once we reliably write
		// position information for all nodes.
		return src.NoXPos
	}

	if r.prevBase == nil {
		base.Fatalf("missing posbase")
	}
	pos := src.MakePos(r.prevBase, uint(r.prevLine), uint(r.prevColumn))
	return base.Ctxt.PosTable.XPos(pos)
}

func (r *importReader) typ() *types.Type {
	// If this is a top-level type call, defer type instantiations until the
	// type is fully constructed.
	types.DeferCheckSize()
	deferDoInst()
	t := r.p.typAt(r.uint64())
	resumeDoInst()
	types.ResumeCheckSize()
	return t
}

func (r *importReader) exoticType() *types.Type {
	switch r.uint64() {
	case exoticTypeNil:
		return nil
	case exoticTypeTuple:
		funarg := types.Funarg(r.uint64())
		n := r.uint64()
		fs := make([]*types.Field, n)
		for i := range fs {
			pos := r.pos()
			var sym *types.Sym
			switch r.uint64() {
			case exoticTypeSymNil:
				sym = nil
			case exoticTypeSymNoPkg:
				sym = types.NoPkg.Lookup(r.string())
			case exoticTypeSymWithPkg:
				pkg := r.pkg()
				sym = pkg.Lookup(r.string())
			default:
				base.Fatalf("unknown symbol kind")
			}
			typ := r.typ()
			f := types.NewField(pos, sym, typ)
			fs[i] = f
		}
		t := types.NewStruct(types.NoPkg, fs)
		t.StructType().Funarg = funarg
		return t
	case exoticTypeRecv:
		var rcvr *types.Field
		if r.bool() { // isFakeRecv
			rcvr = types.FakeRecv()
		} else {
			rcvr = r.exoticParam()
		}
		return r.exoticSignature(rcvr)
	case exoticTypeRegular:
		return r.typ()
	default:
		base.Fatalf("bad kind of call type")
		return nil
	}
}

func (r *importReader) exoticSelector() *types.Sym {
	name := r.string()
	if name == "" {
		return nil
	}
	pkg := r.currPkg
	if types.IsExported(name) {
		pkg = types.LocalPkg
	}
	if r.uint64() != 0 {
		pkg = r.pkg()
	}
	return pkg.Lookup(name)
}

func (r *importReader) exoticSignature(recv *types.Field) *types.Type {
	var pkg *types.Pkg
	if r.bool() { // hasPkg
		pkg = r.pkg()
	}
	params := r.exoticParamList()
	results := r.exoticParamList()
	return types.NewSignature(pkg, recv, nil, params, results)
}

func (r *importReader) exoticParamList() []*types.Field {
	n := r.uint64()
	fs := make([]*types.Field, n)
	for i := range fs {
		fs[i] = r.exoticParam()
	}
	return fs
}

func (r *importReader) exoticParam() *types.Field {
	pos := r.pos()
	sym := r.exoticSym()
	off := r.uint64()
	typ := r.exoticType()
	ddd := r.bool()
	f := types.NewField(pos, sym, typ)
	f.Offset = int64(off)
	if sym != nil {
		f.Nname = ir.NewNameAt(pos, sym)
	}
	f.SetIsDDD(ddd)
	return f
}

func (r *importReader) exoticField() *types.Field {
	pos := r.pos()
	sym := r.exoticSym()
	off := r.uint64()
	typ := r.exoticType()
	note := r.string()
	f := types.NewField(pos, sym, typ)
	f.Offset = int64(off)
	if sym != nil {
		f.Nname = ir.NewNameAt(pos, sym)
	}
	f.Note = note
	return f
}

func (r *importReader) exoticSym() *types.Sym {
	name := r.string()
	if name == "" {
		return nil
	}
	var pkg *types.Pkg
	if types.IsExported(name) {
		pkg = types.LocalPkg
	} else {
		pkg = r.pkg()
	}
	return pkg.Lookup(name)
}

func (p *iimporter) typAt(off uint64) *types.Type {
	t, ok := p.typCache[off]
	if !ok {
		if off < predeclReserved {
			base.Fatalf("predeclared type missing from cache: %d", off)
		}
		t = p.newReader(off-predeclReserved, nil).typ1()
		// Ensure size is calculated for imported types. Since CL 283313, the compiler
		// does not compile the function immediately when it sees them. Instead, funtions
		// are pushed to compile queue, then draining from the queue for compiling.
		// During this process, the size calculation is disabled, so it is not safe for
		// calculating size during SSA generation anymore. See issue #44732.
		//
		// No need to calc sizes for re-instantiated generic types, and
		// they are not necessarily resolved until the top-level type is
		// defined (because of recursive types).
		if t.OrigSym() == nil || !t.HasTParam() {
			types.CheckSize(t)
		}
		p.typCache[off] = t
	}
	return t
}

func (r *importReader) typ1() *types.Type {
	switch k := r.kind(); k {
	default:
		base.Fatalf("unexpected kind tag in %q: %v", r.p.ipkg.Path, k)
		return nil

	case definedType:
		// We might be called from within doInline, in which
		// case Sym.Def can point to declared parameters
		// instead of the top-level types. Also, we don't
		// support inlining functions with local defined
		// types. Therefore, this must be a package-scope
		// type.
		n := expandDecl(r.qualifiedIdent())
		if n.Op() != ir.OTYPE {
			base.Fatalf("expected OTYPE, got %v: %v, %v", n.Op(), n.Sym(), n)
		}
		return n.Type()
	case pointerType:
		return types.NewPtr(r.typ())
	case sliceType:
		return types.NewSlice(r.typ())
	case arrayType:
		n := r.uint64()
		return types.NewArray(r.typ(), int64(n))
	case chanType:
		dir := types.ChanDir(r.uint64())
		return types.NewChan(r.typ(), dir)
	case mapType:
		return types.NewMap(r.typ(), r.typ())

	case signatureType:
		r.setPkg()
		return r.signature(nil, nil)

	case structType:
		r.setPkg()

		fs := make([]*types.Field, r.uint64())
		for i := range fs {
			pos := r.pos()
			sym := r.selector()
			typ := r.typ()
			emb := r.bool()
			note := r.string()

			f := types.NewField(pos, sym, typ)
			if emb {
				f.Embedded = 1
			}
			f.Note = note
			fs[i] = f
		}

		return types.NewStruct(r.currPkg, fs)

	case interfaceType:
		r.setPkg()

		embeddeds := make([]*types.Field, r.uint64())
		for i := range embeddeds {
			pos := r.pos()
			typ := r.typ()

			embeddeds[i] = types.NewField(pos, nil, typ)
		}

		methods := make([]*types.Field, r.uint64())
		for i := range methods {
			pos := r.pos()
			sym := r.selector()
			typ := r.signature(types.FakeRecv(), nil)

			methods[i] = types.NewField(pos, sym, typ)
		}

		if len(embeddeds)+len(methods) == 0 {
			return types.Types[types.TINTER]
		}

		t := types.NewInterface(r.currPkg, append(embeddeds, methods...))

		// Ensure we expand the interface in the frontend (#25055).
		types.CheckSize(t)
		return t

	case typeParamType:
		if r.p.exportVersion < iexportVersionGenerics {
			base.Fatalf("unexpected type param type")
		}
		// Similar to code for defined types, since we "declared"
		// typeparams to deal with recursion (typeparam is used within its
		// own type bound).
		ident := r.qualifiedIdent()
		if ident.Sym().Def != nil {
			return ident.Sym().Def.(*ir.Name).Type()
		}
		n := expandDecl(ident)
		if n.Op() != ir.OTYPE {
			base.Fatalf("expected OTYPE, got %v: %v, %v", n.Op(), n.Sym(), n)
		}
		return n.Type()

	case instanceType:
		if r.p.exportVersion < iexportVersionGenerics {
			base.Fatalf("unexpected instantiation type")
		}
		pos := r.pos()
		len := r.uint64()
		targs := make([]*types.Type, len)
		for i := range targs {
			targs[i] = r.typ()
		}
		baseType := r.typ()
		t := Instantiate(pos, baseType, targs)
		return t

	case unionType:
		if r.p.exportVersion < iexportVersionGenerics {
			base.Fatalf("unexpected instantiation type")
		}
		nt := int(r.uint64())
		terms := make([]*types.Type, nt)
		tildes := make([]bool, nt)
		for i := range terms {
			tildes[i] = r.bool()
			terms[i] = r.typ()
		}
		return types.NewUnion(terms, tildes)
	}
}

func (r *importReader) kind() itag {
	return itag(r.uint64())
}

func (r *importReader) signature(recv *types.Field, tparams []*types.Field) *types.Type {
	params := r.paramList()
	results := r.paramList()
	if n := len(params); n > 0 {
		params[n-1].SetIsDDD(r.bool())
	}
	return types.NewSignature(r.currPkg, recv, tparams, params, results)
}

func (r *importReader) typeList() []*types.Type {
	n := r.uint64()
	if n == 0 {
		return nil
	}
	ts := make([]*types.Type, n)
	for i := range ts {
		ts[i] = r.typ()
		if ts[i].IsTypeParam() {
			ts[i].SetIndex(i)
		}
	}
	return ts
}

func (r *importReader) tparamList() []*types.Field {
	n := r.uint64()
	if n == 0 {
		return nil
	}
	fs := make([]*types.Field, n)
	for i := range fs {
		typ := r.typ()
		typ.SetIndex(i)
		fs[i] = types.NewField(typ.Pos(), typ.Sym(), typ)
	}
	return fs
}

func (r *importReader) paramList() []*types.Field {
	fs := make([]*types.Field, r.uint64())
	for i := range fs {
		fs[i] = r.param()
	}
	return fs
}

func (r *importReader) param() *types.Field {
	return types.NewField(r.pos(), r.localIdent(), r.typ())
}

func (r *importReader) bool() bool {
	return r.uint64() != 0
}

func (r *importReader) int64() int64 {
	n, err := binary.ReadVarint(r)
	if err != nil {
		base.Fatalf("readVarint: %v", err)
	}
	return n
}

func (r *importReader) uint64() uint64 {
	n, err := binary.ReadUvarint(r)
	if err != nil {
		base.Fatalf("readVarint: %v", err)
	}
	return n
}

func (r *importReader) byte() byte {
	x, err := r.ReadByte()
	if err != nil {
		base.Fatalf("declReader.ReadByte: %v", err)
	}
	return x
}

// Compiler-specific extensions.

func (r *importReader) constExt(n *ir.Name) {
	switch n.Type() {
	case types.UntypedFloat:
		n.SetVal(r.mprat(n.Val()))
	case types.UntypedComplex:
		v := n.Val()
		re := r.mprat(constant.Real(v))
		im := r.mprat(constant.Imag(v))
		n.SetVal(makeComplex(re, im))
	}
}

func (r *importReader) varExt(n *ir.Name) {
	r.linkname(n.Sym())
	r.symIdx(n.Sym())
}

func (r *importReader) funcExt(n *ir.Name) {
	r.linkname(n.Sym())
	r.symIdx(n.Sym())

	n.Func.ABI = obj.ABI(r.uint64())

	// Make sure //go:noinline pragma is imported (so stenciled functions have
	// same noinline status as the corresponding generic function.)
	n.Func.Pragma = ir.PragmaFlag(r.uint64())

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

	// Inline body.
	if u := r.uint64(); u > 0 {
		n.Func.Inl = &ir.Inline{
			Cost:            int32(u - 1),
			CanDelayResults: r.bool(),
		}
		n.Func.Endlineno = r.pos()
	}
}

func (r *importReader) methExt(m *types.Field) {
	if r.bool() {
		m.SetNointerface(true)
	}
	r.funcExt(m.Nname.(*ir.Name))
}

func (r *importReader) linkname(s *types.Sym) {
	s.Linkname = r.string()
}

func (r *importReader) symIdx(s *types.Sym) {
	lsym := s.Linksym()
	idx := int32(r.int64())
	if idx != -1 {
		if s.Linkname != "" {
			base.Fatalf("bad index for linknamed symbol: %v %d\n", lsym, idx)
		}
		lsym.SymIdx = idx
		lsym.Set(obj.AttrIndexed, true)
	}
}

func (r *importReader) typeExt(t *types.Type) {
	t.SetNotInHeap(r.bool())
	SetBaseTypeIndex(t, r.int64(), r.int64())
}

func SetBaseTypeIndex(t *types.Type, i, pi int64) {
	if t.Obj() == nil {
		base.Fatalf("SetBaseTypeIndex on non-defined type %v", t)
	}
	if i != -1 && pi != -1 {
		typeSymIdx[t] = [2]int64{i, pi}
	}
}

// Map imported type T to the index of type descriptor symbols of T and *T,
// so we can use index to reference the symbol.
// TODO(mdempsky): Store this information directly in the Type's Name.
var typeSymIdx = make(map[*types.Type][2]int64)

func BaseTypeIndex(t *types.Type) int64 {
	tbase := t
	if t.IsPtr() && t.Sym() == nil && t.Elem().Sym() != nil {
		tbase = t.Elem()
	}
	i, ok := typeSymIdx[tbase]
	if !ok {
		return -1
	}
	if t != tbase {
		return i[1]
	}
	return i[0]
}

func (r *importReader) doInline(fn *ir.Func) {
	if len(fn.Inl.Body) != 0 {
		base.Fatalf("%v already has inline body", fn)
	}

	//fmt.Printf("Importing %s\n", fn.Nname.Sym().Name)
	r.funcBody(fn)

	importlist = append(importlist, fn)

	if base.Flag.E > 0 && base.Flag.LowerM > 2 {
		if base.Flag.LowerM > 3 {
			fmt.Printf("inl body for %v %v: %+v\n", fn, fn.Type(), ir.Nodes(fn.Inl.Body))
		} else {
			fmt.Printf("inl body for %v %v: %v\n", fn, fn.Type(), ir.Nodes(fn.Inl.Body))
		}
	}
}

// ----------------------------------------------------------------------------
// Inlined function bodies

// Approach: Read nodes and use them to create/declare the same data structures
// as done originally by the (hidden) parser by closely following the parser's
// original code. In other words, "parsing" the import data (which happens to
// be encoded in binary rather textual form) is the best way at the moment to
// re-establish the syntax tree's invariants. At some future point we might be
// able to avoid this round-about way and create the rewritten nodes directly,
// possibly avoiding a lot of duplicate work (name resolution, type checking).
//
// Refined nodes (e.g., ODOTPTR as a refinement of OXDOT) are exported as their
// unrefined nodes (since this is what the importer uses). The respective case
// entries are unreachable in the importer.

func (r *importReader) funcBody(fn *ir.Func) {
	outerfn := r.curfn
	r.curfn = fn

	// Import local declarations.
	fn.Inl.Dcl = r.readFuncDcls(fn)

	// Import function body.
	body := r.stmtList()
	if body == nil {
		// Make sure empty body is not interpreted as
		// no inlineable body (see also parser.fnbody)
		// (not doing so can cause significant performance
		// degradation due to unnecessary calls to empty
		// functions).
		body = []ir.Node{}
	}
	if go117ExportTypes {
		ir.VisitList(body, func(n ir.Node) {
			n.SetTypecheck(1)
		})
	}
	fn.Inl.Body = body

	r.curfn = outerfn
	if base.Flag.W >= 3 {
		fmt.Printf("Imported for %v", fn)
		ir.DumpList("", fn.Inl.Body)
	}
}

func (r *importReader) readNames(fn *ir.Func) []*ir.Name {
	dcls := make([]*ir.Name, r.int64())
	for i := range dcls {
		n := ir.NewDeclNameAt(r.pos(), ir.ONAME, r.localIdent())
		n.Class = ir.PAUTO // overwritten below for parameters/results
		n.Curfn = fn
		n.SetType(r.typ())
		dcls[i] = n
	}
	r.allDcls = append(r.allDcls, dcls...)
	return dcls
}

func (r *importReader) readFuncDcls(fn *ir.Func) []*ir.Name {
	dcls := r.readNames(fn)

	// Fixup parameter classes and associate with their
	// signature's type fields.
	i := 0
	fix := func(f *types.Field, class ir.Class) {
		if class == ir.PPARAM && (f.Sym == nil || f.Sym.Name == "_") {
			return
		}
		n := dcls[i]
		n.Class = class
		f.Nname = n
		i++
	}

	typ := fn.Type()
	if recv := typ.Recv(); recv != nil {
		fix(recv, ir.PPARAM)
	}
	for _, f := range typ.Params().FieldSlice() {
		fix(f, ir.PPARAM)
	}
	for _, f := range typ.Results().FieldSlice() {
		fix(f, ir.PPARAMOUT)
	}
	return dcls
}

func (r *importReader) localName() *ir.Name {
	i := r.int64()
	if i == -1 {
		return ir.BlankNode.(*ir.Name)
	}
	if i < 0 {
		return r.allClosureVars[-i-2]
	}
	return r.allDcls[i]
}

func (r *importReader) stmtList() []ir.Node {
	var list []ir.Node
	for {
		n := r.node()
		if n == nil {
			break
		}
		// OBLOCK nodes are not written to the import data directly,
		// but the handling of ODCL calls liststmt, which creates one.
		// Inline them into the statement list.
		if n.Op() == ir.OBLOCK {
			n := n.(*ir.BlockStmt)
			list = append(list, n.List...)
			continue
		}
		if len(list) > 0 {
			// check for an optional label that can only immediately
			// precede a for/range/select/switch statement.
			if last := list[len(list)-1]; last.Op() == ir.OLABEL {
				label := last.(*ir.LabelStmt).Label
				switch n.Op() {
				case ir.OFOR:
					n.(*ir.ForStmt).Label = label
				case ir.ORANGE:
					n.(*ir.RangeStmt).Label = label
				case ir.OSELECT:
					n.(*ir.SelectStmt).Label = label
				case ir.OSWITCH:
					n.(*ir.SwitchStmt).Label = label
				}
			}
		}
		list = append(list, n)
	}
	return list
}

func (r *importReader) caseList(switchExpr ir.Node) []*ir.CaseClause {
	namedTypeSwitch := isNamedTypeSwitch(switchExpr)

	cases := make([]*ir.CaseClause, r.uint64())
	for i := range cases {
		cas := ir.NewCaseStmt(r.pos(), nil, nil)
		cas.List = r.stmtList()
		if namedTypeSwitch {
			cas.Var = r.localName()
			cas.Var.Defn = switchExpr
		}
		cas.Body = r.stmtList()
		cases[i] = cas
	}
	return cases
}

func (r *importReader) commList() []*ir.CommClause {
	cases := make([]*ir.CommClause, r.uint64())
	for i := range cases {
		pos := r.pos()
		defaultCase := r.bool()
		var comm ir.Node
		if !defaultCase {
			comm = r.node()
		}
		cases[i] = ir.NewCommStmt(pos, comm, r.stmtList())
	}
	return cases
}

func (r *importReader) exprList() []ir.Node {
	var list []ir.Node
	for {
		n := r.expr()
		if n == nil {
			break
		}
		list = append(list, n)
	}
	return list
}

func (r *importReader) expr() ir.Node {
	n := r.node()
	if n != nil && n.Op() == ir.OBLOCK {
		n := n.(*ir.BlockStmt)
		base.Fatalf("unexpected block node: %v", n)
	}
	return n
}

// TODO(gri) split into expr and stmt
func (r *importReader) node() ir.Node {
	op := r.op()
	switch op {
	// expressions
	// case OPAREN:
	// 	unreachable - unpacked by exporter

	case ir.ONIL:
		pos := r.pos()
		typ := r.typ()

		n := ir.NewNilExpr(pos)
		n.SetType(typ)
		return n

	case ir.OLITERAL:
		pos := r.pos()
		typ := r.typ()

		n := ir.NewBasicLit(pos, r.value(typ))
		n.SetType(typ)
		return n

	case ir.ONONAME:
		n := r.qualifiedIdent()
		if go117ExportTypes {
			n2 := Resolve(n)
			typ := r.typ()
			if n2.Type() == nil {
				n2.SetType(typ)
			}
			return n2
		}
		return n

	case ir.ONAME:
		isBuiltin := r.bool()
		if isBuiltin {
			pkg := types.BuiltinPkg
			if r.bool() {
				pkg = types.UnsafePkg
			}
			return pkg.Lookup(r.string()).Def.(*ir.Name)
		}
		return r.localName()

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

	case ir.OTYPE:
		return ir.TypeNode(r.typ())

	case ir.ODYNAMICTYPE:
		n := ir.NewDynamicType(r.pos(), r.expr())
		if r.bool() {
			n.ITab = r.expr()
		}
		n.SetType(r.typ())
		return n

	case ir.OTYPESW:
		pos := r.pos()
		var tag *ir.Ident
		if s := r.localIdent(); s != nil {
			tag = ir.NewIdent(pos, s)
		}
		return ir.NewTypeSwitchGuard(pos, tag, r.expr())

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

	case ir.OCLOSURE:
		//println("Importing CLOSURE")
		pos := r.pos()
		typ := r.signature(nil, nil)

		// All the remaining code below is similar to (*noder).funcLit(), but
		// with Dcls and ClosureVars lists already set up
		fn := ir.NewClosureFunc(pos, true)
		fn.Nname.SetType(typ)

		cvars := make([]*ir.Name, r.int64())
		for i := range cvars {
			cvars[i] = ir.CaptureName(r.pos(), fn, r.localName().Canonical())
			if go117ExportTypes && cvars[i].Defn == nil {
				base.Fatalf("bad import of closure variable")
			}
		}
		fn.ClosureVars = cvars
		r.allClosureVars = append(r.allClosureVars, cvars...)

		fn.Inl = &ir.Inline{}
		// Read in the Dcls and Body of the closure after temporarily
		// setting r.curfn to fn.
		r.funcBody(fn)
		fn.Dcl = fn.Inl.Dcl
		fn.Body = fn.Inl.Body
		if len(fn.Body) == 0 {
			// An empty closure must be represented as a single empty
			// block statement, else it will be dropped.
			fn.Body = []ir.Node{ir.NewBlockStmt(src.NoXPos, nil)}
		}
		fn.Inl = nil

		ir.FinishCaptureNames(pos, r.curfn, fn)

		clo := fn.OClosure
		if go117ExportTypes {
			clo.SetType(typ)
		}
		return clo

	case ir.OSTRUCTLIT:
		if go117ExportTypes {
			pos := r.pos()
			typ := r.typ()
			list := r.fieldList()
			n := ir.NewCompLitExpr(pos, ir.OSTRUCTLIT, nil, list)
			n.SetType(typ)
			return n
		}
		return ir.NewCompLitExpr(r.pos(), ir.OCOMPLIT, ir.TypeNode(r.typ()), r.fieldList())

	case ir.OCOMPLIT:
		pos := r.pos()
		t := r.typ()
		n := ir.NewCompLitExpr(pos, ir.OCOMPLIT, ir.TypeNode(t), r.exprList())
		n.SetType(t)
		return n

	case ir.OARRAYLIT, ir.OSLICELIT, ir.OMAPLIT:
		if !go117ExportTypes {
			// unreachable - mapped to OCOMPLIT by exporter
			goto error
		}
		pos := r.pos()
		typ := r.typ()
		list := r.exprList()
		n := ir.NewCompLitExpr(pos, op, ir.TypeNode(typ), list)
		n.SetType(typ)
		if op == ir.OSLICELIT {
			n.Len = int64(r.uint64())
		}
		return n

	case ir.OKEY:
		return ir.NewKeyExpr(r.pos(), r.expr(), r.expr())

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

	case ir.OXDOT, ir.ODOT, ir.ODOTPTR, ir.ODOTINTER, ir.ODOTMETH, ir.OMETHVALUE, ir.OMETHEXPR:
		// For !go117ExportTypes,  we should only see OXDOT.
		// For go117ExportTypes, we usually see all the other ops, but can see
		// OXDOT for generic functions.
		if op != ir.OXDOT && !go117ExportTypes {
			goto error
		}
		pos := r.pos()
		expr := r.expr()
		sel := r.exoticSelector()
		n := ir.NewSelectorExpr(pos, op, expr, sel)
		if go117ExportTypes {
			n.SetType(r.exoticType())
			switch op {
			case ir.OXDOT:
				hasSelection := r.bool()
				// We reconstruct n.Selection for method calls on
				// generic types and method calls due to type param
				// bounds.  Otherwise, n.Selection is nil.
				if hasSelection {
					n1 := ir.NewSelectorExpr(pos, op, expr, sel)
					AddImplicitDots(n1)
					var m *types.Field
					if n1.X.Type().IsTypeParam() {
						genType := n1.X.Type().Bound()
						m = Lookdot1(n1, sel, genType, genType.AllMethods(), 1)
					} else {
						genType := types.ReceiverBaseType(n1.X.Type())
						if genType.IsInstantiatedGeneric() {
							genType = genType.OrigSym().Def.Type()
						}
						m = Lookdot1(n1, sel, genType, genType.Methods(), 1)
					}
					assert(m != nil)
					n.Selection = m
				}
			case ir.ODOT, ir.ODOTPTR, ir.ODOTINTER:
				n.Selection = r.exoticField()
			case ir.OMETHEXPR:
				n = typecheckMethodExpr(n).(*ir.SelectorExpr)
			case ir.ODOTMETH, ir.OMETHVALUE:
				// These require a Lookup to link to the correct declaration.
				rcvrType := expr.Type()
				typ := n.Type()
				n.Selection = Lookdot(n, rcvrType, 1)
				if op == ir.OMETHVALUE {
					// Lookdot clobbers the opcode and type, undo that.
					n.SetOp(op)
					n.SetType(typ)
				}
			}
		}
		return n

	case ir.ODOTTYPE, ir.ODOTTYPE2:
		n := ir.NewTypeAssertExpr(r.pos(), r.expr(), nil)
		n.SetType(r.typ())
		if go117ExportTypes {
			n.SetOp(op)
		}
		return n

	case ir.ODYNAMICDOTTYPE, ir.ODYNAMICDOTTYPE2:
		n := ir.NewDynamicTypeAssertExpr(r.pos(), op, r.expr(), r.expr())
		n.SetType(r.typ())
		return n

	case ir.OINDEX, ir.OINDEXMAP:
		n := ir.NewIndexExpr(r.pos(), r.expr(), r.expr())
		if go117ExportTypes {
			n.SetOp(op)
			n.SetType(r.exoticType())
			if op == ir.OINDEXMAP {
				n.Assigned = r.bool()
			}
		}
		return n

	case ir.OSLICE, ir.OSLICESTR, ir.OSLICEARR, ir.OSLICE3, ir.OSLICE3ARR:
		pos, x := r.pos(), r.expr()
		low, high := r.exprsOrNil()
		var max ir.Node
		if op.IsSlice3() {
			max = r.expr()
		}
		n := ir.NewSliceExpr(pos, op, x, low, high, max)
		if go117ExportTypes {
			n.SetType(r.typ())
		}
		return n

	case ir.OCONV, ir.OCONVIFACE, ir.OCONVIDATA, ir.OCONVNOP, ir.OBYTES2STR, ir.ORUNES2STR, ir.OSTR2BYTES, ir.OSTR2RUNES, ir.ORUNESTR, ir.OSLICE2ARRPTR:
		if !go117ExportTypes && op != ir.OCONV {
			// 	unreachable - mapped to OCONV case by exporter
			goto error
		}
		return ir.NewConvExpr(r.pos(), op, r.typ(), r.expr())

	case ir.OCOPY, ir.OCOMPLEX, ir.OREAL, ir.OIMAG, ir.OAPPEND, ir.OCAP, ir.OCLOSE, ir.ODELETE, ir.OLEN, ir.OMAKE, ir.ONEW, ir.OPANIC, ir.ORECOVER, ir.OPRINT, ir.OPRINTN, ir.OUNSAFEADD, ir.OUNSAFESLICE:
		if go117ExportTypes {
			switch op {
			case ir.OCOPY, ir.OCOMPLEX, ir.OUNSAFEADD, ir.OUNSAFESLICE:
				n := ir.NewBinaryExpr(r.pos(), op, r.expr(), r.expr())
				n.SetType(r.typ())
				return n
			case ir.OREAL, ir.OIMAG, ir.OCAP, ir.OCLOSE, ir.OLEN, ir.ONEW, ir.OPANIC:
				n := ir.NewUnaryExpr(r.pos(), op, r.expr())
				if op != ir.OPANIC {
					n.SetType(r.typ())
				}
				return n
			case ir.OAPPEND, ir.ODELETE, ir.ORECOVER, ir.OPRINT, ir.OPRINTN:
				n := ir.NewCallExpr(r.pos(), op, nil, r.exprList())
				if op == ir.OAPPEND {
					n.IsDDD = r.bool()
				}
				if op == ir.OAPPEND || op == ir.ORECOVER {
					n.SetType(r.typ())
				}
				return n
			}
			// ir.OMAKE
			goto error
		}
		n := builtinCall(r.pos(), op)
		n.Args = r.exprList()
		if op == ir.OAPPEND {
			n.IsDDD = r.bool()
		}
		return n

	case ir.OCALL, ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER, ir.OGETG:
		pos := r.pos()
		init := r.stmtList()
		n := ir.NewCallExpr(pos, ir.OCALL, r.expr(), r.exprList())
		if go117ExportTypes {
			n.SetOp(op)
		}
		n.SetInit(init)
		n.IsDDD = r.bool()
		if go117ExportTypes {
			n.SetType(r.exoticType())
		}
		return n

	case ir.OMAKEMAP, ir.OMAKECHAN, ir.OMAKESLICE:
		if go117ExportTypes {
			pos := r.pos()
			typ := r.typ()
			list := r.exprList()
			var len_, cap_ ir.Node
			if len(list) > 0 {
				len_ = list[0]
			}
			if len(list) > 1 {
				cap_ = list[1]
			}
			n := ir.NewMakeExpr(pos, op, len_, cap_)
			n.SetType(typ)
			return n
		}
		n := builtinCall(r.pos(), ir.OMAKE)
		n.Args.Append(ir.TypeNode(r.typ()))
		n.Args.Append(r.exprList()...)
		return n

	case ir.OLINKSYMOFFSET:
		pos := r.pos()
		name := r.string()
		off := r.uint64()
		typ := r.typ()
		return ir.NewLinksymOffsetExpr(pos, Lookup(name).Linksym(), int64(off), typ)

	// unary expressions
	case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT, ir.ORECV, ir.OIDATA:
		n := ir.NewUnaryExpr(r.pos(), op, r.expr())
		if go117ExportTypes {
			n.SetType(r.typ())
		}
		return n

	case ir.OADDR, ir.OPTRLIT:
		n := NodAddrAt(r.pos(), r.expr())
		if go117ExportTypes {
			n.SetOp(op)
			n.SetType(r.typ())
		}
		return n

	case ir.ODEREF:
		n := ir.NewStarExpr(r.pos(), r.expr())
		if go117ExportTypes {
			n.SetType(r.typ())
		}
		return n

	// binary expressions
	case ir.OADD, ir.OAND, ir.OANDNOT, ir.ODIV, ir.OEQ, ir.OGE, ir.OGT, ir.OLE, ir.OLT,
		ir.OLSH, ir.OMOD, ir.OMUL, ir.ONE, ir.OOR, ir.ORSH, ir.OSUB, ir.OXOR, ir.OEFACE:
		n := ir.NewBinaryExpr(r.pos(), op, r.expr(), r.expr())
		if go117ExportTypes {
			n.SetType(r.typ())
		}
		return n

	case ir.OANDAND, ir.OOROR:
		n := ir.NewLogicalExpr(r.pos(), op, r.expr(), r.expr())
		if go117ExportTypes {
			n.SetType(r.typ())
		}
		return n

	case ir.OSEND:
		return ir.NewSendStmt(r.pos(), r.expr(), r.expr())

	case ir.OADDSTR:
		pos := r.pos()
		list := r.exprList()
		if go117ExportTypes {
			n := ir.NewAddStringExpr(pos, list)
			n.SetType(r.typ())
			return n
		}
		x := list[0]
		for _, y := range list[1:] {
			x = ir.NewBinaryExpr(pos, ir.OADD, x, y)
		}
		return x

	// --------------------------------------------------------------------
	// statements
	case ir.ODCL:
		var stmts ir.Nodes
		n := r.localName()
		stmts.Append(ir.NewDecl(n.Pos(), ir.ODCL, n))
		stmts.Append(ir.NewAssignStmt(n.Pos(), n, nil))
		return ir.NewBlockStmt(n.Pos(), stmts)

	// case OASWB:
	// 	unreachable - never exported

	case ir.OAS:
		pos := r.pos()
		init := r.stmtList()
		n := ir.NewAssignStmt(pos, r.expr(), r.expr())
		n.SetInit(init)
		n.Def = r.bool()
		return n

	case ir.OASOP:
		n := ir.NewAssignOpStmt(r.pos(), r.op(), r.expr(), nil)
		if !r.bool() {
			n.Y = ir.NewInt(1)
			n.IncDec = true
		} else {
			n.Y = r.expr()
		}
		return n

	case ir.OAS2, ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2RECV:
		if !go117ExportTypes && op != ir.OAS2 {
			// unreachable - mapped to case OAS2 by exporter
			goto error
		}
		pos := r.pos()
		init := r.stmtList()
		n := ir.NewAssignListStmt(pos, op, r.exprList(), r.exprList())
		n.SetInit(init)
		n.Def = r.bool()
		return n

	case ir.ORETURN:
		return ir.NewReturnStmt(r.pos(), r.exprList())

	// case ORETJMP:
	// 	unreachable - generated by compiler for trampolin routines (not exported)

	case ir.OGO, ir.ODEFER:
		return ir.NewGoDeferStmt(r.pos(), op, r.expr())

	case ir.OIF:
		pos, init := r.pos(), r.stmtList()
		n := ir.NewIfStmt(pos, r.expr(), r.stmtList(), r.stmtList())
		n.SetInit(init)
		return n

	case ir.OFOR:
		pos, init := r.pos(), r.stmtList()
		cond, post := r.exprsOrNil()
		n := ir.NewForStmt(pos, nil, cond, post, r.stmtList())
		n.SetInit(init)
		return n

	case ir.ORANGE:
		pos, init := r.pos(), r.stmtList()
		k, v := r.exprsOrNil()
		n := ir.NewRangeStmt(pos, k, v, r.expr(), r.stmtList())
		n.SetInit(init)
		return n

	case ir.OSELECT:
		pos := r.pos()
		init := r.stmtList()
		n := ir.NewSelectStmt(pos, r.commList())
		n.SetInit(init)
		return n

	case ir.OSWITCH:
		pos := r.pos()
		init := r.stmtList()
		x, _ := r.exprsOrNil()
		n := ir.NewSwitchStmt(pos, x, r.caseList(x))
		n.SetInit(init)
		return n

	// case OCASE:
	//	handled by caseList

	case ir.OFALL:
		return ir.NewBranchStmt(r.pos(), ir.OFALL, nil)

	// case OEMPTY:
	// 	unreachable - not emitted by exporter

	case ir.OBREAK, ir.OCONTINUE, ir.OGOTO:
		pos := r.pos()
		var sym *types.Sym
		if label := r.string(); label != "" {
			sym = Lookup(label)
		}
		return ir.NewBranchStmt(pos, op, sym)

	case ir.OLABEL:
		return ir.NewLabelStmt(r.pos(), Lookup(r.string()))

	case ir.OEND:
		return nil

	case ir.OFUNCINST:
		pos := r.pos()
		x := r.expr()
		ntargs := r.uint64()
		var targs []ir.Node
		if ntargs > 0 {
			targs = make([]ir.Node, ntargs)
			for i := range targs {
				targs[i] = ir.TypeNode(r.typ())
			}
		}
		n := ir.NewInstExpr(pos, ir.OFUNCINST, x, targs)
		if go117ExportTypes {
			n.SetType(r.typ())
		}
		return n

	case ir.OSELRECV2:
		pos := r.pos()
		init := r.stmtList()
		n := ir.NewAssignListStmt(pos, ir.OSELRECV2, r.exprList(), r.exprList())
		n.SetInit(init)
		n.Def = r.bool()
		return n

	default:
		base.Fatalf("cannot import %v (%d) node\n"+
			"\t==> please file an issue and assign to gri@", op, int(op))
		panic("unreachable") // satisfy compiler
	}
error:
	base.Fatalf("cannot import %v (%d) node\n"+
		"\t==> please file an issue and assign to khr@", op, int(op))
	panic("unreachable") // satisfy compiler
}

func (r *importReader) op() ir.Op {
	if debug && r.uint64() != magic {
		base.Fatalf("import stream has desynchronized")
	}
	return ir.Op(r.uint64())
}

func (r *importReader) fieldList() []ir.Node {
	list := make([]ir.Node, r.uint64())
	for i := range list {
		list[i] = ir.NewStructKeyExpr(r.pos(), r.exoticField(), r.expr())
	}
	return list
}

func (r *importReader) exprsOrNil() (a, b ir.Node) {
	ab := r.uint64()
	if ab&1 != 0 {
		a = r.expr()
	}
	if ab&2 != 0 {
		b = r.node()
	}
	return
}

func builtinCall(pos src.XPos, op ir.Op) *ir.CallExpr {
	if go117ExportTypes {
		// These should all be encoded as direct ops, not OCALL.
		base.Fatalf("builtinCall should not be invoked when types are included in import/export")
	}
	return ir.NewCallExpr(pos, ir.OCALL, ir.NewIdent(base.Pos, types.BuiltinPkg.Lookup(ir.OpNames[op])), nil)
}

// NewIncompleteNamedType returns a TFORW type t with name specified by sym, such
// that t.nod and sym.Def are set correctly. If there are any RParams for the type,
// they should be set soon after creating the TFORW type, before creating the
// underlying type. That ensures that the HasTParam and HasShape flags will be set
// properly, in case this type is part of some mutually recursive type.
func NewIncompleteNamedType(pos src.XPos, sym *types.Sym) *types.Type {
	name := ir.NewDeclNameAt(pos, ir.OTYPE, sym)
	forw := types.NewNamed(name)
	name.SetType(forw)
	sym.Def = name
	return forw
}

// Instantiate creates a new named type which is the instantiation of the base
// named generic type, with the specified type args.
func Instantiate(pos src.XPos, baseType *types.Type, targs []*types.Type) *types.Type {
	baseSym := baseType.Sym()
	if strings.Index(baseSym.Name, "[") >= 0 {
		base.Fatalf("arg to Instantiate is not a base generic type")
	}
	name := InstTypeName(baseSym.Name, targs)
	instSym := baseSym.Pkg.Lookup(name)
	if instSym.Def != nil {
		// May match existing type from previous import or
		// types2-to-types1 conversion.
		t := instSym.Def.Type()
		if t.Kind() != types.TFORW {
			return t
		}
		// Or, we have started creating this type in (*TSubster).Typ, but its
		// underlying type was not completed yet, so we need to add this type
		// to deferredInstStack, if not already there.
		found := false
		for _, t2 := range deferredInstStack {
			if t2 == t {
				found = true
				break
			}
		}
		if !found {
			deferredInstStack = append(deferredInstStack, t)
		}
		return t
	}

	t := NewIncompleteNamedType(baseType.Pos(), instSym)
	t.SetRParams(targs)
	t.SetOrigSym(baseSym)

	// baseType may still be TFORW or its methods may not be fully filled in
	// (since we are in the middle of importing it). So, delay call to
	// substInstType until we get back up to the top of the current top-most
	// type import.
	deferredInstStack = append(deferredInstStack, t)

	return t
}

var deferredInstStack []*types.Type
var deferInst int

// deferDoInst defers substitution on instantiated types until we are at the
// top-most defined type, so the base types are fully defined.
func deferDoInst() {
	deferInst++
}

func resumeDoInst() {
	if deferInst == 1 {
		for len(deferredInstStack) > 0 {
			t := deferredInstStack[0]
			deferredInstStack = deferredInstStack[1:]
			substInstType(t, t.OrigSym().Def.(*ir.Name).Type(), t.RParams())
		}
	}
	deferInst--
}

// doInst creates a new instantiation type (which will be added to
// deferredInstStack for completion later) for an incomplete type encountered
// during a type substitution for an instantiation. This is needed for
// instantiations of mutually recursive types.
func doInst(t *types.Type) *types.Type {
	assert(t.Kind() == types.TFORW)
	return Instantiate(t.Pos(), t.OrigSym().Def.(*ir.Name).Type(), t.RParams())
}

// substInstType completes the instantiation of a generic type by doing a
// substitution on the underlying type itself and any methods. t is the
// instantiation being created, baseType is the base generic type, and targs are
// the type arguments that baseType is being instantiated with.
func substInstType(t *types.Type, baseType *types.Type, targs []*types.Type) {
	assert(t.Kind() == types.TFORW)
	subst := Tsubster{
		Tparams:       baseType.RParams(),
		Targs:         targs,
		SubstForwFunc: doInst,
	}
	t.SetUnderlying(subst.Typ(baseType.Underlying()))

	newfields := make([]*types.Field, baseType.Methods().Len())
	for i, f := range baseType.Methods().Slice() {
		if !f.IsMethod() || types.IsInterfaceMethod(f.Type) {
			// Do a normal substitution if this is a non-method (which
			// means this must be an interface used as a constraint) or
			// an interface method.
			t2 := subst.Typ(f.Type)
			newfields[i] = types.NewField(f.Pos, f.Sym, t2)
			continue
		}
		recvType := f.Type.Recv().Type
		if recvType.IsPtr() {
			recvType = recvType.Elem()
		}
		// Substitute in the method using the type params used in the
		// method (not the type params in the definition of the generic type).
		msubst := Tsubster{
			Tparams:       recvType.RParams(),
			Targs:         targs,
			SubstForwFunc: doInst,
		}
		t2 := msubst.Typ(f.Type)
		oldsym := f.Nname.Sym()
		newsym := MakeFuncInstSym(oldsym, targs, true, true)
		var nname *ir.Name
		if newsym.Def != nil {
			nname = newsym.Def.(*ir.Name)
		} else {
			nname = ir.NewNameAt(f.Pos, newsym)
			nname.SetType(t2)
			ir.MarkFunc(nname)
			newsym.Def = nname
		}
		newfields[i] = types.NewField(f.Pos, f.Sym, t2)
		newfields[i].Nname = nname
	}
	t.Methods().Set(newfields)
	if !t.HasTParam() && !t.HasShape() && t.Kind() != types.TINTER && t.Methods().Len() > 0 {
		// Generate all the methods for a new fully-instantiated,
		// non-interface, non-shape type.
		NeedInstType(t)
	}
}
