]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.ssa] cmd/compile/internal/ssa: fix string index
authorKeith Randall <khr@golang.org>
Thu, 10 Sep 2015 17:01:15 +0000 (10:01 -0700)
committerKeith Randall <khr@golang.org>
Mon, 14 Sep 2015 05:14:51 +0000 (05:14 +0000)
Change-Id: I984d3e0410ac38c4e42ae8e3670ea47e2140de76
Reviewed-on: https://go-review.googlesource.com/14466
Reviewed-by: Alexandru Moșoi <alexandru@mosoi.ro>
Reviewed-by: Todd Neal <todd@tneal.org>
src/cmd/compile/internal/gc/ssa.go
src/cmd/compile/internal/gc/testdata/string_ssa.go

index 70350e0e2cf63f5cf80c14f9dfbebd1f1cdc6815..0551ddbf083977fdb1f3ca153816ca07d8ffa232 100644 (file)
@@ -1693,19 +1693,22 @@ func (s *state) expr(n *Node) *ssa.Value {
                        a := s.expr(n.Left)
                        i := s.expr(n.Right)
                        i = s.extendIndex(i)
-                       var elemtype *Type
-                       var len *ssa.Value
                        if n.Left.Type.IsString() {
-                               len = s.newValue1(ssa.OpStringLen, Types[TINT], a)
-                               elemtype = Types[TUINT8]
+                               if !n.Bounded {
+                                       len := s.newValue1(ssa.OpStringLen, Types[TINT], a)
+                                       s.boundsCheck(i, len)
+                               }
+                               ptrtyp := Ptrto(Types[TUINT8])
+                               ptr := s.newValue1(ssa.OpStringPtr, ptrtyp, a)
+                               ptr = s.newValue2(ssa.OpAddPtr, ptrtyp, ptr, i)
+                               return s.newValue2(ssa.OpLoad, Types[TUINT8], ptr, s.mem())
                        } else {
-                               len = s.constInt(Types[TINT], n.Left.Type.Bound)
-                               elemtype = n.Left.Type.Type
-                       }
-                       if !n.Bounded {
-                               s.boundsCheck(i, len)
+                               if !n.Bounded {
+                                       len := s.constInt(Types[TINT], n.Left.Type.Bound)
+                                       s.boundsCheck(i, len)
+                               }
+                               return s.newValue2(ssa.OpArrayIndex, n.Left.Type.Type, a, i)
                        }
-                       return s.newValue2(ssa.OpArrayIndex, elemtype, a, i)
                } else { // slice
                        p := s.addr(n)
                        return s.newValue2(ssa.OpLoad, n.Left.Type.Type, p, s.mem())
index 448433acd3e8e127fe71a1d2077925cf7baa85cd..0ff6ce1a12bf910aaf0a87b3e7ac7848a7effb1c 100644 (file)
@@ -70,6 +70,7 @@ func testStructSlice() {
        p.slice_ssa()
        if "pre" != p.prefix {
                println("wrong field slice: wanted %s got %s", "pre", p.prefix)
+               failed = true
        }
 }
 
@@ -114,11 +115,51 @@ func testSmallIndexType() {
        }
 }
 
+func testStringElem_ssa(s string, i int) byte {
+       switch { // prevent inlining
+       }
+       return s[i]
+}
+
+func testStringElem() {
+       tests := []struct {
+               s string
+               i int
+               n byte
+       }{
+               {"foobar", 3, 98},
+               {"foobar", 0, 102},
+               {"foobar", 5, 114},
+       }
+       for _, t := range tests {
+               if got := testStringElem_ssa(t.s, t.i); got != t.n {
+                       print("testStringElem \"", t.s, "\"[", t.i, "]=", got, ", wanted ", t.n, "\n")
+                       failed = true
+               }
+       }
+}
+
+func testStringElemConst_ssa(i int) byte {
+       switch { // prevent inlining
+       }
+       s := "foobar"
+       return s[i]
+}
+
+func testStringElemConst() {
+       if got := testStringElemConst_ssa(3); got != 98 {
+               println("testStringElemConst=", got, ", wanted 98")
+               failed = true
+       }
+}
+
 func main() {
        testStringSlice()
        testStringSlicePanic()
        testStructSlice()
        testSmallIndexType()
+       testStringElem()
+       testStringElemConst()
 
        if failed {
                panic("failed")