aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Gerrand <adg@golang.org>2013-07-29 09:57:49 +1000
committerRuss Cox <rsc@golang.org>2013-07-29 09:57:49 +1000
commit3e917131a188e1a59b690f4a18c1d97555d54959 (patch)
tree5f7df5caf3b043cef6b4fdc1ba1e71fdeb1798a5
parent89020aa72cbdff82ab35af759246c85c26462dfe (diff)
downloadgo-3e917131a188e1a59b690f4a18c1d97555d54959.tar.gz
go-3e917131a188e1a59b690f4a18c1d97555d54959.zip
[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
-rw-r--r--misc/cgo/test/callback.go4
-rw-r--r--src/cmd/cgo/out.go68
2 files changed, 66 insertions, 6 deletions
diff --git a/misc/cgo/test/callback.go b/misc/cgo/test/callback.go
index b6e2e3c1ce..c642d5f0fb 100644
--- a/misc/cgo/test/callback.go
+++ b/misc/cgo/test/callback.go
@@ -142,6 +142,10 @@ func testBlocking(t *testing.T) {
// Test that the stack can be unwound through a call out and call back
// into Go.
func testCallbackCallers(t *testing.T) {
+ if runtime.Compiler != "gc" {
+ // The exact function names are not going to be the same.
+ t.Skip("skipping for non-gc toolchain")
+ }
pc := make([]uintptr, 100)
n := 0
name := []string{
diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go
index ee1d89142e..7fb8181689 100644
--- a/src/cmd/cgo/out.go
+++ b/src/cmd/cgo/out.go
@@ -318,6 +318,9 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
Type: gtype,
}
+ // Builtins defined in the C prolog.
+ inProlog := name == "CString" || name == "GoString" || name == "GoStringN" || name == "GoBytes"
+
if *gccgo {
// Gccgo style hooks.
fmt.Fprint(fgo2, "\n")
@@ -331,8 +334,10 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
conf.Fprint(fgo2, fset, d)
fmt.Fprint(fgo2, " {\n")
- fmt.Fprint(fgo2, "\tdefer syscall.CgocallDone()\n")
- fmt.Fprint(fgo2, "\tsyscall.Cgocall()\n")
+ if !inProlog {
+ fmt.Fprint(fgo2, "\tdefer syscall.CgocallDone()\n")
+ fmt.Fprint(fgo2, "\tsyscall.Cgocall()\n")
+ }
if n.AddError {
fmt.Fprint(fgo2, "\tsyscall.SetErrno(0)\n")
}
@@ -363,7 +368,11 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
fmt.Fprint(fgo2, "}\n")
// declare the C function.
- fmt.Fprintf(fgo2, "//extern %s\n", n.C)
+ if inProlog {
+ fmt.Fprintf(fgo2, "//extern %s\n", n.C)
+ } else {
+ fmt.Fprintf(fgo2, "//extern _cgo%s%s\n", cPrefix, n.Mangle)
+ }
d.Name = ast.NewIdent(cname)
if n.AddError {
l := d.Type.Results.List
@@ -377,8 +386,7 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
conf.Fprint(fgo2, fset, d)
fmt.Fprint(fgo2, "\n")
- if name == "CString" || name == "GoString" || name == "GoStringN" || name == "GoBytes" {
- // The builtins are already defined in the C prolog.
+ if inProlog {
return
}
@@ -466,7 +474,7 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
p.Written[name] = true
if *gccgo {
- // we don't use wrappers with gccgo.
+ p.writeGccgoOutputFunc(fgcc, n)
return
}
@@ -518,6 +526,54 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
fmt.Fprintf(fgcc, "\n")
}
+// Write out a wrapper for a function when using gccgo. This is a
+// simple wrapper that just calls the real function. We only need a
+// wrapper to support static functions in the prologue--without a
+// wrapper, we can't refer to the function, since the reference is in
+// a different file.
+func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) {
+ if t := n.FuncType.Result; t != nil {
+ fmt.Fprintf(fgcc, "%s\n", t.C.String())
+ } else {
+ fmt.Fprintf(fgcc, "void\n")
+ }
+ fmt.Fprintf(fgcc, "_cgo%s%s(", cPrefix, n.Mangle)
+ for i, t := range n.FuncType.Params {
+ if i > 0 {
+ fmt.Fprintf(fgcc, ", ")
+ }
+ c := t.Typedef
+ if c == "" {
+ c = t.C.String()
+ }
+ fmt.Fprintf(fgcc, "%s p%d", c, i)
+ }
+ fmt.Fprintf(fgcc, ")\n")
+ fmt.Fprintf(fgcc, "{\n")
+ fmt.Fprintf(fgcc, "\t")
+ if t := n.FuncType.Result; t != nil {
+ fmt.Fprintf(fgcc, "return ")
+ // Cast to void* to avoid warnings due to omitted qualifiers.
+ if c := t.C.String(); c[len(c)-1] == '*' {
+ fmt.Fprintf(fgcc, "(void*)")
+ }
+ }
+ fmt.Fprintf(fgcc, "%s(", n.C)
+ for i, t := range n.FuncType.Params {
+ if i > 0 {
+ fmt.Fprintf(fgcc, ", ")
+ }
+ // Cast to void* to avoid warnings due to omitted qualifiers.
+ if c := t.C.String(); c[len(c)-1] == '*' {
+ fmt.Fprintf(fgcc, "(void*)")
+ }
+ fmt.Fprintf(fgcc, "p%d", i)
+ }
+ fmt.Fprintf(fgcc, ");\n")
+ fmt.Fprintf(fgcc, "}\n")
+ fmt.Fprintf(fgcc, "\n")
+}
+
// Write out the various stubs we need to support functions exported
// from Go so that they are callable from C.
func (p *Package) writeExports(fgo2, fc, fm *os.File) {