mirror of
https://github.com/golang/go
synced 2024-11-23 06:30:06 -07:00
cmd/cgo: retain Go pointer passed to C call for duration of call
Fixes #6397. R=golang-dev, bradfitz, iant CC=golang-dev https://golang.org/cl/13858043
This commit is contained in:
parent
7616c94921
commit
5639d2754b
@ -651,9 +651,10 @@ bcomplex(Node *n, Node *c)
|
|||||||
// Updates the bitvector with a set bit for each pointer containing
|
// Updates the bitvector with a set bit for each pointer containing
|
||||||
// value in the type description starting at offset.
|
// value in the type description starting at offset.
|
||||||
static void
|
static void
|
||||||
walktype1(Type *t, int32 offset, Bvec *bv)
|
walktype1(Type *t, int32 offset, Bvec *bv, int param)
|
||||||
{
|
{
|
||||||
Type *t1;
|
Type *t1;
|
||||||
|
int32 o;
|
||||||
|
|
||||||
switch(t->etype) {
|
switch(t->etype) {
|
||||||
case TCHAR:
|
case TCHAR:
|
||||||
@ -672,21 +673,29 @@ walktype1(Type *t, int32 offset, Bvec *bv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case TIND:
|
case TIND:
|
||||||
case TARRAY: // unlike Go, C passes arrays by reference
|
pointer:
|
||||||
// pointer types
|
// pointer types
|
||||||
if((offset + t->offset) % ewidth[TIND] != 0)
|
if((offset + t->offset) % ewidth[TIND] != 0)
|
||||||
yyerror("unaligned pointer");
|
yyerror("unaligned pointer");
|
||||||
bvset(bv, ((offset + t->offset) / ewidth[TIND])*BitsPerPointer);
|
bvset(bv, ((offset + t->offset) / ewidth[TIND])*BitsPerPointer);
|
||||||
break;
|
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:
|
case TSTRUCT:
|
||||||
// build map recursively
|
// build map recursively
|
||||||
for(t1 = t->link; t1 != T; t1 = t1->down)
|
for(t1 = t->link; t1 != T; t1 = t1->down)
|
||||||
walktype1(t1, offset, bv);
|
walktype1(t1, offset, bv, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TUNION:
|
case TUNION:
|
||||||
walktype1(t->link, offset, bv);
|
walktype1(t->link, offset, bv, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -728,7 +737,7 @@ dumpgcargs(Type *fn, Sym *sym)
|
|||||||
if(t->etype == TVOID)
|
if(t->etype == TVOID)
|
||||||
continue;
|
continue;
|
||||||
argoffset = align(argoffset, t, Aarg1, nil);
|
argoffset = align(argoffset, t, Aarg1, nil);
|
||||||
walktype1(t, argoffset, bv);
|
walktype1(t, argoffset, bv, 1);
|
||||||
argoffset = align(argoffset, t, Aarg2, nil);
|
argoffset = align(argoffset, t, Aarg2, nil);
|
||||||
}
|
}
|
||||||
gextern(sym, nodconst(bv->n), 0, 4);
|
gextern(sym, nodconst(bv->n), 0, 4);
|
||||||
|
@ -413,7 +413,17 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
|
|||||||
if argSize == 0 {
|
if argSize == 0 {
|
||||||
argSize++
|
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, "{\n")
|
||||||
fmt.Fprintf(fc, "\truntime·cgocall(_cgo%s%s, &p);\n", cPrefix, n.Mangle)
|
fmt.Fprintf(fc, "\truntime·cgocall(_cgo%s%s, &p);\n", cPrefix, n.Mangle)
|
||||||
if n.AddError {
|
if n.AddError {
|
||||||
|
Loading…
Reference in New Issue
Block a user