]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.ssa] cmd/compile/ssa: place for loop incr in a separate block
authorJosh Bleecher Snyder <josharian@gmail.com>
Mon, 6 Jul 2015 22:29:39 +0000 (15:29 -0700)
committerJosh Bleecher Snyder <josharian@gmail.com>
Fri, 10 Jul 2015 03:39:20 +0000 (03:39 +0000)
This is a prerequisite for implementing break and continue;
blocks ending in break or continue need to have
the increment block as a successor.

While we're here, implement for loops with no condition.

Change-Id: I85d8ba020628d805bfd0bd583dfd16e1be6f6fae
Reviewed-on: https://go-review.googlesource.com/11941
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/gc/ssa.go

index 866db610b884af0efb420c50047154e48f91b3e5..96ae49a1796974106724a78099305f43de17a253 100644 (file)
@@ -379,8 +379,10 @@ func (s *state) stmt(n *Node) {
                addEdge(b, s.exit)
 
        case OFOR:
+               // OFOR: for Ninit; Left; Right { Nbody }
                bCond := s.f.NewBlock(ssa.BlockPlain)
                bBody := s.f.NewBlock(ssa.BlockPlain)
+               bIncr := s.f.NewBlock(ssa.BlockPlain)
                bEnd := s.f.NewBlock(ssa.BlockPlain)
 
                // first, jump to condition test
@@ -388,13 +390,14 @@ func (s *state) stmt(n *Node) {
                addEdge(b, bCond)
 
                // generate code to test condition
-               // TODO(khr): Left == nil exception
-               if n.Left == nil {
-                       s.Unimplementedf("cond n.Left == nil: %v", n)
-               }
                s.startBlock(bCond)
-               s.stmtList(n.Left.Ninit)
-               cond := s.expr(n.Left)
+               var cond *ssa.Value
+               if n.Left != nil {
+                       s.stmtList(n.Left.Ninit)
+                       cond = s.expr(n.Left)
+               } else {
+                       cond = s.entryNewValue0A(ssa.OpConst, Types[TBOOL], true)
+               }
                b = s.endBlock()
                b.Kind = ssa.BlockIf
                b.Control = cond
@@ -405,13 +408,16 @@ func (s *state) stmt(n *Node) {
                // generate body
                s.startBlock(bBody)
                s.stmtList(n.Nbody)
+               if b := s.endBlock(); b != nil {
+                       addEdge(b, bIncr)
+               }
+
+               // generate incr
+               s.startBlock(bIncr)
                if n.Right != nil {
                        s.stmt(n.Right)
                }
-               b = s.endBlock()
-               // If the body ends in a return statement,
-               // the condition check and loop are unreachable.
-               if b != nil {
+               if b := s.endBlock(); b != nil {
                        addEdge(b, bCond)
                }
                s.startBlock(bEnd)