[dev.regabi] cmd/compile: remove {Ptr,Set}Init from Node interface

This CL separates out PtrInit and SetInit into a new InitNode
extension interface, and adds a new TakeInit helper function for
taking and clearing the Init list (if any) from a Node.

This allows removing miniNode.SetInit and miniNode.PtrInit, which in
turn allow getting rid of immutableEmptyNodes, and will allow
simplification of the Nodes API.

It would be nice to get rid of the default Init method too, but
there's way more code that expects to be able to call that at the
moment, so that'll have to wait.

Passes toolstash -cmp.

Change-Id: Ia8c18fab9555b774376f7f43eeecfde4f07b5946
Reviewed-on: https://go-review.googlesource.com/c/go/+/281001
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 01:04:19 -08:00
parent 1544a03198
commit 2f2d4b4e68
14 changed files with 52 additions and 73 deletions

View file

@ -84,7 +84,9 @@ func stmts(nn *ir.Nodes) {
}
}
stmts(n.PtrInit())
if len(n.Init()) != 0 {
stmts(n.(ir.InitNode).PtrInit())
}
switch n.Op() {
case ir.OBLOCK:
n := n.(*ir.BlockStmt)

View file

@ -639,7 +639,7 @@ func inlCallee(fn ir.Node) *ir.Func {
return nil
}
func inlParam(t *types.Field, as ir.Node, inlvars map[*ir.Name]*ir.Name) ir.Node {
func inlParam(t *types.Field, as ir.InitNode, inlvars map[*ir.Name]*ir.Name) ir.Node {
if t.Nname == nil {
return ir.BlankNode
}
@ -741,7 +741,7 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b
callee := n.X
for callee.Op() == ir.OCONVNOP {
conv := callee.(*ir.ConvExpr)
ninit.Append(conv.PtrInit().Take()...)
ninit.Append(ir.TakeInit(conv)...)
callee = conv.X
}
if callee.Op() != ir.ONAME && callee.Op() != ir.OCLOSURE && callee.Op() != ir.OMETHEXPR {

View file

@ -80,13 +80,7 @@ func (n *miniNode) SetDiag(x bool) { n.bits.set(miniDiag, x) }
// Empty, immutable graph structure.
func (n *miniNode) Init() Nodes { return Nodes{} }
func (n *miniNode) PtrInit() *Nodes { return &immutableEmptyNodes }
func (n *miniNode) SetInit(x Nodes) {
if x != nil {
panic(n.no("SetInit"))
}
}
func (n *miniNode) Init() Nodes { return Nodes{} }
// Additional functionality unavailable.

View file

@ -34,8 +34,6 @@ type Node interface {
// Abstract graph structure, for generic traversals.
Op() Op
Init() Nodes
PtrInit() *Nodes
SetInit(x Nodes)
// Fields specific to certain Ops only.
Type() *types.Type
@ -90,6 +88,20 @@ func MayBeShared(n Node) bool {
return false
}
type InitNode interface {
Node
PtrInit() *Nodes
SetInit(x Nodes)
}
func TakeInit(n Node) Nodes {
init := n.Init()
if len(init) != 0 {
n.(InitNode).SetInit(nil)
}
return init
}
//go:generate stringer -type=Op -trimprefix=O node.go
type Op uint8
@ -311,35 +323,15 @@ const (
// a slice to save space.
type Nodes []Node
// immutableEmptyNodes is an immutable, empty Nodes list.
// The methods that would modify it panic instead.
var immutableEmptyNodes = Nodes{}
func (n *Nodes) mutate() {
if n == &immutableEmptyNodes {
panic("immutable Nodes.Set")
}
}
// Set sets n to a slice.
// This takes ownership of the slice.
func (n *Nodes) Set(s []Node) {
if n == &immutableEmptyNodes {
if len(s) == 0 {
// Allow immutableEmptyNodes.Set(nil) (a no-op).
return
}
n.mutate()
}
*n = s
}
func (n *Nodes) Set(s []Node) { *n = s }
// Append appends entries to Nodes.
func (n *Nodes) Append(a ...Node) {
if len(a) == 0 {
return
}
n.mutate()
*n = append(*n, a...)
}
@ -349,7 +341,6 @@ func (n *Nodes) Prepend(a ...Node) {
if len(a) == 0 {
return
}
n.mutate()
*n = append(a, *n...)
}
@ -544,15 +535,16 @@ func SetPos(n Node) src.XPos {
// The result of InitExpr MUST be assigned back to n, e.g.
// n.Left = InitExpr(init, n.Left)
func InitExpr(init []Node, n Node) Node {
func InitExpr(init []Node, expr Node) Node {
if len(init) == 0 {
return n
return expr
}
if MayBeShared(n) {
n, ok := expr.(InitNode)
if !ok || MayBeShared(n) {
// Introduce OCONVNOP to hold init list.
old := n
n = NewConvExpr(base.Pos, OCONVNOP, nil, old)
n.SetType(old.Type())
n = NewConvExpr(base.Pos, OCONVNOP, nil, expr)
n.SetType(expr.Type())
n.SetTypecheck(1)
}

View file

@ -1200,7 +1200,7 @@ func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) ir.Node {
panic("unhandled Stmt")
}
func (p *noder) assignList(expr syntax.Expr, defn ir.Node, colas bool) []ir.Node {
func (p *noder) assignList(expr syntax.Expr, defn ir.InitNode, colas bool) []ir.Node {
if !colas {
return p.exprList(expr)
}

View file

@ -914,7 +914,7 @@ func typecheck1(n ir.Node, top int) ir.Node {
// Each must execute its own return n.
}
func typecheckargs(n ir.Node) {
func typecheckargs(n ir.InitNode) {
var list []ir.Node
switch n := n.(type) {
default:

View file

@ -17,7 +17,7 @@ import (
// walkAssign walks an OAS (AssignExpr) or OASOP (AssignOpExpr) node.
func walkAssign(init *ir.Nodes, n ir.Node) ir.Node {
init.Append(n.PtrInit().Take()...)
init.Append(ir.TakeInit(n)...)
var left, right ir.Node
switch n.Op() {
@ -124,7 +124,7 @@ func walkAssignDotType(n *ir.AssignListStmt, init *ir.Nodes) ir.Node {
// walkAssignFunc walks an OAS2FUNC node.
func walkAssignFunc(init *ir.Nodes, n *ir.AssignListStmt) ir.Node {
init.Append(n.PtrInit().Take()...)
init.Append(ir.TakeInit(n)...)
r := n.Rhs[0]
walkExprListSafe(n.Lhs, init)
@ -142,7 +142,7 @@ func walkAssignFunc(init *ir.Nodes, n *ir.AssignListStmt) ir.Node {
// walkAssignList walks an OAS2 node.
func walkAssignList(init *ir.Nodes, n *ir.AssignListStmt) ir.Node {
init.Append(n.PtrInit().Take()...)
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))
@ -150,7 +150,7 @@ func walkAssignList(init *ir.Nodes, n *ir.AssignListStmt) ir.Node {
// walkAssignMapRead walks an OAS2MAPR node.
func walkAssignMapRead(init *ir.Nodes, n *ir.AssignListStmt) ir.Node {
init.Append(n.PtrInit().Take()...)
init.Append(ir.TakeInit(n)...)
r := n.Rhs[0].(*ir.IndexExpr)
walkExprListSafe(n.Lhs, init)
@ -213,7 +213,7 @@ func walkAssignMapRead(init *ir.Nodes, n *ir.AssignListStmt) ir.Node {
// walkAssignRecv walks an OAS2RECV node.
func walkAssignRecv(init *ir.Nodes, n *ir.AssignListStmt) ir.Node {
init.Append(n.PtrInit().Take()...)
init.Append(ir.TakeInit(n)...)
r := n.Rhs[0].(*ir.UnaryExpr) // recv
walkExprListSafe(n.Lhs, init)

View file

@ -206,7 +206,7 @@ func walkCopy(n *ir.BinaryExpr, init *ir.Nodes, runtimecall bool) ir.Node {
// walkDelete walks an ODELETE node.
func walkDelete(init *ir.Nodes, n *ir.CallExpr) ir.Node {
init.Append(n.PtrInit().Take()...)
init.Append(ir.TakeInit(n)...)
map_ := n.Args[0]
key := n.Args[1]
map_ = walkExpr(map_, init)

View file

@ -26,7 +26,7 @@ func walkExpr(n ir.Node, init *ir.Nodes) ir.Node {
return n
}
if init == n.PtrInit() {
if n, ok := n.(ir.InitNode); ok && init == n.PtrInit() {
// not okay to use n->ninit when walking n,
// because we might replace n with some other node
// and would lose the init list.
@ -35,7 +35,7 @@ func walkExpr(n ir.Node, init *ir.Nodes) ir.Node {
if len(n.Init()) != 0 {
walkStmtList(n.Init())
init.Append(n.PtrInit().Take()...)
init.Append(ir.TakeInit(n)...)
}
lno := ir.SetPos(n)
@ -359,7 +359,7 @@ func safeExpr(n ir.Node, init *ir.Nodes) ir.Node {
if len(n.Init()) != 0 {
walkStmtList(n.Init())
init.Append(n.PtrInit().Take()...)
init.Append(ir.TakeInit(n)...)
}
switch n.Op() {

View file

@ -466,8 +466,7 @@ func (o *orderState) init(n ir.Node) {
}
return
}
o.stmtList(n.Init())
n.PtrInit().Set(nil)
o.stmtList(ir.TakeInit(n))
}
// call orders the call expression n.
@ -938,8 +937,7 @@ func (o *orderState) stmt(n ir.Node) {
if !ir.IsAutoTmp(recv.X) {
recv.X = o.copyExpr(recv.X)
}
init := *r.PtrInit()
r.PtrInit().Set(nil)
init := ir.TakeInit(r)
colas := r.Def
do := func(i int, t *types.Type) {
@ -1000,8 +998,7 @@ func (o *orderState) stmt(n ir.Node) {
// TODO(mdempsky): Is this actually necessary?
// walkselect appears to walk Ninit.
cas.Body.Prepend(cas.Init()...)
cas.PtrInit().Set(nil)
cas.Body.Prepend(ir.TakeInit(cas)...)
}
o.out = append(o.out, n)

View file

@ -210,7 +210,7 @@ func walkRange(nrange *ir.RangeStmt) ir.Node {
a.SetTypecheck(1)
a.Lhs = []ir.Node{hv1, hb}
a.Rhs = []ir.Node{ir.NewUnaryExpr(base.Pos, ir.ORECV, ha)}
*nfor.Cond.PtrInit() = []ir.Node{a}
nfor.Cond = ir.InitExpr([]ir.Node{a}, nfor.Cond)
if v1 == nil {
body = nil
} else {

View file

@ -17,8 +17,7 @@ func walkSelect(sel *ir.SelectStmt) {
base.Fatalf("double walkselect")
}
init := sel.Init()
sel.PtrInit().Set(nil)
init := ir.TakeInit(sel)
init = append(init, walkSelectCases(sel.Cases)...)
sel.Cases = nil
@ -45,8 +44,7 @@ func walkSelectCases(cases []*ir.CommClause) []ir.Node {
l := cas.Init()
if cas.Comm != nil { // not default:
n := cas.Comm
l = append(l, n.Init()...)
n.PtrInit().Set(nil)
l = append(l, ir.TakeInit(n)...)
switch n.Op() {
default:
base.Fatalf("select %v", n.Op())
@ -171,8 +169,7 @@ func walkSelectCases(cases []*ir.CommClause) []ir.Node {
for _, cas := range cases {
ir.SetPos(cas)
init = append(init, cas.Init()...)
cas.PtrInit().Set(nil)
init = append(init, ir.TakeInit(cas)...)
n := cas.Comm
if n == nil { // default:

View file

@ -55,8 +55,7 @@ func walkStmt(n ir.Node) ir.Node {
if n.Typecheck() == 0 {
base.Fatalf("missing typecheck: %+v", n)
}
init := n.Init()
n.PtrInit().Set(nil)
init := ir.TakeInit(n)
n = walkExpr(n, &init)
if n.Op() == ir.ONAME {
// copy rewrote to a statement list and a temp for the length.
@ -67,7 +66,7 @@ func walkStmt(n ir.Node) ir.Node {
if len(init) > 0 {
switch n.Op() {
case ir.OAS, ir.OAS2, ir.OBLOCK:
n.PtrInit().Prepend(init...)
n.(ir.InitNode).PtrInit().Prepend(init...)
default:
init.Append(n)
@ -191,9 +190,8 @@ func walkDecl(n *ir.Decl) ir.Node {
// walkFor walks an OFOR or OFORUNTIL node.
func walkFor(n *ir.ForStmt) ir.Node {
if n.Cond != nil {
walkStmtList(n.Cond.Init())
init := n.Cond.Init()
n.Cond.PtrInit().Set(nil)
init := ir.TakeInit(n.Cond)
walkStmtList(init)
n.Cond = walkExpr(n.Cond, &init)
n.Cond = ir.InitExpr(init, n.Cond)
}
@ -257,7 +255,7 @@ func walkIf(n *ir.IfStmt) ir.Node {
func wrapCall(n *ir.CallExpr, init *ir.Nodes) ir.Node {
if len(n.Init()) != 0 {
walkStmtList(n.Init())
init.Append(n.PtrInit().Take()...)
init.Append(ir.TakeInit(n)...)
}
isBuiltinCall := n.Op() != ir.OCALLFUNC && n.Op() != ir.OCALLMETH && n.Op() != ir.OCALLINTER

View file

@ -81,8 +81,7 @@ func walkRecv(n *ir.UnaryExpr) ir.Node {
if n.Typecheck() == 0 {
base.Fatalf("missing typecheck: %+v", n)
}
init := n.Init()
n.PtrInit().Set(nil)
init := ir.TakeInit(n)
n.X = walkExpr(n.X, &init)
call := walkExpr(mkcall1(chanfn("chanrecv1", 2, n.X.Type()), nil, &init, n.X, typecheck.NodNil()), &init)