cgo: supports c/go callback funcs
This commit is contained in:
@@ -77,9 +77,26 @@ static void test_macros() {
|
|||||||
#define MY_VERSION "1.0.0"
|
#define MY_VERSION "1.0.0"
|
||||||
#define MY_CODE 0x12345678
|
#define MY_CODE 0x12345678
|
||||||
|
|
||||||
void test_void() {
|
static void test_void() {
|
||||||
printf("test_void\n");
|
printf("test_void\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef int (*Cb)(int);
|
||||||
|
|
||||||
|
extern int go_callback(int);
|
||||||
|
|
||||||
|
extern int c_callback(int i);
|
||||||
|
|
||||||
|
static void test_callback(Cb cb) {
|
||||||
|
printf("test_callback, cb: %p, go_callback: %p, c_callback: %p\n", cb, go_callback, c_callback);
|
||||||
|
printf("test_callback, *cb: %p, *go_callback: %p, *c_callback: %p\n", *(void**)cb, *(void**)(go_callback), *(void**)(c_callback));
|
||||||
|
printf("cb result: %d\n", cb(123));
|
||||||
|
printf("done\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void run_callback() {
|
||||||
|
test_callback(c_callback);
|
||||||
|
}
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
import (
|
import (
|
||||||
@@ -90,6 +107,11 @@ import (
|
|||||||
"github.com/goplus/llgo/_demo/cgofull/pymod2"
|
"github.com/goplus/llgo/_demo/cgofull/pymod2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//export go_callback
|
||||||
|
func go_callback(i C.int) C.int {
|
||||||
|
return i + 1
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
runPy()
|
runPy()
|
||||||
f := &C.Foo{a: 1}
|
f := &C.Foo{a: 1}
|
||||||
@@ -104,6 +126,16 @@ func main() {
|
|||||||
fmt.Println(C.MY_VERSION)
|
fmt.Println(C.MY_VERSION)
|
||||||
fmt.Println(int(C.MY_CODE))
|
fmt.Println(int(C.MY_CODE))
|
||||||
C.test_void()
|
C.test_void()
|
||||||
|
|
||||||
|
println("call run_callback")
|
||||||
|
C.run_callback()
|
||||||
|
|
||||||
|
// test _Cgo_ptr and _cgoCheckResult
|
||||||
|
println("call with go_callback")
|
||||||
|
C.test_callback((C.Cb)(C.go_callback))
|
||||||
|
|
||||||
|
println("call with c_callback")
|
||||||
|
C.test_callback((C.Cb)(C.c_callback))
|
||||||
}
|
}
|
||||||
|
|
||||||
func runPy() {
|
func runPy() {
|
||||||
@@ -112,4 +144,6 @@ func runPy() {
|
|||||||
Run("print('Hello, Python!')")
|
Run("print('Hello, Python!')")
|
||||||
C.PyObject_Print((*C.PyObject)(unsafe.Pointer(pymod1.Float(1.23))), C.stderr, 0)
|
C.PyObject_Print((*C.PyObject)(unsafe.Pointer(pymod1.Float(1.23))), C.stderr, 0)
|
||||||
C.PyObject_Print((*C.PyObject)(unsafe.Pointer(pymod2.Long(123))), C.stdout, 0)
|
C.PyObject_Print((*C.PyObject)(unsafe.Pointer(pymod2.Long(123))), C.stdout, 0)
|
||||||
|
// test _Cgo_use
|
||||||
|
C.PyObject_Print((*C.PyObject)(unsafe.Pointer(C.PyComplex_FromDoubles(C.double(1.23), C.double(4.56)))), C.stdout, 0)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "foo.h"
|
#include "foo.h"
|
||||||
|
|
||||||
void print_foo(Foo* f) {
|
void print_foo(Foo *f)
|
||||||
|
{
|
||||||
printf("print_foo: %d\n", f->a);
|
printf("print_foo: %d\n", f->a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int c_callback(int i)
|
||||||
|
{
|
||||||
|
return i + 1;
|
||||||
|
}
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
; ModuleID = 'main'
|
|
||||||
source_filename = "main"
|
|
||||||
|
|
||||||
%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 }
|
|
||||||
|
|
||||||
@"main.init$guard" = global i1 false, align 1
|
|
||||||
@0 = private unnamed_addr constant [5 x i8] c"hello", align 1
|
|
||||||
@__llgo_argc = global i32 0, align 4
|
|
||||||
@__llgo_argv = global ptr null, align 8
|
|
||||||
|
|
||||||
define i64 @main.Foo(%"github.com/goplus/llgo/internal/runtime.String" %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %0, 1
|
|
||||||
ret i64 %1
|
|
||||||
}
|
|
||||||
|
|
||||||
define void @main.Test() {
|
|
||||||
_llgo_0:
|
|
||||||
br label %_llgo_3
|
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_3
|
|
||||||
%0 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %0, i32 0, i32 0
|
|
||||||
store ptr @0, ptr %1, align 8
|
|
||||||
%2 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %0, i32 0, i32 1
|
|
||||||
store i64 5, ptr %2, align 4
|
|
||||||
%3 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %0, align 8
|
|
||||||
%4 = call i64 @main.Foo(%"github.com/goplus/llgo/internal/runtime.String" %3)
|
|
||||||
%5 = add i64 %6, 1
|
|
||||||
br label %_llgo_3
|
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_3
|
|
||||||
ret void
|
|
||||||
|
|
||||||
_llgo_3: ; preds = %_llgo_1, %_llgo_0
|
|
||||||
%6 = phi i64 [ 0, %_llgo_0 ], [ %5, %_llgo_1 ]
|
|
||||||
%7 = icmp slt i64 %6, 1000000
|
|
||||||
br i1 %7, label %_llgo_1, label %_llgo_2
|
|
||||||
}
|
|
||||||
|
|
||||||
define void @main.init() {
|
|
||||||
_llgo_0:
|
|
||||||
%0 = load i1, ptr @"main.init$guard", align 1
|
|
||||||
br i1 %0, label %_llgo_2, label %_llgo_1
|
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_0
|
|
||||||
store i1 true, ptr @"main.init$guard", align 1
|
|
||||||
br label %_llgo_2
|
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
|
|
||||||
define i32 @main(i32 %0, ptr %1) {
|
|
||||||
_llgo_0:
|
|
||||||
store i32 %0, ptr @__llgo_argc, align 4
|
|
||||||
store ptr %1, ptr @__llgo_argv, align 8
|
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
|
||||||
call void @main.init()
|
|
||||||
call void @main.Test()
|
|
||||||
ret i32 0
|
|
||||||
}
|
|
||||||
|
|
||||||
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
|
||||||
@@ -1,12 +1,23 @@
|
|||||||
; ModuleID = 'main'
|
; ModuleID = 'main'
|
||||||
source_filename = "main"
|
source_filename = "main"
|
||||||
|
|
||||||
|
%"github.com/goplus/llgo/internal/runtime.eface" = type { ptr, ptr }
|
||||||
|
|
||||||
@"github.com/goplus/llgo/internal/runtime.cgoAlwaysFalse" = external global i1, align 1
|
@"github.com/goplus/llgo/internal/runtime.cgoAlwaysFalse" = external global i1, align 1
|
||||||
@main.format = global [10 x i8] zeroinitializer, align 1
|
@main.format = global [10 x i8] zeroinitializer, align 1
|
||||||
@"main.init$guard" = global i1 false, align 1
|
@"main.init$guard" = global i1 false, align 1
|
||||||
@__llgo_argc = global i32 0, align 4
|
@__llgo_argc = global i32 0, align 4
|
||||||
@__llgo_argv = global ptr null, align 8
|
@__llgo_argv = global ptr null, align 8
|
||||||
|
|
||||||
|
define ptr @main._Cgo_ptr(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
ret ptr %0
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @runtime.cgoUse(%"github.com/goplus/llgo/internal/runtime.eface")
|
||||||
|
|
||||||
|
declare void @runtime.cgoCheckResult(%"github.com/goplus/llgo/internal/runtime.eface")
|
||||||
|
|
||||||
define void @main.init() {
|
define void @main.init() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%0 = load i1, ptr @"main.init$guard", align 1
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
source_filename = "main"
|
source_filename = "main"
|
||||||
|
|
||||||
%main.Foo = type { i32, i1 }
|
%main.Foo = type { i32, i1 }
|
||||||
|
%"github.com/goplus/llgo/internal/runtime.eface" = type { ptr, ptr }
|
||||||
|
|
||||||
@"github.com/goplus/llgo/internal/runtime.cgoAlwaysFalse" = external global i1, align 1
|
@"github.com/goplus/llgo/internal/runtime.cgoAlwaysFalse" = external global i1, align 1
|
||||||
@main.format = global [10 x i8] zeroinitializer, align 1
|
@main.format = global [10 x i8] zeroinitializer, align 1
|
||||||
@@ -35,6 +36,15 @@ _llgo_0:
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define ptr @main._Cgo_ptr(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
ret ptr %0
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @runtime.cgoUse(%"github.com/goplus/llgo/internal/runtime.eface")
|
||||||
|
|
||||||
|
declare void @runtime.cgoCheckResult(%"github.com/goplus/llgo/internal/runtime.eface")
|
||||||
|
|
||||||
define void @main.init() {
|
define void @main.init() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%0 = load i1, ptr @"main.init$guard", align 1
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
; ModuleID = 'main'
|
; ModuleID = 'main'
|
||||||
source_filename = "main"
|
source_filename = "main"
|
||||||
|
|
||||||
|
%"github.com/goplus/llgo/internal/runtime.eface" = type { ptr, ptr }
|
||||||
|
|
||||||
@"github.com/goplus/llgo/internal/runtime.cgoAlwaysFalse" = external global i1, align 1
|
@"github.com/goplus/llgo/internal/runtime.cgoAlwaysFalse" = external global i1, align 1
|
||||||
@main.format = global [10 x i8] zeroinitializer, align 1
|
@main.format = global [10 x i8] zeroinitializer, align 1
|
||||||
@"main.init$guard" = global i1 false, align 1
|
@"main.init$guard" = global i1 false, align 1
|
||||||
@@ -23,6 +25,15 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define ptr @main._Cgo_ptr(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
ret ptr %0
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @runtime.cgoUse(%"github.com/goplus/llgo/internal/runtime.eface")
|
||||||
|
|
||||||
|
declare void @runtime.cgoCheckResult(%"github.com/goplus/llgo/internal/runtime.eface")
|
||||||
|
|
||||||
define void @main.init() {
|
define void @main.init() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%0 = load i1, ptr @"main.init$guard", align 1
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ var (
|
|||||||
argvTy = types.NewPointer(types.NewPointer(types.Typ[types.Int8]))
|
argvTy = types.NewPointer(types.NewPointer(types.Typ[types.Int8]))
|
||||||
)
|
)
|
||||||
|
|
||||||
func isCgoCfuncOrCmacro(f *ssa.Function) bool {
|
func isCgoExternSymbol(f *ssa.Function) bool {
|
||||||
name := f.Name()
|
name := f.Name()
|
||||||
return isCgoCfunc(name) || isCgoCmacro(name)
|
return isCgoCfunc(name) || isCgoCmacro(name)
|
||||||
}
|
}
|
||||||
@@ -202,6 +202,10 @@ func isCgoCmacro(name string) bool {
|
|||||||
return strings.HasPrefix(name, "_Cmacro_")
|
return strings.HasPrefix(name, "_Cmacro_")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isCgoVar(name string) bool {
|
||||||
|
return strings.HasPrefix(name, "__cgo_")
|
||||||
|
}
|
||||||
|
|
||||||
func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Function, llssa.PyObjRef, int) {
|
func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Function, llssa.PyObjRef, int) {
|
||||||
pkgTypes, name, ftype := p.funcName(f, true)
|
pkgTypes, name, ftype := p.funcName(f, true)
|
||||||
if ftype != goFunc {
|
if ftype != goFunc {
|
||||||
@@ -255,7 +259,7 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun
|
|||||||
fn.Inline(llssa.NoInline)
|
fn.Inline(llssa.NoInline)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
isCgo := isCgoCfuncOrCmacro(f)
|
isCgo := isCgoExternSymbol(f)
|
||||||
if nblk := len(f.Blocks); nblk > 0 {
|
if nblk := len(f.Blocks); nblk > 0 {
|
||||||
p.cgoCalled = false
|
p.cgoCalled = false
|
||||||
p.cgoArgs = nil
|
p.cgoArgs = nil
|
||||||
@@ -918,7 +922,17 @@ func (p *context) compileValue(b llssa.Builder, v ssa.Value) llssa.Expr {
|
|||||||
}
|
}
|
||||||
return pyFn.Expr
|
return pyFn.Expr
|
||||||
case *ssa.Global:
|
case *ssa.Global:
|
||||||
|
varName := v.Name()
|
||||||
val := p.varOf(b, v)
|
val := p.varOf(b, v)
|
||||||
|
if isCgoVar(varName) {
|
||||||
|
fname := p.fset.Position(v.Pos()).Filename
|
||||||
|
funcs, ok := p.cgoFuncs[fname]
|
||||||
|
if !ok {
|
||||||
|
funcs = make([]string, 0, 1)
|
||||||
|
}
|
||||||
|
funcs = append(funcs, val.Name())
|
||||||
|
p.cgoFuncs[fname] = funcs
|
||||||
|
}
|
||||||
if debugSymbols {
|
if debugSymbols {
|
||||||
pos := p.fset.Position(v.Pos())
|
pos := p.fset.Position(v.Pos())
|
||||||
b.DIGlobal(val, v.Name(), pos)
|
b.DIGlobal(val, v.Name(), pos)
|
||||||
@@ -1053,6 +1067,26 @@ func NewPackageEx(prog llssa.Program, patches Patches, pkg *ssa.Package, files [
|
|||||||
fn()
|
fn()
|
||||||
}
|
}
|
||||||
externs = ctx.cgoFuncs
|
externs = ctx.cgoFuncs
|
||||||
|
// TODO(lijie): read export name
|
||||||
|
for _, funcs := range externs {
|
||||||
|
for _, funcName := range funcs {
|
||||||
|
if strings.Contains(funcName, ".__cgo_") {
|
||||||
|
goFnName := strings.Replace(funcName, ".__cgo_", ".", 1)
|
||||||
|
idx := strings.LastIndex(funcName, ".__cgo_")
|
||||||
|
cfuncName := funcName[idx+len(".__cgo_"):]
|
||||||
|
v := ret.VarOf(funcName)
|
||||||
|
if fn := ret.FuncOf(goFnName); fn != nil {
|
||||||
|
// TODO(lijie): naive go:export, need better way from comment
|
||||||
|
fn.SetName(cfuncName)
|
||||||
|
// Replace symbol instead of static linking
|
||||||
|
v.ReplaceAllUsesWith(fn.Expr)
|
||||||
|
} else if fn := ret.FuncOf(cfuncName); fn != nil {
|
||||||
|
// Replace symbol instead of static linking
|
||||||
|
v.ReplaceAllUsesWith(fn.Expr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -448,7 +448,7 @@ func (p *context) funcName(fn *ssa.Function, ignore bool) (*types.Package, strin
|
|||||||
if checkCgo(fname) && !cgoIgnored(fname) {
|
if checkCgo(fname) && !cgoIgnored(fname) {
|
||||||
return nil, fname, llgoInstr
|
return nil, fname, llgoInstr
|
||||||
}
|
}
|
||||||
if isCgoCfuncOrCmacro(fn) {
|
if isCgoExternSymbol(fn) {
|
||||||
if _, ok := llgoInstrs[fname]; ok {
|
if _, ok := llgoInstrs[fname]; ok {
|
||||||
return nil, fname, llgoInstr
|
return nil, fname, llgoInstr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -525,6 +525,7 @@ func buildPkg(ctx *context, aPkg *aPackage, verbose bool) (cgoLdflags []string,
|
|||||||
cl.SetDebug(0)
|
cl.SetDebug(0)
|
||||||
}
|
}
|
||||||
check(err)
|
check(err)
|
||||||
|
aPkg.LPkg = ret
|
||||||
cgoLdflags, err = buildCgo(ctx, aPkg, aPkg.Package.Syntax, externs, verbose)
|
cgoLdflags, err = buildCgo(ctx, aPkg, aPkg.Package.Syntax, externs, verbose)
|
||||||
if needLLFile(ctx.mode) {
|
if needLLFile(ctx.mode) {
|
||||||
pkg.ExportFile += ".ll"
|
pkg.ExportFile += ".ll"
|
||||||
@@ -533,7 +534,6 @@ func buildPkg(ctx *context, aPkg *aPackage, verbose bool) (cgoLdflags []string,
|
|||||||
fmt.Fprintf(os.Stderr, "==> Export %s: %s\n", aPkg.PkgPath, pkg.ExportFile)
|
fmt.Fprintf(os.Stderr, "==> Export %s: %s\n", aPkg.PkgPath, pkg.ExportFile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
aPkg.LPkg = ret
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"go/token"
|
"go/token"
|
||||||
|
"go/types"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -29,6 +30,7 @@ import (
|
|||||||
|
|
||||||
"github.com/goplus/llgo/internal/buildtags"
|
"github.com/goplus/llgo/internal/buildtags"
|
||||||
"github.com/goplus/llgo/internal/safesplit"
|
"github.com/goplus/llgo/internal/safesplit"
|
||||||
|
llssa "github.com/goplus/llgo/ssa"
|
||||||
)
|
)
|
||||||
|
|
||||||
type cgoDecl struct {
|
type cgoDecl struct {
|
||||||
@@ -93,12 +95,21 @@ func buildCgo(ctx *context, pkg *aPackage, files []*ast.File, externs map[string
|
|||||||
mallocFix := false
|
mallocFix := false
|
||||||
for _, symbols := range externs {
|
for _, symbols := range externs {
|
||||||
for _, symbolName := range symbols {
|
for _, symbolName := range symbols {
|
||||||
if m := re.FindStringSubmatch(symbolName); len(m) > 0 {
|
lastPart := symbolName
|
||||||
cgoSymbols[symbolName] = m[3]
|
lastDot := strings.LastIndex(symbolName, ".")
|
||||||
pkgPrefix := m[1]
|
if lastDot != -1 {
|
||||||
|
lastPart = symbolName[lastDot+1:]
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(lastPart, "__cgo_") {
|
||||||
|
// func ptr var: main.__cgo_func_name
|
||||||
|
cgoSymbols[symbolName] = lastPart
|
||||||
|
} else if m := re.FindStringSubmatch(symbolName); len(m) > 0 {
|
||||||
|
prefix := m[1] // _cgo_hash_(Cfunc|Cmacro)_
|
||||||
|
name := m[3] // remaining part
|
||||||
|
cgoSymbols[symbolName] = name
|
||||||
// fix missing _cgo_9113e32b6599_Cfunc__Cmalloc
|
// fix missing _cgo_9113e32b6599_Cfunc__Cmalloc
|
||||||
if !mallocFix && m[2] == "Cfunc" {
|
if !mallocFix && m[2] == "Cfunc" {
|
||||||
mallocName := pkgPrefix + "_Cmalloc"
|
mallocName := prefix + "_Cmalloc"
|
||||||
cgoSymbols[mallocName] = "_Cmalloc"
|
cgoSymbols[mallocName] = "_Cmalloc"
|
||||||
mallocFix = true
|
mallocFix = true
|
||||||
}
|
}
|
||||||
@@ -113,7 +124,7 @@ func buildCgo(ctx *context, pkg *aPackage, files []*ast.File, externs map[string
|
|||||||
tmpName := tmpFile.Name()
|
tmpName := tmpFile.Name()
|
||||||
defer os.Remove(tmpName)
|
defer os.Remove(tmpName)
|
||||||
code := cgoHeader + "\n\n" + preamble.src
|
code := cgoHeader + "\n\n" + preamble.src
|
||||||
externDecls, err := genExternDeclsByClang(code, cflags, cgoSymbols)
|
externDecls, err := genExternDeclsByClang(pkg, code, cflags, cgoSymbols)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -137,7 +148,7 @@ type clangASTNode struct {
|
|||||||
Inner []clangASTNode `json:"inner,omitempty"`
|
Inner []clangASTNode `json:"inner,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func genExternDeclsByClang(src string, cflags []string, cgoSymbols map[string]string) (string, error) {
|
func genExternDeclsByClang(pkg *aPackage, src string, cflags []string, cgoSymbols map[string]string) (string, error) {
|
||||||
tmpSrc, err := os.CreateTemp("", "cgo-src-*.c")
|
tmpSrc, err := os.CreateTemp("", "cgo-src-*.c")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@@ -158,25 +169,37 @@ func genExternDeclsByClang(src string, cflags []string, cgoSymbols map[string]st
|
|||||||
b := strings.Builder{}
|
b := strings.Builder{}
|
||||||
var toRemove []string
|
var toRemove []string
|
||||||
for cgoName, symbolName := range cgoSymbols {
|
for cgoName, symbolName := range cgoSymbols {
|
||||||
if symbolNames[symbolName] {
|
if strings.HasPrefix(symbolName, "__cgo_") {
|
||||||
b.WriteString(fmt.Sprintf("void* %s = (void*)%s;\n", cgoName, symbolName))
|
cfuncName := symbolName[len("__cgo_"):]
|
||||||
|
cfn := pkg.LPkg.NewFunc(cfuncName, types.NewSignature(nil, nil, nil, false), llssa.InC)
|
||||||
|
cgoVar := pkg.LPkg.VarOf(cgoName)
|
||||||
|
cgoVar.ReplaceAllUsesWith(cfn.Expr)
|
||||||
toRemove = append(toRemove, cgoName)
|
toRemove = append(toRemove, cgoName)
|
||||||
} else if macroNames[symbolName] {
|
} else {
|
||||||
|
usePtr := ""
|
||||||
|
if symbolNames[symbolName] {
|
||||||
|
usePtr = "*"
|
||||||
|
} else if !macroNames[symbolName] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
/* template:
|
/* template:
|
||||||
typeof(stdout) _cgo_1574167f3838_Cmacro_stdout;
|
typeof(fputs)* _cgo_1574167f3838_Cfunc_fputs;
|
||||||
|
|
||||||
__attribute__((constructor))
|
__attribute__((constructor))
|
||||||
static void _init__cgo_1574167f3838_Cmacro_stdout() {
|
static void _init__cgo_1574167f3838_Cfunc_fputs() {
|
||||||
_cgo_1574167f3838_Cmacro_stdout = stdout;
|
_cgo_1574167f3838_Cfunc_fputs = fputs;
|
||||||
}*/
|
}*/
|
||||||
b.WriteString(fmt.Sprintf(`
|
b.WriteString(fmt.Sprintf(`
|
||||||
typeof(%s) %s;
|
typeof(%s)%s %s;
|
||||||
|
|
||||||
__attribute__((constructor))
|
__attribute__((constructor))
|
||||||
static void _init_%s() {
|
static void _init_%s() {
|
||||||
%s = %s;
|
%s = %s;
|
||||||
}
|
}
|
||||||
`, symbolName, cgoName, cgoName, cgoName, symbolName))
|
`,
|
||||||
|
symbolName, usePtr, cgoName,
|
||||||
|
cgoName,
|
||||||
|
cgoName, symbolName))
|
||||||
toRemove = append(toRemove, cgoName)
|
toRemove = append(toRemove, cgoName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,6 +117,10 @@ func (g Global) InitNil() {
|
|||||||
g.impl.SetInitializer(llvm.ConstNull(g.impl.GlobalValueType()))
|
g.impl.SetInitializer(llvm.ConstNull(g.impl.GlobalValueType()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g Global) ReplaceAllUsesWith(v Expr) {
|
||||||
|
g.impl.ReplaceAllUsesWith(v.impl)
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
// Function represents the parameters, results, and code of a function
|
// Function represents the parameters, results, and code of a function
|
||||||
|
|||||||
@@ -59,6 +59,15 @@ func (v Expr) SetOrdering(ordering AtomicOrdering) Expr {
|
|||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v Expr) SetName(alias string) Expr {
|
||||||
|
v.impl.SetName(alias)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Expr) Name() string {
|
||||||
|
return v.impl.Name()
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
type builtinTy struct {
|
type builtinTy struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user