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

     1  // UNREVIEWED
     2  
     3  // Copyright 2021 The Go Authors. All rights reserved.
     4  // Use of this source code is governed by a BSD-style
     5  // license that can be found in the LICENSE file.
     6  
     7  package noder
     8  
     9  import (
    10  	"fmt"
    11  	"go/constant"
    12  
    13  	"cmd/compile/internal/base"
    14  	"cmd/compile/internal/ir"
    15  	"cmd/compile/internal/syntax"
    16  	"cmd/compile/internal/types2"
    17  )
    18  
    19  type pkgWriter struct {
    20  	pkgEncoder
    21  
    22  	m      posMap
    23  	curpkg *types2.Package
    24  	info   *types2.Info
    25  
    26  	posBasesIdx map[*syntax.PosBase]int
    27  	pkgsIdx     map[*types2.Package]int
    28  	typsIdx     map[types2.Type]int
    29  	globalsIdx  map[types2.Object]int
    30  
    31  	funDecls map[*types2.Func]*syntax.FuncDecl
    32  	typDecls map[*types2.TypeName]typeDeclGen
    33  
    34  	linknames  map[types2.Object]string
    35  	cgoPragmas [][]string
    36  
    37  	dups dupTypes
    38  }
    39  
    40  func newPkgWriter(m posMap, pkg *types2.Package, info *types2.Info) *pkgWriter {
    41  	return &pkgWriter{
    42  		pkgEncoder: newPkgEncoder(),
    43  
    44  		m:      m,
    45  		curpkg: pkg,
    46  		info:   info,
    47  
    48  		pkgsIdx:    make(map[*types2.Package]int),
    49  		globalsIdx: make(map[types2.Object]int),
    50  		typsIdx:    make(map[types2.Type]int),
    51  
    52  		posBasesIdx: make(map[*syntax.PosBase]int),
    53  
    54  		funDecls: make(map[*types2.Func]*syntax.FuncDecl),
    55  		typDecls: make(map[*types2.TypeName]typeDeclGen),
    56  
    57  		linknames: make(map[types2.Object]string),
    58  	}
    59  }
    60  
    61  func (pw *pkgWriter) errorf(p poser, msg string, args ...interface{}) {
    62  	base.ErrorfAt(pw.m.pos(p), msg, args...)
    63  }
    64  
    65  func (pw *pkgWriter) fatalf(p poser, msg string, args ...interface{}) {
    66  	base.FatalfAt(pw.m.pos(p), msg, args...)
    67  }
    68  
    69  func (pw *pkgWriter) unexpected(what string, p poser) {
    70  	pw.fatalf(p, "unexpected %s: %v (%T)", what, p, p)
    71  }
    72  
    73  type writer struct {
    74  	p *pkgWriter
    75  
    76  	encoder
    77  
    78  	// TODO(mdempsky): We should be able to prune localsIdx whenever a
    79  	// scope closes, and then maybe we can just use the same map for
    80  	// storing the TypeParams too (as their TypeName instead).
    81  
    82  	// variables declared within this function
    83  	localsIdx map[*types2.Var]int
    84  
    85  	closureVars    []posObj
    86  	closureVarsIdx map[*types2.Var]int
    87  
    88  	dict    *writerDict
    89  	derived bool
    90  }
    91  
    92  // A writerDict tracks types and objects that are used by a declaration.
    93  type writerDict struct {
    94  	implicits []*types2.TypeName
    95  
    96  	// derived is a slice of type indices for computing derived types
    97  	// (i.e., types that depend on the declaration's type parameters).
    98  	derived []derivedInfo
    99  
   100  	// derivedIdx maps a Type to its corresponding index within the
   101  	// derived slice, if present.
   102  	derivedIdx map[types2.Type]int
   103  
   104  	// funcs lists references to generic functions that were
   105  	// instantiated with derived types (i.e., that require
   106  	// sub-dictionaries when called at run time).
   107  	funcs []objInfo
   108  }
   109  
   110  type derivedInfo struct {
   111  	idx    int
   112  	needed bool
   113  }
   114  
   115  type typeInfo struct {
   116  	idx     int
   117  	derived bool
   118  }
   119  
   120  type objInfo struct {
   121  	idx       int        // index for the generic function declaration
   122  	explicits []typeInfo // info for the type arguments
   123  }
   124  
   125  func (info objInfo) anyDerived() bool {
   126  	for _, explicit := range info.explicits {
   127  		if explicit.derived {
   128  			return true
   129  		}
   130  	}
   131  	return false
   132  }
   133  
   134  func (info objInfo) equals(other objInfo) bool {
   135  	if info.idx != other.idx {
   136  		return false
   137  	}
   138  	assert(len(info.explicits) == len(other.explicits))
   139  	for i, targ := range info.explicits {
   140  		if targ != other.explicits[i] {
   141  			return false
   142  		}
   143  	}
   144  	return true
   145  }
   146  
   147  func (pw *pkgWriter) newWriter(k reloc, marker syncMarker) *writer {
   148  	return &writer{
   149  		encoder: pw.newEncoder(k, marker),
   150  		p:       pw,
   151  	}
   152  }
   153  
   154  // @@@ Positions
   155  
   156  func (w *writer) pos(p poser) {
   157  	w.sync(syncPos)
   158  	pos := p.Pos()
   159  
   160  	// TODO(mdempsky): Track down the remaining cases here and fix them.
   161  	if !w.bool(pos.IsKnown()) {
   162  		return
   163  	}
   164  
   165  	// TODO(mdempsky): Delta encoding. Also, if there's a b-side, update
   166  	// its position base too (but not vice versa!).
   167  	w.posBase(pos.Base())
   168  	w.uint(pos.Line())
   169  	w.uint(pos.Col())
   170  }
   171  
   172  func (w *writer) posBase(b *syntax.PosBase) {
   173  	w.reloc(relocPosBase, w.p.posBaseIdx(b))
   174  }
   175  
   176  func (pw *pkgWriter) posBaseIdx(b *syntax.PosBase) int {
   177  	if idx, ok := pw.posBasesIdx[b]; ok {
   178  		return idx
   179  	}
   180  
   181  	w := pw.newWriter(relocPosBase, syncPosBase)
   182  	w.p.posBasesIdx[b] = w.idx
   183  
   184  	w.string(trimFilename(b))
   185  
   186  	if !w.bool(b.IsFileBase()) {
   187  		w.pos(b)
   188  		w.uint(b.Line())
   189  		w.uint(b.Col())
   190  	}
   191  
   192  	return w.flush()
   193  }
   194  
   195  // @@@ Packages
   196  
   197  func (w *writer) pkg(pkg *types2.Package) {
   198  	w.sync(syncPkg)
   199  	w.reloc(relocPkg, w.p.pkgIdx(pkg))
   200  }
   201  
   202  func (pw *pkgWriter) pkgIdx(pkg *types2.Package) int {
   203  	if idx, ok := pw.pkgsIdx[pkg]; ok {
   204  		return idx
   205  	}
   206  
   207  	w := pw.newWriter(relocPkg, syncPkgDef)
   208  	pw.pkgsIdx[pkg] = w.idx
   209  
   210  	if pkg == nil {
   211  		w.string("builtin")
   212  	} else {
   213  		var path string
   214  		if pkg != w.p.curpkg {
   215  			path = pkg.Path()
   216  		}
   217  		w.string(path)
   218  		w.string(pkg.Name())
   219  		w.len(pkg.Height())
   220  
   221  		w.len(len(pkg.Imports()))
   222  		for _, imp := range pkg.Imports() {
   223  			w.pkg(imp)
   224  		}
   225  	}
   226  
   227  	return w.flush()
   228  }
   229  
   230  // @@@ Types
   231  
   232  var anyTypeName = types2.Universe.Lookup("any").(*types2.TypeName)
   233  
   234  func (w *writer) typ(typ types2.Type) {
   235  	w.typInfo(w.p.typIdx(typ, w.dict))
   236  }
   237  
   238  func (w *writer) typInfo(info typeInfo) {
   239  	w.sync(syncType)
   240  	if w.bool(info.derived) {
   241  		w.len(info.idx)
   242  		w.derived = true
   243  	} else {
   244  		w.reloc(relocType, info.idx)
   245  	}
   246  }
   247  
   248  // typIdx returns the index where the export data description of type
   249  // can be read back in. If no such index exists yet, it's created.
   250  //
   251  // typIdx also reports whether typ is a derived type; that is, whether
   252  // its identity depends on type parameters.
   253  func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo {
   254  	if quirksMode() {
   255  		typ = pw.dups.orig(typ)
   256  	}
   257  
   258  	if idx, ok := pw.typsIdx[typ]; ok {
   259  		return typeInfo{idx: idx, derived: false}
   260  	}
   261  	if dict != nil {
   262  		if idx, ok := dict.derivedIdx[typ]; ok {
   263  			return typeInfo{idx: idx, derived: true}
   264  		}
   265  	}
   266  
   267  	w := pw.newWriter(relocType, syncTypeIdx)
   268  	w.dict = dict
   269  
   270  	switch typ := typ.(type) {
   271  	default:
   272  		base.Fatalf("unexpected type: %v (%T)", typ, typ)
   273  
   274  	case *types2.Basic:
   275  		switch kind := typ.Kind(); {
   276  		case kind == types2.Invalid:
   277  			base.Fatalf("unexpected types2.Invalid")
   278  
   279  		case types2.Typ[kind] == typ:
   280  			w.code(typeBasic)
   281  			w.len(int(kind))
   282  
   283  		default:
   284  			// Handle "byte" and "rune" as references to their TypeName.
   285  			obj := types2.Universe.Lookup(typ.Name())
   286  			assert(obj.Type() == typ)
   287  
   288  			w.code(typeNamed)
   289  			w.obj(obj, nil)
   290  		}
   291  
   292  	case *types2.Named:
   293  		// Type aliases can refer to uninstantiated generic types, so we
   294  		// might see len(TParams) != 0 && len(TArgs) == 0 here.
   295  		// TODO(mdempsky): Revisit after #46477 is resolved.
   296  		assert(typ.TypeParams().Len() == typ.TypeArgs().Len() || typ.TypeArgs().Len() == 0)
   297  
   298  		// TODO(mdempsky): Why do we need to loop here?
   299  		orig := typ
   300  		for orig.TypeArgs() != nil {
   301  			orig = orig.Origin()
   302  		}
   303  
   304  		w.code(typeNamed)
   305  		w.obj(orig.Obj(), typ.TypeArgs())
   306  
   307  	case *types2.TypeParam:
   308  		index := func() int {
   309  			for idx, name := range w.dict.implicits {
   310  				if name.Type().(*types2.TypeParam) == typ {
   311  					return idx
   312  				}
   313  			}
   314  
   315  			return len(w.dict.implicits) + typ.Index()
   316  		}()
   317  
   318  		w.derived = true
   319  		w.code(typeTypeParam)
   320  		w.len(index)
   321  
   322  	case *types2.Array:
   323  		w.code(typeArray)
   324  		w.uint64(uint64(typ.Len()))
   325  		w.typ(typ.Elem())
   326  
   327  	case *types2.Chan:
   328  		w.code(typeChan)
   329  		w.len(int(typ.Dir()))
   330  		w.typ(typ.Elem())
   331  
   332  	case *types2.Map:
   333  		w.code(typeMap)
   334  		w.typ(typ.Key())
   335  		w.typ(typ.Elem())
   336  
   337  	case *types2.Pointer:
   338  		w.code(typePointer)
   339  		w.typ(typ.Elem())
   340  
   341  	case *types2.Signature:
   342  		base.Assertf(typ.TypeParams() == nil, "unexpected type params: %v", typ)
   343  		w.code(typeSignature)
   344  		w.signature(typ)
   345  
   346  	case *types2.Slice:
   347  		w.code(typeSlice)
   348  		w.typ(typ.Elem())
   349  
   350  	case *types2.Struct:
   351  		w.code(typeStruct)
   352  		w.structType(typ)
   353  
   354  	case *types2.Interface:
   355  		if typ == anyTypeName.Type() {
   356  			w.code(typeNamed)
   357  			w.obj(anyTypeName, nil)
   358  			break
   359  		}
   360  
   361  		w.code(typeInterface)
   362  		w.interfaceType(typ)
   363  
   364  	case *types2.Union:
   365  		w.code(typeUnion)
   366  		w.unionType(typ)
   367  	}
   368  
   369  	if w.derived {
   370  		idx := len(dict.derived)
   371  		dict.derived = append(dict.derived, derivedInfo{idx: w.flush()})
   372  		dict.derivedIdx[typ] = idx
   373  		return typeInfo{idx: idx, derived: true}
   374  	}
   375  
   376  	pw.typsIdx[typ] = w.idx
   377  	return typeInfo{idx: w.flush(), derived: false}
   378  }
   379  
   380  func (w *writer) structType(typ *types2.Struct) {
   381  	w.len(typ.NumFields())
   382  	for i := 0; i < typ.NumFields(); i++ {
   383  		f := typ.Field(i)
   384  		w.pos(f)
   385  		w.selector(f)
   386  		w.typ(f.Type())
   387  		w.string(typ.Tag(i))
   388  		w.bool(f.Embedded())
   389  	}
   390  }
   391  
   392  func (w *writer) unionType(typ *types2.Union) {
   393  	w.len(typ.Len())
   394  	for i := 0; i < typ.Len(); i++ {
   395  		t := typ.Term(i)
   396  		w.bool(t.Tilde())
   397  		w.typ(t.Type())
   398  	}
   399  }
   400  
   401  func (w *writer) interfaceType(typ *types2.Interface) {
   402  	w.len(typ.NumExplicitMethods())
   403  	w.len(typ.NumEmbeddeds())
   404  
   405  	for i := 0; i < typ.NumExplicitMethods(); i++ {
   406  		m := typ.ExplicitMethod(i)
   407  		sig := m.Type().(*types2.Signature)
   408  		assert(sig.TypeParams() == nil)
   409  
   410  		w.pos(m)
   411  		w.selector(m)
   412  		w.signature(sig)
   413  	}
   414  
   415  	for i := 0; i < typ.NumEmbeddeds(); i++ {
   416  		w.typ(typ.EmbeddedType(i))
   417  	}
   418  }
   419  
   420  func (w *writer) signature(sig *types2.Signature) {
   421  	w.sync(syncSignature)
   422  	w.params(sig.Params())
   423  	w.params(sig.Results())
   424  	w.bool(sig.Variadic())
   425  }
   426  
   427  func (w *writer) params(typ *types2.Tuple) {
   428  	w.sync(syncParams)
   429  	w.len(typ.Len())
   430  	for i := 0; i < typ.Len(); i++ {
   431  		w.param(typ.At(i))
   432  	}
   433  }
   434  
   435  func (w *writer) param(param *types2.Var) {
   436  	w.sync(syncParam)
   437  	w.pos(param)
   438  	w.localIdent(param)
   439  	w.typ(param.Type())
   440  }
   441  
   442  // @@@ Objects
   443  
   444  func (w *writer) obj(obj types2.Object, explicits *types2.TypeList) {
   445  	explicitInfos := make([]typeInfo, explicits.Len())
   446  	for i := range explicitInfos {
   447  		explicitInfos[i] = w.p.typIdx(explicits.At(i), w.dict)
   448  	}
   449  	info := objInfo{idx: w.p.objIdx(obj), explicits: explicitInfos}
   450  
   451  	if _, ok := obj.(*types2.Func); ok && info.anyDerived() {
   452  		idx := -1
   453  		for i, prev := range w.dict.funcs {
   454  			if prev.equals(info) {
   455  				idx = i
   456  			}
   457  		}
   458  		if idx < 0 {
   459  			idx = len(w.dict.funcs)
   460  			w.dict.funcs = append(w.dict.funcs, info)
   461  		}
   462  
   463  		// TODO(mdempsky): Push up into expr; this shouldn't appear
   464  		// outside of expression context.
   465  		w.sync(syncObject)
   466  		w.bool(true)
   467  		w.len(idx)
   468  		return
   469  	}
   470  
   471  	// TODO(mdempsky): Push up into typIdx; this shouldn't be needed
   472  	// except while writing out types.
   473  	if isDefinedType(obj) && obj.Pkg() == w.p.curpkg {
   474  		decl, ok := w.p.typDecls[obj.(*types2.TypeName)]
   475  		assert(ok)
   476  		if len(decl.implicits) != 0 {
   477  			w.derived = true
   478  		}
   479  	}
   480  
   481  	w.sync(syncObject)
   482  	w.bool(false)
   483  	w.reloc(relocObj, info.idx)
   484  
   485  	w.len(len(info.explicits))
   486  	for _, info := range info.explicits {
   487  		w.typInfo(info)
   488  	}
   489  }
   490  
   491  func (pw *pkgWriter) objIdx(obj types2.Object) int {
   492  	if idx, ok := pw.globalsIdx[obj]; ok {
   493  		return idx
   494  	}
   495  
   496  	dict := &writerDict{
   497  		derivedIdx: make(map[types2.Type]int),
   498  	}
   499  
   500  	if isDefinedType(obj) && obj.Pkg() == pw.curpkg {
   501  		decl, ok := pw.typDecls[obj.(*types2.TypeName)]
   502  		assert(ok)
   503  		dict.implicits = decl.implicits
   504  	}
   505  
   506  	w := pw.newWriter(relocObj, syncObject1)
   507  	wext := pw.newWriter(relocObjExt, syncObject1)
   508  	wname := pw.newWriter(relocName, syncObject1)
   509  	wdict := pw.newWriter(relocObjDict, syncObject1)
   510  
   511  	pw.globalsIdx[obj] = w.idx // break cycles
   512  	assert(wext.idx == w.idx)
   513  	assert(wname.idx == w.idx)
   514  	assert(wdict.idx == w.idx)
   515  
   516  	w.dict = dict
   517  	wext.dict = dict
   518  
   519  	code := w.doObj(wext, obj)
   520  	w.flush()
   521  	wext.flush()
   522  
   523  	wname.qualifiedIdent(obj)
   524  	wname.code(code)
   525  	wname.flush()
   526  
   527  	wdict.objDict(obj, w.dict)
   528  	wdict.flush()
   529  
   530  	return w.idx
   531  }
   532  
   533  func (w *writer) doObj(wext *writer, obj types2.Object) codeObj {
   534  	if obj.Pkg() != w.p.curpkg {
   535  		return objStub
   536  	}
   537  
   538  	switch obj := obj.(type) {
   539  	default:
   540  		w.p.unexpected("object", obj)
   541  		panic("unreachable")
   542  
   543  	case *types2.Const:
   544  		w.pos(obj)
   545  		w.typ(obj.Type())
   546  		w.value(obj.Val())
   547  		return objConst
   548  
   549  	case *types2.Func:
   550  		decl, ok := w.p.funDecls[obj]
   551  		assert(ok)
   552  		sig := obj.Type().(*types2.Signature)
   553  
   554  		w.pos(obj)
   555  		w.typeParamNames(sig.TypeParams())
   556  		w.signature(sig)
   557  		w.pos(decl)
   558  		wext.funcExt(obj)
   559  		return objFunc
   560  
   561  	case *types2.TypeName:
   562  		decl, ok := w.p.typDecls[obj]
   563  		assert(ok)
   564  
   565  		if obj.IsAlias() {
   566  			w.pos(obj)
   567  			w.typ(obj.Type())
   568  			return objAlias
   569  		}
   570  
   571  		named := obj.Type().(*types2.Named)
   572  		assert(named.TypeArgs() == nil)
   573  
   574  		w.pos(obj)
   575  		w.typeParamNames(named.TypeParams())
   576  		wext.typeExt(obj)
   577  		w.typExpr(decl.Type)
   578  
   579  		w.len(named.NumMethods())
   580  		for i := 0; i < named.NumMethods(); i++ {
   581  			w.method(wext, named.Method(i))
   582  		}
   583  
   584  		return objType
   585  
   586  	case *types2.Var:
   587  		w.pos(obj)
   588  		w.typ(obj.Type())
   589  		wext.varExt(obj)
   590  		return objVar
   591  	}
   592  }
   593  
   594  // typExpr writes the type represented by the given expression.
   595  func (w *writer) typExpr(expr syntax.Expr) {
   596  	tv, ok := w.p.info.Types[expr]
   597  	assert(ok)
   598  	assert(tv.IsType())
   599  	w.typ(tv.Type)
   600  }
   601  
   602  // objDict writes the dictionary needed for reading the given object.
   603  func (w *writer) objDict(obj types2.Object, dict *writerDict) {
   604  	// TODO(mdempsky): Split objDict into multiple entries? reader.go
   605  	// doesn't care about the type parameter bounds, and reader2.go
   606  	// doesn't care about referenced functions.
   607  
   608  	w.dict = dict // TODO(mdempsky): This is a bit sketchy.
   609  
   610  	w.len(len(dict.implicits))
   611  
   612  	tparams := objTypeParams(obj)
   613  	ntparams := tparams.Len()
   614  	w.len(ntparams)
   615  	for i := 0; i < ntparams; i++ {
   616  		w.typ(tparams.At(i).Constraint())
   617  	}
   618  
   619  	nderived := len(dict.derived)
   620  	w.len(nderived)
   621  	for _, typ := range dict.derived {
   622  		w.reloc(relocType, typ.idx)
   623  		w.bool(typ.needed)
   624  	}
   625  
   626  	nfuncs := len(dict.funcs)
   627  	w.len(nfuncs)
   628  	for _, fn := range dict.funcs {
   629  		w.reloc(relocObj, fn.idx)
   630  		w.len(len(fn.explicits))
   631  		for _, targ := range fn.explicits {
   632  			w.typInfo(targ)
   633  		}
   634  	}
   635  
   636  	assert(len(dict.derived) == nderived)
   637  	assert(len(dict.funcs) == nfuncs)
   638  }
   639  
   640  func (w *writer) typeParamNames(tparams *types2.TypeParamList) {
   641  	w.sync(syncTypeParamNames)
   642  
   643  	ntparams := tparams.Len()
   644  	for i := 0; i < ntparams; i++ {
   645  		tparam := tparams.At(i).Obj()
   646  		w.pos(tparam)
   647  		w.localIdent(tparam)
   648  	}
   649  }
   650  
   651  func (w *writer) method(wext *writer, meth *types2.Func) {
   652  	decl, ok := w.p.funDecls[meth]
   653  	assert(ok)
   654  	sig := meth.Type().(*types2.Signature)
   655  
   656  	w.sync(syncMethod)
   657  	w.pos(meth)
   658  	w.selector(meth)
   659  	w.typeParamNames(sig.RecvTypeParams())
   660  	w.param(sig.Recv())
   661  	w.signature(sig)
   662  
   663  	w.pos(decl) // XXX: Hack to workaround linker limitations.
   664  	wext.funcExt(meth)
   665  }
   666  
   667  // qualifiedIdent writes out the name of an object declared at package
   668  // scope. (For now, it's also used to refer to local defined types.)
   669  func (w *writer) qualifiedIdent(obj types2.Object) {
   670  	w.sync(syncSym)
   671  
   672  	name := obj.Name()
   673  	if isDefinedType(obj) && obj.Pkg() == w.p.curpkg {
   674  		decl, ok := w.p.typDecls[obj.(*types2.TypeName)]
   675  		assert(ok)
   676  		if decl.gen != 0 {
   677  			// TODO(mdempsky): Find a better solution than embedding middle
   678  			// dot in the symbol name; this is terrible.
   679  			name = fmt.Sprintf("%s·%v", name, decl.gen)
   680  		}
   681  	}
   682  
   683  	w.pkg(obj.Pkg())
   684  	w.string(name)
   685  }
   686  
   687  // TODO(mdempsky): We should be able to omit pkg from both localIdent
   688  // and selector, because they should always be known from context.
   689  // However, past frustrations with this optimization in iexport make
   690  // me a little nervous to try it again.
   691  
   692  // localIdent writes the name of a locally declared object (i.e.,
   693  // objects that can only be accessed by name, within the context of a
   694  // particular function).
   695  func (w *writer) localIdent(obj types2.Object) {
   696  	assert(!isGlobal(obj))
   697  	w.sync(syncLocalIdent)
   698  	w.pkg(obj.Pkg())
   699  	w.string(obj.Name())
   700  }
   701  
   702  // selector writes the name of a field or method (i.e., objects that
   703  // can only be accessed using selector expressions).
   704  func (w *writer) selector(obj types2.Object) {
   705  	w.sync(syncSelector)
   706  	w.pkg(obj.Pkg())
   707  	w.string(obj.Name())
   708  }
   709  
   710  // @@@ Compiler extensions
   711  
   712  func (w *writer) funcExt(obj *types2.Func) {
   713  	decl, ok := w.p.funDecls[obj]
   714  	assert(ok)
   715  
   716  	// TODO(mdempsky): Extend these pragma validation flags to account
   717  	// for generics. E.g., linkname probably doesn't make sense at
   718  	// least.
   719  
   720  	pragma := asPragmaFlag(decl.Pragma)
   721  	if pragma&ir.Systemstack != 0 && pragma&ir.Nosplit != 0 {
   722  		w.p.errorf(decl, "go:nosplit and go:systemstack cannot be combined")
   723  	}
   724  
   725  	if decl.Body != nil {
   726  		if pragma&ir.Noescape != 0 {
   727  			w.p.errorf(decl, "can only use //go:noescape with external func implementations")
   728  		}
   729  	} else {
   730  		if base.Flag.Complete || decl.Name.Value == "init" {
   731  			// Linknamed functions are allowed to have no body. Hopefully
   732  			// the linkname target has a body. See issue 23311.
   733  			if _, ok := w.p.linknames[obj]; !ok {
   734  				w.p.errorf(decl, "missing function body")
   735  			}
   736  		}
   737  	}
   738  
   739  	sig, block := obj.Type().(*types2.Signature), decl.Body
   740  	body, closureVars := w.p.bodyIdx(w.p.curpkg, sig, block, w.dict)
   741  	assert(len(closureVars) == 0)
   742  
   743  	w.sync(syncFuncExt)
   744  	w.pragmaFlag(pragma)
   745  	w.linkname(obj)
   746  	w.bool(false) // stub extension
   747  	w.reloc(relocBody, body)
   748  	w.sync(syncEOF)
   749  }
   750  
   751  func (w *writer) typeExt(obj *types2.TypeName) {
   752  	decl, ok := w.p.typDecls[obj]
   753  	assert(ok)
   754  
   755  	w.sync(syncTypeExt)
   756  
   757  	w.pragmaFlag(asPragmaFlag(decl.Pragma))
   758  
   759  	// No LSym.SymIdx info yet.
   760  	w.int64(-1)
   761  	w.int64(-1)
   762  }
   763  
   764  func (w *writer) varExt(obj *types2.Var) {
   765  	w.sync(syncVarExt)
   766  	w.linkname(obj)
   767  }
   768  
   769  func (w *writer) linkname(obj types2.Object) {
   770  	w.sync(syncLinkname)
   771  	w.int64(-1)
   772  	w.string(w.p.linknames[obj])
   773  }
   774  
   775  func (w *writer) pragmaFlag(p ir.PragmaFlag) {
   776  	w.sync(syncPragma)
   777  	w.int(int(p))
   778  }
   779  
   780  // @@@ Function bodies
   781  
   782  func (pw *pkgWriter) bodyIdx(pkg *types2.Package, sig *types2.Signature, block *syntax.BlockStmt, dict *writerDict) (idx int, closureVars []posObj) {
   783  	w := pw.newWriter(relocBody, syncFuncBody)
   784  	w.dict = dict
   785  
   786  	w.funcargs(sig)
   787  	if w.bool(block != nil) {
   788  		w.stmts(block.List)
   789  		w.pos(block.Rbrace)
   790  	}
   791  
   792  	return w.flush(), w.closureVars
   793  }
   794  
   795  func (w *writer) funcargs(sig *types2.Signature) {
   796  	do := func(params *types2.Tuple, result bool) {
   797  		for i := 0; i < params.Len(); i++ {
   798  			w.funcarg(params.At(i), result)
   799  		}
   800  	}
   801  
   802  	if recv := sig.Recv(); recv != nil {
   803  		w.funcarg(recv, false)
   804  	}
   805  	do(sig.Params(), false)
   806  	do(sig.Results(), true)
   807  }
   808  
   809  func (w *writer) funcarg(param *types2.Var, result bool) {
   810  	if param.Name() != "" || result {
   811  		w.addLocal(param)
   812  	}
   813  }
   814  
   815  func (w *writer) addLocal(obj *types2.Var) {
   816  	w.sync(syncAddLocal)
   817  	idx := len(w.localsIdx)
   818  	if enableSync {
   819  		w.int(idx)
   820  	}
   821  	if w.localsIdx == nil {
   822  		w.localsIdx = make(map[*types2.Var]int)
   823  	}
   824  	w.localsIdx[obj] = idx
   825  }
   826  
   827  func (w *writer) useLocal(pos syntax.Pos, obj *types2.Var) {
   828  	w.sync(syncUseObjLocal)
   829  
   830  	if idx, ok := w.localsIdx[obj]; w.bool(ok) {
   831  		w.len(idx)
   832  		return
   833  	}
   834  
   835  	idx, ok := w.closureVarsIdx[obj]
   836  	if !ok {
   837  		if w.closureVarsIdx == nil {
   838  			w.closureVarsIdx = make(map[*types2.Var]int)
   839  		}
   840  		idx = len(w.closureVars)
   841  		w.closureVars = append(w.closureVars, posObj{pos, obj})
   842  		w.closureVarsIdx[obj] = idx
   843  	}
   844  	w.len(idx)
   845  }
   846  
   847  func (w *writer) openScope(pos syntax.Pos) {
   848  	w.sync(syncOpenScope)
   849  	w.pos(pos)
   850  }
   851  
   852  func (w *writer) closeScope(pos syntax.Pos) {
   853  	w.sync(syncCloseScope)
   854  	w.pos(pos)
   855  	w.closeAnotherScope()
   856  }
   857  
   858  func (w *writer) closeAnotherScope() {
   859  	w.sync(syncCloseAnotherScope)
   860  }
   861  
   862  // @@@ Statements
   863  
   864  func (w *writer) stmt(stmt syntax.Stmt) {
   865  	var stmts []syntax.Stmt
   866  	if stmt != nil {
   867  		stmts = []syntax.Stmt{stmt}
   868  	}
   869  	w.stmts(stmts)
   870  }
   871  
   872  func (w *writer) stmts(stmts []syntax.Stmt) {
   873  	w.sync(syncStmts)
   874  	for _, stmt := range stmts {
   875  		w.stmt1(stmt)
   876  	}
   877  	w.code(stmtEnd)
   878  	w.sync(syncStmtsEnd)
   879  }
   880  
   881  func (w *writer) stmt1(stmt syntax.Stmt) {
   882  	switch stmt := stmt.(type) {
   883  	default:
   884  		w.p.unexpected("statement", stmt)
   885  
   886  	case nil, *syntax.EmptyStmt:
   887  		return
   888  
   889  	case *syntax.AssignStmt:
   890  		switch {
   891  		case stmt.Rhs == nil:
   892  			w.code(stmtIncDec)
   893  			w.op(binOps[stmt.Op])
   894  			w.expr(stmt.Lhs)
   895  			w.pos(stmt)
   896  
   897  		case stmt.Op != 0 && stmt.Op != syntax.Def:
   898  			w.code(stmtAssignOp)
   899  			w.op(binOps[stmt.Op])
   900  			w.expr(stmt.Lhs)
   901  			w.pos(stmt)
   902  			w.expr(stmt.Rhs)
   903  
   904  		default:
   905  			w.code(stmtAssign)
   906  			w.pos(stmt)
   907  			w.exprList(stmt.Rhs)
   908  			w.assignList(stmt.Lhs)
   909  		}
   910  
   911  	case *syntax.BlockStmt:
   912  		w.code(stmtBlock)
   913  		w.blockStmt(stmt)
   914  
   915  	case *syntax.BranchStmt:
   916  		w.code(stmtBranch)
   917  		w.pos(stmt)
   918  		w.op(branchOps[stmt.Tok])
   919  		w.optLabel(stmt.Label)
   920  
   921  	case *syntax.CallStmt:
   922  		w.code(stmtCall)
   923  		w.pos(stmt)
   924  		w.op(callOps[stmt.Tok])
   925  		w.expr(stmt.Call)
   926  
   927  	case *syntax.DeclStmt:
   928  		for _, decl := range stmt.DeclList {
   929  			w.declStmt(decl)
   930  		}
   931  
   932  	case *syntax.ExprStmt:
   933  		w.code(stmtExpr)
   934  		w.expr(stmt.X)
   935  
   936  	case *syntax.ForStmt:
   937  		w.code(stmtFor)
   938  		w.forStmt(stmt)
   939  
   940  	case *syntax.IfStmt:
   941  		w.code(stmtIf)
   942  		w.ifStmt(stmt)
   943  
   944  	case *syntax.LabeledStmt:
   945  		w.code(stmtLabel)
   946  		w.pos(stmt)
   947  		w.label(stmt.Label)
   948  		w.stmt1(stmt.Stmt)
   949  
   950  	case *syntax.ReturnStmt:
   951  		w.code(stmtReturn)
   952  		w.pos(stmt)
   953  		w.exprList(stmt.Results)
   954  
   955  	case *syntax.SelectStmt:
   956  		w.code(stmtSelect)
   957  		w.selectStmt(stmt)
   958  
   959  	case *syntax.SendStmt:
   960  		w.code(stmtSend)
   961  		w.pos(stmt)
   962  		w.expr(stmt.Chan)
   963  		w.expr(stmt.Value)
   964  
   965  	case *syntax.SwitchStmt:
   966  		w.code(stmtSwitch)
   967  		w.switchStmt(stmt)
   968  	}
   969  }
   970  
   971  func (w *writer) assignList(expr syntax.Expr) {
   972  	exprs := unpackListExpr(expr)
   973  	w.len(len(exprs))
   974  
   975  	for _, expr := range exprs {
   976  		if name, ok := expr.(*syntax.Name); ok && name.Value != "_" {
   977  			if obj, ok := w.p.info.Defs[name]; ok {
   978  				obj := obj.(*types2.Var)
   979  
   980  				w.bool(true)
   981  				w.pos(obj)
   982  				w.localIdent(obj)
   983  				w.typ(obj.Type())
   984  
   985  				// TODO(mdempsky): Minimize locals index size by deferring
   986  				// this until the variables actually come into scope.
   987  				w.addLocal(obj)
   988  				continue
   989  			}
   990  		}
   991  
   992  		w.bool(false)
   993  		w.expr(expr)
   994  	}
   995  }
   996  
   997  func (w *writer) declStmt(decl syntax.Decl) {
   998  	switch decl := decl.(type) {
   999  	default:
  1000  		w.p.unexpected("declaration", decl)
  1001  
  1002  	case *syntax.ConstDecl:
  1003  
  1004  	case *syntax.TypeDecl:
  1005  		// Quirk: The legacy inliner doesn't support inlining functions
  1006  		// with type declarations. Unified IR doesn't have any need to
  1007  		// write out type declarations explicitly (they're always looked
  1008  		// up via global index tables instead), so we just write out a
  1009  		// marker so the reader knows to synthesize a fake declaration to
  1010  		// prevent inlining.
  1011  		if quirksMode() {
  1012  			w.code(stmtTypeDeclHack)
  1013  		}
  1014  
  1015  	case *syntax.VarDecl:
  1016  		values := unpackListExpr(decl.Values)
  1017  
  1018  		// Quirk: When N variables are declared with N initialization
  1019  		// values, we need to decompose that into N interleaved
  1020  		// declarations+initializations, because it leads to different
  1021  		// (albeit semantically equivalent) code generation.
  1022  		if quirksMode() && len(decl.NameList) == len(values) {
  1023  			for i, name := range decl.NameList {
  1024  				w.code(stmtAssign)
  1025  				w.pos(decl)
  1026  				w.exprList(values[i])
  1027  				w.assignList(name)
  1028  			}
  1029  			break
  1030  		}
  1031  
  1032  		w.code(stmtAssign)
  1033  		w.pos(decl)
  1034  		w.exprList(decl.Values)
  1035  		w.assignList(namesAsExpr(decl.NameList))
  1036  	}
  1037  }
  1038  
  1039  func (w *writer) blockStmt(stmt *syntax.BlockStmt) {
  1040  	w.sync(syncBlockStmt)
  1041  	w.openScope(stmt.Pos())
  1042  	w.stmts(stmt.List)
  1043  	w.closeScope(stmt.Rbrace)
  1044  }
  1045  
  1046  func (w *writer) forStmt(stmt *syntax.ForStmt) {
  1047  	w.sync(syncForStmt)
  1048  	w.openScope(stmt.Pos())
  1049  
  1050  	if rang, ok := stmt.Init.(*syntax.RangeClause); w.bool(ok) {
  1051  		w.pos(rang)
  1052  		w.expr(rang.X)
  1053  		w.assignList(rang.Lhs)
  1054  	} else {
  1055  		w.pos(stmt)
  1056  		w.stmt(stmt.Init)
  1057  		w.expr(stmt.Cond)
  1058  		w.stmt(stmt.Post)
  1059  	}
  1060  
  1061  	w.blockStmt(stmt.Body)
  1062  	w.closeAnotherScope()
  1063  }
  1064  
  1065  func (w *writer) ifStmt(stmt *syntax.IfStmt) {
  1066  	w.sync(syncIfStmt)
  1067  	w.openScope(stmt.Pos())
  1068  	w.pos(stmt)
  1069  	w.stmt(stmt.Init)
  1070  	w.expr(stmt.Cond)
  1071  	w.blockStmt(stmt.Then)
  1072  	w.stmt(stmt.Else)
  1073  	w.closeAnotherScope()
  1074  }
  1075  
  1076  func (w *writer) selectStmt(stmt *syntax.SelectStmt) {
  1077  	w.sync(syncSelectStmt)
  1078  
  1079  	w.pos(stmt)
  1080  	w.len(len(stmt.Body))
  1081  	for i, clause := range stmt.Body {
  1082  		if i > 0 {
  1083  			w.closeScope(clause.Pos())
  1084  		}
  1085  		w.openScope(clause.Pos())
  1086  
  1087  		w.pos(clause)
  1088  		w.stmt(clause.Comm)
  1089  		w.stmts(clause.Body)
  1090  	}
  1091  	if len(stmt.Body) > 0 {
  1092  		w.closeScope(stmt.Rbrace)
  1093  	}
  1094  }
  1095  
  1096  func (w *writer) switchStmt(stmt *syntax.SwitchStmt) {
  1097  	w.sync(syncSwitchStmt)
  1098  
  1099  	w.openScope(stmt.Pos())
  1100  	w.pos(stmt)
  1101  	w.stmt(stmt.Init)
  1102  
  1103  	if guard, ok := stmt.Tag.(*syntax.TypeSwitchGuard); w.bool(ok) {
  1104  		w.pos(guard)
  1105  		if tag := guard.Lhs; w.bool(tag != nil) {
  1106  			w.pos(tag)
  1107  			w.string(tag.Value)
  1108  		}
  1109  		w.expr(guard.X)
  1110  	} else {
  1111  		w.expr(stmt.Tag)
  1112  	}
  1113  
  1114  	w.len(len(stmt.Body))
  1115  	for i, clause := range stmt.Body {
  1116  		if i > 0 {
  1117  			w.closeScope(clause.Pos())
  1118  		}
  1119  		w.openScope(clause.Pos())
  1120  
  1121  		w.pos(clause)
  1122  		w.exprList(clause.Cases)
  1123  
  1124  		if obj, ok := w.p.info.Implicits[clause]; ok {
  1125  			// TODO(mdempsky): These pos details are quirkish, but also
  1126  			// necessary so the variable's position is correct for DWARF
  1127  			// scope assignment later. It would probably be better for us to
  1128  			// instead just set the variable's DWARF scoping info earlier so
  1129  			// we can give it the correct position information.
  1130  			pos := clause.Pos()
  1131  			if typs := unpackListExpr(clause.Cases); len(typs) != 0 {
  1132  				pos = typeExprEndPos(typs[len(typs)-1])
  1133  			}
  1134  			w.pos(pos)
  1135  
  1136  			obj := obj.(*types2.Var)
  1137  			w.typ(obj.Type())
  1138  			w.addLocal(obj)
  1139  		}
  1140  
  1141  		w.stmts(clause.Body)
  1142  	}
  1143  	if len(stmt.Body) > 0 {
  1144  		w.closeScope(stmt.Rbrace)
  1145  	}
  1146  
  1147  	w.closeScope(stmt.Rbrace)
  1148  }
  1149  
  1150  func (w *writer) label(label *syntax.Name) {
  1151  	w.sync(syncLabel)
  1152  
  1153  	// TODO(mdempsky): Replace label strings with dense indices.
  1154  	w.string(label.Value)
  1155  }
  1156  
  1157  func (w *writer) optLabel(label *syntax.Name) {
  1158  	w.sync(syncOptLabel)
  1159  	if w.bool(label != nil) {
  1160  		w.label(label)
  1161  	}
  1162  }
  1163  
  1164  // @@@ Expressions
  1165  
  1166  func (w *writer) expr(expr syntax.Expr) {
  1167  	expr = unparen(expr) // skip parens; unneeded after typecheck
  1168  
  1169  	obj, inst := lookupObj(w.p.info, expr)
  1170  	targs := inst.TypeArgs
  1171  
  1172  	if tv, ok := w.p.info.Types[expr]; ok {
  1173  		// TODO(mdempsky): Be more judicious about which types are marked as "needed".
  1174  		if inst.Type != nil {
  1175  			w.needType(inst.Type)
  1176  		} else {
  1177  			w.needType(tv.Type)
  1178  		}
  1179  
  1180  		if tv.IsType() {
  1181  			w.code(exprType)
  1182  			w.typ(tv.Type)
  1183  			return
  1184  		}
  1185  
  1186  		if tv.Value != nil {
  1187  			pos := expr.Pos()
  1188  			if quirksMode() {
  1189  				if obj != nil {
  1190  					// Quirk: IR (and thus iexport) doesn't track position
  1191  					// information for uses of declared objects.
  1192  					pos = syntax.Pos{}
  1193  				} else if tv.Value.Kind() == constant.String {
  1194  					// Quirk: noder.sum picks a particular position for certain
  1195  					// string concatenations.
  1196  					pos = sumPos(expr)
  1197  				}
  1198  			}
  1199  
  1200  			w.code(exprConst)
  1201  			w.pos(pos)
  1202  			w.typ(tv.Type)
  1203  			w.value(tv.Value)
  1204  
  1205  			// TODO(mdempsky): These details are only important for backend
  1206  			// diagnostics. Explore writing them out separately.
  1207  			w.op(constExprOp(expr))
  1208  			w.string(syntax.String(expr))
  1209  			return
  1210  		}
  1211  	}
  1212  
  1213  	if obj != nil {
  1214  		if isGlobal(obj) {
  1215  			w.code(exprName)
  1216  			w.obj(obj, targs)
  1217  			return
  1218  		}
  1219  
  1220  		obj := obj.(*types2.Var)
  1221  		assert(!obj.IsField())
  1222  		assert(targs.Len() == 0)
  1223  
  1224  		w.code(exprLocal)
  1225  		w.useLocal(expr.Pos(), obj)
  1226  		return
  1227  	}
  1228  
  1229  	switch expr := expr.(type) {
  1230  	default:
  1231  		w.p.unexpected("expression", expr)
  1232  
  1233  	case nil: // absent slice index, for condition, or switch tag
  1234  		w.code(exprNone)
  1235  
  1236  	case *syntax.Name:
  1237  		assert(expr.Value == "_")
  1238  		w.code(exprBlank)
  1239  
  1240  	case *syntax.CompositeLit:
  1241  		w.code(exprCompLit)
  1242  		w.compLit(expr)
  1243  
  1244  	case *syntax.FuncLit:
  1245  		w.code(exprFuncLit)
  1246  		w.funcLit(expr)
  1247  
  1248  	case *syntax.SelectorExpr:
  1249  		sel, ok := w.p.info.Selections[expr]
  1250  		assert(ok)
  1251  
  1252  		w.code(exprSelector)
  1253  		w.expr(expr.X)
  1254  		w.pos(expr)
  1255  		w.selector(sel.Obj())
  1256  
  1257  	case *syntax.IndexExpr:
  1258  		tv, ok := w.p.info.Types[expr.Index]
  1259  		assert(ok && tv.IsValue())
  1260  
  1261  		w.code(exprIndex)
  1262  		w.expr(expr.X)
  1263  		w.pos(expr)
  1264  		w.expr(expr.Index)
  1265  
  1266  	case *syntax.SliceExpr:
  1267  		w.code(exprSlice)
  1268  		w.expr(expr.X)
  1269  		w.pos(expr)
  1270  		for _, n := range &expr.Index {
  1271  			w.expr(n)
  1272  		}
  1273  
  1274  	case *syntax.AssertExpr:
  1275  		w.code(exprAssert)
  1276  		w.expr(expr.X)
  1277  		w.pos(expr)
  1278  		w.expr(expr.Type)
  1279  
  1280  	case *syntax.Operation:
  1281  		if expr.Y == nil {
  1282  			w.code(exprUnaryOp)
  1283  			w.op(unOps[expr.Op])
  1284  			w.pos(expr)
  1285  			w.expr(expr.X)
  1286  			break
  1287  		}
  1288  
  1289  		w.code(exprBinaryOp)
  1290  		w.op(binOps[expr.Op])
  1291  		w.expr(expr.X)
  1292  		w.pos(expr)
  1293  		w.expr(expr.Y)
  1294  
  1295  	case *syntax.CallExpr:
  1296  		tv, ok := w.p.info.Types[expr.Fun]
  1297  		assert(ok)
  1298  		if tv.IsType() {
  1299  			assert(len(expr.ArgList) == 1)
  1300  			assert(!expr.HasDots)
  1301  
  1302  			w.code(exprConvert)
  1303  			w.typ(tv.Type)
  1304  			w.pos(expr)
  1305  			w.expr(expr.ArgList[0])
  1306  			break
  1307  		}
  1308  
  1309  		writeFunExpr := func() {
  1310  			if selector, ok := unparen(expr.Fun).(*syntax.SelectorExpr); ok {
  1311  				if sel, ok := w.p.info.Selections[selector]; ok && sel.Kind() == types2.MethodVal {
  1312  					w.expr(selector.X)
  1313  					w.bool(true) // method call
  1314  					w.pos(selector)
  1315  					w.selector(sel.Obj())
  1316  					return
  1317  				}
  1318  			}
  1319  
  1320  			w.expr(expr.Fun)
  1321  			w.bool(false) // not a method call (i.e., normal function call)
  1322  		}
  1323  
  1324  		w.code(exprCall)
  1325  		writeFunExpr()
  1326  		w.pos(expr)
  1327  		w.exprs(expr.ArgList)
  1328  		w.bool(expr.HasDots)
  1329  	}
  1330  }
  1331  
  1332  func (w *writer) compLit(lit *syntax.CompositeLit) {
  1333  	tv, ok := w.p.info.Types[lit]
  1334  	assert(ok)
  1335  
  1336  	w.sync(syncCompLit)
  1337  	w.pos(lit)
  1338  	w.typ(tv.Type)
  1339  
  1340  	typ := tv.Type
  1341  	if ptr, ok := types2.CoreType(typ).(*types2.Pointer); ok {
  1342  		typ = ptr.Elem()
  1343  	}
  1344  	str, isStruct := types2.CoreType(typ).(*types2.Struct)
  1345  
  1346  	w.len(len(lit.ElemList))
  1347  	for i, elem := range lit.ElemList {
  1348  		if isStruct {
  1349  			if kv, ok := elem.(*syntax.KeyValueExpr); ok {
  1350  				// use position of expr.Key rather than of elem (which has position of ':')
  1351  				w.pos(kv.Key)
  1352  				w.len(fieldIndex(w.p.info, str, kv.Key.(*syntax.Name)))
  1353  				elem = kv.Value
  1354  			} else {
  1355  				w.pos(elem)
  1356  				w.len(i)
  1357  			}
  1358  		} else {
  1359  			if kv, ok := elem.(*syntax.KeyValueExpr); w.bool(ok) {
  1360  				// use position of expr.Key rather than of elem (which has position of ':')
  1361  				w.pos(kv.Key)
  1362  				w.expr(kv.Key)
  1363  				elem = kv.Value
  1364  			}
  1365  		}
  1366  		w.pos(elem)
  1367  		w.expr(elem)
  1368  	}
  1369  }
  1370  
  1371  func (w *writer) funcLit(expr *syntax.FuncLit) {
  1372  	tv, ok := w.p.info.Types[expr]
  1373  	assert(ok)
  1374  	sig := tv.Type.(*types2.Signature)
  1375  
  1376  	body, closureVars := w.p.bodyIdx(w.p.curpkg, sig, expr.Body, w.dict)
  1377  
  1378  	w.sync(syncFuncLit)
  1379  	w.pos(expr)
  1380  	w.pos(expr.Type) // for QuirksMode
  1381  	w.signature(sig)
  1382  
  1383  	w.len(len(closureVars))
  1384  	for _, cv := range closureVars {
  1385  		w.pos(cv.pos)
  1386  		if quirksMode() {
  1387  			cv.pos = expr.Body.Rbrace
  1388  		}
  1389  		w.useLocal(cv.pos, cv.obj)
  1390  	}
  1391  
  1392  	w.reloc(relocBody, body)
  1393  }
  1394  
  1395  type posObj struct {
  1396  	pos syntax.Pos
  1397  	obj *types2.Var
  1398  }
  1399  
  1400  func (w *writer) exprList(expr syntax.Expr) {
  1401  	w.sync(syncExprList)
  1402  	w.exprs(unpackListExpr(expr))
  1403  }
  1404  
  1405  func (w *writer) exprs(exprs []syntax.Expr) {
  1406  	if len(exprs) == 0 {
  1407  		assert(exprs == nil)
  1408  	}
  1409  
  1410  	w.sync(syncExprs)
  1411  	w.len(len(exprs))
  1412  	for _, expr := range exprs {
  1413  		w.expr(expr)
  1414  	}
  1415  }
  1416  
  1417  func (w *writer) op(op ir.Op) {
  1418  	// TODO(mdempsky): Remove in favor of explicit codes? Would make
  1419  	// export data more stable against internal refactorings, but low
  1420  	// priority at the moment.
  1421  	assert(op != 0)
  1422  	w.sync(syncOp)
  1423  	w.len(int(op))
  1424  }
  1425  
  1426  func (w *writer) needType(typ types2.Type) {
  1427  	// Decompose tuple into component element types.
  1428  	if typ, ok := typ.(*types2.Tuple); ok {
  1429  		for i := 0; i < typ.Len(); i++ {
  1430  			w.needType(typ.At(i).Type())
  1431  		}
  1432  		return
  1433  	}
  1434  
  1435  	if info := w.p.typIdx(typ, w.dict); info.derived {
  1436  		w.dict.derived[info.idx].needed = true
  1437  	}
  1438  }
  1439  
  1440  // @@@ Package initialization
  1441  
  1442  // Caution: This code is still clumsy, because toolstash -cmp is
  1443  // particularly sensitive to it.
  1444  
  1445  type typeDeclGen struct {
  1446  	*syntax.TypeDecl
  1447  	gen int
  1448  
  1449  	// Implicit type parameters in scope at this type declaration.
  1450  	implicits []*types2.TypeName
  1451  }
  1452  
  1453  type fileImports struct {
  1454  	importedEmbed, importedUnsafe bool
  1455  }
  1456  
  1457  type declCollector struct {
  1458  	pw         *pkgWriter
  1459  	typegen    *int
  1460  	file       *fileImports
  1461  	withinFunc bool
  1462  	implicits  []*types2.TypeName
  1463  }
  1464  
  1465  func (c *declCollector) withTParams(obj types2.Object) *declCollector {
  1466  	tparams := objTypeParams(obj)
  1467  	n := tparams.Len()
  1468  	if n == 0 {
  1469  		return c
  1470  	}
  1471  
  1472  	copy := *c
  1473  	copy.implicits = copy.implicits[:len(copy.implicits):len(copy.implicits)]
  1474  	for i := 0; i < n; i++ {
  1475  		copy.implicits = append(copy.implicits, tparams.At(i).Obj())
  1476  	}
  1477  	return &copy
  1478  }
  1479  
  1480  func (c *declCollector) Visit(n syntax.Node) syntax.Visitor {
  1481  	pw := c.pw
  1482  
  1483  	switch n := n.(type) {
  1484  	case *syntax.File:
  1485  		pw.checkPragmas(n.Pragma, ir.GoBuildPragma, false)
  1486  
  1487  	case *syntax.ImportDecl:
  1488  		pw.checkPragmas(n.Pragma, 0, false)
  1489  
  1490  		switch pkgNameOf(pw.info, n).Imported().Path() {
  1491  		case "embed":
  1492  			c.file.importedEmbed = true
  1493  		case "unsafe":
  1494  			c.file.importedUnsafe = true
  1495  		}
  1496  
  1497  	case *syntax.ConstDecl:
  1498  		pw.checkPragmas(n.Pragma, 0, false)
  1499  
  1500  	case *syntax.FuncDecl:
  1501  		pw.checkPragmas(n.Pragma, funcPragmas, false)
  1502  
  1503  		obj := pw.info.Defs[n.Name].(*types2.Func)
  1504  		pw.funDecls[obj] = n
  1505  
  1506  		return c.withTParams(obj)
  1507  
  1508  	case *syntax.TypeDecl:
  1509  		obj := pw.info.Defs[n.Name].(*types2.TypeName)
  1510  		d := typeDeclGen{TypeDecl: n, implicits: c.implicits}
  1511  
  1512  		if n.Alias {
  1513  			pw.checkPragmas(n.Pragma, 0, false)
  1514  		} else {
  1515  			pw.checkPragmas(n.Pragma, typePragmas, false)
  1516  
  1517  			// Assign a unique ID to function-scoped defined types.
  1518  			if c.withinFunc {
  1519  				*c.typegen++
  1520  				d.gen = *c.typegen
  1521  			}
  1522  		}
  1523  
  1524  		pw.typDecls[obj] = d
  1525  
  1526  		// TODO(mdempsky): Omit? Not strictly necessary; only matters for
  1527  		// type declarations within function literals within parameterized
  1528  		// type declarations, but types2 the function literals will be
  1529  		// constant folded away.
  1530  		return c.withTParams(obj)
  1531  
  1532  	case *syntax.VarDecl:
  1533  		pw.checkPragmas(n.Pragma, 0, true)
  1534  
  1535  		if p, ok := n.Pragma.(*pragmas); ok && len(p.Embeds) > 0 {
  1536  			if err := checkEmbed(n, c.file.importedEmbed, c.withinFunc); err != nil {
  1537  				pw.errorf(p.Embeds[0].Pos, "%s", err)
  1538  			}
  1539  		}
  1540  
  1541  		// Workaround for #46208. For variable declarations that
  1542  		// declare multiple variables and have an explicit type
  1543  		// expression, the type expression is evaluated multiple
  1544  		// times. This affects toolstash -cmp, because iexport is
  1545  		// sensitive to *types.Type pointer identity.
  1546  		if quirksMode() && n.Type != nil {
  1547  			tv, ok := pw.info.Types[n.Type]
  1548  			assert(ok)
  1549  			assert(tv.IsType())
  1550  			for _, name := range n.NameList {
  1551  				obj := pw.info.Defs[name].(*types2.Var)
  1552  				pw.dups.add(obj.Type(), tv.Type)
  1553  			}
  1554  		}
  1555  
  1556  	case *syntax.BlockStmt:
  1557  		if !c.withinFunc {
  1558  			copy := *c
  1559  			copy.withinFunc = true
  1560  			return &copy
  1561  		}
  1562  	}
  1563  
  1564  	return c
  1565  }
  1566  
  1567  func (pw *pkgWriter) collectDecls(noders []*noder) {
  1568  	var typegen int
  1569  	for _, p := range noders {
  1570  		var file fileImports
  1571  
  1572  		syntax.Walk(p.file, &declCollector{
  1573  			pw:      pw,
  1574  			typegen: &typegen,
  1575  			file:    &file,
  1576  		})
  1577  
  1578  		pw.cgoPragmas = append(pw.cgoPragmas, p.pragcgobuf...)
  1579  
  1580  		for _, l := range p.linknames {
  1581  			if !file.importedUnsafe {
  1582  				pw.errorf(l.pos, "//go:linkname only allowed in Go files that import \"unsafe\"")
  1583  				continue
  1584  			}
  1585  
  1586  			switch obj := pw.curpkg.Scope().Lookup(l.local).(type) {
  1587  			case *types2.Func, *types2.Var:
  1588  				if _, ok := pw.linknames[obj]; !ok {
  1589  					pw.linknames[obj] = l.remote
  1590  				} else {
  1591  					pw.errorf(l.pos, "duplicate //go:linkname for %s", l.local)
  1592  				}
  1593  
  1594  			default:
  1595  				// TODO(mdempsky): Enable after #42938 is fixed.
  1596  				if false {
  1597  					pw.errorf(l.pos, "//go:linkname must refer to declared function or variable")
  1598  				}
  1599  			}
  1600  		}
  1601  	}
  1602  }
  1603  
  1604  func (pw *pkgWriter) checkPragmas(p syntax.Pragma, allowed ir.PragmaFlag, embedOK bool) {
  1605  	if p == nil {
  1606  		return
  1607  	}
  1608  	pragma := p.(*pragmas)
  1609  
  1610  	for _, pos := range pragma.Pos {
  1611  		if pos.Flag&^allowed != 0 {
  1612  			pw.errorf(pos.Pos, "misplaced compiler directive")
  1613  		}
  1614  	}
  1615  
  1616  	if !embedOK {
  1617  		for _, e := range pragma.Embeds {
  1618  			pw.errorf(e.Pos, "misplaced go:embed directive")
  1619  		}
  1620  	}
  1621  }
  1622  
  1623  func (w *writer) pkgInit(noders []*noder) {
  1624  	if quirksMode() {
  1625  		posBases := posBasesOf(noders)
  1626  		w.len(len(posBases))
  1627  		for _, posBase := range posBases {
  1628  			w.posBase(posBase)
  1629  		}
  1630  
  1631  		objs := importedObjsOf(w.p.curpkg, w.p.info, noders)
  1632  		w.len(len(objs))
  1633  		for _, obj := range objs {
  1634  			w.qualifiedIdent(obj)
  1635  		}
  1636  	}
  1637  
  1638  	w.len(len(w.p.cgoPragmas))
  1639  	for _, cgoPragma := range w.p.cgoPragmas {
  1640  		w.strings(cgoPragma)
  1641  	}
  1642  
  1643  	w.sync(syncDecls)
  1644  	for _, p := range noders {
  1645  		for _, decl := range p.file.DeclList {
  1646  			w.pkgDecl(decl)
  1647  		}
  1648  	}
  1649  	w.code(declEnd)
  1650  
  1651  	w.sync(syncEOF)
  1652  }
  1653  
  1654  func (w *writer) pkgDecl(decl syntax.Decl) {
  1655  	switch decl := decl.(type) {
  1656  	default:
  1657  		w.p.unexpected("declaration", decl)
  1658  
  1659  	case *syntax.ImportDecl:
  1660  
  1661  	case *syntax.ConstDecl:
  1662  		w.code(declOther)
  1663  		w.pkgObjs(decl.NameList...)
  1664  
  1665  	case *syntax.FuncDecl:
  1666  		if decl.Name.Value == "_" {
  1667  			break // skip blank functions
  1668  		}
  1669  
  1670  		obj := w.p.info.Defs[decl.Name].(*types2.Func)
  1671  		sig := obj.Type().(*types2.Signature)
  1672  
  1673  		if sig.RecvTypeParams() != nil || sig.TypeParams() != nil {
  1674  			break // skip generic functions
  1675  		}
  1676  
  1677  		if recv := sig.Recv(); recv != nil {
  1678  			w.code(declMethod)
  1679  			w.typ(recvBase(recv))
  1680  			w.selector(obj)
  1681  			break
  1682  		}
  1683  
  1684  		w.code(declFunc)
  1685  		w.pkgObjs(decl.Name)
  1686  
  1687  	case *syntax.TypeDecl:
  1688  		if len(decl.TParamList) != 0 {
  1689  			break // skip generic type decls
  1690  		}
  1691  
  1692  		if decl.Name.Value == "_" {
  1693  			break // skip blank type decls
  1694  		}
  1695  
  1696  		name := w.p.info.Defs[decl.Name].(*types2.TypeName)
  1697  		// Skip type declarations for interfaces that are only usable as
  1698  		// type parameter bounds.
  1699  		if iface, ok := name.Type().Underlying().(*types2.Interface); ok && !iface.IsMethodSet() {
  1700  			break
  1701  		}
  1702  
  1703  		// Skip aliases to uninstantiated generic types.
  1704  		// TODO(mdempsky): Revisit after #46477 is resolved.
  1705  		if name.IsAlias() {
  1706  			named, ok := name.Type().(*types2.Named)
  1707  			if ok && named.TypeParams().Len() != 0 && named.TypeArgs().Len() == 0 {
  1708  				break
  1709  			}
  1710  		}
  1711  
  1712  		w.code(declOther)
  1713  		w.pkgObjs(decl.Name)
  1714  
  1715  	case *syntax.VarDecl:
  1716  		w.code(declVar)
  1717  		w.pos(decl)
  1718  		w.pkgObjs(decl.NameList...)
  1719  		w.exprList(decl.Values)
  1720  
  1721  		var embeds []pragmaEmbed
  1722  		if p, ok := decl.Pragma.(*pragmas); ok {
  1723  			embeds = p.Embeds
  1724  		}
  1725  		w.len(len(embeds))
  1726  		for _, embed := range embeds {
  1727  			w.pos(embed.Pos)
  1728  			w.strings(embed.Patterns)
  1729  		}
  1730  	}
  1731  }
  1732  
  1733  func (w *writer) pkgObjs(names ...*syntax.Name) {
  1734  	w.sync(syncDeclNames)
  1735  	w.len(len(names))
  1736  
  1737  	for _, name := range names {
  1738  		obj, ok := w.p.info.Defs[name]
  1739  		assert(ok)
  1740  
  1741  		w.sync(syncDeclName)
  1742  		w.obj(obj, nil)
  1743  	}
  1744  }
  1745  
  1746  // @@@ Helpers
  1747  
  1748  // isDefinedType reports whether obj is a defined type.
  1749  func isDefinedType(obj types2.Object) bool {
  1750  	if obj, ok := obj.(*types2.TypeName); ok {
  1751  		return !obj.IsAlias()
  1752  	}
  1753  	return false
  1754  }
  1755  
  1756  // isGlobal reports whether obj was declared at package scope.
  1757  //
  1758  // Caveat: blank objects are not declared.
  1759  func isGlobal(obj types2.Object) bool {
  1760  	return obj.Parent() == obj.Pkg().Scope()
  1761  }
  1762  
  1763  // lookupObj returns the object that expr refers to, if any. If expr
  1764  // is an explicit instantiation of a generic object, then the instance
  1765  // object is returned as well.
  1766  func lookupObj(info *types2.Info, expr syntax.Expr) (obj types2.Object, inst types2.Instance) {
  1767  	if index, ok := expr.(*syntax.IndexExpr); ok {
  1768  		args := unpackListExpr(index.Index)
  1769  		if len(args) == 1 {
  1770  			tv, ok := info.Types[args[0]]
  1771  			assert(ok)
  1772  			if tv.IsValue() {
  1773  				return // normal index expression
  1774  			}
  1775  		}
  1776  
  1777  		expr = index.X
  1778  	}
  1779  
  1780  	// Strip package qualifier, if present.
  1781  	if sel, ok := expr.(*syntax.SelectorExpr); ok {
  1782  		if !isPkgQual(info, sel) {
  1783  			return // normal selector expression
  1784  		}
  1785  		expr = sel.Sel
  1786  	}
  1787  
  1788  	if name, ok := expr.(*syntax.Name); ok {
  1789  		obj = info.Uses[name]
  1790  		inst = info.Instances[name]
  1791  	}
  1792  	return
  1793  }
  1794  
  1795  // isPkgQual reports whether the given selector expression is a
  1796  // package-qualified identifier.
  1797  func isPkgQual(info *types2.Info, sel *syntax.SelectorExpr) bool {
  1798  	if name, ok := sel.X.(*syntax.Name); ok {
  1799  		_, isPkgName := info.Uses[name].(*types2.PkgName)
  1800  		return isPkgName
  1801  	}
  1802  	return false
  1803  }
  1804  
  1805  // recvBase returns the base type for the given receiver parameter.
  1806  func recvBase(recv *types2.Var) *types2.Named {
  1807  	typ := recv.Type()
  1808  	if ptr, ok := typ.(*types2.Pointer); ok {
  1809  		typ = ptr.Elem()
  1810  	}
  1811  	return typ.(*types2.Named)
  1812  }
  1813  
  1814  // namesAsExpr returns a list of names as a syntax.Expr.
  1815  func namesAsExpr(names []*syntax.Name) syntax.Expr {
  1816  	if len(names) == 1 {
  1817  		return names[0]
  1818  	}
  1819  
  1820  	exprs := make([]syntax.Expr, len(names))
  1821  	for i, name := range names {
  1822  		exprs[i] = name
  1823  	}
  1824  	return &syntax.ListExpr{ElemList: exprs}
  1825  }
  1826  
  1827  // fieldIndex returns the index of the struct field named by key.
  1828  func fieldIndex(info *types2.Info, str *types2.Struct, key *syntax.Name) int {
  1829  	field := info.Uses[key].(*types2.Var)
  1830  
  1831  	for i := 0; i < str.NumFields(); i++ {
  1832  		if str.Field(i) == field {
  1833  			return i
  1834  		}
  1835  	}
  1836  
  1837  	panic(fmt.Sprintf("%s: %v is not a field of %v", key.Pos(), field, str))
  1838  }
  1839  
  1840  // objTypeParams returns the type parameters on the given object.
  1841  func objTypeParams(obj types2.Object) *types2.TypeParamList {
  1842  	switch obj := obj.(type) {
  1843  	case *types2.Func:
  1844  		sig := obj.Type().(*types2.Signature)
  1845  		if sig.Recv() != nil {
  1846  			return sig.RecvTypeParams()
  1847  		}
  1848  		return sig.TypeParams()
  1849  	case *types2.TypeName:
  1850  		if !obj.IsAlias() {
  1851  			return obj.Type().(*types2.Named).TypeParams()
  1852  		}
  1853  	}
  1854  	return nil
  1855  }
  1856  
  1857  func asPragmaFlag(p syntax.Pragma) ir.PragmaFlag {
  1858  	if p == nil {
  1859  		return 0
  1860  	}
  1861  	return p.(*pragmas).Flag
  1862  }
  1863  

View as plain text