[dev.regabi] cmd/compile: simplify walkReturn

Just de-duplicating some logic and adding better comments.

Passes toolstash -cmp.

Change-Id: I15ec07070510692c6d4367880bc3d2d9847370ab
Reviewed-on: https://go-review.googlesource.com/c/go/+/281132
Trust: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
This commit is contained in:
Matthew Dempsky 2021-01-02 22:43:58 -08:00
parent bb1b6c95c2
commit 5d80a590a2

View file

@ -143,8 +143,6 @@ func walkAssignFunc(init *ir.Nodes, n *ir.AssignListStmt) ir.Node {
// walkAssignList walks an OAS2 node. // walkAssignList walks an OAS2 node.
func walkAssignList(init *ir.Nodes, n *ir.AssignListStmt) ir.Node { func walkAssignList(init *ir.Nodes, n *ir.AssignListStmt) ir.Node {
init.Append(ir.TakeInit(n)...) init.Append(ir.TakeInit(n)...)
walkExprListSafe(n.Lhs, init)
walkExprListSafe(n.Rhs, init)
return ir.NewBlockStmt(src.NoXPos, ascompatee(ir.OAS, n.Lhs, n.Rhs, init)) return ir.NewBlockStmt(src.NoXPos, ascompatee(ir.OAS, n.Lhs, n.Rhs, init))
} }
@ -232,54 +230,33 @@ func walkAssignRecv(init *ir.Nodes, n *ir.AssignListStmt) ir.Node {
// walkReturn walks an ORETURN node. // walkReturn walks an ORETURN node.
func walkReturn(n *ir.ReturnStmt) ir.Node { func walkReturn(n *ir.ReturnStmt) ir.Node {
ir.CurFunc.NumReturns++ fn := ir.CurFunc
fn.NumReturns++
if len(n.Results) == 0 { if len(n.Results) == 0 {
return n return n
} }
if (ir.HasNamedResults(ir.CurFunc) && len(n.Results) > 1) || paramoutheap(ir.CurFunc) {
// assign to the function out parameters,
// so that ascompatee can fix up conflicts
var rl []ir.Node
for _, ln := range ir.CurFunc.Dcl { results := fn.Type().Results().FieldSlice()
cl := ln.Class_ dsts := make([]ir.Node, len(results))
if cl == ir.PAUTO || cl == ir.PAUTOHEAP { for i, v := range results {
break // TODO(mdempsky): typecheck should have already checked the result variables.
} dsts[i] = typecheck.AssignExpr(v.Nname.(*ir.Name))
if cl == ir.PPARAMOUT {
var ln ir.Node = ln
if ir.IsParamStackCopy(ln) {
ln = walkExpr(typecheck.Expr(ir.NewStarExpr(base.Pos, ln.Name().Heapaddr)), nil)
}
rl = append(rl, ln)
}
} }
if got, want := len(n.Results), len(rl); got != want { if (ir.HasNamedResults(fn) && len(n.Results) > 1) || paramoutheap(fn) {
// order should have rewritten multi-value function calls // General case: For anything tricky, let ascompatee handle
// with explicit OAS2FUNC nodes. // ordering the assignments correctly.
base.Fatalf("expected %v return arguments, have %v", want, got) n.Results = ascompatee(n.Op(), dsts, n.Results, n.PtrInit())
}
// move function calls out, to make ascompatee's job easier.
walkExprListSafe(n.Results, n.PtrInit())
n.Results = ascompatee(n.Op(), rl, n.Results, n.PtrInit())
return n return n
} }
walkExprList(n.Results, n.PtrInit())
// For each return parameter (lhs), assign the corresponding result (rhs). // Common case: Assignment order doesn't matter. Simply assign to
lhs := ir.CurFunc.Type().Results() // each result parameter in order.
rhs := n.Results walkExprList(n.Results, n.PtrInit())
res := make([]ir.Node, lhs.NumFields()) res := make([]ir.Node, len(results))
for i, nl := range lhs.FieldSlice() { for i, v := range n.Results {
nname := ir.AsNode(nl.Nname) res[i] = convas(ir.NewAssignStmt(base.Pos, dsts[i], v), n.PtrInit())
if ir.IsParamHeapCopy(nname) {
nname = nname.Name().Stackcopy
}
a := ir.NewAssignStmt(base.Pos, nname, rhs[i])
res[i] = convas(a, n.PtrInit())
} }
n.Results = res n.Results = res
return n return n
@ -348,6 +325,14 @@ func ascompatee(op ir.Op, nl, nr []ir.Node, init *ir.Nodes) []ir.Node {
base.Fatalf("assignment operands mismatch: %+v / %+v", ir.Nodes(nl), ir.Nodes(nr)) base.Fatalf("assignment operands mismatch: %+v / %+v", ir.Nodes(nl), ir.Nodes(nr))
} }
// TODO(mdempsky): Simplify this code. Not only is it redundant to
// call safeExpr on the operands twice, but ensuring order of
// evaluation for function calls was already handled by order.go.
// move function calls out, to make ascompatee's job easier.
walkExprListSafe(nl, init)
walkExprListSafe(nr, init)
// ensure order of evaluation for function calls // ensure order of evaluation for function calls
for i := range nl { for i := range nl {
nl[i] = safeExpr(nl[i], init) nl[i] = safeExpr(nl[i], init)