// Copyright 2021 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.

package noder

import (
	"fmt"
	"go/constant"
	"go/token"
	"go/version"
	"internal/buildcfg"
	"internal/pkgbits"
	"os"
	"slices"
	"strings"

	"cmd/compile/internal/base"
	"cmd/compile/internal/ir"
	"cmd/compile/internal/syntax"
	"cmd/compile/internal/types"
	"cmd/compile/internal/types2"
)

// This file implements the Unified IR package writer and defines the
// Unified IR export data format.
//
// Low-level coding details (e.g., byte-encoding of individual
// primitive values, or handling element bitstreams and
// cross-references) are handled by internal/pkgbits, so here we only
// concern ourselves with higher-level worries like mapping Go
// language constructs into elements.

// There are two central types in the writing process: the "writer"
// type handles writing out individual elements, while the "pkgWriter"
// type keeps track of which elements have already been created.
//
// For each sort of "thing" (e.g., position, package, object, type)
// that can be written into the export data, there are generally
// several methods that work together:
//
// - writer.thing handles writing out a *use* of a thing, which often
//   means writing a relocation to that thing's encoded index.
//
// - pkgWriter.thingIdx handles reserving an index for a thing, and
//   writing out any elements needed for the thing.
//
// - writer.doThing handles writing out the *definition* of a thing,
//   which in general is a mix of low-level coding primitives (e.g.,
//   ints and strings) or uses of other things.
//
// A design goal of Unified IR is to have a single, canonical writer
// implementation, but multiple reader implementations each tailored
// to their respective needs. For example, within cmd/compile's own
// backend, inlining is implemented largely by just re-running the
// function body reading code.

// TODO(mdempsky): Add an importer for Unified IR to the x/tools repo,
// and better document the file format boundary between public and
// private data.

type index = pkgbits.Index

func assert(p bool) { base.Assert(p) }

// A pkgWriter constructs Unified IR export data from the results of
// running the types2 type checker on a Go compilation unit.
type pkgWriter struct {
	pkgbits.PkgEncoder

	m                     posMap
	curpkg                *types2.Package
	info                  *types2.Info
	rangeFuncBodyClosures map[*syntax.FuncLit]bool // non-public information, e.g., which functions are closures range function bodies?

	// Indices for previously written syntax and types2 things.

	posBasesIdx map[*syntax.PosBase]index
	pkgsIdx     map[*types2.Package]index
	typsIdx     map[types2.Type]index
	objsIdx     map[types2.Object]index

	// Maps from types2.Objects back to their syntax.Decl.

	funDecls map[*types2.Func]*syntax.FuncDecl
	typDecls map[*types2.TypeName]typeDeclGen

	// linknames maps package-scope objects to their linker symbol name,
	// if specified by a //go:linkname or //go:linknamestd directive.
	linknames map[types2.Object]struct {
		remote string
		std    bool
	}

	// cgoPragmas accumulates any //go:cgo_* pragmas that need to be
	// passed through to cmd/link.
	cgoPragmas [][]string
}

// newPkgWriter returns an initialized pkgWriter for the specified
// package.
func newPkgWriter(m posMap, pkg *types2.Package, info *types2.Info, otherInfo map[*syntax.FuncLit]bool) *pkgWriter {
	return &pkgWriter{
		PkgEncoder: pkgbits.NewPkgEncoder(uirVersion, base.Debug.SyncFrames),

		m:                     m,
		curpkg:                pkg,
		info:                  info,
		rangeFuncBodyClosures: otherInfo,

		pkgsIdx: make(map[*types2.Package]index),
		objsIdx: make(map[types2.Object]index),
		typsIdx: make(map[types2.Type]index),

		posBasesIdx: make(map[*syntax.PosBase]index),

		funDecls: make(map[*types2.Func]*syntax.FuncDecl),
		typDecls: make(map[*types2.TypeName]typeDeclGen),

		linknames: make(map[types2.Object]struct {
			remote string
			std    bool
		}),
	}
}

// errorf reports a user error about thing p.
func (pw *pkgWriter) errorf(p poser, msg string, args ...any) {
	base.ErrorfAt(pw.m.pos(p), 0, msg, args...)
}

// fatalf reports an internal compiler error about thing p.
func (pw *pkgWriter) fatalf(p poser, msg string, args ...any) {
	base.FatalfAt(pw.m.pos(p), msg, args...)
}

// unexpected reports a fatal error about a thing of unexpected
// dynamic type.
func (pw *pkgWriter) unexpected(what string, p poser) {
	pw.fatalf(p, "unexpected %s: %v (%T)", what, p, p)
}

func (pw *pkgWriter) typeAndValue(x syntax.Expr) syntax.TypeAndValue {
	tv, ok := pw.maybeTypeAndValue(x)
	if !ok {
		pw.fatalf(x, "missing Types entry: %v", syntax.String(x))
	}
	return tv
}

func (pw *pkgWriter) maybeTypeAndValue(x syntax.Expr) (syntax.TypeAndValue, bool) {
	tv := x.GetTypeInfo()

	// If x is a generic function whose type arguments are inferred
	// from assignment context, then we need to find its inferred type
	// in Info.Instances instead.
	if name, ok := x.(*syntax.Name); ok {
		if inst, ok := pw.info.Instances[name]; ok {
			tv.Type = inst.Type
		}
	}

	return tv, tv.Type != nil
}

// typeOf returns the Type of the given value expression.
func (pw *pkgWriter) typeOf(expr syntax.Expr) types2.Type {
	tv := pw.typeAndValue(expr)
	if !tv.IsValue() {
		pw.fatalf(expr, "expected value: %v", syntax.String(expr))
	}
	return tv.Type
}

// A writer provides APIs for writing out an individual element.
type writer struct {
	p *pkgWriter

	*pkgbits.Encoder

	// sig holds the signature for the current function body, if any.
	sig *types2.Signature

	// TODO(mdempsky): We should be able to prune localsIdx whenever a
	// scope closes, and then maybe we can just use the same map for
	// storing the TypeParams too (as their TypeName instead).

	// localsIdx tracks any local variables declared within this
	// function body. It's unused for writing out non-body things.
	localsIdx map[*types2.Var]int

	// closureVars tracks any free variables that are referenced by this
	// function body. It's unused for writing out non-body things.
	closureVars    []posVar
	closureVarsIdx map[*types2.Var]int // index of previously seen free variables

	dict *writerDict

	// derived tracks whether the type being written out references any
	// type parameters. It's unused for writing non-type things.
	derived bool
}

// A writerDict tracks types and objects that are used by a declaration.
type writerDict struct {
	// implicits contains type parameters from enclosing declarations.
	implicits []*types2.TypeParam
	// receivers contains receiver type parameters of the declaration.
	receivers []*types2.TypeParam

	// derived is a slice of type indices for computing derived types
	// (i.e., types that depend on the declaration's type parameters).
	derived []derivedInfo

	// derivedIdx maps a Type to its corresponding index within the
	// derived slice, if present.
	derivedIdx map[types2.Type]index

	// These slices correspond to entries in the runtime dictionary.
	typeParamMethodExprs []writerMethodExprInfo
	subdicts             []objInfo
	rtypes               []typeInfo
	itabs                []itabInfo
}

type itabInfo struct {
	typ   typeInfo
	iface typeInfo
}

// typeParamIndex returns the index of the given type parameter within
// the dictionary. This may differ from typ.Index() when there are
// implicit or receiver type parameters.
func (dict *writerDict) typeParamIndex(typ *types2.TypeParam) int {
	for idx, implicit := range dict.implicits {
		if implicit == typ {
			return idx
		}
	}

	for idx, receiver := range dict.receivers {
		if receiver == typ {
			return len(dict.implicits) + idx
		}
	}

	return len(dict.implicits) + len(dict.receivers) + typ.Index()
}

// A derivedInfo represents a reference to an encoded generic Go type.
type derivedInfo struct {
	idx index
}

// A typeInfo represents a reference to an encoded Go type.
//
// If derived is true, then the typeInfo represents a generic Go type
// that contains type parameters. In this case, idx is an index into
// the readerDict.derived{,Types} arrays.
//
// Otherwise, the typeInfo represents a non-generic Go type, and idx
// is an index into the reader.typs array instead.
type typeInfo struct {
	idx     index
	derived bool
}

// An objInfo represents a reference to an encoded, instantiated (if
// applicable) Go object.
type objInfo struct {
	idx       index      // index for the generic function declaration
	explicits []typeInfo // info for the type arguments
}

// A selectorInfo represents a reference to an encoded field or method
// name (i.e., objects that can only be accessed using selector
// expressions).
type selectorInfo struct {
	pkgIdx  index
	nameIdx index
}

// anyDerived reports whether any of info's explicit type arguments
// are derived types.
func (info objInfo) anyDerived() bool {
	for _, explicit := range info.explicits {
		if explicit.derived {
			return true
		}
	}
	return false
}

// equals reports whether info and other represent the same Go object
// (i.e., same base object and identical type arguments, if any).
func (info objInfo) equals(other objInfo) bool {
	if info.idx != other.idx {
		return false
	}
	assert(len(info.explicits) == len(other.explicits))
	for i, targ := range info.explicits {
		if targ != other.explicits[i] {
			return false
		}
	}
	return true
}

type writerMethodExprInfo struct {
	typeParamIdx int
	methodInfo   selectorInfo
}

// typeParamMethodExprIdx returns the index where the given encoded
// method expression function pointer appears within this dictionary's
// type parameters method expressions section, adding it if necessary.
func (dict *writerDict) typeParamMethodExprIdx(typeParamIdx int, methodInfo selectorInfo) int {
	newInfo := writerMethodExprInfo{typeParamIdx, methodInfo}

	for idx, oldInfo := range dict.typeParamMethodExprs {
		if oldInfo == newInfo {
			return idx
		}
	}

	idx := len(dict.typeParamMethodExprs)
	dict.typeParamMethodExprs = append(dict.typeParamMethodExprs, newInfo)
	return idx
}

// subdictIdx returns the index where the given encoded object's
// runtime dictionary appears within this dictionary's subdictionary
// section, adding it if necessary.
func (dict *writerDict) subdictIdx(newInfo objInfo) int {
	for idx, oldInfo := range dict.subdicts {
		if oldInfo.equals(newInfo) {
			return idx
		}
	}

	idx := len(dict.subdicts)
	dict.subdicts = append(dict.subdicts, newInfo)
	return idx
}

// rtypeIdx returns the index where the given encoded type's
// *runtime._type value appears within this dictionary's rtypes
// section, adding it if necessary.
func (dict *writerDict) rtypeIdx(newInfo typeInfo) int {
	for idx, oldInfo := range dict.rtypes {
		if oldInfo == newInfo {
			return idx
		}
	}

	idx := len(dict.rtypes)
	dict.rtypes = append(dict.rtypes, newInfo)
	return idx
}

// itabIdx returns the index where the given encoded type pair's
// *runtime.itab value appears within this dictionary's itabs section,
// adding it if necessary.
func (dict *writerDict) itabIdx(typInfo, ifaceInfo typeInfo) int {
	newInfo := itabInfo{typInfo, ifaceInfo}

	for idx, oldInfo := range dict.itabs {
		if oldInfo == newInfo {
			return idx
		}
	}

	idx := len(dict.itabs)
	dict.itabs = append(dict.itabs, newInfo)
	return idx
}

func (pw *pkgWriter) newWriter(k pkgbits.SectionKind, marker pkgbits.SyncMarker) *writer {
	return &writer{
		Encoder: pw.NewEncoder(k, marker),
		p:       pw,
	}
}

// @@@ Positions

// pos writes the position of p into the element bitstream.
func (w *writer) pos(p poser) {
	w.Sync(pkgbits.SyncPos)
	pos := p.Pos()

	// TODO(mdempsky): Track down the remaining cases here and fix them.
	if !w.Bool(pos.IsKnown()) {
		return
	}

	// TODO(mdempsky): Delta encoding.
	w.posBase(pos.Base())
	w.Uint(pos.Line())
	w.Uint(pos.Col())
}

// posBase writes a reference to the given PosBase into the element
// bitstream.
func (w *writer) posBase(b *syntax.PosBase) {
	w.Reloc(pkgbits.SectionPosBase, w.p.posBaseIdx(b))
}

// posBaseIdx returns the index for the given PosBase.
func (pw *pkgWriter) posBaseIdx(b *syntax.PosBase) index {
	if idx, ok := pw.posBasesIdx[b]; ok {
		return idx
	}

	w := pw.newWriter(pkgbits.SectionPosBase, pkgbits.SyncPosBase)
	w.p.posBasesIdx[b] = w.Idx

	w.String(trimFilename(b))

	if !w.Bool(b.IsFileBase()) {
		w.pos(b)
		w.Uint(b.Line())
		w.Uint(b.Col())
	}

	return w.Flush()
}

// @@@ Packages

// pkg writes a use of the given Package into the element bitstream.
func (w *writer) pkg(pkg *types2.Package) {
	w.pkgRef(w.p.pkgIdx(pkg))
}

