Skip to content

Commit 3e91713

Browse files
adgrsc
authored andcommitted
[release-branch.go1.1] cmd/cgo: gccgo fixes
««« CL 11406047 / 4d9c3095de9d cmd/cgo: gccgo fixes Don't require a full-scale callback for calls to the special prologue functions. Always use a simple wrapper function for C functions, so that we can handle static functions defined in the import "C" comment. Disable a test that relies on gc-specific function names. Fixes #5905. R=golang-dev, rsc CC=golang-dev https://golang.org/cl/11406047 »»» Update #5928 R=golang-dev, dave CC=golang-dev https://golang.org/cl/11887043
1 parent 89020aa commit 3e91713

File tree

2 files changed

+66
-6
lines changed

2 files changed

+66
-6
lines changed

misc/cgo/test/callback.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,10 @@ func testBlocking(t *testing.T) {
142142
// Test that the stack can be unwound through a call out and call back
143143
// into Go.
144144
func testCallbackCallers(t *testing.T) {
145+
if runtime.Compiler != "gc" {
146+
// The exact function names are not going to be the same.
147+
t.Skip("skipping for non-gc toolchain")
148+
}
145149
pc := make([]uintptr, 100)
146150
n := 0
147151
name := []string{

src/cmd/cgo/out.go

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,9 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
318318
Type: gtype,
319319
}
320320

321+
// Builtins defined in the C prolog.
322+
inProlog := name == "CString" || name == "GoString" || name == "GoStringN" || name == "GoBytes"
323+
321324
if *gccgo {
322325
// Gccgo style hooks.
323326
fmt.Fprint(fgo2, "\n")
@@ -331,8 +334,10 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
331334

332335
conf.Fprint(fgo2, fset, d)
333336
fmt.Fprint(fgo2, " {\n")
334-
fmt.Fprint(fgo2, "\tdefer syscall.CgocallDone()\n")
335-
fmt.Fprint(fgo2, "\tsyscall.Cgocall()\n")
337+
if !inProlog {
338+
fmt.Fprint(fgo2, "\tdefer syscall.CgocallDone()\n")
339+
fmt.Fprint(fgo2, "\tsyscall.Cgocall()\n")
340+
}
336341
if n.AddError {
337342
fmt.Fprint(fgo2, "\tsyscall.SetErrno(0)\n")
338343
}
@@ -363,7 +368,11 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
363368
fmt.Fprint(fgo2, "}\n")
364369

365370
// declare the C function.
366-
fmt.Fprintf(fgo2, "//extern %s\n", n.C)
371+
if inProlog {
372+
fmt.Fprintf(fgo2, "//extern %s\n", n.C)
373+
} else {
374+
fmt.Fprintf(fgo2, "//extern _cgo%s%s\n", cPrefix, n.Mangle)
375+
}
367376
d.Name = ast.NewIdent(cname)
368377
if n.AddError {
369378
l := d.Type.Results.List
@@ -377,8 +386,7 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
377386
conf.Fprint(fgo2, fset, d)
378387
fmt.Fprint(fgo2, "\n")
379388

380-
if name == "CString" || name == "GoString" || name == "GoStringN" || name == "GoBytes" {
381-
// The builtins are already defined in the C prolog.
389+
if inProlog {
382390
return
383391
}
384392

@@ -466,7 +474,7 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
466474
p.Written[name] = true
467475

468476
if *gccgo {
469-
// we don't use wrappers with gccgo.
477+
p.writeGccgoOutputFunc(fgcc, n)
470478
return
471479
}
472480

@@ -518,6 +526,54 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
518526
fmt.Fprintf(fgcc, "\n")
519527
}
520528

529+
// Write out a wrapper for a function when using gccgo. This is a
530+
// simple wrapper that just calls the real function. We only need a
531+
// wrapper to support static functions in the prologue--without a
532+
// wrapper, we can't refer to the function, since the reference is in
533+
// a different file.
534+
func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) {
535+
if t := n.FuncType.Result; t != nil {
536+
fmt.Fprintf(fgcc, "%s\n", t.C.String())
537+
} else {
538+
fmt.Fprintf(fgcc, "void\n")
539+
}
540+
fmt.Fprintf(fgcc, "_cgo%s%s(", cPrefix, n.Mangle)
541+
for i, t := range n.FuncType.Params {
542+
if i > 0 {
543+
fmt.Fprintf(fgcc, ", ")
544+
}
545+
c := t.Typedef
546+
if c == "" {
547+
c = t.C.String()
548+
}
549+
fmt.Fprintf(fgcc, "%s p%d", c, i)
550+
}
551+
fmt.Fprintf(fgcc, ")\n")
552+
fmt.Fprintf(fgcc, "{\n")
553+
fmt.Fprintf(fgcc, "\t")
554+
if t := n.FuncType.Result; t != nil {
555+
fmt.Fprintf(fgcc, "return ")
556+
// Cast to void* to avoid warnings due to omitted qualifiers.
557+
if c := t.C.String(); c[len(c)-1] == '*' {
558+
fmt.Fprintf(fgcc, "(void*)")
559+
}
560+
}
561+
fmt.Fprintf(fgcc, "%s(", n.C)
562+
for i, t := range n.FuncType.Params {
563+
if i > 0 {
564+
fmt.Fprintf(fgcc, ", ")
565+
}
566+
// Cast to void* to avoid warnings due to omitted qualifiers.
567+
if c := t.C.String(); c[len(c)-1] == '*' {
568+
fmt.Fprintf(fgcc, "(void*)")
569+
}
570+
fmt.Fprintf(fgcc, "p%d", i)
571+
}
572+
fmt.Fprintf(fgcc, ");\n")
573+
fmt.Fprintf(fgcc, "}\n")
574+
fmt.Fprintf(fgcc, "\n")
575+
}
576+
521577
// Write out the various stubs we need to support functions exported
522578
// from Go so that they are callable from C.
523579
func (p *Package) writeExports(fgo2, fc, fm *os.File) {

0 commit comments

Comments
 (0)