]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/6g: extend componentgen to small arrays and structs.
authorRémy Oudompheng <oudomphe@phare.normalesup.org>
Mon, 12 Nov 2012 23:08:04 +0000 (00:08 +0100)
committerRémy Oudompheng <oudomphe@phare.normalesup.org>
Mon, 12 Nov 2012 23:08:04 +0000 (00:08 +0100)
Fixes #4092.

R=golang-dev, dave, rsc
CC=golang-dev
https://golang.org/cl/6819083

src/cmd/6g/cgen.c
src/cmd/6g/gg.h
src/cmd/gc/gen.c

index 1333dc194f4f8d92f3371b3d1cf3f22319fe63f1..34e70ded098c8430ee0cdab77f99813e7180c5dc 100644 (file)
@@ -1458,6 +1458,8 @@ cadable(Node *n)
 /*
  * copy a composite value by moving its individual components.
  * Slices, strings and interfaces are supported.
+ * Small structs or arrays with elements of basic type are
+ * also supported.
  * nr is N when assigning a zero value.
  * return 1 if can do, 0 if cant.
  */
@@ -1465,7 +1467,10 @@ int
 componentgen(Node *nr, Node *nl)
 {
        Node nodl, nodr;
+       Type *t;
        int freel, freer;
+       vlong fldcount;
+       vlong loffset, roffset;
 
        freel = 0;
        freer = 0;
@@ -1475,8 +1480,33 @@ componentgen(Node *nr, Node *nl)
                goto no;
 
        case TARRAY:
-               if(!isslice(nl->type))
+               t = nl->type;
+
+               // Slices are ok.
+               if(isslice(t))
+                       break;
+               // Small arrays are ok.
+               if(t->bound > 0 && t->bound <= 3 && !isfat(t->type))
+                       break;
+
+               goto no;
+
+       case TSTRUCT:
+               // Small structs with non-fat types are ok.
+               // Zero-sized structs are treated separately elsewhere.
+               fldcount = 0;
+               for(t=nl->type->type; t; t=t->down) {
+                       if(isfat(t->type))
+                               goto no;
+                       if(t->etype != TFIELD)
+                               fatal("componentgen: not a TFIELD: %lT", t);
+                       fldcount++;
+               }
+               if(fldcount == 0 || fldcount > 3)
                        goto no;
+
+               break;
+
        case TSTRING:
        case TINTER:
                break;
@@ -1500,6 +1530,23 @@ componentgen(Node *nr, Node *nl)
 
        switch(nl->type->etype) {
        case TARRAY:
+               // componentgen for arrays.
+               t = nl->type;
+               if(!isslice(t)) {
+                       nodl.type = t->type;
+                       nodr.type = nodl.type;
+                       for(fldcount=0; fldcount < t->bound; fldcount++) {
+                               if(nr == N)
+                                       clearslim(&nodl);
+                               else
+                                       gmove(&nodr, &nodl);
+                               nodl.xoffset += t->type->width;
+                               nodr.xoffset += t->type->width;
+                       }
+                       goto yes;
+               }
+
+               // componentgen for slices.
                nodl.xoffset += Array_array;
                nodl.type = ptrto(nl->type->type);
 
@@ -1577,6 +1624,23 @@ componentgen(Node *nr, Node *nl)
                gmove(&nodr, &nodl);
 
                goto yes;
+
+       case TSTRUCT:
+               loffset = nodl.xoffset;
+               roffset = nodr.xoffset;
+               for(t=nl->type->type; t; t=t->down) {
+                       nodl.xoffset = loffset + t->width;
+                       nodl.type = t->type;
+
+                       if(nr == N)
+                               clearslim(&nodl);
+                       else {
+                               nodr.xoffset = roffset + t->width;
+                               nodr.type = nodl.type;
+                               gmove(&nodr, &nodl);
+                       }
+               }
+               goto yes;
        }
 
 no:
index ba1ad75f32e33eaa41cda44baf5f275fa6ea0810..9f8e95ceb5332d9dc7ab893f0e5ae882957c941a 100644 (file)
@@ -79,6 +79,7 @@ void  allocparams(void);
 void   checklabels();
 void   ginscall(Node*, int);
 int    gen_as_init(Node*);
+void   clearslim(Node*);
 
 /*
  * cgen.c
index 4f5aa3c3a6b15a8c0b3ca96f890961058cec7c5f..456ca622fb4a739ead48567a5580af04428d7df8 100644 (file)
@@ -632,6 +632,67 @@ cgen_discard(Node *nr)
        }
 }
 
+/*
+ * clearslim generates code to zero a slim node.
+ */
+void
+clearslim(Node *n)
+{
+       Node z;
+       Mpflt zero;
+
+       memset(&z, 0, sizeof(z));
+       z.op = OLITERAL;
+       z.type = n->type;
+       z.addable = 1;
+
+       switch(simtype[n->type->etype]) {
+       case TCOMPLEX64:
+       case TCOMPLEX128:
+               z.val.u.cval = mal(sizeof(z.val.u.cval));
+               mpmovecflt(&z.val.u.cval->real, 0.0);
+               mpmovecflt(&z.val.u.cval->imag, 0.0);
+               break;
+
+       case TFLOAT32:
+       case TFLOAT64:
+               mpmovecflt(&zero, 0.0);
+               z.val.ctype = CTFLT;
+               z.val.u.fval = &zero;
+               break;
+
+       case TPTR32:
+       case TPTR64:
+       case TCHAN:
+       case TMAP:
+               z.val.ctype = CTNIL;
+               break;
+
+       case TBOOL:
+               z.val.ctype = CTBOOL;
+               break;
+
+       case TINT8:
+       case TINT16:
+       case TINT32:
+       case TINT64:
+       case TUINT8:
+       case TUINT16:
+       case TUINT32:
+       case TUINT64:
+               z.val.ctype = CTINT;
+               z.val.u.xval = mal(sizeof(z.val.u.xval));
+               mpmovecfix(z.val.u.xval, 0);
+               break;
+
+       default:
+               fatal("clearslim called on type %T", n->type);
+       }
+
+       ullmancalc(&z);
+       cgen(&z, n);
+}
+
 /*
  * generate assignment:
  *     nl = nr
@@ -640,9 +701,7 @@ cgen_discard(Node *nr)
 void
 cgen_as(Node *nl, Node *nr)
 {
-       Node nc;
        Type *tl;
-       int iszer;
 
        if(debug['g']) {
                dump("cgen_as", nl);
@@ -657,7 +716,6 @@ cgen_as(Node *nl, Node *nr)
                return;
        }
 
-       iszer = 0;
        if(nr == N || isnil(nr)) {
                // externals and heaps should already be clear
                if(nr == N) {
@@ -672,59 +730,12 @@ cgen_as(Node *nl, Node *nr)
                        return;
                if(isfat(tl)) {
                        clearfat(nl);
-                       goto ret;
-               }
-
-               /* invent a "zero" for the rhs */
-               iszer = 1;
-               nr = &nc;
-               memset(nr, 0, sizeof(*nr));
-               switch(simtype[tl->etype]) {
-               default:
-                       fatal("cgen_as: tl %T", tl);
-                       break;
-
-               case TINT8:
-               case TUINT8:
-               case TINT16:
-               case TUINT16:
-               case TINT32:
-               case TUINT32:
-               case TINT64:
-               case TUINT64:
-                       nr->val.u.xval = mal(sizeof(*nr->val.u.xval));
-                       mpmovecfix(nr->val.u.xval, 0);
-                       nr->val.ctype = CTINT;
-                       break;
-
-               case TFLOAT32:
-               case TFLOAT64:
-                       nr->val.u.fval = mal(sizeof(*nr->val.u.fval));
-                       mpmovecflt(nr->val.u.fval, 0.0);
-                       nr->val.ctype = CTFLT;
-                       break;
-
-               case TBOOL:
-                       nr->val.u.bval = 0;
-                       nr->val.ctype = CTBOOL;
-                       break;
-
-               case TPTR32:
-               case TPTR64:
-                       nr->val.ctype = CTNIL;
-                       break;
-
-               case TCOMPLEX64:
-               case TCOMPLEX128:
-                       nr->val.u.cval = mal(sizeof(*nr->val.u.cval));
-                       mpmovecflt(&nr->val.u.cval->real, 0.0);
-                       mpmovecflt(&nr->val.u.cval->imag, 0.0);
-                       break;
+                       return;
                }
-               nr->op = OLITERAL;
-               nr->type = tl;
-               nr->addable = 1;
-               ullmancalc(nr);
+               clearslim(nl);
+               if(nl->addable)
+                       gused(nl);
+               return;
        }
 
        tl = nl->type;
@@ -732,11 +743,6 @@ cgen_as(Node *nl, Node *nr)
                return;
 
        cgen(nr, nl);
-       if(iszer && nl->addable)
-               gused(nl);
-
-ret:
-       ;
 }
 
 /*