From: Ken Thompson Date: Sat, 23 May 2009 22:34:29 +0000 (-0700) Subject: 1. check for dups in complex literals X-Git-Tag: weekly.2009-11-06~1553 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=4238b1834482f54f67b714c85a126b306b524a8c;p=gostls13.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 --- diff --git a/src/cmd/6g/cgen.c b/src/cmd/6g/cgen.c index 2408cfea80..1027f9076f 100644 --- a/src/cmd/6g/cgen.c +++ b/src/cmd/6g/cgen.c @@ -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); diff --git a/src/cmd/6g/gg.h b/src/cmd/6g/gg.h index 0d83506aee..ce5f6c86cd 100644 --- a/src/cmd/6g/gg.h +++ b/src/cmd/6g/gg.h @@ -23,6 +23,7 @@ struct Addr char sval[NSNAME]; Sym* sym; + int width; uchar type; uchar index; uchar etype; diff --git a/src/cmd/6g/ggen.c b/src/cmd/6g/ggen.c index 1b7505e610..6da512da1d 100644 --- a/src/cmd/6g/ggen.c +++ b/src/cmd/6g/ggen.c @@ -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)) diff --git a/src/cmd/6g/gsubr.c b/src/cmd/6g/gsubr.c index f63d1c352d..0d9034f2ce 100644 --- a/src/cmd/6g/gsubr.c +++ b/src/cmd/6g/gsubr.c @@ -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; diff --git a/src/cmd/6g/reg.c b/src/cmd/6g/reg.c index a2c64fa9fa..865d3a60fd 100644 --- a/src/cmd/6g/reg.c +++ b/src/cmd/6g/reg.c @@ -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; isym) 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; zetype != 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; zleft->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); diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c index 3afaa5ba29..38e9c6fb76 100644 --- a/src/cmd/gc/subr.c +++ b/src/cmd/gc/subr.c @@ -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; diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c index a6303a82fc..974a7e62d2 100644 --- a/src/cmd/gc/walk.c +++ b/src/cmd/gc/walk.c @@ -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); + 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; - // build list of var.field = expr - a = nod(ODOT, var, newname(l->sym)); - a = nod(OAS, a, r); - walktype(a, Etop); +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; - } - if(r->op != OKEY) { - mixflag = 1; - goto incr2; + // 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(mixflag) + yyerror("mixture of field:value initializers"); + return var; +} - // 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); +static void +indexdup(Node *n, Node *hash[], ulong nhash) +{ + uint h; + Node *a; + ulong b, c; -incr2: - r = listnext(&saver); - goto loop2; + 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; + } + } + 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);