1
0
mirror of https://github.com/golang/go synced 2024-11-24 22:00:09 -07:00

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
This commit is contained in:
Ian Lance Taylor 2013-07-25 09:53:57 -04:00 committed by Russ Cox
parent d7c99cdf9f
commit d9d3debee5
2 changed files with 66 additions and 6 deletions

View 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{

View 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) {