[dev.regabi] cmd/compile: rewrite some generic ir.Nod calls

An automated rewrite is going to remove the bulk of the calls
to ir.Nod and friends. This CL takes care of the ones that don't
have fixed opcodes and so aren't amenable to automatic rewriting.

Passes buildall w/ toolstash -cmp.

Replay of CL 275886, lost to the bad-merge history rewrite.

Change-Id: I5bf8d1d182f847f4ab44b7e278b752913e30e4c8
Reviewed-on: https://go-review.googlesource.com/c/go/+/277956
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Russ Cox 2020-12-07 14:58:26 -05:00
parent 5ae70b85c6
commit 578fbbe3aa
7 changed files with 89 additions and 68 deletions

View file

@ -894,10 +894,10 @@ func (r *importReader) node() ir.Node {
// unreachable - mapped to cases below by exporter
case ir.OINDEX:
return ir.NodAt(r.pos(), op, r.expr(), r.expr())
return ir.NodAt(r.pos(), ir.OINDEX, r.expr(), r.expr())
case ir.OSLICE, ir.OSLICE3:
n := ir.NodAt(r.pos(), op, r.expr(), nil)
n := ir.NewSliceExpr(r.pos(), op, r.expr())
low, high := r.exprsOrNil()
var max ir.Node
if n.Op().IsSlice3() {
@ -940,15 +940,25 @@ func (r *importReader) node() ir.Node {
return n
// unary expressions
case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ODEREF, ir.ONOT, ir.ORECV:
return ir.NodAt(r.pos(), op, r.expr(), nil)
case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT, ir.ORECV:
return ir.NewUnaryExpr(r.pos(), op, r.expr())
case ir.OADDR:
return nodAddrAt(r.pos(), r.expr())
case ir.ODEREF:
return ir.NewStarExpr(r.pos(), r.expr())
// binary expressions
case ir.OADD, ir.OAND, ir.OANDAND, ir.OANDNOT, ir.ODIV, ir.OEQ, ir.OGE, ir.OGT, ir.OLE, ir.OLT,
ir.OLSH, ir.OMOD, ir.OMUL, ir.ONE, ir.OOR, ir.OOROR, ir.ORSH, ir.OSEND, ir.OSUB, ir.OXOR:
return ir.NodAt(r.pos(), op, r.expr(), r.expr())
case ir.OADD, ir.OAND, ir.OANDNOT, ir.ODIV, ir.OEQ, ir.OGE, ir.OGT, ir.OLE, ir.OLT,
ir.OLSH, ir.OMOD, ir.OMUL, ir.ONE, ir.OOR, ir.ORSH, ir.OSUB, ir.OXOR:
return ir.NewBinaryExpr(r.pos(), op, r.expr(), r.expr())
case ir.OANDAND, ir.OOROR:
return ir.NewLogicalExpr(r.pos(), op, r.expr(), r.expr())
case ir.OSEND:
return ir.NewSendStmt(r.pos(), r.expr(), r.expr())
case ir.OADDSTR:
pos := r.pos()
@ -1003,7 +1013,7 @@ func (r *importReader) node() ir.Node {
// unreachable - generated by compiler for trampolin routines (not exported)
case ir.OGO, ir.ODEFER:
return ir.NodAt(r.pos(), op, r.expr(), nil)
return ir.NewGoDeferStmt(r.pos(), op, r.expr())
case ir.OIF:
n := ir.NodAt(r.pos(), ir.OIF, nil, nil)
@ -1029,8 +1039,16 @@ func (r *importReader) node() ir.Node {
n.PtrBody().Set(r.stmtList())
return n
case ir.OSELECT, ir.OSWITCH:
n := ir.NodAt(r.pos(), op, nil, nil)
case ir.OSELECT:
n := ir.NodAt(r.pos(), ir.OSELECT, nil, nil)
n.PtrInit().Set(r.stmtList())
left, _ := r.exprsOrNil()
n.SetLeft(left)
n.PtrList().Set(r.caseList(n))
return n
case ir.OSWITCH:
n := ir.NodAt(r.pos(), ir.OSWITCH, nil, nil)
n.PtrInit().Set(r.stmtList())
left, _ := r.exprsOrNil()
n.SetLeft(left)
@ -1047,12 +1065,16 @@ func (r *importReader) node() ir.Node {
// case OEMPTY:
// unreachable - not emitted by exporter
case ir.OBREAK, ir.OCONTINUE, ir.OGOTO, ir.OLABEL:
n := ir.NodAt(r.pos(), op, nil, nil)
case ir.OBREAK, ir.OCONTINUE, ir.OGOTO:
var sym *types.Sym
pos := r.pos()
if label := r.string(); label != "" {
n.SetSym(lookup(label))
sym = lookup(label)
}
return n
return ir.NewBranchStmt(pos, op, sym)
case ir.OLABEL:
return ir.NewLabelStmt(r.pos(), lookup(r.string()))
case ir.OEND:
return nil

View file

@ -699,7 +699,7 @@ func (p *noder) expr(expr syntax.Expr) ir.Node {
if expr.Full {
op = ir.OSLICE3
}
n := p.nod(expr, op, p.expr(expr.X), nil)
n := ir.NewSliceExpr(p.pos(expr), op, p.expr(expr.X))
var index [3]ir.Node
for i, x := range &expr.Index {
if x != nil {
@ -716,9 +716,22 @@ func (p *noder) expr(expr syntax.Expr) ir.Node {
}
x := p.expr(expr.X)
if expr.Y == nil {
return p.nod(expr, p.unOp(expr.Op), x, nil)
pos, op := p.pos(expr), p.unOp(expr.Op)
switch op {
case ir.OADDR:
return nodAddrAt(pos, x)
case ir.ODEREF:
return ir.NewStarExpr(pos, x)
}
return ir.NewUnaryExpr(pos, op, x)
}
return p.nod(expr, p.binOp(expr.Op), x, p.expr(expr.Y))
pos, op, y := p.pos(expr), p.binOp(expr.Op), p.expr(expr.Y)
switch op {
case ir.OANDAND, ir.OOROR:
return ir.NewLogicalExpr(pos, op, x, y)
}
return ir.NewBinaryExpr(pos, op, x, y)
case *syntax.CallExpr:
n := p.nod(expr, ir.OCALL, p.expr(expr.Fun), nil)
n.PtrList().Set(p.exprs(expr.ArgList))
@ -1043,11 +1056,11 @@ func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) ir.Node {
default:
panic("unhandled BranchStmt")
}
n := p.nod(stmt, op, nil, nil)
var sym *types.Sym
if stmt.Label != nil {
n.SetSym(p.name(stmt.Label))
sym = p.name(stmt.Label)
}
return n
return ir.NewBranchStmt(p.pos(stmt), op, sym)
case *syntax.CallStmt:
var op ir.Op
switch stmt.Tok {
@ -1058,7 +1071,7 @@ func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) ir.Node {
default:
panic("unhandled CallStmt")
}
return p.nod(stmt, op, p.expr(stmt.Call), nil)
return ir.NewGoDeferStmt(p.pos(stmt), op, p.expr(stmt.Call))
case *syntax.ReturnStmt:
var results []ir.Node
if stmt.Results != nil {

View file

@ -619,11 +619,8 @@ func (o *Order) stmt(n ir.Node) {
l2.SetIndexMapLValue(false)
}
l2 = o.copyExpr(l2)
r := ir.NodAt(n.Pos(), n.SubOp(), l2, n.Right())
r = typecheck(r, ctxExpr)
r = o.expr(r, nil)
n = ir.NodAt(n.Pos(), ir.OAS, l1, r)
n = typecheck(n, ctxStmt)
r := o.expr(typecheck(ir.NewBinaryExpr(n.Pos(), n.SubOp(), l2, n.Right()), ctxExpr), nil)
n = typecheck(ir.NodAt(n.Pos(), ir.OAS, l1, r), ctxStmt)
}
o.mapAssign(n)

View file

@ -70,7 +70,8 @@ func typecheckselect(sel ir.Node) {
case ir.ORECV:
// convert <-c into OSELRECV(_, <-c)
n = ir.NodAt(n.Pos(), ir.OSELRECV, ir.BlankNode, n)
n = ir.NodAt(n.Pos(), ir.OAS, ir.BlankNode, n)
n.SetOp(ir.OSELRECV)
n.SetTypecheck(1)
ncase.SetLeft(n)
@ -164,7 +165,8 @@ func walkselectcases(cases *ir.Nodes) []ir.Node {
// Lower x, _ = <-c to x = <-c.
if n.Op() == ir.OSELRECV2 && ir.IsBlank(n.List().Second()) {
n = ir.NodAt(n.Pos(), ir.OSELRECV, n.List().First(), n.Rlist().First())
n = ir.NodAt(n.Pos(), ir.OAS, n.List().First(), n.Rlist().First())
n.SetOp(ir.OSELRECV)
n.SetTypecheck(1)
cas.SetLeft(n)
}

View file

@ -547,8 +547,7 @@ func assignconvfn(n ir.Node, t *types.Type, context func() string) ir.Node {
op = ir.OCONV
}
r := ir.Nod(op, n, nil)
r.SetType(t)
r := ir.NewConvExpr(base.Pos, op, t, n)
r.SetTypecheck(1)
r.SetImplicit(true)
return r
@ -1169,7 +1168,7 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) {
fn.PtrBody().Append(n)
}
dot := adddot(nodSym(ir.OXDOT, nthis, method.Sym))
dot := adddot(ir.NewSelectorExpr(base.Pos, ir.OXDOT, nthis, method.Sym))
// generate call
// It's not possible to use a tail call when dynamic linking on ppc64le. The

View file

@ -766,8 +766,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
dowidth(l.Type())
if r.Type().IsInterface() == l.Type().IsInterface() || l.Type().Width >= 1<<16 {
l = ir.Nod(aop, l, nil)
l.SetType(r.Type())
l = ir.NewConvExpr(base.Pos, aop, r.Type(), l)
l.SetTypecheck(1)
n.SetLeft(l)
}
@ -788,8 +787,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
dowidth(r.Type())
if r.Type().IsInterface() == l.Type().IsInterface() || r.Type().Width >= 1<<16 {
r = ir.Nod(aop, r, nil)
r.SetType(l.Type())
r = ir.NewConvExpr(base.Pos, aop, l.Type(), r)
r.SetTypecheck(1)
n.SetRight(r)
}
@ -1361,12 +1359,12 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
switch l.SubOp() {
default:
base.Fatalf("unknown builtin %v", l)
return n
case ir.OAPPEND, ir.ODELETE, ir.OMAKE, ir.OPRINT, ir.OPRINTN, ir.ORECOVER:
n.SetOp(l.SubOp())
n.SetLeft(nil)
n.SetTypecheck(0) // re-typechecking new op is OK, not a loop
return typecheck(n, top)
case ir.OCAP, ir.OCLOSE, ir.OIMAG, ir.OLEN, ir.OPANIC, ir.OREAL:
typecheckargs(n)
@ -1377,9 +1375,8 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
n.SetType(nil)
return n
}
old := n
n = ir.NodAt(n.Pos(), l.SubOp(), arg, nil)
n = initExpr(old.Init().Slice(), n) // typecheckargs can add to old.Init
u := ir.NewUnaryExpr(n.Pos(), l.SubOp(), arg)
return typecheck(initExpr(n.Init().Slice(), u), top) // typecheckargs can add to old.Init
case ir.OCOMPLEX, ir.OCOPY:
typecheckargs(n)
@ -1388,11 +1385,10 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
n.SetType(nil)
return n
}
old := n
n = ir.NodAt(n.Pos(), l.SubOp(), arg1, arg2)
n = initExpr(old.Init().Slice(), n) // typecheckargs can add to old.Init
b := ir.NewBinaryExpr(n.Pos(), l.SubOp(), arg1, arg2)
return typecheck(initExpr(n.Init().Slice(), b), top) // typecheckargs can add to old.Init
}
return typecheck(n, top)
panic("unreachable")
}
n.SetLeft(defaultlit(n.Left(), nil))

View file

@ -666,7 +666,7 @@ func walkexpr1(n ir.Node, init *ir.Nodes) ir.Node {
if n.Op() == ir.OASOP {
// Rewrite x op= y into x = x op y.
n = ir.Nod(ir.OAS, n.Left(),
typecheck(ir.Nod(n.SubOp(), n.Left(), n.Right()), ctxExpr))
typecheck(ir.NewBinaryExpr(base.Pos, n.SubOp(), n.Left(), n.Right()), ctxExpr))
}
if oaslit(n, init) {
@ -3232,16 +3232,16 @@ func walkcompare(n ir.Node, init *ir.Nodes) ir.Node {
if l.Type().IsEmptyInterface() {
tab.SetType(types.NewPtr(types.Types[types.TUINT8]))
tab.SetTypecheck(1)
eqtype = ir.Nod(eq, tab, rtyp)
eqtype = ir.NewBinaryExpr(base.Pos, eq, tab, rtyp)
} else {
nonnil := ir.Nod(brcom(eq), nodnil(), tab)
match := ir.Nod(eq, itabType(tab), rtyp)
eqtype = ir.Nod(andor, nonnil, match)
nonnil := ir.NewBinaryExpr(base.Pos, brcom(eq), nodnil(), tab)
match := ir.NewBinaryExpr(base.Pos, eq, itabType(tab), rtyp)
eqtype = ir.NewLogicalExpr(base.Pos, andor, nonnil, match)
}
// Check for data equal.
eqdata := ir.Nod(eq, ifaceData(n.Pos(), l, r.Type()), r)
eqdata := ir.NewBinaryExpr(base.Pos, eq, ifaceData(n.Pos(), l, r.Type()), r)
// Put it all together.
expr := ir.Nod(andor, eqtype, eqdata)
expr := ir.NewLogicalExpr(base.Pos, andor, eqtype, eqdata)
n = finishcompare(n, expr, init)
return n
}
@ -3354,11 +3354,11 @@ func walkcompare(n ir.Node, init *ir.Nodes) ir.Node {
}
var expr ir.Node
compare := func(el, er ir.Node) {
a := ir.Nod(n.Op(), el, er)
a := ir.NewBinaryExpr(base.Pos, n.Op(), el, er)
if expr == nil {
expr = a
} else {
expr = ir.Nod(andor, expr, a)
expr = ir.NewLogicalExpr(base.Pos, andor, expr, a)
}
}
cmpl = safeexpr(cmpl, init)
@ -3519,13 +3519,13 @@ func walkcompareString(n ir.Node, init *ir.Nodes) ir.Node {
if len(s) > 0 {
ncs = safeexpr(ncs, init)
}
r := ir.Nod(cmp, ir.Nod(ir.OLEN, ncs, nil), nodintconst(int64(len(s))))
r := ir.Node(ir.NewBinaryExpr(base.Pos, cmp, ir.Nod(ir.OLEN, ncs, nil), nodintconst(int64(len(s)))))
remains := len(s)
for i := 0; remains > 0; {
if remains == 1 || !canCombineLoads {
cb := nodintconst(int64(s[i]))
ncb := ir.Nod(ir.OINDEX, ncs, nodintconst(int64(i)))
r = ir.Nod(and, r, ir.Nod(cmp, ncb, cb))
r = ir.NewLogicalExpr(base.Pos, and, r, ir.NewBinaryExpr(base.Pos, cmp, ncb, cb))
remains--
i++
continue
@ -3556,7 +3556,7 @@ func walkcompareString(n ir.Node, init *ir.Nodes) ir.Node {
}
csubstrPart := nodintconst(csubstr)
// Compare "step" bytes as once
r = ir.Nod(and, r, ir.Nod(cmp, csubstrPart, ncsubstr))
r = ir.NewLogicalExpr(base.Pos, and, r, ir.NewBinaryExpr(base.Pos, cmp, csubstrPart, ncsubstr))
remains -= step
i += step
}
@ -3583,7 +3583,7 @@ func walkcompareString(n ir.Node, init *ir.Nodes) ir.Node {
} else {
// sys_cmpstring(s1, s2) :: 0
r = mkcall("cmpstring", types.Types[types.TINT], init, conv(n.Left(), types.Types[types.TSTRING]), conv(n.Right(), types.Types[types.TSTRING]))
r = ir.Nod(n.Op(), r, nodintconst(0))
r = ir.NewBinaryExpr(base.Pos, n.Op(), r, nodintconst(0))
}
return finishcompare(n, r, init)
@ -3909,17 +3909,13 @@ func wrapCall(n ir.Node, init *ir.Nodes) ir.Node {
if origArg == nil {
continue
}
arg := ir.Nod(origArg.Op(), args[i], nil)
arg.SetType(origArg.Type())
args[i] = arg
args[i] = ir.NewConvExpr(base.Pos, origArg.Op(), origArg.Type(), args[i])
}
call := ir.Nod(n.Op(), nil, nil)
call := ir.NewCallExpr(base.Pos, n.Op(), n.Left(), args)
if !isBuiltinCall {
call.SetOp(ir.OCALL)
call.SetLeft(n.Left())
call.SetIsDDD(n.IsDDD())
}
call.PtrList().Set(args)
fn.PtrBody().Set1(call)
funcbody()
@ -3928,12 +3924,8 @@ func wrapCall(n ir.Node, init *ir.Nodes) ir.Node {
typecheckslice(fn.Body().Slice(), ctxStmt)
xtop = append(xtop, fn)
call = ir.Nod(ir.OCALL, nil, nil)
call.SetLeft(fn.Nname)
call.PtrList().Set(n.List().Slice())
call = typecheck(call, ctxStmt)
call = walkexpr(call, init)
return call
call = ir.NewCallExpr(base.Pos, ir.OCALL, fn.Nname, n.List().Slice())
return walkexpr(typecheck(call, ctxStmt), init)
}
// substArgTypes substitutes the given list of types for