// 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.stringAt(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.stringAt(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]
}

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) 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':
		var rparams []*types.Type
		if tag == 'U' {
			rparams = r.typeList()
		}

		// Types can be recursive. We need to setup a stub
		// declaration before recursing.
		n := importtype(pos, sym)
		t := n.Type()
		if tag == 'U' {
			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.string()
	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 = fakeRecvField()
		} 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(fakeRecvField(), 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 instType:
		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...)
		} else {
			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 {
			return types.BuiltinPkg.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.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:
		return ir.NewCompLitExpr(r.pos(), ir.OCOMPLIT, ir.TypeNode(r.typ()), r.exprList())

	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.ODOTMETH, ir.OMETHVALUE, ir.OMETHEXPR:
				// 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 || op == ir.OMETHEXPR {
					// 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.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.PtrInit() = 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:
		return ir.NewAssignStmt(r.pos(), r.expr(), r.expr())

	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
		}
		return ir.NewAssignListStmt(r.pos(), op, r.exprList(), r.exprList())

	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.PtrInit() = 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.PtrInit() = init
		return n

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

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

	case ir.OSWITCH:
		pos := r.pos()
		init := r.stmtList()
		x, _ := r.exprsOrNil()
		n := ir.NewSwitchStmt(pos, x, r.caseList(x))
		*n.PtrInit() = 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:
		return ir.NewAssignListStmt(r.pos(), ir.OSELRECV2, r.exprList(), r.exprList())

	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.
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, or from in-progress instantiation
		// in the current type import stack.
		return instSym.Def.Type()
	}

	t := NewIncompleteNamedType(baseType.Pos(), instSym)
	t.SetRParams(targs)
	t.OrigSym = 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 {
	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) {
	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)
		var nname *ir.Name
		if newsym.Def != nil {
			nname = newsym.Def.(*ir.Name)
		} else {
			nname = ir.NewNameAt(f.Pos, newsym)
			nname.SetType(t2)
			newsym.Def = nname
		}
		newfields[i] = types.NewField(f.Pos, f.Sym, t2)
		newfields[i].Nname = nname
	}
	t.Methods().Set(newfields)
}
