]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.regabi] cmd/compile: merge OBLOCK and OEMPTY
authorRuss Cox <rsc@golang.org>
Tue, 1 Dec 2020 02:56:24 +0000 (21:56 -0500)
committerRuss Cox <rsc@golang.org>
Wed, 2 Dec 2020 20:12:47 +0000 (20:12 +0000)
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>
13 files changed:
src/cmd/compile/internal/gc/escape.go
src/cmd/compile/internal/gc/iexport.go
src/cmd/compile/internal/gc/iimport.go
src/cmd/compile/internal/gc/init.go
src/cmd/compile/internal/gc/inl.go
src/cmd/compile/internal/gc/noder.go
src/cmd/compile/internal/gc/order.go
src/cmd/compile/internal/gc/ssa.go
src/cmd/compile/internal/gc/typecheck.go
src/cmd/compile/internal/gc/walk.go
src/cmd/compile/internal/ir/fmt.go
src/cmd/compile/internal/ir/node.go
src/cmd/compile/internal/ir/stmt.go

index c1397717302d2b3f6d588f6a6f2a7a3dbff3ef73..9fc3dd27788d7856c8694d2dbf9439f0f5ed554c 100644 (file)
@@ -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:
index 7b21efb8c2b95c39482909a4b169f233c32b5f9b..85518bc9391a1251bf3fa51f896fdd18a18b32bd 100644 (file)
@@ -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())
index 419db285b58ccc900d0d7215145123406f7006d4..1d9baed5ad81267b156d77757fb5562e6a0a92db 100644 (file)
@@ -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 {
index e67a032c5d6c64a23126f4721be79c4ea25117d9..dc825b24218a3d25ba41649ebb90811f567e8034 100644 (file)
@@ -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())
        }
index b36a01e3898b6d89f9bbd5870c79c98e3f2c4381..89c9873c1dae32246697767856cb97f223f685fe 100644 (file)
@@ -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--
index 4c8165762833144ab96a1b592ae434a4416b16f9..9352463f18c47d7797eaac4c08027537d63772a4 100644 (file)
@@ -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)
index c2e236537f7bef63a45b6fbb65a33d5f59d53d51..352e9c473b51c5ec5099318151bda6ed07639f88 100644 (file)
@@ -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.
index 60e65e4b11c922cb4cfa0c373cfaffa3080ba881..7c74054b6032a86c42b964648791dc250660307e 100644 (file)
@@ -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:
index 2a0caad4693f3beeed2beaea7a1a5cdcf724b894..5a073ac32462e09d42b3570fd10835877257dcd8 100644 (file)
@@ -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) {
index 183a7acc1b5b33fba6da36f1ccebbd987489cef7..7e8ae22e4e1fe914938f7443179b1fa49253ec6b 100644 (file)
@@ -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
 }
 
index 5bb1ed857c0bad35081264c304a94d9cff07e64e..9486d8b021d5400457fe820ab66585360a2b08a2 100644 (file)
@@ -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,
index d121cc19d4017ed26d9f2875aafbca211aaa182f..06bc48e9ca2b1c3a7d00a83543ab5b0adbc31092 100644 (file)
@@ -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:
index 91714e38e3dd26f3a6f245df001a7860b5cff415..a6bbab48896b740e99afc1f72212fb0d0cd6820d 100644 (file)
@@ -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 {