Commit 46e62f87 authored by Keith Randall's avatar Keith Randall

[dev.ssa] cmd/compile: used Bounded field to fix empty range loops

    for i, v := range a {
    }

Walk converts this to a regular for loop, like this:

    for i := 0, p := &a[0]; i < len(a); i++, p++ {
        v := *p
    }

Unfortunately, &a[0] fails its bounds check when a is
the empty slice (or string).  The old compiler gets around this
by marking &a[0] as Bounded, meaning "don't emit bounds checks
for this index op".  This change makes SSA honor that same mark.

The SSA compiler hasn't implemented bounds check panics yet,
so the failed bounds check just causes the current routine
to return immediately.

Fixes bytes package tests.

Change-Id: Ibe838853ef4046c92f76adbded8cca3b1e449e0b
Reviewed-on: https://go-review.googlesource.com/13685Reviewed-by: default avatarJosh Bleecher Snyder <josharian@gmail.com>
parent 67cbd5b5
......@@ -1313,7 +1313,9 @@ func (s *state) expr(n *Node) *ssa.Value {
len = s.constInt(Types[TINT], n.Left.Type.Bound)
elemtype = n.Left.Type.Type
}
s.boundsCheck(i, len)
if !n.Bounded {
s.boundsCheck(i, len)
}
return s.newValue2(ssa.OpArrayIndex, elemtype, a, i)
} else { // slice
p := s.addr(n)
......@@ -1530,7 +1532,9 @@ func (s *state) addr(n *Node) *ssa.Value {
i := s.expr(n.Right)
i = s.extendIndex(i)
len := s.newValue1(ssa.OpSliceLen, Types[TUINTPTR], a)
s.boundsCheck(i, len)
if !n.Bounded {
s.boundsCheck(i, len)
}
p := s.newValue1(ssa.OpSlicePtr, Ptrto(n.Left.Type.Type), a)
return s.newValue2(ssa.OpPtrIndex, Ptrto(n.Left.Type.Type), p, i)
} else { // array
......@@ -1538,7 +1542,9 @@ func (s *state) addr(n *Node) *ssa.Value {
i := s.expr(n.Right)
i = s.extendIndex(i)
len := s.constInt(Types[TINT], n.Left.Type.Bound)
s.boundsCheck(i, len)
if !n.Bounded {
s.boundsCheck(i, len)
}
return s.newValue2(ssa.OpPtrIndex, Ptrto(n.Left.Type.Type), a, i)
}
case OIND:
......
......@@ -43,10 +43,25 @@ func testPhiControl() {
}
}
func emptyRange_ssa(b []byte) bool {
for _, x := range b {
_ = x
}
return true
}
func testEmptyRange() {
if !emptyRange_ssa([]byte{}) {
println("emptyRange_ssa([]byte{})=false, want true")
failed = true
}
}
var failed = false
func main() {
testPhiControl()
testEmptyRange()
if failed {
panic("failed")
}
......
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