Help us shape the future of Go! Take the 2026 Go Developer Survey

Source file src/cmd/compile/internal/noder/writer.go

     1  // Copyright 2021 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package noder
     6  
     7  import (
     8  	"fmt"
     9  	"go/constant"
    10  	"go/token"
    11  	"go/version"
    12  	"internal/buildcfg"
    13  	"internal/pkgbits"
    14  	"log"
    15  	"os"
    16  	"slices"
    17  	"strings"
    18  
    19  	"cmd/compile/internal/base"
    20  	"cmd/compile/internal/ir"
    21  	"cmd/compile/internal/syntax"
    22  	"cmd/compile/internal/types"
    23  	"cmd/compile/internal/types2"
    24  )
    25  
    26  // This file implements the Unified IR package writer and defines the
    27  // Unified IR export data format.
    28  //
    29  // Low-level coding details (e.g., byte-encoding of individual
    30  // primitive values, or handling element bitstreams and
    31  // cross-references) are handled by internal/pkgbits, so here we only
    32  // concern ourselves with higher-level worries like mapping Go
    33  // language constructs into elements.
    34  
    35  // There are two central types in the writing process: the "writer"
    36  // type handles writing out individual elements, while the "pkgWriter"
    37  // type keeps track of which elements have already been created.
    38  //
    39  // For each sort of "thing" (e.g., position, package, object, type)
    40  // that can be written into the export data, there are generally
    41  // several methods that work together:
    42  //
    43  // - writer.thing handles writing out a *use* of a thing, which often
    44  //   means writing a relocation to that thing's encoded index.
    45  //
    46  // - pkgWriter.thingIdx handles reserving an index for a thing, and
    47  //   writing out any elements needed for the thing.
    48  //
    49  // - writer.doThing handles writing out the *definition* of a thing,
    50  //   which in general is a mix of low-level coding primitives (e.g.,
    51  //   ints and strings) or uses of other things.
    52  //
    53  // A design goal of Unified IR is to have a single, canonical writer
    54  // implementation, but multiple reader implementations each tailored
    55  // to their respective needs. For example, within cmd/compile's own
    56  // backend, inlining is implemented largely by just re-running the
    57  // function body reading code.
    58  
    59  // TODO(mdempsky): Add an importer for Unified IR to the x/tools repo,
    60  // and better document the file format boundary between public and
    61  // private data.
    62  
    63  type index = pkgbits.Index
    64  
    65  func assert(p bool) { base.Assert(p) }
    66  
    67  // A pkgWriter constructs Unified IR export data from the results of
    68  // running the types2 type checker on a Go compilation unit.
    69  type pkgWriter struct {
    70  	pkgbits.PkgEncoder
    71  
    72  	m                     posMap
    73  	curpkg                *types2.Package
    74  	info                  *types2.Info
    75  	rangeFuncBodyClosures map[*syntax.FuncLit]bool // non-public information, e.g., which functions are closures range function bodies?
    76  
    77  	// Indices for previously written syntax and types2 things.
    78  
    79  	posBasesIdx map[*syntax.PosBase]index
    80  	pkgsIdx     map[*types2.Package]index
    81  	typsIdx     map[types2.Type]index
    82  	objsIdx     map[types2.Object]index
    83  
    84  	// Maps from types2.Objects back to their syntax.Decl.
    85  
    86  	funDecls  map[*types2.Func]*syntax.FuncDecl
    87  	typDecls  map[*types2.TypeName]typeDeclGen
    88  	methodIdx map[*types2.Func]int // method declaration order, for x/tools decoder (#81188)
    89  
    90  	// linknames maps package-scope objects to their linker symbol name,
    91  	// if specified by a //go:linkname or //go:linknamestd directive.
    92  	linknames map[types2.Object]struct {
    93  		remote string
    94  		std    bool
    95  	}
    96  
    97  	// cgoPragmas accumulates any //go:cgo_* pragmas that need to be
    98  	// passed through to cmd/link.
    99  	cgoPragmas [][]string
   100  }
   101  
   102  // newPkgWriter returns an initialized pkgWriter for the specified
   103  // package.
   104  func newPkgWriter(m posMap, pkg *types2.Package, info *types2.Info, otherInfo map[*syntax.FuncLit]bool) *pkgWriter {
   105  	return &pkgWriter{
   106  		PkgEncoder: pkgbits.NewPkgEncoder(uirVersion, base.Debug.SyncFrames),
   107  
   108  		m:                     m,
   109  		curpkg:                pkg,
   110  		info:                  info,
   111  		rangeFuncBodyClosures: otherInfo,
   112  
   113  		pkgsIdx: make(map[*types2.Package]index),
   114  		objsIdx: make(map[types2.Object]index),
   115  		typsIdx: make(map[types2.Type]index),
   116  
   117  		posBasesIdx: make(map[*syntax.PosBase]index),
   118  
   119  		funDecls:  make(map[*types2.Func]*syntax.FuncDecl),
   120  		typDecls:  make(map[*types2.TypeName]typeDeclGen),
   121  		methodIdx: make(map[*types2.Func]int),
   122  
   123  		linknames: make(map[types2.Object]struct {
   124  			remote string
   125  			std    bool
   126  		}),
   127  	}
   128  }
   129  
   130  // errorf reports a user error about thing p.
   131  func (pw *pkgWriter) errorf(p poser, msg string, args ...any) {
   132  	base.ErrorfAt(pw.m.pos(p), 0, msg, args...)
   133  }
   134  
   135  // fatalf reports an internal compiler error about thing p.
   136  func (pw *pkgWriter) fatalf(p poser, msg string, args ...any) {
   137  	base.FatalfAt(pw.m.pos(p), msg, args...)
   138  }
   139  
   140  // unexpected reports a fatal error about a thing of unexpected
   141  // dynamic type.
   142  func (pw *pkgWriter) unexpected(what string, p poser) {
   143  	pw.fatalf(p, "unexpected %s: %v (%T)", what, p, p)
   144  }
   145  
   146  func (pw *pkgWriter) typeAndValue(x syntax.Expr) syntax.TypeAndValue {
   147  	tv, ok := pw.maybeTypeAndValue(x)
   148  	if !ok {
   149  		pw.fatalf(x, "missing Types entry: %v", syntax.String(x))
   150  	}
   151  	return tv
   152  }
   153  
   154  func (pw *pkgWriter) maybeTypeAndValue(x syntax.Expr) (syntax.TypeAndValue, bool) {
   155  	tv := x.GetTypeInfo()
   156  
   157  	// If x is a generic function whose type arguments are inferred
   158  	// from assignment context, then we need to find its inferred type
   159  	// in Info.Instances instead.
   160  	if name, ok := x.(*syntax.Name); ok {
   161  		if inst, ok := pw.info.Instances[name]; ok {
   162  			tv.Type = inst.Type
   163  		}
   164  	}
   165  
   166  	return tv, tv.Type != nil
   167  }
   168  
   169  // typeOf returns the Type of the given value expression.
   170  func (pw *pkgWriter) typeOf(expr syntax.Expr) types2.Type {
   171  	tv := pw.typeAndValue(expr)
   172  	if !tv.IsValue() {
   173  		pw.fatalf(expr, "expected value: %v", syntax.String(expr))
   174  	}
   175  	return tv.Type
   176  }
   177  
   178  // A writer provides APIs for writing out an individual element.
   179  type writer struct {
   180  	p *pkgWriter
   181  
   182  	*pkgbits.Encoder
   183  
   184  	// sig holds the signature for the current function body, if any.
   185  	sig *types2.Signature
   186  
   187  	// TODO(mdempsky): We should be able to prune localsIdx whenever a
   188  	// scope closes, and then maybe we can just use the same map for
   189  	// storing the TypeParams too (as their TypeName instead).
   190  
   191  	// localsIdx tracks any local variables declared within this
   192  	// function body. It's unused for writing out non-body things.
   193  	localsIdx map[*types2.Var]int
   194  
   195  	// closureVars tracks any free variables that are referenced by this
   196  	// function body. It's unused for writing out non-body things.
   197  	closureVars    []posVar
   198  	closureVarsIdx map[*types2.Var]int // index of previously seen free variables
   199  
   200  	dict *writerDict
   201  
   202  	// derived tracks whether the type being written out references any
   203  	// type parameters. It's unused for writing non-type things.
   204  	derived bool
   205  }
   206  
   207  // A writerDict tracks types and objects that are used by a declaration.
   208  type writerDict struct {
   209  	// implicits contains type parameters from enclosing declarations.
   210  	implicits []*types2.TypeParam
   211  	// receivers contains receiver type parameters of the declaration.
   212  	receivers []*types2.TypeParam
   213  
   214  	// derived is a slice of type indices for computing derived types
   215  	// (i.e., types that depend on the declaration's type parameters).
   216  	derived []derivedInfo
   217  
   218  	// derivedIdx maps a Type to its corresponding index within the
   219  	// derived slice, if present.
   220  	derivedIdx map[types2.Type]index
   221  
   222  	// These slices correspond to entries in the runtime dictionary.
   223  	typeParamMethodExprs []writerMethodExprInfo
   224  	subdicts             []objInfo
   225  	rtypes               []typeInfo
   226  	itabs                []itabInfo
   227  }
   228  
   229  type itabInfo struct {
   230  	typ   typeInfo
   231  	iface typeInfo
   232  }
   233  
   234  // typeParamIndex returns the index of the given type parameter within
   235  // the dictionary. This may differ from typ.Index() when there are
   236  // implicit or receiver type parameters.
   237  func (dict *writerDict) typeParamIndex(typ *types2.TypeParam) int {
   238  	for idx, implicit := range dict.implicits {
   239  		if implicit == typ {
   240  			return idx
   241  		}
   242  	}
   243  
   244  	for idx, receiver := range dict.receivers {
   245  		if receiver == typ {
   246  			return len(dict.implicits) + idx
   247  		}
   248  	}
   249  
   250  	return len(dict.implicits) + len(dict.receivers) + typ.Index()
   251  }
   252  
   253  // A derivedInfo represents a reference to an encoded generic Go type.
   254  type derivedInfo struct {
   255  	idx index
   256  }
   257  
   258  // A typeInfo represents a reference to an encoded Go type.
   259  //
   260  // If derived is true, then the typeInfo represents a generic Go type
   261  // that contains type parameters. In this case, idx is an index into
   262  // the readerDict.derived{,Types} arrays.
   263  //
   264  // Otherwise, the typeInfo represents a non-generic Go type, and idx
   265  // is an index into the reader.typs array instead.
   266  type typeInfo struct {
   267  	idx     index
   268  	derived bool
   269  }
   270  
   271  // An objInfo represents a reference to an encoded, instantiated (if
   272  // applicable) Go object.
   273  type objInfo struct {
   274  	idx       index      // index for the generic function declaration
   275  	explicits []typeInfo // info for the type arguments
   276  }
   277  
   278  // A selectorInfo represents a reference to an encoded field or method
   279  // name (i.e., objects that can only be accessed using selector
   280  // expressions).
   281  type selectorInfo struct {
   282  	pkgIdx  index
   283  	nameIdx index
   284  }
   285  
   286  // anyDerived reports whether any of info's explicit type arguments
   287  // are derived types.
   288  func (info objInfo) anyDerived() bool {
   289  	for _, explicit := range info.explicits {
   290  		if explicit.derived {
   291  			return true
   292  		}
   293  	}
   294  	return false
   295  }
   296  
   297  // equals reports whether info and other represent the same Go object
   298  // (i.e., same base object and identical type arguments, if any).
   299  func (info objInfo) equals(other objInfo) bool {
   300  	if info.idx != other.idx {
   301  		return false
   302  	}
   303  	assert(len(info.explicits) == len(other.explicits))
   304  	for i, targ := range info.explicits {
   305  		if targ != other.explicits[i] {
   306  			return false
   307  		}
   308  	}
   309  	return true
   310  }
   311  
   312  type writerMethodExprInfo struct {
   313  	typeParamIdx int
   314  	methodInfo   selectorInfo
   315  }
   316  
   317  // typeParamMethodExprIdx returns the index where the given encoded
   318  // method expression function pointer appears within this dictionary's
   319  // type parameters method expressions section, adding it if necessary.
   320  func (dict *writerDict) typeParamMethodExprIdx(typeParamIdx int, methodInfo selectorInfo) int {
   321  	newInfo := writerMethodExprInfo{typeParamIdx, methodInfo}
   322  
   323  	for idx, oldInfo := range dict.typeParamMethodExprs {
   324  		if oldInfo == newInfo {
   325  			return idx
   326  		}
   327  	}
   328  
   329  	idx := len(dict.typeParamMethodExprs)
   330  	dict.typeParamMethodExprs = append(dict.typeParamMethodExprs, newInfo)
   331  	return idx
   332  }
   333  
   334  // subdictIdx returns the index where the given encoded object's
   335  // runtime dictionary appears within this dictionary's subdictionary
   336  // section, adding it if necessary.
   337  func (dict *writerDict) subdictIdx(newInfo objInfo) int {
   338  	for idx, oldInfo := range dict.subdicts {
   339  		if oldInfo.equals(newInfo) {
   340  			return idx
   341  		}
   342  	}
   343  
   344  	idx := len(dict.subdicts)
   345  	dict.subdicts = append(dict.subdicts, newInfo)
   346  	return idx
   347  }
   348  
   349  // rtypeIdx returns the index where the given encoded type's
   350  // *runtime._type value appears within this dictionary's rtypes
   351  // section, adding it if necessary.
   352  func (dict *writerDict) rtypeIdx(newInfo typeInfo) int {
   353  	for idx, oldInfo := range dict.rtypes {
   354  		if oldInfo == newInfo {
   355  			return idx
   356  		}
   357  	}
   358  
   359  	idx := len(dict.rtypes)
   360  	dict.rtypes = append(dict.rtypes, newInfo)
   361  	return idx
   362  }
   363  
   364  // itabIdx returns the index where the given encoded type pair's
   365  // *runtime.itab value appears within this dictionary's itabs section,
   366  // adding it if necessary.
   367  func (dict *writerDict) itabIdx(typInfo, ifaceInfo typeInfo) int {
   368  	newInfo := itabInfo{typInfo, ifaceInfo}
   369  
   370  	for idx, oldInfo := range dict.itabs {
   371  		if oldInfo == newInfo {
   372  			return idx
   373  		}
   374  	}
   375  
   376  	idx := len(dict.itabs)
   377  	dict.itabs = append(dict.itabs, newInfo)
   378  	return idx
   379  }
   380  
   381  func (pw *pkgWriter) newWriter(k pkgbits.SectionKind, marker pkgbits.SyncMarker) *writer {
   382  	return &writer{
   383  		Encoder: pw.NewEncoder(k, marker),
   384  		p:       pw,
   385  	}
   386  }
   387  
   388  // @@@ Positions
   389  
   390  // pos writes the position of p into the element bitstream.
   391  func (w *writer) pos(p poser) {
   392  	w.Sync(pkgbits.SyncPos)
   393  	pos := p.Pos()
   394  
   395  	// TODO(mdempsky): Track down the remaining cases here and fix them.
   396  	if !w.Bool(pos.IsKnown()) {
   397  		return
   398  	}
   399  
   400  	// TODO(mdempsky): Delta encoding.
   401  	w.posBase(pos.Base())
   402  	w.Uint(pos.Line())
   403  	w.Uint(pos.Col())
   404  }
   405  
   406  // posBase writes a reference to the given PosBase into the element
   407  // bitstream.
   408  func (w *writer) posBase(b *syntax.PosBase) {
   409  	w.Reloc(pkgbits.SectionPosBase, w.p.posBaseIdx(b))
   410  }
   411  
   412  // posBaseIdx returns the index for the given PosBase.
   413  func (pw *pkgWriter) posBaseIdx(b *syntax.PosBase) index {
   414  	if idx, ok := pw.posBasesIdx[b]; ok {
   415  		return idx
   416  	}
   417  
   418  	w := pw.newWriter(pkgbits.SectionPosBase, pkgbits.SyncPosBase)
   419  	w.p.posBasesIdx[b] = w.Idx
   420  
   421  	w.String(trimFilename(b))
   422  
   423  	if !w.Bool(b.IsFileBase()) {
   424  		w.pos(b)
   425  		w.Uint(b.Line())
   426  		w.Uint(b.Col())
   427  	}
   428  
   429  	return w.Flush()
   430  }
   431  
   432  // @@@ Packages
   433  
   434  // pkg writes a use of the given Package into the element bitstream.
   435  func (w *writer) pkg(pkg *types2.Package) {
   436  	w.pkgRef(w.p.pkgIdx(pkg))
   437  }
   438  
   439  func (w *writer) pkgRef(idx index) {
   440  	w.Sync(pkgbits.SyncPkg)
   441  	w.Reloc(pkgbits.SectionPkg, idx)
   442  }
   443  
   444  // pkgIdx returns the index for the given package, adding it to the
   445  // package export data if needed.
   446  func (pw *pkgWriter) pkgIdx(pkg *types2.Package) index {
   447  	if idx, ok := pw.pkgsIdx[pkg]; ok {
   448  		return idx
   449  	}
   450  
   451  	w := pw.newWriter(pkgbits.SectionPkg, pkgbits.SyncPkgDef)
   452  	pw.pkgsIdx[pkg] = w.Idx
   453  
   454  	// The universe and package unsafe need to be handled specially by
   455  	// importers anyway, so we serialize them using just their package
   456  	// path. This ensures that readers don't confuse them for
   457  	// user-defined packages.
   458  	switch pkg {
   459  	case nil: // universe
   460  		w.String("builtin") // same package path used by godoc
   461  	case types2.Unsafe:
   462  		w.String("unsafe")
   463  	default:
   464  		// TODO(mdempsky): Write out pkg.Path() for curpkg too.
   465  		var path string
   466  		if pkg != w.p.curpkg {
   467  			path = pkg.Path()
   468  		}
   469  		base.Assertf(path != "builtin" && path != "unsafe", "unexpected path for user-defined package: %q", path)
   470  		w.String(path)
   471  		w.String(pkg.Name())
   472  
   473  		w.Len(len(pkg.Imports()))
   474  		for _, imp := range pkg.Imports() {
   475  			w.pkg(imp)
   476  		}
   477  	}
   478  
   479  	return w.Flush()
   480  }
   481  
   482  // @@@ Types
   483  
   484  var (
   485  	anyTypeName        = types2.Universe.Lookup("any").(*types2.TypeName)
   486  	comparableTypeName = types2.Universe.Lookup("comparable").(*types2.TypeName)
   487  	runeTypeName       = types2.Universe.Lookup("rune").(*types2.TypeName)
   488  )
   489  
   490  // typ writes a use of the given type into the bitstream.
   491  func (w *writer) typ(typ types2.Type) {
   492  	w.typInfo(w.p.typIdx(typ, w.dict))
   493  }
   494  
   495  // typInfo writes a use of the given type (specified as a typeInfo
   496  // instead) into the bitstream.
   497  func (w *writer) typInfo(info typeInfo) {
   498  	w.Sync(pkgbits.SyncType)
   499  	if w.Bool(info.derived) {
   500  		w.Len(int(info.idx))
   501  		w.derived = true
   502  	} else {
   503  		w.Reloc(pkgbits.SectionType, info.idx)
   504  	}
   505  }
   506  
   507  // typIdx returns the index where the export data description of type
   508  // can be read back in. If no such index exists yet, it's created.
   509  //
   510  // typIdx also reports whether typ is a derived type; that is, whether
   511  // its identity depends on type parameters.
   512  func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo {
   513  	// Strip non-global aliases, because they only appear in inline
   514  	// bodies anyway. Otherwise, they can cause types.Sym collisions
   515  	// (e.g., "main.C" for both of the local type aliases in
   516  	// test/fixedbugs/issue50190.go).
   517  	for {
   518  		if alias, ok := typ.(*types2.Alias); ok && !isGlobal(alias.Obj()) {
   519  			typ = alias.Rhs()
   520  		} else {
   521  			break
   522  		}
   523  	}
   524  
   525  	if idx, ok := pw.typsIdx[typ]; ok {
   526  		return typeInfo{idx: idx, derived: false}
   527  	}
   528  	if dict != nil {
   529  		if idx, ok := dict.derivedIdx[typ]; ok {
   530  			return typeInfo{idx: idx, derived: true}
   531  		}
   532  	}
   533  
   534  	w := pw.newWriter(pkgbits.SectionType, pkgbits.SyncTypeIdx)
   535  	w.dict = dict
   536  
   537  	switch typ := typ.(type) {
   538  	default:
   539  		base.Fatalf("unexpected type: %v (%T)", typ, typ)
   540  
   541  	case *types2.Basic:
   542  		switch kind := typ.Kind(); {
   543  		case kind == types2.Invalid:
   544  			base.Fatalf("unexpected types2.Invalid")
   545  
   546  		case types2.Typ[kind] == typ:
   547  			w.Code(pkgbits.TypeBasic)
   548  			w.Len(int(kind))
   549  
   550  		default:
   551  			// Handle "byte" and "rune" as references to their TypeNames.
   552  			obj := types2.Universe.Lookup(typ.Name()).(*types2.TypeName)
   553  			assert(obj.Type() == typ)
   554  
   555  			w.Code(pkgbits.TypeNamed)
   556  			w.namedType(obj, nil)
   557  		}
   558  
   559  	case *types2.Named:
   560  		w.Code(pkgbits.TypeNamed)
   561  		w.namedType(splitNamed(typ))
   562  
   563  	case *types2.Alias:
   564  		w.Code(pkgbits.TypeNamed)
   565  		w.namedType(splitAlias(typ))
   566  
   567  	case *types2.TypeParam:
   568  		w.derived = true
   569  		w.Code(pkgbits.TypeTypeParam)
   570  		w.Len(w.dict.typeParamIndex(typ))
   571  
   572  	case *types2.Array:
   573  		w.Code(pkgbits.TypeArray)
   574  		w.Uint64(uint64(typ.Len()))
   575  		w.typ(typ.Elem())
   576  
   577  	case *types2.Chan:
   578  		w.Code(pkgbits.TypeChan)
   579  		w.Len(int(typ.Dir()))
   580  		w.typ(typ.Elem())
   581  
   582  	case *types2.Map:
   583  		w.Code(pkgbits.TypeMap)
   584  		w.typ(typ.Key())
   585  		w.typ(typ.Elem())
   586  
   587  	case *types2.Pointer:
   588  		w.Code(pkgbits.TypePointer)
   589  		w.typ(typ.Elem())
   590  
   591  	case *types2.Signature:
   592  		base.Assertf(typ.TypeParams() == nil, "unexpected type params: %v", typ)
   593  		w.Code(pkgbits.TypeSignature)
   594  		w.signature(typ)
   595  
   596  	case *types2.Slice:
   597  		w.Code(pkgbits.TypeSlice)
   598  		w.typ(typ.Elem())
   599  
   600  	case *types2.Struct:
   601  		w.Code(pkgbits.TypeStruct)
   602  		w.structType(typ)
   603  
   604  	case *types2.Interface:
   605  		// Handle "any" as reference to its TypeName.
   606  		// The underlying "any" interface is canonical, so this logic handles both
   607  		// GODEBUG=gotypesalias=1 (when any is represented as a types2.Alias), and
   608  		// gotypesalias=0.
   609  		if types2.Unalias(typ) == types2.Unalias(anyTypeName.Type()) {
   610  			w.Code(pkgbits.TypeNamed)
   611  			w.obj(anyTypeName, nil)
   612  			break
   613  		}
   614  
   615  		w.Code(pkgbits.TypeInterface)
   616  		w.interfaceType(typ)
   617  
   618  	case *types2.Union:
   619  		w.Code(pkgbits.TypeUnion)
   620  		w.unionType(typ)
   621  	}
   622  
   623  	if w.derived {
   624  		idx := index(len(dict.derived))
   625  		dict.derived = append(dict.derived, derivedInfo{idx: w.Flush()})
   626  		dict.derivedIdx[typ] = idx
   627  		return typeInfo{idx: idx, derived: true}
   628  	}
   629  
   630  	pw.typsIdx[typ] = w.Idx
   631  	return typeInfo{idx: w.Flush(), derived: false}
   632  }
   633  
   634  // namedType writes a use of the given named type into the bitstream.
   635  func (w *writer) namedType(obj *types2.TypeName, targs []types2.Type) {
   636  	// Named types that are declared within a generic function (and
   637  	// thus have implicit type parameters) are always derived types.
   638  	if w.p.hasImplicitTypeParams(obj) {
   639  		w.derived = true
   640  	}
   641  
   642  	w.obj(obj, targs)
   643  }
   644  
   645  func (w *writer) structType(typ *types2.Struct) {
   646  	w.Len(typ.NumFields())
   647  	for i := 0; i < typ.NumFields(); i++ {
   648  		f := typ.Field(i)
   649  		w.pos(f)
   650  		w.selector(f)
   651  		w.typ(f.Type())
   652  		w.String(typ.Tag(i))
   653  		w.Bool(f.Embedded())
   654  	}
   655  }
   656  
   657  func (w *writer) unionType(typ *types2.Union) {
   658  	w.Len(typ.Len())
   659  	for i := 0; i < typ.Len(); i++ {
   660  		t := typ.Term(i)
   661  		w.Bool(t.Tilde())
   662  		w.typ(t.Type())
   663  	}
   664  }
   665  
   666  func (w *writer) interfaceType(typ *types2.Interface) {
   667  	// If typ has no embedded types but it's not a basic interface, then
   668  	// the natural description we write out below will fail to
   669  	// reconstruct it.
   670  	if typ.NumEmbeddeds() == 0 && !typ.IsMethodSet() {
   671  		// Currently, this can only happen for the underlying Interface of
   672  		// "comparable", which is needed to handle type declarations like
   673  		// "type C comparable".
   674  		assert(typ == comparableTypeName.Type().(*types2.Named).Underlying())
   675  
   676  		// Export as "interface{ comparable }".
   677  		w.Len(0)                         // NumExplicitMethods
   678  		w.Len(1)                         // NumEmbeddeds
   679  		w.Bool(false)                    // IsImplicit
   680  		w.typ(comparableTypeName.Type()) // EmbeddedType(0)
   681  		return
   682  	}
   683  
   684  	w.Len(typ.NumExplicitMethods())
   685  	w.Len(typ.NumEmbeddeds())
   686  
   687  	if typ.NumExplicitMethods() == 0 && typ.NumEmbeddeds() == 1 {
   688  		w.Bool(typ.IsImplicit())
   689  	} else {
   690  		// Implicit interfaces always have 0 explicit methods and 1
   691  		// embedded type, so we skip writing out the implicit flag
   692  		// otherwise as a space optimization.
   693  		assert(!typ.IsImplicit())
   694  	}
   695  
   696  	for i := 0; i < typ.NumExplicitMethods(); i++ {
   697  		m := typ.ExplicitMethod(i)
   698  		sig := m.Type().(*types2.Signature)
   699  		assert(sig.TypeParams() == nil)
   700  
   701  		w.pos(m)
   702  		w.selector(m)
   703  		w.signature(sig)
   704  	}
   705  
   706  	for i := 0; i < typ.NumEmbeddeds(); i++ {
   707  		w.typ(typ.EmbeddedType(i))
   708  	}
   709  }
   710  
   711  func (w *writer) signature(sig *types2.Signature) {
   712  	w.Sync(pkgbits.SyncSignature)
   713  	w.params(sig.Params())
   714  	w.params(sig.Results())
   715  	w.Bool(sig.Variadic())
   716  }
   717  
   718  func (w *writer) params(typ *types2.Tuple) {
   719  	w.Sync(pkgbits.SyncParams)
   720  	w.Len(typ.Len())
   721  	for i := 0; i < typ.Len(); i++ {
   722  		w.param(typ.At(i))
   723  	}
   724  }
   725  
   726  func (w *writer) param(param *types2.Var) {
   727  	w.Sync(pkgbits.SyncParam)
   728  	w.pos(param)
   729  	w.localIdent(param)
   730  	w.typ(param.Type())
   731  }
   732  
   733  // @@@ Objects
   734  
   735  // obj writes a use of the given object into the bitstream.
   736  //
   737  // If obj is a generic object, then explicits are the explicit type
   738  // arguments used to instantiate it (i.e., used to substitute the
   739  // object's own declared type parameters).
   740  func (w *writer) obj(obj types2.Object, explicits []types2.Type) {
   741  	w.objInfo(w.p.objInstIdx(obj, explicits, w.dict))
   742  }
   743  
   744  // objInfo writes a use of the given encoded object into the
   745  // bitstream.
   746  func (w *writer) objInfo(info objInfo) {
   747  	w.Sync(pkgbits.SyncObject)
   748  	if w.Version().Has(pkgbits.DerivedFuncInstance) {
   749  		w.Bool(false)
   750  	}
   751  	w.Reloc(pkgbits.SectionObj, info.idx)
   752  
   753  	w.Len(len(info.explicits))
   754  	for _, info := range info.explicits {
   755  		w.typInfo(info)
   756  	}
   757  }
   758  
   759  // objInstIdx returns the indices for an object and a corresponding
   760  // list of type arguments used to instantiate it, adding them to the
   761  // export data as needed.
   762  func (pw *pkgWriter) objInstIdx(obj types2.Object, explicits []types2.Type, dict *writerDict) objInfo {
   763  	explicitInfos := make([]typeInfo, len(explicits))
   764  	for i := range explicitInfos {
   765  		explicitInfos[i] = pw.typIdx(explicits[i], dict)
   766  	}
   767  	return objInfo{idx: pw.objIdx(obj), explicits: explicitInfos}
   768  }
   769  
   770  // objIdx returns the index for the given Object, adding it to the
   771  // export data as needed.
   772  func (pw *pkgWriter) objIdx(obj types2.Object) index {
   773  	// TODO(mdempsky): Validate that obj is a global object (or a local
   774  	// defined type, which we hoist to global scope anyway).
   775  
   776  	if idx, ok := pw.objsIdx[obj]; ok {
   777  		return idx
   778  	}
   779  
   780  	dict := &writerDict{
   781  		derivedIdx: make(map[types2.Type]index),
   782  	}
   783  
   784  	if isDefinedType(obj) && obj.Pkg() == pw.curpkg {
   785  		decl, ok := pw.typDecls[obj.(*types2.TypeName)]
   786  		if !ok {
   787  			base.Fatalf("%v not in pw.typDecls", obj.(*types2.TypeName))
   788  		}
   789  		dict.implicits = decl.implicits
   790  	}
   791  
   792  	if isGenericMethod(obj.Type()) {
   793  		dict.receivers = asTypeParamSlice(obj.Type().(*types2.Signature).RecvTypeParams())
   794  	}
   795  
   796  	// We encode objects into 4 elements across different sections, all
   797  	// sharing the same index:
   798  	//
   799  	// - RelocName has just the object's qualified name (i.e.,
   800  	//   Object.Pkg and Object.Name) and the CodeObj indicating what
   801  	//   specific type of Object it is (Var, Func, etc).
   802  	//
   803  	// - RelocObj has the remaining public details about the object,
   804  	//   relevant to go/types importers.
   805  	//
   806  	// - RelocObjExt has additional private details about the object,
   807  	//   which are only relevant to cmd/compile itself. This is
   808  	//   separated from RelocObj so that go/types importers are
   809  	//   unaffected by internal compiler changes.
   810  	//
   811  	// - RelocObjDict has public details about the object's type
   812  	//   parameters and derived type's used by the object. This is
   813  	//   separated to facilitate the eventual introduction of
   814  	//   shape-based stenciling.
   815  	//
   816  	// TODO(mdempsky): Re-evaluate whether RelocName still makes sense
   817  	// to keep separate from RelocObj.
   818  
   819  	w := pw.newWriter(pkgbits.SectionObj, pkgbits.SyncObject1)
   820  	wext := pw.newWriter(pkgbits.SectionObjExt, pkgbits.SyncObject1)
   821  	wname := pw.newWriter(pkgbits.SectionName, pkgbits.SyncObject1)
   822  	wdict := pw.newWriter(pkgbits.SectionObjDict, pkgbits.SyncObject1)
   823  
   824  	pw.objsIdx[obj] = w.Idx // break cycles
   825  	assert(wext.Idx == w.Idx)
   826  	assert(wname.Idx == w.Idx)
   827  	assert(wdict.Idx == w.Idx)
   828  
   829  	w.dict = dict
   830  	wext.dict = dict
   831  
   832  	code := w.doObj(wext, obj)
   833  	w.Flush()
   834  	wext.Flush()
   835  
   836  	wname.qualifiedIdent(obj)
   837  	wname.Code(code)
   838  	wname.Flush()
   839  
   840  	wdict.objDict(obj, w.dict)
   841  	wdict.Flush()
   842  
   843  	return w.Idx
   844  }
   845  
   846  // doObj writes the RelocObj definition for obj to w, and the
   847  // RelocObjExt definition to wext.
   848  func (w *writer) doObj(wext *writer, obj types2.Object) pkgbits.CodeObj {
   849  	if obj.Pkg() != w.p.curpkg {
   850  		return pkgbits.ObjStub
   851  	}
   852  
   853  	switch obj := obj.(type) {
   854  	default:
   855  		w.p.unexpected("object", obj)
   856  		panic("unreachable")
   857  
   858  	case *types2.Const:
   859  		w.pos(obj)
   860  		w.typ(obj.Type())
   861  		w.Value(obj.Val())
   862  		return pkgbits.ObjConst
   863  
   864  	case *types2.Func:
   865  		if base.Flag.LowerH > 0 {
   866  			// Unified IR panics are the worst; this is a huge help in debugging them.
   867  			defer func() {
   868  				if p := recover(); p != nil {
   869  					log.Printf("Intercepted unified IR writer panic for function %s, repanicking", obj.FullName())
   870  					panic(p)
   871  				}
   872  			}()
   873  		}
   874  		decl, ok := w.p.funDecls[obj]
   875  		assert(ok)
   876  		sig := obj.Type().(*types2.Signature)
   877  
   878  		w.pos(obj)
   879  		if isGenericMethod(sig) {
   880  			w.Bool(true) // generic method
   881  
   882  			w.selector(obj)
   883  			w.typeParamNames(sig.RecvTypeParams())
   884  			w.param(sig.Recv())
   885  			if w.Version().Has(pkgbits.PreserveMethodOrder) {
   886  				w.Len(w.p.methodIdx[obj.Origin()])
   887  			}
   888  		} else {
   889  			if w.Version().Has(pkgbits.GenericMethods) {
   890  				w.Bool(false) // function
   891  			}
   892  		}
   893  		w.typeParamNames(sig.TypeParams())
   894  		w.signature(sig)
   895  		w.pos(decl)
   896  		wext.funcExt(obj)
   897  		return pkgbits.ObjFunc
   898  
   899  	case *types2.TypeName:
   900  		if obj.IsAlias() {
   901  			w.pos(obj)
   902  			rhs := obj.Type()
   903  			var tparams *types2.TypeParamList
   904  			if alias, ok := rhs.(*types2.Alias); ok { // materialized alias
   905  				assert(alias.TypeArgs() == nil)
   906  				tparams = alias.TypeParams()
   907  				rhs = alias.Rhs()
   908  			}
   909  			if w.Version().Has(pkgbits.AliasTypeParamNames) {
   910  				w.typeParamNames(tparams)
   911  			}
   912  			assert(w.Version().Has(pkgbits.AliasTypeParamNames) || tparams.Len() == 0)
   913  			w.typ(rhs)
   914  			return pkgbits.ObjAlias
   915  		}
   916  
   917  		named := obj.Type().(*types2.Named)
   918  		assert(named.TypeArgs() == nil)
   919  
   920  		// Record method indices before encoding anything else, as
   921  		// encoding the underlying type may transitively encode one of
   922  		// named's generic methods (e.g., via a function body that
   923  		// calls it), which needs its index.
   924  		for i := range named.NumMethods() {
   925  			w.p.methodIdx[named.Method(i)] = i
   926  		}
   927  
   928  		w.pos(obj)
   929  		w.typeParamNames(named.TypeParams())
   930  		wext.typeExt(obj)
   931  		w.typ(named.Underlying())
   932  
   933  		// separate generic and non-generic methods
   934  		var methods, gmethods []*types2.Func
   935  		for i := range named.NumMethods() {
   936  			m := named.Method(i)
   937  			if isGenericMethod(m.Type()) {
   938  				gmethods = append(gmethods, m)
   939  			} else {
   940  				methods = append(methods, m)
   941  			}
   942  		}
   943  		// encode non-generic methods inline
   944  		w.Len(len(methods))
   945  		for _, m := range methods {
   946  			w.method(wext, m)
   947  		}
   948  		if len(gmethods) > 0 {
   949  			assert(w.Version().Has(pkgbits.GenericMethods))
   950  		}
   951  		// encode a pointer to each generic method
   952  		if w.Version().Has(pkgbits.GenericMethods) {
   953  			w.Len(len(gmethods))
   954  			for _, m := range gmethods {
   955  				w.Reloc(pkgbits.SectionObj, w.p.objIdx(m))
   956  			}
   957  		}
   958  
   959  		return pkgbits.ObjType
   960  
   961  	case *types2.Var:
   962  		w.pos(obj)
   963  		w.typ(obj.Type())
   964  		wext.varExt(obj)
   965  		return pkgbits.ObjVar
   966  	}
   967  }
   968  
   969  // objDict writes the dictionary needed for reading the given object.
   970  func (w *writer) objDict(obj types2.Object, dict *writerDict) {
   971  	// TODO(mdempsky): Split objDict into multiple entries? reader.go
   972  	// doesn't care about the type parameter bounds, and reader2.go
   973  	// doesn't care about referenced functions.
   974  
   975  	w.dict = dict // TODO(mdempsky): This is a bit sketchy.
   976  	w.Len(len(dict.implicits))
   977  
   978  	rtparams := objRecvTypeParams(obj)
   979  	tparams := objTypeParams(obj)
   980  
   981  	if w.Version().Has(pkgbits.GenericMethods) {
   982  		w.Len(len(rtparams))
   983  	} else {
   984  		assert(len(rtparams) == 0)
   985  	}
   986  	w.Len(len(tparams))
   987  
   988  	for _, rtparam := range rtparams {
   989  		w.typ(rtparam.Constraint())
   990  	}
   991  	for _, tparam := range tparams {
   992  		w.typ(tparam.Constraint())
   993  	}
   994  
   995  	nderived := len(dict.derived)
   996  	w.Len(nderived)
   997  	for _, typ := range dict.derived {
   998  		w.Reloc(pkgbits.SectionType, typ.idx)
   999  		if w.Version().Has(pkgbits.DerivedInfoNeeded) {
  1000  			w.Bool(false)
  1001  		}
  1002  	}
  1003  
  1004  	// Write runtime dictionary information.
  1005  	//
  1006  	// N.B., the go/types importer reads up to the section, but doesn't
  1007  	// read any further, so it's safe to change. (See TODO above.)
  1008  
  1009  	// For each type parameter, write out whether the constraint is a
  1010  	// basic interface. This is used to determine how aggressively we
  1011  	// can shape corresponding type arguments.
  1012  	//
  1013  	// This is somewhat redundant with writing out the full type
  1014  	// parameter constraints above, but the compiler currently skips
  1015  	// over those. Also, we don't care about the *declared* constraints,
  1016  	// but how the type parameters are actually *used*. E.g., if a type
  1017  	// parameter is constrained to `int | uint` but then never used in
  1018  	// arithmetic/conversions/etc, we could shape those together.
  1019  	for _, implicit := range dict.implicits {
  1020  		w.Bool(implicit.Underlying().(*types2.Interface).IsMethodSet())
  1021  	}
  1022  	for _, rtparam := range rtparams {
  1023  		w.Bool(rtparam.Underlying().(*types2.Interface).IsMethodSet())
  1024  	}
  1025  	for _, tparam := range tparams {
  1026  		w.Bool(tparam.Underlying().(*types2.Interface).IsMethodSet())
  1027  	}
  1028  
  1029  	w.Len(len(dict.typeParamMethodExprs))
  1030  	for _, info := range dict.typeParamMethodExprs {
  1031  		w.Len(info.typeParamIdx)
  1032  		w.selectorInfo(info.methodInfo)
  1033  	}
  1034  
  1035  	w.Len(len(dict.subdicts))
  1036  	for _, info := range dict.subdicts {
  1037  		w.objInfo(info)
  1038  	}
  1039  
  1040  	w.Len(len(dict.rtypes))
  1041  	for _, info := range dict.rtypes {
  1042  		w.typInfo(info)
  1043  	}
  1044  
  1045  	w.Len(len(dict.itabs))
  1046  	for _, info := range dict.itabs {
  1047  		w.typInfo(info.typ)
  1048  		w.typInfo(info.iface)
  1049  	}
  1050  
  1051  	assert(len(dict.derived) == nderived)
  1052  }
  1053  
  1054  func (w *writer) typeParamNames(tparams *types2.TypeParamList) {
  1055  	w.Sync(pkgbits.SyncTypeParamNames)
  1056  
  1057  	ntparams := tparams.Len()
  1058  	for i := 0; i < ntparams; i++ {
  1059  		tparam := tparams.At(i).Obj()
  1060  		w.pos(tparam)
  1061  		w.localIdent(tparam)
  1062  	}
  1063  }
  1064  
  1065  func (w *writer) method(wext *writer, meth *types2.Func) {
  1066  	decl, ok := w.p.funDecls[meth]
  1067  	assert(ok)
  1068  	sig := meth.Type().(*types2.Signature)
  1069  
  1070  	w.Sync(pkgbits.SyncMethod)
  1071  	if w.Version().Has(pkgbits.PreserveMethodOrder) {
  1072  		w.Len(w.p.methodIdx[meth.Origin()])
  1073  	}
  1074  	w.pos(meth)
  1075  	w.selector(meth)
  1076  	w.typeParamNames(sig.RecvTypeParams())
  1077  	w.param(sig.Recv())
  1078  	w.signature(sig)
  1079  
  1080  	w.pos(decl) // XXX: Hack to workaround linker limitations.
  1081  	wext.funcExt(meth)
  1082  }
  1083  
  1084  // qualifiedIdent writes out the name of an object typically declared at package
  1085  // scope. It's also used to refer to generic methods and locally defined types.
  1086  func (w *writer) qualifiedIdent(obj types2.Object) {
  1087  	w.Sync(pkgbits.SyncSym)
  1088  
  1089  	name := obj.Name()
  1090  	if isDefinedType(obj) && obj.Pkg() == w.p.curpkg {
  1091  		decl, ok := w.p.typDecls[obj.(*types2.TypeName)]
  1092  		assert(ok)
  1093  		if decl.gen != 0 {
  1094  			// For local defined types, we embed a scope-disambiguation
  1095  			// number directly into their name. types.SplitVargenSuffix then
  1096  			// knows to look for this.
  1097  			//
  1098  			// TODO(mdempsky): Find a better solution; this is terrible.
  1099  			name = fmt.Sprintf("%s·%v", name, decl.gen)
  1100  		}
  1101  	}
  1102  
  1103  	// Generic methods are promoted to objects and thus need qualified identifiers.
  1104  	// They must be contextualized by their defining type.
  1105  	if isGenericMethod(obj.Type()) {
  1106  		recv := obj.Type().(*types2.Signature).Recv().Type()
  1107  		fstr := "%s.%s"
  1108  		if _, ok := types2.Unalias(recv).(*types2.Pointer); ok {
  1109  			fstr = "(*%s).%s"
  1110  		}
  1111  		name = fmt.Sprintf(fstr, types2.Unalias(deref2(recv)).(*types2.Named).Obj().Name(), name)
  1112  	}
  1113  
  1114  	w.pkg(obj.Pkg())
  1115  	w.String(name)
  1116  }
  1117  
  1118  // TODO(mdempsky): We should be able to omit pkg from both localIdent
  1119  // and selector, because they should always be known from context.
  1120  // However, past frustrations with this optimization in iexport make
  1121  // me a little nervous to try it again.
  1122  
  1123  // localIdent writes the name of a locally declared object (i.e.,
  1124  // objects that can only be accessed by non-qualified name, within the
  1125  // context of a particular function).
  1126  func (w *writer) localIdent(obj types2.Object) {
  1127  	assert(!isGlobal(obj))
  1128  	w.Sync(pkgbits.SyncLocalIdent)
  1129  	w.pkg(obj.Pkg())
  1130  	w.String(obj.Name())
  1131  }
  1132  
  1133  // selector writes the name of a field or method (i.e., objects that
  1134  // can only be accessed using selector expressions).
  1135  func (w *writer) selector(obj types2.Object) {
  1136  	w.selectorInfo(w.p.selectorIdx(obj))
  1137  }
  1138  
  1139  func (w *writer) selectorInfo(info selectorInfo) {
  1140  	w.Sync(pkgbits.SyncSelector)
  1141  	w.pkgRef(info.pkgIdx)
  1142  	w.StringRef(info.nameIdx)
  1143  }
  1144  
  1145  func (pw *pkgWriter) selectorIdx(obj types2.Object) selectorInfo {
  1146  	pkgIdx := pw.pkgIdx(obj.Pkg())
  1147  	nameIdx := pw.StringIdx(obj.Name())
  1148  	return selectorInfo{pkgIdx: pkgIdx, nameIdx: nameIdx}
  1149  }
  1150  
  1151  // @@@ Compiler extensions
  1152  
  1153  func (w *writer) funcExt(obj *types2.Func) {
  1154  	decl, ok := w.p.funDecls[obj]
  1155  	assert(ok)
  1156  
  1157  	// TODO(mdempsky): Extend these pragma validation flags to account
  1158  	// for generics. E.g., linkname probably doesn't make sense at
  1159  	// least.
  1160  
  1161  	pragma := asPragmaFlag(decl.Pragma)
  1162  	if pragma&ir.Systemstack != 0 && pragma&ir.Nosplit != 0 {
  1163  		w.p.errorf(decl, "go:nosplit and go:systemstack cannot be combined")
  1164  	}
  1165  	wi := asWasmImport(decl.Pragma)
  1166  	we := asWasmExport(decl.Pragma)
  1167  
  1168  	if decl.Body != nil {
  1169  		if pragma&ir.Noescape != 0 {
  1170  			w.p.errorf(decl, "can only use //go:noescape with external func implementations")
  1171  		}
  1172  		if wi != nil {
  1173  			w.p.errorf(decl, "can only use //go:wasmimport with external func implementations")
  1174  		}
  1175  		if (pragma&ir.UintptrKeepAlive != 0 && pragma&ir.UintptrEscapes == 0) && pragma&ir.Nosplit == 0 {
  1176  			// Stack growth can't handle uintptr arguments that may
  1177  			// be pointers (as we don't know which are pointers
  1178  			// when creating the stack map). Thus uintptrkeepalive
  1179  			// functions (and all transitive callees) must be
  1180  			// nosplit.
  1181  			//
  1182  			// N.B. uintptrescapes implies uintptrkeepalive but it
  1183  			// is OK since the arguments must escape to the heap.
  1184  			//
  1185  			// TODO(prattmic): Add recursive nosplit check of callees.
  1186  			// TODO(prattmic): Functions with no body (i.e.,
  1187  			// assembly) must also be nosplit, but we can't check
  1188  			// that here.
  1189  			w.p.errorf(decl, "go:uintptrkeepalive requires go:nosplit")
  1190  		}
  1191  	} else {
  1192  		if base.Flag.Complete || decl.Name.Value == "init" {
  1193  			// Linknamed functions are allowed to have no body. Hopefully
  1194  			// the linkname target has a body. See issue 23311.
  1195  			// Wasmimport functions are also allowed to have no body.
  1196  			if _, ok := w.p.linknames[obj]; !ok && wi == nil {
  1197  				w.p.errorf(decl, "missing function body")
  1198  			}
  1199  		}
  1200  	}
  1201  
  1202  	sig, block := obj.Type().(*types2.Signature), decl.Body
  1203  	body, closureVars := w.p.bodyIdx(sig, block, w.dict)
  1204  	if len(closureVars) > 0 {
  1205  		fmt.Fprintln(os.Stderr, "CLOSURE", closureVars)
  1206  	}
  1207  	assert(len(closureVars) == 0)
  1208  
  1209  	w.Sync(pkgbits.SyncFuncExt)
  1210  	w.pragmaFlag(pragma)
  1211  	w.linkname(obj)
  1212  
  1213  	if buildcfg.GOARCH == "wasm" {
  1214  		if wi != nil {
  1215  			w.String(wi.Module)
  1216  			w.String(wi.Name)
  1217  		} else {
  1218  			w.String("")
  1219  			w.String("")
  1220  		}
  1221  		if we != nil {
  1222  			w.String(we.Name)
  1223  		} else {
  1224  			w.String("")
  1225  		}
  1226  	}
  1227  
  1228  	w.Bool(false) // stub extension
  1229  	w.Reloc(pkgbits.SectionBody, body)
  1230  	w.Sync(pkgbits.SyncEOF)
  1231  }
  1232  
  1233  func (w *writer) typeExt(obj *types2.TypeName) {
  1234  	decl, ok := w.p.typDecls[obj]
  1235  	assert(ok)
  1236  
  1237  	w.Sync(pkgbits.SyncTypeExt)
  1238  
  1239  	w.pragmaFlag(asPragmaFlag(decl.Pragma))
  1240  
  1241  	// No LSym.SymIdx info yet.
  1242  	w.Int64(-1)
  1243  	w.Int64(-1)
  1244  }
  1245  
  1246  func (w *writer) varExt(obj *types2.Var) {
  1247  	w.Sync(pkgbits.SyncVarExt)
  1248  	w.linkname(obj)
  1249  }
  1250  
  1251  func (w *writer) linkname(obj types2.Object) {
  1252  	w.Sync(pkgbits.SyncLinkname)
  1253  	w.Int64(-1)
  1254  	info := w.p.linknames[obj]
  1255  	w.String(info.remote)
  1256  	w.Bool(info.std)
  1257  }
  1258  
  1259  func (w *writer) pragmaFlag(p ir.PragmaFlag) {
  1260  	w.Sync(pkgbits.SyncPragma)
  1261  	w.Int(int(p))
  1262  }
  1263  
  1264  // @@@ Function bodies
  1265  
  1266  // bodyIdx returns the index for the given function body (specified by
  1267  // block), adding it to the export data
  1268  func (pw *pkgWriter) bodyIdx(sig *types2.Signature, block *syntax.BlockStmt, dict *writerDict) (idx index, closureVars []posVar) {
  1269  	w := pw.newWriter(pkgbits.SectionBody, pkgbits.SyncFuncBody)
  1270  	w.sig = sig
  1271  	w.dict = dict
  1272  
  1273  	w.declareParams(sig)
  1274  	if w.Bool(block != nil) {
  1275  		w.stmts(block.List)
  1276  		w.pos(block.Rbrace)
  1277  	}
  1278  
  1279  	return w.Flush(), w.closureVars
  1280  }
  1281  
  1282  func (w *writer) declareParams(sig *types2.Signature) {
  1283  	addLocals := func(params *types2.Tuple) {
  1284  		for i := 0; i < params.Len(); i++ {
  1285  			w.addLocal(params.At(i))
  1286  		}
  1287  	}
  1288  
  1289  	if recv := sig.Recv(); recv != nil {
  1290  		w.addLocal(recv)
  1291  	}
  1292  	addLocals(sig.Params())
  1293  	addLocals(sig.Results())
  1294  }
  1295  
  1296  // addLocal records the declaration of a new local variable.
  1297  func (w *writer) addLocal(obj *types2.Var) {
  1298  	idx := len(w.localsIdx)
  1299  
  1300  	w.Sync(pkgbits.SyncAddLocal)
  1301  	if w.p.SyncMarkers() {
  1302  		w.Int(idx)
  1303  	}
  1304  	w.varDictIndex(obj)
  1305  
  1306  	if w.localsIdx == nil {
  1307  		w.localsIdx = make(map[*types2.Var]int)
  1308  	}
  1309  	w.localsIdx[obj] = idx
  1310  }
  1311  
  1312  // useLocal writes a reference to the given local or free variable
  1313  // into the bitstream.
  1314  func (w *writer) useLocal(pos syntax.Pos, obj *types2.Var) {
  1315  	w.Sync(pkgbits.SyncUseObjLocal)
  1316  
  1317  	if idx, ok := w.localsIdx[obj]; w.Bool(ok) {
  1318  		w.Len(idx)
  1319  		return
  1320  	}
  1321  
  1322  	idx, ok := w.closureVarsIdx[obj]
  1323  	if !ok {
  1324  		if w.closureVarsIdx == nil {
  1325  			w.closureVarsIdx = make(map[*types2.Var]int)
  1326  		}
  1327  		idx = len(w.closureVars)
  1328  		w.closureVars = append(w.closureVars, posVar{pos, obj})
  1329  		w.closureVarsIdx[obj] = idx
  1330  	}
  1331  	w.Len(idx)
  1332  }
  1333  
  1334  func (w *writer) openScope(pos syntax.Pos) {
  1335  	w.Sync(pkgbits.SyncOpenScope)
  1336  	w.pos(pos)
  1337  }
  1338  
  1339  func (w *writer) closeScope(pos syntax.Pos) {
  1340  	w.Sync(pkgbits.SyncCloseScope)
  1341  	w.pos(pos)
  1342  	w.closeAnotherScope()
  1343  }
  1344  
  1345  func (w *writer) closeAnotherScope() {
  1346  	w.Sync(pkgbits.SyncCloseAnotherScope)
  1347  }
  1348  
  1349  // @@@ Statements
  1350  
  1351  // stmt writes the given statement into the function body bitstream.
  1352  func (w *writer) stmt(stmt syntax.Stmt) {
  1353  	var stmts []syntax.Stmt
  1354  	if stmt != nil {
  1355  		stmts = []syntax.Stmt{stmt}
  1356  	}
  1357  	w.stmts(stmts)
  1358  }
  1359  
  1360  func (w *writer) stmts(stmts []syntax.Stmt) {
  1361  	dead := false
  1362  	w.Sync(pkgbits.SyncStmts)
  1363  	var lastLabel = -1
  1364  	for i, stmt := range stmts {
  1365  		if _, ok := stmt.(*syntax.LabeledStmt); ok {
  1366  			lastLabel = i
  1367  		}
  1368  	}
  1369  	for i, stmt := range stmts {
  1370  		if dead && i > lastLabel {
  1371  			// Any statements after a terminating and last label statement are safe to omit.
  1372  			// Otherwise, code after label statement may refer to dead stmts between terminating
  1373  			// and label statement, see issue #65593.
  1374  			if _, ok := stmt.(*syntax.LabeledStmt); !ok {
  1375  				continue
  1376  			}
  1377  		}
  1378  		w.stmt1(stmt)
  1379  		dead = w.p.terminates(stmt)
  1380  	}
  1381  	w.Code(stmtEnd)
  1382  	w.Sync(pkgbits.SyncStmtsEnd)
  1383  }
  1384  
  1385  func (w *writer) stmt1(stmt syntax.Stmt) {
  1386  	switch stmt := stmt.(type) {
  1387  	default:
  1388  		w.p.unexpected("statement", stmt)
  1389  
  1390  	case nil, *syntax.EmptyStmt:
  1391  		return
  1392  
  1393  	case *syntax.AssignStmt:
  1394  		switch {
  1395  		case stmt.Rhs == nil:
  1396  			w.Code(stmtIncDec)
  1397  			w.op(binOps[stmt.Op])
  1398  			w.expr(stmt.Lhs)
  1399  			w.pos(stmt)
  1400  
  1401  		case stmt.Op != 0 && stmt.Op != syntax.Def:
  1402  			w.Code(stmtAssignOp)
  1403  			w.op(binOps[stmt.Op])
  1404  			w.expr(stmt.Lhs)
  1405  			w.pos(stmt)
  1406  
  1407  			var typ types2.Type
  1408  			if stmt.Op != syntax.Shl && stmt.Op != syntax.Shr {
  1409  				typ = w.p.typeOf(stmt.Lhs)
  1410  			}
  1411  			w.implicitConvExpr(typ, stmt.Rhs)
  1412  
  1413  		default:
  1414  			w.assignStmt(stmt, stmt.Lhs, stmt.Rhs)
  1415  		}
  1416  
  1417  	case *syntax.BlockStmt:
  1418  		w.Code(stmtBlock)
  1419  		w.blockStmt(stmt)
  1420  
  1421  	case *syntax.BranchStmt:
  1422  		w.Code(stmtBranch)
  1423  		w.pos(stmt)
  1424  		var op ir.Op
  1425  		switch stmt.Tok {
  1426  		case syntax.Break:
  1427  			op = ir.OBREAK
  1428  		case syntax.Continue:
  1429  			op = ir.OCONTINUE
  1430  		case syntax.Fallthrough:
  1431  			op = ir.OFALL
  1432  		case syntax.Goto:
  1433  			op = ir.OGOTO
  1434  		}
  1435  		w.op(op)
  1436  		w.optLabel(stmt.Label)
  1437  
  1438  	case *syntax.CallStmt:
  1439  		w.Code(stmtCall)
  1440  		w.pos(stmt)
  1441  		var op ir.Op
  1442  		switch stmt.Tok {
  1443  		case syntax.Defer:
  1444  			op = ir.ODEFER
  1445  		case syntax.Go:
  1446  			op = ir.OGO
  1447  		}
  1448  		w.op(op)
  1449  		w.expr(stmt.Call)
  1450  		if stmt.Tok == syntax.Defer {
  1451  			w.optExpr(stmt.DeferAt)
  1452  		}
  1453  
  1454  	case *syntax.DeclStmt:
  1455  		for _, decl := range stmt.DeclList {
  1456  			w.declStmt(decl)
  1457  		}
  1458  
  1459  	case *syntax.ExprStmt:
  1460  		w.Code(stmtExpr)
  1461  		w.expr(stmt.X)
  1462  
  1463  	case *syntax.ForStmt:
  1464  		w.Code(stmtFor)
  1465  		w.forStmt(stmt)
  1466  
  1467  	case *syntax.IfStmt:
  1468  		w.Code(stmtIf)
  1469  		w.ifStmt(stmt)
  1470  
  1471  	case *syntax.LabeledStmt:
  1472  		w.Code(stmtLabel)
  1473  		w.pos(stmt)
  1474  		w.label(stmt.Label)
  1475  		w.stmt1(stmt.Stmt)
  1476  
  1477  	case *syntax.ReturnStmt:
  1478  		w.Code(stmtReturn)
  1479  		w.pos(stmt)
  1480  
  1481  		resultTypes := w.sig.Results()
  1482  		dstType := func(i int) types2.Type {
  1483  			return resultTypes.At(i).Type()
  1484  		}
  1485  		w.multiExpr(stmt, dstType, syntax.UnpackListExpr(stmt.Results))
  1486  
  1487  	case *syntax.SelectStmt:
  1488  		w.Code(stmtSelect)
  1489  		w.selectStmt(stmt)
  1490  
  1491  	case *syntax.SendStmt:
  1492  		chanType := types2.CoreType(w.p.typeOf(stmt.Chan)).(*types2.Chan)
  1493  
  1494  		w.Code(stmtSend)
  1495  		w.pos(stmt)
  1496  		w.expr(stmt.Chan)
  1497  		w.implicitConvExpr(chanType.Elem(), stmt.Value)
  1498  
  1499  	case *syntax.SwitchStmt:
  1500  		w.Code(stmtSwitch)
  1501  		w.switchStmt(stmt)
  1502  	}
  1503  }
  1504  
  1505  func (w *writer) assignList(expr syntax.Expr) {
  1506  	exprs := syntax.UnpackListExpr(expr)
  1507  	w.Len(len(exprs))
  1508  
  1509  	for _, expr := range exprs {
  1510  		w.assign(expr)
  1511  	}
  1512  }
  1513  
  1514  func (w *writer) assign(expr syntax.Expr) {
  1515  	expr = syntax.Unparen(expr)
  1516  
  1517  	if name, ok := expr.(*syntax.Name); ok {
  1518  		if name.Value == "_" {
  1519  			w.Code(assignBlank)
  1520  			return
  1521  		}
  1522  
  1523  		if obj, ok := w.p.info.Defs[name]; ok {
  1524  			obj := obj.(*types2.Var)
  1525  
  1526  			w.Code(assignDef)
  1527  			w.pos(obj)
  1528  			w.localIdent(obj)
  1529  			w.typ(obj.Type())
  1530  
  1531  			// TODO(mdempsky): Minimize locals index size by deferring
  1532  			// this until the variables actually come into scope.
  1533  			w.addLocal(obj)
  1534  			return
  1535  		}
  1536  	}
  1537  
  1538  	w.Code(assignExpr)
  1539  	w.expr(expr)
  1540  }
  1541  
  1542  func (w *writer) declStmt(decl syntax.Decl) {
  1543  	switch decl := decl.(type) {
  1544  	default:
  1545  		w.p.unexpected("declaration", decl)
  1546  
  1547  	case *syntax.ConstDecl, *syntax.TypeDecl:
  1548  
  1549  	case *syntax.VarDecl:
  1550  		w.assignStmt(decl, namesAsExpr(decl.NameList), decl.Values)
  1551  	}
  1552  }
  1553  
  1554  // assignStmt writes out an assignment for "lhs = rhs".
  1555  func (w *writer) assignStmt(pos poser, lhs0, rhs0 syntax.Expr) {
  1556  	lhs := syntax.UnpackListExpr(lhs0)
  1557  	rhs := syntax.UnpackListExpr(rhs0)
  1558  
  1559  	w.Code(stmtAssign)
  1560  	w.pos(pos)
  1561  
  1562  	// As if w.assignList(lhs0).
  1563  	w.Len(len(lhs))
  1564  	for _, expr := range lhs {
  1565  		w.assign(expr)
  1566  	}
  1567  
  1568  	dstType := func(i int) types2.Type {
  1569  		dst := lhs[i]
  1570  
  1571  		// Finding dstType is somewhat involved, because for VarDecl
  1572  		// statements, the Names are only added to the info.{Defs,Uses}
  1573  		// maps, not to info.Types.
  1574  		if name, ok := syntax.Unparen(dst).(*syntax.Name); ok {
  1575  			if name.Value == "_" {
  1576  				return nil // ok: no implicit conversion
  1577  			} else if def, ok := w.p.info.Defs[name].(*types2.Var); ok {
  1578  				return def.Type()
  1579  			} else if use, ok := w.p.info.Uses[name].(*types2.Var); ok {
  1580  				return use.Type()
  1581  			} else {
  1582  				w.p.fatalf(dst, "cannot find type of destination object: %v", dst)
  1583  			}
  1584  		}
  1585  
  1586  		return w.p.typeOf(dst)
  1587  	}
  1588  
  1589  	w.multiExpr(pos, dstType, rhs)
  1590  }
  1591  
  1592  func (w *writer) blockStmt(stmt *syntax.BlockStmt) {
  1593  	w.Sync(pkgbits.SyncBlockStmt)
  1594  	w.openScope(stmt.Pos())
  1595  	w.stmts(stmt.List)
  1596  	w.closeScope(stmt.Rbrace)
  1597  }
  1598  
  1599  func (w *writer) forStmt(stmt *syntax.ForStmt) {
  1600  	w.Sync(pkgbits.SyncForStmt)
  1601  	w.openScope(stmt.Pos())
  1602  
  1603  	if rang, ok := stmt.Init.(*syntax.RangeClause); w.Bool(ok) {
  1604  		w.pos(rang)
  1605  		w.assignList(rang.Lhs)
  1606  		w.expr(rang.X)
  1607  
  1608  		xtyp := w.p.typeOf(rang.X)
  1609  		if _, isMap := types2.CoreType(xtyp).(*types2.Map); isMap {
  1610  			w.rtype(xtyp)
  1611  		}
  1612  		{
  1613  			lhs := syntax.UnpackListExpr(rang.Lhs)
  1614  			assign := func(i int, src types2.Type) {
  1615  				if i >= len(lhs) {
  1616  					return
  1617  				}
  1618  				dst := syntax.Unparen(lhs[i])
  1619  				if name, ok := dst.(*syntax.Name); ok && name.Value == "_" {
  1620  					return
  1621  				}
  1622  
  1623  				var dstType types2.Type
  1624  				if rang.Def {
  1625  					// For `:=` assignments, the LHS names only appear in Defs,
  1626  					// not Types (as used by typeOf).
  1627  					dstType = w.p.info.Defs[dst.(*syntax.Name)].(*types2.Var).Type()
  1628  				} else {
  1629  					dstType = w.p.typeOf(dst)
  1630  				}
  1631  
  1632  				w.convRTTI(src, dstType)
  1633  			}
  1634  
  1635  			keyType, valueType := types2.RangeKeyVal(w.p.typeOf(rang.X))
  1636  			assign(0, keyType)
  1637  			assign(1, valueType)
  1638  		}
  1639  
  1640  	} else {
  1641  		if stmt.Cond != nil && w.p.staticBool(&stmt.Cond) < 0 { // always false
  1642  			stmt.Post = nil
  1643  			stmt.Body.List = nil
  1644  		}
  1645  
  1646  		w.pos(stmt)
  1647  		w.stmt(stmt.Init)
  1648  		w.optExpr(stmt.Cond)
  1649  		w.stmt(stmt.Post)
  1650  	}
  1651  
  1652  	w.blockStmt(stmt.Body)
  1653  	w.Bool(w.distinctVars(stmt))
  1654  	w.closeAnotherScope()
  1655  }
  1656  
  1657  func (w *writer) distinctVars(stmt *syntax.ForStmt) bool {
  1658  	lv := base.Debug.LoopVar
  1659  	fileVersion := w.p.info.FileVersions[stmt.Pos().FileBase()]
  1660  	is122 := fileVersion == "" || version.Compare(fileVersion, "go1.22") >= 0
  1661  
  1662  	// Turning off loopvar for 1.22 is only possible with loopvarhash=qn
  1663  	//
  1664  	// Debug.LoopVar values to be preserved for 1.21 compatibility are 1 and 2,
  1665  	// which are also set (=1) by GOEXPERIMENT=loopvar.  The knobs for turning on
  1666  	// the new, unshared, loopvar behavior apply to versions less than 1.21 because
  1667  	// (1) 1.21 also did that and (2) this is believed to be the likely use case;
  1668  	// anyone checking to see if it affects their code will just run the GOEXPERIMENT
  1669  	// but will not also update all their go.mod files to 1.21.
  1670  	//
  1671  	// -gcflags=-d=loopvar=3 enables logging for 1.22 but does not turn loopvar on for <= 1.21.
  1672  
  1673  	return is122 || lv > 0 && lv != 3
  1674  }
  1675  
  1676  func (w *writer) ifStmt(stmt *syntax.IfStmt) {
  1677  	cond := w.p.staticBool(&stmt.Cond)
  1678  
  1679  	w.Sync(pkgbits.SyncIfStmt)
  1680  	w.openScope(stmt.Pos())
  1681  	w.pos(stmt)
  1682  	w.stmt(stmt.Init)
  1683  	w.expr(stmt.Cond)
  1684  	w.Int(cond)
  1685  	if cond >= 0 {
  1686  		w.blockStmt(stmt.Then)
  1687  	} else {
  1688  		w.pos(stmt.Then.Rbrace)
  1689  	}
  1690  	if cond <= 0 {
  1691  		w.stmt(stmt.Else)
  1692  	}
  1693  	w.closeAnotherScope()
  1694  }
  1695  
  1696  func (w *writer) selectStmt(stmt *syntax.SelectStmt) {
  1697  	w.Sync(pkgbits.SyncSelectStmt)
  1698  
  1699  	w.pos(stmt)
  1700  	w.Len(len(stmt.Body))
  1701  	for i, clause := range stmt.Body {
  1702  		if i > 0 {
  1703  			w.closeScope(clause.Pos())
  1704  		}
  1705  		w.openScope(clause.Pos())
  1706  
  1707  		w.pos(clause)
  1708  		w.stmt(clause.Comm)
  1709  		w.stmts(clause.Body)
  1710  	}
  1711  	if len(stmt.Body) > 0 {
  1712  		w.closeScope(stmt.Rbrace)
  1713  	}
  1714  }
  1715  
  1716  func (w *writer) switchStmt(stmt *syntax.SwitchStmt) {
  1717  	w.Sync(pkgbits.SyncSwitchStmt)
  1718  
  1719  	w.openScope(stmt.Pos())
  1720  	w.pos(stmt)
  1721  	w.stmt(stmt.Init)
  1722  
  1723  	var iface, tagType types2.Type
  1724  	var tagTypeIsChan bool
  1725  	if guard, ok := stmt.Tag.(*syntax.TypeSwitchGuard); w.Bool(ok) {
  1726  		iface = w.p.typeOf(guard.X)
  1727  
  1728  		w.pos(guard)
  1729  		if tag := guard.Lhs; w.Bool(tag != nil) {
  1730  			w.pos(tag)
  1731  
  1732  			// Like w.localIdent, but we don't have a types2.Object.
  1733  			w.Sync(pkgbits.SyncLocalIdent)
  1734  			w.pkg(w.p.curpkg)
  1735  			w.String(tag.Value)
  1736  		}
  1737  		w.expr(guard.X)
  1738  	} else {
  1739  		tag := stmt.Tag
  1740  
  1741  		var tagValue constant.Value
  1742  		if tag != nil {
  1743  			tv := w.p.typeAndValue(tag)
  1744  			tagType = tv.Type
  1745  			tagValue = tv.Value
  1746  			_, tagTypeIsChan = tagType.Underlying().(*types2.Chan)
  1747  		} else {
  1748  			tagType = types2.Typ[types2.Bool]
  1749  			tagValue = constant.MakeBool(true)
  1750  		}
  1751  
  1752  		if tagValue != nil {
  1753  			// If the switch tag has a constant value, look for a case
  1754  			// clause that we always branch to.
  1755  			func() {
  1756  				var target *syntax.CaseClause
  1757  			Outer:
  1758  				for _, clause := range stmt.Body {
  1759  					if clause.Cases == nil {
  1760  						target = clause
  1761  					}
  1762  					for _, cas := range syntax.UnpackListExpr(clause.Cases) {
  1763  						tv := w.p.typeAndValue(cas)
  1764  						if tv.Value == nil {
  1765  							return // non-constant case; give up
  1766  						}
  1767  						if constant.Compare(tagValue, token.EQL, tv.Value) {
  1768  							target = clause
  1769  							break Outer
  1770  						}
  1771  					}
  1772  				}
  1773  				// We've found the target clause, if any.
  1774  
  1775  				if target != nil {
  1776  					if hasFallthrough(target.Body) {
  1777  						return // fallthrough is tricky; give up
  1778  					}
  1779  
  1780  					// Rewrite as single "default" case.
  1781  					target.Cases = nil
  1782  					stmt.Body = []*syntax.CaseClause{target}
  1783  				} else {
  1784  					stmt.Body = nil
  1785  				}
  1786  
  1787  				// Clear switch tag (i.e., replace with implicit "true").
  1788  				tag = nil
  1789  				stmt.Tag = nil
  1790  				tagType = types2.Typ[types2.Bool]
  1791  			}()
  1792  		}
  1793  
  1794  		// Walk is going to emit comparisons between the tag value and
  1795  		// each case expression, and we want these comparisons to always
  1796  		// have the same type. If there are any case values that can't be
  1797  		// converted to the tag value's type, then convert everything to
  1798  		// `any` instead.
  1799  		//
  1800  		// Except that we need to keep comparisons of channel values from
  1801  		// being wrapped in any(). See issue #67190.
  1802  
  1803  		if !tagTypeIsChan {
  1804  		Outer:
  1805  			for _, clause := range stmt.Body {
  1806  				for _, cas := range syntax.UnpackListExpr(clause.Cases) {
  1807  					if casType := w.p.typeOf(cas); !types2.AssignableTo(casType, tagType) && (types2.IsInterface(casType) || types2.IsInterface(tagType)) {
  1808  						tagType = types2.NewInterfaceType(nil, nil)
  1809  						break Outer
  1810  					}
  1811  				}
  1812  			}
  1813  		}
  1814  
  1815  		if w.Bool(tag != nil) {
  1816  			w.implicitConvExpr(tagType, tag)
  1817  		}
  1818  	}
  1819  
  1820  	w.Len(len(stmt.Body))
  1821  	for i, clause := range stmt.Body {
  1822  		if i > 0 {
  1823  			w.closeScope(clause.Pos())
  1824  		}
  1825  		w.openScope(clause.Pos())
  1826  
  1827  		w.pos(clause)
  1828  
  1829  		cases := syntax.UnpackListExpr(clause.Cases)
  1830  		if iface != nil {
  1831  			w.Len(len(cases))
  1832  			for _, cas := range cases {
  1833  				if w.Bool(isNil(w.p, cas)) {
  1834  					continue
  1835  				}
  1836  				w.exprType(iface, cas)
  1837  			}
  1838  		} else {
  1839  			// As if w.exprList(clause.Cases),
  1840  			// but with implicit conversions to tagType.
  1841  
  1842  			w.Sync(pkgbits.SyncExprList)
  1843  			w.Sync(pkgbits.SyncExprs)
  1844  			w.Len(len(cases))
  1845  			for _, cas := range cases {
  1846  				typ := tagType
  1847  				if tagTypeIsChan {
  1848  					typ = nil
  1849  				}
  1850  				w.implicitConvExpr(typ, cas)
  1851  			}
  1852  		}
  1853  
  1854  		if obj, ok := w.p.info.Implicits[clause]; ok {
  1855  			// TODO(mdempsky): These pos details are quirkish, but also
  1856  			// necessary so the variable's position is correct for DWARF
  1857  			// scope assignment later. It would probably be better for us to
  1858  			// instead just set the variable's DWARF scoping info earlier so
  1859  			// we can give it the correct position information.
  1860  			pos := clause.Pos()
  1861  			if typs := syntax.UnpackListExpr(clause.Cases); len(typs) != 0 {
  1862  				pos = typeExprEndPos(typs[len(typs)-1])
  1863  			}
  1864  			w.pos(pos)
  1865  
  1866  			obj := obj.(*types2.Var)
  1867  			w.typ(obj.Type())
  1868  			w.addLocal(obj)
  1869  		}
  1870  
  1871  		w.stmts(clause.Body)
  1872  	}
  1873  	if len(stmt.Body) > 0 {
  1874  		w.closeScope(stmt.Rbrace)
  1875  	}
  1876  
  1877  	w.closeScope(stmt.Rbrace)
  1878  }
  1879  
  1880  func (w *writer) label(label *syntax.Name) {
  1881  	w.Sync(pkgbits.SyncLabel)
  1882  
  1883  	// TODO(mdempsky): Replace label strings with dense indices.
  1884  	w.String(label.Value)
  1885  }
  1886  
  1887  func (w *writer) optLabel(label *syntax.Name) {
  1888  	w.Sync(pkgbits.SyncOptLabel)
  1889  	if w.Bool(label != nil) {
  1890  		w.label(label)
  1891  	}
  1892  }
  1893  
  1894  // @@@ Expressions
  1895  
  1896  // expr writes the given expression into the function body bitstream.
  1897  func (w *writer) expr(expr syntax.Expr) {
  1898  	base.Assertf(expr != nil, "missing expression")
  1899  
  1900  	expr = syntax.Unparen(expr) // skip parens; unneeded after typecheck
  1901  
  1902  	obj, inst := lookupObj(w.p, expr)
  1903  	targs := asTypeSlice(inst.TypeArgs)
  1904  
  1905  	if tv, ok := w.p.maybeTypeAndValue(expr); ok {
  1906  		if tv.IsRuntimeHelper() {
  1907  			if pkg := obj.Pkg(); pkg != nil && pkg.Name() == "runtime" {
  1908  				objName := obj.Name()
  1909  				w.Code(exprRuntimeBuiltin)
  1910  				w.String(objName)
  1911  				return
  1912  			}
  1913  		}
  1914  
  1915  		if tv.IsType() {
  1916  			w.p.fatalf(expr, "unexpected type expression %v", syntax.String(expr))
  1917  		}
  1918  
  1919  		if tv.Value != nil {
  1920  			w.Code(exprConst)
  1921  			w.pos(expr)
  1922  			typ := idealType(tv)
  1923  			assert(typ != nil)
  1924  			w.typ(typ)
  1925  			w.Value(tv.Value)
  1926  			return
  1927  		}
  1928  
  1929  		if _, isNil := obj.(*types2.Nil); isNil {
  1930  			w.Code(exprZero)
  1931  			w.pos(expr)
  1932  			w.typ(tv.Type)
  1933  			return
  1934  		}
  1935  
  1936  		// With shape types (and particular pointer shaping), we may have
  1937  		// an expression of type "go.shape.*uint8", but need to reshape it
  1938  		// to another shape-identical type to allow use in field
  1939  		// selection, indexing, etc.
  1940  		if typ := tv.Type; !tv.IsBuiltin() && !isTuple(typ) && !isUntyped(typ) {
  1941  			w.Code(exprReshape)
  1942  			w.typ(typ)
  1943  			// fallthrough
  1944  		}
  1945  	}
  1946  
  1947  	if obj != nil {
  1948  		if len(targs) != 0 {
  1949  			obj := obj.(*types2.Func)
  1950  
  1951  			w.Code(exprFuncInst)
  1952  			w.pos(expr)
  1953  			w.funcInst(obj, targs)
  1954  			return
  1955  		}
  1956  
  1957  		if isGlobal(obj) {
  1958  			w.Code(exprGlobal)
  1959  			w.obj(obj, nil)
  1960  			return
  1961  		}
  1962  
  1963  		obj := obj.(*types2.Var)
  1964  		assert(!obj.IsField())
  1965  
  1966  		w.Code(exprLocal)
  1967  		w.useLocal(expr.Pos(), obj)
  1968  		return
  1969  	}
  1970  
  1971  	switch expr := expr.(type) {
  1972  	default:
  1973  		w.p.unexpected("expression", expr)
  1974  
  1975  	case *syntax.CompositeLit:
  1976  		w.Code(exprCompLit)
  1977  		w.compLit(expr)
  1978  
  1979  	case *syntax.FuncLit:
  1980  		w.Code(exprFuncLit)
  1981  		w.funcLit(expr)
  1982  
  1983  	case *syntax.SelectorExpr:
  1984  		sel, ok := w.p.info.Selections[expr]
  1985  		assert(ok)
  1986  
  1987  		switch sel.Kind() {
  1988  		default:
  1989  			w.p.fatalf(expr, "unexpected selection kind: %v", sel.Kind())
  1990  
  1991  		case types2.FieldVal:
  1992  			w.Code(exprFieldVal)
  1993  			w.expr(expr.X)
  1994  			w.pos(expr)
  1995  			w.selector(sel.Obj())
  1996  
  1997  		case types2.MethodVal:
  1998  			w.methVal(expr, sel)
  1999  
  2000  		case types2.MethodExpr:
  2001  			w.methExpr(expr, sel)
  2002  		}
  2003  
  2004  	case *syntax.IndexExpr:
  2005  		// might be explicit instantiation of a generic method
  2006  		if selector, ok := expr.X.(*syntax.SelectorExpr); ok {
  2007  			if sel, ok := w.p.info.Selections[selector]; ok {
  2008  				switch sel.Kind() {
  2009  				default:
  2010  					w.p.fatalf(selector, "unexpected selection kind: %v", sel.Kind())
  2011  				case types2.FieldVal:
  2012  					// not a method
  2013  				case types2.MethodVal:
  2014  					w.methVal(selector, sel)
  2015  					return
  2016  				case types2.MethodExpr:
  2017  					w.methExpr(selector, sel)
  2018  					return
  2019  				}
  2020  			}
  2021  		}
  2022  		_ = w.p.typeOf(expr.Index) // ensure this is an index expression, not an instantiation
  2023  
  2024  		xtyp := w.p.typeOf(expr.X)
  2025  
  2026  		var keyType types2.Type
  2027  		if mapType, ok := types2.CoreType(xtyp).(*types2.Map); ok {
  2028  			keyType = mapType.Key()
  2029  		}
  2030  
  2031  		w.Code(exprIndex)
  2032  		w.expr(expr.X)
  2033  		w.pos(expr)
  2034  		w.implicitConvExpr(keyType, expr.Index)
  2035  		if keyType != nil {
  2036  			w.rtype(xtyp)
  2037  		}
  2038  
  2039  	case *syntax.SliceExpr:
  2040  		w.Code(exprSlice)
  2041  		w.expr(expr.X)
  2042  		w.pos(expr)
  2043  		for _, n := range &expr.Index {
  2044  			w.optExpr(n)
  2045  		}
  2046  
  2047  	case *syntax.AssertExpr:
  2048  		iface := w.p.typeOf(expr.X)
  2049  
  2050  		w.Code(exprAssert)
  2051  		w.expr(expr.X)
  2052  		w.pos(expr)
  2053  		w.exprType(iface, expr.Type)
  2054  		w.rtype(iface)
  2055  
  2056  	case *syntax.Operation:
  2057  		if expr.Y == nil {
  2058  			w.Code(exprUnaryOp)
  2059  			w.op(unOps[expr.Op])
  2060  			w.pos(expr)
  2061  			w.expr(expr.X)
  2062  			break
  2063  		}
  2064  
  2065  		var commonType types2.Type
  2066  		switch expr.Op {
  2067  		case syntax.Shl, syntax.Shr:
  2068  			// ok: operands are allowed to have different types
  2069  		default:
  2070  			xtyp := w.p.typeOf(expr.X)
  2071  			ytyp := w.p.typeOf(expr.Y)
  2072  			switch {
  2073  			case types2.AssignableTo(xtyp, ytyp):
  2074  				commonType = ytyp
  2075  			case types2.AssignableTo(ytyp, xtyp):
  2076  				commonType = xtyp
  2077  			default:
  2078  				w.p.fatalf(expr, "failed to find common type between %v and %v", xtyp, ytyp)
  2079  			}
  2080  		}
  2081  
  2082  		w.Code(exprBinaryOp)
  2083  		w.op(binOps[expr.Op])
  2084  		w.implicitConvExpr(commonType, expr.X)
  2085  		w.pos(expr)
  2086  		w.implicitConvExpr(commonType, expr.Y)
  2087  
  2088  	case *syntax.CallExpr:
  2089  		tv := w.p.typeAndValue(expr.Fun)
  2090  		if tv.IsType() {
  2091  			assert(len(expr.ArgList) == 1)
  2092  			assert(!expr.HasDots)
  2093  			w.convertExpr(tv.Type, expr.ArgList[0], false)
  2094  			break
  2095  		}
  2096  
  2097  		var rtype types2.Type
  2098  		if tv.IsBuiltin() {
  2099  			switch obj, _ := lookupObj(w.p, syntax.Unparen(expr.Fun)); obj.Name() {
  2100  			case "make":
  2101  				assert(len(expr.ArgList) >= 1)
  2102  				assert(!expr.HasDots)
  2103  
  2104  				w.Code(exprMake)
  2105  				w.pos(expr)
  2106  				w.exprType(nil, expr.ArgList[0])
  2107  				w.exprs(expr.ArgList[1:])
  2108  
  2109  				typ := w.p.typeOf(expr)
  2110  				switch coreType := types2.CoreType(typ).(type) {
  2111  				default:
  2112  					w.p.fatalf(expr, "unexpected core type: %v", coreType)
  2113  				case *types2.Chan:
  2114  					w.rtype(typ)
  2115  				case *types2.Map:
  2116  					w.rtype(typ)
  2117  				case *types2.Slice:
  2118  					w.rtype(sliceElem(typ))
  2119  				}
  2120  
  2121  				return
  2122  
  2123  			case "new":
  2124  				assert(len(expr.ArgList) == 1)
  2125  				assert(!expr.HasDots)
  2126  				arg := expr.ArgList[0]
  2127  
  2128  				w.Code(exprNew)
  2129  				w.pos(expr)
  2130  				tv := w.p.typeAndValue(arg)
  2131  				if w.Bool(!tv.IsType()) {
  2132  					w.expr(arg) // new(expr), go1.26
  2133  				} else {
  2134  					w.exprType(nil, arg) // new(T)
  2135  				}
  2136  				return
  2137  
  2138  			case "Sizeof":
  2139  				assert(len(expr.ArgList) == 1)
  2140  				assert(!expr.HasDots)
  2141  
  2142  				w.Code(exprSizeof)
  2143  				w.pos(expr)
  2144  				w.typ(w.p.typeOf(expr.ArgList[0]))
  2145  				return
  2146  
  2147  			case "Alignof":
  2148  				assert(len(expr.ArgList) == 1)
  2149  				assert(!expr.HasDots)
  2150  
  2151  				w.Code(exprAlignof)
  2152  				w.pos(expr)
  2153  				w.typ(w.p.typeOf(expr.ArgList[0]))
  2154  				return
  2155  
  2156  			case "Offsetof":
  2157  				assert(len(expr.ArgList) == 1)
  2158  				assert(!expr.HasDots)
  2159  				selector := syntax.Unparen(expr.ArgList[0]).(*syntax.SelectorExpr)
  2160  				index := w.p.info.Selections[selector].Index()
  2161  
  2162  				w.Code(exprOffsetof)
  2163  				w.pos(expr)
  2164  				w.typ(deref2(w.p.typeOf(selector.X)))
  2165  				w.Len(len(index) - 1)
  2166  				for _, idx := range index {
  2167  					w.Len(idx)
  2168  				}
  2169  				return
  2170  
  2171  			case "append":
  2172  				rtype = sliceElem(w.p.typeOf(expr))
  2173  			case "copy":
  2174  				typ := w.p.typeOf(expr.ArgList[0])
  2175  				if tuple, ok := typ.(*types2.Tuple); ok { // "copy(g())"
  2176  					typ = tuple.At(0).Type()
  2177  				}
  2178  				rtype = sliceElem(typ)
  2179  			case "delete":
  2180  				typ := w.p.typeOf(expr.ArgList[0])
  2181  				if tuple, ok := typ.(*types2.Tuple); ok { // "delete(g())"
  2182  					typ = tuple.At(0).Type()
  2183  				}
  2184  				rtype = typ
  2185  			case "Slice":
  2186  				rtype = sliceElem(w.p.typeOf(expr))
  2187  			}
  2188  		}
  2189  
  2190  		writeFunExpr := func() {
  2191  			fun := syntax.Unparen(expr.Fun)
  2192  
  2193  			expr := fun
  2194  			if idx, ok := expr.(*syntax.IndexExpr); ok {
  2195  				expr = idx.X
  2196  			}
  2197  			if selector, ok := expr.(*syntax.SelectorExpr); ok {
  2198  				if sel, ok := w.p.info.Selections[selector]; ok && sel.Kind() == types2.MethodVal {
  2199  					w.Bool(true) // method call
  2200  					typ := w.recvExpr(selector, sel)
  2201  					w.methodExpr(selector, typ, sel)
  2202  					return
  2203  				}
  2204  			}
  2205  
  2206  			w.Bool(false) // not a method call (i.e., normal function call)
  2207  
  2208  			if obj, inst := lookupObj(w.p, fun); w.Bool(obj != nil && inst.TypeArgs.Len() != 0) {
  2209  				obj := obj.(*types2.Func)
  2210  
  2211  				w.pos(fun)
  2212  				w.funcInst(obj, asTypeSlice(inst.TypeArgs))
  2213  				return
  2214  			}
  2215  
  2216  			w.expr(fun)
  2217  		}
  2218  
  2219  		sigType := types2.CoreType(tv.Type).(*types2.Signature)
  2220  		paramTypes := sigType.Params()
  2221  
  2222  		w.Code(exprCall)
  2223  		writeFunExpr()
  2224  		w.pos(expr)
  2225  
  2226  		paramType := func(i int) types2.Type {
  2227  			if sigType.Variadic() && !expr.HasDots && i >= paramTypes.Len()-1 {
  2228  				return paramTypes.At(paramTypes.Len() - 1).Type().(*types2.Slice).Elem()
  2229  			}
  2230  			return paramTypes.At(i).Type()
  2231  		}
  2232  
  2233  		w.multiExpr(expr, paramType, expr.ArgList)
  2234  		w.Bool(expr.HasDots)
  2235  		if rtype != nil {
  2236  			w.rtype(rtype)
  2237  		}
  2238  	}
  2239  }
  2240  
  2241  func sliceElem(typ types2.Type) types2.Type {
  2242  	return types2.CoreType(typ).(*types2.Slice).Elem()
  2243  }
  2244  
  2245  func (w *writer) optExpr(expr syntax.Expr) {
  2246  	if w.Bool(expr != nil) {
  2247  		w.expr(expr)
  2248  	}
  2249  }
  2250  
  2251  func (w *writer) methVal(expr *syntax.SelectorExpr, sel *types2.Selection) {
  2252  	w.Code(exprMethodVal)
  2253  	typ := w.recvExpr(expr, sel)
  2254  	w.pos(expr)
  2255  	w.methodExpr(expr, typ, sel)
  2256  }
  2257  
  2258  func (w *writer) methExpr(expr *syntax.SelectorExpr, sel *types2.Selection) {
  2259  	w.Code(exprMethodExpr)
  2260  
  2261  	tv := w.p.typeAndValue(expr.X)
  2262  	assert(tv.IsType())
  2263  
  2264  	index := sel.Index()
  2265  	implicits := index[:len(index)-1]
  2266  
  2267  	typ := tv.Type
  2268  	w.typ(typ)
  2269  
  2270  	w.Len(len(implicits))
  2271  	for _, ix := range implicits {
  2272  		w.Len(ix)
  2273  		typ = deref2(typ).Underlying().(*types2.Struct).Field(ix).Type()
  2274  	}
  2275  
  2276  	recv := sel.Obj().(*types2.Func).Type().(*types2.Signature).Recv().Type()
  2277  	if w.Bool(isPtrTo(typ, recv)) { // need deref
  2278  		typ = recv
  2279  	} else if w.Bool(isPtrTo(recv, typ)) { // need addr
  2280  		typ = recv
  2281  	}
  2282  
  2283  	w.pos(expr)
  2284  	w.methodExpr(expr, typ, sel)
  2285  }
  2286  
  2287  // recvExpr writes out expr.X, but handles any implicit addressing,
  2288  // dereferencing, and field selections appropriate for the method
  2289  // selection.
  2290  func (w *writer) recvExpr(expr *syntax.SelectorExpr, sel *types2.Selection) types2.Type {
  2291  	index := sel.Index()
  2292  	implicits := index[:len(index)-1]
  2293  
  2294  	w.Code(exprRecv)
  2295  	w.expr(expr.X)
  2296  	w.pos(expr)
  2297  	w.Len(len(implicits))
  2298  
  2299  	typ := w.p.typeOf(expr.X)
  2300  	for _, ix := range implicits {
  2301  		typ = deref2(typ).Underlying().(*types2.Struct).Field(ix).Type()
  2302  		w.Len(ix)
  2303  	}
  2304  
  2305  	recv := sel.Obj().(*types2.Func).Type().(*types2.Signature).Recv().Type()
  2306  	if w.Bool(isPtrTo(typ, recv)) { // needs deref
  2307  		typ = recv
  2308  	} else if w.Bool(isPtrTo(recv, typ)) { // needs addr
  2309  		typ = recv
  2310  	}
  2311  
  2312  	return typ
  2313  }
  2314  
  2315  // funcInst writes a reference to an instantiated function.
  2316  func (w *writer) funcInst(obj *types2.Func, targs []types2.Type) {
  2317  	info := w.p.objInstIdx(obj, targs, w.dict)
  2318  
  2319  	// Type arguments list contains derived types; we can emit a static
  2320  	// call to the shaped function, but need to dynamically compute the
  2321  	// runtime dictionary pointer.
  2322  	if w.Bool(info.anyDerived()) {
  2323  		w.Len(w.dict.subdictIdx(info))
  2324  		return
  2325  	}
  2326  
  2327  	// Type arguments list is statically known; we can emit a static
  2328  	// call with a statically reference to the respective runtime
  2329  	// dictionary.
  2330  	w.objInfo(info)
  2331  }
  2332  
  2333  // methodExpr writes out a reference to the method selected by
  2334  // expr. sel should be the corresponding types2.Selection, and recv
  2335  // the type produced after any implicit addressing, dereferencing, and
  2336  // field selection. (Note: recv might differ from sel.Obj()'s receiver
  2337  // parameter in the case of interface types, and is needed for
  2338  // handling type parameter methods.)
  2339  func (w *writer) methodExpr(expr *syntax.SelectorExpr, recv types2.Type, sel *types2.Selection) {
  2340  	fun := sel.Obj().(*types2.Func)
  2341  	sig := fun.Type().(*types2.Signature)
  2342  
  2343  	w.typ(recv)
  2344  
  2345  	// only pass the signature if it's not a generic method
  2346  	if isGenericMethod(sig) {
  2347  		assert(w.Version().Has(pkgbits.GenericMethods))
  2348  		w.Bool(true)
  2349  	} else {
  2350  		if w.Version().Has(pkgbits.GenericMethods) {
  2351  			w.Bool(false)
  2352  		}
  2353  		w.typ(sig)
  2354  	}
  2355  
  2356  	w.pos(expr)
  2357  	w.selector(fun)
  2358  
  2359  	// Method on a type parameter. These require an indirect call
  2360  	// through the current function's runtime dictionary.
  2361  	if typeParam, ok := types2.Unalias(recv).(*types2.TypeParam); w.Bool(ok) {
  2362  		typeParamIdx := w.dict.typeParamIndex(typeParam)
  2363  		methodInfo := w.p.selectorIdx(fun)
  2364  
  2365  		w.Len(w.dict.typeParamMethodExprIdx(typeParamIdx, methodInfo))
  2366  		return
  2367  	}
  2368  
  2369  	if isInterface(recv) != isInterface(sig.Recv().Type()) {
  2370  		w.p.fatalf(expr, "isInterface inconsistency: %v and %v", recv, sig.Recv().Type())
  2371  	}
  2372  
  2373  	if isConcreteMethod(sig) {
  2374  		tname, tExplicits := splitNamed(types2.Unalias(deref2(recv)).(*types2.Named))
  2375  		var info objInfo
  2376  		if isGenericMethod(sig) {
  2377  			// For generic methods, the shaped object is the method itself.
  2378  			mExplicits := asTypeSlice(w.p.info.Instances[expr.Sel].TypeArgs)
  2379  			info = w.p.objInstIdx(fun.Origin(), slices.Concat(tExplicits, mExplicits), w.dict)
  2380  		} else {
  2381  			// For non-generic concrete methods on generic types, the shaped object
  2382  			// is the type. The method must be looked up on the type by name.
  2383  			info = w.p.objInstIdx(tname, tExplicits, w.dict)
  2384  		}
  2385  		// We don't know all of the type arguments statically. These can be
  2386  		// handled by a static call to the shaped method, but require
  2387  		// dynamically looking up the appropriate dictionary argument
  2388  		// in the current function's runtime dictionary.
  2389  		if info.anyDerived() {
  2390  			w.Bool(true) // dynamic subdictionary
  2391  			w.Len(w.dict.subdictIdx(info))
  2392  			return
  2393  		}
  2394  		// We know all of the type arguments statically. These can be handled
  2395  		// by a static call to the shaped method, and with a static reference
  2396  		// to either the receiver type's or method's dictionary (see above).
  2397  		if len(info.explicits) > 0 {
  2398  			w.Bool(false) // no dynamic subdictionary
  2399  			w.Bool(true)  // static dictionary
  2400  			w.objInfo(info)
  2401  			return
  2402  		}
  2403  		// no type arguments
  2404  	}
  2405  
  2406  	w.Bool(false) // no dynamic subdictionary
  2407  	w.Bool(false) // no static dictionary
  2408  }
  2409  
  2410  // multiExpr writes a sequence of expressions, where the i'th value is
  2411  // implicitly converted to dstType(i). It also handles when exprs is a
  2412  // single, multi-valued expression (e.g., the multi-valued argument in
  2413  // an f(g()) call, or the RHS operand in a comma-ok assignment).
  2414  func (w *writer) multiExpr(pos poser, dstType func(int) types2.Type, exprs []syntax.Expr) {
  2415  	w.Sync(pkgbits.SyncMultiExpr)
  2416  
  2417  	if len(exprs) == 1 {
  2418  		expr := exprs[0]
  2419  		if tuple, ok := w.p.typeOf(expr).(*types2.Tuple); ok {
  2420  			assert(tuple.Len() > 1)
  2421  			w.Bool(true) // N:1 assignment
  2422  			w.pos(pos)
  2423  			w.expr(expr)
  2424  
  2425  			w.Len(tuple.Len())
  2426  			for i := 0; i < tuple.Len(); i++ {
  2427  				src := tuple.At(i).Type()
  2428  				// TODO(mdempsky): Investigate not writing src here. I think
  2429  				// the reader should be able to infer it from expr anyway.
  2430  				w.typ(src)
  2431  				if dst := dstType(i); w.Bool(dst != nil && !types2.Identical(src, dst)) {
  2432  					if src == nil || dst == nil {
  2433  						w.p.fatalf(pos, "src is %v, dst is %v", src, dst)
  2434  					}
  2435  					if !types2.AssignableTo(src, dst) {
  2436  						w.p.fatalf(pos, "%v is not assignable to %v", src, dst)
  2437  					}
  2438  					w.typ(dst)
  2439  					w.convRTTI(src, dst)
  2440  				}
  2441  			}
  2442  			return
  2443  		}
  2444  	}
  2445  
  2446  	w.Bool(false) // N:N assignment
  2447  	w.Len(len(exprs))
  2448  	for i, expr := range exprs {
  2449  		w.implicitConvExpr(dstType(i), expr)
  2450  	}
  2451  }
  2452  
  2453  // implicitConvExpr is like expr, but if dst is non-nil and different
  2454  // from expr's type, then an implicit conversion operation is inserted
  2455  // at expr's position.
  2456  func (w *writer) implicitConvExpr(dst types2.Type, expr syntax.Expr) {
  2457  	w.convertExpr(dst, expr, true)
  2458  }
  2459  
  2460  func (w *writer) convertExpr(dst types2.Type, expr syntax.Expr, implicit bool) {
  2461  	src := w.p.typeOf(expr)
  2462  
  2463  	// Omit implicit no-op conversions.
  2464  	identical := dst == nil || types2.Identical(src, dst)
  2465  	if implicit && identical {
  2466  		w.expr(expr)
  2467  		return
  2468  	}
  2469  
  2470  	if implicit && !types2.AssignableTo(src, dst) {
  2471  		w.p.fatalf(expr, "%v is not assignable to %v", src, dst)
  2472  	}
  2473  
  2474  	w.Code(exprConvert)
  2475  	w.Bool(implicit)
  2476  	w.typ(dst)
  2477  	w.pos(expr)
  2478  	w.convRTTI(src, dst)
  2479  	w.Bool(isTypeParam(dst))
  2480  	w.Bool(identical)
  2481  	w.expr(expr)
  2482  }
  2483  
  2484  func (w *writer) compLit(lit *syntax.CompositeLit) {
  2485  	typ := w.p.typeOf(lit)
  2486  
  2487  	w.Sync(pkgbits.SyncCompLit)
  2488  	w.pos(lit)
  2489  	w.typ(typ)
  2490  
  2491  	if ptr, ok := types2.CoreType(typ).(*types2.Pointer); ok {
  2492  		typ = ptr.Elem()
  2493  	}
  2494  
  2495  	if w.Version().Has(pkgbits.CompactCompLiterals) {
  2496  		switch typ0 := typ; typ := types2.CoreType(typ).(type) {
  2497  		default:
  2498  			w.p.fatalf(lit, "unexpected composite literal type: %v", typ)
  2499  		case *types2.Array:
  2500  			w.arrayElems(typ.Elem(), lit.ElemList)
  2501  		case *types2.Map:
  2502  			w.rtype(typ0)
  2503  			w.mapElems(typ.Key(), typ.Elem(), lit.ElemList)
  2504  		case *types2.Slice:
  2505  			w.arrayElems(typ.Elem(), lit.ElemList)
  2506  		case *types2.Struct:
  2507  			w.structElems(typ, lit.NKeys == 0, lit.ElemList)
  2508  		}
  2509  		return
  2510  	}
  2511  
  2512  	// old format
  2513  	var keyType, elemType types2.Type
  2514  	var structType *types2.Struct
  2515  	switch typ0 := typ; typ := types2.CoreType(typ).(type) {
  2516  	default:
  2517  		w.p.fatalf(lit, "unexpected composite literal type: %v", typ)
  2518  	case *types2.Array:
  2519  		elemType = typ.Elem()
  2520  	case *types2.Map:
  2521  		w.rtype(typ0)
  2522  		keyType, elemType = typ.Key(), typ.Elem()
  2523  	case *types2.Slice:
  2524  		elemType = typ.Elem()
  2525  	case *types2.Struct:
  2526  		structType = typ
  2527  	}
  2528  
  2529  	w.Len(len(lit.ElemList))
  2530  	for i, elem := range lit.ElemList {
  2531  		elemType := elemType
  2532  		if structType != nil {
  2533  			if kv, ok := elem.(*syntax.KeyValueExpr); ok {
  2534  				// use position of expr.Key rather than of elem (which has position of ':')
  2535  				w.pos(kv.Key)
  2536  				i = fieldIndex(w.p.info, structType, kv.Key.(*syntax.Name))
  2537  				elem = kv.Value
  2538  			} else {
  2539  				w.pos(elem)
  2540  			}
  2541  			elemType = structType.Field(i).Type()
  2542  			w.Len(i)
  2543  		} else {
  2544  			if kv, ok := elem.(*syntax.KeyValueExpr); w.Bool(ok) {
  2545  				// use position of expr.Key rather than of elem (which has position of ':')
  2546  				w.pos(kv.Key)
  2547  				w.implicitConvExpr(keyType, kv.Key)
  2548  				elem = kv.Value
  2549  			}
  2550  		}
  2551  		w.implicitConvExpr(elemType, elem)
  2552  	}
  2553  }
  2554  
  2555  func (w *writer) arrayElems(elemType types2.Type, elems []syntax.Expr) {
  2556  	valuesOnly := true
  2557  	for _, elem := range elems {
  2558  		if _, ok := elem.(*syntax.KeyValueExpr); ok {
  2559  			valuesOnly = false
  2560  			break
  2561  		}
  2562  	}
  2563  
  2564  	if valuesOnly {
  2565  		w.Int(len(elems))
  2566  		for _, elem := range elems {
  2567  			w.implicitConvExpr(elemType, elem)
  2568  		}
  2569  		return
  2570  	}
  2571  	// some elements may have a key
  2572  	w.Int(-len(elems))
  2573  	for _, elem := range elems {
  2574  		if kv, ok := elem.(*syntax.KeyValueExpr); w.Bool(ok) {
  2575  			w.pos(kv.Key) // use position of Key rather than of elem (which has position of ':')
  2576  			w.implicitConvExpr(nil, kv.Key)
  2577  			elem = kv.Value
  2578  		}
  2579  		w.implicitConvExpr(elemType, elem)
  2580  	}
  2581  }
  2582  
  2583  func (w *writer) mapElems(keyType, valueType types2.Type, elems []syntax.Expr) {
  2584  	// all elements have a key
  2585  	w.Int(-len(elems))
  2586  	for _, elem := range elems {
  2587  		kv := elem.(*syntax.KeyValueExpr)
  2588  		w.pos(kv.Key) // use position of Key rather than of elem (which has position of ':')
  2589  		w.implicitConvExpr(keyType, kv.Key)
  2590  		w.implicitConvExpr(valueType, kv.Value)
  2591  	}
  2592  }
  2593  
  2594  func (w *writer) structElems(typ *types2.Struct, valuesOnly bool, elems []syntax.Expr) {
  2595  	n := len(elems)
  2596  	if valuesOnly {
  2597  		// no element has a key
  2598  		w.Int(n)
  2599  		for i, elem := range elems {
  2600  			w.pos(elem)
  2601  			w.implicitConvExpr(typ.Field(i).Type(), elem)
  2602  		}
  2603  		return
  2604  	}
  2605  	// all elements have a key
  2606  	w.Int(-n)
  2607  	for _, elem := range elems {
  2608  		kv := elem.(*syntax.KeyValueExpr)
  2609  		w.pos(kv.Key) // use position of Key rather than of elem (which has position of ':')
  2610  		// TODO(gri): rather than doing this lookup again, perhaps the index should be recorded by types2
  2611  		fld, index, _ := types2.LookupFieldOrMethod(typ, false, w.p.curpkg, kv.Key.(*syntax.Name).Value)
  2612  		if n := len(index); n > 1 {
  2613  			// embedded field
  2614  			w.Int(-n)
  2615  			for _, i := range index {
  2616  				w.Int(i)
  2617  			}
  2618  		} else { // n == 1
  2619  			w.Int(index[0])
  2620  		}
  2621  		w.implicitConvExpr(fld.Type(), kv.Value)
  2622  	}
  2623  }
  2624  
  2625  func (w *writer) funcLit(expr *syntax.FuncLit) {
  2626  	sig := w.p.typeOf(expr).(*types2.Signature)
  2627  
  2628  	body, closureVars := w.p.bodyIdx(sig, expr.Body, w.dict)
  2629  
  2630  	w.Sync(pkgbits.SyncFuncLit)
  2631  	w.pos(expr)
  2632  	w.signature(sig)
  2633  	w.Bool(w.p.rangeFuncBodyClosures[expr])
  2634  
  2635  	w.Len(len(closureVars))
  2636  	for _, cv := range closureVars {
  2637  		w.pos(cv.pos)
  2638  		w.useLocal(cv.pos, cv.var_)
  2639  	}
  2640  
  2641  	w.Reloc(pkgbits.SectionBody, body)
  2642  }
  2643  
  2644  type posVar struct {
  2645  	pos  syntax.Pos
  2646  	var_ *types2.Var
  2647  }
  2648  
  2649  func (p posVar) String() string {
  2650  	return p.pos.String() + ":" + p.var_.String()
  2651  }
  2652  
  2653  func (w *writer) exprs(exprs []syntax.Expr) {
  2654  	w.Sync(pkgbits.SyncExprs)
  2655  	w.Len(len(exprs))
  2656  	for _, expr := range exprs {
  2657  		w.expr(expr)
  2658  	}
  2659  }
  2660  
  2661  // rtype writes information so that the reader can construct an
  2662  // expression of type *runtime._type representing typ.
  2663  func (w *writer) rtype(typ types2.Type) {
  2664  	typ = types2.Default(typ)
  2665  
  2666  	info := w.p.typIdx(typ, w.dict)
  2667  	w.rtypeInfo(info)
  2668  }
  2669  
  2670  func (w *writer) rtypeInfo(info typeInfo) {
  2671  	w.Sync(pkgbits.SyncRType)
  2672  
  2673  	if w.Bool(info.derived) {
  2674  		w.Len(w.dict.rtypeIdx(info))
  2675  	} else {
  2676  		w.typInfo(info)
  2677  	}
  2678  }
  2679  
  2680  // varDictIndex writes out information for populating DictIndex for
  2681  // the ir.Name that will represent obj.
  2682  func (w *writer) varDictIndex(obj *types2.Var) {
  2683  	info := w.p.typIdx(obj.Type(), w.dict)
  2684  	if w.Bool(info.derived) {
  2685  		w.Len(w.dict.rtypeIdx(info))
  2686  	}
  2687  }
  2688  
  2689  // isUntyped reports whether typ is an untyped type.
  2690  func isUntyped(typ types2.Type) bool {
  2691  	// Note: types2.Unalias is unnecessary here, since untyped types can't be aliased.
  2692  	basic, ok := typ.(*types2.Basic)
  2693  	return ok && basic.Info()&types2.IsUntyped != 0
  2694  }
  2695  
  2696  // isTuple reports whether typ is a tuple type.
  2697  func isTuple(typ types2.Type) bool {
  2698  	// Note: types2.Unalias is unnecessary here, since tuple types can't be aliased.
  2699  	_, ok := typ.(*types2.Tuple)
  2700  	return ok
  2701  }
  2702  
  2703  func (w *writer) itab(typ, iface types2.Type) {
  2704  	typ = types2.Default(typ)
  2705  	iface = types2.Default(iface)
  2706  
  2707  	typInfo := w.p.typIdx(typ, w.dict)
  2708  	ifaceInfo := w.p.typIdx(iface, w.dict)
  2709  
  2710  	w.rtypeInfo(typInfo)
  2711  	w.rtypeInfo(ifaceInfo)
  2712  	if w.Bool(typInfo.derived || ifaceInfo.derived) {
  2713  		w.Len(w.dict.itabIdx(typInfo, ifaceInfo))
  2714  	}
  2715  }
  2716  
  2717  // convRTTI writes information so that the reader can construct
  2718  // expressions for converting from src to dst.
  2719  func (w *writer) convRTTI(src, dst types2.Type) {
  2720  	w.Sync(pkgbits.SyncConvRTTI)
  2721  	w.itab(src, dst)
  2722  }
  2723  
  2724  func (w *writer) exprType(iface types2.Type, typ syntax.Expr) {
  2725  	base.Assertf(iface == nil || isInterface(iface), "%v must be nil or an interface type", iface)
  2726  
  2727  	tv := w.p.typeAndValue(typ)
  2728  	assert(tv.IsType())
  2729  
  2730  	w.Sync(pkgbits.SyncExprType)
  2731  	w.pos(typ)
  2732  
  2733  	if w.Bool(iface != nil && !iface.Underlying().(*types2.Interface).Empty()) {
  2734  		w.itab(tv.Type, iface)
  2735  	} else {
  2736  		w.rtype(tv.Type)
  2737  
  2738  		info := w.p.typIdx(tv.Type, w.dict)
  2739  		w.Bool(info.derived)
  2740  	}
  2741  }
  2742  
  2743  // isInterface reports whether typ is known to be an interface type.
  2744  // If typ is a type parameter, then isInterface reports an internal
  2745  // compiler error instead.
  2746  func isInterface(typ types2.Type) bool {
  2747  	if _, ok := types2.Unalias(typ).(*types2.TypeParam); ok {
  2748  		// typ is a type parameter and may be instantiated as either a
  2749  		// concrete or interface type, so the writer can't depend on
  2750  		// knowing this.
  2751  		base.Fatalf("%v is a type parameter", typ)
  2752  	}
  2753  
  2754  	_, ok := typ.Underlying().(*types2.Interface)
  2755  	return ok
  2756  }
  2757  
  2758  // isConcreteMethod reports whether typ is a concrete method. That is,
  2759  // it's a method with a receiver that isn't an interface type.
  2760  func isConcreteMethod(typ types2.Type) bool {
  2761  	sig, ok := typ.(*types2.Signature)
  2762  	return ok && sig.Recv() != nil && !isInterface(sig.Recv().Type())
  2763  }
  2764  
  2765  // TODO(mark): Use isGenericMethod. It is included now to help justify
  2766  // the existence of isConcreteMethod.
  2767  
  2768  // isGenericMethod reports whether typ is a generic method. That is,
  2769  // it's a method with type parameters apart from those which may or
  2770  // may not appear on the receiver type.
  2771  //
  2772  // Note that generic methods are always concrete methods.
  2773  func isGenericMethod(typ types2.Type) bool {
  2774  	sig, ok := typ.(*types2.Signature)
  2775  	return ok && sig.Recv() != nil && sig.TypeParams().Len() > 0
  2776  }
  2777  
  2778  // op writes an Op into the bitstream.
  2779  func (w *writer) op(op ir.Op) {
  2780  	// TODO(mdempsky): Remove in favor of explicit codes? Would make
  2781  	// export data more stable against internal refactorings, but low
  2782  	// priority at the moment.
  2783  	assert(op != 0)
  2784  	w.Sync(pkgbits.SyncOp)
  2785  	w.Len(int(op))
  2786  }
  2787  
  2788  // @@@ Package initialization
  2789  
  2790  // Caution: This code is still clumsy, because toolstash -cmp is
  2791  // particularly sensitive to it.
  2792  
  2793  type typeDeclGen struct {
  2794  	*syntax.TypeDecl
  2795  	gen int
  2796  
  2797  	// Implicit type parameters in scope at this type declaration.
  2798  	implicits []*types2.TypeParam
  2799  }
  2800  
  2801  type fileImports struct {
  2802  	importedEmbed, importedUnsafe bool
  2803  }
  2804  
  2805  // declCollector is a visitor type that collects compiler-needed
  2806  // information about declarations that types2 doesn't track.
  2807  //
  2808  // Notably, it maps declared types and functions back to their
  2809  // declaration statement, keeps track of implicit type parameters, and
  2810  // assigns unique type "generation" numbers to local defined types.
  2811  type declCollector struct {
  2812  	pw         *pkgWriter
  2813  	typegen    *int
  2814  	file       *fileImports
  2815  	withinFunc bool
  2816  	implicits  []*types2.TypeParam
  2817  }
  2818  
  2819  func (c *declCollector) withTParams(obj types2.Object) *declCollector {
  2820  	tparams := slices.Concat(objRecvTypeParams(obj), objTypeParams(obj))
  2821  	if len(tparams) == 0 {
  2822  		return c
  2823  	}
  2824  
  2825  	copy := *c
  2826  	copy.implicits = copy.implicits[:len(copy.implicits):len(copy.implicits)]
  2827  	for _, tparam := range tparams {
  2828  		copy.implicits = append(copy.implicits, tparam)
  2829  	}
  2830  	return &copy
  2831  }
  2832  
  2833  func (c *declCollector) Visit(n syntax.Node) syntax.Visitor {
  2834  	pw := c.pw
  2835  
  2836  	switch n := n.(type) {
  2837  	case *syntax.File:
  2838  		pw.checkPragmas(n.Pragma, ir.GoBuildPragma, false)
  2839  
  2840  	case *syntax.ImportDecl:
  2841  		pw.checkPragmas(n.Pragma, 0, false)
  2842  
  2843  		switch pw.info.PkgNameOf(n).Imported().Path() {
  2844  		case "embed":
  2845  			c.file.importedEmbed = true
  2846  		case "unsafe":
  2847  			c.file.importedUnsafe = true
  2848  		}
  2849  
  2850  	case *syntax.ConstDecl:
  2851  		pw.checkPragmas(n.Pragma, 0, false)
  2852  
  2853  	case *syntax.FuncDecl:
  2854  		pw.checkPragmas(n.Pragma, funcPragmas, false)
  2855  
  2856  		obj := pw.info.Defs[n.Name].(*types2.Func)
  2857  		pw.funDecls[obj] = n
  2858  
  2859  		return c.withTParams(obj)
  2860  
  2861  	case *syntax.TypeDecl:
  2862  		obj := pw.info.Defs[n.Name].(*types2.TypeName)
  2863  		d := typeDeclGen{TypeDecl: n, implicits: c.implicits}
  2864  
  2865  		if n.Alias {
  2866  			pw.checkPragmas(n.Pragma, 0, false)
  2867  		} else {
  2868  			pw.checkPragmas(n.Pragma, 0, false)
  2869  
  2870  			// Assign a unique ID to function-scoped defined types.
  2871  			if c.withinFunc {
  2872  				*c.typegen++
  2873  				d.gen = *c.typegen
  2874  			}
  2875  		}
  2876  
  2877  		pw.typDecls[obj] = d
  2878  
  2879  		// TODO(mdempsky): Omit? Not strictly necessary; only matters for
  2880  		// type declarations within function literals within parameterized
  2881  		// type declarations, but types2 the function literals will be
  2882  		// constant folded away.
  2883  		return c.withTParams(obj)
  2884  
  2885  	case *syntax.VarDecl:
  2886  		pw.checkPragmas(n.Pragma, 0, true)
  2887  
  2888  		if p, ok := n.Pragma.(*pragmas); ok && len(p.Embeds) > 0 {
  2889  			if err := checkEmbed(n, c.file.importedEmbed, c.withinFunc); err != nil {
  2890  				pw.errorf(p.Embeds[0].Pos, "%s", err)
  2891  			}
  2892  		}
  2893  
  2894  	case *syntax.BlockStmt:
  2895  		if !c.withinFunc {
  2896  			copy := *c
  2897  			copy.withinFunc = true
  2898  			return &copy
  2899  		}
  2900  	}
  2901  
  2902  	return c
  2903  }
  2904  
  2905  func (pw *pkgWriter) collectDecls(noders []*noder) {
  2906  	var typegen int
  2907  	for _, p := range noders {
  2908  		var file fileImports
  2909  
  2910  		syntax.Walk(p.file, &declCollector{
  2911  			pw:      pw,
  2912  			typegen: &typegen,
  2913  			file:    &file,
  2914  		})
  2915  
  2916  		pw.cgoPragmas = append(pw.cgoPragmas, p.pragcgobuf...)
  2917  
  2918  		for _, l := range p.linknames {
  2919  			directive := "go:linkname"
  2920  			if l.std {
  2921  				directive = "go:linknamestd"
  2922  			}
  2923  			if !file.importedUnsafe {
  2924  				pw.errorf(l.pos, "//%s only allowed in Go files that import \"unsafe\"", directive)
  2925  				continue
  2926  			}
  2927  			if strings.Contains(l.remote, "[") && strings.Contains(l.remote, "]") {
  2928  				pw.errorf(l.pos, "//%s reference of an instantiation is not allowed", directive)
  2929  				continue
  2930  			}
  2931  
  2932  			switch obj := pw.curpkg.Scope().Lookup(l.local).(type) {
  2933  			case *types2.Func, *types2.Var:
  2934  				if _, ok := pw.linknames[obj]; !ok {
  2935  					pw.linknames[obj] = struct {
  2936  						remote string
  2937  						std    bool
  2938  					}{l.remote, l.std}
  2939  				} else {
  2940  					pw.errorf(l.pos, "duplicate //%s for %s", directive, l.local)
  2941  				}
  2942  
  2943  			default:
  2944  				if types.AllowsGoVersion(1, 18) {
  2945  					pw.errorf(l.pos, "//%s must refer to declared function or variable", directive)
  2946  				}
  2947  			}
  2948  		}
  2949  	}
  2950  }
  2951  
  2952  func (pw *pkgWriter) checkPragmas(p syntax.Pragma, allowed ir.PragmaFlag, embedOK bool) {
  2953  	if p == nil {
  2954  		return
  2955  	}
  2956  	pragma := p.(*pragmas)
  2957  
  2958  	for _, pos := range pragma.Pos {
  2959  		if pos.Flag&^allowed != 0 {
  2960  			pw.errorf(pos.Pos, "misplaced compiler directive")
  2961  		}
  2962  	}
  2963  
  2964  	if !embedOK {
  2965  		for _, e := range pragma.Embeds {
  2966  			pw.errorf(e.Pos, "misplaced go:embed directive")
  2967  		}
  2968  	}
  2969  }
  2970  
  2971  func (w *writer) pkgInit(noders []*noder) {
  2972  	w.Len(len(w.p.cgoPragmas))
  2973  	for _, cgoPragma := range w.p.cgoPragmas {
  2974  		w.Strings(cgoPragma)
  2975  	}
  2976  
  2977  	w.pkgInitOrder()
  2978  
  2979  	w.Sync(pkgbits.SyncDecls)
  2980  	for _, p := range noders {
  2981  		for _, decl := range p.file.DeclList {
  2982  			w.pkgDecl(decl)
  2983  		}
  2984  	}
  2985  	w.Code(declEnd)
  2986  
  2987  	w.Sync(pkgbits.SyncEOF)
  2988  }
  2989  
  2990  func (w *writer) pkgInitOrder() {
  2991  	// TODO(mdempsky): Write as a function body instead?
  2992  	w.Len(len(w.p.info.InitOrder))
  2993  	for _, init := range w.p.info.InitOrder {
  2994  		w.Len(len(init.Lhs))
  2995  		for _, v := range init.Lhs {
  2996  			w.obj(v, nil)
  2997  		}
  2998  		w.expr(init.Rhs)
  2999  	}
  3000  }
  3001  
  3002  func (w *writer) pkgDecl(decl syntax.Decl) {
  3003  	switch decl := decl.(type) {
  3004  	default:
  3005  		w.p.unexpected("declaration", decl)
  3006  
  3007  	case *syntax.ImportDecl:
  3008  
  3009  	case *syntax.ConstDecl:
  3010  		w.Code(declOther)
  3011  		w.pkgObjs(decl.NameList...)
  3012  
  3013  	case *syntax.FuncDecl:
  3014  		if decl.Name.Value == "_" {
  3015  			break // skip blank functions
  3016  		}
  3017  
  3018  		obj := w.p.info.Defs[decl.Name].(*types2.Func)
  3019  		sig := obj.Type().(*types2.Signature)
  3020  
  3021  		if sig.RecvTypeParams() != nil || sig.TypeParams() != nil {
  3022  			break // skip generic functions
  3023  		}
  3024  
  3025  		if recv := sig.Recv(); recv != nil {
  3026  			w.Code(declMethod)
  3027  			w.typ(recvBase(recv))
  3028  			w.selector(obj)
  3029  			break
  3030  		}
  3031  
  3032  		w.Code(declFunc)
  3033  		w.pkgObjs(decl.Name)
  3034  
  3035  	case *syntax.TypeDecl:
  3036  		if len(decl.TParamList) != 0 {
  3037  			break // skip generic type decls
  3038  		}
  3039  
  3040  		if decl.Name.Value == "_" {
  3041  			break // skip blank type decls
  3042  		}
  3043  
  3044  		name := w.p.info.Defs[decl.Name].(*types2.TypeName)
  3045  		// Skip type declarations for interfaces that are only usable as
  3046  		// type parameter bounds.
  3047  		if iface, ok := name.Type().Underlying().(*types2.Interface); ok && !iface.IsMethodSet() {
  3048  			break
  3049  		}
  3050  
  3051  		w.Code(declOther)
  3052  		w.pkgObjs(decl.Name)
  3053  
  3054  	case *syntax.VarDecl:
  3055  		w.Code(declVar)
  3056  		w.pkgObjs(decl.NameList...)
  3057  
  3058  		var embeds []pragmaEmbed
  3059  		if p, ok := decl.Pragma.(*pragmas); ok {
  3060  			embeds = p.Embeds
  3061  		}
  3062  		w.Len(len(embeds))
  3063  		for _, embed := range embeds {
  3064  			w.pos(embed.Pos)
  3065  			w.Strings(embed.Patterns)
  3066  		}
  3067  	}
  3068  }
  3069  
  3070  func (w *writer) pkgObjs(names ...*syntax.Name) {
  3071  	w.Sync(pkgbits.SyncDeclNames)
  3072  	w.Len(len(names))
  3073  
  3074  	for _, name := range names {
  3075  		obj, ok := w.p.info.Defs[name]
  3076  		assert(ok)
  3077  
  3078  		w.Sync(pkgbits.SyncDeclName)
  3079  		w.obj(obj, nil)
  3080  	}
  3081  }
  3082  
  3083  // @@@ Helpers
  3084  
  3085  // staticBool analyzes a boolean expression and reports whether it's
  3086  // always true (positive result), always false (negative result), or
  3087  // unknown (zero).
  3088  //
  3089  // It also simplifies the expression while preserving semantics, if
  3090  // possible.
  3091  func (pw *pkgWriter) staticBool(ep *syntax.Expr) int {
  3092  	if val := pw.typeAndValue(*ep).Value; val != nil {
  3093  		if constant.BoolVal(val) {
  3094  			return +1
  3095  		} else {
  3096  			return -1
  3097  		}
  3098  	}
  3099  
  3100  	if e, ok := (*ep).(*syntax.Operation); ok {
  3101  		switch e.Op {
  3102  		case syntax.Not:
  3103  			return pw.staticBool(&e.X)
  3104  
  3105  		case syntax.AndAnd:
  3106  			x := pw.staticBool(&e.X)
  3107  			if x < 0 {
  3108  				*ep = e.X
  3109  				return x
  3110  			}
  3111  
  3112  			y := pw.staticBool(&e.Y)
  3113  			if x > 0 || y < 0 {
  3114  				if pw.typeAndValue(e.X).Value != nil {
  3115  					*ep = e.Y
  3116  				}
  3117  				return y
  3118  			}
  3119  
  3120  		case syntax.OrOr:
  3121  			x := pw.staticBool(&e.X)
  3122  			if x > 0 {
  3123  				*ep = e.X
  3124  				return x
  3125  			}
  3126  
  3127  			y := pw.staticBool(&e.Y)
  3128  			if x < 0 || y > 0 {
  3129  				if pw.typeAndValue(e.X).Value != nil {
  3130  					*ep = e.Y
  3131  				}
  3132  				return y
  3133  			}
  3134  		}
  3135  	}
  3136  
  3137  	return 0
  3138  }
  3139  
  3140  // hasImplicitTypeParams reports whether obj is a defined type with
  3141  // implicit type parameters (e.g., declared within a generic function
  3142  // or method).
  3143  func (pw *pkgWriter) hasImplicitTypeParams(obj *types2.TypeName) bool {
  3144  	if obj.Pkg() == pw.curpkg {
  3145  		decl, ok := pw.typDecls[obj]
  3146  		assert(ok)
  3147  		if len(decl.implicits) != 0 {
  3148  			return true
  3149  		}
  3150  	}
  3151  	return false
  3152  }
  3153  
  3154  // isDefinedType reports whether obj is a defined type.
  3155  func isDefinedType(obj types2.Object) bool {
  3156  	if obj, ok := obj.(*types2.TypeName); ok {
  3157  		return !obj.IsAlias()
  3158  	}
  3159  	return false
  3160  }
  3161  
  3162  // isGlobal reports whether obj was declared at package scope.
  3163  //
  3164  // Caveat: blank objects are not declared.
  3165  func isGlobal(obj types2.Object) bool {
  3166  	return obj.Parent() == obj.Pkg().Scope()
  3167  }
  3168  
  3169  // lookupObj returns the object that expr refers to, if any. If expr
  3170  // is an explicit instantiation of a generic object, then the instance
  3171  // object is returned as well.
  3172  func lookupObj(p *pkgWriter, expr syntax.Expr) (obj types2.Object, inst types2.Instance) {
  3173  	if index, ok := expr.(*syntax.IndexExpr); ok {
  3174  		args := syntax.UnpackListExpr(index.Index)
  3175  		if len(args) == 1 {
  3176  			tv := p.typeAndValue(args[0])
  3177  			if tv.IsValue() {
  3178  				return // normal index expression
  3179  			}
  3180  		}
  3181  
  3182  		expr = index.X
  3183  	}
  3184  
  3185  	// Strip package qualifier, if present.
  3186  	if sel, ok := expr.(*syntax.SelectorExpr); ok {
  3187  		if !isPkgQual(p.info, sel) {
  3188  			return // normal selector expression
  3189  		}
  3190  		expr = sel.Sel
  3191  	}
  3192  
  3193  	if name, ok := expr.(*syntax.Name); ok {
  3194  		obj = p.info.Uses[name]
  3195  		inst = p.info.Instances[name]
  3196  	}
  3197  	return
  3198  }
  3199  
  3200  // isPkgQual reports whether the given selector expression is a
  3201  // package-qualified identifier.
  3202  func isPkgQual(info *types2.Info, sel *syntax.SelectorExpr) bool {
  3203  	if name, ok := sel.X.(*syntax.Name); ok {
  3204  		_, isPkgName := info.Uses[name].(*types2.PkgName)
  3205  		return isPkgName
  3206  	}
  3207  	return false
  3208  }
  3209  
  3210  // isNil reports whether expr is a (possibly parenthesized) reference
  3211  // to the predeclared nil value.
  3212  func isNil(p *pkgWriter, expr syntax.Expr) bool {
  3213  	tv := p.typeAndValue(expr)
  3214  	return tv.IsNil()
  3215  }
  3216  
  3217  // isBuiltin reports whether expr is a (possibly parenthesized)
  3218  // referenced to the specified built-in function.
  3219  func (pw *pkgWriter) isBuiltin(expr syntax.Expr, builtin string) bool {
  3220  	if name, ok := syntax.Unparen(expr).(*syntax.Name); ok && name.Value == builtin {
  3221  		return pw.typeAndValue(name).IsBuiltin()
  3222  	}
  3223  	return false
  3224  }
  3225  
  3226  // recvBase returns the base type for the given receiver parameter.
  3227  func recvBase(recv *types2.Var) *types2.Named {
  3228  	typ := types2.Unalias(recv.Type())
  3229  	if ptr, ok := typ.(*types2.Pointer); ok {
  3230  		typ = types2.Unalias(ptr.Elem())
  3231  	}
  3232  	return typ.(*types2.Named)
  3233  }
  3234  
  3235  // namesAsExpr returns a list of names as a syntax.Expr.
  3236  func namesAsExpr(names []*syntax.Name) syntax.Expr {
  3237  	if len(names) == 1 {
  3238  		return names[0]
  3239  	}
  3240  
  3241  	exprs := make([]syntax.Expr, len(names))
  3242  	for i, name := range names {
  3243  		exprs[i] = name
  3244  	}
  3245  	return &syntax.ListExpr{ElemList: exprs}
  3246  }
  3247  
  3248  // fieldIndex returns the index of the struct field named by key.
  3249  func fieldIndex(info *types2.Info, str *types2.Struct, key *syntax.Name) int {
  3250  	field := info.Uses[key].(*types2.Var)
  3251  
  3252  	for i := 0; i < str.NumFields(); i++ {
  3253  		if str.Field(i) == field {
  3254  			return i
  3255  		}
  3256  	}
  3257  
  3258  	panic(fmt.Sprintf("%s: %v is not a field of %v", key.Pos(), field, str))
  3259  }
  3260  
  3261  // objRecvTypeParams returns the receiver type parameters on the given object.
  3262  func objRecvTypeParams(obj types2.Object) []*types2.TypeParam {
  3263  	if f, ok := obj.(*types2.Func); ok {
  3264  		return asTypeParamSlice(f.Signature().RecvTypeParams())
  3265  	}
  3266  	return nil
  3267  }
  3268  
  3269  // objTypeParams returns the type parameters on the given object.
  3270  func objTypeParams(obj types2.Object) []*types2.TypeParam {
  3271  	switch t := obj.(type) {
  3272  	case *types2.Func:
  3273  		return asTypeParamSlice(t.Signature().TypeParams())
  3274  	case *types2.TypeName:
  3275  		switch t := obj.Type().(type) {
  3276  		case *types2.Named:
  3277  			return asTypeParamSlice(t.TypeParams())
  3278  		case *types2.Alias:
  3279  			return asTypeParamSlice(t.TypeParams())
  3280  		}
  3281  	}
  3282  	return nil
  3283  }
  3284  
  3285  // asTypeParamSlice unpacks a types2.TypeParamList to a []types2.TypeParam
  3286  func asTypeParamSlice(l *types2.TypeParamList) []*types2.TypeParam {
  3287  	if l.Len() == 0 {
  3288  		return nil
  3289  	}
  3290  	s := make([]*types2.TypeParam, l.Len())
  3291  	for i := range l.Len() {
  3292  		s[i] = l.At(i)
  3293  	}
  3294  	return s
  3295  }
  3296  
  3297  // splitNamed decomposes a use of a defined type into its original
  3298  // type definition and the type arguments used to instantiate it.
  3299  func splitNamed(typ *types2.Named) (*types2.TypeName, []types2.Type) {
  3300  	base.Assertf(typ.TypeParams().Len() == typ.TypeArgs().Len(), "use of uninstantiated type: %v", typ)
  3301  
  3302  	orig := typ.Origin()
  3303  	base.Assertf(orig.TypeArgs() == nil, "origin %v of %v has type arguments", orig, typ)
  3304  	base.Assertf(typ.Obj() == orig.Obj(), "%v has object %v, but %v has object %v", typ, typ.Obj(), orig, orig.Obj())
  3305  
  3306  	return typ.Obj(), asTypeSlice(typ.TypeArgs())
  3307  }
  3308  
  3309  // splitAlias is like splitNamed, but for an alias type.
  3310  func splitAlias(typ *types2.Alias) (*types2.TypeName, []types2.Type) {
  3311  	orig := typ.Origin()
  3312  	base.Assertf(typ.Obj() == orig.Obj(), "alias type %v has object %v, but %v has object %v", typ, typ.Obj(), orig, orig.Obj())
  3313  
  3314  	return typ.Obj(), asTypeSlice(typ.TypeArgs())
  3315  }
  3316  
  3317  // asTypeSlice unpacks a types2.TypeList to a []types2.Type
  3318  func asTypeSlice(l *types2.TypeList) []types2.Type {
  3319  	if l.Len() == 0 {
  3320  		return nil
  3321  	}
  3322  	s := make([]types2.Type, l.Len())
  3323  	for i := range l.Len() {
  3324  		s[i] = l.At(i)
  3325  	}
  3326  	return s
  3327  }
  3328  
  3329  func asPragmaFlag(p syntax.Pragma) ir.PragmaFlag {
  3330  	if p == nil {
  3331  		return 0
  3332  	}
  3333  	return p.(*pragmas).Flag
  3334  }
  3335  
  3336  func asWasmImport(p syntax.Pragma) *WasmImport {
  3337  	if p == nil {
  3338  		return nil
  3339  	}
  3340  	return p.(*pragmas).WasmImport
  3341  }
  3342  
  3343  func asWasmExport(p syntax.Pragma) *WasmExport {
  3344  	if p == nil {
  3345  		return nil
  3346  	}
  3347  	return p.(*pragmas).WasmExport
  3348  }
  3349  
  3350  // isPtrTo reports whether from is the type *to.
  3351  func isPtrTo(from, to types2.Type) bool {
  3352  	ptr, ok := types2.Unalias(from).(*types2.Pointer)
  3353  	return ok && types2.Identical(ptr.Elem(), to)
  3354  }
  3355  
  3356  // hasFallthrough reports whether stmts ends in a fallthrough
  3357  // statement.
  3358  func hasFallthrough(stmts []syntax.Stmt) bool {
  3359  	// From spec: the last non-empty statement may be a (possibly labeled) "fallthrough" statement
  3360  	// Stripping (possible nested) labeled statement if any.
  3361  	stmt := lastNonEmptyStmt(stmts)
  3362  	for {
  3363  		ls, ok := stmt.(*syntax.LabeledStmt)
  3364  		if !ok {
  3365  			break
  3366  		}
  3367  		stmt = ls.Stmt
  3368  	}
  3369  	last, ok := stmt.(*syntax.BranchStmt)
  3370  	return ok && last.Tok == syntax.Fallthrough
  3371  }
  3372  
  3373  // lastNonEmptyStmt returns the last non-empty statement in list, if
  3374  // any.
  3375  func lastNonEmptyStmt(stmts []syntax.Stmt) syntax.Stmt {
  3376  	for i := len(stmts) - 1; i >= 0; i-- {
  3377  		stmt := stmts[i]
  3378  		if _, ok := stmt.(*syntax.EmptyStmt); !ok {
  3379  			return stmt
  3380  		}
  3381  	}
  3382  	return nil
  3383  }
  3384  
  3385  // terminates reports whether stmt terminates normal control flow
  3386  // (i.e., does not merely advance to the following statement).
  3387  func (pw *pkgWriter) terminates(stmt syntax.Stmt) bool {
  3388  	switch stmt := stmt.(type) {
  3389  	case *syntax.BranchStmt:
  3390  		if stmt.Tok == syntax.Goto {
  3391  			return true
  3392  		}
  3393  	case *syntax.ReturnStmt:
  3394  		return true
  3395  	case *syntax.ExprStmt:
  3396  		if call, ok := syntax.Unparen(stmt.X).(*syntax.CallExpr); ok {
  3397  			if pw.isBuiltin(call.Fun, "panic") {
  3398  				return true
  3399  			}
  3400  		}
  3401  
  3402  		// The handling of BlockStmt here is approximate, but it serves to
  3403  		// allow dead-code elimination for:
  3404  		//
  3405  		//	if true {
  3406  		//		return x
  3407  		//	}
  3408  		//	unreachable
  3409  	case *syntax.IfStmt:
  3410  		cond := pw.staticBool(&stmt.Cond)
  3411  		return (cond < 0 || pw.terminates(stmt.Then)) && (cond > 0 || pw.terminates(stmt.Else))
  3412  	case *syntax.BlockStmt:
  3413  		return pw.terminates(lastNonEmptyStmt(stmt.List))
  3414  	}
  3415  
  3416  	return false
  3417  }
  3418  

View as plain text