From 5639d2754b1c9e33bc4440e23d21726d2cc3454b Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 24 Sep 2013 15:52:48 -0400 Subject: [PATCH] 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 --- src/cmd/cc/pgen.c | 19 ++++++++++++++----- src/cmd/cgo/out.go | 12 +++++++++++- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/cmd/cc/pgen.c b/src/cmd/cc/pgen.c index 66075572b69..b82872bc5d8 100644 --- a/src/cmd/cc/pgen.c +++ b/src/cmd/cc/pgen.c @@ -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); diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go index 9cf8dc55bec..d41dc156591 100644 --- a/src/cmd/cgo/out.go +++ b/src/cmd/cgo/out.go @@ -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 {