[dev.ssa] cmd/compile/internal/ssa: fix string index
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>
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index 70350e0..0551ddb 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -1693,19 +1693,22 @@
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 {
+ len := s.constInt(Types[TINT], n.Left.Type.Bound)
+ s.boundsCheck(i, len)
+ }
+ return s.newValue2(ssa.OpArrayIndex, n.Left.Type.Type, a, i)
}
- if !n.Bounded {
- s.boundsCheck(i, len)
- }
- 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())
diff --git a/src/cmd/compile/internal/gc/testdata/string_ssa.go b/src/cmd/compile/internal/gc/testdata/string_ssa.go
index 448433a..0ff6ce1 100644
--- a/src/cmd/compile/internal/gc/testdata/string_ssa.go
+++ b/src/cmd/compile/internal/gc/testdata/string_ssa.go
@@ -70,6 +70,7 @@
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 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")