]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/cgo: gccgo fixes
authorIan Lance Taylor <iant@golang.org>
Thu, 25 Jul 2013 13:53:57 +0000 (09:53 -0400)
committerRuss Cox <rsc@golang.org>
Thu, 25 Jul 2013 13:53:57 +0000 (09:53 -0400)
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

misc/cgo/test/callback.go
src/cmd/cgo/out.go

index b1e0b8632e2da0f76766f28416a3a4a2d87865de..77780e84d764c739951ec7150dd85208d0eb4f5c 100644 (file)
@@ -143,6 +143,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{
index f5618e3e8a1e7607166923fe793c902bf6a8ec21..fa4e5806b5e17cd5c1926424c146b17da8f0211c 100644 (file)
@@ -321,6 +321,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")
@@ -334,8 +337,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")
                }
@@ -366,7 +371,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
@@ -380,8 +389,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
        }
 
@@ -469,7 +477,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
        }
 
@@ -526,6 +534,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) {