]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.ssa] cmd/compile: used Bounded field to fix empty range loops
authorKeith Randall <khr@golang.org>
Tue, 18 Aug 2015 21:17:30 +0000 (14:17 -0700)
committerKeith Randall <khr@golang.org>
Wed, 19 Aug 2015 21:44:44 +0000 (21:44 +0000)
    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/13685
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
src/cmd/compile/internal/gc/ssa.go
src/cmd/compile/internal/gc/testdata/ctl_ssa.go

index f2dd20bcb4f5c13639e7f772fcbc1158fdfc7645..6a5ecbf04d569598c82385e6fd4653584f27e08b 100644 (file)
@@ -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:
index 7377c9aee8a95e4448904ba0cbd05c9c6932394e..f7c3b807990406c277d2bbc0178aba86e38f9720 100644 (file)
@@ -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")
        }