diff options
| author | Matthew Dempsky <mdempsky@google.com> | 2023-09-13 19:26:32 -0700 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2023-09-14 13:15:50 +0000 |
| commit | d18e9407b078001a1ed07c783bb9b624b19f6609 (patch) | |
| tree | 26d38c28c1fd5a5566681d8ac8c8a1dec2e7b51b /src/cmd/compile/internal/noder/reader.go | |
| parent | de4ead8102c3ba5dc9475ed3e117b2c50220b4df (diff) | |
| download | go-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.go | 266 |
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(¶ms, 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()) |
