mirror of
https://github.com/golang/go
synced 2024-11-11 19:51:37 -07:00
[dev.regabi] cmd/compile: merge OBLOCK and OEMPTY
OEMPTY is an empty *statement*, but it confusingly gets handled as an expression in a few places. More confusingly, OEMPTY often has an init list, making it not empty at all. Replace uses and analysis of OEMPTY with OBLOCK instead. Passes buildall w/ toolstash -cmp. Change-Id: I8d4fcef151e4f441fa19b1b96da5272d778131d6 Reviewed-on: https://go-review.googlesource.com/c/go/+/274594 Trust: Russ Cox <rsc@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
c769d393de
commit
ec5f349b22
@ -302,7 +302,7 @@ func (e *Escape) stmt(n ir.Node) {
|
||||
default:
|
||||
base.Fatalf("unexpected stmt: %v", n)
|
||||
|
||||
case ir.ODCLCONST, ir.ODCLTYPE, ir.OEMPTY, ir.OFALL, ir.OINLMARK:
|
||||
case ir.ODCLCONST, ir.ODCLTYPE, ir.OFALL, ir.OINLMARK:
|
||||
// nop
|
||||
|
||||
case ir.OBREAK, ir.OCONTINUE, ir.OGOTO:
|
||||
|
@ -1048,6 +1048,17 @@ func (w *exportWriter) stmt(n ir.Node) {
|
||||
}
|
||||
|
||||
switch op := n.Op(); op {
|
||||
case ir.OBLOCK:
|
||||
// No OBLOCK in export data.
|
||||
// Inline content into this statement list,
|
||||
// like the init list above.
|
||||
// (At the moment neither the parser nor the typechecker
|
||||
// generate OBLOCK nodes except to denote an empty
|
||||
// function body, although that may change.)
|
||||
for _, n := range n.List().Slice() {
|
||||
w.stmt(n)
|
||||
}
|
||||
|
||||
case ir.ODCL:
|
||||
w.op(ir.ODCL)
|
||||
w.pos(n.Left().Pos())
|
||||
@ -1129,9 +1140,6 @@ func (w *exportWriter) stmt(n ir.Node) {
|
||||
w.op(ir.OFALL)
|
||||
w.pos(n.Pos())
|
||||
|
||||
case ir.OEMPTY:
|
||||
// nothing to emit
|
||||
|
||||
case ir.OBREAK, ir.OCONTINUE, ir.OGOTO, ir.OLABEL:
|
||||
w.op(op)
|
||||
w.pos(n.Pos())
|
||||
|
@ -742,7 +742,9 @@ func (r *importReader) stmtList() []ir.Node {
|
||||
if n == nil {
|
||||
break
|
||||
}
|
||||
// OBLOCK nodes may be created when importing ODCL nodes - unpack them
|
||||
// OBLOCK nodes are not written to the import data directly,
|
||||
// but the handling of ODCL calls liststmt, which creates one.
|
||||
// Inline them into the statement list.
|
||||
if n.Op() == ir.OBLOCK {
|
||||
list = append(list, n.List().Slice()...)
|
||||
} else {
|
||||
|
@ -88,8 +88,10 @@ func fninit(n []ir.Node) {
|
||||
s := lookupN("init.", i)
|
||||
fn := ir.AsNode(s.Def).Name().Defn
|
||||
// Skip init functions with empty bodies.
|
||||
if fn.Body().Len() == 1 && fn.Body().First().Op() == ir.OEMPTY {
|
||||
continue
|
||||
if fn.Body().Len() == 1 {
|
||||
if stmt := fn.Body().First(); stmt.Op() == ir.OBLOCK && stmt.List().Len() == 0 {
|
||||
continue
|
||||
}
|
||||
}
|
||||
fns = append(fns, s.Linksym())
|
||||
}
|
||||
|
@ -396,7 +396,7 @@ func (v *hairyVisitor) visit(n ir.Node) bool {
|
||||
case ir.OAPPEND:
|
||||
v.budget -= inlineExtraAppendCost
|
||||
|
||||
case ir.ODCLCONST, ir.OEMPTY, ir.OFALL:
|
||||
case ir.ODCLCONST, ir.OFALL:
|
||||
// These nodes don't produce code; omit from inlining budget.
|
||||
return false
|
||||
|
||||
@ -425,6 +425,11 @@ func (v *hairyVisitor) visit(n ir.Node) bool {
|
||||
v.usedLocals[n] = true
|
||||
}
|
||||
|
||||
case ir.OBLOCK:
|
||||
// The only OBLOCK we should see at this point is an empty one.
|
||||
// In any event, let the visitList(n.List()) below take care of the statements,
|
||||
// and don't charge for the OBLOCK itself. The ++ undoes the -- below.
|
||||
v.budget++
|
||||
}
|
||||
|
||||
v.budget--
|
||||
|
@ -164,7 +164,7 @@ func (p *noder) funcBody(fn *ir.Func, block *syntax.BlockStmt) {
|
||||
if block != nil {
|
||||
body := p.stmts(block.List)
|
||||
if body == nil {
|
||||
body = []ir.Node{ir.Nod(ir.OEMPTY, nil, nil)}
|
||||
body = []ir.Node{ir.Nod(ir.OBLOCK, nil, nil)}
|
||||
}
|
||||
fn.PtrBody().Set(body)
|
||||
|
||||
@ -967,7 +967,9 @@ func (p *noder) stmtsFall(stmts []syntax.Stmt, fallOK bool) []ir.Node {
|
||||
for i, stmt := range stmts {
|
||||
s := p.stmtFall(stmt, fallOK && i+1 == len(stmts))
|
||||
if s == nil {
|
||||
} else if s.Op() == ir.OBLOCK && s.Init().Len() == 0 {
|
||||
} else if s.Op() == ir.OBLOCK && s.List().Len() > 0 {
|
||||
// Inline non-empty block.
|
||||
// Empty blocks must be preserved for checkreturn.
|
||||
nodes = append(nodes, s.List().Slice()...)
|
||||
} else {
|
||||
nodes = append(nodes, s)
|
||||
@ -991,7 +993,7 @@ func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) ir.Node {
|
||||
l := p.blockStmt(stmt)
|
||||
if len(l) == 0 {
|
||||
// TODO(mdempsky): Line number?
|
||||
return ir.Nod(ir.OEMPTY, nil, nil)
|
||||
return ir.Nod(ir.OBLOCK, nil, nil)
|
||||
}
|
||||
return liststmt(l)
|
||||
case *syntax.ExprStmt:
|
||||
@ -1166,7 +1168,7 @@ func (p *noder) ifStmt(stmt *syntax.IfStmt) ir.Node {
|
||||
n.PtrBody().Set(p.blockStmt(stmt.Then))
|
||||
if stmt.Else != nil {
|
||||
e := p.stmt(stmt.Else)
|
||||
if e.Op() == ir.OBLOCK && e.Init().Len() == 0 {
|
||||
if e.Op() == ir.OBLOCK {
|
||||
n.PtrRlist().Set(e.List().Slice())
|
||||
} else {
|
||||
n.PtrRlist().Set1(e)
|
||||
@ -1319,7 +1321,7 @@ func (p *noder) labeledStmt(label *syntax.LabeledStmt, fallOK bool) ir.Node {
|
||||
|
||||
l := []ir.Node{lhs}
|
||||
if ls != nil {
|
||||
if ls.Op() == ir.OBLOCK && ls.Init().Len() == 0 {
|
||||
if ls.Op() == ir.OBLOCK {
|
||||
l = append(l, ls.List().Slice()...)
|
||||
} else {
|
||||
l = append(l, ls)
|
||||
|
@ -676,7 +676,7 @@ func (o *Order) stmt(n ir.Node) {
|
||||
o.cleanTemp(t)
|
||||
|
||||
// Special: does not save n onto out.
|
||||
case ir.OBLOCK, ir.OEMPTY:
|
||||
case ir.OBLOCK:
|
||||
o.stmtList(n.List())
|
||||
|
||||
// Special: n->left is not an expression; save as is.
|
||||
|
@ -1071,7 +1071,7 @@ func (s *state) stmt(n ir.Node) {
|
||||
s.stmtList(n.List())
|
||||
|
||||
// No-ops
|
||||
case ir.OEMPTY, ir.ODCLCONST, ir.ODCLTYPE, ir.OFALL:
|
||||
case ir.ODCLCONST, ir.ODCLTYPE, ir.OFALL:
|
||||
|
||||
// Expression statements
|
||||
case ir.OCALLFUNC:
|
||||
|
@ -1950,13 +1950,16 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
|
||||
case ir.OBREAK,
|
||||
ir.OCONTINUE,
|
||||
ir.ODCL,
|
||||
ir.OEMPTY,
|
||||
ir.OGOTO,
|
||||
ir.OFALL,
|
||||
ir.OVARKILL,
|
||||
ir.OVARLIVE:
|
||||
ok |= ctxStmt
|
||||
|
||||
case ir.OBLOCK:
|
||||
ok |= ctxStmt
|
||||
typecheckslice(n.List().Slice(), ctxStmt)
|
||||
|
||||
case ir.OLABEL:
|
||||
ok |= ctxStmt
|
||||
decldepth++
|
||||
@ -1964,7 +1967,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
|
||||
// Empty identifier is valid but useless.
|
||||
// Eliminate now to simplify life later.
|
||||
// See issues 7538, 11589, 11593.
|
||||
n = ir.NodAt(n.Pos(), ir.OEMPTY, nil, nil)
|
||||
n = ir.NodAt(n.Pos(), ir.OBLOCK, nil, nil)
|
||||
}
|
||||
|
||||
case ir.ODEFER:
|
||||
@ -3808,7 +3811,7 @@ func deadcode(fn *ir.Func) {
|
||||
}
|
||||
}
|
||||
|
||||
fn.PtrBody().Set([]ir.Node{ir.Nod(ir.OEMPTY, nil, nil)})
|
||||
fn.PtrBody().Set([]ir.Node{ir.Nod(ir.OBLOCK, nil, nil)})
|
||||
}
|
||||
|
||||
func deadcodeslice(nn *ir.Nodes) {
|
||||
|
@ -142,7 +142,6 @@ func walkstmt(n ir.Node) ir.Node {
|
||||
ir.OPRINT,
|
||||
ir.OPRINTN,
|
||||
ir.OPANIC,
|
||||
ir.OEMPTY,
|
||||
ir.ORECOVER,
|
||||
ir.OGETG:
|
||||
if n.Typecheck() == 0 {
|
||||
@ -155,7 +154,7 @@ func walkstmt(n ir.Node) ir.Node {
|
||||
if wascopy && n.Op() == ir.ONAME {
|
||||
// copy rewrote to a statement list and a temp for the length.
|
||||
// Throw away the temp to avoid plain values as statements.
|
||||
n = ir.NodAt(n.Pos(), ir.OEMPTY, nil, nil)
|
||||
n = ir.NodAt(n.Pos(), ir.OBLOCK, nil, nil)
|
||||
}
|
||||
n = addinit(n, init.Slice())
|
||||
|
||||
@ -470,7 +469,7 @@ opswitch:
|
||||
ir.Dump("walk", n)
|
||||
base.Fatalf("walkexpr: switch 1 unknown op %+S", n)
|
||||
|
||||
case ir.ONONAME, ir.OEMPTY, ir.OGETG, ir.ONEWOBJ, ir.OMETHEXPR:
|
||||
case ir.ONONAME, ir.OGETG, ir.ONEWOBJ, ir.OMETHEXPR:
|
||||
|
||||
case ir.OTYPE, ir.ONAME, ir.OLITERAL, ir.ONIL:
|
||||
// TODO(mdempsky): Just return n; see discussion on CL 38655.
|
||||
@ -609,7 +608,7 @@ opswitch:
|
||||
}
|
||||
|
||||
if oaslit(n, init) {
|
||||
n = ir.NodAt(n.Pos(), ir.OEMPTY, nil, nil)
|
||||
n = ir.NodAt(n.Pos(), ir.OBLOCK, nil, nil)
|
||||
break
|
||||
}
|
||||
|
||||
@ -2032,10 +2031,10 @@ func walkprint(nn ir.Node, init *ir.Nodes) ir.Node {
|
||||
typecheckslice(calls, ctxStmt)
|
||||
walkexprlist(calls, init)
|
||||
|
||||
r := ir.Nod(ir.OEMPTY, nil, nil)
|
||||
r := ir.Nod(ir.OBLOCK, nil, nil)
|
||||
r = typecheck(r, ctxStmt)
|
||||
r = walkexpr(r, init)
|
||||
r.PtrInit().Set(calls)
|
||||
r = walkstmt(r)
|
||||
r.PtrList().Set(calls)
|
||||
return r
|
||||
}
|
||||
|
||||
|
@ -942,6 +942,11 @@ func stmtFmt(n Node, s fmt.State, mode FmtMode) {
|
||||
mode.Fprintf(s, "%.v = %.v", n.List(), n.Rlist())
|
||||
}
|
||||
|
||||
case OBLOCK:
|
||||
if n.List().Len() != 0 {
|
||||
mode.Fprintf(s, "%v", n.List())
|
||||
}
|
||||
|
||||
case ORETURN:
|
||||
mode.Fprintf(s, "return %.v", n.List())
|
||||
|
||||
@ -1044,9 +1049,6 @@ func stmtFmt(n Node, s fmt.State, mode FmtMode) {
|
||||
mode.Fprintf(s, "%#v", n.Op())
|
||||
}
|
||||
|
||||
case OEMPTY:
|
||||
break
|
||||
|
||||
case OLABEL:
|
||||
mode.Fprintf(s, "%v: ", n.Sym())
|
||||
}
|
||||
@ -1155,12 +1157,12 @@ var OpPrec = []int{
|
||||
OAS2MAPR: -1,
|
||||
OAS2RECV: -1,
|
||||
OASOP: -1,
|
||||
OBLOCK: -1,
|
||||
OBREAK: -1,
|
||||
OCASE: -1,
|
||||
OCONTINUE: -1,
|
||||
ODCL: -1,
|
||||
ODEFER: -1,
|
||||
OEMPTY: -1,
|
||||
OFALL: -1,
|
||||
OFOR: -1,
|
||||
OFORUNTIL: -1,
|
||||
|
@ -301,7 +301,7 @@ const (
|
||||
OCASE
|
||||
OCONTINUE // continue [Sym]
|
||||
ODEFER // defer Left (Left must be call)
|
||||
OEMPTY // no-op (empty statement)
|
||||
OEMPTY // TODO(rsc): Delete. (Use OBLOCK instead.)
|
||||
OFALL // fallthrough
|
||||
OFOR // for Ninit; Left; Right { Nbody }
|
||||
// OFORUNTIL is like OFOR, but the test (Left) is applied after the body:
|
||||
@ -781,8 +781,6 @@ func NodAt(pos src.XPos, op Op, nleft, nright Node) Node {
|
||||
n := NewTypeAssertExpr(pos, nleft, typ)
|
||||
n.SetOp(op)
|
||||
return n
|
||||
case OEMPTY:
|
||||
return NewEmptyStmt(pos)
|
||||
case OFOR:
|
||||
return NewForStmt(pos, nil, nleft, nright, nil)
|
||||
case OGO:
|
||||
|
@ -266,22 +266,6 @@ func (n *DeferStmt) rawCopy() Node { c := *n; return &c }
|
||||
func (n *DeferStmt) Left() Node { return n.Call }
|
||||
func (n *DeferStmt) SetLeft(x Node) { n.Call = x }
|
||||
|
||||
// An EmptyStmt is an empty statement
|
||||
type EmptyStmt struct {
|
||||
miniStmt
|
||||
}
|
||||
|
||||
func NewEmptyStmt(pos src.XPos) *EmptyStmt {
|
||||
n := &EmptyStmt{}
|
||||
n.pos = pos
|
||||
n.op = OEMPTY
|
||||
return n
|
||||
}
|
||||
|
||||
func (n *EmptyStmt) String() string { return fmt.Sprint(n) }
|
||||
func (n *EmptyStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
|
||||
func (n *EmptyStmt) rawCopy() Node { c := *n; return &c }
|
||||
|
||||
// A ForStmt is a non-range for loop: for Init; Cond; Post { Body }
|
||||
// Op can be OFOR or OFORUNTIL (!Cond).
|
||||
type ForStmt struct {
|
||||
|
Loading…
Reference in New Issue
Block a user