func (w *writer) pkgRef(idx index) {
	w.Sync(pkgbits.SyncPkg)
	w.Reloc(pkgbits.SectionPkg, idx)
}

// pkgIdx returns the index for the given package, adding it to the
// package export data if needed.
func (pw *pkgWriter) pkgIdx(pkg *types2.Package) index {
	if idx, ok := pw.pkgsIdx[pkg]; ok {
		return idx
	}

	w := pw.newWriter(pkgbits.SectionPkg, pkgbits.SyncPkgDef)
	pw.pkgsIdx[pkg] = w.Idx

	// The universe and package unsafe need to be handled specially by
	// importers anyway, so we serialize them using just their package
	// path. This ensures that readers don't confuse them for
	// user-defined packages.
	switch pkg {
	case nil: // universe
		w.String("builtin") // same package path used by godoc
	case types2.Unsafe:
		w.String("unsafe")
	default:
		// TODO(mdempsky): Write out pkg.Path() for curpkg too.
		var path string
		if pkg != w.p.curpkg {
			path = pkg.Path()
		}
		base.Assertf(path != "builtin" && path != "unsafe", "unexpected path for user-defined package: %q", path)
		w.String(path)
		w.String(pkg.Name())

		w.Len(len(pkg.Imports()))
		for _, imp := range pkg.Imports() {
			w.pkg(imp)
		}
	}

	return w.Flush()
}

// @@@ Types

var (
	anyTypeName        = types2.Universe.Lookup("any").(*types2.TypeName)
	comparableTypeName = types2.Universe.Lookup("comparable").(*types2.TypeName)
	runeTypeName       = types2.Universe.Lookup("rune").(*types2.TypeName)
)

// typ writes a use of the given type into the bitstream.
func (w *writer) typ(typ types2.Type) {
	w.typInfo(w.p.typIdx(typ, w.dict))
}

// typInfo writes a use of the given type (specified as a typeInfo
// instead) into the bitstream.
func (w *writer) typInfo(info typeInfo) {
	w.Sync(pkgbits.SyncType)
	if w.Bool(info.derived) {
		w.Len(int(info.idx))
		w.derived = true
	} else {
		w.Reloc(pkgbits.SectionType, info.idx)
	}
}

// typIdx returns the index where the export data description of type
// can be read back in. If no such index exists yet, it's created.
//
// typIdx also reports whether typ is a derived type; that is, whether
// its identity depends on type parameters.
func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo {
	// Strip non-global aliases, because they only appear in inline
	// bodies anyway. Otherwise, they can cause types.Sym collisions
	// (e.g., "main.C" for both of the local type aliases in
	// test/fixedbugs/issue50190.go).
	for {
		if alias, ok := typ.(*types2.Alias); ok && !isGlobal(alias.Obj()) {
			typ = alias.Rhs()
		} else {
			break
		}
	}

	if idx, ok := pw.typsIdx[typ]; ok {
		return typeInfo{idx: idx, derived: false}
	}
	if dict != nil {
		if idx, ok := dict.derivedIdx[typ]; ok {
			return typeInfo{idx: idx, derived: true}
		}
	}

	w := pw.newWriter(pkgbits.SectionType, pkgbits.SyncTypeIdx)
	w.dict = dict

	switch typ := typ.(type) {
	default:
		base.Fatalf("unexpected type: %v (%T)", typ, typ)

	case *types2.Basic:
		switch kind := typ.Kind(); {
		case kind == types2.Invalid:
			base.Fatalf("unexpected types2.Invalid")

		case types2.Typ[kind] == typ:
			w.Code(pkgbits.TypeBasic)
			w.Len(int(kind))

		default:
			// Handle "byte" and "rune" as references to their TypeNames.
			obj := types2.Universe.Lookup(typ.Name()).(*types2.TypeName)
			assert(obj.Type() == typ)

			w.Code(pkgbits.TypeNamed)
			w.namedType(obj, nil)
		}

	case *types2.Named:
		w.Code(pkgbits.TypeNamed)
		w.namedType(splitNamed(typ))

	case *types2.Alias:
		w.Code(pkgbits.TypeNamed)
		w.namedType(splitAlias(typ))

	case *types2.TypeParam:
		w.derived = true
		w.Code(pkgbits.TypeTypeParam)
		w.Len(w.dict.typeParamIndex(typ))

	case *types2.Array:
		w.Code(pkgbits.TypeArray)
		w.Uint64(uint64(typ.Len()))
		w.typ(typ.Elem())

	case *types2.Chan:
		w.Code(pkgbits.TypeChan)
		w.Len(int(typ.Dir()))
		w.typ(typ.Elem())

	case *types2.Map:
		w.Code(pkgbits.TypeMap)
		w.typ(typ.Key())
		w.typ(typ.Elem())

	case *types2.Pointer:
		w.Code(pkgbits.TypePointer)
		w.typ(typ.Elem())

	case *types2.Signature:
		base.Assertf(typ.TypeParams() == nil, "unexpected type params: %v", typ)
		w.Code(pkgbits.TypeSignature)
		w.signature(typ)

	case *types2.Slice:
		w.Code(pkgbits.TypeSlice)
		w.typ(typ.Elem())

	case *types2.Struct:
		w.Code(pkgbits.TypeStruct)
		w.structType(typ)

	case *types2.Interface:
		// Handle "any" as reference to its TypeName.
		// The underlying "any" interface is canonical, so this logic handles both
		// GODEBUG=gotypesalias=1 (when any is represented as a types2.Alias), and
		// gotypesalias=0.
		if types2.Unalias(typ) == types2.Unalias(anyTypeName.Type()) {
			w.Code(pkgbits.TypeNamed)
			w.obj(anyTypeName, nil)
			break
		}

		w.Code(pkgbits.TypeInterface)
		w.interfaceType(typ)

	case *types2.Union:
		w.Code(pkgbits.TypeUnion)
		w.unionType(typ)
	}

	if w.derived {
		idx := index(len(dict.derived))
		dict.derived = append(dict.derived, derivedInfo{idx: w.Flush()})
		dict.derivedIdx[typ] = idx
		return typeInfo{idx: idx, derived: true}
	}

	pw.typsIdx[typ] = w.Idx
	return typeInfo{idx: w.Flush(), derived: false}
}

// namedType writes a use of the given named type into the bitstream.
func (w *writer) namedType(obj *types2.TypeName, targs []types2.Type) {
	// Named types that are declared within a generic function (and
	// thus have implicit type parameters) are always derived types.
	if w.p.hasImplicitTypeParams(obj) {
		w.derived = true
	}

	w.obj(obj, targs)
}

func (w *writer) structType(typ *types2.Struct) {
	w.Len(typ.NumFields())
	for i := 0; i < typ.NumFields(); i++ {
		f := typ.Field(i)
		w.pos(f)
		w.selector(f)
		w.typ(f.Type())
		w.String(typ.Tag(i))
		w.Bool(f.Embedded())
	}
}

func (w *writer) unionType(typ *types2.Union) {
	w.Len(typ.Len())
	for i := 0; i < typ.Len(); i++ {
		t := typ.Term(i)
		w.Bool(t.Tilde())
		w.typ(t.Type())
	}
}

func (w *writer) interfaceType(typ *types2.Interface) {
	// If typ has no embedded types but it's not a basic interface, then
	// the natural description we write out below will fail to
	// reconstruct it.
	if typ.NumEmbeddeds() == 0 && !typ.IsMethodSet() {
		// Currently, this can only happen for the underlying Interface of
		// "comparable", which is needed to handle type declarations like
		// "type C comparable".
		assert(typ == comparableTypeName.Type().(*types2.Named).Underlying())

		// Export as "interface{ comparable }".
		w.Len(0)                         // NumExplicitMethods
		w.Len(1)                         // NumEmbeddeds
		w.Bool(false)                    // IsImplicit
		w.typ(comparableTypeName.Type()) // EmbeddedType(0)
		return
	}

	w.Len(typ.NumExplicitMethods())
	w.Len(typ.NumEmbeddeds())

	if typ.NumExplicitMethods() == 0 && typ.NumEmbeddeds() == 1 {
		w.Bool(typ.IsImplicit())
	} else {
		// Implicit interfaces always have 0 explicit methods and 1
		// embedded type, so we skip writing out the implicit flag
		// otherwise as a space optimization.
		assert(!typ.IsImplicit())
	}

	for i := 0; i < typ.NumExplicitMethods(); i++ {
		m := typ.ExplicitMethod(i)
		sig := m.Type().(*types2.Signature)
		assert(sig.TypeParams() == nil)

		w.pos(m)
		w.selector(m)
		w.signature(sig)
	}

	for i := 0; i < typ.NumEmbeddeds(); i++ {
		w.typ(typ.EmbeddedType(i))
	}
}

func (w *writer) signature(sig *types2.Signature) {
	w.Sync(pkgbits.SyncSignature)
	w.params(sig.Params())
	w.params(sig.Results())
	w.Bool(sig.Variadic())
}

func (w *writer) params(typ *types2.Tuple) {
	w.Sync(pkgbits.SyncParams)
	w.Len(typ.Len())
	for i := 0; i < typ.Len(); i++ {
		w.param(typ.At(i))
	}
}

func (w *writer) param(param *types2.Var) {
	w.Sync(pkgbits.SyncParam)
	w.pos(param)
	w.localIdent(param)
	w.typ(param.Type())
}

// @@@ Objects

// obj writes a use of the given object into the bitstream.
//
// If obj is a generic object, then explicits are the explicit type
// arguments used to instantiate it (i.e., used to substitute the
// object's own declared type parameters).
func (w *writer) obj(obj types2.Object, explicits []types2.Type) {
	w.objInfo(w.p.objInstIdx(obj, explicits, w.dict))
}

// objInfo writes a use of the given encoded object into the
// bitstream.
func (w *writer) objInfo(info objInfo) {
	w.Sync(pkgbits.SyncObject)
	if w.Version().Has(pkgbits.DerivedFuncInstance) {
		w.Bool(false)
	}
	w.Reloc(pkgbits.SectionObj, info.idx)

	w.Len(len(info.explicits))
	for _, info := range info.explicits {
		w.typInfo(info)
	}
}

// objInstIdx returns the indices for an object and a corresponding
// list of type arguments used to instantiate it, adding them to the
// export data as needed.
func (pw *pkgWriter) objInstIdx(obj types2.Object, explicits []types2.Type, dict *writerDict) objInfo {
	explicitInfos := make([]typeInfo, len(explicits))
	for i := range explicitInfos {
		explicitInfos[i] = pw.typIdx(explicits[i], dict)
	}
	return objInfo{idx: pw.objIdx(obj), explicits: explicitInfos}
}

// objIdx returns the index for the given Object, adding it to the
// export data as needed.
func (pw *pkgWriter) objIdx(obj types2.Object) index {
	// TODO(mdempsky): Validate that obj is a global object (or a local
	// defined type, which we hoist to global scope anyway).

	if idx, ok := pw.objsIdx[obj]; ok {
		return idx
	}

	dict := &writerDict{
		derivedIdx: make(map[types2.Type]index),
	}

	if isDefinedType(obj) && obj.Pkg() == pw.curpkg {
		decl, ok := pw.typDecls[obj.(*types2.TypeName)]
		assert(ok)
		dict.implicits = decl.implicits
	}

	if isGenericMethod(obj.Type()) {
		dict.receivers = asTypeParamSlice(obj.Type().(*types2.Signature).RecvTypeParams())
	}

	// We encode objects into 4 elements across different sections, all
	// sharing the same index:
	//
	// - RelocName has just the object's qualified name (i.e.,
	//   Object.Pkg and Object.Name) and the CodeObj indicating what
	//   specific type of Object it is (Var, Func, etc).
	//
	// - RelocObj has the remaining public details about the object,
	//   relevant to go/types importers.
	//
	// - RelocObjExt has additional private details about the object,
	//   which are only relevant to cmd/compile itself. This is
	//   separated from RelocObj so that go/types importers are
	//   unaffected by internal compiler changes.
	//
	// - RelocObjDict has public details about the object's type
	//   parameters and derived type's used by the object. This is
	//   separated to facilitate the eventual introduction of
	//   shape-based stenciling.
	//
	// TODO(mdempsky): Re-evaluate whether RelocName still makes sense
	// to keep separate from RelocObj.

	w := pw.newWriter(pkgbits.SectionObj, pkgbits.SyncObject1)
	wext := pw.newWriter(pkgbits.SectionObjExt, pkgbits.SyncObject1)
	wname := pw.newWriter(pkgbits.SectionName, pkgbits.SyncObject1)
	wdict := pw.newWriter(pkgbits.SectionObjDict, pkgbits.SyncObject1)

	pw.objsIdx[obj] = w.Idx // break cycles
	assert(wext.Idx == w.Idx)
	assert(wname.Idx == w.Idx)
	assert(wdict.Idx == w.Idx)

	w.dict = dict
	wext.dict = dict

	code := w.doObj(wext, obj)
	w.Flush()
	wext.Flush()

	wname.qualifiedIdent(obj)
	wname.Code(code)
	wname.Flush()

	wdict.objDict(obj, w.dict)
	wdict.Flush()

	return w.Idx
}

