mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/cgo: Add support for C function pointers
* Add a new kind of Name, "fpvar" which stands for function pointer variable * When walking the AST, find functions used as expressions and create a new Name object for them * Track functions which are only used in expr contexts, and avoid generating bridge code for them R=golang-dev, minux.ma, fullung, rsc, iant CC=golang-dev https://golang.org/cl/9835047
This commit is contained in:
parent
469250fb77
commit
c18dc11ef2
6 changed files with 148 additions and 19 deletions
|
|
@ -548,25 +548,40 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
|
|||
|
||||
}
|
||||
|
||||
// mangleName does name mangling to translate names
|
||||
// from the original Go source files to the names
|
||||
// used in the final Go files generated by cgo.
|
||||
func (p *Package) mangleName(n *Name) {
|
||||
// When using gccgo variables have to be
|
||||
// exported so that they become global symbols
|
||||
// that the C code can refer to.
|
||||
prefix := "_C"
|
||||
if *gccgo && n.IsVar() {
|
||||
prefix = "C"
|
||||
}
|
||||
n.Mangle = prefix + n.Kind + "_" + n.Go
|
||||
}
|
||||
|
||||
// rewriteRef rewrites all the C.xxx references in f.AST to refer to the
|
||||
// Go equivalents, now that we have figured out the meaning of all
|
||||
// the xxx. In *godefs or *cdefs mode, rewriteRef replaces the names
|
||||
// with full definitions instead of mangled names.
|
||||
func (p *Package) rewriteRef(f *File) {
|
||||
// Keep a list of all the functions, to remove the ones
|
||||
// only used as expressions and avoid generating bridge
|
||||
// code for them.
|
||||
functions := make(map[string]bool)
|
||||
|
||||
// Assign mangled names.
|
||||
for _, n := range f.Name {
|
||||
if n.Kind == "not-type" {
|
||||
n.Kind = "var"
|
||||
}
|
||||
if n.Mangle == "" {
|
||||
// When using gccgo variables have to be
|
||||
// exported so that they become global symbols
|
||||
// that the C code can refer to.
|
||||
prefix := "_C"
|
||||
if *gccgo && n.Kind == "var" {
|
||||
prefix = "C"
|
||||
}
|
||||
n.Mangle = prefix + n.Kind + "_" + n.Go
|
||||
p.mangleName(n)
|
||||
}
|
||||
if n.Kind == "func" {
|
||||
functions[n.Go] = false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -590,6 +605,7 @@ func (p *Package) rewriteRef(f *File) {
|
|||
error_(r.Pos(), "call of non-function C.%s", r.Name.Go)
|
||||
break
|
||||
}
|
||||
functions[r.Name.Go] = true
|
||||
if r.Context == "call2" {
|
||||
// Invent new Name for the two-result function.
|
||||
n := f.Name["2"+r.Name.Go]
|
||||
|
|
@ -606,13 +622,26 @@ func (p *Package) rewriteRef(f *File) {
|
|||
}
|
||||
case "expr":
|
||||
if r.Name.Kind == "func" {
|
||||
error_(r.Pos(), "must call C.%s", r.Name.Go)
|
||||
}
|
||||
if r.Name.Kind == "type" {
|
||||
// Function is being used in an expression, to e.g. pass around a C function pointer.
|
||||
// Create a new Name for this Ref which causes the variable to be declared in Go land.
|
||||
fpName := "fp_" + r.Name.Go
|
||||
name := f.Name[fpName]
|
||||
if name == nil {
|
||||
name = &Name{
|
||||
Go: fpName,
|
||||
C: r.Name.C,
|
||||
Kind: "fpvar",
|
||||
Type: &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*"), Go: ast.NewIdent("unsafe.Pointer")},
|
||||
}
|
||||
p.mangleName(name)
|
||||
f.Name[fpName] = name
|
||||
}
|
||||
r.Name = name
|
||||
expr = ast.NewIdent(name.Mangle)
|
||||
} else if r.Name.Kind == "type" {
|
||||
// Okay - might be new(T)
|
||||
expr = r.Name.Type.Go
|
||||
}
|
||||
if r.Name.Kind == "var" {
|
||||
} else if r.Name.Kind == "var" {
|
||||
expr = &ast.StarExpr{X: expr}
|
||||
}
|
||||
|
||||
|
|
@ -644,6 +673,14 @@ func (p *Package) rewriteRef(f *File) {
|
|||
}
|
||||
*r.Expr = expr
|
||||
}
|
||||
|
||||
// Remove functions only used as expressions, so their respective
|
||||
// bridge functions are not generated.
|
||||
for name, used := range functions {
|
||||
if !used {
|
||||
delete(f.Name, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// gccBaseCmd returns the start of the compiler command line.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue