// 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)]
		if !ok {
			base.Fatalf("%v not in pw.typDecls", obj.(*types2.TypeName))
		}
		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:
		if base.Flag.LowerH > 0 {
			// Unified IR panics are the worst; this is a huge help in debugging them.
			defer func() {
				if p := recover(); p != nil {
					fmt.Printf("Intercepted unified IR writer panic for function %s, repanicking", obj.FullName())
					panic(p)
				}
			}()
		}
		decl, ok := w.p.funDecls[obj]
		assert(ok)
		sig := obj.Type().(*types2.Signature)

		w.pos(obj)
		if isGenericMethod(sig) {
			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)
		}
		if len(gmethods) > 0 {
			assert(w.Version().Has(pkgbits.GenericMethods))
		}
		// 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 := types2.Unalias(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
}
