mirror of https://github.com/golang/go.git
1. check for dups in complex literals
structtype{a:1, a:2}
maptypetype{"xx":1, "xx":2}
arraytypetype{5:1, 5:2}
2. bug in registerization concerning
alias of a struct and one of its elements
3. code optimization of struct.field
(which exposed bug in 2)
R=r
OCL=29315
CL=29315
This commit is contained in:
parent
368b42103e
commit
4238b18344
|
|
@ -106,6 +106,7 @@ cgen(Node *n, Node *res)
|
|||
|
||||
nl = n->left;
|
||||
nr = n->right;
|
||||
|
||||
if(nl != N && nl->ullman >= UINF)
|
||||
if(nr != N && nr->ullman >= UINF) {
|
||||
tempname(&n1, nl->type);
|
||||
|
|
@ -555,7 +556,6 @@ agen(Node *n, Node *res)
|
|||
break;
|
||||
|
||||
case ODOT:
|
||||
t = nl->type;
|
||||
agen(nl, res);
|
||||
if(n->xoffset != 0) {
|
||||
nodconst(&n1, types[TINT64], n->xoffset);
|
||||
|
|
@ -564,9 +564,6 @@ agen(Node *n, Node *res)
|
|||
break;
|
||||
|
||||
case ODOTPTR:
|
||||
t = nl->type;
|
||||
if(!isptr[t->etype])
|
||||
fatal("agen: not ptr %N", n);
|
||||
cgen(nl, res);
|
||||
if(n->xoffset != 0) {
|
||||
nodconst(&n1, types[TINT64], n->xoffset);
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ struct Addr
|
|||
char sval[NSNAME];
|
||||
|
||||
Sym* sym;
|
||||
int width;
|
||||
uchar type;
|
||||
uchar index;
|
||||
uchar etype;
|
||||
|
|
|
|||
|
|
@ -717,7 +717,7 @@ stataddr(Node *nam, Node *n)
|
|||
switch(n->op) {
|
||||
case ONAME:
|
||||
*nam = *n;
|
||||
return 1;
|
||||
return n->addable;
|
||||
|
||||
case ODOT:
|
||||
if(!stataddr(nam, n->left))
|
||||
|
|
|
|||
|
|
@ -1088,7 +1088,8 @@ naddr(Node *n, Addr *a)
|
|||
case OPARAM:
|
||||
// n->left is PHEAP ONAME for stack parameter.
|
||||
// compute address of actual parameter on stack.
|
||||
a->etype = n->left->type->etype;
|
||||
a->etype = simtype[n->left->type->etype];
|
||||
a->width = n->left->type->width;
|
||||
a->offset = n->xoffset;
|
||||
a->sym = n->left->sym;
|
||||
a->type = D_PARAM;
|
||||
|
|
@ -1096,8 +1097,11 @@ naddr(Node *n, Addr *a)
|
|||
|
||||
case ONAME:
|
||||
a->etype = 0;
|
||||
if(n->type != T)
|
||||
a->width = 0;
|
||||
if(n->type != T) {
|
||||
a->etype = simtype[n->type->etype];
|
||||
a->width = n->type->width;
|
||||
}
|
||||
a->offset = n->xoffset;
|
||||
a->sym = n->sym;
|
||||
if(a->sym == S)
|
||||
|
|
@ -1819,6 +1823,15 @@ odot:
|
|||
if(nn == N)
|
||||
goto no;
|
||||
|
||||
if(nn->addable && o == 1 && oary[0] >= 0) {
|
||||
// directly addressable set of DOTs
|
||||
n1 = *nn;
|
||||
n1.type = n->type;
|
||||
n1.xoffset += oary[0];
|
||||
naddr(&n1, a);
|
||||
goto yes;
|
||||
}
|
||||
|
||||
regalloc(reg, types[tptr], N);
|
||||
n1 = *reg;
|
||||
n1.op = OINDREG;
|
||||
|
|
|
|||
|
|
@ -752,7 +752,7 @@ Bits
|
|||
mkvar(Reg *r, Adr *a)
|
||||
{
|
||||
Var *v;
|
||||
int i, t, n, et, z;
|
||||
int i, t, n, et, z, w;
|
||||
int32 o;
|
||||
Bits bit;
|
||||
Sym *s;
|
||||
|
|
@ -787,31 +787,29 @@ mkvar(Reg *r, Adr *a)
|
|||
s = a->sym;
|
||||
if(s == S)
|
||||
goto none;
|
||||
// if(s->name[0] == '!')
|
||||
// goto none;
|
||||
if(s->name[0] == '.')
|
||||
goto none;
|
||||
et = a->etype;
|
||||
o = a->offset;
|
||||
w = a->width;
|
||||
v = var;
|
||||
for(i=0; i<nvar; i++) {
|
||||
if(s == v->sym)
|
||||
if(n == v->name)
|
||||
if(o == v->offset)
|
||||
goto out;
|
||||
v++;
|
||||
}
|
||||
|
||||
switch(et) {
|
||||
case 0:
|
||||
case TFUNC:
|
||||
case TARRAY:
|
||||
case 0:
|
||||
goto none;
|
||||
}
|
||||
|
||||
if(nvar >= NVAR) {
|
||||
if(debug['w'] > 1 && s)
|
||||
fatal("variable not optimized: %s", s->name);
|
||||
fatal("variable not optimized: %D", a);
|
||||
goto none;
|
||||
}
|
||||
i = nvar;
|
||||
|
|
@ -821,8 +819,9 @@ mkvar(Reg *r, Adr *a)
|
|||
v->offset = o;
|
||||
v->name = n;
|
||||
v->etype = et;
|
||||
v->width = w;
|
||||
if(debug['R'])
|
||||
print("bit=%2d et=%2d %D\n", i, et, a);
|
||||
print("bit=%2d et=%2d w=%d %D\n", i, et, w, a);
|
||||
ostats.nvar++;
|
||||
|
||||
out:
|
||||
|
|
@ -833,10 +832,17 @@ out:
|
|||
if(n == D_PARAM)
|
||||
for(z=0; z<BITS; z++)
|
||||
params.b[z] |= bit.b[z];
|
||||
if(v->etype != et) {
|
||||
|
||||
// this has horrible consequences -
|
||||
// no structure elements are registerized,
|
||||
// but i dont know how to be more specific
|
||||
if(v->etype != et || v->width != w || v->offset != o) {
|
||||
/* funny punning */
|
||||
if(debug['R'])
|
||||
print("pun %d %d %S\n", v->etype, et, s);
|
||||
print("pun et=%d/%d w=%d/%d o=%d/%d %D\n",
|
||||
v->etype, et,
|
||||
v->width, w,
|
||||
v->offset, o, a);
|
||||
for(z=0; z<BITS; z++)
|
||||
addrs.b[z] |= bit.b[z];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -434,6 +434,7 @@ struct Var
|
|||
{
|
||||
vlong offset;
|
||||
Sym* sym;
|
||||
int width;
|
||||
char name;
|
||||
char etype;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -41,14 +41,6 @@ initlin(Node* n)
|
|||
|
||||
case OCALL:
|
||||
// call to mapassign1
|
||||
if(n->left->op != ONAME ||
|
||||
n->right->op != OLIST ||
|
||||
n->right->left->op != OAS ||
|
||||
n->right->right->op != OLIST ||
|
||||
n->right->right->left->op != OAS ||
|
||||
n->right->right->right->op != OAS ||
|
||||
strcmp(n->left->sym->name, "mapassign1") != 0)
|
||||
dump("o=call", n);
|
||||
n->ninit = N;
|
||||
xxx.list = list(xxx.list, n);
|
||||
break;
|
||||
|
|
@ -72,7 +64,7 @@ inittmp(Node *n)
|
|||
if(n->op == ONAME)
|
||||
if(n->sym != S)
|
||||
if(n->class == PAUTO)
|
||||
if(strcmp(n->sym->name, "!tmpname!") == 0)
|
||||
if(memcmp(n->sym->name, "autotmp_", 8) == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -325,8 +317,9 @@ initfix(Node* n)
|
|||
xxx.list = N;
|
||||
initlin(n);
|
||||
xxx.list = rev(xxx.list);
|
||||
|
||||
if(1)
|
||||
return xxx.list;
|
||||
|
||||
if(debug['A'])
|
||||
dump("preinitfix", xxx.list);
|
||||
|
||||
|
|
|
|||
|
|
@ -2379,7 +2379,10 @@ tempname(Node *n, Type *t)
|
|||
t = types[TINT32];
|
||||
}
|
||||
|
||||
s = lookup("!tmpname!");
|
||||
// give each tmp a different name so that there
|
||||
// a chance to registerizer them
|
||||
snprint(namebuf, sizeof(namebuf), "autotmp_%.4d", statuniqgen);
|
||||
s = lookup(namebuf);
|
||||
|
||||
memset(n, 0, sizeof(*n));
|
||||
n->op = ONAME;
|
||||
|
|
|
|||
|
|
@ -3980,6 +3980,27 @@ reorder4(Node *n)
|
|||
return n;
|
||||
}
|
||||
|
||||
static void
|
||||
fielddup(Node *n, Node *hash[], ulong nhash)
|
||||
{
|
||||
uint h;
|
||||
char *s;
|
||||
Node *a;
|
||||
|
||||
if(n->op != ONAME)
|
||||
fatal("fielddup: not ONAME");
|
||||
s = n->sym->name;
|
||||
h = stringhash(s)%nhash;
|
||||
for(a=hash[h]; a!=N; a=a->ntest) {
|
||||
if(strcmp(a->sym->name, s) == 0) {
|
||||
yyerror("duplicate field name in struct literal: %s", s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
n->ntest = hash[h];
|
||||
hash[h] = n;
|
||||
}
|
||||
|
||||
Node*
|
||||
structlit(Node *n, Node *var)
|
||||
{
|
||||
|
|
@ -3987,6 +4008,7 @@ structlit(Node *n, Node *var)
|
|||
Type *l, *t;
|
||||
Node *r, *a;
|
||||
int mixflag;
|
||||
Node* hash[101];
|
||||
|
||||
t = n->type;
|
||||
if(t->etype != TSTRUCT)
|
||||
|
|
@ -4004,61 +4026,86 @@ structlit(Node *n, Node *var)
|
|||
return var;
|
||||
|
||||
mixflag = 0;
|
||||
if(r->op == OKEY) {
|
||||
a = nod(OAS, var, N);
|
||||
addtop = list(addtop, a);
|
||||
goto loop2;
|
||||
}
|
||||
if(r->op == OKEY)
|
||||
goto keyval;
|
||||
l = structfirst(&savel, &n->type);
|
||||
|
||||
loop1:
|
||||
// assignment to every field
|
||||
if(l == T || r == N) {
|
||||
if(l != T)
|
||||
yyerror("struct literal expect expr of type %T", l);
|
||||
if(r != N)
|
||||
yyerror("struct literal too many expressions");
|
||||
if(mixflag)
|
||||
yyerror("mixture of field:value initializers");
|
||||
return var;
|
||||
}
|
||||
if(r->op == OKEY) {
|
||||
mixflag = 1;
|
||||
goto incr1;
|
||||
}
|
||||
while(r != N) {
|
||||
// assignment to every field
|
||||
if(l == T)
|
||||
break;
|
||||
if(r->op == OKEY) {
|
||||
mixflag = 1; // defer diagnostic
|
||||
l = structnext(&savel);
|
||||
r = listnext(&saver);
|
||||
continue;
|
||||
}
|
||||
|
||||
// build list of var.field = expr
|
||||
a = nod(ODOT, var, newname(l->sym));
|
||||
a = nod(OAS, a, r);
|
||||
walktype(a, Etop);
|
||||
// build list of var.field = expr
|
||||
a = nod(ODOT, var, newname(l->sym));
|
||||
a = nod(OAS, a, r);
|
||||
walktype(a, Etop);
|
||||
addtop = list(addtop, a);
|
||||
|
||||
l = structnext(&savel);
|
||||
r = listnext(&saver);
|
||||
}
|
||||
if(l != T)
|
||||
yyerror("struct literal expect expr of type %T", l);
|
||||
if(r != N)
|
||||
yyerror("struct literal too many expressions");
|
||||
if(mixflag)
|
||||
yyerror("mixture of field:value initializers");
|
||||
return var;
|
||||
|
||||
keyval:
|
||||
memset(hash, 0, sizeof(hash));
|
||||
a = nod(OAS, var, N);
|
||||
addtop = list(addtop, a);
|
||||
|
||||
incr1:
|
||||
l = structnext(&savel);
|
||||
r = listnext(&saver);
|
||||
goto loop1;
|
||||
while(r != N) {
|
||||
// assignment to field:value elements
|
||||
if(r->op != OKEY) {
|
||||
mixflag = 1;
|
||||
r = listnext(&saver);
|
||||
continue;
|
||||
}
|
||||
|
||||
loop2:
|
||||
// assignment to field:value elements
|
||||
if(r == N) {
|
||||
if(mixflag)
|
||||
yyerror("mixture of field:value initializers");
|
||||
return var;
|
||||
// build list of var.field = expr
|
||||
a = nod(ODOT, var, newname(r->left->sym));
|
||||
fielddup(a->right, hash, nelem(hash));
|
||||
a = nod(OAS, a, r->right);
|
||||
walktype(a, Etop);
|
||||
addtop = list(addtop, a);
|
||||
|
||||
r = listnext(&saver);
|
||||
}
|
||||
if(r->op != OKEY) {
|
||||
mixflag = 1;
|
||||
goto incr2;
|
||||
if(mixflag)
|
||||
yyerror("mixture of field:value initializers");
|
||||
return var;
|
||||
}
|
||||
|
||||
static void
|
||||
indexdup(Node *n, Node *hash[], ulong nhash)
|
||||
{
|
||||
uint h;
|
||||
Node *a;
|
||||
ulong b, c;
|
||||
|
||||
if(n->op != OLITERAL)
|
||||
fatal("indexdup: not OLITERAL");
|
||||
|
||||
b = mpgetfix(n->val.u.xval);
|
||||
h = b%nhash;
|
||||
for(a=hash[h]; a!=N; a=a->ntest) {
|
||||
c = mpgetfix(a->val.u.xval);
|
||||
if(b == c) {
|
||||
yyerror("duplicate index in array literal: %ld", b);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// build list of var.field = expr
|
||||
a = nod(ODOT, var, newname(r->left->sym));
|
||||
a = nod(OAS, a, r->right);
|
||||
walktype(a, Etop);
|
||||
addtop = list(addtop, a);
|
||||
|
||||
incr2:
|
||||
r = listnext(&saver);
|
||||
goto loop2;
|
||||
n->ntest = hash[h];
|
||||
hash[h] = n;
|
||||
}
|
||||
|
||||
Node*
|
||||
|
|
@ -4068,6 +4115,7 @@ arraylit(Node *n, Node *var)
|
|||
Type *t;
|
||||
Node *r, *a;
|
||||
long ninit, b;
|
||||
Node* hash[101];
|
||||
|
||||
t = n->type;
|
||||
if(t->etype != TARRAY)
|
||||
|
|
@ -4126,6 +4174,8 @@ arraylit(Node *n, Node *var)
|
|||
r = listfirst(&saver, &n->left);
|
||||
if(r != N && r->op == OEMPTY)
|
||||
r = N;
|
||||
|
||||
memset(hash, 0, sizeof(hash));
|
||||
while(r != N) {
|
||||
// build list of var[c] = expr
|
||||
if(r->op == OKEY) {
|
||||
|
|
@ -4137,6 +4187,7 @@ arraylit(Node *n, Node *var)
|
|||
r = r->right;
|
||||
}
|
||||
a = nodintconst(b);
|
||||
indexdup(a, hash, nelem(hash));
|
||||
a = nod(OINDEX, var, a);
|
||||
a = nod(OAS, a, r);
|
||||
|
||||
|
|
@ -4149,12 +4200,68 @@ arraylit(Node *n, Node *var)
|
|||
return var;
|
||||
}
|
||||
|
||||
static void
|
||||
keydup(Node *n, Node *hash[], ulong nhash)
|
||||
{
|
||||
uint h;
|
||||
ulong b;
|
||||
double d;
|
||||
int i;
|
||||
Node *a;
|
||||
Node cmp;
|
||||
char *s;
|
||||
|
||||
evconst(n);
|
||||
if(n->op != OLITERAL)
|
||||
return; // we dont check variables
|
||||
|
||||
switch(n->val.ctype) {
|
||||
default: // unknown, bool, nil
|
||||
b = 23;
|
||||
break;
|
||||
case CTINT:
|
||||
b = mpgetfix(n->val.u.xval);
|
||||
break;
|
||||
case CTFLT:
|
||||
d = mpgetflt(n->val.u.fval);
|
||||
s = (char*)&d;
|
||||
b = 0;
|
||||
for(i=sizeof(d); i>0; i--)
|
||||
b = b*PRIME1 + *s++;
|
||||
break;
|
||||
case CTSTR:
|
||||
b = 0;
|
||||
s = n->val.u.sval->s;
|
||||
for(i=n->val.u.sval->len; i>0; i--)
|
||||
b = b*PRIME1 + *s++;
|
||||
break;
|
||||
}
|
||||
|
||||
h = b%nhash;
|
||||
memset(&cmp, 0, sizeof(cmp));
|
||||
for(a=hash[h]; a!=N; a=a->ntest) {
|
||||
cmp.op = OEQ;
|
||||
cmp.left = n;
|
||||
cmp.right = a;
|
||||
evconst(&cmp);
|
||||
b = cmp.val.u.bval;
|
||||
if(b) {
|
||||
// too lazy to print the literal
|
||||
yyerror("duplicate key in map literal");
|
||||
return;
|
||||
}
|
||||
}
|
||||
n->ntest = hash[h];
|
||||
hash[h] = n;
|
||||
}
|
||||
|
||||
Node*
|
||||
maplit(Node *n, Node *var)
|
||||
{
|
||||
Iter saver;
|
||||
Type *t;
|
||||
Node *r, *a;
|
||||
Node* hash[101];
|
||||
|
||||
t = n->type;
|
||||
if(t->etype != TMAP)
|
||||
|
|
@ -4174,6 +4281,7 @@ maplit(Node *n, Node *var)
|
|||
if(r != N && r->op == OEMPTY)
|
||||
r = N;
|
||||
|
||||
memset(hash, 0, sizeof(hash));
|
||||
while(r != N) {
|
||||
if(r == N)
|
||||
break;
|
||||
|
|
@ -4184,9 +4292,11 @@ maplit(Node *n, Node *var)
|
|||
}
|
||||
|
||||
// build list of var[c] = expr
|
||||
keydup(r->left, hash, nelem(hash));
|
||||
|
||||
a = nod(OINDEX, var, r->left);
|
||||
a = nod(OAS, a, r->right);
|
||||
walktype(a, Etop); // add any assignments in r to addtop
|
||||
walktype(a, Etop);
|
||||
addtop = list(addtop, a);
|
||||
|
||||
r = listnext(&saver);
|
||||
|
|
|
|||
Loading…
Reference in New Issue