1
0
mirror of https://github.com/golang/go synced 2024-10-05 20:31:20 -06:00

[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/11941
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Josh Bleecher Snyder 2015-07-06 15:29:39 -07:00
parent 41dafe6ecc
commit 5173868325

View File

@ -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) {
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) {
// 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)