diff --git a/_pydemo/pi/pi.go b/_pydemo/pi/pi.go index 934fe31a..239bc543 100644 --- a/_pydemo/pi/pi.go +++ b/_pydemo/pi/pi.go @@ -6,5 +6,5 @@ import ( ) func main() { - c.Printf(c.Str("pi = %f\n"), math.Pi) + c.Printf(c.Str("pi = %f\n"), math.Pi.Float64()) } diff --git a/cl/_testpy/pi/in.go b/cl/_testpy/pi/in.go index 934fe31a..239bc543 100644 --- a/cl/_testpy/pi/in.go +++ b/cl/_testpy/pi/in.go @@ -6,5 +6,5 @@ import ( ) func main() { - c.Printf(c.Str("pi = %f\n"), math.Pi) + c.Printf(c.Str("pi = %f\n"), math.Pi.Float64()) } diff --git a/cl/_testpy/pi/out.ll b/cl/_testpy/pi/out.ll index e69de29b..696cb264 100644 --- a/cl/_testpy/pi/out.ll +++ b/cl/_testpy/pi/out.ll @@ -0,0 +1,49 @@ +; ModuleID = 'main' +source_filename = "main" + +@"main.init$guard" = global ptr null +@__llgo_argc = global ptr null +@__llgo_argv = global ptr null +@0 = private unnamed_addr constant [9 x i8] c"pi = %f\0A\00", align 1 +@__llgo_py.math = external global ptr +@1 = private unnamed_addr constant [3 x i8] c"pi\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"() + 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 = load ptr, ptr @__llgo_py.math, align 8 + %3 = call ptr @PyObject_GetAttrString(ptr %2, ptr @1) + %4 = call double @PyFloat_AsDouble(ptr %3) + %5 = call i32 (ptr, ...) @printf(ptr @0, double %4) + ret void +} + +declare void @"github.com/goplus/llgo/py/math.init"() + +declare void @"github.com/goplus/llgo/internal/runtime.init"() + +declare ptr @PyObject_GetAttrString(ptr, ptr) + +declare double @PyFloat_AsDouble(ptr) + +declare i32 @printf(ptr, ...) + +declare void @Py_Initialize() diff --git a/cl/compile.go b/cl/compile.go index edcc1fde..606347a2 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -293,7 +293,7 @@ func (p *context) funcOf(fn *ssa.Function) (aFn llssa.Function, pyFn llssa.PyObj pkg := p.pkg fnName := pysymPrefix + mod + "." + name if pyFn = pkg.PyObjOf(fnName); pyFn == nil { - pyFn = pkg.NewPyFunc(fnName, fn.Signature, true) + pyFn = pkg.PyNewFunc(fnName, fn.Signature, true) return } } diff --git a/cl/compile_test.go b/cl/compile_test.go index 5b26c9e7..6f417cbe 100644 --- a/cl/compile_test.go +++ b/cl/compile_test.go @@ -29,7 +29,7 @@ func testCompile(t *testing.T, src, expected string) { } func TestFromTestpy(t *testing.T) { - cltest.FromDir(t, "pi", "./_testpy", false) + cltest.FromDir(t, "", "./_testpy", false) } func TestFromTestlibc(t *testing.T) { diff --git a/cl/import.go b/cl/import.go index 0f57b1c6..f59f0ac6 100644 --- a/cl/import.go +++ b/cl/import.go @@ -379,7 +379,7 @@ func (p *context) varOf(b llssa.Builder, v *ssa.Global) llssa.Expr { name, vtype := p.varName(pkgTypes, v) if vtype == pyVar { if kind, mod := pkgKindByScope(pkgTypes.Scope()); kind == PkgPyModule { - return b.PyLoadVar(pysymPrefix+mod, name) + return b.PyNewVar(pysymPrefix+mod, name).Expr } panic("unreachable") } diff --git a/ssa/decl.go b/ssa/decl.go index 181e47e4..fd8ecefc 100644 --- a/ssa/decl.go +++ b/ssa/decl.go @@ -282,6 +282,29 @@ func (p Function) Block(idx int) BasicBlock { // ----------------------------------------------------------------------------- +type aPyGlobal struct { + Expr +} + +type PyGlobal = *aPyGlobal + +// PyNewVar creates a Python variable. +func (b Builder) PyNewVar(modName, name string) PyGlobal { + pkg := b.Func.Pkg + modPtr := pkg.PyNewModVar(modName, false).Expr + mod := b.Load(modPtr) + return &aPyGlobal{pyVarExpr(mod, name)} +} + +func (b Builder) pyLoad(ptr Expr) Expr { + pkg := b.Func.Pkg + t := ptr.raw.Type.(*pyVarTy) + fn := pkg.pyFunc("PyObject_GetAttrString", b.Prog.tyGetAttrString()) + return b.Call(fn, t.mod, b.CStr(t.name)) +} + +// ----------------------------------------------------------------------------- + type aPyObjRef struct { Expr Obj Global @@ -290,8 +313,8 @@ type aPyObjRef struct { // PyObjRef represents a python object reference. type PyObjRef = *aPyObjRef -// NewPyFunc creates a new python function. -func (p Package) NewPyFunc(name string, sig *types.Signature, doInit bool) PyObjRef { +// PyNewFunc creates a new python function. +func (p Package) PyNewFunc(name string, sig *types.Signature, doInit bool) PyObjRef { if v, ok := p.pyobjs[name]; ok { return v } diff --git a/ssa/expr.go b/ssa/expr.go index 420ceb97..a9d1d1ef 100644 --- a/ssa/expr.go +++ b/ssa/expr.go @@ -54,6 +54,26 @@ func (v Expr) Do(b Builder) Expr { // ----------------------------------------------------------------------------- +type pyVarTy struct { + mod Expr + name string +} + +func (p pyVarTy) Underlying() types.Type { + panic("don't call") +} + +func (p pyVarTy) String() string { + return "pyVar" +} + +func pyVarExpr(mod Expr, name string) Expr { + tvar := &aType{raw: rawType{&pyVarTy{mod, name}}, kind: vkPyVarRef} + return Expr{Type: tvar} +} + +// ----------------------------------------------------------------------------- + type phisExprTy struct { phis []llvm.Value Type @@ -68,7 +88,8 @@ func (p phisExprTy) String() string { } func phisExpr(t Type, phis []llvm.Value) Expr { - return Expr{Type: &aType{raw: rawType{&phisExprTy{phis, t}}, kind: vkPhisExpr}} + tphi := &aType{raw: rawType{&phisExprTy{phis, t}}, kind: vkPhisExpr} + return Expr{Type: tphi} } // ----------------------------------------------------------------------------- @@ -513,6 +534,9 @@ func (b Builder) Load(ptr Expr) Expr { if debugInstr { log.Printf("Load %v\n", ptr.impl) } + if ptr.kind == vkPyVarRef { + return b.pyLoad(ptr) + } telem := b.Prog.Elem(ptr.Type) return Expr{llvm.CreateLoad(b.impl, telem.ll, ptr.impl), telem} } diff --git a/ssa/package.go b/ssa/package.go index 07cb0fa8..bcfe246e 100644 --- a/ssa/package.go +++ b/ssa/package.go @@ -146,6 +146,7 @@ type aProgram struct { callOneArg *types.Signature callFOArgs *types.Signature loadPyModS *types.Signature + getAttrStr *types.Signature paramObjPtr_ *types.Var @@ -497,6 +498,7 @@ func (p Program) paramObjPtr() *types.Var { return p.paramObjPtr_ } +// func(*char) *Object func (p Program) tyImportPyModule() *types.Signature { if p.pyImpTy == nil { charPtr := types.NewPointer(types.Typ[types.Int8]) @@ -507,6 +509,7 @@ func (p Program) tyImportPyModule() *types.Signature { return p.pyImpTy } +// func(*Object) *Object func (p Program) tyCallNoArgs() *types.Signature { if p.callNoArgs == nil { params := types.NewTuple(p.paramObjPtr()) @@ -515,6 +518,7 @@ func (p Program) tyCallNoArgs() *types.Signature { return p.callNoArgs } +// func(*Object, *Object) *Object func (p Program) tyCallOneArg() *types.Signature { if p.callOneArg == nil { paramObjPtr := p.paramObjPtr() @@ -525,6 +529,7 @@ func (p Program) tyCallOneArg() *types.Signature { return p.callOneArg } +// func(*Object, ...) *Object func (p Program) tyCallFunctionObjArgs() *types.Signature { if p.callFOArgs == nil { paramObjPtr := p.paramObjPtr() @@ -536,6 +541,7 @@ func (p Program) tyCallFunctionObjArgs() *types.Signature { } /* +// func(*Object, *Object, *Object) *Object func (p Program) tyCall() *types.Signature { if p.callArgs == nil { paramObjPtr := p.paramObjPtr() @@ -547,6 +553,7 @@ func (p Program) tyCall() *types.Signature { } */ +// func(*Object, uintptr, *Object) cint func (p Program) tyListSetItem() *types.Signature { if p.pyListSetI == nil { paramUintptr := types.NewParam(token.NoPos, nil, "", p.Uintptr().raw.Type) @@ -559,6 +566,7 @@ func (p Program) tyListSetItem() *types.Signature { return p.pyListSetI } +// func(uintptr) *Object func (p Program) tyNewList() *types.Signature { if p.pyNewList == nil { paramUintptr := types.NewParam(token.NoPos, nil, "", p.Uintptr().raw.Type) @@ -569,6 +577,7 @@ func (p Program) tyNewList() *types.Signature { return p.pyNewList } +// func(float64) *Object func (p Program) tyFloatFromDouble() *types.Signature { if p.callArgs == nil { paramObjPtr := p.paramObjPtr() @@ -580,16 +589,28 @@ func (p Program) tyFloatFromDouble() *types.Signature { return p.callArgs } +// func(*Object, ...) func (p Program) tyLoadPyModSyms() *types.Signature { if p.loadPyModS == nil { - objPtr := p.PyObjectPtr().raw.Type - paramObjPtr := types.NewParam(token.NoPos, nil, "mod", objPtr) + paramObjPtr := p.paramObjPtr() params := types.NewTuple(paramObjPtr, VArg()) p.loadPyModS = types.NewSignatureType(nil, nil, nil, params, nil, true) } return p.loadPyModS } +// func(*Objecg, *char) *Object +func (p Program) tyGetAttrString() *types.Signature { + if p.getAttrStr == nil { + charPtr := types.NewPointer(types.Typ[types.Int8]) + paramObjPtr := p.paramObjPtr() + params := types.NewTuple(paramObjPtr, types.NewParam(token.NoPos, nil, "", charPtr)) + results := types.NewTuple(paramObjPtr) + p.getAttrStr = types.NewSignatureType(nil, nil, nil, params, results, false) + } + return p.getAttrStr +} + // PyInit initializes Python for a main package. func (p Package) PyInit() bool { if fn := p.FuncOf("main"); fn != nil { @@ -644,10 +665,6 @@ func (b Builder) PyLoadModSyms(modName string, objs ...PyObjRef) Expr { return b.Call(fnLoad, args...) } -func (b Builder) PyLoadVar(modName, name string) Expr { - panic("todo") -} - func (b Builder) pyCall(fn Expr, args []Expr) (ret Expr) { prog := b.Prog pkg := b.Func.Pkg diff --git a/ssa/ssa_test.go b/ssa/ssa_test.go index 070344ea..57e235b6 100644 --- a/ssa/ssa_test.go +++ b/ssa/ssa_test.go @@ -143,8 +143,8 @@ func TestPyFunc(t *testing.T) { prog.SetPython(py) pkg := prog.NewPackage("bar", "foo/bar") sig := types.NewSignatureType(nil, nil, nil, nil, nil, false) - a := pkg.NewPyFunc("a", sig, false) - if pkg.NewPyFunc("a", sig, false) != a { + a := pkg.PyNewFunc("a", sig, false) + if pkg.PyNewFunc("a", sig, false) != a { t.Fatal("NewPyFunc(a) failed") } foo := pkg.PyNewModVar("foo", false) diff --git a/ssa/type.go b/ssa/type.go index 18f35630..6814b07e 100644 --- a/ssa/type.go +++ b/ssa/type.go @@ -44,6 +44,7 @@ const ( vkFuncPtr vkClosure vkPyFuncRef + vkPyVarRef vkTuple vkSlice vkPhisExpr = -1