From 3e917131a188e1a59b690f4a18c1d97555d54959 Mon Sep 17 00:00:00 2001 From: Andrew Gerrand Date: Mon, 29 Jul 2013 09:57:49 +1000 Subject: [release-branch.go1.1] cmd/cgo: gccgo fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ««« 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 --- misc/cgo/test/callback.go | 4 +++ src/cmd/cgo/out.go | 68 ++++++++++++++++++++++++++++++++++++++++++----- 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) { -- cgit v1.2.3-54-g00ecf