5g, 6g, 8g: generate code for string index
instead of calling function.

R=ken2
CC=golang-dev
https://golang.org/cl/2762041
diff --git a/src/cmd/gc/builtin.c.boot b/src/cmd/gc/builtin.c.boot
index bb1a5f5..10559a9 100644
--- a/src/cmd/gc/builtin.c.boot
+++ b/src/cmd/gc/builtin.c.boot
@@ -24,7 +24,6 @@
 	"func \"\".cmpstring (? string, ? string) int\n"
 	"func \"\".slicestring (? string, ? int, ? int) string\n"
 	"func \"\".slicestring1 (? string, ? int) string\n"
-	"func \"\".indexstring (? string, ? int) uint8\n"
 	"func \"\".intstring (? int64) string\n"
 	"func \"\".slicebytetostring (? []uint8) string\n"
 	"func \"\".sliceinttostring (? []int) string\n"
diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c
index d2396aa..65861c7 100644
--- a/src/cmd/gc/gen.c
+++ b/src/cmd/gc/gen.c
@@ -652,7 +652,6 @@
 	snprint(namebuf, sizeof(namebuf), "autotmp_%.4d", statuniqgen);
 	statuniqgen++;
 	s = lookup(namebuf);
-
 	memset(n, 0, sizeof(*n));
 	n->op = ONAME;
 	n->sym = s;
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index 78472d2..91a1562 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -369,7 +369,7 @@
 	ODOTTYPE2,
 	OEQ, ONE, OLT, OLE, OGE, OGT,
 	OIND,
-	OINDEX, OINDEXSTR, OINDEXMAP,
+	OINDEX, OINDEXMAP,
 	OKEY, OPARAM,
 	OLEN,
 	OMAKE, OMAKECHAN, OMAKEMAP, OMAKESLICE,
diff --git a/src/cmd/gc/print.c b/src/cmd/gc/print.c
index 32e8b7d..478aa84 100644
--- a/src/cmd/gc/print.c
+++ b/src/cmd/gc/print.c
@@ -59,6 +59,9 @@
 	case OPRINT:
 	case OPRINTN:
 	case OCALL:
+	case OCALLMETH:
+	case OCALLINTER:
+	case OCALLFUNC:
 	case OCONV:
 	case OCONVNOP:
 	case OMAKESLICE:
@@ -72,6 +75,8 @@
 	case ORECV:
 	case OCONVIFACE:
 	case OTPAREN:
+	case OINDEX:
+	case OINDEXMAP:
 		nprec = 7;
 		break;
 
@@ -328,7 +333,6 @@
 
 	case OINDEX:
 	case OINDEXMAP:
-	case OINDEXSTR:
 		exprfmt(f, n->left, 7);
 		fmtprint(f, "[");
 		exprfmt(f, n->right, 0);
diff --git a/src/cmd/gc/runtime.go b/src/cmd/gc/runtime.go
index 2279384..1be706f 100644
--- a/src/cmd/gc/runtime.go
+++ b/src/cmd/gc/runtime.go
@@ -39,7 +39,6 @@
 func cmpstring(string, string) int
 func slicestring(string, int, int) string
 func slicestring1(string, int) string
-func indexstring(string, int) byte
 func intstring(int64) string
 func slicebytetostring([]byte) string
 func sliceinttostring([]int) string
diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c
index 6148337..c4f0826 100644
--- a/src/cmd/gc/typecheck.c
+++ b/src/cmd/gc/typecheck.c
@@ -614,7 +614,6 @@
 			if(n->right->type != T && !isint[n->right->type->etype])
 				yyerror("non-integer string index %#N", n->right);
 			n->type = types[TUINT8];
-			n->op = OINDEXSTR;
 			break;
 		}
 		goto ret;
@@ -2052,6 +2051,8 @@
 	case OINDEX:
 		if(isfixedarray(n->left->type))
 			return islvalue(n->left);
+		if(n->left->type != T && n->left->type->etype == TSTRING)
+			return 0;
 		// fall through
 	case OIND:
 	case ODOTPTR:
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index bf20102..757b6d9 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -1033,22 +1033,35 @@
 
 		// if range of type cannot exceed static array bound,
 		// disable bounds check
-		if(!isslice(n->left->type))
+		if(isfixedarray(n->left->type))
 		if(n->right->type->width < 4)
 		if((1<<(8*n->right->type->width)) <= n->left->type->bound)
 			n->etype = 1;
 
+		if(isconst(n->left, CTSTR))
+		if(n->right->type->width < 4)
+		if((1<<(8*n->right->type->width)) <= n->left->val.u.sval->len)
+			n->etype = 1;
+
 		// check for static out of bounds
 		if(isconst(n->right, CTINT) && !n->etype) {
 			v = mpgetfix(n->right->val.u.xval);
 			len = 1LL<<60;
 			t = n->left->type;
+			if(isconst(n->left, CTSTR))
+				len = n->left->val.u.sval->len;
 			if(t != T && isptr[t->etype])
 				t = t->type;
 			if(isfixedarray(t))
 				len = t->bound;
 			if(v < 0 || v >= (1LL<<31) || v >= len)
 				yyerror("index out of bounds");
+			else if(isconst(n->left, CTSTR)) {
+				// replace "abc"[2] with 'b'.
+				// delayed until now because "abc"[2] is not
+				// an ideal constant.
+				nodconst(n, n->type, n->left->val.u.sval->s[v]);
+			}
 		}
 		goto ret;
 
@@ -1252,14 +1265,6 @@
 		}
 		goto ret;
 
-	case OINDEXSTR:
-		// TODO(rsc): should be done in back end
-		// sys_indexstring(s, i)
-		n = mkcall("indexstring", n->type, init,
-			conv(n->left, types[TSTRING]),
-			conv(n->right, types[TINT]));
-		goto ret;
-
 	case OCOPY:
 		if(n->right->type->etype == TSTRING)
 			fn = syslook("slicestringcopy", 1);