]> Cypherpunks repositories - gostls13.git/commitdiff
undo CL 11788043 / 62d06cccc261
authorKeith Randall <khr@golang.org>
Fri, 26 Jul 2013 00:51:33 +0000 (17:51 -0700)
committerKeith Randall <khr@golang.org>
Fri, 26 Jul 2013 00:51:33 +0000 (17:51 -0700)
Reason for breakage fixed with CL 11888043.

««« original CL description
undo CL 11683043 / bb75d03e6ccb

Broke arm build.
R=dave

««« original CL description
cc: generate argument pointer maps for C functions.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/11683043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/11788043
»»»

TBR=dave
CC=golang-dev
https://golang.org/cl/11789043

src/cmd/cc/pgen.c

index 27022d54e8c4bf979801973c72e05a0caed8a16b..a6b0f947e1eeb9a49dfd2f0286ab0044b3d9f149 100644 (file)
@@ -31,6 +31,8 @@
 #include "gc.h"
 #include "../../pkg/runtime/funcdata.h"
 
+static int32 pointermap(Sym *gcsym, int32 offset);
+
 int
 hasdotdotdot(void)
 {
@@ -101,7 +103,21 @@ codgen(Node *n, Node *nn)
 
        p = gtext(n1->sym, stkoff);
        sp = p;
-       
+
+       /*
+        * generate funcdata symbol for this function.
+        * data is filled in at the end of codgen().
+        */
+       snprint(namebuf, sizeof namebuf, "gc·%d", ngcsym++);
+       gcsym = slookup(namebuf);
+       gcsym->class = CSTATIC;
+
+       memset(&nod, 0, sizeof nod);
+       nod.op = ONAME;
+       nod.sym = gcsym;
+       nod.class = CSTATIC;
+       gins(AFUNCDATA, nodconst(FUNCDATA_GC), &nod);
+
        /*
         * isolate first argument
         */
@@ -139,17 +155,6 @@ codgen(Node *n, Node *nn)
                maxargsafe = xround(maxargsafe, 8);
        sp->to.offset += maxargsafe;
        
-       snprint(namebuf, sizeof namebuf, "gc·%d", ngcsym++);
-       gcsym = slookup(namebuf);
-       gcsym->class = CSTATIC;
-
-       memset(&nod, 0, sizeof nod);
-       nod.op = ONAME;
-       nod.sym = gcsym;
-       nod.class = CSTATIC;
-
-       gins(AFUNCDATA, nodconst(FUNCDATA_GC), &nod);
-
        // TODO(rsc): "stkoff" is not right. It does not account for
        // the possibility of data stored in .safe variables.
        // Unfortunately those move up and down just like
@@ -162,8 +167,7 @@ codgen(Node *n, Node *nn)
        off = 0;
        gextern(gcsym, nodconst(stkoff), off, 4); // locals
        off += 4;
-       gextern(gcsym, nodconst(0), off, 4); // nptrs
-       off += 4;
+       off = pointermap(gcsym, off); // nptrs and ptrs[...]
        gcsym->type = typ(0, T);
        gcsym->type->width = off;
 }
@@ -633,3 +637,105 @@ bcomplex(Node *n, Node *c)
        boolgen(n, 1, Z);
        return 0;
 }
+
+// Makes a bitmap marking the the pointers in t.  t starts at the given byte
+// offset in the argument list.  The returned bitmap should be for pointer
+// indexes (relative to offset 0) between baseidx and baseidx+32.
+static int32
+pointermap_type(Type *t, int32 offset, int32 baseidx)
+{
+       Type *t1;
+       int32 idx;
+       int32 m;
+
+       switch(t->etype) {
+       case TCHAR:
+       case TUCHAR:
+       case TSHORT:
+       case TUSHORT:
+       case TINT:
+       case TUINT:
+       case TLONG:
+       case TULONG:
+       case TVLONG:
+       case TUVLONG:
+       case TFLOAT:
+       case TDOUBLE:
+               // non-pointer types
+               return 0;
+       case TIND:
+       case TARRAY: // unlike Go, C passes arrays by reference
+               // pointer types
+               if((offset + t->offset) % ewidth[TIND] != 0)
+                       yyerror("unaligned pointer");
+               idx = (offset + t->offset) / ewidth[TIND];
+               if(idx >= baseidx && idx < baseidx + 32)
+                       return 1 << (idx - baseidx);
+               return 0;
+       case TSTRUCT:
+               // build map recursively
+               m = 0;
+               for(t1=t->link; t1; t1=t1->down)
+                       m |= pointermap_type(t1, offset, baseidx);
+               return m;
+       case TUNION:
+               // We require that all elements of the union have the same pointer map.
+               m = pointermap_type(t->link, offset, baseidx);
+               for(t1=t->link->down; t1; t1=t1->down) {
+                       if(pointermap_type(t1, offset, baseidx) != m)
+                               yyerror("invalid union in argument list - pointer maps differ");
+               }
+               return m;
+       default:
+               yyerror("can't handle arg type %s\n", tnames[t->etype]);
+               return 0;
+       }
+}
+
+// Compute a bit vector to describe the pointer containing locations
+// in the argument list.  Adds the data to gcsym and returns the offset
+// of end of the bit vector.
+static int32
+pointermap(Sym *gcsym, int32 off)
+{
+       int32 nptrs;
+       int32 i;
+       int32 s;     // offset in argument list (in bytes)
+       int32 m;     // current ptrs[i/32]
+       Type *t;
+
+       if(hasdotdotdot()) {
+               // give up for C vararg functions.
+               // TODO: maybe make a map just for the args we do know?
+               gextern(gcsym, nodconst(0), off, 4); // nptrs=0
+               return off + 4;
+       }
+       nptrs = (argsize() + ewidth[TIND] - 1) / ewidth[TIND];
+       gextern(gcsym, nodconst(nptrs), off, 4);
+       off += 4;
+
+       for(i = 0; i < nptrs; i += 32) {
+               // generate mask for ptrs at offsets i ... i+31
+               m = 0;
+               s = align(0, thisfn->link, Aarg0, nil);
+               if(s > 0 && i == 0) {
+                       // C Calling convention returns structs by copying
+                       // them to a location pointed to by a hidden first
+                       // argument.  This first argument is a pointer.
+                       if(s != ewidth[TIND])
+                               yyerror("passbyptr arg not the right size");
+                       m = 1;
+               }
+               for(t=thisfn->down; t!=T; t=t->down) {
+                       if(t->etype == TVOID)
+                               continue;
+                       s = align(s, t, Aarg1, nil);
+                       m |= pointermap_type(t, s, i);
+                       s = align(s, t, Aarg2, nil);
+               }
+               gextern(gcsym, nodconst(m), off, 4);
+               off += 4;
+       }
+       return off;
+       // TODO: needs a test for nptrs>32
+}