// doObj writes the RelocObj definition for obj to w, and the
// RelocObjExt definition to wext.
func (w *writer) doObj(wext *writer, obj types2.Object) pkgbits.CodeObj {
	if obj.Pkg() != w.p.curpkg {
		return pkgbits.ObjStub
	}

	switch obj := obj.(type) {
	default:
		w.p.unexpected("object", obj)
		panic("unreachable")

	case *types2.Const:
		w.pos(obj)
		w.typ(obj.Type())
		w.Value(obj.Val())
		return pkgbits.ObjConst

	case *types2.Func:
		decl, ok := w.p.funDecls[obj]
		assert(ok)
		sig := obj.Type().(*types2.Signature)

		w.pos(obj)
		if isGenericMethod(sig) {
			// otherwise the reader won't know to expect the flag
			assert(w.Version().Has(pkgbits.GenericMethods))
			w.Bool(true) // generic method

			w.selector(obj)
			w.typeParamNames(sig.RecvTypeParams())
			w.param(sig.Recv())
		} else {
			if w.Version().Has(pkgbits.GenericMethods) {
				w.Bool(false) // function
			}
		}
		w.typeParamNames(sig.TypeParams())
		w.signature(sig)
		w.pos(decl)
		wext.funcExt(obj)
		return pkgbits.ObjFunc

	case *types2.TypeName:
		if obj.IsAlias() {
			w.pos(obj)
			rhs := obj.Type()
			var tparams *types2.TypeParamList
			if alias, ok := rhs.(*types2.Alias); ok { // materialized alias
				assert(alias.TypeArgs() == nil)
				tparams = alias.TypeParams()
				rhs = alias.Rhs()
			}
			if w.Version().Has(pkgbits.AliasTypeParamNames) {
				w.typeParamNames(tparams)
			}
			assert(w.Version().Has(pkgbits.AliasTypeParamNames) || tparams.Len() == 0)
			w.typ(rhs)
			return pkgbits.ObjAlias
		}

		named := obj.Type().(*types2.Named)
		assert(named.TypeArgs() == nil)

		w.pos(obj)
		w.typeParamNames(named.TypeParams())
		wext.typeExt(obj)
		w.typ(named.Underlying())

		// separate generic and non-generic methods
		var methods, gmethods []*types2.Func
		for i := range named.NumMethods() {
			m := named.Method(i)
			if isGenericMethod(m.Type()) {
				gmethods = append(gmethods, m)
			} else {
				methods = append(methods, m)
			}
		}
		// encode non-generic methods inline
		w.Len(len(methods))
		for _, m := range methods {
			w.method(wext, m)
		}
		// encode a pointer to each generic method
		if w.Version().Has(pkgbits.GenericMethods) {
			w.Len(len(gmethods))
			for _, m := range gmethods {
				w.Reloc(pkgbits.SectionObj, w.p.objIdx(m))
			}
		}

		return pkgbits.ObjType

	case *types2.Var:
		w.pos(obj)
		w.typ(obj.Type())
		wext.varExt(obj)
		return pkgbits.ObjVar
	}
}

// objDict writes the dictionary needed for reading the given object.
func (w *writer) objDict(obj types2.Object, dict *writerDict) {
	// TODO(mdempsky): Split objDict into multiple entries? reader.go
	// doesn't care about the type parameter bounds, and reader2.go
	// doesn't care about referenced functions.

	w.dict = dict // TODO(mdempsky): This is a bit sketchy.
	w.Len(len(dict.implicits))

	rtparams := objRecvTypeParams(obj)
	tparams := objTypeParams(obj)

	if w.Version().Has(pkgbits.GenericMethods) {
		w.Len(len(rtparams))
	} else {
		assert(len(rtparams) == 0)
	}
	w.Len(len(tparams))

	for _, rtparam := range rtparams {
		w.typ(rtparam.Constraint())
	}
	for _, tparam := range tparams {
		w.typ(tparam.Constraint())
	}

	nderived := len(dict.derived)
	w.Len(nderived)
	for _, typ := range dict.derived {
		w.Reloc(pkgbits.SectionType, typ.idx)
		if w.Version().Has(pkgbits.DerivedInfoNeeded) {
			w.Bool(false)
		}
	}

	// Write runtime dictionary information.
	//
	// N.B., the go/types importer reads up to the section, but doesn't
	// read any further, so it's safe to change. (See TODO above.)

	// For each type parameter, write out whether the constraint is a
	// basic interface. This is used to determine how aggressively we
	// can shape corresponding type arguments.
	//
	// This is somewhat redundant with writing out the full type
	// parameter constraints above, but the compiler currently skips
	// over those. Also, we don't care about the *declared* constraints,
	// but how the type parameters are actually *used*. E.g., if a type
	// parameter is constrained to `int | uint` but then never used in
	// arithmetic/conversions/etc, we could shape those together.
	for _, implicit := range dict.implicits {
		w.Bool(implicit.Underlying().(*types2.Interface).IsMethodSet())
	}
	for _, rtparam := range rtparams {
		w.Bool(rtparam.Underlying().(*types2.Interface).IsMethodSet())
	}
	for _, tparam := range tparams {
		w.Bool(tparam.Underlying().(*types2.Interface).IsMethodSet())
	}

	w.Len(len(dict.typeParamMethodExprs))
	for _, info := range dict.typeParamMethodExprs {
		w.Len(info.typeParamIdx)
		w.selectorInfo(info.methodInfo)
	}

	w.Len(len(dict.subdicts))
	for _, info := range dict.subdicts {
		w.objInfo(info)
	}

	w.Len(len(dict.rtypes))
	for _, info := range dict.rtypes {
		w.typInfo(info)
	}

	w.Len(len(dict.itabs))
	for _, info := range dict.itabs {
		w.typInfo(info.typ)
		w.typInfo(info.iface)
	}

	assert(len(dict.derived) == nderived)
}

func (w *writer) typeParamNames(tparams *types2.TypeParamList) {
	w.Sync(pkgbits.SyncTypeParamNames)

	ntparams := tparams.Len()
	for i := 0; i < ntparams; i++ {
		tparam := tparams.At(i).Obj()
		w.pos(tparam)
		w.localIdent(tparam)
	}
}

func (w *writer) method(wext *writer, meth *types2.Func) {
	decl, ok := w.p.funDecls[meth]
	assert(ok)
	sig := meth.Type().(*types2.Signature)

	w.Sync(pkgbits.SyncMethod)
	w.pos(meth)
	w.selector(meth)
	w.typeParamNames(sig.RecvTypeParams())
	w.param(sig.Recv())
	w.signature(sig)

	w.pos(decl) // XXX: Hack to workaround linker limitations.
	wext.funcExt(meth)
}

// qualifiedIdent writes out the name of an object typically declared at package
// scope. It's also used to refer to generic methods and locally defined types.
func (w *writer) qualifiedIdent(obj types2.Object) {
	w.Sync(pkgbits.SyncSym)

	name := obj.Name()
	if isDefinedType(obj) && obj.Pkg() == w.p.curpkg {
		decl, ok := w.p.typDecls[obj.(*types2.TypeName)]
		assert(ok)
		if decl.gen != 0 {
			// For local defined types, we embed a scope-disambiguation
			// number directly into their name. types.SplitVargenSuffix then
			// knows to look for this.
			//
			// TODO(mdempsky): Find a better solution; this is terrible.
			name = fmt.Sprintf("%s·%v", name, decl.gen)
		}
	}

	// Generic methods are promoted to objects and thus need qualified identifiers.
	// They must be contextualized by their defining type.
	if isGenericMethod(obj.Type()) {
		recv := obj.Type().(*types2.Signature).Recv().Type()
		fstr := "%s.%s"
		if _, ok := recv.(*types2.Pointer); ok {
			fstr = "(*%s).%s"
		}
		name = fmt.Sprintf(fstr, types2.Unalias(deref2(recv)).(*types2.Named).Obj().Name(), name)
	}

	w.pkg(obj.Pkg())
	w.String(name)
}

// TODO(mdempsky): We should be able to omit pkg from both localIdent
// and selector, because they should always be known from context.
// However, past frustrations with this optimization in iexport make
// me a little nervous to try it again.

// localIdent writes the name of a locally declared object (i.e.,
// objects that can only be accessed by non-qualified name, within the
// context of a particular function).
func (w *writer) localIdent(obj types2.Object) {
	assert(!isGlobal(obj))
	w.Sync(pkgbits.SyncLocalIdent)
	w.pkg(obj.Pkg())
	w.String(obj.Name())
}

// selector writes the name of a field or method (i.e., objects that
// can only be accessed using selector expressions).
func (w *writer) selector(obj types2.Object) {
	w.selectorInfo(w.p.selectorIdx(obj))
}

func (w *writer) selectorInfo(info selectorInfo) {
	w.Sync(pkgbits.SyncSelector)
	w.pkgRef(info.pkgIdx)
	w.StringRef(info.nameIdx)
}

func (pw *pkgWriter) selectorIdx(obj types2.Object) selectorInfo {
	pkgIdx := pw.pkgIdx(obj.Pkg())
	nameIdx := pw.StringIdx(obj.Name())
	return selectorInfo{pkgIdx: pkgIdx, nameIdx: nameIdx}
}

// @@@ Compiler extensions

func (w *writer) funcExt(obj *types2.Func) {
	decl, ok := w.p.funDecls[obj]
	assert(ok)

	// TODO(mdempsky): Extend these pragma validation flags to account
	// for generics. E.g., linkname probably doesn't make sense at
	// least.

	pragma := asPragmaFlag(decl.Pragma)
	if pragma&ir.Systemstack != 0 && pragma&ir.Nosplit != 0 {
		w.p.errorf(decl, "go:nosplit and go:systemstack cannot be combined")
	}
	wi := asWasmImport(decl.Pragma)
	we := asWasmExport(decl.Pragma)

	if decl.Body != nil {
		if pragma&ir.Noescape != 0 {
			w.p.errorf(decl, "can only use //go:noescape with external func implementations")
		}
		if wi != nil {
			w.p.errorf(decl, "can only use //go:wasmimport with external func implementations")
		}
		if (pragma&ir.UintptrKeepAlive != 0 && pragma&ir.UintptrEscapes == 0) && pragma&ir.Nosplit == 0 {
			// Stack growth can't handle uintptr arguments that may
			// be pointers (as we don't know which are pointers
			// when creating the stack map). Thus uintptrkeepalive
			// functions (and all transitive callees) must be
			// nosplit.
			//
			// N.B. uintptrescapes implies uintptrkeepalive but it
			// is OK since the arguments must escape to the heap.
			//
			// TODO(prattmic): Add recursive nosplit check of callees.
			// TODO(prattmic): Functions with no body (i.e.,
			// assembly) must also be nosplit, but we can't check
			// that here.
			w.p.errorf(decl, "go:uintptrkeepalive requires go:nosplit")
		}
	} else {
		if base.Flag.Complete || decl.Name.Value == "init" {
			// Linknamed functions are allowed to have no body. Hopefully
			// the linkname target has a body. See issue 23311.
			// Wasmimport functions are also allowed to have no body.
			if _, ok := w.p.linknames[obj]; !ok && wi == nil {
				w.p.errorf(decl, "missing function body")
			}
		}
	}

	sig, block := obj.Type().(*types2.Signature), decl.Body
	body, closureVars := w.p.bodyIdx(sig, block, w.dict)
	if len(closureVars) > 0 {
		fmt.Fprintln(os.Stderr, "CLOSURE", closureVars)
	}
	assert(len(closureVars) == 0)

	w.Sync(pkgbits.SyncFuncExt)
	w.pragmaFlag(pragma)
	w.linkname(obj)

	if buildcfg.GOARCH == "wasm" {
		if wi != nil {
			w.String(wi.Module)
			w.String(wi.Name)
		} else {
			w.String("")
			w.String("")
		}
		if we != nil {
			w.String(we.Name)
		} else {
			w.String("")
		}
	}

	w.Bool(false) // stub extension
	w.Reloc(pkgbits.SectionBody, body)
	w.Sync(pkgbits.SyncEOF)
}

func (w *writer) typeExt(obj *types2.TypeName) {
	decl, ok := w.p.typDecls[obj]
	assert(ok)

	w.Sync(pkgbits.SyncTypeExt)

	w.pragmaFlag(asPragmaFlag(decl.Pragma))

	// No LSym.SymIdx info yet.
	w.Int64(-1)
	w.Int64(-1)
}

func (w *writer) varExt(obj *types2.Var) {
	w.Sync(pkgbits.SyncVarExt)
	w.linkname(obj)
}

func (w *writer) linkname(obj types2.Object) {
	w.Sync(pkgbits.SyncLinkname)
	w.Int64(-1)
	info := w.p.linknames[obj]
	w.String(info.remote)
	w.Bool(info.std)
}

func (w *writer) pragmaFlag(p ir.PragmaFlag) {
	w.Sync(pkgbits.SyncPragma)
	w.Int(int(p))
}

// @@@ Function bodies

