]> Cypherpunks repositories - gostls13.git/commitdiff
1. check for dups in complex literals
authorKen Thompson <ken@golang.org>
Sat, 23 May 2009 22:34:29 +0000 (15:34 -0700)
committerKen Thompson <ken@golang.org>
Sat, 23 May 2009 22:34:29 +0000 (15:34 -0700)
   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

src/cmd/6g/cgen.c
src/cmd/6g/gg.h
src/cmd/6g/ggen.c
src/cmd/6g/gsubr.c
src/cmd/6g/reg.c
src/cmd/gc/go.h
src/cmd/gc/sinit.c
src/cmd/gc/subr.c
src/cmd/gc/walk.c

index 2408cfea80b44ba1b6c098afe3ded7771369a219..1027f9076fb488113ce696e4fab1360f887221ea 100644 (file)
@@ -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);
index 0d83506aeee7c33b328c27001dbc2224865d1497..ce5f6c86cd7fce3f3563ffcdfc10cf9300e29889 100644 (file)
@@ -23,6 +23,7 @@ struct        Addr
        char    sval[NSNAME];
 
        Sym*    sym;
+       int     width;
        uchar   type;
        uchar   index;
        uchar   etype;
index 1b7505e610e8670dbb385110eb8cf9e36036dd73..6da512da1d0b819979fb414cdf6e80b312b0fcf6 100644 (file)
@@ -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))
index f63d1c352d9896c35e07ee51b71776cbb63c4f58..0d9034f2ce226bf9a31f8085e70132087a42ed45 100644 (file)
@@ -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;
index a2c64fa9fab2829727e60ed637351731e4b7f38a..865d3a60fd30991f8a923460c7ad4b2b36d6c817 100644 (file)
@@ -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];
        }
index 71aa57190bfe5340fe301d4c648ab5637483b734..c5d28cca7eaa48a192bdda40b3e03fe336cde46c 100644 (file)
@@ -434,6 +434,7 @@ struct      Var
 {
        vlong   offset;
        Sym*    sym;
+       int     width;
        char    name;
        char    etype;
 };
index 2567151f1baf28ac87aab32bf41c382300e6df51..836cdd452c08741333ea0438f3d9a85dd77ffee0 100644 (file)
@@ -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);
 
index 3afaa5ba29e7f77a96fb2e771387ebcd61adbe8d..38e9c6fb76fe491648686ab6fcac24b21a7be23c 100644 (file)
@@ -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;
index a6303a82fc475299ea581b1159be812dfee30074..974a7e62d26b0ae6e76c410dea094c26f5112ad2 100644 (file)
@@ -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);