aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/noder/reader.go
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@google.com>2023-09-13 19:26:32 -0700
committerGopher Robot <gobot@golang.org>2023-09-14 13:15:50 +0000
commitd18e9407b078001a1ed07c783bb9b624b19f6609 (patch)
tree26d38c28c1fd5a5566681d8ac8c8a1dec2e7b51b /src/cmd/compile/internal/noder/reader.go
parentde4ead8102c3ba5dc9475ed3e117b2c50220b4df (diff)
downloadgo-d18e9407b078001a1ed07c783bb9b624b19f6609.tar.xz
cmd/compile/internal/ir: add Func.DeclareParams
There's several copies of this function. We only need one. While here, normalize so that we always declare parameters, and always use the names ~pNN for params and ~rNN for results. Change-Id: I49e90d3fd1820f3c07936227ed5cfefd75d49a1c Reviewed-on: https://go-review.googlesource.com/c/go/+/528415 Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> Auto-Submit: Matthew Dempsky <mdempsky@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Than McIntosh <thanm@google.com>
Diffstat (limited to 'src/cmd/compile/internal/noder/reader.go')
-rw-r--r--src/cmd/compile/internal/noder/reader.go266
1 files changed, 69 insertions, 197 deletions
diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go
index 760170ddfc..d4ccfb087b 100644
--- a/src/cmd/compile/internal/noder/reader.go
+++ b/src/cmd/compile/internal/noder/reader.go
@@ -107,6 +107,11 @@ type reader struct {
locals []*ir.Name
closureVars []*ir.Name
+ // funarghack is used during inlining to suppress setting
+ // Field.Nname to the inlined copies of the parameters. This is
+ // necessary because we reuse the same types.Type as the original
+ // function, and most of the compiler still relies on field.Nname to
+ // find parameters/results.
funarghack bool
// methodSym is the name of method's name, if reading a method.
@@ -145,14 +150,6 @@ type reader struct {
// Label to return to.
retlabel *types.Sym
-
- // inlvars is the list of variables that the inlinee's arguments are
- // assigned to, one for each receiver and normal parameter, in order.
- inlvars ir.Nodes
-
- // retvars is the list of variables that the inlinee's results are
- // assigned to, one for each result parameter, in order.
- retvars ir.Nodes
}
// A readerDict represents an instantiated "compile-time dictionary,"
@@ -1237,7 +1234,7 @@ func (r *reader) funcBody(fn *ir.Func) {
}
ir.WithFunc(fn, func() {
- r.funcargs(fn)
+ r.declareParams()
if r.syntheticBody(fn.Pos()) {
return
@@ -1294,7 +1291,7 @@ func (r *reader) callShaped(pos src.XPos) {
shapedFn = shapedMethodExpr(pos, shapedObj, r.methodSym)
}
- recvs, params := r.syntheticArgs(pos)
+ params := r.syntheticArgs()
// Construct the arguments list: receiver (if any), then runtime
// dictionary, and finally normal parameters.
@@ -1306,7 +1303,10 @@ func (r *reader) callShaped(pos src.XPos) {
// putting the dictionary parameter after that is the least invasive
// solution at the moment.
var args ir.Nodes
- args.Append(recvs...)
+ if r.methodSym != nil {
+ args.Append(params[0])
+ params = params[1:]
+ }
args.Append(typecheck.Expr(ir.NewAddrExpr(pos, r.p.dictNameOf(r.dict))))
args.Append(params...)
@@ -1315,44 +1315,9 @@ func (r *reader) callShaped(pos src.XPos) {
// syntheticArgs returns the recvs and params arguments passed to the
// current function.
-func (r *reader) syntheticArgs(pos src.XPos) (recvs, params ir.Nodes) {
+func (r *reader) syntheticArgs() ir.Nodes {
sig := r.curfn.Nname.Type()
-
- inlVarIdx := 0
- addParams := func(out *ir.Nodes, params []*types.Field) {
- for _, param := range params {
- var arg ir.Node
- if param.Nname != nil {
- name := param.Nname.(*ir.Name)
- if !ir.IsBlank(name) {
- if r.inlCall != nil {
- // During inlining, we want the respective inlvar where we
- // assigned the callee's arguments.
- arg = r.inlvars[inlVarIdx]
- } else {
- // Otherwise, we can use the parameter itself directly.
- base.AssertfAt(name.Curfn == r.curfn, name.Pos(), "%v has curfn %v, but want %v", name, name.Curfn, r.curfn)
- arg = name
- }
- }
- }
-
- // For anonymous and blank parameters, we don't have an *ir.Name
- // to use as the argument. However, since we know the shaped
- // function won't use the value either, we can just pass the
- // zero value.
- if arg == nil {
- arg = ir.NewZero(pos, param.Type)
- }
-
- out.Append(arg)
- inlVarIdx++
- }
- }
-
- addParams(&recvs, sig.Recvs())
- addParams(&params, sig.Params())
- return
+ return ir.ToNodes(r.curfn.Dcl[:sig.NumRecvs()+sig.NumParams()])
}
// syntheticTailCall emits a tail call to fn, passing the given
@@ -1489,105 +1454,32 @@ func (dict *readerDict) varType() *types.Type {
return types.NewArray(types.Types[types.TUINTPTR], dict.numWords())
}
-func (r *reader) funcargs(fn *ir.Func) {
- sig := fn.Nname.Type()
-
- if recv := sig.Recv(); recv != nil {
- r.funcarg(recv, recv.Sym, ir.PPARAM)
- }
- for _, param := range sig.Params() {
- r.funcarg(param, param.Sym, ir.PPARAM)
- }
-
- for i, param := range sig.Results() {
- sym := param.Sym
+func (r *reader) declareParams() {
+ r.curfn.DeclareParams(!r.funarghack)
- if sym == nil || sym.IsBlank() {
- prefix := "~r"
- if r.inlCall != nil {
- prefix = "~R"
- } else if sym != nil {
- prefix = "~b"
- }
- sym = typecheck.LookupNum(prefix, i)
+ for _, name := range r.curfn.Dcl {
+ if name.Sym().Name == dictParamName {
+ r.dictParam = name
+ continue
}
- r.funcarg(param, sym, ir.PPARAMOUT)
+ r.addLocal(name)
}
}
-func (r *reader) funcarg(param *types.Field, sym *types.Sym, ctxt ir.Class) {
- if sym == nil {
- assert(ctxt == ir.PPARAM)
- if r.inlCall != nil {
- r.inlvars.Append(ir.BlankNode)
- }
- return
- }
-
- name := r.addLocal(r.inlPos(param.Pos), sym, ctxt, param.Type)
-
- if r.inlCall == nil {
- if !r.funarghack {
- param.Nname = name
- }
- } else {
- if ctxt == ir.PPARAMOUT {
- r.retvars.Append(name)
- } else {
- r.inlvars.Append(name)
- }
- }
-}
-
-func (r *reader) addLocal(pos src.XPos, sym *types.Sym, ctxt ir.Class, typ *types.Type) *ir.Name {
- assert(ctxt == ir.PAUTO || ctxt == ir.PPARAM || ctxt == ir.PPARAMOUT)
-
- name := ir.NewNameAt(pos, sym, typ)
-
- if name.Sym().Name == dictParamName {
- r.dictParam = name
- } else {
- if r.synthetic == nil {
- r.Sync(pkgbits.SyncAddLocal)
- if r.p.SyncMarkers() {
- want := r.Int()
- if have := len(r.locals); have != want {
- base.FatalfAt(name.Pos(), "locals table has desynced")
- }
+func (r *reader) addLocal(name *ir.Name) {
+ if r.synthetic == nil {
+ r.Sync(pkgbits.SyncAddLocal)
+ if r.p.SyncMarkers() {
+ want := r.Int()
+ if have := len(r.locals); have != want {
+ base.FatalfAt(name.Pos(), "locals table has desynced")
}
- r.varDictIndex(name)
}
-
- r.locals = append(r.locals, name)
- }
-
- name.SetUsed(true)
-
- // TODO(mdempsky): Move earlier.
- if ir.IsBlank(name) {
- return name
+ r.varDictIndex(name)
}
- if r.inlCall != nil {
- if ctxt == ir.PAUTO {
- name.SetInlLocal(true)
- } else {
- name.SetInlFormal(true)
- ctxt = ir.PAUTO
- }
- }
-
- name.Class = ctxt
- name.Curfn = r.curfn
-
- r.curfn.Dcl = append(r.curfn.Dcl, name)
-
- if ctxt == ir.PAUTO {
- name.SetFrameOffset(0)
- }
-
- return name
+ r.locals = append(r.locals, name)
}
func (r *reader) useLocal() *ir.Name {
@@ -1836,7 +1728,8 @@ func (r *reader) assign() (ir.Node, bool) {
_, sym := r.localIdent()
typ := r.typ()
- name := r.addLocal(pos, sym, ir.PAUTO, typ)
+ name := r.curfn.NewLocal(pos, sym, typ)
+ r.addLocal(name)
return name, true
case assignExpr:
@@ -2076,10 +1969,8 @@ func (r *reader) switchStmt(label *types.Sym) ir.Node {
clause.RTypes = rtypes
if ident != nil {
- pos := r.pos()
- typ := r.typ()
-
- name := r.addLocal(pos, ident.Sym(), ir.PAUTO, typ)
+ name := r.curfn.NewLocal(r.pos(), ident.Sym(), r.typ())
+ r.addLocal(name)
clause.Var = name
name.Defn = tag
}
@@ -2651,14 +2542,11 @@ func (r *reader) curry(origPos src.XPos, ifaceHack bool, fun ir.Node, arg0, arg1
typ := types.NewSignature(nil, params, results)
addBody := func(pos src.XPos, r *reader, captured []ir.Node) {
- recvs, params := r.syntheticArgs(pos)
- assert(len(recvs) == 0)
-
fun := captured[0]
var args ir.Nodes
args.Append(captured[1:]...)
- args.Append(params...)
+ args.Append(r.syntheticArgs()...)
r.syntheticTailCall(pos, fun, args)
}
@@ -2689,10 +2577,8 @@ func (r *reader) methodExprWrap(origPos src.XPos, recv *types.Type, implicits []
typ := types.NewSignature(nil, params, results)
addBody := func(pos src.XPos, r *reader, captured []ir.Node) {
- recvs, args := r.syntheticArgs(pos)
- assert(len(recvs) == 0)
-
fn := captured[0]
+ args := r.syntheticArgs()
// Rewrite first argument based on implicits/deref/addr.
{
@@ -2805,17 +2691,13 @@ func syntheticSig(sig *types.Type) (params, results []*types.Field) {
clone := func(params []*types.Field) []*types.Field {
res := make([]*types.Field, len(params))
for i, param := range params {
- sym := param.Sym
- if sym == nil || sym.Name == "_" {
- sym = typecheck.LookupNum(".anon", i)
- }
// TODO(mdempsky): It would be nice to preserve the original
// parameter positions here instead, but at least
// typecheck.NewMethodType replaces them with base.Pos, making
// them useless. Worse, the positions copied from base.Pos may
// have inlining contexts, which we definitely don't want here
// (e.g., #54625).
- res[i] = types.NewField(base.AutogeneratedPos, sym, param.Type)
+ res[i] = types.NewField(base.AutogeneratedPos, param.Sym, param.Type)
res[i].SetIsDDD(param.IsDDD())
}
return res
@@ -3492,6 +3374,7 @@ func unifiedInlineCall(callerfn *ir.Func, call *ir.CallExpr, fn *ir.Func, inlInd
r.inlFunc = fn
r.inlTreeIndex = inlIndex
r.inlPosBases = make(map[*src.PosBase]*src.PosBase)
+ r.funarghack = true
r.closureVars = make([]*ir.Name, len(r.inlFunc.ClosureVars))
for i, cv := range r.inlFunc.ClosureVars {
@@ -3506,7 +3389,17 @@ func unifiedInlineCall(callerfn *ir.Func, call *ir.CallExpr, fn *ir.Func, inlInd
r.dictParam = r.closureVars[len(r.closureVars)-1] // dictParam is last; see reader.funcLit
}
- r.funcargs(fn)
+ r.declareParams()
+
+ var inlvars, retvars []*ir.Name
+ {
+ sig := r.curfn.Type()
+ endParams := sig.NumRecvs() + sig.NumParams()
+ endResults := endParams + sig.NumResults()
+
+ inlvars = r.curfn.Dcl[:endParams]
+ retvars = r.curfn.Dcl[endParams:endResults]
+ }
r.delayResults = fn.Inl.CanDelayResults
@@ -3529,15 +3422,14 @@ func unifiedInlineCall(callerfn *ir.Func, call *ir.CallExpr, fn *ir.Func, inlInd
args.Append(call.Args...)
// Create assignment to declare and initialize inlvars.
- as2 := ir.NewAssignListStmt(call.Pos(), ir.OAS2, r.inlvars, args)
+ as2 := ir.NewAssignListStmt(call.Pos(), ir.OAS2, ir.ToNodes(inlvars), args)
as2.Def = true
var as2init ir.Nodes
- for _, name := range r.inlvars {
+ for _, name := range inlvars {
if ir.IsBlank(name) {
continue
}
// TODO(mdempsky): Use inlined position of name.Pos() instead?
- name := name.(*ir.Name)
as2init.Append(ir.NewDecl(call.Pos(), ir.ODCL, name))
name.Defn = as2
}
@@ -3547,9 +3439,8 @@ func unifiedInlineCall(callerfn *ir.Func, call *ir.CallExpr, fn *ir.Func, inlInd
if !r.delayResults {
// If not delaying retvars, declare and zero initialize the
// result variables now.
- for _, name := range r.retvars {
+ for _, name := range retvars {
// TODO(mdempsky): Use inlined position of name.Pos() instead?
- name := name.(*ir.Name)
init.Append(ir.NewDecl(call.Pos(), ir.ODCL, name))
ras := ir.NewAssignStmt(call.Pos(), name, nil)
init.Append(typecheck.Stmt(ras))
@@ -3582,7 +3473,7 @@ func unifiedInlineCall(callerfn *ir.Func, call *ir.CallExpr, fn *ir.Func, inlInd
var edit func(ir.Node) ir.Node
edit = func(n ir.Node) ir.Node {
if ret, ok := n.(*ir.ReturnStmt); ok {
- n = typecheck.Stmt(r.inlReturn(ret))
+ n = typecheck.Stmt(r.inlReturn(ret, retvars))
}
ir.EditChildren(n, edit)
return n
@@ -3595,17 +3486,20 @@ func unifiedInlineCall(callerfn *ir.Func, call *ir.CallExpr, fn *ir.Func, inlInd
// Reparent any declarations into the caller function.
for _, name := range r.curfn.Dcl {
name.Curfn = callerfn
- callerfn.Dcl = append(callerfn.Dcl, name)
- if name.AutoTemp() {
- name.SetEsc(ir.EscUnknown)
+ if name.Class != ir.PAUTO {
+ name.SetPos(r.inlPos(name.Pos()))
+ name.SetInlFormal(true)
+ name.Class = ir.PAUTO
+ } else {
name.SetInlLocal(true)
}
}
+ callerfn.Dcl = append(callerfn.Dcl, r.curfn.Dcl...)
body.Append(ir.NewLabelStmt(call.Pos(), r.retlabel))
- res := ir.NewInlinedCallExpr(call.Pos(), body, append([]ir.Node(nil), r.retvars...))
+ res := ir.NewInlinedCallExpr(call.Pos(), body, ir.ToNodes(retvars))
res.SetInit(init)
res.SetType(call.Type())
res.SetTypecheck(1)
@@ -3618,20 +3512,19 @@ func unifiedInlineCall(callerfn *ir.Func, call *ir.CallExpr, fn *ir.Func, inlInd
// inlReturn returns a statement that can substitute for the given
// return statement when inlining.
-func (r *reader) inlReturn(ret *ir.ReturnStmt) *ir.BlockStmt {
+func (r *reader) inlReturn(ret *ir.ReturnStmt, retvars []*ir.Name) *ir.BlockStmt {
pos := r.inlCall.Pos()
block := ir.TakeInit(ret)
if results := ret.Results; len(results) != 0 {
- assert(len(r.retvars) == len(results))
+ assert(len(retvars) == len(results))
- as2 := ir.NewAssignListStmt(pos, ir.OAS2, append([]ir.Node(nil), r.retvars...), ret.Results)
+ as2 := ir.NewAssignListStmt(pos, ir.OAS2, ir.ToNodes(retvars), ret.Results)
if r.delayResults {
- for _, name := range r.retvars {
+ for _, name := range retvars {
// TODO(mdempsky): Use inlined position of name.Pos() instead?
- name := name.(*ir.Name)
block.Append(ir.NewDecl(pos, ir.ODCL, name))
name.Defn = as2
}
@@ -3667,18 +3560,11 @@ func expandInline(fn *ir.Func, pri pkgReaderIndex) {
r.funcBody(tmpfn)
}
- used := usedLocals(tmpfn.Body)
-
+ // Move tmpfn's params to fn.Inl.Dcl, and reparent under fn.
for _, name := range tmpfn.Dcl {
- if name.Class != ir.PAUTO || used.Has(name) {
- name.Curfn = fn
- fn.Inl.Dcl = append(fn.Inl.Dcl, name)
- } else {
- // TODO(mdempsky): Simplify code after confident that this never
- // happens anymore.
- base.FatalfAt(name.Pos(), "unused auto: %v", name)
- }
+ name.Curfn = fn
}
+ fn.Inl.Dcl = tmpfn.Dcl
fn.Inl.HaveDcl = true
// Double check that we didn't change fn.Dcl by accident.
@@ -3895,19 +3781,9 @@ func newWrapperFunc(pos src.XPos, sym *types.Sym, wrapper *types.Type, method *t
sig := newWrapperType(wrapper, method)
fn := ir.NewFunc(pos, pos, sym, sig)
+ fn.DeclareParams(true)
fn.SetDupok(true) // TODO(mdempsky): Leave unset for local, non-generic wrappers?
- // TODO(mdempsky): De-duplicate with similar logic in funcargs.
- defParams := func(class ir.Class, params []*types.Field) {
- for _, param := range params {
- param.Nname = fn.NewLocal(param.Pos, param.Sym, class, param.Type)
- }
- }
-
- defParams(ir.PPARAM, sig.Recvs())
- defParams(ir.PPARAM, sig.Params())
- defParams(ir.PPARAMOUT, sig.Results())
-
return fn
}
@@ -3946,11 +3822,7 @@ func newWrapperType(recvType *types.Type, method *types.Field) *types.Type {
clone := func(params []*types.Field) []*types.Field {
res := make([]*types.Field, len(params))
for i, param := range params {
- sym := param.Sym
- if sym == nil || sym.Name == "_" {
- sym = typecheck.LookupNum(".anon", i)
- }
- res[i] = types.NewField(param.Pos, sym, param.Type)
+ res[i] = types.NewField(param.Pos, param.Sym, param.Type)
res[i].SetIsDDD(param.IsDDD())
}
return res
@@ -3960,7 +3832,7 @@ func newWrapperType(recvType *types.Type, method *types.Field) *types.Type {
var recv *types.Field
if recvType != nil {
- recv = types.NewField(sig.Recv().Pos, typecheck.Lookup(".this"), recvType)
+ recv = types.NewField(sig.Recv().Pos, sig.Recv().Sym, recvType)
}
params := clone(sig.Params())
results := clone(sig.Results())