// bodyIdx returns the index for the given function body (specified by
// block), adding it to the export data
func (pw *pkgWriter) bodyIdx(sig *types2.Signature, block *syntax.BlockStmt, dict *writerDict) (idx index, closureVars []posVar) {
	w := pw.newWriter(pkgbits.SectionBody, pkgbits.SyncFuncBody)
	w.sig = sig
	w.dict = dict

	w.declareParams(sig)
	if w.Bool(block != nil) {
		w.stmts(block.List)
		w.pos(block.Rbrace)
	}

	return w.Flush(), w.closureVars
}

func (w *writer) declareParams(sig *types2.Signature) {
	addLocals := func(params *types2.Tuple) {
		for i := 0; i < params.Len(); i++ {
			w.addLocal(params.At(i))
		}
	}

	if recv := sig.Recv(); recv != nil {
		w.addLocal(recv)
	}
	addLocals(sig.Params())
	addLocals(sig.Results())
}

// addLocal records the declaration of a new local variable.
func (w *writer) addLocal(obj *types2.Var) {
	idx := len(w.localsIdx)

	w.Sync(pkgbits.SyncAddLocal)
	if w.p.SyncMarkers() {
		w.Int(idx)
	}
	w.varDictIndex(obj)

	if w.localsIdx == nil {
		w.localsIdx = make(map[*types2.Var]int)
	}
	w.localsIdx[obj] = idx
}

// useLocal writes a reference to the given local or free variable
// into the bitstream.
func (w *writer) useLocal(pos syntax.Pos, obj *types2.Var) {
	w.Sync(pkgbits.SyncUseObjLocal)

	if idx, ok := w.localsIdx[obj]; w.Bool(ok) {
		w.Len(idx)
		return
	}

	idx, ok := w.closureVarsIdx[obj]
	if !ok {
		if w.closureVarsIdx == nil {
			w.closureVarsIdx = make(map[*types2.Var]int)
		}
		idx = len(w.closureVars)
		w.closureVars = append(w.closureVars, posVar{pos, obj})
		w.closureVarsIdx[obj] = idx
	}
	w.Len(idx)
}

func (w *writer) openScope(pos syntax.Pos) {
	w.Sync(pkgbits.SyncOpenScope)
	w.pos(pos)
}

func (w *writer) closeScope(pos syntax.Pos) {
	w.Sync(pkgbits.SyncCloseScope)
	w.pos(pos)
	w.closeAnotherScope()
}

func (w *writer) closeAnotherScope() {
	w.Sync(pkgbits.SyncCloseAnotherScope)
}

// @@@ Statements

// stmt writes the given statement into the function body bitstream.
func (w *writer) stmt(stmt syntax.Stmt) {
	var stmts []syntax.Stmt
	if stmt != nil {
		stmts = []syntax.Stmt{stmt}
	}
	w.stmts(stmts)
}

func (w *writer) stmts(stmts []syntax.Stmt) {
	dead := false
	w.Sync(pkgbits.SyncStmts)
	var lastLabel = -1
	for i, stmt := range stmts {
		if _, ok := stmt.(*syntax.LabeledStmt); ok {
			lastLabel = i
		}
	}
	for i, stmt := range stmts {
		if dead && i > lastLabel {
			// Any statements after a terminating and last label statement are safe to omit.
			// Otherwise, code after label statement may refer to dead stmts between terminating
			// and label statement, see issue #65593.
			if _, ok := stmt.(*syntax.LabeledStmt); !ok {
				continue
			}
		}
		w.stmt1(stmt)
		dead = w.p.terminates(stmt)
	}
	w.Code(stmtEnd)
	w.Sync(pkgbits.SyncStmtsEnd)
}

func (w *writer) stmt1(stmt syntax.Stmt) {
	switch stmt := stmt.(type) {
	default:
		w.p.unexpected("statement", stmt)

	case nil, *syntax.EmptyStmt:
		return

	case *syntax.AssignStmt:
		switch {
		case stmt.Rhs == nil:
			w.Code(stmtIncDec)
			w.op(binOps[stmt.Op])
			w.expr(stmt.Lhs)
			w.pos(stmt)

		case stmt.Op != 0 && stmt.Op != syntax.Def:
			w.Code(stmtAssignOp)
			w.op(binOps[stmt.Op])
			w.expr(stmt.Lhs)
			w.pos(stmt)

			var typ types2.Type
			if stmt.Op != syntax.Shl && stmt.Op != syntax.Shr {
				typ = w.p.typeOf(stmt.Lhs)
			}
			w.implicitConvExpr(typ, stmt.Rhs)

		default:
			w.assignStmt(stmt, stmt.Lhs, stmt.Rhs)
		}

	case *syntax.BlockStmt:
		w.Code(stmtBlock)
		w.blockStmt(stmt)

	case *syntax.BranchStmt:
		w.Code(stmtBranch)
		w.pos(stmt)
		var op ir.Op
		switch stmt.Tok {
		case syntax.Break:
			op = ir.OBREAK
		case syntax.Continue:
			op = ir.OCONTINUE
		case syntax.Fallthrough:
			op = ir.OFALL
		case syntax.Goto:
			op = ir.OGOTO
		}
		w.op(op)
		w.optLabel(stmt.Label)

	case *syntax.CallStmt:
		w.Code(stmtCall)
		w.pos(stmt)
		var op ir.Op
		switch stmt.Tok {
		case syntax.Defer:
			op = ir.ODEFER
		case syntax.Go:
			op = ir.OGO
		}
		w.op(op)
		w.expr(stmt.Call)
		if stmt.Tok == syntax.Defer {
			w.optExpr(stmt.DeferAt)
		}

	case *syntax.DeclStmt:
		for _, decl := range stmt.DeclList {
			w.declStmt(decl)
		}

	case *syntax.ExprStmt:
		w.Code(stmtExpr)
		w.expr(stmt.X)

	case *syntax.ForStmt:
		w.Code(stmtFor)
		w.forStmt(stmt)

	case *syntax.IfStmt:
		w.Code(stmtIf)
		w.ifStmt(stmt)

	case *syntax.LabeledStmt:
		w.Code(stmtLabel)
		w.pos(stmt)
		w.label(stmt.Label)
		w.stmt1(stmt.Stmt)

	case *syntax.ReturnStmt:
		w.Code(stmtReturn)
		w.pos(stmt)

		resultTypes := w.sig.Results()
		dstType := func(i int) types2.Type {
			return resultTypes.At(i).Type()
		}
		w.multiExpr(stmt, dstType, syntax.UnpackListExpr(stmt.Results))

	case *syntax.SelectStmt:
		w.Code(stmtSelect)
		w.selectStmt(stmt)

	case *syntax.SendStmt:
		chanType := types2.CoreType(w.p.typeOf(stmt.Chan)).(*types2.Chan)

		w.Code(stmtSend)
		w.pos(stmt)
		w.expr(stmt.Chan)
		w.implicitConvExpr(chanType.Elem(), stmt.Value)

	case *syntax.SwitchStmt:
		w.Code(stmtSwitch)
		w.switchStmt(stmt)
	}
}

func (w *writer) assignList(expr syntax.Expr) {
	exprs := syntax.UnpackListExpr(expr)
	w.Len(len(exprs))

	for _, expr := range exprs {
		w.assign(expr)
	}
}

func (w *writer) assign(expr syntax.Expr) {
	expr = syntax.Unparen(expr)

	if name, ok := expr.(*syntax.Name); ok {
		if name.Value == "_" {
			w.Code(assignBlank)
			return
		}

		if obj, ok := w.p.info.Defs[name]; ok {
			obj := obj.(*types2.Var)

			w.Code(assignDef)
			w.pos(obj)
			w.localIdent(obj)
			w.typ(obj.Type())

			// TODO(mdempsky): Minimize locals index size by deferring
			// this until the variables actually come into scope.
			w.addLocal(obj)
			return
		}
	}

	w.Code(assignExpr)
	w.expr(expr)
}

func (w *writer) declStmt(decl syntax.Decl) {
	switch decl := decl.(type) {
	default:
		w.p.unexpected("declaration", decl)

	case *syntax.ConstDecl, *syntax.TypeDecl:

	case *syntax.VarDecl:
		w.assignStmt(decl, namesAsExpr(decl.NameList), decl.Values)
	}
}

// assignStmt writes out an assignment for "lhs = rhs".
func (w *writer) assignStmt(pos poser, lhs0, rhs0 syntax.Expr) {
	lhs := syntax.UnpackListExpr(lhs0)
	rhs := syntax.UnpackListExpr(rhs0)

	w.Code(stmtAssign)
	w.pos(pos)

	// As if w.assignList(lhs0).
	w.Len(len(lhs))
	for _, expr := range lhs {
		w.assign(expr)
	}

	dstType := func(i int) types2.Type {
		dst := lhs[i]

		// Finding dstType is somewhat involved, because for VarDecl
		// statements, the Names are only added to the info.{Defs,Uses}
		// maps, not to info.Types.
		if name, ok := syntax.Unparen(dst).(*syntax.Name); ok {
			if name.Value == "_" {
				return nil // ok: no implicit conversion
			} else if def, ok := w.p.info.Defs[name].(*types2.Var); ok {
				return def.Type()
			} else if use, ok := w.p.info.Uses[name].(*types2.Var); ok {
				return use.Type()
			} else {
				w.p.fatalf(dst, "cannot find type of destination object: %v", dst)
			}
		}

		return w.p.typeOf(dst)
	}

	w.multiExpr(pos, dstType, rhs)
}

func (w *writer) blockStmt(stmt *syntax.BlockStmt) {
	w.Sync(pkgbits.SyncBlockStmt)
	w.openScope(stmt.Pos())
	w.stmts(stmt.List)
	w.closeScope(stmt.Rbrace)
}

func (w *writer) forStmt(stmt *syntax.ForStmt) {
	w.Sync(pkgbits.SyncForStmt)
	w.openScope(stmt.Pos())

	if rang, ok := stmt.Init.(*syntax.RangeClause); w.Bool(ok) {
		w.pos(rang)
		w.assignList(rang.Lhs)
		w.expr(rang.X)

		xtyp := w.p.typeOf(rang.X)
		if _, isMap := types2.CoreType(xtyp).(*types2.Map); isMap {
			w.rtype(xtyp)
		}
		{
			lhs := syntax.UnpackListExpr(rang.Lhs)
			assign := func(i int, src types2.Type) {
				if i >= len(lhs) {
					return
				}
				dst := syntax.Unparen(lhs[i])
				if name, ok := dst.(*syntax.Name); ok && name.Value == "_" {
					return
				}

				var dstType types2.Type
				if rang.Def {
					// For `:=` assignments, the LHS names only appear in Defs,
					// not Types (as used by typeOf).
					dstType = w.p.info.Defs[dst.(*syntax.Name)].(*types2.Var).Type()
				} else {
					dstType = w.p.typeOf(dst)
				}

				w.convRTTI(src, dstType)
			}

			keyType, valueType := types2.RangeKeyVal(w.p.typeOf(rang.X))
			assign(0, keyType)
			assign(1, valueType)
		}

	} else {
		if stmt.Cond != nil && w.p.staticBool(&stmt.Cond) < 0 { // always false
			stmt.Post = nil
			stmt.Body.List = nil
		}

		w.pos(stmt)
		w.stmt(stmt.Init)
		w.optExpr(stmt.Cond)
		w.stmt(stmt.Post)
	}

	w.blockStmt(stmt.Body)
	w.Bool(w.distinctVars(stmt))
	w.closeAnotherScope()
}

func (w *writer) distinctVars(stmt *syntax.ForStmt) bool {
	lv := base.Debug.LoopVar
	fileVersion := w.p.info.FileVersions[stmt.Pos().FileBase()]
	is122 := fileVersion == "" || version.Compare(fileVersion, "go1.22") >= 0

	// Turning off loopvar for 1.22 is only possible with loopvarhash=qn
	//
	// Debug.LoopVar values to be preserved for 1.21 compatibility are 1 and 2,
	// which are also set (=1) by GOEXPERIMENT=loopvar.  The knobs for turning on
	// the new, unshared, loopvar behavior apply to versions less than 1.21 because
	// (1) 1.21 also did that and (2) this is believed to be the likely use case;
	// anyone checking to see if it affects their code will just run the GOEXPERIMENT
	// but will not also update all their go.mod files to 1.21.
	//
	// -gcflags=-d=loopvar=3 enables logging for 1.22 but does not turn loopvar on for <= 1.21.

	return is122 || lv > 0 && lv != 3
}

func (w *writer) ifStmt(stmt *syntax.IfStmt) {
	cond := w.p.staticBool(&stmt.Cond)

	w.Sync(pkgbits.SyncIfStmt)
	w.openScope(stmt.Pos())
	w.pos(stmt)
	w.stmt(stmt.Init)
	w.expr(stmt.Cond)
	w.Int(cond)
	if cond >= 0 {
		w.blockStmt(stmt.Then)
	} else {
		w.pos(stmt.Then.Rbrace)
	}
	if cond <= 0 {
		w.stmt(stmt.Else)
	}
	w.closeAnotherScope()
}

