cgo: support macros
This commit is contained in:
@@ -189,8 +189,17 @@ var (
|
||||
argvTy = types.NewPointer(types.NewPointer(types.Typ[types.Int8]))
|
||||
)
|
||||
|
||||
func isCgoCfunc(f *ssa.Function) bool {
|
||||
return strings.HasPrefix(f.Name(), "_Cfunc_")
|
||||
func isCgoCfuncOrCmacro(f *ssa.Function) bool {
|
||||
name := f.Name()
|
||||
return isCgoCfunc(name) || isCgoCmacro(name)
|
||||
}
|
||||
|
||||
func isCgoCfunc(name string) bool {
|
||||
return strings.HasPrefix(name, "_Cfunc_")
|
||||
}
|
||||
|
||||
func isCgoCmacro(name string) bool {
|
||||
return strings.HasPrefix(name, "_Cmacro_")
|
||||
}
|
||||
|
||||
func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Function, llssa.PyObjRef, int) {
|
||||
@@ -246,10 +255,11 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun
|
||||
fn.Inline(llssa.NoInline)
|
||||
}
|
||||
}
|
||||
isCgo := isCgoCfuncOrCmacro(f)
|
||||
if nblk := len(f.Blocks); nblk > 0 {
|
||||
p.cgoCalled = false
|
||||
p.cgoArgs = nil
|
||||
if isCgoCfunc(f) {
|
||||
if isCgo {
|
||||
fn.MakeBlocks(1)
|
||||
} else {
|
||||
fn.MakeBlocks(nblk) // to set fn.HasBody() = true
|
||||
@@ -278,7 +288,7 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun
|
||||
}
|
||||
p.bvals = make(map[ssa.Value]llssa.Expr)
|
||||
off := make([]int, len(f.Blocks))
|
||||
if isCgoCfunc(f) {
|
||||
if isCgo {
|
||||
p.cgoArgs = make([]llssa.Expr, len(f.Params))
|
||||
for i, param := range f.Params {
|
||||
p.cgoArgs[i] = p.compileValue(b, param)
|
||||
@@ -295,7 +305,7 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun
|
||||
doMainInit := (i == 0 && name == "main")
|
||||
doModInit := (i == 1 && isInit)
|
||||
p.compileBlock(b, block, off[i], doMainInit, doModInit)
|
||||
if isCgoCfunc(f) {
|
||||
if isCgo {
|
||||
// just process first block for performance
|
||||
break
|
||||
}
|
||||
@@ -409,36 +419,46 @@ func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, do
|
||||
if funcs, ok := p.cgoFuncs[fname]; ok {
|
||||
cgoFuncs = funcs
|
||||
}
|
||||
fnName := block.Parent().Name()
|
||||
cgoReturned := false
|
||||
isCgoCfunc := isCgoCfunc(fnName)
|
||||
isCgoCmacro := isCgoCmacro(fnName)
|
||||
for i, instr := range instrs {
|
||||
if i == 1 && doModInit && p.state == pkgInPatch { // in patch package but no pkgFNoOldInit
|
||||
initFnNameOld := initFnNameOfHasPatch(p.fn.Name())
|
||||
fnOld := pkg.NewFunc(initFnNameOld, llssa.NoArgsNoRet, llssa.InC)
|
||||
b.Call(fnOld.Expr)
|
||||
}
|
||||
if isCgoCfunc(block.Parent()) {
|
||||
if isCgoCfunc || isCgoCmacro {
|
||||
switch instr := instr.(type) {
|
||||
case *ssa.Alloc:
|
||||
// return value allocation
|
||||
p.compileInstr(b, instr)
|
||||
case *ssa.UnOp:
|
||||
// load cgo function pointer
|
||||
if instr.Op == token.MUL && strings.HasPrefix(instr.X.Name(), "_cgo_") {
|
||||
cgoFuncs = append(cgoFuncs, instr.X.Name())
|
||||
varName := instr.X.Name()
|
||||
if instr.Op == token.MUL && strings.HasPrefix(varName, "_cgo_") {
|
||||
cgoFuncs = append(cgoFuncs, varName)
|
||||
p.cgoFuncs[fname] = cgoFuncs
|
||||
p.compileInstr(b, instr)
|
||||
}
|
||||
case *ssa.Call:
|
||||
// call c function
|
||||
p.compileInstr(b, instr)
|
||||
p.cgoCalled = true
|
||||
if isCgoCmacro {
|
||||
p.cgoRet = p.compileValue(b, instr.Call.Args[0])
|
||||
p.cgoCalled = true
|
||||
} else {
|
||||
// call c function
|
||||
p.compileInstr(b, instr)
|
||||
p.cgoCalled = true
|
||||
}
|
||||
case *ssa.Return:
|
||||
// return cgo function result
|
||||
if len(instr.Results) > 0 {
|
||||
b.Return(p.cgoRet)
|
||||
} else {
|
||||
b.Return(llssa.Nil)
|
||||
if isCgoCmacro {
|
||||
ty := p.type_(instr.Results[0].Type(), llssa.InGo)
|
||||
p.cgoRet.Type = p.prog.Pointer(ty)
|
||||
p.cgoRet = b.Load(p.cgoRet)
|
||||
}
|
||||
b.Return(p.cgoRet)
|
||||
cgoReturned = true
|
||||
}
|
||||
} else {
|
||||
@@ -446,18 +466,14 @@ func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, do
|
||||
}
|
||||
}
|
||||
// is cgo cfunc but not return yet, some funcs has multiple blocks
|
||||
if isCgoCfunc(block.Parent()) && !cgoReturned {
|
||||
if (isCgoCfunc || isCgoCmacro) && !cgoReturned {
|
||||
if !p.cgoCalled {
|
||||
panic("cgo cfunc not called")
|
||||
}
|
||||
for _, block := range block.Parent().Blocks {
|
||||
for _, instr := range block.Instrs {
|
||||
if instr, ok := instr.(*ssa.Return); ok {
|
||||
if len(instr.Results) > 0 {
|
||||
b.Return(p.cgoRet)
|
||||
} else {
|
||||
b.Return(llssa.Nil)
|
||||
}
|
||||
if _, ok := instr.(*ssa.Return); ok {
|
||||
b.Return(p.cgoRet)
|
||||
goto end
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user