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

View as plain text