func (w *writer) selectStmt(stmt *syntax.SelectStmt) {
	w.Sync(pkgbits.SyncSelectStmt)

	w.pos(stmt)
	w.Len(len(stmt.Body))
	for i, clause := range stmt.Body {
		if i > 0 {
			w.closeScope(clause.Pos())
		}
		w.openScope(clause.Pos())

		w.pos(clause)
		w.stmt(clause.Comm)
		w.stmts(clause.Body)
	}
	if len(stmt.Body) > 0 {
		w.closeScope(stmt.Rbrace)
	}
}

func (w *writer) switchStmt(stmt *syntax.SwitchStmt) {
	w.Sync(pkgbits.SyncSwitchStmt)

	w.openScope(stmt.Pos())
	w.pos(stmt)
	w.stmt(stmt.Init)

	var iface, tagType types2.Type
	var tagTypeIsChan bool
	if guard, ok := stmt.Tag.(*syntax.TypeSwitchGuard); w.Bool(ok) {
		iface = w.p.typeOf(guard.X)

		w.pos(guard)
		if tag := guard.Lhs; w.Bool(tag != nil) {
			w.pos(tag)

			// Like w.localIdent, but we don't have a types2.Object.
			w.Sync(pkgbits.SyncLocalIdent)
			w.pkg(w.p.curpkg)
			w.String(tag.Value)
		}
		w.expr(guard.X)
	} else {
		tag := stmt.Tag

		var tagValue constant.Value
		if tag != nil {
			tv := w.p.typeAndValue(tag)
			tagType = tv.Type
			tagValue = tv.Value
			_, tagTypeIsChan = tagType.Underlying().(*types2.Chan)
		} else {
			tagType = types2.Typ[types2.Bool]
			tagValue = constant.MakeBool(true)
		}

		if tagValue != nil {
			// If the switch tag has a constant value, look for a case
			// clause that we always branch to.
			func() {
				var target *syntax.CaseClause
			Outer:
				for _, clause := range stmt.Body {
					if clause.Cases == nil {
						target = clause
					}
					for _, cas := range syntax.UnpackListExpr(clause.Cases) {
						tv := w.p.typeAndValue(cas)
						if tv.Value == nil {
							return // non-constant case; give up
						}
						if constant.Compare(tagValue, token.EQL, tv.Value) {
							target = clause
							break Outer
						}
					}
				}
				// We've found the target clause, if any.

				if target != nil {
					if hasFallthrough(target.Body) {
						return // fallthrough is tricky; give up
					}

					// Rewrite as single "default" case.
					target.Cases = nil
					stmt.Body = []*syntax.CaseClause{target}
				} else {
					stmt.Body = nil
				}

				// Clear switch tag (i.e., replace with implicit "true").
				tag = nil
				stmt.Tag = nil
				tagType = types2.Typ[types2.Bool]
			}()
		}

		// Walk is going to emit comparisons between the tag value and
		// each case expression, and we want these comparisons to always
		// have the same type. If there are any case values that can't be
		// converted to the tag value's type, then convert everything to
		// `any` instead.
		//
		// Except that we need to keep comparisons of channel values from
		// being wrapped in any(). See issue #67190.

		if !tagTypeIsChan {
		Outer:
			for _, clause := range stmt.Body {
				for _, cas := range syntax.UnpackListExpr(clause.Cases) {
					if casType := w.p.typeOf(cas); !types2.AssignableTo(casType, tagType) && (types2.IsInterface(casType) || types2.IsInterface(tagType)) {
						tagType = types2.NewInterfaceType(nil, nil)
						break Outer
					}
				}
			}
		}

		if w.Bool(tag != nil) {
			w.implicitConvExpr(tagType, tag)
		}
	}

	w.Len(len(stmt.Body))
	for i, clause := range stmt.Body {
		if i > 0 {
			w.closeScope(clause.Pos())
		}
		w.openScope(clause.Pos())

		w.pos(clause)

		cases := syntax.UnpackListExpr(clause.Cases)
		if iface != nil {
			w.Len(len(cases))
			for _, cas := range cases {
				if w.Bool(isNil(w.p, cas)) {
					continue
				}
				w.exprType(iface, cas)
			}
		} else {
			// As if w.exprList(clause.Cases),
			// but with implicit conversions to tagType.

			w.Sync(pkgbits.SyncExprList)
			w.Sync(pkgbits.SyncExprs)
			w.Len(len(cases))
			for _, cas := range cases {
				typ := tagType
				if tagTypeIsChan {
					typ = nil
				}
				w.implicitConvExpr(typ, cas)
			}
		}

		if obj, ok := w.p.info.Implicits[clause]; ok {
			// TODO(mdempsky): These pos details are quirkish, but also
			// necessary so the variable's position is correct for DWARF
			// scope assignment later. It would probably be better for us to
			// instead just set the variable's DWARF scoping info earlier so
			// we can give it the correct position information.
			pos := clause.Pos()
			if typs := syntax.UnpackListExpr(clause.Cases); len(typs) != 0 {
				pos = typeExprEndPos(typs[len(typs)-1])
			}
			w.pos(pos)

			obj := obj.(*types2.Var)
			w.typ(obj.Type())
			w.addLocal(obj)
		}

		w.stmts(clause.Body)
	}
	if len(stmt.Body) > 0 {
		w.closeScope(stmt.Rbrace)
	}

	w.closeScope(stmt.Rbrace)
}

func (w *writer) label(label *syntax.Name) {
	w.Sync(pkgbits.SyncLabel)

	// TODO(mdempsky): Replace label strings with dense indices.
	w.String(label.Value)
}

func (w *writer) optLabel(label *syntax.Name) {
	w.Sync(pkgbits.SyncOptLabel)
	if w.Bool(label != nil) {
		w.label(label)
	}
}

// @@@ Expressions

// expr writes the given expression into the function body bitstream.
func (w *writer) expr(expr syntax.Expr) {
	base.Assertf(expr != nil, "missing expression")

	expr = syntax.Unparen(expr) // skip parens; unneeded after typecheck

	obj, inst := lookupObj(w.p, expr)
	targs := asTypeSlice(inst.TypeArgs)

	if tv, ok := w.p.maybeTypeAndValue(expr); ok {
		if tv.IsRuntimeHelper() {
			if pkg := obj.Pkg(); pkg != nil && pkg.Name() == "runtime" {
				objName := obj.Name()
				w.Code(exprRuntimeBuiltin)
				w.String(objName)
				return
			}
		}

		if tv.IsType() {
			w.p.fatalf(expr, "unexpected type expression %v", syntax.String(expr))
		}

		if tv.Value != nil {
			w.Code(exprConst)
			w.pos(expr)
			typ := idealType(tv)
			assert(typ != nil)
			w.typ(typ)
			w.Value(tv.Value)
			return
		}

		if _, isNil := obj.(*types2.Nil); isNil {
			w.Code(exprZero)
			w.pos(expr)
			w.typ(tv.Type)
			return
		}

		// With shape types (and particular pointer shaping), we may have
		// an expression of type "go.shape.*uint8", but need to reshape it
		// to another shape-identical type to allow use in field
		// selection, indexing, etc.
		if typ := tv.Type; !tv.IsBuiltin() && !isTuple(typ) && !isUntyped(typ) {
			w.Code(exprReshape)
			w.typ(typ)
			// fallthrough
		}
	}

	if obj != nil {
		if len(targs) != 0 {
			obj := obj.(*types2.Func)

			w.Code(exprFuncInst)
			w.pos(expr)
			w.funcInst(obj, targs)
			return
		}

		if isGlobal(obj) {
			w.Code(exprGlobal)
			w.obj(obj, nil)
			return
		}

		obj := obj.(*types2.Var)
		assert(!obj.IsField())

		w.Code(exprLocal)
		w.useLocal(expr.Pos(), obj)
		return
	}

	switch expr := expr.(type) {
	default:
		w.p.unexpected("expression", expr)

	case *syntax.CompositeLit:
		w.Code(exprCompLit)
		w.compLit(expr)

	case *syntax.FuncLit:
		w.Code(exprFuncLit)
		w.funcLit(expr)

	case *syntax.SelectorExpr:
		sel, ok := w.p.info.Selections[expr]
		assert(ok)

		switch sel.Kind() {
		default:
			w.p.fatalf(expr, "unexpected selection kind: %v", sel.Kind())

		case types2.FieldVal:
			w.Code(exprFieldVal)
			w.expr(expr.X)
			w.pos(expr)
			w.selector(sel.Obj())

		case types2.MethodVal:
			w.methVal(expr, sel)

		case types2.MethodExpr:
			w.methExpr(expr, sel)
		}

	case *syntax.IndexExpr:
		// might be explicit instantiation of a generic method
		if selector, ok := expr.X.(*syntax.SelectorExpr); ok {
			if sel, ok := w.p.info.Selections[selector]; ok {
				switch sel.Kind() {
				default:
					w.p.fatalf(selector, "unexpected selection kind: %v", sel.Kind())
				case types2.FieldVal:
					// not a method
				case types2.MethodVal:
					w.methVal(selector, sel)
					return
				case types2.MethodExpr:
					w.methExpr(selector, sel)
					return
				}
			}
		}
		_ = w.p.typeOf(expr.Index) // ensure this is an index expression, not an instantiation

		xtyp := w.p.typeOf(expr.X)

		var keyType types2.Type
		if mapType, ok := types2.CoreType(xtyp).(*types2.Map); ok {
			keyType = mapType.Key()
		}

		w.Code(exprIndex)
		w.expr(expr.X)
		w.pos(expr)
		w.implicitConvExpr(keyType, expr.Index)
		if keyType != nil {
			w.rtype(xtyp)
		}

	case *syntax.SliceExpr:
		w.Code(exprSlice)
		w.expr(expr.X)
		w.pos(expr)
		for _, n := range &expr.Index {
			w.optExpr(n)
		}

	case *syntax.AssertExpr:
		iface := w.p.typeOf(expr.X)

		w.Code(exprAssert)
		w.expr(expr.X)
		w.pos(expr)
		w.exprType(iface, expr.Type)
		w.rtype(iface)

	case *syntax.Operation:
		if expr.Y == nil {
			w.Code(exprUnaryOp)
			w.op(unOps[expr.Op])
			w.pos(expr)
			w.expr(expr.X)
			break
		}

		var commonType types2.Type
		switch expr.Op {
		case syntax.Shl, syntax.Shr:
			// ok: operands are allowed to have different types
		default:
			xtyp := w.p.typeOf(expr.X)
			ytyp := w.p.typeOf(expr.Y)
			switch {
			case types2.AssignableTo(xtyp, ytyp):
				commonType = ytyp
			case types2.AssignableTo(ytyp, xtyp):
				commonType = xtyp
			default:
				w.p.fatalf(expr, "failed to find common type between %v and %v", xtyp, ytyp)
			}
		}

		w.Code(exprBinaryOp)
		w.op(binOps[expr.Op])
		w.implicitConvExpr(commonType, expr.X)
		w.pos(expr)
		w.implicitConvExpr(commonType, expr.Y)

	case *syntax.CallExpr:
		tv := w.p.typeAndValue(expr.Fun)
		if tv.IsType() {
			assert(len(expr.ArgList) == 1)
			assert(!expr.HasDots)
			w.convertExpr(tv.Type, expr.ArgList[0], false)
			break
		}

		var rtype types2.Type
		if tv.IsBuiltin() {
			switch obj, _ := lookupObj(w.p, syntax.Unparen(expr.Fun)); obj.Name() {
			case "make":
				assert(len(expr.ArgList) >= 1)
				assert(!expr.HasDots)

				w.Code(exprMake)
				w.pos(expr)
				w.exprType(nil, expr.ArgList[0])
				w.exprs(expr.ArgList[1:])

				typ := w.p.typeOf(expr)
				switch coreType := types2.CoreType(typ).(type) {
				default:
					w.p.fatalf(expr, "unexpected core type: %v", coreType)
				case *types2.Chan:
					w.rtype(typ)
				case *types2.Map:
					w.rtype(typ)
				case *types2.Slice:
					w.rtype(sliceElem(typ))
				}

				return

			case "new":
				assert(len(expr.ArgList) == 1)
				assert(!expr.HasDots)
				arg := expr.ArgList[0]

				w.Code(exprNew)
				w.pos(expr)
				tv := w.p.typeAndValue(arg)
				if w.Bool(!tv.IsType()) {
					w.expr(arg) // new(expr), go1.26
				} else {
					w.exprType(nil, arg) // new(T)
				}
				return

			case "Sizeof":
				assert(len(expr.ArgList) == 1)
				assert(!expr.HasDots)

				w.Code(exprSizeof)
				w.pos(expr)
				w.typ(w.p.typeOf(expr.ArgList[0]))
				return

			case "Alignof":
				assert(len(expr.ArgList) == 1)
				assert(!expr.HasDots)

				w.Code(exprAlignof)
				w.pos(expr)
				w.typ(w.p.typeOf(expr.ArgList[0]))
				return

			case "Offsetof":
				assert(len(expr.ArgList) == 1)
				assert(!expr.HasDots)
				selector := syntax.Unparen(expr.ArgList[0]).(*syntax.SelectorExpr)
				index := w.p.info.Selections[selector].Index()

				w.Code(exprOffsetof)
				w.pos(expr)
				w.typ(deref2(w.p.typeOf(selector.X)))
				w.Len(len(index) - 1)
				for _, idx := range index {
					w.Len(idx)
				}
				return

			case "append":
				rtype = sliceElem(w.p.typeOf(expr))
			case "copy":
				typ := w.p.typeOf(expr.ArgList[0])
				if tuple, ok := typ.(*types2.Tuple); ok { // "copy(g())"
					typ = tuple.At(0).Type()
				}
				rtype = sliceElem(typ)
			case "delete":
				typ := w.p.typeOf(expr.ArgList[0])
				if tuple, ok := typ.(*types2.Tuple); ok { // "delete(g())"
					typ = tuple.At(0).Type()
				}
				rtype = typ
			case "Slice":
				rtype = sliceElem(w.p.typeOf(expr))
			}
		}

		writeFunExpr := func() {
			fun := syntax.Unparen(expr.Fun)

			expr := fun
			if idx, ok := expr.(*syntax.IndexExpr); ok {
				expr = idx.X
			}
			if selector, ok := expr.(*syntax.SelectorExpr); ok {
				if sel, ok := w.p.info.Selections[selector]; ok && sel.Kind() == types2.MethodVal {
					w.Bool(true) // method call
					typ := w.recvExpr(selector, sel)
					w.methodExpr(selector, typ, sel)
					return
				}
			}

			w.Bool(false) // not a method call (i.e., normal function call)

			if obj, inst := lookupObj(w.p, fun); w.Bool(obj != nil && inst.TypeArgs.Len() != 0) {
				obj := obj.(*types2.Func)

				w.pos(fun)
				w.funcInst(obj, asTypeSlice(inst.TypeArgs))
				return
			}

			w.expr(fun)
		}

		sigType := types2.CoreType(tv.Type).(*types2.Signature)
		paramTypes := sigType.Params()

		w.Code(exprCall)
		writeFunExpr()
		w.pos(expr)

		paramType := func(i int) types2.Type {
			if sigType.Variadic() && !expr.HasDots && i >= paramTypes.Len()-1 {
				return paramTypes.At(paramTypes.Len() - 1).Type().(*types2.Slice).Elem()
			}
			return paramTypes.At(i).Type()
		}

		w.multiExpr(expr, paramType, expr.ArgList)
		w.Bool(expr.HasDots)
		if rtype != nil {
			w.rtype(rtype)
		}
	}
}

