Skip to content

Commit d9d3deb

Browse files
ianlancetaylorrsc
authored andcommitted
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
1 parent d7c99cd commit d9d3deb

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
@@ -143,6 +143,10 @@ func testBlocking(t *testing.T) {
143143
// Test that the stack can be unwound through a call out and call back
144144
// into Go.
145145
func testCallbackCallers(t *testing.T) {
146+
if runtime.Compiler != "gc" {
147+
// The exact function names are not going to be the same.
148+
t.Skip("skipping for non-gc toolchain")
149+
}
146150
pc := make([]uintptr, 100)
147151
n := 0
148152
name := []string{

src/cmd/cgo/out.go

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

324+
// Builtins defined in the C prolog.
325+
inProlog := name == "CString" || name == "GoString" || name == "GoStringN" || name == "GoBytes"
326+
324327
if *gccgo {
325328
// Gccgo style hooks.
326329
fmt.Fprint(fgo2, "\n")
@@ -334,8 +337,10 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
334337

335338
conf.Fprint(fgo2, fset, d)
336339
fmt.Fprint(fgo2, " {\n")
337-
fmt.Fprint(fgo2, "\tdefer syscall.CgocallDone()\n")
338-
fmt.Fprint(fgo2, "\tsyscall.Cgocall()\n")
340+
if !inProlog {
341+
fmt.Fprint(fgo2, "\tdefer syscall.CgocallDone()\n")
342+
fmt.Fprint(fgo2, "\tsyscall.Cgocall()\n")
343+
}
339344
if n.AddError {
340345
fmt.Fprint(fgo2, "\tsyscall.SetErrno(0)\n")
341346
}
@@ -366,7 +371,11 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
366371
fmt.Fprint(fgo2, "}\n")
367372

368373
// declare the C function.
369-
fmt.Fprintf(fgo2, "//extern %s\n", n.C)
374+
if inProlog {
375+
fmt.Fprintf(fgo2, "//extern %s\n", n.C)
376+
} else {
377+
fmt.Fprintf(fgo2, "//extern _cgo%s%s\n", cPrefix, n.Mangle)
378+
}
370379
d.Name = ast.NewIdent(cname)
371380
if n.AddError {
372381
l := d.Type.Results.List
@@ -380,8 +389,7 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
380389
conf.Fprint(fgo2, fset, d)
381390
fmt.Fprint(fgo2, "\n")
382391

383-
if name == "CString" || name == "GoString" || name == "GoStringN" || name == "GoBytes" {
384-
// The builtins are already defined in the C prolog.
392+
if inProlog {
385393
return
386394
}
387395

@@ -469,7 +477,7 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
469477
p.Written[name] = true
470478

471479
if *gccgo {
472-
// we don't use wrappers with gccgo.
480+
p.writeGccgoOutputFunc(fgcc, n)
473481
return
474482
}
475483

@@ -526,6 +534,54 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
526534
fmt.Fprintf(fgcc, "\n")
527535
}
528536

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

0 commit comments

Comments
 (0)