1
0
mirror of https://github.com/golang/go synced 2024-11-19 02:24:41 -07:00

5g, 6g, 8g: generate code for string index

instead of calling function.

R=ken2
CC=golang-dev
https://golang.org/cl/2762041
This commit is contained in:
Russ Cox 2010-10-26 21:11:17 -07:00
parent 705c0382e8
commit e48c0fb562
14 changed files with 117 additions and 69 deletions

View File

@ -558,9 +558,11 @@ agen(Node *n, Node *res)
p2 = nil; // to be patched to panicindex. p2 = nil; // to be patched to panicindex.
w = n->type->width; w = n->type->width;
if(nr->addable) { if(nr->addable) {
agenr(nl, &n3, res); if(!isconst(nr, CTINT))
if(!isconst(nr, CTINT)) {
tempname(&tmp, types[TINT32]); tempname(&tmp, types[TINT32]);
if(!isconst(nl, CTSTR))
agenr(nl, &n3, res);
if(!isconst(nr, CTINT)) {
p2 = cgenindex(nr, &tmp); p2 = cgenindex(nr, &tmp);
regalloc(&n1, tmp.type, N); regalloc(&n1, tmp.type, N);
gmove(&tmp, &n1); gmove(&tmp, &n1);
@ -572,13 +574,16 @@ agen(Node *n, Node *res)
regalloc(&n1, tmp.type, N); regalloc(&n1, tmp.type, N);
gmove(&tmp, &n1); gmove(&tmp, &n1);
} }
regalloc(&n3, types[tptr], res); if(!isconst(nl, CTSTR)) {
agen(nl, &n3); regalloc(&n3, types[tptr], res);
agen(nl, &n3);
}
} else { } else {
tempname(&tmp, types[TINT32]); tempname(&tmp, types[TINT32]);
p2 = cgenindex(nr, &tmp); p2 = cgenindex(nr, &tmp);
nr = &tmp; nr = &tmp;
agenr(nl, &n3, res); if(!isconst(nl, CTSTR))
agenr(nl, &n3, res);
regalloc(&n1, tmp.type, N); regalloc(&n1, tmp.type, N);
gins(optoas(OAS, tmp.type), &tmp, &n1); gins(optoas(OAS, tmp.type), &tmp, &n1);
} }
@ -592,9 +597,10 @@ agen(Node *n, Node *res)
// constant index // constant index
if(isconst(nr, CTINT)) { if(isconst(nr, CTINT)) {
if(isconst(nl, CTSTR))
fatal("constant string constant index");
v = mpgetfix(nr->val.u.xval); v = mpgetfix(nr->val.u.xval);
if(isslice(nl->type)) { if(isslice(nl->type) || nl->type->etype == TSTRING) {
if(!debug['B'] && !n->etype) { if(!debug['B'] && !n->etype) {
n1 = n3; n1 = n3;
n1.op = OINDREG; n1.op = OINDREG;
@ -638,7 +644,10 @@ agen(Node *n, Node *res)
if(!debug['B'] && !n->etype) { if(!debug['B'] && !n->etype) {
// check bounds // check bounds
regalloc(&n4, types[TUINT32], N); regalloc(&n4, types[TUINT32], N);
if(isslice(nl->type)) { if(isconst(nl, CTSTR)) {
nodconst(&n1, types[TUINT32], nl->val.u.sval->len);
gmove(&n1, &n4);
} else if(isslice(nl->type) || nl->type->etype == TSTRING) {
n1 = n3; n1 = n3;
n1.op = OINDREG; n1.op = OINDREG;
n1.type = types[tptr]; n1.type = types[tptr];
@ -656,8 +665,13 @@ agen(Node *n, Node *res)
ginscall(panicindex, 0); ginscall(panicindex, 0);
patch(p1, pc); patch(p1, pc);
} }
if(isslice(nl->type)) { if(isconst(nl, CTSTR)) {
regalloc(&n3, types[tptr], res);
p1 = gins(AMOVW, N, &n3);
datastring(nl->val.u.sval->s, nl->val.u.sval->len, &p1->from);
p1->from.type = D_CONST;
} else if(isslice(nl->type) || nl->type->etype == TSTRING) {
n1 = n3; n1 = n3;
n1.op = OINDREG; n1.op = OINDREG;
n1.type = types[tptr]; n1.type = types[tptr];
@ -795,12 +809,8 @@ igen(Node *n, Node *a, Node *res)
void void
agenr(Node *n, Node *a, Node *res) agenr(Node *n, Node *a, Node *res)
{ {
Node n1;
tempname(&n1, types[tptr]);
agen(n, &n1);
regalloc(a, types[tptr], res); regalloc(a, types[tptr], res);
gmove(&n1, a); agen(n, a);
} }
/* /*

View File

@ -1678,6 +1678,8 @@ sudoaddable(int as, Node *n, Addr *a, int *w)
goto odot; goto odot;
case OINDEX: case OINDEX:
if(n->left->type->etype == TSTRING)
return 0;
cleani += 2; cleani += 2;
reg = &clean[cleani-1]; reg = &clean[cleani-1];
reg1 = &clean[cleani-2]; reg1 = &clean[cleani-2];

View File

@ -477,8 +477,10 @@ agen(Node *n, Node *res)
regalloc(&n1, nr->type, N); regalloc(&n1, nr->type, N);
cgen(nr, &n1); cgen(nr, &n1);
} }
regalloc(&n3, types[tptr], res); if(!isconst(nl, CTSTR)) {
agen(nl, &n3); regalloc(&n3, types[tptr], res);
agen(nl, &n3);
}
goto index; goto index;
} }
tempname(&tmp, nr->type); tempname(&tmp, nr->type);
@ -486,8 +488,10 @@ agen(Node *n, Node *res)
nr = &tmp; nr = &tmp;
irad: irad:
regalloc(&n3, types[tptr], res); if(!isconst(nl, CTSTR)) {
agen(nl, &n3); regalloc(&n3, types[tptr], res);
agen(nl, &n3);
}
if(!isconst(nr, CTINT)) { if(!isconst(nr, CTINT)) {
regalloc(&n1, nr->type, N); regalloc(&n1, nr->type, N);
cgen(nr, &n1); cgen(nr, &n1);
@ -501,7 +505,7 @@ agen(Node *n, Node *res)
// explicit check for nil if array is large enough // explicit check for nil if array is large enough
// that we might derive too big a pointer. // that we might derive too big a pointer.
if(!isslice(nl->type) && nl->type->width >= unmappedzero) { if(isfixedarray(nl->type) && nl->type->width >= unmappedzero) {
regalloc(&n4, types[tptr], &n3); regalloc(&n4, types[tptr], &n3);
gmove(&n3, &n4); gmove(&n3, &n4);
n4.op = OINDREG; n4.op = OINDREG;
@ -516,8 +520,10 @@ agen(Node *n, Node *res)
// constant index // constant index
if(isconst(nr, CTINT)) { if(isconst(nr, CTINT)) {
if(isconst(nl, CTSTR))
fatal("constant string constant index"); // front end should handle
v = mpgetfix(nr->val.u.xval); v = mpgetfix(nr->val.u.xval);
if(isslice(nl->type)) { if(isslice(nl->type) || nl->type->etype == TSTRING) {
if(!debug['B'] && !n->etype) { if(!debug['B'] && !n->etype) {
n1 = n3; n1 = n3;
n1.op = OINDREG; n1.op = OINDREG;
@ -556,20 +562,21 @@ agen(Node *n, Node *res)
// check bounds // check bounds
n5.op = OXXX; n5.op = OXXX;
t = types[TUINT32]; t = types[TUINT32];
if(isslice(nl->type)) { if(is64(nr->type))
t = types[TUINT64];
if(isconst(nl, CTSTR)) {
nodconst(&n1, t, nl->val.u.sval->len);
} else if(isslice(nl->type) || nl->type->etype == TSTRING) {
n1 = n3; n1 = n3;
n1.op = OINDREG; n1.op = OINDREG;
n1.type = types[TUINT32]; n1.type = types[TUINT32];
n1.xoffset = Array_nel; n1.xoffset = Array_nel;
if(is64(nr->type)) { if(is64(nr->type)) {
t = types[TUINT64];
regalloc(&n5, t, N); regalloc(&n5, t, N);
gmove(&n1, &n5); gmove(&n1, &n5);
n1 = n5; n1 = n5;
} }
} else { } else {
if(is64(nr->type))
t = types[TUINT64];
nodconst(&n1, t, nl->type->bound); nodconst(&n1, t, nl->type->bound);
} }
gins(optoas(OCMP, t), &n2, &n1); gins(optoas(OCMP, t), &n2, &n1);
@ -580,7 +587,16 @@ agen(Node *n, Node *res)
patch(p1, pc); patch(p1, pc);
} }
if(isslice(nl->type)) { if(isconst(nl, CTSTR)) {
regalloc(&n3, types[tptr], res);
p1 = gins(ALEAQ, N, &n3);
datastring(nl->val.u.sval->s, nl->val.u.sval->len, &p1->from);
p1->from.scale = 1;
p1->from.index = n2.val.u.reg;
goto indexdone;
}
if(isslice(nl->type) || nl->type->etype == TSTRING) {
n1 = n3; n1 = n3;
n1.op = OINDREG; n1.op = OINDREG;
n1.type = types[tptr]; n1.type = types[tptr];
@ -599,6 +615,7 @@ agen(Node *n, Node *res)
gmove(&n3, res); gmove(&n3, res);
} }
indexdone:
gmove(&n3, res); gmove(&n3, res);
regfree(&n2); regfree(&n2);
regfree(&n3); regfree(&n3);

View File

@ -1784,6 +1784,8 @@ sudoaddable(int as, Node *n, Addr *a)
goto odot; goto odot;
case OINDEX: case OINDEX:
if(n->left->type->etype == TSTRING)
return 0;
goto oindex; goto oindex;
} }
return 0; return 0;

View File

@ -230,8 +230,8 @@ cgen(Node *n, Node *res)
cgen(nl, res); cgen(nl, res);
break; break;
} }
mgen(nl, &n1, res);
tempname(&n2, n->type); tempname(&n2, n->type);
mgen(nl, &n1, res);
gmove(&n1, &n2); gmove(&n1, &n2);
gmove(&n2, res); gmove(&n2, res);
mfree(&n1); mfree(&n1);
@ -518,9 +518,11 @@ agen(Node *n, Node *res)
p2 = nil; // to be patched to panicindex. p2 = nil; // to be patched to panicindex.
w = n->type->width; w = n->type->width;
if(nr->addable) { if(nr->addable) {
agenr(nl, &n3, res); if(!isconst(nr, CTINT))
if(!isconst(nr, CTINT)) {
tempname(&tmp, types[TINT32]); tempname(&tmp, types[TINT32]);
if(!isconst(nl, CTSTR))
agenr(nl, &n3, res);
if(!isconst(nr, CTINT)) {
p2 = cgenindex(nr, &tmp); p2 = cgenindex(nr, &tmp);
regalloc(&n1, tmp.type, N); regalloc(&n1, tmp.type, N);
gmove(&tmp, &n1); gmove(&tmp, &n1);
@ -532,13 +534,16 @@ agen(Node *n, Node *res)
regalloc(&n1, tmp.type, N); regalloc(&n1, tmp.type, N);
gmove(&tmp, &n1); gmove(&tmp, &n1);
} }
regalloc(&n3, types[tptr], res); if(!isconst(nl, CTSTR)) {
agen(nl, &n3); regalloc(&n3, types[tptr], res);
agen(nl, &n3);
}
} else { } else {
tempname(&tmp, types[TINT32]); tempname(&tmp, types[TINT32]);
p2 = cgenindex(nr, &tmp); p2 = cgenindex(nr, &tmp);
nr = &tmp; nr = &tmp;
agenr(nl, &n3, res); if(!isconst(nl, CTSTR))
agenr(nl, &n3, res);
regalloc(&n1, tmp.type, N); regalloc(&n1, tmp.type, N);
gins(optoas(OAS, tmp.type), &tmp, &n1); gins(optoas(OAS, tmp.type), &tmp, &n1);
} }
@ -549,7 +554,7 @@ agen(Node *n, Node *res)
// explicit check for nil if array is large enough // explicit check for nil if array is large enough
// that we might derive too big a pointer. // that we might derive too big a pointer.
if(!isslice(nl->type) && nl->type->width >= unmappedzero) { if(isfixedarray(nl->type) && nl->type->width >= unmappedzero) {
regalloc(&n4, types[tptr], &n3); regalloc(&n4, types[tptr], &n3);
gmove(&n3, &n4); gmove(&n3, &n4);
n4.op = OINDREG; n4.op = OINDREG;
@ -564,9 +569,10 @@ agen(Node *n, Node *res)
// constant index // constant index
if(isconst(nr, CTINT)) { if(isconst(nr, CTINT)) {
if(isconst(nl, CTSTR))
fatal("constant string constant index");
v = mpgetfix(nr->val.u.xval); v = mpgetfix(nr->val.u.xval);
if(isslice(nl->type)) { if(isslice(nl->type) || nl->type->etype == TSTRING) {
if(!debug['B'] && !n->etype) { if(!debug['B'] && !n->etype) {
n1 = n3; n1 = n3;
n1.op = OINDREG; n1.op = OINDREG;
@ -600,7 +606,9 @@ agen(Node *n, Node *res)
if(!debug['B'] && !n->etype) { if(!debug['B'] && !n->etype) {
// check bounds // check bounds
if(isslice(nl->type)) { if(isconst(nl, CTSTR))
nodconst(&n1, types[TUINT32], nl->val.u.sval->len);
else if(isslice(nl->type) || nl->type->etype == TSTRING) {
n1 = n3; n1 = n3;
n1.op = OINDREG; n1.op = OINDREG;
n1.type = types[tptr]; n1.type = types[tptr];
@ -614,8 +622,17 @@ agen(Node *n, Node *res)
ginscall(panicindex, 0); ginscall(panicindex, 0);
patch(p1, pc); patch(p1, pc);
} }
if(isconst(nl, CTSTR)) {
regalloc(&n3, types[tptr], res);
p1 = gins(ALEAL, N, &n3);
datastring(nl->val.u.sval->s, nl->val.u.sval->len, &p1->from);
p1->from.scale = 1;
p1->from.index = n2.val.u.reg;
goto indexdone;
}
if(isslice(nl->type)) { if(isslice(nl->type) || nl->type->etype == TSTRING) {
n1 = n3; n1 = n3;
n1.op = OINDREG; n1.op = OINDREG;
n1.type = types[tptr]; n1.type = types[tptr];
@ -635,6 +652,7 @@ agen(Node *n, Node *res)
gmove(&n3, res); gmove(&n3, res);
} }
indexdone:
gmove(&n3, res); gmove(&n3, res);
regfree(&n2); regfree(&n2);
regfree(&n3); regfree(&n3);
@ -710,8 +728,14 @@ igen(Node *n, Node *a, Node *res)
{ {
Node n1; Node n1;
// release register for now, to avoid
// confusing tempname.
if(res != N && res->op == OREGISTER)
reg[res->val.u.reg]--;
tempname(&n1, types[tptr]); tempname(&n1, types[tptr]);
agen(n, &n1); agen(n, &n1);
if(res != N && res->op == OREGISTER)
reg[res->val.u.reg]++;
regalloc(a, types[tptr], res); regalloc(a, types[tptr], res);
gmove(&n1, a); gmove(&n1, a);
a->op = OINDREG; a->op = OINDREG;

View File

@ -789,6 +789,8 @@ mkvar(Reg *r, Adr *a)
// if they overlaps, disable both // if they overlaps, disable both
if(overlap(v->offset, v->width, o, w)) { if(overlap(v->offset, v->width, o, w)) {
if(debug['R'])
print("disable %s\n", v->sym->name);
v->addr = 1; v->addr = 1;
flag = 1; flag = 1;
} }
@ -821,7 +823,7 @@ mkvar(Reg *r, Adr *a)
v->addr = flag; // funny punning v->addr = flag; // funny punning
if(debug['R']) if(debug['R'])
print("bit=%2d et=%2d w=%d %S %D\n", i, et, w, s, a); print("bit=%2d et=%2d w=%d %S %D flag=%d\n", i, et, w, s, a, v->addr);
ostats.nvar++; ostats.nvar++;
bit = blsh(i); bit = blsh(i);

View File

@ -24,7 +24,6 @@ char *runtimeimport =
"func \"\".cmpstring (? string, ? string) int\n" "func \"\".cmpstring (? string, ? string) int\n"
"func \"\".slicestring (? string, ? int, ? int) string\n" "func \"\".slicestring (? string, ? int, ? int) string\n"
"func \"\".slicestring1 (? string, ? int) string\n" "func \"\".slicestring1 (? string, ? int) string\n"
"func \"\".indexstring (? string, ? int) uint8\n"
"func \"\".intstring (? int64) string\n" "func \"\".intstring (? int64) string\n"
"func \"\".slicebytetostring (? []uint8) string\n" "func \"\".slicebytetostring (? []uint8) string\n"
"func \"\".sliceinttostring (? []int) string\n" "func \"\".sliceinttostring (? []int) string\n"

View File

@ -652,7 +652,6 @@ tempname(Node *n, Type *t)
snprint(namebuf, sizeof(namebuf), "autotmp_%.4d", statuniqgen); snprint(namebuf, sizeof(namebuf), "autotmp_%.4d", statuniqgen);
statuniqgen++; statuniqgen++;
s = lookup(namebuf); s = lookup(namebuf);
memset(n, 0, sizeof(*n)); memset(n, 0, sizeof(*n));
n->op = ONAME; n->op = ONAME;
n->sym = s; n->sym = s;

View File

@ -369,7 +369,7 @@ enum
ODOTTYPE2, ODOTTYPE2,
OEQ, ONE, OLT, OLE, OGE, OGT, OEQ, ONE, OLT, OLE, OGE, OGT,
OIND, OIND,
OINDEX, OINDEXSTR, OINDEXMAP, OINDEX, OINDEXMAP,
OKEY, OPARAM, OKEY, OPARAM,
OLEN, OLEN,
OMAKE, OMAKECHAN, OMAKEMAP, OMAKESLICE, OMAKE, OMAKECHAN, OMAKEMAP, OMAKESLICE,

View File

@ -59,6 +59,9 @@ exprfmt(Fmt *f, Node *n, int prec)
case OPRINT: case OPRINT:
case OPRINTN: case OPRINTN:
case OCALL: case OCALL:
case OCALLMETH:
case OCALLINTER:
case OCALLFUNC:
case OCONV: case OCONV:
case OCONVNOP: case OCONVNOP:
case OMAKESLICE: case OMAKESLICE:
@ -72,6 +75,8 @@ exprfmt(Fmt *f, Node *n, int prec)
case ORECV: case ORECV:
case OCONVIFACE: case OCONVIFACE:
case OTPAREN: case OTPAREN:
case OINDEX:
case OINDEXMAP:
nprec = 7; nprec = 7;
break; break;
@ -328,7 +333,6 @@ exprfmt(Fmt *f, Node *n, int prec)
case OINDEX: case OINDEX:
case OINDEXMAP: case OINDEXMAP:
case OINDEXSTR:
exprfmt(f, n->left, 7); exprfmt(f, n->left, 7);
fmtprint(f, "["); fmtprint(f, "[");
exprfmt(f, n->right, 0); exprfmt(f, n->right, 0);

View File

@ -39,7 +39,6 @@ func concatstring()
func cmpstring(string, string) int func cmpstring(string, string) int
func slicestring(string, int, int) string func slicestring(string, int, int) string
func slicestring1(string, int) string func slicestring1(string, int) string
func indexstring(string, int) byte
func intstring(int64) string func intstring(int64) string
func slicebytetostring([]byte) string func slicebytetostring([]byte) string
func sliceinttostring([]int) string func sliceinttostring([]int) string

View File

@ -614,7 +614,6 @@ reswitch:
if(n->right->type != T && !isint[n->right->type->etype]) if(n->right->type != T && !isint[n->right->type->etype])
yyerror("non-integer string index %#N", n->right); yyerror("non-integer string index %#N", n->right);
n->type = types[TUINT8]; n->type = types[TUINT8];
n->op = OINDEXSTR;
break; break;
} }
goto ret; goto ret;
@ -2052,6 +2051,8 @@ islvalue(Node *n)
case OINDEX: case OINDEX:
if(isfixedarray(n->left->type)) if(isfixedarray(n->left->type))
return islvalue(n->left); return islvalue(n->left);
if(n->left->type != T && n->left->type->etype == TSTRING)
return 0;
// fall through // fall through
case OIND: case OIND:
case ODOTPTR: case ODOTPTR:

View File

@ -1033,22 +1033,35 @@ walkexpr(Node **np, NodeList **init)
// if range of type cannot exceed static array bound, // if range of type cannot exceed static array bound,
// disable bounds check // disable bounds check
if(!isslice(n->left->type)) if(isfixedarray(n->left->type))
if(n->right->type->width < 4) if(n->right->type->width < 4)
if((1<<(8*n->right->type->width)) <= n->left->type->bound) if((1<<(8*n->right->type->width)) <= n->left->type->bound)
n->etype = 1; 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 // check for static out of bounds
if(isconst(n->right, CTINT) && !n->etype) { if(isconst(n->right, CTINT) && !n->etype) {
v = mpgetfix(n->right->val.u.xval); v = mpgetfix(n->right->val.u.xval);
len = 1LL<<60; len = 1LL<<60;
t = n->left->type; t = n->left->type;
if(isconst(n->left, CTSTR))
len = n->left->val.u.sval->len;
if(t != T && isptr[t->etype]) if(t != T && isptr[t->etype])
t = t->type; t = t->type;
if(isfixedarray(t)) if(isfixedarray(t))
len = t->bound; len = t->bound;
if(v < 0 || v >= (1LL<<31) || v >= len) if(v < 0 || v >= (1LL<<31) || v >= len)
yyerror("index out of bounds"); 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; goto ret;
@ -1252,14 +1265,6 @@ walkexpr(Node **np, NodeList **init)
} }
goto ret; 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: case OCOPY:
if(n->right->type->etype == TSTRING) if(n->right->type->etype == TSTRING)
fn = syslook("slicestringcopy", 1); fn = syslook("slicestringcopy", 1);

View File

@ -200,10 +200,6 @@ func slicestring(si String, lindex int32, hindex int32) (so String) {
l = hindex-lindex; l = hindex-lindex;
so.str = si.str + lindex; so.str = si.str + lindex;
so.len = l; so.len = l;
// alternate to create a new string
// so = gostringsize(l);
// mcpy(so.str, si.str+lindex, l);
} }
func slicestring1(si String, lindex int32) (so String) { func slicestring1(si String, lindex int32) (so String) {
@ -216,18 +212,6 @@ func slicestring1(si String, lindex int32) (so String) {
l = si.len-lindex; l = si.len-lindex;
so.str = si.str + lindex; so.str = si.str + lindex;
so.len = l; so.len = l;
// alternate to create a new string
// so = gostringsize(l);
// mcpy(so.str, si.str+lindex, l);
}
func indexstring(s String, i int32) (b byte) {
if(i < 0 || i >= s.len) {
·panicindex();
}
b = s.str[i];
} }
func intstring(v int64) (s String) { func intstring(v int64) (s String) {