func sliceElem(typ types2.Type) types2.Type {
	return types2.CoreType(typ).(*types2.Slice).Elem()
}

func (w *writer) optExpr(expr syntax.Expr) {
	if w.Bool(expr != nil) {
		w.expr(expr)
	}
}

func (w *writer) methVal(expr *syntax.SelectorExpr, sel *types2.Selection) {
	w.Code(exprMethodVal)
	typ := w.recvExpr(expr, sel)
	w.pos(expr)
	w.methodExpr(expr, typ, sel)
}

func (w *writer) methExpr(expr *syntax.SelectorExpr, sel *types2.Selection) {
	w.Code(exprMethodExpr)

	tv := w.p.typeAndValue(expr.X)
	assert(tv.IsType())

	index := sel.Index()
	implicits := index[:len(index)-1]

	typ := tv.Type
	w.typ(typ)

	w.Len(len(implicits))
	for _, ix := range implicits {
		w.Len(ix)
		typ = deref2(typ).Underlying().(*types2.Struct).Field(ix).Type()
	}

	recv := sel.Obj().(*types2.Func).Type().(*types2.Signature).Recv().Type()
	if w.Bool(isPtrTo(typ, recv)) { // need deref
		typ = recv
	} else if w.Bool(isPtrTo(recv, typ)) { // need addr
		typ = recv
	}

	w.pos(expr)
	w.methodExpr(expr, typ, sel)
}

// recvExpr writes out expr.X, but handles any implicit addressing,
// dereferencing, and field selections appropriate for the method
// selection.
func (w *writer) recvExpr(expr *syntax.SelectorExpr, sel *types2.Selection) types2.Type {
	index := sel.Index()
	implicits := index[:len(index)-1]

	w.Code(exprRecv)
	w.expr(expr.X)
	w.pos(expr)
	w.Len(len(implicits))

	typ := w.p.typeOf(expr.X)
	for _, ix := range implicits {
		typ = deref2(typ).Underlying().(*types2.Struct).Field(ix).Type()
		w.Len(ix)
	}

	recv := sel.Obj().(*types2.Func).Type().(*types2.Signature).Recv().Type()
	if w.Bool(isPtrTo(typ, recv)) { // needs deref
		typ = recv
	} else if w.Bool(isPtrTo(recv, typ)) { // needs addr
		typ = recv
	}

	return typ
}

// funcInst writes a reference to an instantiated function.
func (w *writer) funcInst(obj *types2.Func, targs []types2.Type) {
	info := w.p.objInstIdx(obj, targs, w.dict)

	// Type arguments list contains derived types; we can emit a static
	// call to the shaped function, but need to dynamically compute the
	// runtime dictionary pointer.
	if w.Bool(info.anyDerived()) {
		w.Len(w.dict.subdictIdx(info))
		return
	}

	// Type arguments list is statically known; we can emit a static
	// call with a statically reference to the respective runtime
	// dictionary.
	w.objInfo(info)
}

// methodExpr writes out a reference to the method selected by
// expr. sel should be the corresponding types2.Selection, and recv
// the type produced after any implicit addressing, dereferencing, and
// field selection. (Note: recv might differ from sel.Obj()'s receiver
// parameter in the case of interface types, and is needed for
// handling type parameter methods.)
func (w *writer) methodExpr(expr *syntax.SelectorExpr, recv types2.Type, sel *types2.Selection) {
	fun := sel.Obj().(*types2.Func)
	sig := fun.Type().(*types2.Signature)

	w.typ(recv)

	// only pass the signature if it's not a generic method
	if isGenericMethod(sig) {
		assert(w.Version().Has(pkgbits.GenericMethods))
		w.Bool(true)
	} else {
		if w.Version().Has(pkgbits.GenericMethods) {
			w.Bool(false)
		}
		w.typ(sig)
	}

	w.pos(expr)
	w.selector(fun)

	// Method on a type parameter. These require an indirect call
	// through the current function's runtime dictionary.
	if typeParam, ok := types2.Unalias(recv).(*types2.TypeParam); w.Bool(ok) {
		typeParamIdx := w.dict.typeParamIndex(typeParam)
		methodInfo := w.p.selectorIdx(fun)

		w.Len(w.dict.typeParamMethodExprIdx(typeParamIdx, methodInfo))
		return
	}

	if isInterface(recv) != isInterface(sig.Recv().Type()) {
		w.p.fatalf(expr, "isInterface inconsistency: %v and %v", recv, sig.Recv().Type())
	}

	if isConcreteMethod(sig) {
		tname, tExplicits := splitNamed(types2.Unalias(deref2(recv)).(*types2.Named))
		var info objInfo
		if isGenericMethod(sig) {
			// For generic methods, the shaped object is the method itself.
			mExplicits := asTypeSlice(w.p.info.Instances[expr.Sel].TypeArgs)
			info = w.p.objInstIdx(fun.Origin(), slices.Concat(tExplicits, mExplicits), w.dict)
		} else {
			// For non-generic concrete methods on generic types, the shaped object
			// is the type. The method must be looked up on the type by name.
			info = w.p.objInstIdx(tname, tExplicits, w.dict)
		}
		// We don't know all of the type arguments statically. These can be
		// handled by a static call to the shaped method, but require
		// dynamically looking up the appropriate dictionary argument
		// in the current function's runtime dictionary.
		if info.anyDerived() {
			w.Bool(true) // dynamic subdictionary
			w.Len(w.dict.subdictIdx(info))
			return
		}
		// We know all of the type arguments statically. These can be handled
		// by a static call to the shaped method, and with a static reference
		// to either the receiver type's or method's dictionary (see above).
		if len(info.explicits) > 0 {
			w.Bool(false) // no dynamic subdictionary
			w.Bool(true)  // static dictionary
			w.objInfo(info)
			return
		}
		// no type arguments
	}

	w.Bool(false) // no dynamic subdictionary
	w.Bool(false) // no static dictionary
}

// multiExpr writes a sequence of expressions, where the i'th value is
// implicitly converted to dstType(i). It also handles when exprs is a
// single, multi-valued expression (e.g., the multi-valued argument in
// an f(g()) call, or the RHS operand in a comma-ok assignment).
func (w *writer) multiExpr(pos poser, dstType func(int) types2.Type, exprs []syntax.Expr) {
	w.Sync(pkgbits.SyncMultiExpr)

	if len(exprs) == 1 {
		expr := exprs[0]
		if tuple, ok := w.p.typeOf(expr).(*types2.Tuple); ok {
			assert(tuple.Len() > 1)
			w.Bool(true) // N:1 assignment
			w.pos(pos)
			w.expr(expr)

			w.Len(tuple.Len())
			for i := 0; i < tuple.Len(); i++ {
				src := tuple.At(i).Type()
				// TODO(mdempsky): Investigate not writing src here. I think
				// the reader should be able to infer it from expr anyway.
				w.typ(src)
				if dst := dstType(i); w.Bool(dst != nil && !types2.Identical(src, dst)) {
					if src == nil || dst == nil {
						w.p.fatalf(pos, "src is %v, dst is %v", src, dst)
					}
					if !types2.AssignableTo(src, dst) {
						w.p.fatalf(pos, "%v is not assignable to %v", src, dst)
					}
					w.typ(dst)
					w.convRTTI(src, dst)
				}
			}
			return
		}
	}

	w.Bool(false) // N:N assignment
	w.Len(len(exprs))
	for i, expr := range exprs {
		w.implicitConvExpr(dstType(i), expr)
	}
}

// implicitConvExpr is like expr, but if dst is non-nil and different
// from expr's type, then an implicit conversion operation is inserted
// at expr's position.
func (w *writer) implicitConvExpr(dst types2.Type, expr syntax.Expr) {
	w.convertExpr(dst, expr, true)
}

func (w *writer) convertExpr(dst types2.Type, expr syntax.Expr, implicit bool) {
	src := w.p.typeOf(expr)

	// Omit implicit no-op conversions.
	identical := dst == nil || types2.Identical(src, dst)
	if implicit && identical {
		w.expr(expr)
		return
	}

	if implicit && !types2.AssignableTo(src, dst) {
		w.p.fatalf(expr, "%v is not assignable to %v", src, dst)
	}

	w.Code(exprConvert)
	w.Bool(implicit)
	w.typ(dst)
	w.pos(expr)
	w.convRTTI(src, dst)
	w.Bool(isTypeParam(dst))
	w.Bool(identical)
	w.expr(expr)
}

func (w *writer) compLit(lit *syntax.CompositeLit) {
	typ := w.p.typeOf(lit)

	w.Sync(pkgbits.SyncCompLit)
	w.pos(lit)
	w.typ(typ)

	if ptr, ok := types2.CoreType(typ).(*types2.Pointer); ok {
		typ = ptr.Elem()
	}

	if w.Version().Has(pkgbits.CompactCompLiterals) {
		switch typ0 := typ; typ := types2.CoreType(typ).(type) {
		default:
			w.p.fatalf(lit, "unexpected composite literal type: %v", typ)
		case *types2.Array:
			w.arrayElems(typ.Elem(), lit.ElemList)
		case *types2.Map:
			w.rtype(typ0)
			w.mapElems(typ.Key(), typ.Elem(), lit.ElemList)
		case *types2.Slice:
			w.arrayElems(typ.Elem(), lit.ElemList)
		case *types2.Struct:
			w.structElems(typ, lit.NKeys == 0, lit.ElemList)
		}
		return
	}

	// old format
	var keyType, elemType types2.Type
	var structType *types2.Struct
	switch typ0 := typ; typ := types2.CoreType(typ).(type) {
	default:
		w.p.fatalf(lit, "unexpected composite literal type: %v", typ)
	case *types2.Array:
		elemType = typ.Elem()
	case *types2.Map:
		w.rtype(typ0)
		keyType, elemType = typ.Key(), typ.Elem()
	case *types2.Slice:
		elemType = typ.Elem()
	case *types2.Struct:
		structType = typ
	}

	w.Len(len(lit.ElemList))
	for i, elem := range lit.ElemList {
		elemType := elemType
		if structType != nil {
			if kv, ok := elem.(*syntax.KeyValueExpr); ok {
				// use position of expr.Key rather than of elem (which has position of ':')
				w.pos(kv.Key)
				i = fieldIndex(w.p.info, structType, kv.Key.(*syntax.Name))
				elem = kv.Value
			} else {
				w.pos(elem)
			}
			elemType = structType.Field(i).Type()
			w.Len(i)
		} else {
			if kv, ok := elem.(*syntax.KeyValueExpr); w.Bool(ok) {
				// use position of expr.Key rather than of elem (which has position of ':')
				w.pos(kv.Key)
				w.implicitConvExpr(keyType, kv.Key)
				elem = kv.Value
			}
		}
		w.implicitConvExpr(elemType, elem)
	}
}

