diff --git a/cl/_testpy/pow/in.go b/cl/_testpy/pow/in.go new file mode 100644 index 00000000..6dc98ead --- /dev/null +++ b/cl/_testpy/pow/in.go @@ -0,0 +1,12 @@ +package main + +import ( + "github.com/goplus/llgo/c" + "github.com/goplus/llgo/py" + "github.com/goplus/llgo/py/math" +) + +func main() { + x := math.Pow(py.Float(2), py.Float(3)) + c.Printf(c.Str("pow(2, 3) = %f\n"), x.Float64()) +} diff --git a/cl/_testpy/pow/out.ll b/cl/_testpy/pow/out.ll new file mode 100644 index 00000000..e1bd0f04 --- /dev/null +++ b/cl/_testpy/pow/out.ll @@ -0,0 +1,58 @@ +; ModuleID = 'main' +source_filename = "main" + +@"main.init$guard" = global ptr null +@__llgo_argc = global ptr null +@__llgo_argv = global ptr null +@__llgo_py.math.pow = linkonce global ptr null +@0 = private unnamed_addr constant [16 x i8] c"pow(2, 3) = %f\0A\00", align 1 +@__llgo_py.math = external global ptr +@1 = private unnamed_addr constant [4 x i8] c"pow\00", align 1 + +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 + call void @"github.com/goplus/llgo/py/math.init"() + %1 = load ptr, ptr @__llgo_py.math, align 8 + call void (ptr, ...) @llgoLoadPyModSyms(ptr %1, ptr @1, ptr @__llgo_py.math.pow, ptr null) + br label %_llgo_2 + +_llgo_2: ; preds = %_llgo_1, %_llgo_0 + ret void +} + +define void @main(i32 %0, ptr %1) { +_llgo_0: + call void @Py_Initialize() + 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() + %2 = call ptr @PyFloat_FromDouble(double 2.000000e+00) + %3 = call ptr @PyFloat_FromDouble(double 3.000000e+00) + %4 = load ptr, ptr @__llgo_py.math.pow, align 8 + %5 = call ptr (ptr, ...) @PyObject_CallFunctionObjArgs(ptr %4, ptr %2, ptr %3, ptr null) + %6 = call double @PyFloat_AsDouble(ptr %5) + %7 = call i32 (ptr, ...) @printf(ptr @0, double %6) + ret void +} + +declare void @"github.com/goplus/llgo/py/math.init"() + +declare void @"github.com/goplus/llgo/internal/runtime.init"() + +declare ptr @PyFloat_FromDouble(double) + +declare ptr @PyObject_CallFunctionObjArgs(ptr, ...) + +declare double @PyFloat_AsDouble(ptr) + +declare i32 @printf(ptr, ...) + +declare void @llgoLoadPyModSyms(ptr, ...) + +declare void @Py_Initialize() diff --git a/ssa/expr.go b/ssa/expr.go index 5097234c..b532984a 100644 --- a/ssa/expr.go +++ b/ssa/expr.go @@ -78,6 +78,11 @@ func (p Program) Null(t Type) Expr { return Expr{llvm.ConstNull(t.ll), t} } +// PyNull returns a null *PyObject constant expression. +func (p Program) PyNull() Expr { + return p.Null(p.PyObjectPtr()) +} + // BoolVal returns a boolean constant expression. func (p Program) BoolVal(v bool) Expr { t := p.Bool() diff --git a/ssa/package.go b/ssa/package.go index eeee0f24..7de579cb 100644 --- a/ssa/package.go +++ b/ssa/package.go @@ -130,6 +130,7 @@ type aProgram struct { voidPtr Type boolTy Type cstrTy Type + cintTy Type stringTy Type uintptrTy Type intTy Type @@ -137,11 +138,17 @@ type aProgram struct { pyObjPtr Type pyObjPPtr Type - pyImpTy *types.Signature + pyImpTy *types.Signature + //pyNewList *types.Signature + //pyListSetI *types.Signature + //callArgs *types.Signature callNoArgs *types.Signature callOneArg *types.Signature + callFOArgs *types.Signature loadPyModS *types.Signature + paramObjPtr_ *types.Var + NeedRuntime bool NeedPyInit bool } @@ -328,6 +335,13 @@ func (p Program) Any() Type { return p.anyTy } +func (p Program) CInt() Type { + if p.cintTy == nil { // C.int + p.cintTy = p.rawType(types.Typ[types.Int32]) // TODO(xsw): support 64-bit + } + return p.cintTy +} + // Int returns int type. func (p Program) Int() Type { if p.intTy == nil { @@ -475,12 +489,19 @@ func (p *Package) WriteFile(file string) (err error) { // ----------------------------------------------------------------------------- +func (p Program) paramObjPtr() *types.Var { + if p.paramObjPtr_ == nil { + objPtr := p.PyObjectPtr().raw.Type + p.paramObjPtr_ = types.NewParam(token.NoPos, nil, "", objPtr) + } + return p.paramObjPtr_ +} + func (p Program) tyImportPyModule() *types.Signature { if p.pyImpTy == nil { charPtr := types.NewPointer(types.Typ[types.Int8]) - objPtr := p.PyObjectPtr().raw.Type params := types.NewTuple(types.NewParam(token.NoPos, nil, "", charPtr)) - results := types.NewTuple(types.NewParam(token.NoPos, nil, "", objPtr)) + results := types.NewTuple(p.paramObjPtr()) p.pyImpTy = types.NewSignatureType(nil, nil, nil, params, results, false) } return p.pyImpTy @@ -488,9 +509,7 @@ func (p Program) tyImportPyModule() *types.Signature { func (p Program) tyCallNoArgs() *types.Signature { if p.callNoArgs == nil { - objPtr := p.PyObjectPtr().raw.Type - paramObjPtr := types.NewParam(token.NoPos, nil, "", objPtr) - params := types.NewTuple(paramObjPtr) + params := types.NewTuple(p.paramObjPtr()) p.callNoArgs = types.NewSignatureType(nil, nil, nil, params, params, false) } return p.callNoArgs @@ -498,8 +517,7 @@ func (p Program) tyCallNoArgs() *types.Signature { func (p Program) tyCallOneArg() *types.Signature { if p.callOneArg == nil { - objPtr := p.PyObjectPtr().raw.Type - paramObjPtr := types.NewParam(token.NoPos, nil, "", objPtr) + paramObjPtr := p.paramObjPtr() params := types.NewTuple(paramObjPtr, paramObjPtr) results := types.NewTuple(paramObjPtr) p.callOneArg = types.NewSignatureType(nil, nil, nil, params, results, false) @@ -507,6 +525,50 @@ func (p Program) tyCallOneArg() *types.Signature { return p.callOneArg } +func (p Program) tyCallFunctionObjArgs() *types.Signature { + if p.callFOArgs == nil { + paramObjPtr := p.paramObjPtr() + params := types.NewTuple(paramObjPtr, VArg()) + results := types.NewTuple(paramObjPtr) + p.callFOArgs = types.NewSignatureType(nil, nil, nil, params, results, false) + } + return p.callFOArgs +} + +/* +func (p Program) tyCall() *types.Signature { + if p.callArgs == nil { + paramObjPtr := p.paramObjPtr() + params := types.NewTuple(paramObjPtr, paramObjPtr, paramObjPtr) + results := types.NewTuple(paramObjPtr) + p.callArgs = types.NewSignatureType(nil, nil, nil, params, results, false) + } + return p.callArgs +} + +func (p Program) tyListSetItem() *types.Signature { + if p.pyListSetI == nil { + paramUintptr := types.NewParam(token.NoPos, nil, "", p.Uintptr().raw.Type) + paramCInt := types.NewParam(token.NoPos, nil, "", p.CInt().raw.Type) + paramObjPtr := p.paramObjPtr() + params := types.NewTuple(paramObjPtr, paramUintptr, paramObjPtr) + results := types.NewTuple(paramCInt) + p.pyListSetI = types.NewSignatureType(nil, nil, nil, params, results, false) + } + return p.pyListSetI +} + +func (p Program) tyNewList() *types.Signature { + if p.pyNewList == nil { + paramUintptr := types.NewParam(token.NoPos, nil, "", p.Uintptr().raw.Type) + params := types.NewTuple(paramUintptr) + results := types.NewTuple(p.paramObjPtr()) + p.pyNewList = types.NewSignatureType(nil, nil, nil, params, results, false) + } + return p.pyNewList +} +*/ + func (p Program) tyLoadPyModSyms() *types.Signature { if p.loadPyModS == nil { objPtr := p.PyObjectPtr().raw.Type @@ -586,11 +648,47 @@ func (b Builder) pyCall(fn Expr, args []Expr) (ret Expr) { call := pkg.pyFunc("PyObject_CallOneArg", prog.tyCallOneArg()) ret = b.Call(call, fn, args[0]) default: - panic("todo") + call := pkg.pyFunc("PyObject_CallFunctionObjArgs", prog.tyCallFunctionObjArgs()) + n = len(args) + callargs := make([]Expr, n+2) + callargs[0] = fn + copy(callargs[1:], args) + callargs[n+1] = prog.PyNull() + ret = b.Call(call, callargs...) } return } +/* +// PyNewList(n uintptr) *Object +func (b Builder) PyNewList(n Expr) (ret Expr) { + prog := b.Prog + pkg := b.Func.Pkg + fn := pkg.pyFunc("PyList_New", prog.tyNewList()) + return b.Call(fn, n) +} + +// PyListSetItem(list *Object, index uintptr, item *Object) c.Int +func (b Builder) PyListSetItem(list, index, item Expr) (ret Expr) { + prog := b.Prog + pkg := b.Func.Pkg + fn := pkg.pyFunc("PyList_SetItem", prog.tyListSetItem()) + return b.Call(fn, list, index, item) +} + +// PyList(items ...*Object) *Object +func (b Builder) PyList(args ...Expr) (ret Expr) { + prog := b.Prog + n := len(args) + uintPtr := prog.Uintptr() + list := b.PyNewList(prog.IntVal(uint64(n), uintPtr)) + for i, arg := range args { + b.PyListSetItem(list, prog.IntVal(uint64(i), uintPtr), arg) + } + return list +} +*/ + // CallPyInit calls Py_Initialize. func (b Builder) CallPyInit() (ret Expr) { fn := b.Func.Pkg.pyFunc("Py_Initialize", NoArgsNoRet)