cl: TestPython; build: PkgLinkExtern

This commit is contained in:
xushiwei
2024-05-12 13:05:15 +08:00
parent 2e3cc49782
commit acecbf587d
9 changed files with 38 additions and 62 deletions

View File

@@ -8,11 +8,23 @@ llgo - A Go compiler based on LLVM
[![GoDoc](https://pkg.go.dev/badge/github.com/goplus/llgo.svg)](https://pkg.go.dev/github.com/goplus/llgo)
[![Language](https://img.shields.io/badge/language-Go+-blue.svg)](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
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

View File

@@ -486,7 +486,7 @@ func isPhi(i ssa.Instruction) bool {
func (p *context) compilePhis(b llssa.Builder, block *ssa.BasicBlock) int {
ret := p.fn.Block(block.Index)
b.SetBlock(ret)
b.SetBlockEx(ret, llssa.AtEnd)
if ninstr := len(block.Instrs); ninstr > 0 {
if isPhi(block.Instrs[0]) {
n := 1

View File

@@ -52,6 +52,10 @@ func TestFromTestpymath(t *testing.T) {
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) {
cltest.Pkg(t, ssa.PkgRuntime, "../internal/runtime/llgo_autogen.ll")
}

View File

@@ -195,23 +195,26 @@ func buildAllPkgs(prog llssa.Program, initial []*packages.Package, mode Mode, ve
// skip packages that only contain declarations
// and set no export file
pkg.ExportFile = ""
case cl.PkgLinkIR, cl.PkgPyModule:
// skip packages that don't need to be compiled but need to be linked
case cl.PkgLinkIR, cl.PkgLinkExtern, cl.PkgPyModule:
pkgPath := pkg.PkgPath
if isPkgInLLGo(pkgPath) {
pkg.ExportFile = concatPkgLinkFiles(pkgPath)
} else {
panic("todo")
}
case cl.PkgLinkExtern:
// skip packages that don't need to be compiled but need to be linked with external library
if kind == cl.PkgLinkExtern { // need to be linked with external library
linkFile := os.ExpandEnv(strings.TrimSpace(param))
dir, lib := filepath.Split(linkFile)
command := " -l " + lib
if dir != "" {
command += " -L " + dir
}
pkg.ExportFile = command
if isMultiLinkFiles(pkg.ExportFile) {
pkg.ExportFile = command + pkg.ExportFile
} else {
pkg.ExportFile = command + " " + pkg.ExportFile
}
}
default:
buildPkg(prog, aPkg, mode, verbose)
setNeedRuntimeOrPyInit(pkg, prog.NeedRuntime(), prog.NeedPyInit())

View File

@@ -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

View File

@@ -11,7 +11,7 @@ func main() {
code := py.CompileString(c.Str(`print('Hello, World!')`), c.Str(`hello.py`), py.EvalInput)
if code != nil {
mod := py.ImportModule(c.Str("__main__"))
gbl := mod.GetDict()
gbl := mod.ModuleGetDict()
result := py.EvalCode(code, gbl, nil)

BIN
py/llgo_autogen.lla Normal file

Binary file not shown.

View File

@@ -22,18 +22,13 @@ import (
"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
// instead of an Object.
//
//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
// 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.
//
//go:linkname Import C.PyImport_Import
func Import(name *Object) *Module
func Import(name *Object) *Object
// Return the dictionary object that implements modules namespace; this object is the same
// 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
// manipulate a modules __dict__.
//
// llgo:link (*Module).GetDict C.PyModule_GetDict
func (m *Module) GetDict() *Object { return nil }
// llgo:link (*Object).ModuleGetDict C.PyModule_GetDict
func (m *Object) ModuleGetDict() *Object { return nil }
// -----------------------------------------------------------------------------

View File

@@ -128,7 +128,7 @@ func (o *Object) CallFunctionObjArgs(__llgo_va_list ...any) *Object { return nil
// llgo:link (*Object).CallMethod C.PyObject_CallMethod
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