func (w *writer) arrayElems(elemType types2.Type, elems []syntax.Expr) {
	valuesOnly := true
	for _, elem := range elems {
		if _, ok := elem.(*syntax.KeyValueExpr); ok {
			valuesOnly = false
			break
		}
	}

	if valuesOnly {
		w.Int(len(elems))
		for _, elem := range elems {
			w.implicitConvExpr(elemType, elem)
		}
		return
	}
	// some elements may have a key
	w.Int(-len(elems))
	for _, elem := range elems {
		if kv, ok := elem.(*syntax.KeyValueExpr); w.Bool(ok) {
			w.pos(kv.Key) // use position of Key rather than of elem (which has position of ':')
			w.implicitConvExpr(nil, kv.Key)
			elem = kv.Value
		}
		w.implicitConvExpr(elemType, elem)
	}
}

func (w *writer) mapElems(keyType, valueType types2.Type, elems []syntax.Expr) {
	// all elements have a key
	w.Int(-len(elems))
	for _, elem := range elems {
		kv := elem.(*syntax.KeyValueExpr)
		w.pos(kv.Key) // use position of Key rather than of elem (which has position of ':')
		w.implicitConvExpr(keyType, kv.Key)
		w.implicitConvExpr(valueType, kv.Value)
	}
}

func (w *writer) structElems(typ *types2.Struct, valuesOnly bool, elems []syntax.Expr) {
	n := len(elems)
	if valuesOnly {
		// no element has a key
		w.Int(n)
		for i, elem := range elems {
			w.pos(elem)
			w.implicitConvExpr(typ.Field(i).Type(), elem)
		}
		return
	}
	// all elements have a key
	w.Int(-n)
	for _, elem := range elems {
		kv := elem.(*syntax.KeyValueExpr)
		w.pos(kv.Key) // use position of Key rather than of elem (which has position of ':')
		// TODO(gri): rather than doing this lookup again, perhaps the index should be recorded by types2
		fld, index, _ := types2.LookupFieldOrMethod(typ, false, w.p.curpkg, kv.Key.(*syntax.Name).Value)
		if n := len(index); n > 1 {
			// embedded field
			w.Int(-n)
			for _, i := range index {
				w.Int(i)
			}
		} else { // n == 1
			w.Int(index[0])
		}
		w.implicitConvExpr(fld.Type(), kv.Value)
	}
}

func (w *writer) funcLit(expr *syntax.FuncLit) {
	sig := w.p.typeOf(expr).(*types2.Signature)

	body, closureVars := w.p.bodyIdx(sig, expr.Body, w.dict)

	w.Sync(pkgbits.SyncFuncLit)
	w.pos(expr)
	w.signature(sig)
	w.Bool(w.p.rangeFuncBodyClosures[expr])

	w.Len(len(closureVars))
	for _, cv := range closureVars {
		w.pos(cv.pos)
		w.useLocal(cv.pos, cv.var_)
	}

	w.Reloc(pkgbits.SectionBody, body)
}

type posVar struct {
	pos  syntax.Pos
	var_ *types2.Var
}

func (p posVar) String() string {
	return p.pos.String() + ":" + p.var_.String()
}

func (w *writer) exprs(exprs []syntax.Expr) {
	w.Sync(pkgbits.SyncExprs)
	w.Len(len(exprs))
	for _, expr := range exprs {
		w.expr(expr)
	}
}

// rtype writes information so that the reader can construct an
// expression of type *runtime._type representing typ.
func (w *writer) rtype(typ types2.Type) {
	typ = types2.Default(typ)

	info := w.p.typIdx(typ, w.dict)
	w.rtypeInfo(info)
}

func (w *writer) rtypeInfo(info typeInfo) {
	w.Sync(pkgbits.SyncRType)

	if w.Bool(info.derived) {
		w.Len(w.dict.rtypeIdx(info))
	} else {
		w.typInfo(info)
	}
}

// varDictIndex writes out information for populating DictIndex for
// the ir.Name that will represent obj.
func (w *writer) varDictIndex(obj *types2.Var) {
	info := w.p.typIdx(obj.Type(), w.dict)
	if w.Bool(info.derived) {
		w.Len(w.dict.rtypeIdx(info))
	}
}

// isUntyped reports whether typ is an untyped type.
func isUntyped(typ types2.Type) bool {
	// Note: types2.Unalias is unnecessary here, since untyped types can't be aliased.
	basic, ok := typ.(*types2.Basic)
	return ok && basic.Info()&types2.IsUntyped != 0
}

// isTuple reports whether typ is a tuple type.
func isTuple(typ types2.Type) bool {
	// Note: types2.Unalias is unnecessary here, since tuple types can't be aliased.
	_, ok := typ.(*types2.Tuple)
	return ok
}

func (w *writer) itab(typ, iface types2.Type) {
	typ = types2.Default(typ)
	iface = types2.Default(iface)

	typInfo := w.p.typIdx(typ, w.dict)
	ifaceInfo := w.p.typIdx(iface, w.dict)

	w.rtypeInfo(typInfo)
	w.rtypeInfo(ifaceInfo)
	if w.Bool(typInfo.derived || ifaceInfo.derived) {
		w.Len(w.dict.itabIdx(typInfo, ifaceInfo))
	}
}

// convRTTI writes information so that the reader can construct
// expressions for converting from src to dst.
func (w *writer) convRTTI(src, dst types2.Type) {
	w.Sync(pkgbits.SyncConvRTTI)
	w.itab(src, dst)
}

func (w *writer) exprType(iface types2.Type, typ syntax.Expr) {
	base.Assertf(iface == nil || isInterface(iface), "%v must be nil or an interface type", iface)

	tv := w.p.typeAndValue(typ)
	assert(tv.IsType())

	w.Sync(pkgbits.SyncExprType)
	w.pos(typ)

	if w.Bool(iface != nil && !iface.Underlying().(*types2.Interface).Empty()) {
		w.itab(tv.Type, iface)
	} else {
		w.rtype(tv.Type)

		info := w.p.typIdx(tv.Type, w.dict)
		w.Bool(info.derived)
	}
}

// isInterface reports whether typ is known to be an interface type.
// If typ is a type parameter, then isInterface reports an internal
// compiler error instead.
func isInterface(typ types2.Type) bool {
	if _, ok := types2.Unalias(typ).(*types2.TypeParam); ok {
		// typ is a type parameter and may be instantiated as either a
		// concrete or interface type, so the writer can't depend on
		// knowing this.
		base.Fatalf("%v is a type parameter", typ)
	}

	_, ok := typ.Underlying().(*types2.Interface)
	return ok
}

// isConcreteMethod reports whether typ is a concrete method. That is,
// it's a method with a receiver that isn't an interface type.
func isConcreteMethod(typ types2.Type) bool {
	sig, ok := typ.(*types2.Signature)
	return ok && sig.Recv() != nil && !isInterface(sig.Recv().Type())
}

// TODO(mark): Use isGenericMethod. It is included now to help justify
// the existence of isConcreteMethod.

// isGenericMethod reports whether typ is a generic method. That is,
// it's a method with type parameters apart from those which may or
// may not appear on the receiver type.
//
// Note that generic methods are always concrete methods.
func isGenericMethod(typ types2.Type) bool {
	sig, ok := typ.(*types2.Signature)
	return ok && sig.Recv() != nil && sig.TypeParams().Len() > 0
}

// op writes an Op into the bitstream.
func (w *writer) op(op ir.Op) {
	// TODO(mdempsky): Remove in favor of explicit codes? Would make
	// export data more stable against internal refactorings, but low
	// priority at the moment.
	assert(op != 0)
	w.Sync(pkgbits.SyncOp)
	w.Len(int(op))
}

// @@@ Package initialization

// Caution: This code is still clumsy, because toolstash -cmp is
// particularly sensitive to it.

type typeDeclGen struct {
	*syntax.TypeDecl
	gen int

	// Implicit type parameters in scope at this type declaration.
	implicits []*types2.TypeParam
}

type fileImports struct {
	importedEmbed, importedUnsafe bool
}

// declCollector is a visitor type that collects compiler-needed
// information about declarations that types2 doesn't track.
//
// Notably, it maps declared types and functions back to their
// declaration statement, keeps track of implicit type parameters, and
// assigns unique type "generation" numbers to local defined types.
type declCollector struct {
	pw         *pkgWriter
	typegen    *int
	file       *fileImports
	withinFunc bool
	implicits  []*types2.TypeParam
}

func (c *declCollector) withTParams(obj types2.Object) *declCollector {
	tparams := slices.Concat(objRecvTypeParams(obj), objTypeParams(obj))
	if len(tparams) == 0 {
		return c
	}

	copy := *c
	copy.implicits = copy.implicits[:len(copy.implicits):len(copy.implicits)]
	for _, tparam := range tparams {
		copy.implicits = append(copy.implicits, tparam)
	}
	return &copy
}

func (c *declCollector) Visit(n syntax.Node) syntax.Visitor {
	pw := c.pw

	switch n := n.(type) {
	case *syntax.File:
		pw.checkPragmas(n.Pragma, ir.GoBuildPragma, false)

	case *syntax.ImportDecl:
		pw.checkPragmas(n.Pragma, 0, false)

		switch pw.info.PkgNameOf(n).Imported().Path() {
		case "embed":
			c.file.importedEmbed = true
		case "unsafe":
			c.file.importedUnsafe = true
		}

	case *syntax.ConstDecl:
		pw.checkPragmas(n.Pragma, 0, false)

	case *syntax.FuncDecl:
		pw.checkPragmas(n.Pragma, funcPragmas, false)

		obj := pw.info.Defs[n.Name].(*types2.Func)
		pw.funDecls[obj] = n

		return c.withTParams(obj)

	case *syntax.TypeDecl:
		obj := pw.info.Defs[n.Name].(*types2.TypeName)
		d := typeDeclGen{TypeDecl: n, implicits: c.implicits}

		if n.Alias {
			pw.checkPragmas(n.Pragma, 0, false)
		} else {
			pw.checkPragmas(n.Pragma, 0, false)

			// Assign a unique ID to function-scoped defined types.
			if c.withinFunc {
				*c.typegen++
				d.gen = *c.typegen
			}
		}

		pw.typDecls[obj] = d

		// TODO(mdempsky): Omit? Not strictly necessary; only matters for
		// type declarations within function literals within parameterized
		// type declarations, but types2 the function literals will be
		// constant folded away.
		return c.withTParams(obj)

	case *syntax.VarDecl:
		pw.checkPragmas(n.Pragma, 0, true)

		if p, ok := n.Pragma.(*pragmas); ok && len(p.Embeds) > 0 {
			if err := checkEmbed(n, c.file.importedEmbed, c.withinFunc); err != nil {
				pw.errorf(p.Embeds[0].Pos, "%s", err)
			}
		}

	case *syntax.BlockStmt:
		if !c.withinFunc {
			copy := *c
			copy.withinFunc = true
			return &copy
		}
	}

	return c
}

func (pw *pkgWriter) collectDecls(noders []*noder) {
	var typegen int
	for _, p := range noders {
		var file fileImports

		syntax.Walk(p.file, &declCollector{
			pw:      pw,
			typegen: &typegen,
			file:    &file,
		})

		pw.cgoPragmas = append(pw.cgoPragmas, p.pragcgobuf...)

		for _, l := range p.linknames {
			directive := "go:linkname"
			if l.std {
				directive = "go:linknamestd"
			}
			if !file.importedUnsafe {
				pw.errorf(l.pos, "//%s only allowed in Go files that import \"unsafe\"", directive)
				continue
			}
			if strings.Contains(l.remote, "[") && strings.Contains(l.remote, "]") {
				pw.errorf(l.pos, "//%s reference of an instantiation is not allowed", directive)
				continue
			}

			switch obj := pw.curpkg.Scope().Lookup(l.local).(type) {
			case *types2.Func, *types2.Var:
				if _, ok := pw.linknames[obj]; !ok {
					pw.linknames[obj] = struct {
						remote string
						std    bool
					}{l.remote, l.std}
				} else {
					pw.errorf(l.pos, "duplicate //%s for %s", directive, l.local)
				}

			default:
				if types.AllowsGoVersion(1, 18) {
					pw.errorf(l.pos, "//%s must refer to declared function or variable", directive)
				}
			}
		}
	}
}

func (pw *pkgWriter) checkPragmas(p syntax.Pragma, allowed ir.PragmaFlag, embedOK bool) {
	if p == nil {
		return
	}
	pragma := p.(*pragmas)

	for _, pos := range pragma.Pos {
		if pos.Flag&^allowed != 0 {
			pw.errorf(pos.Pos, "misplaced compiler directive")
		}
	}

	if !embedOK {
		for _, e := range pragma.Embeds {
			pw.errorf(e.Pos, "misplaced go:embed directive")
		}
	}
}

