mirror of
https://github.com/golang/go
synced 2024-11-25 00:57:59 -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:
parent
d7c99cdf9f
commit
d9d3debee5
@ -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{
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user