]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/cgo: retain Go pointer passed to C call for duration of call
authorRuss Cox <rsc@golang.org>
Tue, 24 Sep 2013 19:52:48 +0000 (15:52 -0400)
committerRuss Cox <rsc@golang.org>
Tue, 24 Sep 2013 19:52:48 +0000 (15:52 -0400)
Fixes #6397.

R=golang-dev, bradfitz, iant
CC=golang-dev
https://golang.org/cl/13858043

src/cmd/cc/pgen.c
src/cmd/cgo/out.go

index 66075572b6917ab63469fece719d525f4b2eaa86..b82872bc5d821e104af479c8d613e7b5057aafa1 100644 (file)
@@ -651,9 +651,10 @@ bcomplex(Node *n, Node *c)
 // Updates the bitvector with a set bit for each pointer containing
 // value in the type description starting at offset.
 static void
-walktype1(Type *t, int32 offset, Bvec *bv)
+walktype1(Type *t, int32 offset, Bvec *bv, int param)
 {
        Type *t1;
+       int32 o;
 
        switch(t->etype) {
        case TCHAR:
@@ -672,21 +673,29 @@ walktype1(Type *t, int32 offset, Bvec *bv)
                break;
 
        case TIND:
-       case TARRAY: // unlike Go, C passes arrays by reference
+       pointer:
                // pointer types
                if((offset + t->offset) % ewidth[TIND] != 0)
                        yyerror("unaligned pointer");
                bvset(bv, ((offset + t->offset) / ewidth[TIND])*BitsPerPointer);
                break;
 
+       case TARRAY:
+               if(param)       // unlike Go, C passes arrays by reference
+                       goto pointer;
+               // array in struct or union is an actual array
+               for(o = 0; o < t->width; o += t->link->width)
+                       walktype1(t->link, offset+o, bv, 0);
+               break;
+
        case TSTRUCT:
                // build map recursively
                for(t1 = t->link; t1 != T; t1 = t1->down)
-                       walktype1(t1, offset, bv);
+                       walktype1(t1, offset, bv, 0);
                break;
 
        case TUNION:
-               walktype1(t->link, offset, bv);
+               walktype1(t->link, offset, bv, 0);
                break;
 
        default:
@@ -728,7 +737,7 @@ dumpgcargs(Type *fn, Sym *sym)
                        if(t->etype == TVOID)
                                continue;
                        argoffset = align(argoffset, t, Aarg1, nil);
-                       walktype1(t, argoffset, bv);
+                       walktype1(t, argoffset, bv, 1);
                        argoffset = align(argoffset, t, Aarg2, nil);
                }
                gextern(sym, nodconst(bv->n), 0, 4);
index 9cf8dc55bec3373efe29a132b153c13d5ac2bdea..d41dc156591c1f5925377fdab1a43c39ea66a369 100644 (file)
@@ -413,7 +413,17 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
        if argSize == 0 {
                argSize++
        }
-       fmt.Fprintf(fc, "·%s(struct{uint8 x[%d];}p)\n", n.Mangle, argSize)
+       // TODO(rsc): The struct here should declare pointers only where
+       // there are pointers in the actual argument frame.
+       // This is a workaround for golang.org/issue/6397.
+       fmt.Fprintf(fc, "·%s(struct{", n.Mangle)
+       if n := argSize / p.PtrSize; n > 0 {
+               fmt.Fprintf(fc, "void *y[%d];", n)
+       }
+       if n := argSize % p.PtrSize; n > 0 {
+               fmt.Fprintf(fc, "uint8 x[%d];", n)
+       }
+       fmt.Fprintf(fc, "}p)\n")
        fmt.Fprintf(fc, "{\n")
        fmt.Fprintf(fc, "\truntime·cgocall(_cgo%s%s, &p);\n", cPrefix, n.Mangle)
        if n.AddError {