func (w *writer) pkgInit(noders []*noder) {
	w.Len(len(w.p.cgoPragmas))
	for _, cgoPragma := range w.p.cgoPragmas {
		w.Strings(cgoPragma)
	}

	w.pkgInitOrder()

	w.Sync(pkgbits.SyncDecls)
	for _, p := range noders {
		for _, decl := range p.file.DeclList {
			w.pkgDecl(decl)
		}
	}
	w.Code(declEnd)

	w.Sync(pkgbits.SyncEOF)
}

func (w *writer) pkgInitOrder() {
	// TODO(mdempsky): Write as a function body instead?
	w.Len(len(w.p.info.InitOrder))
	for _, init := range w.p.info.InitOrder {
		w.Len(len(init.Lhs))
		for _, v := range init.Lhs {
			w.obj(v, nil)
		}
		w.expr(init.Rhs)
	}
}

func (w *writer) pkgDecl(decl syntax.Decl) {
	switch decl := decl.(type) {
	default:
		w.p.unexpected("declaration", decl)

	case *syntax.ImportDecl:

	case *syntax.ConstDecl:
		w.Code(declOther)
		w.pkgObjs(decl.NameList...)

	case *syntax.FuncDecl:
		if decl.Name.Value == "_" {
			break // skip blank functions
		}

		obj := w.p.info.Defs[decl.Name].(*types2.Func)
		sig := obj.Type().(*types2.Signature)

		if sig.RecvTypeParams() != nil || sig.TypeParams() != nil {
			break // skip generic functions
		}

		if recv := sig.Recv(); recv != nil {
			w.Code(declMethod)
			w.typ(recvBase(recv))
			w.selector(obj)
			break
		}

		w.Code(declFunc)
		w.pkgObjs(decl.Name)

	case *syntax.TypeDecl:
		if len(decl.TParamList) != 0 {
			break // skip generic type decls
		}

		if decl.Name.Value == "_" {
			break // skip blank type decls
		}

		name := w.p.info.Defs[decl.Name].(*types2.TypeName)
		// Skip type declarations for interfaces that are only usable as
		// type parameter bounds.
		if iface, ok := name.Type().Underlying().(*types2.Interface); ok && !iface.IsMethodSet() {
			break
		}

		w.Code(declOther)
		w.pkgObjs(decl.Name)

	case *syntax.VarDecl:
		w.Code(declVar)
		w.pkgObjs(decl.NameList...)

		var embeds []pragmaEmbed
		if p, ok := decl.Pragma.(*pragmas); ok {
			embeds = p.Embeds
		}
		w.Len(len(embeds))
		for _, embed := range embeds {
			w.pos(embed.Pos)
			w.Strings(embed.Patterns)
		}
	}
}

func (w *writer) pkgObjs(names ...*syntax.Name) {
	w.Sync(pkgbits.SyncDeclNames)
	w.Len(len(names))

	for _, name := range names {
		obj, ok := w.p.info.Defs[name]
		assert(ok)

		w.Sync(pkgbits.SyncDeclName)
		w.obj(obj, nil)
	}
}

// @@@ Helpers

// staticBool analyzes a boolean expression and reports whether it's
// always true (positive result), always false (negative result), or
// unknown (zero).
//
// It also simplifies the expression while preserving semantics, if
// possible.
func (pw *pkgWriter) staticBool(ep *syntax.Expr) int {
	if val := pw.typeAndValue(*ep).Value; val != nil {
		if constant.BoolVal(val) {
			return +1
		} else {
			return -1
		}
	}

	if e, ok := (*ep).(*syntax.Operation); ok {
		switch e.Op {
		case syntax.Not:
			return pw.staticBool(&e.X)

		case syntax.AndAnd:
			x := pw.staticBool(&e.X)
			if x < 0 {
				*ep = e.X
				return x
			}

			y := pw.staticBool(&e.Y)
			if x > 0 || y < 0 {
				if pw.typeAndValue(e.X).Value != nil {
					*ep = e.Y
				}
				return y
			}

		case syntax.OrOr:
			x := pw.staticBool(&e.X)
			if x > 0 {
				*ep = e.X
				return x
			}

			y := pw.staticBool(&e.Y)
			if x < 0 || y > 0 {
				if pw.typeAndValue(e.X).Value != nil {
					*ep = e.Y
				}
				return y
			}
		}
	}

	return 0
}

// hasImplicitTypeParams reports whether obj is a defined type with
// implicit type parameters (e.g., declared within a generic function
// or method).
func (pw *pkgWriter) hasImplicitTypeParams(obj *types2.TypeName) bool {
	if obj.Pkg() == pw.curpkg {
		decl, ok := pw.typDecls[obj]
		assert(ok)
		if len(decl.implicits) != 0 {
			return true
		}
	}
	return false
}

// isDefinedType reports whether obj is a defined type.
func isDefinedType(obj types2.Object) bool {
	if obj, ok := obj.(*types2.TypeName); ok {
		return !obj.IsAlias()
	}
	return false
}

// isGlobal reports whether obj was declared at package scope.
//
// Caveat: blank objects are not declared.
func isGlobal(obj types2.Object) bool {
	return obj.Parent() == obj.Pkg().Scope()
}

// lookupObj returns the object that expr refers to, if any. If expr
// is an explicit instantiation of a generic object, then the instance
// object is returned as well.
func lookupObj(p *pkgWriter, expr syntax.Expr) (obj types2.Object, inst types2.Instance) {
	if index, ok := expr.(*syntax.IndexExpr); ok {
		args := syntax.UnpackListExpr(index.Index)
		if len(args) == 1 {
			tv := p.typeAndValue(args[0])
			if tv.IsValue() {
				return // normal index expression
			}
		}

		expr = index.X
	}

	// Strip package qualifier, if present.
	if sel, ok := expr.(*syntax.SelectorExpr); ok {
		if !isPkgQual(p.info, sel) {
			return // normal selector expression
		}
		expr = sel.Sel
	}

	if name, ok := expr.(*syntax.Name); ok {
		obj = p.info.Uses[name]
		inst = p.info.Instances[name]
	}
	return
}

// isPkgQual reports whether the given selector expression is a
// package-qualified identifier.
func isPkgQual(info *types2.Info, sel *syntax.SelectorExpr) bool {
	if name, ok := sel.X.(*syntax.Name); ok {
		_, isPkgName := info.Uses[name].(*types2.PkgName)
		return isPkgName
	}
	return false
}

// isNil reports whether expr is a (possibly parenthesized) reference
// to the predeclared nil value.
func isNil(p *pkgWriter, expr syntax.Expr) bool {
	tv := p.typeAndValue(expr)
	return tv.IsNil()
}

// isBuiltin reports whether expr is a (possibly parenthesized)
// referenced to the specified built-in function.
func (pw *pkgWriter) isBuiltin(expr syntax.Expr, builtin string) bool {
	if name, ok := syntax.Unparen(expr).(*syntax.Name); ok && name.Value == builtin {
		return pw.typeAndValue(name).IsBuiltin()
	}
	return false
}

// recvBase returns the base type for the given receiver parameter.
func recvBase(recv *types2.Var) *types2.Named {
	typ := types2.Unalias(recv.Type())
	if ptr, ok := typ.(*types2.Pointer); ok {
		typ = types2.Unalias(ptr.Elem())
	}
	return typ.(*types2.Named)
}

// namesAsExpr returns a list of names as a syntax.Expr.
func namesAsExpr(names []*syntax.Name) syntax.Expr {
	if len(names) == 1 {
		return names[0]
	}

	exprs := make([]syntax.Expr, len(names))
	for i, name := range names {
		exprs[i] = name
	}
	return &syntax.ListExpr{ElemList: exprs}
}

// fieldIndex returns the index of the struct field named by key.
func fieldIndex(info *types2.Info, str *types2.Struct, key *syntax.Name) int {
	field := info.Uses[key].(*types2.Var)

	for i := 0; i < str.NumFields(); i++ {
		if str.Field(i) == field {
			return i
		}
	}

	panic(fmt.Sprintf("%s: %v is not a field of %v", key.Pos(), field, str))
}

// objRecvTypeParams returns the receiver type parameters on the given object.
func objRecvTypeParams(obj types2.Object) []*types2.TypeParam {
	if f, ok := obj.(*types2.Func); ok {
		return asTypeParamSlice(f.Signature().RecvTypeParams())
	}
	return nil
}

// objTypeParams returns the type parameters on the given object.
func objTypeParams(obj types2.Object) []*types2.TypeParam {
	switch t := obj.(type) {
	case *types2.Func:
		return asTypeParamSlice(t.Signature().TypeParams())
	case *types2.TypeName:
		switch t := obj.Type().(type) {
		case *types2.Named:
			return asTypeParamSlice(t.TypeParams())
		case *types2.Alias:
			return asTypeParamSlice(t.TypeParams())
		}
	}
	return nil
}

// asTypeParamSlice unpacks a types2.TypeParamList to a []types2.TypeParam
func asTypeParamSlice(l *types2.TypeParamList) []*types2.TypeParam {
	if l.Len() == 0 {
		return nil
	}
	s := make([]*types2.TypeParam, l.Len())
	for i := range l.Len() {
		s[i] = l.At(i)
	}
	return s
}

// splitNamed decomposes a use of a defined type into its original
// type definition and the type arguments used to instantiate it.
func splitNamed(typ *types2.Named) (*types2.TypeName, []types2.Type) {
	base.Assertf(typ.TypeParams().Len() == typ.TypeArgs().Len(), "use of uninstantiated type: %v", typ)

	orig := typ.Origin()
	base.Assertf(orig.TypeArgs() == nil, "origin %v of %v has type arguments", orig, typ)
	base.Assertf(typ.Obj() == orig.Obj(), "%v has object %v, but %v has object %v", typ, typ.Obj(), orig, orig.Obj())

	return typ.Obj(), asTypeSlice(typ.TypeArgs())
}

// splitAlias is like splitNamed, but for an alias type.
func splitAlias(typ *types2.Alias) (*types2.TypeName, []types2.Type) {
	orig := typ.Origin()
	base.Assertf(typ.Obj() == orig.Obj(), "alias type %v has object %v, but %v has object %v", typ, typ.Obj(), orig, orig.Obj())

	return typ.Obj(), asTypeSlice(typ.TypeArgs())
}

// asTypeSlice unpacks a types2.TypeList to a []types2.Type
func asTypeSlice(l *types2.TypeList) []types2.Type {
	if l.Len() == 0 {
		return nil
	}
	s := make([]types2.Type, l.Len())
	for i := range l.Len() {
		s[i] = l.At(i)
	}
	return s
}

func asPragmaFlag(p syntax.Pragma) ir.PragmaFlag {
	if p == nil {
		return 0
	}
	return p.(*pragmas).Flag
}

func asWasmImport(p syntax.Pragma) *WasmImport {
	if p == nil {
		return nil
	}
	return p.(*pragmas).WasmImport
}

func asWasmExport(p syntax.Pragma) *WasmExport {
	if p == nil {
		return nil
	}
	return p.(*pragmas).WasmExport
}

// isPtrTo reports whether from is the type *to.
func isPtrTo(from, to types2.Type) bool {
	ptr, ok := types2.Unalias(from).(*types2.Pointer)
	return ok && types2.Identical(ptr.Elem(), to)
}

// hasFallthrough reports whether stmts ends in a fallthrough
// statement.
func hasFallthrough(stmts []syntax.Stmt) bool {
	// From spec: the last non-empty statement may be a (possibly labeled) "fallthrough" statement
	// Stripping (possible nested) labeled statement if any.
	stmt := lastNonEmptyStmt(stmts)
	for {
		ls, ok := stmt.(*syntax.LabeledStmt)
		if !ok {
			break
		}
		stmt = ls.Stmt
	}
	last, ok := stmt.(*syntax.BranchStmt)
	return ok && last.Tok == syntax.Fallthrough
}

// lastNonEmptyStmt returns the last non-empty statement in list, if
// any.
func lastNonEmptyStmt(stmts []syntax.Stmt) syntax.Stmt {
	for i := len(stmts) - 1; i >= 0; i-- {
		stmt := stmts[i]
		if _, ok := stmt.(*syntax.EmptyStmt); !ok {
			return stmt
		}
	}
	return nil
}

// terminates reports whether stmt terminates normal control flow
// (i.e., does not merely advance to the following statement).
func (pw *pkgWriter) terminates(stmt syntax.Stmt) bool {
	switch stmt := stmt.(type) {
	case *syntax.BranchStmt:
		if stmt.Tok == syntax.Goto {
			return true
		}
	case *syntax.ReturnStmt:
		return true
	case *syntax.ExprStmt:
		if call, ok := syntax.Unparen(stmt.X).(*syntax.CallExpr); ok {
			if pw.isBuiltin(call.Fun, "panic") {
				return true
			}
		}

		// The handling of BlockStmt here is approximate, but it serves to
		// allow dead-code elimination for:
		//
		//	if true {
		//		return x
		//	}
		//	unreachable
	case *syntax.IfStmt:
		cond := pw.staticBool(&stmt.Cond)
		return (cond < 0 || pw.terminates(stmt.Then)) && (cond > 0 || pw.terminates(stmt.Else))
	case *syntax.BlockStmt:
		return pw.terminates(lastNonEmptyStmt(stmt.List))
	}

	return false
}
