Source file src/cmd/compile/internal/noder/reader.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  	"bytes"
    11  	"fmt"
    12  	"go/constant"
    13  	"internal/buildcfg"
    14  	"strings"
    15  
    16  	"cmd/compile/internal/base"
    17  	"cmd/compile/internal/deadcode"
    18  	"cmd/compile/internal/dwarfgen"
    19  	"cmd/compile/internal/inline"
    20  	"cmd/compile/internal/ir"
    21  	"cmd/compile/internal/reflectdata"
    22  	"cmd/compile/internal/typecheck"
    23  	"cmd/compile/internal/types"
    24  	"cmd/internal/obj"
    25  	"cmd/internal/src"
    26  )
    27  
    28  // TODO(mdempsky): Suppress duplicate type/const errors that can arise
    29  // during typecheck due to naive type substitution (e.g., see #42758).
    30  // I anticipate these will be handled as a consequence of adding
    31  // dictionaries support, so it's probably not important to focus on
    32  // this until after that's done.
    33  
    34  type pkgReader struct {
    35  	pkgDecoder
    36  
    37  	posBases []*src.PosBase
    38  	pkgs     []*types.Pkg
    39  	typs     []*types.Type
    40  
    41  	// offset for rewriting the given index into the output,
    42  	// but bitwise inverted so we can detect if we're missing the entry or not.
    43  	newindex []int
    44  }
    45  
    46  func newPkgReader(pr pkgDecoder) *pkgReader {
    47  	return &pkgReader{
    48  		pkgDecoder: pr,
    49  
    50  		posBases: make([]*src.PosBase, pr.numElems(relocPosBase)),
    51  		pkgs:     make([]*types.Pkg, pr.numElems(relocPkg)),
    52  		typs:     make([]*types.Type, pr.numElems(relocType)),
    53  
    54  		newindex: make([]int, pr.totalElems()),
    55  	}
    56  }
    57  
    58  type pkgReaderIndex struct {
    59  	pr   *pkgReader
    60  	idx  int
    61  	dict *readerDict
    62  }
    63  
    64  func (pri pkgReaderIndex) asReader(k reloc, marker syncMarker) *reader {
    65  	r := pri.pr.newReader(k, pri.idx, marker)
    66  	r.dict = pri.dict
    67  	return r
    68  }
    69  
    70  func (pr *pkgReader) newReader(k reloc, idx int, marker syncMarker) *reader {
    71  	return &reader{
    72  		decoder: pr.newDecoder(k, idx, marker),
    73  		p:       pr,
    74  	}
    75  }
    76  
    77  type reader struct {
    78  	decoder
    79  
    80  	p *pkgReader
    81  
    82  	dict *readerDict
    83  
    84  	// TODO(mdempsky): The state below is all specific to reading
    85  	// function bodies. It probably makes sense to split it out
    86  	// separately so that it doesn't take up space in every reader
    87  	// instance.
    88  
    89  	curfn       *ir.Func
    90  	locals      []*ir.Name
    91  	closureVars []*ir.Name
    92  
    93  	funarghack bool
    94  
    95  	// scopeVars is a stack tracking the number of variables declared in
    96  	// the current function at the moment each open scope was opened.
    97  	scopeVars         []int
    98  	marker            dwarfgen.ScopeMarker
    99  	lastCloseScopePos src.XPos
   100  
   101  	// === details for handling inline body expansion ===
   102  
   103  	// If we're reading in a function body because of inlining, this is
   104  	// the call that we're inlining for.
   105  	inlCaller    *ir.Func
   106  	inlCall      *ir.CallExpr
   107  	inlFunc      *ir.Func
   108  	inlTreeIndex int
   109  	inlPosBases  map[*src.PosBase]*src.PosBase
   110  
   111  	delayResults bool
   112  
   113  	// Label to return to.
   114  	retlabel *types.Sym
   115  
   116  	inlvars, retvars ir.Nodes
   117  }
   118  
   119  type readerDict struct {
   120  	// targs holds the implicit and explicit type arguments in use for
   121  	// reading the current object. For example:
   122  	//
   123  	//	func F[T any]() {
   124  	//		type X[U any] struct { t T; u U }
   125  	//		var _ X[string]
   126  	//	}
   127  	//
   128  	//	var _ = F[int]
   129  	//
   130  	// While instantiating F[int], we need to in turn instantiate
   131  	// X[string]. [int] and [string] are explicit type arguments for F
   132  	// and X, respectively; but [int] is also the implicit type
   133  	// arguments for X.
   134  	//
   135  	// (As an analogy to function literals, explicits are the function
   136  	// literal's formal parameters, while implicits are variables
   137  	// captured by the function literal.)
   138  	targs []*types.Type
   139  
   140  	// implicits counts how many of types within targs are implicit type
   141  	// arguments; the rest are explicit.
   142  	implicits int
   143  
   144  	derived      []derivedInfo // reloc index of the derived type's descriptor
   145  	derivedTypes []*types.Type // slice of previously computed derived types
   146  
   147  	funcs    []objInfo
   148  	funcsObj []ir.Node
   149  }
   150  
   151  func setType(n ir.Node, typ *types.Type) {
   152  	n.SetType(typ)
   153  	n.SetTypecheck(1)
   154  
   155  	if name, ok := n.(*ir.Name); ok {
   156  		name.SetWalkdef(1)
   157  		name.Ntype = ir.TypeNode(name.Type())
   158  	}
   159  }
   160  
   161  func setValue(name *ir.Name, val constant.Value) {
   162  	name.SetVal(val)
   163  	name.Defn = nil
   164  }
   165  
   166  // @@@ Positions
   167  
   168  func (r *reader) pos() src.XPos {
   169  	return base.Ctxt.PosTable.XPos(r.pos0())
   170  }
   171  
   172  func (r *reader) pos0() src.Pos {
   173  	r.sync(syncPos)
   174  	if !r.bool() {
   175  		return src.NoPos
   176  	}
   177  
   178  	posBase := r.posBase()
   179  	line := r.uint()
   180  	col := r.uint()
   181  	return src.MakePos(posBase, line, col)
   182  }
   183  
   184  func (r *reader) posBase() *src.PosBase {
   185  	return r.inlPosBase(r.p.posBaseIdx(r.reloc(relocPosBase)))
   186  }
   187  
   188  func (pr *pkgReader) posBaseIdx(idx int) *src.PosBase {
   189  	if b := pr.posBases[idx]; b != nil {
   190  		return b
   191  	}
   192  
   193  	r := pr.newReader(relocPosBase, idx, syncPosBase)
   194  	var b *src.PosBase
   195  
   196  	absFilename := r.string()
   197  	filename := absFilename
   198  
   199  	// For build artifact stability, the export data format only
   200  	// contains the "absolute" filename as returned by objabi.AbsFile.
   201  	// However, some tests (e.g., test/run.go's asmcheck tests) expect
   202  	// to see the full, original filename printed out. Re-expanding
   203  	// "$GOROOT" to buildcfg.GOROOT is a close-enough approximation to
   204  	// satisfy this.
   205  	//
   206  	// TODO(mdempsky): De-duplicate this logic with similar logic in
   207  	// cmd/link/internal/ld's expandGoroot. However, this will probably
   208  	// require being more consistent about when we use native vs UNIX
   209  	// file paths.
   210  	const dollarGOROOT = "$GOROOT"
   211  	if strings.HasPrefix(filename, dollarGOROOT) {
   212  		filename = buildcfg.GOROOT + filename[len(dollarGOROOT):]
   213  	}
   214  
   215  	if r.bool() {
   216  		b = src.NewFileBase(filename, absFilename)
   217  	} else {
   218  		pos := r.pos0()
   219  		line := r.uint()
   220  		col := r.uint()
   221  		b = src.NewLinePragmaBase(pos, filename, absFilename, line, col)
   222  	}
   223  
   224  	pr.posBases[idx] = b
   225  	return b
   226  }
   227  
   228  func (r *reader) inlPosBase(oldBase *src.PosBase) *src.PosBase {
   229  	if r.inlCall == nil {
   230  		return oldBase
   231  	}
   232  
   233  	if newBase, ok := r.inlPosBases[oldBase]; ok {
   234  		return newBase
   235  	}
   236  
   237  	newBase := src.NewInliningBase(oldBase, r.inlTreeIndex)
   238  	r.inlPosBases[oldBase] = newBase
   239  	return newBase
   240  }
   241  
   242  func (r *reader) updatePos(xpos src.XPos) src.XPos {
   243  	pos := base.Ctxt.PosTable.Pos(xpos)
   244  	pos.SetBase(r.inlPosBase(pos.Base()))
   245  	return base.Ctxt.PosTable.XPos(pos)
   246  }
   247  
   248  func (r *reader) origPos(xpos src.XPos) src.XPos {
   249  	if r.inlCall == nil {
   250  		return xpos
   251  	}
   252  
   253  	pos := base.Ctxt.PosTable.Pos(xpos)
   254  	for old, new := range r.inlPosBases {
   255  		if pos.Base() == new {
   256  			pos.SetBase(old)
   257  			return base.Ctxt.PosTable.XPos(pos)
   258  		}
   259  	}
   260  
   261  	base.FatalfAt(xpos, "pos base missing from inlPosBases")
   262  	panic("unreachable")
   263  }
   264  
   265  // @@@ Packages
   266  
   267  func (r *reader) pkg() *types.Pkg {
   268  	r.sync(syncPkg)
   269  	return r.p.pkgIdx(r.reloc(relocPkg))
   270  }
   271  
   272  func (pr *pkgReader) pkgIdx(idx int) *types.Pkg {
   273  	if pkg := pr.pkgs[idx]; pkg != nil {
   274  		return pkg
   275  	}
   276  
   277  	pkg := pr.newReader(relocPkg, idx, syncPkgDef).doPkg()
   278  	pr.pkgs[idx] = pkg
   279  	return pkg
   280  }
   281  
   282  func (r *reader) doPkg() *types.Pkg {
   283  	path := r.string()
   284  	if path == "builtin" {
   285  		return types.BuiltinPkg
   286  	}
   287  	if path == "" {
   288  		path = r.p.pkgPath
   289  	}
   290  
   291  	name := r.string()
   292  	height := r.len()
   293  
   294  	pkg := types.NewPkg(path, "")
   295  
   296  	if pkg.Name == "" {
   297  		pkg.Name = name
   298  	} else {
   299  		assert(pkg.Name == name)
   300  	}
   301  
   302  	if pkg.Height == 0 {
   303  		pkg.Height = height
   304  	} else {
   305  		assert(pkg.Height == height)
   306  	}
   307  
   308  	return pkg
   309  }
   310  
   311  // @@@ Types
   312  
   313  func (r *reader) typ() *types.Type {
   314  	return r.typWrapped(true)
   315  }
   316  
   317  // typWrapped is like typ, but allows suppressing generation of
   318  // unnecessary wrappers as a compile-time optimization.
   319  func (r *reader) typWrapped(wrapped bool) *types.Type {
   320  	return r.p.typIdx(r.typInfo(), r.dict, wrapped)
   321  }
   322  
   323  func (r *reader) typInfo() typeInfo {
   324  	r.sync(syncType)
   325  	if r.bool() {
   326  		return typeInfo{idx: r.len(), derived: true}
   327  	}
   328  	return typeInfo{idx: r.reloc(relocType), derived: false}
   329  }
   330  
   331  func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict, wrapped bool) *types.Type {
   332  	idx := info.idx
   333  	var where **types.Type
   334  	if info.derived {
   335  		where = &dict.derivedTypes[idx]
   336  		idx = dict.derived[idx].idx
   337  	} else {
   338  		where = &pr.typs[idx]
   339  	}
   340  
   341  	if typ := *where; typ != nil {
   342  		return typ
   343  	}
   344  
   345  	r := pr.newReader(relocType, idx, syncTypeIdx)
   346  	r.dict = dict
   347  
   348  	typ := r.doTyp()
   349  	assert(typ != nil)
   350  
   351  	// For recursive type declarations involving interfaces and aliases,
   352  	// above r.doTyp() call may have already set pr.typs[idx], so just
   353  	// double check and return the type.
   354  	//
   355  	// Example:
   356  	//
   357  	//     type F = func(I)
   358  	//
   359  	//     type I interface {
   360  	//         m(F)
   361  	//     }
   362  	//
   363  	// The writer writes data types in following index order:
   364  	//
   365  	//     0: func(I)
   366  	//     1: I
   367  	//     2: interface{m(func(I))}
   368  	//
   369  	// The reader resolves it in following index order:
   370  	//
   371  	//     0 -> 1 -> 2 -> 0 -> 1
   372  	//
   373  	// and can divide in logically 2 steps:
   374  	//
   375  	//  - 0 -> 1     : first time the reader reach type I,
   376  	//                 it creates new named type with symbol I.
   377  	//
   378  	//  - 2 -> 0 -> 1: the reader ends up reaching symbol I again,
   379  	//                 now the symbol I was setup in above step, so
   380  	//                 the reader just return the named type.
   381  	//
   382  	// Now, the functions called return, the pr.typs looks like below:
   383  	//
   384  	//  - 0 -> 1 -> 2 -> 0 : [<T> I <T>]
   385  	//  - 0 -> 1 -> 2      : [func(I) I <T>]
   386  	//  - 0 -> 1           : [func(I) I interface { "".m(func("".I)) }]
   387  	//
   388  	// The idx 1, corresponding with type I was resolved successfully
   389  	// after r.doTyp() call.
   390  
   391  	if prev := *where; prev != nil {
   392  		return prev
   393  	}
   394  
   395  	if wrapped {
   396  		// Only cache if we're adding wrappers, so that other callers that
   397  		// find a cached type know it was wrapped.
   398  		*where = typ
   399  
   400  		r.needWrapper(typ)
   401  	}
   402  
   403  	if !typ.IsUntyped() {
   404  		types.CheckSize(typ)
   405  	}
   406  
   407  	return typ
   408  }
   409  
   410  func (r *reader) doTyp() *types.Type {
   411  	switch tag := codeType(r.code(syncType)); tag {
   412  	default:
   413  		panic(fmt.Sprintf("unexpected type: %v", tag))
   414  
   415  	case typeBasic:
   416  		return *basics[r.len()]
   417  
   418  	case typeNamed:
   419  		obj := r.obj()
   420  		assert(obj.Op() == ir.OTYPE)
   421  		return obj.Type()
   422  
   423  	case typeTypeParam:
   424  		return r.dict.targs[r.len()]
   425  
   426  	case typeArray:
   427  		len := int64(r.uint64())
   428  		return types.NewArray(r.typ(), len)
   429  	case typeChan:
   430  		dir := dirs[r.len()]
   431  		return types.NewChan(r.typ(), dir)
   432  	case typeMap:
   433  		return types.NewMap(r.typ(), r.typ())
   434  	case typePointer:
   435  		return types.NewPtr(r.typ())
   436  	case typeSignature:
   437  		return r.signature(types.LocalPkg, nil)
   438  	case typeSlice:
   439  		return types.NewSlice(r.typ())
   440  	case typeStruct:
   441  		return r.structType()
   442  	case typeInterface:
   443  		return r.interfaceType()
   444  	}
   445  }
   446  
   447  func (r *reader) interfaceType() *types.Type {
   448  	tpkg := types.LocalPkg // TODO(mdempsky): Remove after iexport is gone.
   449  
   450  	nmethods, nembeddeds := r.len(), r.len()
   451  
   452  	fields := make([]*types.Field, nmethods+nembeddeds)
   453  	methods, embeddeds := fields[:nmethods], fields[nmethods:]
   454  
   455  	for i := range methods {
   456  		pos := r.pos()
   457  		pkg, sym := r.selector()
   458  		tpkg = pkg
   459  		mtyp := r.signature(pkg, types.FakeRecv())
   460  		methods[i] = types.NewField(pos, sym, mtyp)
   461  	}
   462  	for i := range embeddeds {
   463  		embeddeds[i] = types.NewField(src.NoXPos, nil, r.typ())
   464  	}
   465  
   466  	if len(fields) == 0 {
   467  		return types.Types[types.TINTER] // empty interface
   468  	}
   469  	return types.NewInterface(tpkg, fields, false)
   470  }
   471  
   472  func (r *reader) structType() *types.Type {
   473  	tpkg := types.LocalPkg // TODO(mdempsky): Remove after iexport is gone.
   474  	fields := make([]*types.Field, r.len())
   475  	for i := range fields {
   476  		pos := r.pos()
   477  		pkg, sym := r.selector()
   478  		tpkg = pkg
   479  		ftyp := r.typ()
   480  		tag := r.string()
   481  		embedded := r.bool()
   482  
   483  		f := types.NewField(pos, sym, ftyp)
   484  		f.Note = tag
   485  		if embedded {
   486  			f.Embedded = 1
   487  		}
   488  		fields[i] = f
   489  	}
   490  	return types.NewStruct(tpkg, fields)
   491  }
   492  
   493  func (r *reader) signature(tpkg *types.Pkg, recv *types.Field) *types.Type {
   494  	r.sync(syncSignature)
   495  
   496  	params := r.params(&tpkg)
   497  	results := r.params(&tpkg)
   498  	if r.bool() { // variadic
   499  		params[len(params)-1].SetIsDDD(true)
   500  	}
   501  
   502  	return types.NewSignature(tpkg, recv, nil, params, results)
   503  }
   504  
   505  func (r *reader) params(tpkg **types.Pkg) []*types.Field {
   506  	r.sync(syncParams)
   507  	fields := make([]*types.Field, r.len())
   508  	for i := range fields {
   509  		*tpkg, fields[i] = r.param()
   510  	}
   511  	return fields
   512  }
   513  
   514  func (r *reader) param() (*types.Pkg, *types.Field) {
   515  	r.sync(syncParam)
   516  
   517  	pos := r.pos()
   518  	pkg, sym := r.localIdent()
   519  	typ := r.typ()
   520  
   521  	return pkg, types.NewField(pos, sym, typ)
   522  }
   523  
   524  // @@@ Objects
   525  
   526  var objReader = map[*types.Sym]pkgReaderIndex{}
   527  
   528  func (r *reader) obj() ir.Node {
   529  	r.sync(syncObject)
   530  
   531  	if r.bool() {
   532  		idx := r.len()
   533  		obj := r.dict.funcsObj[idx]
   534  		if obj == nil {
   535  			fn := r.dict.funcs[idx]
   536  			targs := make([]*types.Type, len(fn.explicits))
   537  			for i, targ := range fn.explicits {
   538  				targs[i] = r.p.typIdx(targ, r.dict, true)
   539  			}
   540  
   541  			obj = r.p.objIdx(fn.idx, nil, targs)
   542  			assert(r.dict.funcsObj[idx] == nil)
   543  			r.dict.funcsObj[idx] = obj
   544  		}
   545  		return obj
   546  	}
   547  
   548  	idx := r.reloc(relocObj)
   549  
   550  	explicits := make([]*types.Type, r.len())
   551  	for i := range explicits {
   552  		explicits[i] = r.typ()
   553  	}
   554  
   555  	var implicits []*types.Type
   556  	if r.dict != nil {
   557  		implicits = r.dict.targs
   558  	}
   559  
   560  	return r.p.objIdx(idx, implicits, explicits)
   561  }
   562  
   563  func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node {
   564  	rname := pr.newReader(relocName, idx, syncObject1)
   565  	_, sym := rname.qualifiedIdent()
   566  	tag := codeObj(rname.code(syncCodeObj))
   567  
   568  	if tag == objStub {
   569  		assert(!sym.IsBlank())
   570  		switch sym.Pkg {
   571  		case types.BuiltinPkg, types.UnsafePkg:
   572  			return sym.Def.(ir.Node)
   573  		}
   574  		if pri, ok := objReader[sym]; ok {
   575  			return pri.pr.objIdx(pri.idx, nil, explicits)
   576  		}
   577  		if haveLegacyImports {
   578  			assert(len(explicits) == 0)
   579  			return typecheck.Resolve(ir.NewIdent(src.NoXPos, sym))
   580  		}
   581  		base.Fatalf("unresolved stub: %v", sym)
   582  	}
   583  
   584  	dict := pr.objDictIdx(sym, idx, implicits, explicits)
   585  
   586  	r := pr.newReader(relocObj, idx, syncObject1)
   587  	rext := pr.newReader(relocObjExt, idx, syncObject1)
   588  
   589  	r.dict = dict
   590  	rext.dict = dict
   591  
   592  	sym = r.mangle(sym)
   593  	if !sym.IsBlank() && sym.Def != nil {
   594  		return sym.Def.(*ir.Name)
   595  	}
   596  
   597  	do := func(op ir.Op, hasTParams bool) *ir.Name {
   598  		pos := r.pos()
   599  		if hasTParams {
   600  			r.typeParamNames()
   601  		}
   602  
   603  		name := ir.NewDeclNameAt(pos, op, sym)
   604  		name.Class = ir.PEXTERN // may be overridden later
   605  		if !sym.IsBlank() {
   606  			if sym.Def != nil {
   607  				base.FatalfAt(name.Pos(), "already have a definition for %v", name)
   608  			}
   609  			assert(sym.Def == nil)
   610  			sym.Def = name
   611  		}
   612  		return name
   613  	}
   614  
   615  	switch tag {
   616  	default:
   617  		panic("unexpected object")
   618  
   619  	case objAlias:
   620  		name := do(ir.OTYPE, false)
   621  		setType(name, r.typ())
   622  		name.SetAlias(true)
   623  		return name
   624  
   625  	case objConst:
   626  		name := do(ir.OLITERAL, false)
   627  		typ := r.typ()
   628  		val := FixValue(typ, r.value())
   629  		setType(name, typ)
   630  		setValue(name, val)
   631  		return name
   632  
   633  	case objFunc:
   634  		if sym.Name == "init" {
   635  			sym = renameinit()
   636  		}
   637  		name := do(ir.ONAME, true)
   638  		setType(name, r.signature(sym.Pkg, nil))
   639  
   640  		name.Func = ir.NewFunc(r.pos())
   641  		name.Func.Nname = name
   642  
   643  		rext.funcExt(name)
   644  		return name
   645  
   646  	case objType:
   647  		name := do(ir.OTYPE, true)
   648  		typ := types.NewNamed(name)
   649  		setType(name, typ)
   650  
   651  		// Important: We need to do this before SetUnderlying.
   652  		rext.typeExt(name)
   653  
   654  		// We need to defer CheckSize until we've called SetUnderlying to
   655  		// handle recursive types.
   656  		types.DeferCheckSize()
   657  		typ.SetUnderlying(r.typWrapped(false))
   658  		types.ResumeCheckSize()
   659  
   660  		methods := make([]*types.Field, r.len())
   661  		for i := range methods {
   662  			methods[i] = r.method(rext)
   663  		}
   664  		if len(methods) != 0 {
   665  			typ.Methods().Set(methods)
   666  		}
   667  
   668  		r.needWrapper(typ)
   669  
   670  		return name
   671  
   672  	case objVar:
   673  		name := do(ir.ONAME, false)
   674  		setType(name, r.typ())
   675  		rext.varExt(name)
   676  		return name
   677  	}
   678  }
   679  
   680  func (r *reader) mangle(sym *types.Sym) *types.Sym {
   681  	if !r.hasTypeParams() {
   682  		return sym
   683  	}
   684  
   685  	var buf bytes.Buffer
   686  	buf.WriteString(sym.Name)
   687  	buf.WriteByte('[')
   688  	for i, targ := range r.dict.targs {
   689  		if i > 0 {
   690  			if i == r.dict.implicits {
   691  				buf.WriteByte(';')
   692  			} else {
   693  				buf.WriteByte(',')
   694  			}
   695  		}
   696  		buf.WriteString(targ.LinkString())
   697  	}
   698  	buf.WriteByte(']')
   699  	return sym.Pkg.Lookup(buf.String())
   700  }
   701  
   702  func (pr *pkgReader) objDictIdx(sym *types.Sym, idx int, implicits, explicits []*types.Type) *readerDict {
   703  	r := pr.newReader(relocObjDict, idx, syncObject1)
   704  
   705  	var dict readerDict
   706  
   707  	nimplicits := r.len()
   708  	nexplicits := r.len()
   709  
   710  	if nimplicits > len(implicits) || nexplicits != len(explicits) {
   711  		base.Fatalf("%v has %v+%v params, but instantiated with %v+%v args", sym, nimplicits, nexplicits, len(implicits), len(explicits))
   712  	}
   713  
   714  	dict.targs = append(implicits[:nimplicits:nimplicits], explicits...)
   715  	dict.implicits = nimplicits
   716  
   717  	// For stenciling, we can just skip over the type parameters.
   718  	for range dict.targs[dict.implicits:] {
   719  		// Skip past bounds without actually evaluating them.
   720  		r.sync(syncType)
   721  		if r.bool() {
   722  			r.len()
   723  		} else {
   724  			r.reloc(relocType)
   725  		}
   726  	}
   727  
   728  	dict.derived = make([]derivedInfo, r.len())
   729  	dict.derivedTypes = make([]*types.Type, len(dict.derived))
   730  	for i := range dict.derived {
   731  		dict.derived[i] = derivedInfo{r.reloc(relocType), r.bool()}
   732  	}
   733  
   734  	dict.funcs = make([]objInfo, r.len())
   735  	dict.funcsObj = make([]ir.Node, len(dict.funcs))
   736  	for i := range dict.funcs {
   737  		objIdx := r.reloc(relocObj)
   738  		targs := make([]typeInfo, r.len())
   739  		for j := range targs {
   740  			targs[j] = r.typInfo()
   741  		}
   742  		dict.funcs[i] = objInfo{idx: objIdx, explicits: targs}
   743  	}
   744  
   745  	return &dict
   746  }
   747  
   748  func (r *reader) typeParamNames() {
   749  	r.sync(syncTypeParamNames)
   750  
   751  	for range r.dict.targs[r.dict.implicits:] {
   752  		r.pos()
   753  		r.localIdent()
   754  	}
   755  }
   756  
   757  func (r *reader) method(rext *reader) *types.Field {
   758  	r.sync(syncMethod)
   759  	pos := r.pos()
   760  	pkg, sym := r.selector()
   761  	r.typeParamNames()
   762  	_, recv := r.param()
   763  	typ := r.signature(pkg, recv)
   764  
   765  	fnsym := sym
   766  	fnsym = ir.MethodSym(recv.Type, fnsym)
   767  	name := ir.NewNameAt(pos, fnsym)
   768  	setType(name, typ)
   769  
   770  	name.Func = ir.NewFunc(r.pos())
   771  	name.Func.Nname = name
   772  
   773  	rext.funcExt(name)
   774  
   775  	meth := types.NewField(name.Func.Pos(), sym, typ)
   776  	meth.Nname = name
   777  	meth.SetNointerface(name.Func.Pragma&ir.Nointerface != 0)
   778  
   779  	return meth
   780  }
   781  
   782  func (r *reader) qualifiedIdent() (pkg *types.Pkg, sym *types.Sym) {
   783  	r.sync(syncSym)
   784  	pkg = r.pkg()
   785  	if name := r.string(); name != "" {
   786  		sym = pkg.Lookup(name)
   787  	}
   788  	return
   789  }
   790  
   791  func (r *reader) localIdent() (pkg *types.Pkg, sym *types.Sym) {
   792  	r.sync(syncLocalIdent)
   793  	pkg = r.pkg()
   794  	if name := r.string(); name != "" {
   795  		sym = pkg.Lookup(name)
   796  	}
   797  	return
   798  }
   799  
   800  func (r *reader) selector() (origPkg *types.Pkg, sym *types.Sym) {
   801  	r.sync(syncSelector)
   802  	origPkg = r.pkg()
   803  	name := r.string()
   804  	pkg := origPkg
   805  	if types.IsExported(name) {
   806  		pkg = types.LocalPkg
   807  	}
   808  	sym = pkg.Lookup(name)
   809  	return
   810  }
   811  
   812  func (r *reader) hasTypeParams() bool {
   813  	return r.dict.hasTypeParams()
   814  }
   815  
   816  func (dict *readerDict) hasTypeParams() bool {
   817  	return dict != nil && len(dict.targs) != 0
   818  }
   819  
   820  // @@@ Compiler extensions
   821  
   822  func (r *reader) funcExt(name *ir.Name) {
   823  	r.sync(syncFuncExt)
   824  
   825  	name.Class = 0 // so MarkFunc doesn't complain
   826  	ir.MarkFunc(name)
   827  
   828  	fn := name.Func
   829  
   830  	// XXX: Workaround because linker doesn't know how to copy Pos.
   831  	if !fn.Pos().IsKnown() {
   832  		fn.SetPos(name.Pos())
   833  	}
   834  
   835  	// Normally, we only compile local functions, which saves redundant compilation work.
   836  	// n.Defn is not nil for local functions, and is nil for imported function. But for
   837  	// generic functions, we might have an instantiation that no other package has seen before.
   838  	// So we need to be conservative and compile it again.
   839  	//
   840  	// That's why name.Defn is set here, so ir.VisitFuncsBottomUp can analyze function.
   841  	// TODO(mdempsky,cuonglm): find a cleaner way to handle this.
   842  	if name.Sym().Pkg == types.LocalPkg || r.hasTypeParams() {
   843  		name.Defn = fn
   844  	}
   845  
   846  	fn.Pragma = r.pragmaFlag()
   847  	r.linkname(name)
   848  
   849  	typecheck.Func(fn)
   850  
   851  	if r.bool() {
   852  		fn.ABI = obj.ABI(r.uint64())
   853  
   854  		// Escape analysis.
   855  		for _, fs := range &types.RecvsParams {
   856  			for _, f := range fs(name.Type()).FieldSlice() {
   857  				f.Note = r.string()
   858  			}
   859  		}
   860  
   861  		if r.bool() {
   862  			fn.Inl = &ir.Inline{
   863  				Cost:            int32(r.len()),
   864  				CanDelayResults: r.bool(),
   865  			}
   866  			r.addBody(name.Func)
   867  		}
   868  	} else {
   869  		r.addBody(name.Func)
   870  	}
   871  	r.sync(syncEOF)
   872  }
   873  
   874  func (r *reader) typeExt(name *ir.Name) {
   875  	r.sync(syncTypeExt)
   876  
   877  	typ := name.Type()
   878  
   879  	if r.hasTypeParams() {
   880  		// Set "RParams" (really type arguments here, not parameters) so
   881  		// this type is treated as "fully instantiated". This ensures the
   882  		// type descriptor is written out as DUPOK and method wrappers are
   883  		// generated even for imported types.
   884  		var targs []*types.Type
   885  		targs = append(targs, r.dict.targs...)
   886  		typ.SetRParams(targs)
   887  	}
   888  
   889  	name.SetPragma(r.pragmaFlag())
   890  	if name.Pragma()&ir.NotInHeap != 0 {
   891  		typ.SetNotInHeap(true)
   892  	}
   893  
   894  	typecheck.SetBaseTypeIndex(typ, r.int64(), r.int64())
   895  }
   896  
   897  func (r *reader) varExt(name *ir.Name) {
   898  	r.sync(syncVarExt)
   899  	r.linkname(name)
   900  }
   901  
   902  func (r *reader) linkname(name *ir.Name) {
   903  	assert(name.Op() == ir.ONAME)
   904  	r.sync(syncLinkname)
   905  
   906  	if idx := r.int64(); idx >= 0 {
   907  		lsym := name.Linksym()
   908  		lsym.SymIdx = int32(idx)
   909  		lsym.Set(obj.AttrIndexed, true)
   910  	} else {
   911  		name.Sym().Linkname = r.string()
   912  	}
   913  }
   914  
   915  func (r *reader) pragmaFlag() ir.PragmaFlag {
   916  	r.sync(syncPragma)
   917  	return ir.PragmaFlag(r.int())
   918  }
   919  
   920  // @@@ Function bodies
   921  
   922  // bodyReader tracks where the serialized IR for a function's body can
   923  // be found.
   924  var bodyReader = map[*ir.Func]pkgReaderIndex{}
   925  
   926  // todoBodies holds the list of function bodies that still need to be
   927  // constructed.
   928  var todoBodies []*ir.Func
   929  
   930  // todoBodiesDone signals that we constructed all function in todoBodies.
   931  // This is necessary to prevent reader.addBody adds thing to todoBodies
   932  // when nested inlining happens.
   933  var todoBodiesDone = false
   934  
   935  func (r *reader) addBody(fn *ir.Func) {
   936  	pri := pkgReaderIndex{r.p, r.reloc(relocBody), r.dict}
   937  	bodyReader[fn] = pri
   938  
   939  	if fn.Nname.Defn == nil {
   940  		// Don't read in function body for imported functions.
   941  		// See comment in funcExt.
   942  		return
   943  	}
   944  
   945  	if r.curfn == nil && !todoBodiesDone {
   946  		todoBodies = append(todoBodies, fn)
   947  		return
   948  	}
   949  
   950  	pri.funcBody(fn)
   951  }
   952  
   953  func (pri pkgReaderIndex) funcBody(fn *ir.Func) {
   954  	r := pri.asReader(relocBody, syncFuncBody)
   955  	r.funcBody(fn)
   956  }
   957  
   958  func (r *reader) funcBody(fn *ir.Func) {
   959  	r.curfn = fn
   960  	r.closureVars = fn.ClosureVars
   961  
   962  	ir.WithFunc(fn, func() {
   963  		r.funcargs(fn)
   964  
   965  		if !r.bool() {
   966  			return
   967  		}
   968  
   969  		body := r.stmts()
   970  		if body == nil {
   971  			pos := src.NoXPos
   972  			if quirksMode() {
   973  				pos = funcParamsEndPos(fn)
   974  			}
   975  			body = []ir.Node{typecheck.Stmt(ir.NewBlockStmt(pos, nil))}
   976  		}
   977  		fn.Body = body
   978  		fn.Endlineno = r.pos()
   979  	})
   980  
   981  	r.marker.WriteTo(fn)
   982  }
   983  
   984  func (r *reader) funcargs(fn *ir.Func) {
   985  	sig := fn.Nname.Type()
   986  
   987  	if recv := sig.Recv(); recv != nil {
   988  		r.funcarg(recv, recv.Sym, ir.PPARAM)
   989  	}
   990  	for _, param := range sig.Params().FieldSlice() {
   991  		r.funcarg(param, param.Sym, ir.PPARAM)
   992  	}
   993  
   994  	for i, param := range sig.Results().FieldSlice() {
   995  		sym := types.OrigSym(param.Sym)
   996  
   997  		if sym == nil || sym.IsBlank() {
   998  			prefix := "~r"
   999  			if r.inlCall != nil {
  1000  				prefix = "~R"
  1001  			} else if sym != nil {
  1002  				prefix = "~b"
  1003  			}
  1004  			sym = typecheck.LookupNum(prefix, i)
  1005  		}
  1006  
  1007  		r.funcarg(param, sym, ir.PPARAMOUT)
  1008  	}
  1009  }
  1010  
  1011  func (r *reader) funcarg(param *types.Field, sym *types.Sym, ctxt ir.Class) {
  1012  	if sym == nil {
  1013  		assert(ctxt == ir.PPARAM)
  1014  		if r.inlCall != nil {
  1015  			r.inlvars.Append(ir.BlankNode)
  1016  		}
  1017  		return
  1018  	}
  1019  
  1020  	name := ir.NewNameAt(r.updatePos(param.Pos), sym)
  1021  	setType(name, param.Type)
  1022  	r.addLocal(name, ctxt)
  1023  
  1024  	if r.inlCall == nil {
  1025  		if !r.funarghack {
  1026  			param.Sym = sym
  1027  			param.Nname = name
  1028  		}
  1029  	} else {
  1030  		if ctxt == ir.PPARAMOUT {
  1031  			r.retvars.Append(name)
  1032  		} else {
  1033  			r.inlvars.Append(name)
  1034  		}
  1035  	}
  1036  }
  1037  
  1038  func (r *reader) addLocal(name *ir.Name, ctxt ir.Class) {
  1039  	assert(ctxt == ir.PAUTO || ctxt == ir.PPARAM || ctxt == ir.PPARAMOUT)
  1040  
  1041  	r.sync(syncAddLocal)
  1042  	if enableSync {
  1043  		want := r.int()
  1044  		if have := len(r.locals); have != want {
  1045  			base.FatalfAt(name.Pos(), "locals table has desynced")
  1046  		}
  1047  	}
  1048  
  1049  	name.SetUsed(true)
  1050  	r.locals = append(r.locals, name)
  1051  
  1052  	// TODO(mdempsky): Move earlier.
  1053  	if ir.IsBlank(name) {
  1054  		return
  1055  	}
  1056  
  1057  	if r.inlCall != nil {
  1058  		if ctxt == ir.PAUTO {
  1059  			name.SetInlLocal(true)
  1060  		} else {
  1061  			name.SetInlFormal(true)
  1062  			ctxt = ir.PAUTO
  1063  		}
  1064  
  1065  		// TODO(mdempsky): Rethink this hack.
  1066  		if strings.HasPrefix(name.Sym().Name, "~") || base.Flag.GenDwarfInl == 0 {
  1067  			name.SetPos(r.inlCall.Pos())
  1068  			name.SetInlFormal(false)
  1069  			name.SetInlLocal(false)
  1070  		}
  1071  	}
  1072  
  1073  	name.Class = ctxt
  1074  	name.Curfn = r.curfn
  1075  
  1076  	r.curfn.Dcl = append(r.curfn.Dcl, name)
  1077  
  1078  	if ctxt == ir.PAUTO {
  1079  		name.SetFrameOffset(0)
  1080  	}
  1081  }
  1082  
  1083  func (r *reader) useLocal() *ir.Name {
  1084  	r.sync(syncUseObjLocal)
  1085  	if r.bool() {
  1086  		return r.locals[r.len()]
  1087  	}
  1088  	return r.closureVars[r.len()]
  1089  }
  1090  
  1091  func (r *reader) openScope() {
  1092  	r.sync(syncOpenScope)
  1093  	pos := r.pos()
  1094  
  1095  	if base.Flag.Dwarf {
  1096  		r.scopeVars = append(r.scopeVars, len(r.curfn.Dcl))
  1097  		r.marker.Push(pos)
  1098  	}
  1099  }
  1100  
  1101  func (r *reader) closeScope() {
  1102  	r.sync(syncCloseScope)
  1103  	r.lastCloseScopePos = r.pos()
  1104  
  1105  	r.closeAnotherScope()
  1106  }
  1107  
  1108  // closeAnotherScope is like closeScope, but it reuses the same mark
  1109  // position as the last closeScope call. This is useful for "for" and
  1110  // "if" statements, as their implicit blocks always end at the same
  1111  // position as an explicit block.
  1112  func (r *reader) closeAnotherScope() {
  1113  	r.sync(syncCloseAnotherScope)
  1114  
  1115  	if base.Flag.Dwarf {
  1116  		scopeVars := r.scopeVars[len(r.scopeVars)-1]
  1117  		r.scopeVars = r.scopeVars[:len(r.scopeVars)-1]
  1118  
  1119  		// Quirkish: noder decides which scopes to keep before
  1120  		// typechecking, whereas incremental typechecking during IR
  1121  		// construction can result in new autotemps being allocated. To
  1122  		// produce identical output, we ignore autotemps here for the
  1123  		// purpose of deciding whether to retract the scope.
  1124  		//
  1125  		// This is important for net/http/fcgi, because it contains:
  1126  		//
  1127  		//	var body io.ReadCloser
  1128  		//	if len(content) > 0 {
  1129  		//		body, req.pw = io.Pipe()
  1130  		//	} else { … }
  1131  		//
  1132  		// Notably, io.Pipe is inlinable, and inlining it introduces a ~R0
  1133  		// variable at the call site.
  1134  		//
  1135  		// Noder does not preserve the scope where the io.Pipe() call
  1136  		// resides, because it doesn't contain any declared variables in
  1137  		// source. So the ~R0 variable ends up being assigned to the
  1138  		// enclosing scope instead.
  1139  		//
  1140  		// However, typechecking this assignment also introduces
  1141  		// autotemps, because io.Pipe's results need conversion before
  1142  		// they can be assigned to their respective destination variables.
  1143  		//
  1144  		// TODO(mdempsky): We should probably just keep all scopes, and
  1145  		// let dwarfgen take care of pruning them instead.
  1146  		retract := true
  1147  		for _, n := range r.curfn.Dcl[scopeVars:] {
  1148  			if !n.AutoTemp() {
  1149  				retract = false
  1150  				break
  1151  			}
  1152  		}
  1153  
  1154  		if retract {
  1155  			// no variables were declared in this scope, so we can retract it.
  1156  			r.marker.Unpush()
  1157  		} else {
  1158  			r.marker.Pop(r.lastCloseScopePos)
  1159  		}
  1160  	}
  1161  }
  1162  
  1163  // @@@ Statements
  1164  
  1165  func (r *reader) stmt() ir.Node {
  1166  	switch stmts := r.stmts(); len(stmts) {
  1167  	case 0:
  1168  		return nil
  1169  	case 1:
  1170  		return stmts[0]
  1171  	default:
  1172  		return ir.NewBlockStmt(stmts[0].Pos(), stmts)
  1173  	}
  1174  }
  1175  
  1176  func (r *reader) stmts() []ir.Node {
  1177  	assert(ir.CurFunc == r.curfn)
  1178  	var res ir.Nodes
  1179  
  1180  	r.sync(syncStmts)
  1181  	for {
  1182  		tag := codeStmt(r.code(syncStmt1))
  1183  		if tag == stmtEnd {
  1184  			r.sync(syncStmtsEnd)
  1185  			return res
  1186  		}
  1187  
  1188  		if n := r.stmt1(tag, &res); n != nil {
  1189  			res.Append(typecheck.Stmt(n))
  1190  		}
  1191  	}
  1192  }
  1193  
  1194  func (r *reader) stmt1(tag codeStmt, out *ir.Nodes) ir.Node {
  1195  	var label *types.Sym
  1196  	if n := len(*out); n > 0 {
  1197  		if ls, ok := (*out)[n-1].(*ir.LabelStmt); ok {
  1198  			label = ls.Label
  1199  		}
  1200  	}
  1201  
  1202  	switch tag {
  1203  	default:
  1204  		panic("unexpected statement")
  1205  
  1206  	case stmtAssign:
  1207  		pos := r.pos()
  1208  
  1209  		// TODO(mdempsky): After quirks mode is gone, swap these
  1210  		// statements so we visit LHS before RHS again.
  1211  		rhs := r.exprList()
  1212  		names, lhs := r.assignList()
  1213  
  1214  		if len(rhs) == 0 {
  1215  			for _, name := range names {
  1216  				as := ir.NewAssignStmt(pos, name, nil)
  1217  				as.PtrInit().Append(ir.NewDecl(pos, ir.ODCL, name))
  1218  				out.Append(typecheck.Stmt(as))
  1219  			}
  1220  			return nil
  1221  		}
  1222  
  1223  		if len(lhs) == 1 && len(rhs) == 1 {
  1224  			n := ir.NewAssignStmt(pos, lhs[0], rhs[0])
  1225  			n.Def = r.initDefn(n, names)
  1226  			return n
  1227  		}
  1228  
  1229  		n := ir.NewAssignListStmt(pos, ir.OAS2, lhs, rhs)
  1230  		n.Def = r.initDefn(n, names)
  1231  		return n
  1232  
  1233  	case stmtAssignOp:
  1234  		op := r.op()
  1235  		lhs := r.expr()
  1236  		pos := r.pos()
  1237  		rhs := r.expr()
  1238  		return ir.NewAssignOpStmt(pos, op, lhs, rhs)
  1239  
  1240  	case stmtIncDec:
  1241  		op := r.op()
  1242  		lhs := r.expr()
  1243  		pos := r.pos()
  1244  		n := ir.NewAssignOpStmt(pos, op, lhs, ir.NewBasicLit(pos, one))
  1245  		n.IncDec = true
  1246  		return n
  1247  
  1248  	case stmtBlock:
  1249  		out.Append(r.blockStmt()...)
  1250  		return nil
  1251  
  1252  	case stmtBranch:
  1253  		pos := r.pos()
  1254  		op := r.op()
  1255  		sym := r.optLabel()
  1256  		return ir.NewBranchStmt(pos, op, sym)
  1257  
  1258  	case stmtCall:
  1259  		pos := r.pos()
  1260  		op := r.op()
  1261  		call := r.expr()
  1262  		return ir.NewGoDeferStmt(pos, op, call)
  1263  
  1264  	case stmtExpr:
  1265  		return r.expr()
  1266  
  1267  	case stmtFor:
  1268  		return r.forStmt(label)
  1269  
  1270  	case stmtIf:
  1271  		return r.ifStmt()
  1272  
  1273  	case stmtLabel:
  1274  		pos := r.pos()
  1275  		sym := r.label()
  1276  		return ir.NewLabelStmt(pos, sym)
  1277  
  1278  	case stmtReturn:
  1279  		pos := r.pos()
  1280  		results := r.exprList()
  1281  		return ir.NewReturnStmt(pos, results)
  1282  
  1283  	case stmtSelect:
  1284  		return r.selectStmt(label)
  1285  
  1286  	case stmtSend:
  1287  		pos := r.pos()
  1288  		ch := r.expr()
  1289  		value := r.expr()
  1290  		return ir.NewSendStmt(pos, ch, value)
  1291  
  1292  	case stmtSwitch:
  1293  		return r.switchStmt(label)
  1294  
  1295  	case stmtTypeDeclHack:
  1296  		// fake "type _ = int" declaration to prevent inlining in quirks mode.
  1297  		assert(quirksMode())
  1298  
  1299  		name := ir.NewDeclNameAt(src.NoXPos, ir.OTYPE, ir.BlankNode.Sym())
  1300  		name.SetAlias(true)
  1301  		setType(name, types.Types[types.TINT])
  1302  
  1303  		n := ir.NewDecl(src.NoXPos, ir.ODCLTYPE, name)
  1304  		n.SetTypecheck(1)
  1305  		return n
  1306  	}
  1307  }
  1308  
  1309  func (r *reader) assignList() ([]*ir.Name, []ir.Node) {
  1310  	lhs := make([]ir.Node, r.len())
  1311  	var names []*ir.Name
  1312  
  1313  	for i := range lhs {
  1314  		if r.bool() {
  1315  			pos := r.pos()
  1316  			_, sym := r.localIdent()
  1317  			typ := r.typ()
  1318  
  1319  			name := ir.NewNameAt(pos, sym)
  1320  			lhs[i] = name
  1321  			names = append(names, name)
  1322  			setType(name, typ)
  1323  			r.addLocal(name, ir.PAUTO)
  1324  			continue
  1325  		}
  1326  
  1327  		lhs[i] = r.expr()
  1328  	}
  1329  
  1330  	return names, lhs
  1331  }
  1332  
  1333  func (r *reader) blockStmt() []ir.Node {
  1334  	r.sync(syncBlockStmt)
  1335  	r.openScope()
  1336  	stmts := r.stmts()
  1337  	r.closeScope()
  1338  	return stmts
  1339  }
  1340  
  1341  func (r *reader) forStmt(label *types.Sym) ir.Node {
  1342  	r.sync(syncForStmt)
  1343  
  1344  	r.openScope()
  1345  
  1346  	if r.bool() {
  1347  		pos := r.pos()
  1348  
  1349  		// TODO(mdempsky): After quirks mode is gone, swap these
  1350  		// statements so we read LHS before X again.
  1351  		x := r.expr()
  1352  		names, lhs := r.assignList()
  1353  
  1354  		body := r.blockStmt()
  1355  		r.closeAnotherScope()
  1356  
  1357  		rang := ir.NewRangeStmt(pos, nil, nil, x, body)
  1358  		if len(lhs) >= 1 {
  1359  			rang.Key = lhs[0]
  1360  			if len(lhs) >= 2 {
  1361  				rang.Value = lhs[1]
  1362  			}
  1363  		}
  1364  		rang.Def = r.initDefn(rang, names)
  1365  		rang.Label = label
  1366  		return rang
  1367  	}
  1368  
  1369  	pos := r.pos()
  1370  	init := r.stmt()
  1371  	cond := r.expr()
  1372  	post := r.stmt()
  1373  	body := r.blockStmt()
  1374  	r.closeAnotherScope()
  1375  
  1376  	stmt := ir.NewForStmt(pos, init, cond, post, body)
  1377  	stmt.Label = label
  1378  	return stmt
  1379  }
  1380  
  1381  func (r *reader) ifStmt() ir.Node {
  1382  	r.sync(syncIfStmt)
  1383  	r.openScope()
  1384  	pos := r.pos()
  1385  	init := r.stmts()
  1386  	cond := r.expr()
  1387  	then := r.blockStmt()
  1388  	els := r.stmts()
  1389  	n := ir.NewIfStmt(pos, cond, then, els)
  1390  	n.SetInit(init)
  1391  	r.closeAnotherScope()
  1392  	return n
  1393  }
  1394  
  1395  func (r *reader) selectStmt(label *types.Sym) ir.Node {
  1396  	r.sync(syncSelectStmt)
  1397  
  1398  	pos := r.pos()
  1399  	clauses := make([]*ir.CommClause, r.len())
  1400  	for i := range clauses {
  1401  		if i > 0 {
  1402  			r.closeScope()
  1403  		}
  1404  		r.openScope()
  1405  
  1406  		pos := r.pos()
  1407  		comm := r.stmt()
  1408  		body := r.stmts()
  1409  
  1410  		clauses[i] = ir.NewCommStmt(pos, comm, body)
  1411  	}
  1412  	if len(clauses) > 0 {
  1413  		r.closeScope()
  1414  	}
  1415  	n := ir.NewSelectStmt(pos, clauses)
  1416  	n.Label = label
  1417  	return n
  1418  }
  1419  
  1420  func (r *reader) switchStmt(label *types.Sym) ir.Node {
  1421  	r.sync(syncSwitchStmt)
  1422  
  1423  	r.openScope()
  1424  	pos := r.pos()
  1425  	init := r.stmt()
  1426  
  1427  	var tag ir.Node
  1428  	if r.bool() {
  1429  		pos := r.pos()
  1430  		var ident *ir.Ident
  1431  		if r.bool() {
  1432  			pos := r.pos()
  1433  			sym := typecheck.Lookup(r.string())
  1434  			ident = ir.NewIdent(pos, sym)
  1435  		}
  1436  		x := r.expr()
  1437  		tag = ir.NewTypeSwitchGuard(pos, ident, x)
  1438  	} else {
  1439  		tag = r.expr()
  1440  	}
  1441  
  1442  	tswitch, ok := tag.(*ir.TypeSwitchGuard)
  1443  	if ok && tswitch.Tag == nil {
  1444  		tswitch = nil
  1445  	}
  1446  
  1447  	clauses := make([]*ir.CaseClause, r.len())
  1448  	for i := range clauses {
  1449  		if i > 0 {
  1450  			r.closeScope()
  1451  		}
  1452  		r.openScope()
  1453  
  1454  		pos := r.pos()
  1455  		cases := r.exprList()
  1456  
  1457  		clause := ir.NewCaseStmt(pos, cases, nil)
  1458  		if tswitch != nil {
  1459  			pos := r.pos()
  1460  			typ := r.typ()
  1461  
  1462  			name := ir.NewNameAt(pos, tswitch.Tag.Sym())
  1463  			setType(name, typ)
  1464  			r.addLocal(name, ir.PAUTO)
  1465  			clause.Var = name
  1466  			name.Defn = tswitch
  1467  		}
  1468  
  1469  		clause.Body = r.stmts()
  1470  		clauses[i] = clause
  1471  	}
  1472  	if len(clauses) > 0 {
  1473  		r.closeScope()
  1474  	}
  1475  	r.closeScope()
  1476  
  1477  	n := ir.NewSwitchStmt(pos, tag, clauses)
  1478  	n.Label = label
  1479  	if init != nil {
  1480  		n.SetInit([]ir.Node{init})
  1481  	}
  1482  	return n
  1483  }
  1484  
  1485  func (r *reader) label() *types.Sym {
  1486  	r.sync(syncLabel)
  1487  	name := r.string()
  1488  	if r.inlCall != nil {
  1489  		name = fmt.Sprintf("~%s·%d", name, inlgen)
  1490  	}
  1491  	return typecheck.Lookup(name)
  1492  }
  1493  
  1494  func (r *reader) optLabel() *types.Sym {
  1495  	r.sync(syncOptLabel)
  1496  	if r.bool() {
  1497  		return r.label()
  1498  	}
  1499  	return nil
  1500  }
  1501  
  1502  // initDefn marks the given names as declared by defn and populates
  1503  // its Init field with ODCL nodes. It then reports whether any names
  1504  // were so declared, which can be used to initialize defn.Def.
  1505  func (r *reader) initDefn(defn ir.InitNode, names []*ir.Name) bool {
  1506  	if len(names) == 0 {
  1507  		return false
  1508  	}
  1509  
  1510  	init := make([]ir.Node, len(names))
  1511  	for i, name := range names {
  1512  		name.Defn = defn
  1513  		init[i] = ir.NewDecl(name.Pos(), ir.ODCL, name)
  1514  	}
  1515  	defn.SetInit(init)
  1516  	return true
  1517  }
  1518  
  1519  // @@@ Expressions
  1520  
  1521  // expr reads and returns a typechecked expression.
  1522  func (r *reader) expr() (res ir.Node) {
  1523  	defer func() {
  1524  		if res != nil && res.Typecheck() == 0 {
  1525  			base.FatalfAt(res.Pos(), "%v missed typecheck", res)
  1526  		}
  1527  	}()
  1528  
  1529  	switch tag := codeExpr(r.code(syncExpr)); tag {
  1530  	default:
  1531  		panic("unhandled expression")
  1532  
  1533  	case exprNone:
  1534  		return nil
  1535  
  1536  	case exprBlank:
  1537  		// blank only allowed in LHS of assignments
  1538  		// TODO(mdempsky): Handle directly in assignList instead?
  1539  		return typecheck.AssignExpr(ir.BlankNode)
  1540  
  1541  	case exprLocal:
  1542  		return typecheck.Expr(r.useLocal())
  1543  
  1544  	case exprName:
  1545  		// Callee instead of Expr allows builtins
  1546  		// TODO(mdempsky): Handle builtins directly in exprCall, like method calls?
  1547  		return typecheck.Callee(r.obj())
  1548  
  1549  	case exprType:
  1550  		// TODO(mdempsky): ir.TypeNode should probably return a typecheck'd node.
  1551  		n := ir.TypeNode(r.typ())
  1552  		n.SetTypecheck(1)
  1553  		return n
  1554  
  1555  	case exprConst:
  1556  		pos := r.pos()
  1557  		typ := r.typ()
  1558  		val := FixValue(typ, r.value())
  1559  		op := r.op()
  1560  		orig := r.string()
  1561  		return typecheck.Expr(OrigConst(pos, typ, val, op, orig))
  1562  
  1563  	case exprCompLit:
  1564  		return r.compLit()
  1565  
  1566  	case exprFuncLit:
  1567  		return r.funcLit()
  1568  
  1569  	case exprSelector:
  1570  		x := r.expr()
  1571  		pos := r.pos()
  1572  		_, sym := r.selector()
  1573  		n := typecheck.Expr(ir.NewSelectorExpr(pos, ir.OXDOT, x, sym)).(*ir.SelectorExpr)
  1574  		if n.Op() == ir.OMETHVALUE {
  1575  			wrapper := methodValueWrapper{
  1576  				rcvr:   n.X.Type(),
  1577  				method: n.Selection,
  1578  			}
  1579  			if r.importedDef() {
  1580  				haveMethodValueWrappers = append(haveMethodValueWrappers, wrapper)
  1581  			} else {
  1582  				needMethodValueWrappers = append(needMethodValueWrappers, wrapper)
  1583  			}
  1584  		}
  1585  		return n
  1586  
  1587  	case exprIndex:
  1588  		x := r.expr()
  1589  		pos := r.pos()
  1590  		index := r.expr()
  1591  		return typecheck.Expr(ir.NewIndexExpr(pos, x, index))
  1592  
  1593  	case exprSlice:
  1594  		x := r.expr()
  1595  		pos := r.pos()
  1596  		var index [3]ir.Node
  1597  		for i := range index {
  1598  			index[i] = r.expr()
  1599  		}
  1600  		op := ir.OSLICE
  1601  		if index[2] != nil {
  1602  			op = ir.OSLICE3
  1603  		}
  1604  		return typecheck.Expr(ir.NewSliceExpr(pos, op, x, index[0], index[1], index[2]))
  1605  
  1606  	case exprAssert:
  1607  		x := r.expr()
  1608  		pos := r.pos()
  1609  		typ := r.expr().(ir.Ntype)
  1610  		return typecheck.Expr(ir.NewTypeAssertExpr(pos, x, typ))
  1611  
  1612  	case exprUnaryOp:
  1613  		op := r.op()
  1614  		pos := r.pos()
  1615  		x := r.expr()
  1616  
  1617  		switch op {
  1618  		case ir.OADDR:
  1619  			return typecheck.Expr(typecheck.NodAddrAt(pos, x))
  1620  		case ir.ODEREF:
  1621  			return typecheck.Expr(ir.NewStarExpr(pos, x))
  1622  		}
  1623  		return typecheck.Expr(ir.NewUnaryExpr(pos, op, x))
  1624  
  1625  	case exprBinaryOp:
  1626  		op := r.op()
  1627  		x := r.expr()
  1628  		pos := r.pos()
  1629  		y := r.expr()
  1630  
  1631  		switch op {
  1632  		case ir.OANDAND, ir.OOROR:
  1633  			return typecheck.Expr(ir.NewLogicalExpr(pos, op, x, y))
  1634  		}
  1635  		return typecheck.Expr(ir.NewBinaryExpr(pos, op, x, y))
  1636  
  1637  	case exprCall:
  1638  		fun := r.expr()
  1639  		if r.bool() { // method call
  1640  			pos := r.pos()
  1641  			_, sym := r.selector()
  1642  			fun = typecheck.Callee(ir.NewSelectorExpr(pos, ir.OXDOT, fun, sym))
  1643  		}
  1644  		pos := r.pos()
  1645  		args := r.exprs()
  1646  		dots := r.bool()
  1647  		return typecheck.Call(pos, fun, args, dots)
  1648  
  1649  	case exprConvert:
  1650  		typ := r.typ()
  1651  		pos := r.pos()
  1652  		x := r.expr()
  1653  		return typecheck.Expr(ir.NewConvExpr(pos, ir.OCONV, typ, x))
  1654  	}
  1655  }
  1656  
  1657  func (r *reader) compLit() ir.Node {
  1658  	r.sync(syncCompLit)
  1659  	pos := r.pos()
  1660  	typ0 := r.typ()
  1661  
  1662  	typ := typ0
  1663  	if typ.IsPtr() {
  1664  		typ = typ.Elem()
  1665  	}
  1666  	if typ.Kind() == types.TFORW {
  1667  		base.FatalfAt(pos, "unresolved composite literal type: %v", typ)
  1668  	}
  1669  	isStruct := typ.Kind() == types.TSTRUCT
  1670  
  1671  	elems := make([]ir.Node, r.len())
  1672  	for i := range elems {
  1673  		elemp := &elems[i]
  1674  
  1675  		if isStruct {
  1676  			sk := ir.NewStructKeyExpr(r.pos(), typ.Field(r.len()), nil)
  1677  			*elemp, elemp = sk, &sk.Value
  1678  		} else if r.bool() {
  1679  			kv := ir.NewKeyExpr(r.pos(), r.expr(), nil)
  1680  			*elemp, elemp = kv, &kv.Value
  1681  		}
  1682  
  1683  		*elemp = wrapName(r.pos(), r.expr())
  1684  	}
  1685  
  1686  	lit := typecheck.Expr(ir.NewCompLitExpr(pos, ir.OCOMPLIT, ir.TypeNode(typ), elems))
  1687  	if typ0.IsPtr() {
  1688  		lit = typecheck.Expr(typecheck.NodAddrAt(pos, lit))
  1689  		lit.SetType(typ0)
  1690  	}
  1691  	return lit
  1692  }
  1693  
  1694  func wrapName(pos src.XPos, x ir.Node) ir.Node {
  1695  	// These nodes do not carry line numbers.
  1696  	// Introduce a wrapper node to give them the correct line.
  1697  	switch ir.Orig(x).Op() {
  1698  	case ir.OTYPE, ir.OLITERAL:
  1699  		if x.Sym() == nil {
  1700  			break
  1701  		}
  1702  		fallthrough
  1703  	case ir.ONAME, ir.ONONAME, ir.OPACK, ir.ONIL:
  1704  		p := ir.NewParenExpr(pos, x)
  1705  		p.SetImplicit(true)
  1706  		return p
  1707  	}
  1708  	return x
  1709  }
  1710  
  1711  func (r *reader) funcLit() ir.Node {
  1712  	r.sync(syncFuncLit)
  1713  
  1714  	pos := r.pos()
  1715  	typPos := r.pos()
  1716  	xtype2 := r.signature(types.LocalPkg, nil)
  1717  
  1718  	opos := pos
  1719  	if quirksMode() {
  1720  		opos = r.origPos(pos)
  1721  	}
  1722  
  1723  	fn := ir.NewClosureFunc(opos, r.curfn != nil)
  1724  	clo := fn.OClosure
  1725  	ir.NameClosure(clo, r.curfn)
  1726  
  1727  	setType(fn.Nname, xtype2)
  1728  	if quirksMode() {
  1729  		fn.Nname.Ntype = ir.TypeNodeAt(typPos, xtype2)
  1730  	}
  1731  	typecheck.Func(fn)
  1732  	setType(clo, fn.Type())
  1733  
  1734  	fn.ClosureVars = make([]*ir.Name, 0, r.len())
  1735  	for len(fn.ClosureVars) < cap(fn.ClosureVars) {
  1736  		ir.NewClosureVar(r.pos(), fn, r.useLocal())
  1737  	}
  1738  
  1739  	r.addBody(fn)
  1740  
  1741  	// TODO(mdempsky): Remove hard-coding of typecheck.Target.
  1742  	return ir.UseClosure(clo, typecheck.Target)
  1743  }
  1744  
  1745  func (r *reader) exprList() []ir.Node {
  1746  	r.sync(syncExprList)
  1747  	return r.exprs()
  1748  }
  1749  
  1750  func (r *reader) exprs() []ir.Node {
  1751  	r.sync(syncExprs)
  1752  	nodes := make([]ir.Node, r.len())
  1753  	if len(nodes) == 0 {
  1754  		return nil // TODO(mdempsky): Unclear if this matters.
  1755  	}
  1756  	for i := range nodes {
  1757  		nodes[i] = r.expr()
  1758  	}
  1759  	return nodes
  1760  }
  1761  
  1762  func (r *reader) op() ir.Op {
  1763  	r.sync(syncOp)
  1764  	return ir.Op(r.len())
  1765  }
  1766  
  1767  // @@@ Package initialization
  1768  
  1769  func (r *reader) pkgInit(self *types.Pkg, target *ir.Package) {
  1770  	if quirksMode() {
  1771  		for i, n := 0, r.len(); i < n; i++ {
  1772  			// Eagerly register position bases, so their filenames are
  1773  			// assigned stable indices.
  1774  			posBase := r.posBase()
  1775  			_ = base.Ctxt.PosTable.XPos(src.MakePos(posBase, 0, 0))
  1776  		}
  1777  
  1778  		for i, n := 0, r.len(); i < n; i++ {
  1779  			// Eagerly resolve imported objects, so any filenames registered
  1780  			// in the process are assigned stable indices too.
  1781  			_, sym := r.qualifiedIdent()
  1782  			typecheck.Resolve(ir.NewIdent(src.NoXPos, sym))
  1783  			assert(sym.Def != nil)
  1784  		}
  1785  	}
  1786  
  1787  	cgoPragmas := make([][]string, r.len())
  1788  	for i := range cgoPragmas {
  1789  		cgoPragmas[i] = r.strings()
  1790  	}
  1791  	target.CgoPragmas = cgoPragmas
  1792  
  1793  	r.pkgDecls(target)
  1794  
  1795  	r.sync(syncEOF)
  1796  }
  1797  
  1798  func (r *reader) pkgDecls(target *ir.Package) {
  1799  	r.sync(syncDecls)
  1800  	for {
  1801  		switch code := codeDecl(r.code(syncDecl)); code {
  1802  		default:
  1803  			panic(fmt.Sprintf("unhandled decl: %v", code))
  1804  
  1805  		case declEnd:
  1806  			return
  1807  
  1808  		case declFunc:
  1809  			names := r.pkgObjs(target)
  1810  			assert(len(names) == 1)
  1811  			target.Decls = append(target.Decls, names[0].Func)
  1812  
  1813  		case declMethod:
  1814  			typ := r.typ()
  1815  			_, sym := r.selector()
  1816  
  1817  			method := typecheck.Lookdot1(nil, sym, typ, typ.Methods(), 0)
  1818  			target.Decls = append(target.Decls, method.Nname.(*ir.Name).Func)
  1819  
  1820  		case declVar:
  1821  			pos := r.pos()
  1822  			names := r.pkgObjs(target)
  1823  			values := r.exprList()
  1824  
  1825  			if len(names) > 1 && len(values) == 1 {
  1826  				as := ir.NewAssignListStmt(pos, ir.OAS2, nil, values)
  1827  				for _, name := range names {
  1828  					as.Lhs.Append(name)
  1829  					name.Defn = as
  1830  				}
  1831  				target.Decls = append(target.Decls, as)
  1832  			} else {
  1833  				for i, name := range names {
  1834  					as := ir.NewAssignStmt(pos, name, nil)
  1835  					if i < len(values) {
  1836  						as.Y = values[i]
  1837  					}
  1838  					name.Defn = as
  1839  					target.Decls = append(target.Decls, as)
  1840  				}
  1841  			}
  1842  
  1843  			if n := r.len(); n > 0 {
  1844  				assert(len(names) == 1)
  1845  				embeds := make([]ir.Embed, n)
  1846  				for i := range embeds {
  1847  					embeds[i] = ir.Embed{Pos: r.pos(), Patterns: r.strings()}
  1848  				}
  1849  				names[0].Embed = &embeds
  1850  				target.Embeds = append(target.Embeds, names[0])
  1851  			}
  1852  
  1853  		case declOther:
  1854  			r.pkgObjs(target)
  1855  		}
  1856  	}
  1857  }
  1858  
  1859  func (r *reader) pkgObjs(target *ir.Package) []*ir.Name {
  1860  	r.sync(syncDeclNames)
  1861  	nodes := make([]*ir.Name, r.len())
  1862  	for i := range nodes {
  1863  		r.sync(syncDeclName)
  1864  
  1865  		name := r.obj().(*ir.Name)
  1866  		nodes[i] = name
  1867  
  1868  		sym := name.Sym()
  1869  		if sym.IsBlank() {
  1870  			continue
  1871  		}
  1872  
  1873  		switch name.Class {
  1874  		default:
  1875  			base.FatalfAt(name.Pos(), "unexpected class: %v", name.Class)
  1876  
  1877  		case ir.PEXTERN:
  1878  			target.Externs = append(target.Externs, name)
  1879  
  1880  		case ir.PFUNC:
  1881  			assert(name.Type().Recv() == nil)
  1882  
  1883  			// TODO(mdempsky): Cleaner way to recognize init?
  1884  			if strings.HasPrefix(sym.Name, "init.") {
  1885  				target.Inits = append(target.Inits, name.Func)
  1886  			}
  1887  		}
  1888  
  1889  		if types.IsExported(sym.Name) {
  1890  			assert(!sym.OnExportList())
  1891  			target.Exports = append(target.Exports, name)
  1892  			sym.SetOnExportList(true)
  1893  		}
  1894  
  1895  		if base.Flag.AsmHdr != "" {
  1896  			assert(!sym.Asm())
  1897  			target.Asms = append(target.Asms, name)
  1898  			sym.SetAsm(true)
  1899  		}
  1900  	}
  1901  
  1902  	return nodes
  1903  }
  1904  
  1905  // @@@ Inlining
  1906  
  1907  var inlgen = 0
  1908  
  1909  func InlineCall(call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExpr {
  1910  	// TODO(mdempsky): Turn callerfn into an explicit parameter.
  1911  	callerfn := ir.CurFunc
  1912  
  1913  	pri, ok := bodyReader[fn]
  1914  	if !ok {
  1915  		// Assume it's an imported function or something that we don't
  1916  		// have access to in quirks mode.
  1917  		if haveLegacyImports {
  1918  			return nil
  1919  		}
  1920  
  1921  		base.FatalfAt(call.Pos(), "missing function body for call to %v", fn)
  1922  	}
  1923  
  1924  	if fn.Inl.Body == nil {
  1925  		expandInline(fn, pri)
  1926  	}
  1927  
  1928  	r := pri.asReader(relocBody, syncFuncBody)
  1929  
  1930  	// TODO(mdempsky): This still feels clumsy. Can we do better?
  1931  	tmpfn := ir.NewFunc(fn.Pos())
  1932  	tmpfn.Nname = ir.NewNameAt(fn.Nname.Pos(), callerfn.Sym())
  1933  	tmpfn.Closgen = callerfn.Closgen
  1934  	defer func() { callerfn.Closgen = tmpfn.Closgen }()
  1935  
  1936  	setType(tmpfn.Nname, fn.Type())
  1937  	r.curfn = tmpfn
  1938  
  1939  	r.inlCaller = callerfn
  1940  	r.inlCall = call
  1941  	r.inlFunc = fn
  1942  	r.inlTreeIndex = inlIndex
  1943  	r.inlPosBases = make(map[*src.PosBase]*src.PosBase)
  1944  
  1945  	r.closureVars = make([]*ir.Name, len(r.inlFunc.ClosureVars))
  1946  	for i, cv := range r.inlFunc.ClosureVars {
  1947  		r.closureVars[i] = cv.Outer
  1948  	}
  1949  
  1950  	r.funcargs(fn)
  1951  
  1952  	assert(r.bool()) // have body
  1953  	r.delayResults = fn.Inl.CanDelayResults
  1954  
  1955  	r.retlabel = typecheck.AutoLabel(".i")
  1956  	inlgen++
  1957  
  1958  	init := ir.TakeInit(call)
  1959  
  1960  	// For normal function calls, the function callee expression
  1961  	// may contain side effects. Make sure to preserve these,
  1962  	// if necessary (#42703).
  1963  	if call.Op() == ir.OCALLFUNC {
  1964  		inline.CalleeEffects(&init, call.X)
  1965  	}
  1966  
  1967  	var args ir.Nodes
  1968  	if call.Op() == ir.OCALLMETH {
  1969  		base.FatalfAt(call.Pos(), "OCALLMETH missed by typecheck")
  1970  	}
  1971  	args.Append(call.Args...)
  1972  
  1973  	// Create assignment to declare and initialize inlvars.
  1974  	as2 := ir.NewAssignListStmt(call.Pos(), ir.OAS2, r.inlvars, args)
  1975  	as2.Def = true
  1976  	var as2init ir.Nodes
  1977  	for _, name := range r.inlvars {
  1978  		if ir.IsBlank(name) {
  1979  			continue
  1980  		}
  1981  		// TODO(mdempsky): Use inlined position of name.Pos() instead?
  1982  		name := name.(*ir.Name)
  1983  		as2init.Append(ir.NewDecl(call.Pos(), ir.ODCL, name))
  1984  		name.Defn = as2
  1985  	}
  1986  	as2.SetInit(as2init)
  1987  	init.Append(typecheck.Stmt(as2))
  1988  
  1989  	if !r.delayResults {
  1990  		// If not delaying retvars, declare and zero initialize the
  1991  		// result variables now.
  1992  		for _, name := range r.retvars {
  1993  			// TODO(mdempsky): Use inlined position of name.Pos() instead?
  1994  			name := name.(*ir.Name)
  1995  			init.Append(ir.NewDecl(call.Pos(), ir.ODCL, name))
  1996  			ras := ir.NewAssignStmt(call.Pos(), name, nil)
  1997  			init.Append(typecheck.Stmt(ras))
  1998  		}
  1999  	}
  2000  
  2001  	// Add an inline mark just before the inlined body.
  2002  	// This mark is inline in the code so that it's a reasonable spot
  2003  	// to put a breakpoint. Not sure if that's really necessary or not
  2004  	// (in which case it could go at the end of the function instead).
  2005  	// Note issue 28603.
  2006  	init.Append(ir.NewInlineMarkStmt(call.Pos().WithIsStmt(), int64(r.inlTreeIndex)))
  2007  
  2008  	nparams := len(r.curfn.Dcl)
  2009  
  2010  	ir.WithFunc(r.curfn, func() {
  2011  		r.curfn.Body = r.stmts()
  2012  		r.curfn.Endlineno = r.pos()
  2013  
  2014  		deadcode.Func(r.curfn)
  2015  
  2016  		// Replace any "return" statements within the function body.
  2017  		var edit func(ir.Node) ir.Node
  2018  		edit = func(n ir.Node) ir.Node {
  2019  			if ret, ok := n.(*ir.ReturnStmt); ok {
  2020  				n = typecheck.Stmt(r.inlReturn(ret))
  2021  			}
  2022  			ir.EditChildren(n, edit)
  2023  			return n
  2024  		}
  2025  		edit(r.curfn)
  2026  	})
  2027  
  2028  	body := ir.Nodes(r.curfn.Body)
  2029  
  2030  	// Quirk: If deadcode elimination turned a non-empty function into
  2031  	// an empty one, we need to set the position for the empty block
  2032  	// left behind to the inlined position for src.NoXPos, so that
  2033  	// an empty string gets added into the DWARF file name listing at
  2034  	// the appropriate index.
  2035  	if quirksMode() && len(body) == 1 {
  2036  		if block, ok := body[0].(*ir.BlockStmt); ok && len(block.List) == 0 {
  2037  			block.SetPos(r.updatePos(src.NoXPos))
  2038  		}
  2039  	}
  2040  
  2041  	// Quirkish: We need to eagerly prune variables added during
  2042  	// inlining, but removed by deadcode.FuncBody above. Unused
  2043  	// variables will get removed during stack frame layout anyway, but
  2044  	// len(fn.Dcl) ends up influencing things like autotmp naming.
  2045  
  2046  	used := usedLocals(body)
  2047  
  2048  	for i, name := range r.curfn.Dcl {
  2049  		if i < nparams || used.Has(name) {
  2050  			name.Curfn = callerfn
  2051  			callerfn.Dcl = append(callerfn.Dcl, name)
  2052  
  2053  			// Quirkish. TODO(mdempsky): Document why.
  2054  			if name.AutoTemp() {
  2055  				name.SetEsc(ir.EscUnknown)
  2056  
  2057  				if base.Flag.GenDwarfInl != 0 {
  2058  					name.SetInlLocal(true)
  2059  				} else {
  2060  					name.SetPos(r.inlCall.Pos())
  2061  				}
  2062  			}
  2063  		}
  2064  	}
  2065  
  2066  	body.Append(ir.NewLabelStmt(call.Pos(), r.retlabel))
  2067  
  2068  	res := ir.NewInlinedCallExpr(call.Pos(), body, append([]ir.Node(nil), r.retvars...))
  2069  	res.SetInit(init)
  2070  	res.SetType(call.Type())
  2071  	res.SetTypecheck(1)
  2072  
  2073  	// Inlining shouldn't add any functions to todoBodies.
  2074  	assert(len(todoBodies) == 0)
  2075  
  2076  	return res
  2077  }
  2078  
  2079  // inlReturn returns a statement that can substitute for the given
  2080  // return statement when inlining.
  2081  func (r *reader) inlReturn(ret *ir.ReturnStmt) *ir.BlockStmt {
  2082  	pos := r.inlCall.Pos()
  2083  
  2084  	block := ir.TakeInit(ret)
  2085  
  2086  	if results := ret.Results; len(results) != 0 {
  2087  		assert(len(r.retvars) == len(results))
  2088  
  2089  		as2 := ir.NewAssignListStmt(pos, ir.OAS2, append([]ir.Node(nil), r.retvars...), ret.Results)
  2090  
  2091  		if r.delayResults {
  2092  			for _, name := range r.retvars {
  2093  				// TODO(mdempsky): Use inlined position of name.Pos() instead?
  2094  				name := name.(*ir.Name)
  2095  				block.Append(ir.NewDecl(pos, ir.ODCL, name))
  2096  				name.Defn = as2
  2097  			}
  2098  		}
  2099  
  2100  		block.Append(as2)
  2101  	}
  2102  
  2103  	block.Append(ir.NewBranchStmt(pos, ir.OGOTO, r.retlabel))
  2104  	return ir.NewBlockStmt(pos, block)
  2105  }
  2106  
  2107  // expandInline reads in an extra copy of IR to populate
  2108  // fn.Inl.{Dcl,Body}.
  2109  func expandInline(fn *ir.Func, pri pkgReaderIndex) {
  2110  	// TODO(mdempsky): Remove this function. It's currently needed by
  2111  	// dwarfgen/dwarf.go:preInliningDcls, which requires fn.Inl.Dcl to
  2112  	// create abstract function DIEs. But we should be able to provide it
  2113  	// with the same information some other way.
  2114  
  2115  	fndcls := len(fn.Dcl)
  2116  	topdcls := len(typecheck.Target.Decls)
  2117  
  2118  	tmpfn := ir.NewFunc(fn.Pos())
  2119  	tmpfn.Nname = ir.NewNameAt(fn.Nname.Pos(), fn.Sym())
  2120  	tmpfn.ClosureVars = fn.ClosureVars
  2121  
  2122  	{
  2123  		r := pri.asReader(relocBody, syncFuncBody)
  2124  		setType(tmpfn.Nname, fn.Type())
  2125  
  2126  		// Don't change parameter's Sym/Nname fields.
  2127  		r.funarghack = true
  2128  
  2129  		r.funcBody(tmpfn)
  2130  
  2131  		ir.WithFunc(tmpfn, func() {
  2132  			deadcode.Func(tmpfn)
  2133  		})
  2134  	}
  2135  
  2136  	used := usedLocals(tmpfn.Body)
  2137  
  2138  	for _, name := range tmpfn.Dcl {
  2139  		if name.Class != ir.PAUTO || used.Has(name) {
  2140  			name.Curfn = fn
  2141  			fn.Inl.Dcl = append(fn.Inl.Dcl, name)
  2142  		}
  2143  	}
  2144  	fn.Inl.Body = tmpfn.Body
  2145  
  2146  	// Double check that we didn't change fn.Dcl by accident.
  2147  	assert(fndcls == len(fn.Dcl))
  2148  
  2149  	// typecheck.Stmts may have added function literals to
  2150  	// typecheck.Target.Decls. Remove them again so we don't risk trying
  2151  	// to compile them multiple times.
  2152  	typecheck.Target.Decls = typecheck.Target.Decls[:topdcls]
  2153  }
  2154  
  2155  // usedLocals returns a set of local variables that are used within body.
  2156  func usedLocals(body []ir.Node) ir.NameSet {
  2157  	var used ir.NameSet
  2158  	ir.VisitList(body, func(n ir.Node) {
  2159  		if n, ok := n.(*ir.Name); ok && n.Op() == ir.ONAME && n.Class == ir.PAUTO {
  2160  			used.Add(n)
  2161  		}
  2162  	})
  2163  	return used
  2164  }
  2165  
  2166  // @@@ Method wrappers
  2167  
  2168  // needWrapperTypes lists types for which we may need to generate
  2169  // method wrappers.
  2170  var needWrapperTypes []*types.Type
  2171  
  2172  // haveWrapperTypes lists types for which we know we already have
  2173  // method wrappers, because we found the type in an imported package.
  2174  var haveWrapperTypes []*types.Type
  2175  
  2176  // needMethodValueWrappers lists methods for which we may need to
  2177  // generate method value wrappers.
  2178  var needMethodValueWrappers []methodValueWrapper
  2179  
  2180  // haveMethodValueWrappers lists methods for which we know we already
  2181  // have method value wrappers, because we found it in an imported
  2182  // package.
  2183  var haveMethodValueWrappers []methodValueWrapper
  2184  
  2185  type methodValueWrapper struct {
  2186  	rcvr   *types.Type
  2187  	method *types.Field
  2188  }
  2189  
  2190  func (r *reader) needWrapper(typ *types.Type) {
  2191  	if typ.IsPtr() {
  2192  		return
  2193  	}
  2194  
  2195  	// If a type was found in an imported package, then we can assume
  2196  	// that package (or one of its transitive dependencies) already
  2197  	// generated method wrappers for it.
  2198  	if r.importedDef() {
  2199  		haveWrapperTypes = append(haveWrapperTypes, typ)
  2200  	} else {
  2201  		needWrapperTypes = append(needWrapperTypes, typ)
  2202  	}
  2203  }
  2204  
  2205  func (r *reader) importedDef() bool {
  2206  	// If a type was found in an imported package, then we can assume
  2207  	// that package (or one of its transitive dependencies) already
  2208  	// generated method wrappers for it.
  2209  	//
  2210  	// Exception: If we're instantiating an imported generic type or
  2211  	// function, we might be instantiating it with type arguments not
  2212  	// previously seen before.
  2213  	//
  2214  	// TODO(mdempsky): Distinguish when a generic function or type was
  2215  	// instantiated in an imported package so that we can add types to
  2216  	// haveWrapperTypes instead.
  2217  	return r.p != localPkgReader && !r.hasTypeParams()
  2218  }
  2219  
  2220  func MakeWrappers(target *ir.Package) {
  2221  	// Only unified IR in non-quirks mode emits its own wrappers.
  2222  	if base.Debug.Unified == 0 || quirksMode() {
  2223  		return
  2224  	}
  2225  
  2226  	// always generate a wrapper for error.Error (#29304)
  2227  	needWrapperTypes = append(needWrapperTypes, types.ErrorType)
  2228  
  2229  	seen := make(map[string]*types.Type)
  2230  
  2231  	for _, typ := range haveWrapperTypes {
  2232  		wrapType(typ, target, seen, false)
  2233  	}
  2234  	haveWrapperTypes = nil
  2235  
  2236  	for _, typ := range needWrapperTypes {
  2237  		wrapType(typ, target, seen, true)
  2238  	}
  2239  	needWrapperTypes = nil
  2240  
  2241  	for _, wrapper := range haveMethodValueWrappers {
  2242  		wrapMethodValue(wrapper.rcvr, wrapper.method, target, false)
  2243  	}
  2244  	haveMethodValueWrappers = nil
  2245  
  2246  	for _, wrapper := range needMethodValueWrappers {
  2247  		wrapMethodValue(wrapper.rcvr, wrapper.method, target, true)
  2248  	}
  2249  	needMethodValueWrappers = nil
  2250  }
  2251  
  2252  func wrapType(typ *types.Type, target *ir.Package, seen map[string]*types.Type, needed bool) {
  2253  	key := typ.LinkString()
  2254  	if prev := seen[key]; prev != nil {
  2255  		if !types.Identical(typ, prev) {
  2256  			base.Fatalf("collision: types %v and %v have link string %q", typ, prev, key)
  2257  		}
  2258  		return
  2259  	}
  2260  	seen[key] = typ
  2261  
  2262  	if !needed {
  2263  		// Only called to add to 'seen'.
  2264  		return
  2265  	}
  2266  
  2267  	if !typ.IsInterface() {
  2268  		typecheck.CalcMethods(typ)
  2269  	}
  2270  	for _, meth := range typ.AllMethods().Slice() {
  2271  		if meth.Sym.IsBlank() || !meth.IsMethod() {
  2272  			base.FatalfAt(meth.Pos, "invalid method: %v", meth)
  2273  		}
  2274  
  2275  		methodWrapper(0, typ, meth, target)
  2276  
  2277  		// For non-interface types, we also want *T wrappers.
  2278  		if !typ.IsInterface() {
  2279  			methodWrapper(1, typ, meth, target)
  2280  
  2281  			// For not-in-heap types, *T is a scalar, not pointer shaped,
  2282  			// so the interface wrappers use **T.
  2283  			if typ.NotInHeap() {
  2284  				methodWrapper(2, typ, meth, target)
  2285  			}
  2286  		}
  2287  	}
  2288  }
  2289  
  2290  func methodWrapper(derefs int, tbase *types.Type, method *types.Field, target *ir.Package) {
  2291  	wrapper := tbase
  2292  	for i := 0; i < derefs; i++ {
  2293  		wrapper = types.NewPtr(wrapper)
  2294  	}
  2295  
  2296  	sym := ir.MethodSym(wrapper, method.Sym)
  2297  	base.Assertf(!sym.Siggen(), "already generated wrapper %v", sym)
  2298  	sym.SetSiggen(true)
  2299  
  2300  	wrappee := method.Type.Recv().Type
  2301  	if types.Identical(wrapper, wrappee) ||
  2302  		!types.IsMethodApplicable(wrapper, method) ||
  2303  		!reflectdata.NeedEmit(tbase) {
  2304  		return
  2305  	}
  2306  
  2307  	// TODO(mdempsky): Use method.Pos instead?
  2308  	pos := base.AutogeneratedPos
  2309  
  2310  	fn := newWrapperFunc(pos, sym, wrapper, method)
  2311  
  2312  	var recv ir.Node = fn.Nname.Type().Recv().Nname.(*ir.Name)
  2313  
  2314  	// For simple *T wrappers around T methods, panicwrap produces a
  2315  	// nicer panic message.
  2316  	if wrapper.IsPtr() && types.Identical(wrapper.Elem(), wrappee) {
  2317  		cond := ir.NewBinaryExpr(pos, ir.OEQ, recv, types.BuiltinPkg.Lookup("nil").Def.(ir.Node))
  2318  		then := []ir.Node{ir.NewCallExpr(pos, ir.OCALL, typecheck.LookupRuntime("panicwrap"), nil)}
  2319  		fn.Body.Append(ir.NewIfStmt(pos, cond, then, nil))
  2320  	}
  2321  
  2322  	// typecheck will add one implicit deref, if necessary,
  2323  	// but not-in-heap types require more for their **T wrappers.
  2324  	for i := 1; i < derefs; i++ {
  2325  		recv = Implicit(ir.NewStarExpr(pos, recv))
  2326  	}
  2327  
  2328  	addTailCall(pos, fn, recv, method)
  2329  
  2330  	finishWrapperFunc(fn, target)
  2331  }
  2332  
  2333  func wrapMethodValue(recvType *types.Type, method *types.Field, target *ir.Package, needed bool) {
  2334  	sym := ir.MethodSymSuffix(recvType, method.Sym, "-fm")
  2335  	if sym.Uniq() {
  2336  		return
  2337  	}
  2338  	sym.SetUniq(true)
  2339  
  2340  	// TODO(mdempsky): Use method.Pos instead?
  2341  	pos := base.AutogeneratedPos
  2342  
  2343  	fn := newWrapperFunc(pos, sym, nil, method)
  2344  	sym.Def = fn.Nname
  2345  
  2346  	// Declare and initialize variable holding receiver.
  2347  	recv := ir.NewHiddenParam(pos, fn, typecheck.Lookup(".this"), recvType)
  2348  
  2349  	if !needed {
  2350  		typecheck.Func(fn)
  2351  		return
  2352  	}
  2353  
  2354  	addTailCall(pos, fn, recv, method)
  2355  
  2356  	finishWrapperFunc(fn, target)
  2357  }
  2358  
  2359  func newWrapperFunc(pos src.XPos, sym *types.Sym, wrapper *types.Type, method *types.Field) *ir.Func {
  2360  	fn := ir.NewFunc(pos)
  2361  	fn.SetDupok(true) // TODO(mdempsky): Leave unset for local, non-generic wrappers?
  2362  
  2363  	name := ir.NewNameAt(pos, sym)
  2364  	ir.MarkFunc(name)
  2365  	name.Func = fn
  2366  	name.Defn = fn
  2367  	fn.Nname = name
  2368  
  2369  	sig := newWrapperType(wrapper, method)
  2370  	setType(name, sig)
  2371  
  2372  	// TODO(mdempsky): De-duplicate with similar logic in funcargs.
  2373  	defParams := func(class ir.Class, params *types.Type) {
  2374  		for _, param := range params.FieldSlice() {
  2375  			name := ir.NewNameAt(param.Pos, param.Sym)
  2376  			name.Class = class
  2377  			setType(name, param.Type)
  2378  
  2379  			name.Curfn = fn
  2380  			fn.Dcl = append(fn.Dcl, name)
  2381  
  2382  			param.Nname = name
  2383  		}
  2384  	}
  2385  
  2386  	defParams(ir.PPARAM, sig.Recvs())
  2387  	defParams(ir.PPARAM, sig.Params())
  2388  	defParams(ir.PPARAMOUT, sig.Results())
  2389  
  2390  	return fn
  2391  }
  2392  
  2393  func finishWrapperFunc(fn *ir.Func, target *ir.Package) {
  2394  	typecheck.Func(fn)
  2395  
  2396  	ir.WithFunc(fn, func() {
  2397  		typecheck.Stmts(fn.Body)
  2398  	})
  2399  
  2400  	// We generate wrappers after the global inlining pass,
  2401  	// so we're responsible for applying inlining ourselves here.
  2402  	inline.InlineCalls(fn)
  2403  
  2404  	target.Decls = append(target.Decls, fn)
  2405  }
  2406  
  2407  // newWrapperType returns a copy of the given signature type, but with
  2408  // the receiver parameter type substituted with recvType.
  2409  // If recvType is nil, newWrapperType returns a signature
  2410  // without a receiver parameter.
  2411  func newWrapperType(recvType *types.Type, method *types.Field) *types.Type {
  2412  	clone := func(params []*types.Field) []*types.Field {
  2413  		res := make([]*types.Field, len(params))
  2414  		for i, param := range params {
  2415  			sym := param.Sym
  2416  			if sym == nil || sym.Name == "_" {
  2417  				sym = typecheck.LookupNum(".anon", i)
  2418  			}
  2419  			res[i] = types.NewField(param.Pos, sym, param.Type)
  2420  			res[i].SetIsDDD(param.IsDDD())
  2421  		}
  2422  		return res
  2423  	}
  2424  
  2425  	sig := method.Type
  2426  
  2427  	var recv *types.Field
  2428  	if recvType != nil {
  2429  		recv = types.NewField(sig.Recv().Pos, typecheck.Lookup(".this"), recvType)
  2430  	}
  2431  	params := clone(sig.Params().FieldSlice())
  2432  	results := clone(sig.Results().FieldSlice())
  2433  
  2434  	return types.NewSignature(types.NoPkg, recv, nil, params, results)
  2435  }
  2436  
  2437  func addTailCall(pos src.XPos, fn *ir.Func, recv ir.Node, method *types.Field) {
  2438  	sig := fn.Nname.Type()
  2439  	args := make([]ir.Node, sig.NumParams())
  2440  	for i, param := range sig.Params().FieldSlice() {
  2441  		args[i] = param.Nname.(*ir.Name)
  2442  	}
  2443  
  2444  	// TODO(mdempsky): Support creating OTAILCALL, when possible. See reflectdata.methodWrapper.
  2445  	// Not urgent though, because tail calls are currently incompatible with regabi anyway.
  2446  
  2447  	fn.SetWrapper(true) // TODO(mdempsky): Leave unset for tail calls?
  2448  
  2449  	dot := ir.NewSelectorExpr(pos, ir.OXDOT, recv, method.Sym)
  2450  	call := typecheck.Call(pos, dot, args, method.Type.IsVariadic()).(*ir.CallExpr)
  2451  
  2452  	if method.Type.NumResults() == 0 {
  2453  		fn.Body.Append(call)
  2454  		return
  2455  	}
  2456  
  2457  	ret := ir.NewReturnStmt(pos, nil)
  2458  	ret.Results = []ir.Node{call}
  2459  	fn.Body.Append(ret)
  2460  }
  2461  

View as plain text