[dev.ssa] cmd/compile/internal/ssa: minor fixes

* Improve some docs and logging.
* Set correct type and len for indexing into strings.

Fixes #11029.

Change-Id: Ib22c45908e41ba3752010d2f5759e37e3921a48e
Reviewed-on: https://go-review.googlesource.com/10635
Reviewed-by: Keith Randall <khr@golang.org>
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index 3c95266..fd1c30e 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -327,11 +327,20 @@
 		return s.curBlock.NewValue2(ssa.OpLoad, n.Type, nil, p, s.mem())
 
 	case OINDEX:
-		if n.Left.Type.Bound >= 0 { // array
+		if n.Left.Type.Bound >= 0 { // array or string
 			a := s.expr(n.Left)
 			i := s.expr(n.Right)
-			s.boundsCheck(i, s.f.ConstInt(s.config.Uintptr, n.Left.Type.Bound))
-			return s.curBlock.NewValue2(ssa.OpArrayIndex, n.Left.Type.Type, nil, a, i)
+			var elemtype *Type
+			var len *ssa.Value
+			if n.Left.Type.IsString() {
+				len = s.curBlock.NewValue1(ssa.OpStringLen, s.config.Uintptr, nil, a)
+				elemtype = Types[TUINT8]
+			} else {
+				len = s.f.ConstInt(s.config.Uintptr, n.Left.Type.Bound)
+				elemtype = n.Left.Type.Type
+			}
+			s.boundsCheck(i, len)
+			return s.curBlock.NewValue2(ssa.OpArrayIndex, elemtype, nil, a, i)
 		} else { // slice
 			p := s.addr(n)
 			return s.curBlock.NewValue2(ssa.OpLoad, n.Left.Type.Type, nil, p, s.mem())
@@ -367,7 +376,7 @@
 	}
 }
 
-// expr converts the address of the expression n to SSA, adds it to s and returns the SSA result.
+// addr converts the address of the expression n to SSA, adds it to s and returns the SSA result.
 func (s *state) addr(n *Node) *ssa.Value {
 	switch n.Op {
 	case ONAME:
@@ -402,7 +411,7 @@
 			return s.curBlock.NewValue2(ssa.OpPtrIndex, Ptrto(n.Left.Type.Type), nil, p, i)
 		}
 	default:
-		log.Fatalf("addr: bad op %v", n.Op)
+		log.Fatalf("addr: bad op %v", Oconv(int(n.Op), 0))
 		return nil
 	}
 }