Commit 51738683 authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder

[dev.ssa] cmd/compile/ssa: place for loop incr in a separate block

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/11941Reviewed-by: default avatarKeith Randall <khr@golang.org>
parent 41dafe6e
...@@ -379,8 +379,10 @@ func (s *state) stmt(n *Node) { ...@@ -379,8 +379,10 @@ func (s *state) stmt(n *Node) {
addEdge(b, s.exit) addEdge(b, s.exit)
case OFOR: case OFOR:
// OFOR: for Ninit; Left; Right { Nbody }
bCond := s.f.NewBlock(ssa.BlockPlain) bCond := s.f.NewBlock(ssa.BlockPlain)
bBody := s.f.NewBlock(ssa.BlockPlain) bBody := s.f.NewBlock(ssa.BlockPlain)
bIncr := s.f.NewBlock(ssa.BlockPlain)
bEnd := s.f.NewBlock(ssa.BlockPlain) bEnd := s.f.NewBlock(ssa.BlockPlain)
// first, jump to condition test // first, jump to condition test
...@@ -388,13 +390,14 @@ func (s *state) stmt(n *Node) { ...@@ -388,13 +390,14 @@ func (s *state) stmt(n *Node) {
addEdge(b, bCond) addEdge(b, bCond)
// generate code to test condition // 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.startBlock(bCond)
s.stmtList(n.Left.Ninit) var cond *ssa.Value
cond := s.expr(n.Left) 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 = s.endBlock()
b.Kind = ssa.BlockIf b.Kind = ssa.BlockIf
b.Control = cond b.Control = cond
...@@ -405,13 +408,16 @@ func (s *state) stmt(n *Node) { ...@@ -405,13 +408,16 @@ func (s *state) stmt(n *Node) {
// generate body // generate body
s.startBlock(bBody) s.startBlock(bBody)
s.stmtList(n.Nbody) s.stmtList(n.Nbody)
if b := s.endBlock(); b != nil {
addEdge(b, bIncr)
}
// generate incr
s.startBlock(bIncr)
if n.Right != nil { if n.Right != nil {
s.stmt(n.Right) s.stmt(n.Right)
} }
b = s.endBlock() if b := s.endBlock(); b != nil {
// If the body ends in a return statement,
// the condition check and loop are unreachable.
if b != nil {
addEdge(b, bCond) addEdge(b, bCond)
} }
s.startBlock(bEnd) s.startBlock(bEnd)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment