cl: TestPython; build: PkgLinkExtern
This commit is contained in:
16
README.md
16
README.md
@@ -8,11 +8,23 @@ llgo - A Go compiler based on LLVM
|
|||||||
[](https://pkg.go.dev/github.com/goplus/llgo)
|
[](https://pkg.go.dev/github.com/goplus/llgo)
|
||||||
[](https://github.com/goplus/gop)
|
[](https://github.com/goplus/gop)
|
||||||
|
|
||||||
This is a Go compiler based on LLVM in order to better integrate Go with the C ecosystem. It's a subproject of [the Go+ project](https://github.com/goplus/gop).
|
This is a Go compiler based on LLVM in order to better integrate Go with the C ecosystem including Python. It's a subproject of [the Go+ project](https://github.com/goplus/gop).
|
||||||
|
|
||||||
## C standard libary support
|
## C standard libary support
|
||||||
|
|
||||||
See [github.com/goplus/llgo/c](https://pkg.go.dev/github.com/goplus/llgo/c).
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "github.com/goplus/llgo/c"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
c.Printf(c.Str("Hello world\n"))
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This is a simple example of calling the C `printf` function to print `Hello world`. Here, `c.Str` is not a function for converting a Go string to a C string, but a built-in instruction supported by llgo for generating a C string constant.
|
||||||
|
|
||||||
|
See [github.com/goplus/llgo/c](https://pkg.go.dev/github.com/goplus/llgo/c) for more detials.
|
||||||
|
|
||||||
|
|
||||||
## Python support
|
## Python support
|
||||||
|
|||||||
@@ -486,7 +486,7 @@ func isPhi(i ssa.Instruction) bool {
|
|||||||
|
|
||||||
func (p *context) compilePhis(b llssa.Builder, block *ssa.BasicBlock) int {
|
func (p *context) compilePhis(b llssa.Builder, block *ssa.BasicBlock) int {
|
||||||
ret := p.fn.Block(block.Index)
|
ret := p.fn.Block(block.Index)
|
||||||
b.SetBlock(ret)
|
b.SetBlockEx(ret, llssa.AtEnd)
|
||||||
if ninstr := len(block.Instrs); ninstr > 0 {
|
if ninstr := len(block.Instrs); ninstr > 0 {
|
||||||
if isPhi(block.Instrs[0]) {
|
if isPhi(block.Instrs[0]) {
|
||||||
n := 1
|
n := 1
|
||||||
|
|||||||
@@ -52,6 +52,10 @@ func TestFromTestpymath(t *testing.T) {
|
|||||||
cltest.Pkg(t, ssa.PkgPython+"/math", "../py/math/llgo_autogen.ll")
|
cltest.Pkg(t, ssa.PkgPython+"/math", "../py/math/llgo_autogen.ll")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPython(t *testing.T) {
|
||||||
|
cltest.Pkg(t, ssa.PkgPython, "../py/llgo_autogen.ll")
|
||||||
|
}
|
||||||
|
|
||||||
func TestRuntime(t *testing.T) {
|
func TestRuntime(t *testing.T) {
|
||||||
cltest.Pkg(t, ssa.PkgRuntime, "../internal/runtime/llgo_autogen.ll")
|
cltest.Pkg(t, ssa.PkgRuntime, "../internal/runtime/llgo_autogen.ll")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -195,23 +195,26 @@ func buildAllPkgs(prog llssa.Program, initial []*packages.Package, mode Mode, ve
|
|||||||
// skip packages that only contain declarations
|
// skip packages that only contain declarations
|
||||||
// and set no export file
|
// and set no export file
|
||||||
pkg.ExportFile = ""
|
pkg.ExportFile = ""
|
||||||
case cl.PkgLinkIR, cl.PkgPyModule:
|
case cl.PkgLinkIR, cl.PkgLinkExtern, cl.PkgPyModule:
|
||||||
// skip packages that don't need to be compiled but need to be linked
|
|
||||||
pkgPath := pkg.PkgPath
|
pkgPath := pkg.PkgPath
|
||||||
if isPkgInLLGo(pkgPath) {
|
if isPkgInLLGo(pkgPath) {
|
||||||
pkg.ExportFile = concatPkgLinkFiles(pkgPath)
|
pkg.ExportFile = concatPkgLinkFiles(pkgPath)
|
||||||
} else {
|
} else {
|
||||||
panic("todo")
|
panic("todo")
|
||||||
}
|
}
|
||||||
case cl.PkgLinkExtern:
|
if kind == cl.PkgLinkExtern { // need to be linked with external library
|
||||||
// skip packages that don't need to be compiled but need to be linked with external library
|
|
||||||
linkFile := os.ExpandEnv(strings.TrimSpace(param))
|
linkFile := os.ExpandEnv(strings.TrimSpace(param))
|
||||||
dir, lib := filepath.Split(linkFile)
|
dir, lib := filepath.Split(linkFile)
|
||||||
command := " -l " + lib
|
command := " -l " + lib
|
||||||
if dir != "" {
|
if dir != "" {
|
||||||
command += " -L " + dir
|
command += " -L " + dir
|
||||||
}
|
}
|
||||||
pkg.ExportFile = command
|
if isMultiLinkFiles(pkg.ExportFile) {
|
||||||
|
pkg.ExportFile = command + pkg.ExportFile
|
||||||
|
} else {
|
||||||
|
pkg.ExportFile = command + " " + pkg.ExportFile
|
||||||
|
}
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
buildPkg(prog, aPkg, mode, verbose)
|
buildPkg(prog, aPkg, mode, verbose)
|
||||||
setNeedRuntimeOrPyInit(pkg, prog.NeedRuntime(), prog.NeedPyInit())
|
setNeedRuntimeOrPyInit(pkg, prog.NeedRuntime(), prog.NeedPyInit())
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pyimport
|
|
||||||
|
|
||||||
import (
|
|
||||||
_ "unsafe"
|
|
||||||
|
|
||||||
"github.com/goplus/llgo/c"
|
|
||||||
"github.com/goplus/llgo/py"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
LLGoPackage = "decl"
|
|
||||||
)
|
|
||||||
|
|
||||||
/*
|
|
||||||
func init() {
|
|
||||||
py.Initialize()
|
|
||||||
py.SetProgramName(*c.Argv)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
//go:linkname Module C.PyImport_ImportModule
|
|
||||||
func Module(name *c.Char) *py.Module
|
|
||||||
@@ -11,7 +11,7 @@ func main() {
|
|||||||
code := py.CompileString(c.Str(`print('Hello, World!')`), c.Str(`hello.py`), py.EvalInput)
|
code := py.CompileString(c.Str(`print('Hello, World!')`), c.Str(`hello.py`), py.EvalInput)
|
||||||
if code != nil {
|
if code != nil {
|
||||||
mod := py.ImportModule(c.Str("__main__"))
|
mod := py.ImportModule(c.Str("__main__"))
|
||||||
gbl := mod.GetDict()
|
gbl := mod.ModuleGetDict()
|
||||||
|
|
||||||
result := py.EvalCode(code, gbl, nil)
|
result := py.EvalCode(code, gbl, nil)
|
||||||
|
|
||||||
|
|||||||
BIN
py/llgo_autogen.lla
Normal file
BIN
py/llgo_autogen.lla
Normal file
Binary file not shown.
13
py/module.go
13
py/module.go
@@ -22,18 +22,13 @@ import (
|
|||||||
"github.com/goplus/llgo/c"
|
"github.com/goplus/llgo/c"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Module represents a Python module object.
|
|
||||||
type Module struct {
|
|
||||||
Object
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
// This is a wrapper around py.Import which takes a const char* as an argument
|
// This is a wrapper around py.Import which takes a const char* as an argument
|
||||||
// instead of an Object.
|
// instead of an Object.
|
||||||
//
|
//
|
||||||
//go:linkname ImportModule C.PyImport_ImportModule
|
//go:linkname ImportModule C.PyImport_ImportModule
|
||||||
func ImportModule(name *c.Char) *Module
|
func ImportModule(name *c.Char) *Object
|
||||||
|
|
||||||
// This is a higher-level interface that calls the current “import hook function” (with
|
// This is a higher-level interface that calls the current “import hook function” (with
|
||||||
// an explicit level of 0, meaning absolute import). It invokes the __import__() function
|
// an explicit level of 0, meaning absolute import). It invokes the __import__() function
|
||||||
@@ -43,7 +38,7 @@ func ImportModule(name *c.Char) *Module
|
|||||||
// This function always uses absolute imports.
|
// This function always uses absolute imports.
|
||||||
//
|
//
|
||||||
//go:linkname Import C.PyImport_Import
|
//go:linkname Import C.PyImport_Import
|
||||||
func Import(name *Object) *Module
|
func Import(name *Object) *Object
|
||||||
|
|
||||||
// Return the dictionary object that implements module’s namespace; this object is the same
|
// Return the dictionary object that implements module’s namespace; this object is the same
|
||||||
// as the __dict__ attribute of the module object. If module is not a module object (or a
|
// as the __dict__ attribute of the module object. If module is not a module object (or a
|
||||||
@@ -52,7 +47,7 @@ func Import(name *Object) *Module
|
|||||||
// It is recommended extensions use other Module and Object functions rather than directly
|
// It is recommended extensions use other Module and Object functions rather than directly
|
||||||
// manipulate a module’s __dict__.
|
// manipulate a module’s __dict__.
|
||||||
//
|
//
|
||||||
// llgo:link (*Module).GetDict C.PyModule_GetDict
|
// llgo:link (*Object).ModuleGetDict C.PyModule_GetDict
|
||||||
func (m *Module) GetDict() *Object { return nil }
|
func (m *Object) ModuleGetDict() *Object { return nil }
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ func (o *Object) CallFunctionObjArgs(__llgo_va_list ...any) *Object { return nil
|
|||||||
|
|
||||||
// llgo:link (*Object).CallMethod C.PyObject_CallMethod
|
// llgo:link (*Object).CallMethod C.PyObject_CallMethod
|
||||||
func (o *Object) CallMethod(name *c.Char, format *c.Char, __llgo_va_list ...any) *Object {
|
func (o *Object) CallMethod(name *c.Char, format *c.Char, __llgo_va_list ...any) *Object {
|
||||||
panic("unreachable")
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// llgo:link (*Object).CallMethodObjArgs C.PyObject_CallMethodObjArgs
|
// llgo:link (*Object).CallMethodObjArgs C.PyObject_CallMethodObjArgs
|
||||||
|
|||||||
Reference in New Issue
Block a user