github.com/bir3/gocompiler@v0.9.2202/src/cmd/compile/internal/noder/writer.go (about)

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