Compare commits
62 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1463ed4835 | ||
|
|
b959de18d5 | ||
|
|
edac3f73c2 | ||
|
|
388b19eed5 | ||
|
|
a337136389 | ||
|
|
31d5a8ac10 | ||
|
|
46527f56ce | ||
|
|
a575c17eca | ||
|
|
a6ea3b1e6f | ||
|
|
4d2ad842a4 | ||
|
|
ce0f5f3797 | ||
|
|
9e0d22ac90 | ||
|
|
ddc2c56115 | ||
|
|
acfbe6902a | ||
|
|
f7dfab481b | ||
|
|
23692430d5 | ||
|
|
03fe594339 | ||
|
|
45babef689 | ||
|
|
9ac0450255 | ||
|
|
b1d55f657d | ||
|
|
aac5e7b3cd | ||
|
|
791634c377 | ||
|
|
090149eab6 | ||
|
|
acecbf587d | ||
|
|
4ef46971d0 | ||
|
|
2e3cc49782 | ||
|
|
8a0189b079 | ||
|
|
0edd7f6df0 | ||
|
|
0b058bc2e8 | ||
|
|
f9ef9cab81 | ||
|
|
fbb2150d88 | ||
|
|
0912f1f509 | ||
|
|
64c13fa9ae | ||
|
|
2a5f9d9641 | ||
|
|
6c32fe87e6 | ||
|
|
09e9cc99d3 | ||
|
|
94a7ee024a | ||
|
|
a2d7a8c978 | ||
|
|
15499ddc14 | ||
|
|
97cb312386 | ||
|
|
92827a1f04 | ||
|
|
00222c7808 | ||
|
|
427d87be68 | ||
|
|
2560a333b6 | ||
|
|
c6b76db789 | ||
|
|
1414853fce | ||
|
|
cbe384a3be | ||
|
|
cca46573ea | ||
|
|
2589c23998 | ||
|
|
29830865d9 | ||
|
|
35dbc7b0b5 | ||
|
|
cd266213ce | ||
|
|
875eadeb19 | ||
|
|
67896c63a7 | ||
|
|
c643f734e9 | ||
|
|
31d91f5e87 | ||
|
|
2a92f1bc55 | ||
|
|
d9db5528f5 | ||
|
|
22a4ffb78b | ||
|
|
1fb37c37fe | ||
|
|
aae663e5e5 | ||
|
|
e985eda857 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -18,6 +18,7 @@ _go/
|
|||||||
_runtime/
|
_runtime/
|
||||||
_tinygo/
|
_tinygo/
|
||||||
build.dir/
|
build.dir/
|
||||||
|
.vscode/
|
||||||
|
|
||||||
# Test binary, built with `go test -c`
|
# Test binary, built with `go test -c`
|
||||||
*.test
|
*.test
|
||||||
|
|||||||
73
README.md
73
README.md
@@ -8,7 +8,51 @@ 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
|
||||||
|
|
||||||
|
```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
|
||||||
|
|
||||||
|
You can import a Python library in llgo! For example:
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/py"
|
||||||
|
"github.com/goplus/llgo/py/math"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
x := math.Sqrt(py.Float(2))
|
||||||
|
c.Printf(c.Str("sqrt(2) = %f\n"), x.Float64())
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Here, We call `py.Float(2)` to create a Python floating point number 2, and pass it to Python’s `math.sqrt` to get `x`. Then use `x.Float64()` to convert the Python object to Go's `float64` type, and finally we print the value through C `printf`.
|
||||||
|
|
||||||
|
|
||||||
|
## Other frequently used libraries
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
|
||||||
## How to install
|
## How to install
|
||||||
|
|
||||||
@@ -46,11 +90,36 @@ The `_demo` directory contains our demos (it start with `_` to prevent the `go`
|
|||||||
* [qsort](_demo/qsort/qsort.go): call C function with a callback (eg. qsort)
|
* [qsort](_demo/qsort/qsort.go): call C function with a callback (eg. qsort)
|
||||||
* [genints](_demo/genints/genints.go): various forms of closure usage (including C function, recv.method and anonymous function)
|
* [genints](_demo/genints/genints.go): various forms of closure usage (including C function, recv.method and anonymous function)
|
||||||
* [llama2-c](_demo/llama2-c): inference Llama 2 (It's the first llgo AI example)
|
* [llama2-c](_demo/llama2-c): inference Llama 2 (It's the first llgo AI example)
|
||||||
* [hellopy](https://github.com/goplus/cpython/blob/main/_demo/hellopy/hello.go): link Python to Go and say `Hello world`
|
|
||||||
|
And the `_pydemo` directory contains python related demos:
|
||||||
|
|
||||||
|
* [callpy](_pydemo/callpy/callpy.go): call Python standard library function `math.sqrt`
|
||||||
|
|
||||||
|
|
||||||
### How to run demos
|
### How to run demos
|
||||||
|
|
||||||
|
To run the demos in directory `_demo`:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cd <demo-directory> # eg. cd _demo/genints
|
cd <demo-directory> # eg. cd _demo/genints
|
||||||
llgo run .
|
llgo run .
|
||||||
```
|
```
|
||||||
|
|
||||||
|
To run the demos in directory `_pydemo`, you need to set the `LLGO_LIB_PYTHON` environment variable first. Assuming you use Python 3.12, and the `libpython3.12.so` (or `libpython3.12.dylib` or `python3.12.lib`) file is in the /foo/bar directory, then you need to set `LLGO_LIB_PYTHON` to:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
export LLGO_LIB_PYTHON=/foo/bar/python3.12
|
||||||
|
```
|
||||||
|
|
||||||
|
For example, `/opt/homebrew/Frameworks/Python.framework/Versions/3.12/libpython3.12.dylib` is a typical python lib location under macOS. So we should set it like this:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
export LLGO_LIB_PYTHON=/opt/homebrew/Frameworks/Python.framework/Versions/3.12/python3.12
|
||||||
|
```
|
||||||
|
|
||||||
|
Then you can run the demos in directory `_pydemo`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd <demo-directory> # eg. cd _pydemo/callpy
|
||||||
|
llgo run .
|
||||||
|
```
|
||||||
|
|||||||
12
_pydemo/callpy/callpy.go
Normal file
12
_pydemo/callpy/callpy.go
Normal file
@@ -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.Sqrt(py.Float(2))
|
||||||
|
c.Printf(c.Str("sqrt(2) = %f\n"), x.Float64())
|
||||||
|
}
|
||||||
2
c/c.go
2
c/c.go
@@ -66,7 +66,7 @@ func Memset(s Pointer, c Int, n uintptr) Pointer
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
//go:linkname GoStringData github.com/goplus/llgo/internal/runtime.StringData
|
//go:linkname GoStringData llgo.stringData
|
||||||
func GoStringData(string) *Char
|
func GoStringData(string) *Char
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/goplus/llgo/x/ar"
|
"github.com/goplus/llgo/xtool/ar"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/goplus/llgo/x/clang/parser"
|
"github.com/goplus/llgo/xtool/clang/parser"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/goplus/llgo/x/clang/preprocessor"
|
"github.com/goplus/llgo/xtool/clang/preprocessor"
|
||||||
)
|
)
|
||||||
|
|
||||||
func usage() {
|
func usage() {
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ func main() {
|
|||||||
|
|
||||||
llgenDir(dir + "/cl/_testlibc")
|
llgenDir(dir + "/cl/_testlibc")
|
||||||
llgenDir(dir + "/cl/_testrt")
|
llgenDir(dir + "/cl/_testrt")
|
||||||
|
llgenDir(dir+"/cl/_testpy", "")
|
||||||
llgenDir(dir+"/cl/_testdata", "")
|
llgenDir(dir+"/cl/_testdata", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/goplus/llgo/x/env/llvm"
|
"github.com/goplus/llgo/xtool/env/llvm"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/goplus/llgo/x/env/llvm"
|
"github.com/goplus/llgo/xtool/env/llvm"
|
||||||
"github.com/goplus/llgo/x/nm"
|
"github.com/goplus/llgo/xtool/nm"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -73,6 +73,11 @@ func makeIndex() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func query(q string) {
|
func query(q string) {
|
||||||
|
if len(q) > 0 {
|
||||||
|
if c := q[0]; c != '*' && c != '_' {
|
||||||
|
q = "_" + q
|
||||||
|
}
|
||||||
|
}
|
||||||
files, err := nm.Query(indexDir(), q)
|
files, err := nm.Query(indexDir(), q)
|
||||||
check(err)
|
check(err)
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
|
|||||||
@@ -13,6 +13,14 @@ func gwrite(b []byte) {
|
|||||||
c.Printf(c.Str("%s"), b)
|
c.Printf(c.Str("%s"), b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func printbool(v bool) {
|
||||||
|
if v {
|
||||||
|
printstring("true")
|
||||||
|
} else {
|
||||||
|
printstring("false")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func printfloat(v float64) {
|
func printfloat(v float64) {
|
||||||
switch {
|
switch {
|
||||||
case v != v:
|
case v != v:
|
||||||
@@ -177,14 +185,37 @@ func main() {
|
|||||||
printnl()
|
printnl()
|
||||||
prinfsub(100.1)
|
prinfsub(100.1)
|
||||||
printnl()
|
printnl()
|
||||||
printnum(float32(1e9))
|
printany(float32(1e9))
|
||||||
printnl()
|
printnl()
|
||||||
printnum(float64(2e9))
|
printany(float64(2e9))
|
||||||
|
printnl()
|
||||||
|
var b bool = true
|
||||||
|
if b == true && b != false {
|
||||||
|
println("check bool", b)
|
||||||
|
}
|
||||||
|
n1 := 0b1001
|
||||||
|
n2 := 0b0011
|
||||||
|
println("check &^", n1&^n2 == 0b1000, n2&^n1 == 0b0010)
|
||||||
|
println(true, false, 'a', 'A', rune('中'),
|
||||||
|
int8(1), int16(2), int32(3), int64(4), 5,
|
||||||
|
uint8(1), uint16(2), uint32(3), uint64(4), uintptr(5),
|
||||||
|
"llgo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func println(args ...any) {
|
||||||
|
for i, v := range args {
|
||||||
|
if i != 0 {
|
||||||
|
printstring(" ")
|
||||||
|
}
|
||||||
|
printany(v)
|
||||||
|
}
|
||||||
printnl()
|
printnl()
|
||||||
}
|
}
|
||||||
|
|
||||||
func printnum(v any) {
|
func printany(v any) {
|
||||||
switch v := v.(type) {
|
switch v := v.(type) {
|
||||||
|
case bool:
|
||||||
|
printbool(v)
|
||||||
case int:
|
case int:
|
||||||
printint(int64(v))
|
printint(int64(v))
|
||||||
case int8:
|
case int8:
|
||||||
@@ -211,6 +242,8 @@ func printnum(v any) {
|
|||||||
printfloat(float64(v))
|
printfloat(float64(v))
|
||||||
case float64:
|
case float64:
|
||||||
printfloat(float64(v))
|
printfloat(float64(v))
|
||||||
|
case string:
|
||||||
|
printstring(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,13 +13,19 @@ source_filename = "main"
|
|||||||
@__llgo_argc = global ptr null
|
@__llgo_argc = global ptr null
|
||||||
@__llgo_argv = global ptr null
|
@__llgo_argv = global ptr null
|
||||||
@1 = private unnamed_addr constant [5 x i8] c"llgo\00", align 1
|
@1 = private unnamed_addr constant [5 x i8] c"llgo\00", align 1
|
||||||
@2 = private unnamed_addr constant [4 x i8] c"NaN\00", align 1
|
@2 = private unnamed_addr constant [11 x i8] c"check bool\00", align 1
|
||||||
@3 = private unnamed_addr constant [5 x i8] c"+Inf\00", align 1
|
@3 = private unnamed_addr constant [9 x i8] c"check &^\00", align 1
|
||||||
@4 = private unnamed_addr constant [5 x i8] c"-Inf\00", align 1
|
@4 = private unnamed_addr constant [5 x i8] c"llgo\00", align 1
|
||||||
@5 = private unnamed_addr constant [17 x i8] c"0123456789abcdef\00", align 1
|
@5 = private unnamed_addr constant [5 x i8] c"true\00", align 1
|
||||||
@6 = private unnamed_addr constant [2 x i8] c"-\00", align 1
|
@6 = private unnamed_addr constant [6 x i8] c"false\00", align 1
|
||||||
@7 = private unnamed_addr constant [2 x i8] c"\0A\00", align 1
|
@7 = private unnamed_addr constant [4 x i8] c"NaN\00", align 1
|
||||||
@8 = private unnamed_addr constant [2 x i8] c" \00", align 1
|
@8 = private unnamed_addr constant [5 x i8] c"+Inf\00", align 1
|
||||||
|
@9 = private unnamed_addr constant [5 x i8] c"-Inf\00", align 1
|
||||||
|
@10 = private unnamed_addr constant [17 x i8] c"0123456789abcdef\00", align 1
|
||||||
|
@11 = private unnamed_addr constant [2 x i8] c"-\00", align 1
|
||||||
|
@12 = private unnamed_addr constant [2 x i8] c" \00", align 1
|
||||||
|
@13 = private unnamed_addr constant [2 x i8] c"\0A\00", align 1
|
||||||
|
@14 = private unnamed_addr constant [2 x i8] c" \00", align 1
|
||||||
|
|
||||||
define %"github.com/goplus/llgo/internal/runtime.Slice" @main.bytes(%"github.com/goplus/llgo/internal/runtime.String" %0) {
|
define %"github.com/goplus/llgo/internal/runtime.Slice" @main.bytes(%"github.com/goplus/llgo/internal/runtime.String" %0) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
@@ -94,13 +100,115 @@ _llgo_0:
|
|||||||
call void @main.printnl()
|
call void @main.printnl()
|
||||||
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 13)
|
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 13)
|
||||||
%4 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %3, i64 1315859240)
|
%4 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %3, i64 1315859240)
|
||||||
call void @main.printnum(%"github.com/goplus/llgo/internal/runtime.iface" %4)
|
call void @main.printany(%"github.com/goplus/llgo/internal/runtime.iface" %4)
|
||||||
call void @main.printnl()
|
call void @main.printnl()
|
||||||
%5 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 14)
|
%5 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 14)
|
||||||
%6 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %5, i64 4746175415993761792)
|
%6 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %5, i64 4746175415993761792)
|
||||||
call void @main.printnum(%"github.com/goplus/llgo/internal/runtime.iface" %6)
|
call void @main.printany(%"github.com/goplus/llgo/internal/runtime.iface" %6)
|
||||||
call void @main.printnl()
|
call void @main.printnl()
|
||||||
|
br i1 true, label %_llgo_3, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_3
|
||||||
|
%7 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
|
||||||
|
%8 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %7, i64 0
|
||||||
|
%9 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @2, i64 10)
|
||||||
|
%10 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %9)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.iface" %10, ptr %8, align 8
|
||||||
|
%11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %7, i64 1
|
||||||
|
%12 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 1)
|
||||||
|
%13 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %12, i64 -1)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.iface" %13, ptr %11, align 8
|
||||||
|
%14 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %7, i64 16, i64 2, i64 0, i64 2, i64 2)
|
||||||
|
call void @main.println(%"github.com/goplus/llgo/internal/runtime.Slice" %14)
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_3, %_llgo_1, %_llgo_0
|
||||||
|
%15 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 48)
|
||||||
|
%16 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %15, i64 0
|
||||||
|
%17 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @3, i64 8)
|
||||||
|
%18 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %17)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.iface" %18, ptr %16, align 8
|
||||||
|
%19 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %15, i64 1
|
||||||
|
%20 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 1)
|
||||||
|
%21 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %20, i64 -1)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.iface" %21, ptr %19, align 8
|
||||||
|
%22 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %15, i64 2
|
||||||
|
%23 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 1)
|
||||||
|
%24 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %23, i64 -1)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.iface" %24, ptr %22, align 8
|
||||||
|
%25 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %15, i64 16, i64 3, i64 0, i64 3, i64 3)
|
||||||
|
call void @main.println(%"github.com/goplus/llgo/internal/runtime.Slice" %25)
|
||||||
|
%26 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 256)
|
||||||
|
%27 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 0
|
||||||
|
%28 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 1)
|
||||||
|
%29 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %28, i64 -1)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.iface" %29, ptr %27, align 8
|
||||||
|
%30 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 1
|
||||||
|
%31 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 1)
|
||||||
|
%32 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %31, i64 0)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.iface" %32, ptr %30, align 8
|
||||||
|
%33 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 2
|
||||||
|
%34 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 5)
|
||||||
|
%35 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %34, i64 97)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.iface" %35, ptr %33, align 8
|
||||||
|
%36 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 3
|
||||||
|
%37 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 5)
|
||||||
|
%38 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %37, i64 65)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.iface" %38, ptr %36, align 8
|
||||||
|
%39 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 4
|
||||||
|
%40 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 5)
|
||||||
|
%41 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %40, i64 20013)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.iface" %41, ptr %39, align 8
|
||||||
|
%42 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 5
|
||||||
|
%43 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 3)
|
||||||
|
%44 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %43, i64 1)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.iface" %44, ptr %42, align 8
|
||||||
|
%45 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 6
|
||||||
|
%46 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 4)
|
||||||
|
%47 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %46, i64 2)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.iface" %47, ptr %45, align 8
|
||||||
|
%48 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 7
|
||||||
|
%49 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 5)
|
||||||
|
%50 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %49, i64 3)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.iface" %50, ptr %48, align 8
|
||||||
|
%51 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 8
|
||||||
|
%52 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 6)
|
||||||
|
%53 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %52, i64 4)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.iface" %53, ptr %51, align 8
|
||||||
|
%54 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 9
|
||||||
|
%55 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2)
|
||||||
|
%56 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %55, i64 5)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.iface" %56, ptr %54, align 8
|
||||||
|
%57 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 10
|
||||||
|
%58 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 8)
|
||||||
|
%59 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %58, i64 1)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.iface" %59, ptr %57, align 8
|
||||||
|
%60 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 11
|
||||||
|
%61 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 9)
|
||||||
|
%62 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %61, i64 2)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.iface" %62, ptr %60, align 8
|
||||||
|
%63 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 12
|
||||||
|
%64 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 10)
|
||||||
|
%65 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %64, i64 3)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.iface" %65, ptr %63, align 8
|
||||||
|
%66 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 13
|
||||||
|
%67 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 11)
|
||||||
|
%68 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %67, i64 4)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.iface" %68, ptr %66, align 8
|
||||||
|
%69 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 14
|
||||||
|
%70 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 12)
|
||||||
|
%71 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %70, i64 5)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.iface" %71, ptr %69, align 8
|
||||||
|
%72 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 15
|
||||||
|
%73 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @4, i64 4)
|
||||||
|
%74 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %73)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.iface" %74, ptr %72, align 8
|
||||||
|
%75 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %26, i64 16, i64 16, i64 0, i64 16, i64 16)
|
||||||
|
call void @main.println(%"github.com/goplus/llgo/internal/runtime.Slice" %75)
|
||||||
ret void
|
ret void
|
||||||
|
|
||||||
|
_llgo_3: ; preds = %_llgo_0
|
||||||
|
br i1 true, label %_llgo_1, label %_llgo_2
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main.prinfsub(double %0) {
|
define void @main.prinfsub(double %0) {
|
||||||
@@ -117,18 +225,223 @@ _llgo_0:
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define void @main.printany(%"github.com/goplus/llgo/internal/runtime.iface" %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 1)
|
||||||
|
%2 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %1)
|
||||||
|
%3 = extractvalue { i64, i1 } %2, 0
|
||||||
|
%4 = trunc i64 %3 to i1
|
||||||
|
%5 = extractvalue { i64, i1 } %2, 1
|
||||||
|
br i1 %5, label %_llgo_2, label %_llgo_3
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_30, %_llgo_29, %_llgo_28, %_llgo_26, %_llgo_24, %_llgo_22, %_llgo_20, %_llgo_18, %_llgo_16, %_llgo_14, %_llgo_12, %_llgo_10, %_llgo_8, %_llgo_6, %_llgo_4, %_llgo_2
|
||||||
|
ret void
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_0
|
||||||
|
call void @main.printbool(i1 %4)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_3: ; preds = %_llgo_0
|
||||||
|
%6 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2)
|
||||||
|
%7 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %6)
|
||||||
|
%8 = extractvalue { i64, i1 } %7, 0
|
||||||
|
%9 = extractvalue { i64, i1 } %7, 1
|
||||||
|
br i1 %9, label %_llgo_4, label %_llgo_5
|
||||||
|
|
||||||
|
_llgo_4: ; preds = %_llgo_3
|
||||||
|
call void @main.printint(i64 %8)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_5: ; preds = %_llgo_3
|
||||||
|
%10 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 3)
|
||||||
|
%11 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %10)
|
||||||
|
%12 = extractvalue { i64, i1 } %11, 0
|
||||||
|
%13 = trunc i64 %12 to i8
|
||||||
|
%14 = extractvalue { i64, i1 } %11, 1
|
||||||
|
br i1 %14, label %_llgo_6, label %_llgo_7
|
||||||
|
|
||||||
|
_llgo_6: ; preds = %_llgo_5
|
||||||
|
%15 = sext i8 %13 to i64
|
||||||
|
call void @main.printint(i64 %15)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_7: ; preds = %_llgo_5
|
||||||
|
%16 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 4)
|
||||||
|
%17 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %16)
|
||||||
|
%18 = extractvalue { i64, i1 } %17, 0
|
||||||
|
%19 = trunc i64 %18 to i16
|
||||||
|
%20 = extractvalue { i64, i1 } %17, 1
|
||||||
|
br i1 %20, label %_llgo_8, label %_llgo_9
|
||||||
|
|
||||||
|
_llgo_8: ; preds = %_llgo_7
|
||||||
|
%21 = sext i16 %19 to i64
|
||||||
|
call void @main.printint(i64 %21)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_9: ; preds = %_llgo_7
|
||||||
|
%22 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 5)
|
||||||
|
%23 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %22)
|
||||||
|
%24 = extractvalue { i64, i1 } %23, 0
|
||||||
|
%25 = trunc i64 %24 to i32
|
||||||
|
%26 = extractvalue { i64, i1 } %23, 1
|
||||||
|
br i1 %26, label %_llgo_10, label %_llgo_11
|
||||||
|
|
||||||
|
_llgo_10: ; preds = %_llgo_9
|
||||||
|
%27 = sext i32 %25 to i64
|
||||||
|
call void @main.printint(i64 %27)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_11: ; preds = %_llgo_9
|
||||||
|
%28 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 6)
|
||||||
|
%29 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %28)
|
||||||
|
%30 = extractvalue { i64, i1 } %29, 0
|
||||||
|
%31 = extractvalue { i64, i1 } %29, 1
|
||||||
|
br i1 %31, label %_llgo_12, label %_llgo_13
|
||||||
|
|
||||||
|
_llgo_12: ; preds = %_llgo_11
|
||||||
|
call void @main.printint(i64 %30)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_13: ; preds = %_llgo_11
|
||||||
|
%32 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 7)
|
||||||
|
%33 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %32)
|
||||||
|
%34 = extractvalue { i64, i1 } %33, 0
|
||||||
|
%35 = extractvalue { i64, i1 } %33, 1
|
||||||
|
br i1 %35, label %_llgo_14, label %_llgo_15
|
||||||
|
|
||||||
|
_llgo_14: ; preds = %_llgo_13
|
||||||
|
call void @main.printuint(i64 %34)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_15: ; preds = %_llgo_13
|
||||||
|
%36 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 8)
|
||||||
|
%37 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %36)
|
||||||
|
%38 = extractvalue { i64, i1 } %37, 0
|
||||||
|
%39 = trunc i64 %38 to i8
|
||||||
|
%40 = extractvalue { i64, i1 } %37, 1
|
||||||
|
br i1 %40, label %_llgo_16, label %_llgo_17
|
||||||
|
|
||||||
|
_llgo_16: ; preds = %_llgo_15
|
||||||
|
%41 = sext i8 %39 to i64
|
||||||
|
call void @main.printuint(i64 %41)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_17: ; preds = %_llgo_15
|
||||||
|
%42 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 9)
|
||||||
|
%43 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %42)
|
||||||
|
%44 = extractvalue { i64, i1 } %43, 0
|
||||||
|
%45 = trunc i64 %44 to i16
|
||||||
|
%46 = extractvalue { i64, i1 } %43, 1
|
||||||
|
br i1 %46, label %_llgo_18, label %_llgo_19
|
||||||
|
|
||||||
|
_llgo_18: ; preds = %_llgo_17
|
||||||
|
%47 = sext i16 %45 to i64
|
||||||
|
call void @main.printuint(i64 %47)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_19: ; preds = %_llgo_17
|
||||||
|
%48 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 10)
|
||||||
|
%49 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %48)
|
||||||
|
%50 = extractvalue { i64, i1 } %49, 0
|
||||||
|
%51 = trunc i64 %50 to i32
|
||||||
|
%52 = extractvalue { i64, i1 } %49, 1
|
||||||
|
br i1 %52, label %_llgo_20, label %_llgo_21
|
||||||
|
|
||||||
|
_llgo_20: ; preds = %_llgo_19
|
||||||
|
%53 = sext i32 %51 to i64
|
||||||
|
call void @main.printuint(i64 %53)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_21: ; preds = %_llgo_19
|
||||||
|
%54 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 11)
|
||||||
|
%55 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %54)
|
||||||
|
%56 = extractvalue { i64, i1 } %55, 0
|
||||||
|
%57 = extractvalue { i64, i1 } %55, 1
|
||||||
|
br i1 %57, label %_llgo_22, label %_llgo_23
|
||||||
|
|
||||||
|
_llgo_22: ; preds = %_llgo_21
|
||||||
|
call void @main.printuint(i64 %56)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_23: ; preds = %_llgo_21
|
||||||
|
%58 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 12)
|
||||||
|
%59 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %58)
|
||||||
|
%60 = extractvalue { i64, i1 } %59, 0
|
||||||
|
%61 = extractvalue { i64, i1 } %59, 1
|
||||||
|
br i1 %61, label %_llgo_24, label %_llgo_25
|
||||||
|
|
||||||
|
_llgo_24: ; preds = %_llgo_23
|
||||||
|
call void @main.printuint(i64 %60)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_25: ; preds = %_llgo_23
|
||||||
|
%62 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 13)
|
||||||
|
%63 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %62)
|
||||||
|
%64 = extractvalue { i64, i1 } %63, 0
|
||||||
|
%65 = trunc i64 %64 to i32
|
||||||
|
%66 = bitcast i32 %65 to float
|
||||||
|
%67 = extractvalue { i64, i1 } %63, 1
|
||||||
|
br i1 %67, label %_llgo_26, label %_llgo_27
|
||||||
|
|
||||||
|
_llgo_26: ; preds = %_llgo_25
|
||||||
|
%68 = fpext float %66 to double
|
||||||
|
call void @main.printfloat(double %68)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_27: ; preds = %_llgo_25
|
||||||
|
%69 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 14)
|
||||||
|
%70 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %69)
|
||||||
|
%71 = extractvalue { i64, i1 } %70, 0
|
||||||
|
%72 = bitcast i64 %71 to double
|
||||||
|
%73 = extractvalue { i64, i1 } %70, 1
|
||||||
|
br i1 %73, label %_llgo_28, label %_llgo_29
|
||||||
|
|
||||||
|
_llgo_28: ; preds = %_llgo_27
|
||||||
|
call void @main.printfloat(double %72)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_29: ; preds = %_llgo_27
|
||||||
|
%74 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 24)
|
||||||
|
%75 = call { %"github.com/goplus/llgo/internal/runtime.String", i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2String"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %74)
|
||||||
|
%76 = extractvalue { %"github.com/goplus/llgo/internal/runtime.String", i1 } %75, 0
|
||||||
|
%77 = extractvalue { %"github.com/goplus/llgo/internal/runtime.String", i1 } %75, 1
|
||||||
|
br i1 %77, label %_llgo_30, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_30: ; preds = %_llgo_29
|
||||||
|
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %76)
|
||||||
|
br label %_llgo_1
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.printbool(i1 %0) {
|
||||||
|
_llgo_0:
|
||||||
|
br i1 %0, label %_llgo_1, label %_llgo_3
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
%1 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @5, i64 4)
|
||||||
|
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %1)
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_3, %_llgo_1
|
||||||
|
ret void
|
||||||
|
|
||||||
|
_llgo_3: ; preds = %_llgo_0
|
||||||
|
%2 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @6, i64 5)
|
||||||
|
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %2)
|
||||||
|
br label %_llgo_2
|
||||||
|
}
|
||||||
|
|
||||||
define void @main.printfloat(double %0) {
|
define void @main.printfloat(double %0) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%1 = fcmp one double %0, %0
|
%1 = fcmp one double %0, %0
|
||||||
br i1 %1, label %_llgo_1, label %_llgo_3
|
br i1 %1, label %_llgo_1, label %_llgo_3
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_0
|
_llgo_1: ; preds = %_llgo_0
|
||||||
%2 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @2, i64 3)
|
%2 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @7, i64 3)
|
||||||
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %2)
|
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %2)
|
||||||
ret void
|
ret void
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_7
|
_llgo_2: ; preds = %_llgo_7
|
||||||
%3 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @3, i64 4)
|
%3 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @8, i64 4)
|
||||||
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %3)
|
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %3)
|
||||||
ret void
|
ret void
|
||||||
|
|
||||||
@@ -138,7 +451,7 @@ _llgo_3: ; preds = %_llgo_0
|
|||||||
br i1 %5, label %_llgo_6, label %_llgo_7
|
br i1 %5, label %_llgo_6, label %_llgo_7
|
||||||
|
|
||||||
_llgo_4: ; preds = %_llgo_10
|
_llgo_4: ; preds = %_llgo_10
|
||||||
%6 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @4, i64 4)
|
%6 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @9, i64 4)
|
||||||
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %6)
|
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %6)
|
||||||
ret void
|
ret void
|
||||||
|
|
||||||
@@ -310,8 +623,8 @@ _llgo_0:
|
|||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_3
|
_llgo_1: ; preds = %_llgo_3
|
||||||
%2 = urem i64 %14, 16
|
%2 = urem i64 %14, 16
|
||||||
%3 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @5, i64 16)
|
%3 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @10, i64 16)
|
||||||
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.StringData"(%"github.com/goplus/llgo/internal/runtime.String" %3)
|
%4 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %3, 0
|
||||||
%5 = getelementptr inbounds i8, ptr %4, i64 %2
|
%5 = getelementptr inbounds i8, ptr %4, i64 %2
|
||||||
%6 = load i8, ptr %5, align 1
|
%6 = load i8, ptr %5, align 1
|
||||||
%7 = getelementptr inbounds i8, ptr %1, i64 %15
|
%7 = getelementptr inbounds i8, ptr %1, i64 %15
|
||||||
@@ -354,7 +667,7 @@ _llgo_0:
|
|||||||
br i1 %1, label %_llgo_1, label %_llgo_2
|
br i1 %1, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_0
|
_llgo_1: ; preds = %_llgo_0
|
||||||
%2 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @6, i64 1)
|
%2 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @11, i64 1)
|
||||||
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %2)
|
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %2)
|
||||||
%3 = sub i64 0, %0
|
%3 = sub i64 0, %0
|
||||||
br label %_llgo_2
|
br label %_llgo_2
|
||||||
@@ -365,165 +678,48 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define void @main.println(%"github.com/goplus/llgo/internal/runtime.Slice" %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %0)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_5, %_llgo_0
|
||||||
|
%2 = phi i64 [ -1, %_llgo_0 ], [ %3, %_llgo_5 ]
|
||||||
|
%3 = add i64 %2, 1
|
||||||
|
%4 = icmp slt i64 %3, %1
|
||||||
|
br i1 %4, label %_llgo_2, label %_llgo_3
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1
|
||||||
|
%5 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %0)
|
||||||
|
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %5, i64 %3
|
||||||
|
%7 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %6, align 8
|
||||||
|
%8 = icmp ne i64 %3, 0
|
||||||
|
br i1 %8, label %_llgo_4, label %_llgo_5
|
||||||
|
|
||||||
|
_llgo_3: ; preds = %_llgo_1
|
||||||
|
call void @main.printnl()
|
||||||
|
ret void
|
||||||
|
|
||||||
|
_llgo_4: ; preds = %_llgo_2
|
||||||
|
%9 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @12, i64 1)
|
||||||
|
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %9)
|
||||||
|
br label %_llgo_5
|
||||||
|
|
||||||
|
_llgo_5: ; preds = %_llgo_4, %_llgo_2
|
||||||
|
call void @main.printany(%"github.com/goplus/llgo/internal/runtime.iface" %7)
|
||||||
|
br label %_llgo_1
|
||||||
|
}
|
||||||
|
|
||||||
define void @main.printnl() {
|
define void @main.printnl() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%0 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @7, i64 1)
|
%0 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @13, i64 1)
|
||||||
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %0)
|
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %0)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main.printnum(%"github.com/goplus/llgo/internal/runtime.iface" %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2)
|
|
||||||
%2 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %1)
|
|
||||||
%3 = extractvalue { i64, i1 } %2, 0
|
|
||||||
%4 = extractvalue { i64, i1 } %2, 1
|
|
||||||
br i1 %4, label %_llgo_2, label %_llgo_3
|
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_26, %_llgo_25, %_llgo_24, %_llgo_22, %_llgo_20, %_llgo_18, %_llgo_16, %_llgo_14, %_llgo_12, %_llgo_10, %_llgo_8, %_llgo_6, %_llgo_4, %_llgo_2
|
|
||||||
ret void
|
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_0
|
|
||||||
call void @main.printint(i64 %3)
|
|
||||||
br label %_llgo_1
|
|
||||||
|
|
||||||
_llgo_3: ; preds = %_llgo_0
|
|
||||||
%5 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 3)
|
|
||||||
%6 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %5)
|
|
||||||
%7 = extractvalue { i64, i1 } %6, 0
|
|
||||||
%8 = extractvalue { i64, i1 } %6, 1
|
|
||||||
br i1 %8, label %_llgo_4, label %_llgo_5
|
|
||||||
|
|
||||||
_llgo_4: ; preds = %_llgo_3
|
|
||||||
call void @main.printint(i64 %7)
|
|
||||||
br label %_llgo_1
|
|
||||||
|
|
||||||
_llgo_5: ; preds = %_llgo_3
|
|
||||||
%9 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 4)
|
|
||||||
%10 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %9)
|
|
||||||
%11 = extractvalue { i64, i1 } %10, 0
|
|
||||||
%12 = extractvalue { i64, i1 } %10, 1
|
|
||||||
br i1 %12, label %_llgo_6, label %_llgo_7
|
|
||||||
|
|
||||||
_llgo_6: ; preds = %_llgo_5
|
|
||||||
call void @main.printint(i64 %11)
|
|
||||||
br label %_llgo_1
|
|
||||||
|
|
||||||
_llgo_7: ; preds = %_llgo_5
|
|
||||||
%13 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 5)
|
|
||||||
%14 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %13)
|
|
||||||
%15 = extractvalue { i64, i1 } %14, 0
|
|
||||||
%16 = extractvalue { i64, i1 } %14, 1
|
|
||||||
br i1 %16, label %_llgo_8, label %_llgo_9
|
|
||||||
|
|
||||||
_llgo_8: ; preds = %_llgo_7
|
|
||||||
call void @main.printint(i64 %15)
|
|
||||||
br label %_llgo_1
|
|
||||||
|
|
||||||
_llgo_9: ; preds = %_llgo_7
|
|
||||||
%17 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 6)
|
|
||||||
%18 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %17)
|
|
||||||
%19 = extractvalue { i64, i1 } %18, 0
|
|
||||||
%20 = extractvalue { i64, i1 } %18, 1
|
|
||||||
br i1 %20, label %_llgo_10, label %_llgo_11
|
|
||||||
|
|
||||||
_llgo_10: ; preds = %_llgo_9
|
|
||||||
call void @main.printint(i64 %19)
|
|
||||||
br label %_llgo_1
|
|
||||||
|
|
||||||
_llgo_11: ; preds = %_llgo_9
|
|
||||||
%21 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 7)
|
|
||||||
%22 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %21)
|
|
||||||
%23 = extractvalue { i64, i1 } %22, 0
|
|
||||||
%24 = extractvalue { i64, i1 } %22, 1
|
|
||||||
br i1 %24, label %_llgo_12, label %_llgo_13
|
|
||||||
|
|
||||||
_llgo_12: ; preds = %_llgo_11
|
|
||||||
call void @main.printuint(i64 %23)
|
|
||||||
br label %_llgo_1
|
|
||||||
|
|
||||||
_llgo_13: ; preds = %_llgo_11
|
|
||||||
%25 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 8)
|
|
||||||
%26 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %25)
|
|
||||||
%27 = extractvalue { i64, i1 } %26, 0
|
|
||||||
%28 = extractvalue { i64, i1 } %26, 1
|
|
||||||
br i1 %28, label %_llgo_14, label %_llgo_15
|
|
||||||
|
|
||||||
_llgo_14: ; preds = %_llgo_13
|
|
||||||
call void @main.printuint(i64 %27)
|
|
||||||
br label %_llgo_1
|
|
||||||
|
|
||||||
_llgo_15: ; preds = %_llgo_13
|
|
||||||
%29 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 9)
|
|
||||||
%30 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %29)
|
|
||||||
%31 = extractvalue { i64, i1 } %30, 0
|
|
||||||
%32 = extractvalue { i64, i1 } %30, 1
|
|
||||||
br i1 %32, label %_llgo_16, label %_llgo_17
|
|
||||||
|
|
||||||
_llgo_16: ; preds = %_llgo_15
|
|
||||||
call void @main.printuint(i64 %31)
|
|
||||||
br label %_llgo_1
|
|
||||||
|
|
||||||
_llgo_17: ; preds = %_llgo_15
|
|
||||||
%33 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 10)
|
|
||||||
%34 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %33)
|
|
||||||
%35 = extractvalue { i64, i1 } %34, 0
|
|
||||||
%36 = extractvalue { i64, i1 } %34, 1
|
|
||||||
br i1 %36, label %_llgo_18, label %_llgo_19
|
|
||||||
|
|
||||||
_llgo_18: ; preds = %_llgo_17
|
|
||||||
call void @main.printuint(i64 %35)
|
|
||||||
br label %_llgo_1
|
|
||||||
|
|
||||||
_llgo_19: ; preds = %_llgo_17
|
|
||||||
%37 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 11)
|
|
||||||
%38 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %37)
|
|
||||||
%39 = extractvalue { i64, i1 } %38, 0
|
|
||||||
%40 = extractvalue { i64, i1 } %38, 1
|
|
||||||
br i1 %40, label %_llgo_20, label %_llgo_21
|
|
||||||
|
|
||||||
_llgo_20: ; preds = %_llgo_19
|
|
||||||
call void @main.printuint(i64 %39)
|
|
||||||
br label %_llgo_1
|
|
||||||
|
|
||||||
_llgo_21: ; preds = %_llgo_19
|
|
||||||
%41 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 12)
|
|
||||||
%42 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %41)
|
|
||||||
%43 = extractvalue { i64, i1 } %42, 0
|
|
||||||
%44 = extractvalue { i64, i1 } %42, 1
|
|
||||||
br i1 %44, label %_llgo_22, label %_llgo_23
|
|
||||||
|
|
||||||
_llgo_22: ; preds = %_llgo_21
|
|
||||||
call void @main.printuint(i64 %43)
|
|
||||||
br label %_llgo_1
|
|
||||||
|
|
||||||
_llgo_23: ; preds = %_llgo_21
|
|
||||||
%45 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 13)
|
|
||||||
%46 = call { float, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Float32"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %45)
|
|
||||||
%47 = extractvalue { float, i1 } %46, 0
|
|
||||||
%48 = extractvalue { float, i1 } %46, 1
|
|
||||||
br i1 %48, label %_llgo_24, label %_llgo_25
|
|
||||||
|
|
||||||
_llgo_24: ; preds = %_llgo_23
|
|
||||||
%49 = fpext float %47 to double
|
|
||||||
call void @main.printfloat(double %49)
|
|
||||||
br label %_llgo_1
|
|
||||||
|
|
||||||
_llgo_25: ; preds = %_llgo_23
|
|
||||||
%50 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 14)
|
|
||||||
%51 = call { double, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Float64"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %50)
|
|
||||||
%52 = extractvalue { double, i1 } %51, 0
|
|
||||||
%53 = extractvalue { double, i1 } %51, 1
|
|
||||||
br i1 %53, label %_llgo_26, label %_llgo_1
|
|
||||||
|
|
||||||
_llgo_26: ; preds = %_llgo_25
|
|
||||||
call void @main.printfloat(double %52)
|
|
||||||
br label %_llgo_1
|
|
||||||
}
|
|
||||||
|
|
||||||
define void @main.printsp() {
|
define void @main.printsp() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%0 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @8, i64 1)
|
%0 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @14, i64 1)
|
||||||
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %0)
|
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %0)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
@@ -599,12 +795,12 @@ declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64)
|
|||||||
|
|
||||||
declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr, i64)
|
declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr, i64)
|
||||||
|
|
||||||
declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr, i64, i64, i64, i64, i64)
|
declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String")
|
||||||
|
|
||||||
declare ptr @"github.com/goplus/llgo/internal/runtime.StringData"(%"github.com/goplus/llgo/internal/runtime.String")
|
declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr, i64, i64, i64, i64, i64)
|
||||||
|
|
||||||
declare { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface", ptr)
|
declare { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface", ptr)
|
||||||
|
|
||||||
declare { float, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Float32"(%"github.com/goplus/llgo/internal/runtime.iface", ptr)
|
declare { %"github.com/goplus/llgo/internal/runtime.String", i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2String"(%"github.com/goplus/llgo/internal/runtime.iface", ptr)
|
||||||
|
|
||||||
declare { double, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Float64"(%"github.com/goplus/llgo/internal/runtime.iface", ptr)
|
declare ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice")
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ _llgo_0:
|
|||||||
br i1 %1, label %_llgo_1, label %_llgo_2
|
br i1 %1, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_0
|
_llgo_1: ; preds = %_llgo_0
|
||||||
%2 = call ptr @sqlite3_errstr()
|
%2 = call ptr @sqlite3_errstr(i32 %0)
|
||||||
%3 = call i32 (ptr, ...) @printf(ptr @0, i32 %0, ptr %2)
|
%3 = call i32 (ptr, ...) @printf(ptr @0, i32 %0, ptr %2)
|
||||||
call void @exit(i32 1)
|
call void @exit(i32 1)
|
||||||
br label %_llgo_2
|
br label %_llgo_2
|
||||||
@@ -45,11 +45,11 @@ _llgo_0:
|
|||||||
%3 = extractvalue { ptr, i32 } %2, 0
|
%3 = extractvalue { ptr, i32 } %2, 0
|
||||||
%4 = extractvalue { ptr, i32 } %2, 1
|
%4 = extractvalue { ptr, i32 } %2, 1
|
||||||
call void @main.check(i32 %4)
|
call void @main.check(i32 %4)
|
||||||
%5 = call i32 @sqlite3_close()
|
%5 = call i32 @sqlite3_close(ptr %3)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
declare ptr @sqlite3_errstr()
|
declare ptr @sqlite3_errstr(i32)
|
||||||
|
|
||||||
declare i32 @printf(ptr, ...)
|
declare i32 @printf(ptr, ...)
|
||||||
|
|
||||||
@@ -59,4 +59,4 @@ declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
|||||||
|
|
||||||
declare { ptr, i32 } @"github.com/goplus/llgo/x/sqlite.OpenV2"(ptr, i32, ptr)
|
declare { ptr, i32 } @"github.com/goplus/llgo/x/sqlite.OpenV2"(ptr, i32, ptr)
|
||||||
|
|
||||||
declare i32 @sqlite3_close()
|
declare i32 @sqlite3_close(ptr)
|
||||||
|
|||||||
15
cl/_testpy/callpy/in.go
Normal file
15
cl/_testpy/callpy/in.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/py"
|
||||||
|
"github.com/goplus/llgo/py/math"
|
||||||
|
"github.com/goplus/llgo/py/os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
x := math.Sqrt(py.Float(2))
|
||||||
|
wd := os.Getcwd()
|
||||||
|
c.Printf(c.Str("sqrt(2) = %f\n"), x.Float64())
|
||||||
|
c.Printf(c.Str("cwd = %s\n"), wd.CStr())
|
||||||
|
}
|
||||||
74
cl/_testpy/callpy/out.ll
Normal file
74
cl/_testpy/callpy/out.ll
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
|
@__llgo_py.math.sqrt = linkonce global ptr null
|
||||||
|
@__llgo_py.os.getcwd = linkonce global ptr null
|
||||||
|
@0 = private unnamed_addr constant [14 x i8] c"sqrt(2) = %f\0A\00", align 1
|
||||||
|
@1 = private unnamed_addr constant [10 x i8] c"cwd = %s\0A\00", align 1
|
||||||
|
@__llgo_py.math = external global ptr
|
||||||
|
@2 = private unnamed_addr constant [5 x i8] c"sqrt\00", align 1
|
||||||
|
@__llgo_py.os = external global ptr
|
||||||
|
@3 = private unnamed_addr constant [7 x i8] c"getcwd\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"()
|
||||||
|
call void @"github.com/goplus/llgo/py/os.init"()
|
||||||
|
%1 = load ptr, ptr @__llgo_py.math, align 8
|
||||||
|
call void (ptr, ...) @llgoLoadPyModSyms(ptr %1, ptr @2, ptr @__llgo_py.math.sqrt, ptr null)
|
||||||
|
%2 = load ptr, ptr @__llgo_py.os, align 8
|
||||||
|
call void (ptr, ...) @llgoLoadPyModSyms(ptr %2, ptr @3, ptr @__llgo_py.os.getcwd, 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 = load ptr, ptr @__llgo_py.math.sqrt, align 8
|
||||||
|
%4 = call ptr @PyObject_CallOneArg(ptr %3, ptr %2)
|
||||||
|
%5 = load ptr, ptr @__llgo_py.os.getcwd, align 8
|
||||||
|
%6 = call ptr @PyObject_CallNoArgs(ptr %5)
|
||||||
|
%7 = call double @PyFloat_AsDouble(ptr %4)
|
||||||
|
%8 = call i32 (ptr, ...) @printf(ptr @0, double %7)
|
||||||
|
%9 = call ptr @PyBytes_AsString(ptr %6)
|
||||||
|
%10 = call i32 (ptr, ...) @printf(ptr @1, ptr %9)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/py/math.init"()
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/py/os.init"()
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare ptr @PyFloat_FromDouble(double)
|
||||||
|
|
||||||
|
declare ptr @PyObject_CallOneArg(ptr, ptr)
|
||||||
|
|
||||||
|
declare ptr @PyObject_CallNoArgs(ptr)
|
||||||
|
|
||||||
|
declare double @PyFloat_AsDouble(ptr)
|
||||||
|
|
||||||
|
declare i32 @printf(ptr, ...)
|
||||||
|
|
||||||
|
declare ptr @PyBytes_AsString(ptr)
|
||||||
|
|
||||||
|
declare void @llgoLoadPyModSyms(ptr, ...)
|
||||||
|
|
||||||
|
declare void @Py_Initialize()
|
||||||
14
cl/_testpy/math/in.go
Normal file
14
cl/_testpy/math/in.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package math
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/py"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LLGoPackage = "py.math"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:linkname Sqrt py.sqrt
|
||||||
|
func Sqrt(x *py.Object) *py.Object
|
||||||
29
cl/_testpy/math/out.ll
Normal file
29
cl/_testpy/math/out.ll
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
; ModuleID = 'math'
|
||||||
|
source_filename = "math"
|
||||||
|
|
||||||
|
@__llgo_py.math.sqrt = external global ptr
|
||||||
|
@"math.init$guard" = global ptr null
|
||||||
|
@__llgo_py.math = linkonce global ptr null
|
||||||
|
@0 = private unnamed_addr constant [5 x i8] c"math\00", align 1
|
||||||
|
|
||||||
|
define void @math.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"math.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"math.init$guard", align 1
|
||||||
|
%1 = load ptr, ptr @__llgo_py.math, align 8
|
||||||
|
%2 = icmp ne ptr %1, null
|
||||||
|
br i1 %2, label %_llgo_2, label %_llgo_3
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_3, %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
|
||||||
|
_llgo_3: ; preds = %_llgo_1
|
||||||
|
%3 = call ptr @PyImport_ImportModule(ptr @0)
|
||||||
|
store ptr %3, ptr @__llgo_py.math, align 8
|
||||||
|
br label %_llgo_2
|
||||||
|
}
|
||||||
|
|
||||||
|
declare ptr @PyImport_ImportModule(ptr)
|
||||||
@@ -34,7 +34,7 @@ _llgo_0:
|
|||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
call void @main.init()
|
call void @main.init()
|
||||||
%2 = call %"github.com/goplus/llgo/internal/runtime.String" @main.hello()
|
%2 = call %"github.com/goplus/llgo/internal/runtime.String" @main.hello()
|
||||||
%3 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %2)
|
%3 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %2, 1
|
||||||
%4 = add i64 %3, 1
|
%4 = add i64 %3, 1
|
||||||
%5 = alloca i8, i64 %4, align 1
|
%5 = alloca i8, i64 %4, align 1
|
||||||
%6 = call ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr %5, %"github.com/goplus/llgo/internal/runtime.String" %2)
|
%6 = call ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr %5, %"github.com/goplus/llgo/internal/runtime.String" %2)
|
||||||
@@ -46,8 +46,6 @@ declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/ll
|
|||||||
|
|
||||||
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
declare i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String")
|
|
||||||
|
|
||||||
declare ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr, %"github.com/goplus/llgo/internal/runtime.String")
|
declare ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr, %"github.com/goplus/llgo/internal/runtime.String")
|
||||||
|
|
||||||
declare i32 @printf(ptr, ...)
|
declare i32 @printf(ptr, ...)
|
||||||
|
|||||||
@@ -131,14 +131,14 @@ _llgo_0:
|
|||||||
%60 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @0, i64 5)
|
%60 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @0, i64 5)
|
||||||
call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %60)
|
call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %60)
|
||||||
%61 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @1, i64 5)
|
%61 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @1, i64 5)
|
||||||
%62 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %61)
|
%62 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %61, 1
|
||||||
%63 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %61, i64 1, i64 %62)
|
%63 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %61, i64 1, i64 %62)
|
||||||
call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %63)
|
call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %63)
|
||||||
%64 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @2, i64 5)
|
%64 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @2, i64 5)
|
||||||
%65 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %64, i64 1, i64 2)
|
%65 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %64, i64 1, i64 2)
|
||||||
call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %65)
|
call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %65)
|
||||||
%66 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @3, i64 5)
|
%66 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @3, i64 5)
|
||||||
%67 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %66)
|
%67 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %66, 1
|
||||||
%68 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %66, i64 5, i64 %67)
|
%68 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %66, i64 5, i64 %67)
|
||||||
call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %68)
|
call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %68)
|
||||||
ret void
|
ret void
|
||||||
@@ -152,7 +152,7 @@ _llgo_0:
|
|||||||
|
|
||||||
define void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %0) {
|
define void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %0) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%1 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %0)
|
%1 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %0, 1
|
||||||
call void @main.out(i64 %1)
|
call void @main.out(i64 %1)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
@@ -171,8 +171,6 @@ declare ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/go
|
|||||||
|
|
||||||
declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr, i64)
|
declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr, i64)
|
||||||
|
|
||||||
declare i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String")
|
|
||||||
|
|
||||||
declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String", i64, i64)
|
declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String", i64, i64)
|
||||||
|
|
||||||
declare i32 @printf(ptr, ...)
|
declare i32 @printf(ptr, ...)
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ _llgo_0:
|
|||||||
%9 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %2, i64 16, i64 3, i64 0, i64 3, i64 3)
|
%9 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %2, i64 16, i64 3, i64 0, i64 3, i64 3)
|
||||||
%10 = call %"github.com/goplus/llgo/internal/runtime.String" @main.concat(%"github.com/goplus/llgo/internal/runtime.Slice" %9)
|
%10 = call %"github.com/goplus/llgo/internal/runtime.String" @main.concat(%"github.com/goplus/llgo/internal/runtime.Slice" %9)
|
||||||
%11 = load ptr, ptr @__stderrp, align 8
|
%11 = load ptr, ptr @__stderrp, align 8
|
||||||
%12 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %10)
|
%12 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %10, 1
|
||||||
%13 = add i64 %12, 1
|
%13 = add i64 %12, 1
|
||||||
%14 = alloca i8, i64 %13, align 1
|
%14 = alloca i8, i64 %13, align 1
|
||||||
%15 = call ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr %14, %"github.com/goplus/llgo/internal/runtime.String" %10)
|
%15 = call ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr %14, %"github.com/goplus/llgo/internal/runtime.String" %10)
|
||||||
@@ -103,8 +103,6 @@ declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
|
|||||||
|
|
||||||
declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr, i64, i64, i64, i64, i64)
|
declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr, i64, i64, i64, i64, i64)
|
||||||
|
|
||||||
declare i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String")
|
|
||||||
|
|
||||||
declare ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr, %"github.com/goplus/llgo/internal/runtime.String")
|
declare ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr, %"github.com/goplus/llgo/internal/runtime.String")
|
||||||
|
|
||||||
declare i32 @fprintf(ptr, ptr, ...)
|
declare i32 @fprintf(ptr, ptr, ...)
|
||||||
|
|||||||
@@ -119,12 +119,12 @@ _llgo_0:
|
|||||||
%61 = load i64, ptr %60, align 4
|
%61 = load i64, ptr %60, align 4
|
||||||
%62 = call i32 (ptr, ...) @printf(ptr @3, i64 %61)
|
%62 = call i32 (ptr, ...) @printf(ptr @3, i64 %61)
|
||||||
%63 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @5, i64 6)
|
%63 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @5, i64 6)
|
||||||
%64 = call ptr @"github.com/goplus/llgo/internal/runtime.StringData"(%"github.com/goplus/llgo/internal/runtime.String" %63)
|
%64 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %63, 0
|
||||||
%65 = getelementptr inbounds i8, ptr %64, i64 2
|
%65 = getelementptr inbounds i8, ptr %64, i64 2
|
||||||
%66 = load i8, ptr %65, align 1
|
%66 = load i8, ptr %65, align 1
|
||||||
%67 = call i32 (ptr, ...) @printf(ptr @4, i8 %66)
|
%67 = call i32 (ptr, ...) @printf(ptr @4, i8 %66)
|
||||||
%68 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @7, i64 6)
|
%68 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @7, i64 6)
|
||||||
%69 = call ptr @"github.com/goplus/llgo/internal/runtime.StringData"(%"github.com/goplus/llgo/internal/runtime.String" %68)
|
%69 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %68, 0
|
||||||
%70 = getelementptr inbounds i8, ptr %69, i64 1
|
%70 = getelementptr inbounds i8, ptr %69, i64 1
|
||||||
%71 = load i8, ptr %70, align 1
|
%71 = load i8, ptr %70, align 1
|
||||||
%72 = call i32 (ptr, ...) @printf(ptr @6, i8 %71)
|
%72 = call i32 (ptr, ...) @printf(ptr @6, i8 %71)
|
||||||
@@ -138,5 +138,3 @@ declare ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr, i64)
|
|||||||
declare i32 @printf(ptr, ...)
|
declare i32 @printf(ptr, ...)
|
||||||
|
|
||||||
declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr, i64)
|
declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr, i64)
|
||||||
|
|
||||||
declare ptr @"github.com/goplus/llgo/internal/runtime.StringData"(%"github.com/goplus/llgo/internal/runtime.String")
|
|
||||||
|
|||||||
39
cl/_testrt/named/in.go
Normal file
39
cl/_testrt/named/in.go
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "github.com/goplus/llgo/internal/runtime/c"
|
||||||
|
|
||||||
|
type mSpanList struct {
|
||||||
|
first *mspan
|
||||||
|
last *mspan
|
||||||
|
}
|
||||||
|
|
||||||
|
type minfo struct {
|
||||||
|
span *mspan
|
||||||
|
info int
|
||||||
|
}
|
||||||
|
|
||||||
|
type mspan struct {
|
||||||
|
next *mspan
|
||||||
|
prev *mspan
|
||||||
|
list *mSpanList
|
||||||
|
info minfo
|
||||||
|
value int
|
||||||
|
check func(int) int
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
m := &mspan{}
|
||||||
|
m.value = 100
|
||||||
|
m.next = &mspan{}
|
||||||
|
m.next.value = 200
|
||||||
|
m.list = &mSpanList{}
|
||||||
|
m.list.last = &mspan{}
|
||||||
|
m.list.last.value = 300
|
||||||
|
m.info.info = 10
|
||||||
|
m.info.span = m
|
||||||
|
m.check = func(n int) int {
|
||||||
|
return m.value * n
|
||||||
|
}
|
||||||
|
c.Printf(c.Str("%d %d %d %d %d %d\n"), m.next.value, m.list.last.value, m.info.info,
|
||||||
|
m.info.span.value, m.check(-2), m.info.span.check(-3))
|
||||||
|
}
|
||||||
143
cl/_testrt/named/out.ll
Normal file
143
cl/_testrt/named/out.ll
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
%main.mspan = type { ptr, ptr, ptr, %main.minfo, i64, { ptr, ptr } }
|
||||||
|
%main.minfo = type { ptr, i64 }
|
||||||
|
%main.mSpanList = type { ptr, ptr }
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
|
@0 = private unnamed_addr constant [19 x i8] c"%d %d %d %d %d %d\0A\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
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main(i32 %0, ptr %1) {
|
||||||
|
_llgo_0:
|
||||||
|
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 @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 8)
|
||||||
|
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 64)
|
||||||
|
store ptr %3, ptr %2, align 8
|
||||||
|
%4 = load ptr, ptr %2, align 8
|
||||||
|
%5 = getelementptr inbounds %main.mspan, ptr %4, i32 0, i32 4
|
||||||
|
store i64 100, ptr %5, align 4
|
||||||
|
%6 = load ptr, ptr %2, align 8
|
||||||
|
%7 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 64)
|
||||||
|
%8 = getelementptr inbounds %main.mspan, ptr %6, i32 0, i32 0
|
||||||
|
store ptr %7, ptr %8, align 8
|
||||||
|
%9 = load ptr, ptr %2, align 8
|
||||||
|
%10 = getelementptr inbounds %main.mspan, ptr %9, i32 0, i32 0
|
||||||
|
%11 = load ptr, ptr %10, align 8
|
||||||
|
%12 = getelementptr inbounds %main.mspan, ptr %11, i32 0, i32 4
|
||||||
|
store i64 200, ptr %12, align 4
|
||||||
|
%13 = load ptr, ptr %2, align 8
|
||||||
|
%14 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 16)
|
||||||
|
%15 = getelementptr inbounds %main.mspan, ptr %13, i32 0, i32 2
|
||||||
|
store ptr %14, ptr %15, align 8
|
||||||
|
%16 = load ptr, ptr %2, align 8
|
||||||
|
%17 = getelementptr inbounds %main.mspan, ptr %16, i32 0, i32 2
|
||||||
|
%18 = load ptr, ptr %17, align 8
|
||||||
|
%19 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 64)
|
||||||
|
%20 = getelementptr inbounds %main.mSpanList, ptr %18, i32 0, i32 1
|
||||||
|
store ptr %19, ptr %20, align 8
|
||||||
|
%21 = load ptr, ptr %2, align 8
|
||||||
|
%22 = getelementptr inbounds %main.mspan, ptr %21, i32 0, i32 2
|
||||||
|
%23 = load ptr, ptr %22, align 8
|
||||||
|
%24 = getelementptr inbounds %main.mSpanList, ptr %23, i32 0, i32 1
|
||||||
|
%25 = load ptr, ptr %24, align 8
|
||||||
|
%26 = getelementptr inbounds %main.mspan, ptr %25, i32 0, i32 4
|
||||||
|
store i64 300, ptr %26, align 4
|
||||||
|
%27 = load ptr, ptr %2, align 8
|
||||||
|
%28 = getelementptr inbounds %main.mspan, ptr %27, i32 0, i32 3
|
||||||
|
%29 = getelementptr inbounds %main.minfo, ptr %28, i32 0, i32 1
|
||||||
|
store i64 10, ptr %29, align 4
|
||||||
|
%30 = load ptr, ptr %2, align 8
|
||||||
|
%31 = getelementptr inbounds %main.mspan, ptr %30, i32 0, i32 3
|
||||||
|
%32 = load ptr, ptr %2, align 8
|
||||||
|
%33 = getelementptr inbounds %main.minfo, ptr %31, i32 0, i32 0
|
||||||
|
store ptr %32, ptr %33, align 8
|
||||||
|
%34 = load ptr, ptr %2, align 8
|
||||||
|
%35 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8)
|
||||||
|
%36 = getelementptr inbounds { ptr }, ptr %35, i32 0, i32 0
|
||||||
|
store ptr %2, ptr %36, align 8
|
||||||
|
%37 = alloca { ptr, ptr }, align 8
|
||||||
|
%38 = getelementptr inbounds { ptr, ptr }, ptr %37, i32 0, i32 0
|
||||||
|
store ptr @"main.main$1", ptr %38, align 8
|
||||||
|
%39 = getelementptr inbounds { ptr, ptr }, ptr %37, i32 0, i32 1
|
||||||
|
store ptr %35, ptr %39, align 8
|
||||||
|
%40 = load { ptr, ptr }, ptr %37, align 8
|
||||||
|
%41 = getelementptr inbounds %main.mspan, ptr %34, i32 0, i32 5
|
||||||
|
store { ptr, ptr } %40, ptr %41, align 8
|
||||||
|
%42 = load ptr, ptr %2, align 8
|
||||||
|
%43 = getelementptr inbounds %main.mspan, ptr %42, i32 0, i32 0
|
||||||
|
%44 = load ptr, ptr %43, align 8
|
||||||
|
%45 = getelementptr inbounds %main.mspan, ptr %44, i32 0, i32 4
|
||||||
|
%46 = load i64, ptr %45, align 4
|
||||||
|
%47 = load ptr, ptr %2, align 8
|
||||||
|
%48 = getelementptr inbounds %main.mspan, ptr %47, i32 0, i32 2
|
||||||
|
%49 = load ptr, ptr %48, align 8
|
||||||
|
%50 = getelementptr inbounds %main.mSpanList, ptr %49, i32 0, i32 1
|
||||||
|
%51 = load ptr, ptr %50, align 8
|
||||||
|
%52 = getelementptr inbounds %main.mspan, ptr %51, i32 0, i32 4
|
||||||
|
%53 = load i64, ptr %52, align 4
|
||||||
|
%54 = load ptr, ptr %2, align 8
|
||||||
|
%55 = getelementptr inbounds %main.mspan, ptr %54, i32 0, i32 3
|
||||||
|
%56 = getelementptr inbounds %main.minfo, ptr %55, i32 0, i32 1
|
||||||
|
%57 = load i64, ptr %56, align 4
|
||||||
|
%58 = load ptr, ptr %2, align 8
|
||||||
|
%59 = getelementptr inbounds %main.mspan, ptr %58, i32 0, i32 3
|
||||||
|
%60 = getelementptr inbounds %main.minfo, ptr %59, i32 0, i32 0
|
||||||
|
%61 = load ptr, ptr %60, align 8
|
||||||
|
%62 = getelementptr inbounds %main.mspan, ptr %61, i32 0, i32 4
|
||||||
|
%63 = load i64, ptr %62, align 4
|
||||||
|
%64 = load ptr, ptr %2, align 8
|
||||||
|
%65 = getelementptr inbounds %main.mspan, ptr %64, i32 0, i32 5
|
||||||
|
%66 = load { ptr, ptr }, ptr %65, align 8
|
||||||
|
%67 = extractvalue { ptr, ptr } %66, 1
|
||||||
|
%68 = extractvalue { ptr, ptr } %66, 0
|
||||||
|
%69 = call i64 %68(ptr %67, i64 -2)
|
||||||
|
%70 = load ptr, ptr %2, align 8
|
||||||
|
%71 = getelementptr inbounds %main.mspan, ptr %70, i32 0, i32 3
|
||||||
|
%72 = getelementptr inbounds %main.minfo, ptr %71, i32 0, i32 0
|
||||||
|
%73 = load ptr, ptr %72, align 8
|
||||||
|
%74 = getelementptr inbounds %main.mspan, ptr %73, i32 0, i32 5
|
||||||
|
%75 = load { ptr, ptr }, ptr %74, align 8
|
||||||
|
%76 = extractvalue { ptr, ptr } %75, 1
|
||||||
|
%77 = extractvalue { ptr, ptr } %75, 0
|
||||||
|
%78 = call i64 %77(ptr %76, i64 -3)
|
||||||
|
%79 = call i32 (ptr, ...) @printf(ptr @0, i64 %46, i64 %53, i64 %57, i64 %63, i64 %69, i64 %78)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
|
||||||
|
|
||||||
|
define i64 @"main.main$1"(ptr %0, i64 %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = load { ptr }, ptr %0, align 8
|
||||||
|
%3 = extractvalue { ptr } %2, 0
|
||||||
|
%4 = load ptr, ptr %3, align 8
|
||||||
|
%5 = getelementptr inbounds %main.mspan, ptr %4, i32 0, i32 4
|
||||||
|
%6 = load i64, ptr %5, align 4
|
||||||
|
%7 = mul i64 %6, %1
|
||||||
|
ret i64 %7
|
||||||
|
}
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64)
|
||||||
|
|
||||||
|
declare i32 @printf(ptr, ...)
|
||||||
@@ -147,11 +147,23 @@ func TestCompileEx(t *testing.T, src any, fname, expected string) {
|
|||||||
}
|
}
|
||||||
return rt
|
return rt
|
||||||
})
|
})
|
||||||
|
prog.SetPython(func() *types.Package {
|
||||||
|
rt, err := imp.Import(llssa.PkgPython)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("load python failed:", err)
|
||||||
|
}
|
||||||
|
return rt
|
||||||
|
})
|
||||||
|
|
||||||
ret, err := cl.NewPackage(prog, foo, files)
|
ret, err := cl.NewPackage(prog, foo, files)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("cl.NewPackage failed:", err)
|
t.Fatal("cl.NewPackage failed:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if prog.NeedPyInit { // call PyInit if needed
|
||||||
|
ret.PyInit()
|
||||||
|
}
|
||||||
|
|
||||||
if v := ret.String(); v != expected {
|
if v := ret.String(); v != expected {
|
||||||
t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected)
|
t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected)
|
||||||
}
|
}
|
||||||
|
|||||||
172
cl/compile.go
172
cl/compile.go
@@ -123,6 +123,7 @@ type instrOrValue interface {
|
|||||||
const (
|
const (
|
||||||
PkgNormal = iota
|
PkgNormal = iota
|
||||||
PkgLLGo
|
PkgLLGo
|
||||||
|
PkgPyModule // py.<module>
|
||||||
PkgNoInit // noinit: a package that don't need to be initialized
|
PkgNoInit // noinit: a package that don't need to be initialized
|
||||||
PkgDeclOnly // decl: a package that only have declarations
|
PkgDeclOnly // decl: a package that only have declarations
|
||||||
PkgLinkIR // link llvm ir (.ll)
|
PkgLinkIR // link llvm ir (.ll)
|
||||||
@@ -142,6 +143,7 @@ type context struct {
|
|||||||
goProg *ssa.Program
|
goProg *ssa.Program
|
||||||
goTyps *types.Package
|
goTyps *types.Package
|
||||||
goPkg *ssa.Package
|
goPkg *ssa.Package
|
||||||
|
pyMod string
|
||||||
link map[string]string // pkgPath.nameInPkg => linkname
|
link map[string]string // pkgPath.nameInPkg => linkname
|
||||||
loaded map[*types.Package]*pkgInfo // loaded packages
|
loaded map[*types.Package]*pkgInfo // loaded packages
|
||||||
bvals map[ssa.Value]llssa.Expr // block values
|
bvals map[ssa.Value]llssa.Expr // block values
|
||||||
@@ -174,7 +176,7 @@ func (p *context) compileMethods(pkg llssa.Package, typ types.Type) {
|
|||||||
for i, n := 0, mthds.Len(); i < n; i++ {
|
for i, n := 0, mthds.Len(); i < n; i++ {
|
||||||
mthd := mthds.At(i)
|
mthd := mthds.At(i)
|
||||||
if ssaMthd := prog.MethodValue(mthd); ssaMthd != nil {
|
if ssaMthd := prog.MethodValue(mthd); ssaMthd != nil {
|
||||||
p.compileFuncDecl(pkg, ssaMthd)
|
p.compileFuncDecl(pkg, ssaMthd, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -209,14 +211,19 @@ var (
|
|||||||
argvTy = types.NewPointer(types.NewPointer(types.Typ[types.Int8]))
|
argvTy = types.NewPointer(types.NewPointer(types.Typ[types.Int8]))
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) llssa.Function {
|
func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function, call bool) (llssa.Function, llssa.PyObjRef, int) {
|
||||||
pkgTypes, name, ftype := p.funcName(f, true)
|
pkgTypes, name, ftype := p.funcName(f, true)
|
||||||
if ftype != goFunc {
|
if ftype != goFunc {
|
||||||
return nil
|
if ftype == pyFunc {
|
||||||
|
// TODO(xsw): pyMod == ""
|
||||||
|
fnName := pysymPrefix + p.pyMod + "." + name
|
||||||
|
return nil, pkg.NewPyFunc(fnName, f.Signature, call), pyFunc
|
||||||
|
}
|
||||||
|
return nil, nil, ignoredFunc
|
||||||
}
|
}
|
||||||
fn := pkg.FuncOf(name)
|
fn := pkg.FuncOf(name)
|
||||||
if fn != nil && fn.HasBody() {
|
if fn != nil && fn.HasBody() {
|
||||||
return fn
|
return fn, nil, goFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
var sig = f.Signature
|
var sig = f.Signature
|
||||||
@@ -262,21 +269,34 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) llssa.Func
|
|||||||
off[i] = p.compilePhis(b, block)
|
off[i] = p.compilePhis(b, block)
|
||||||
}
|
}
|
||||||
for i, block := range f.Blocks {
|
for i, block := range f.Blocks {
|
||||||
p.compileBlock(b, block, off[i], i == 0 && name == "main")
|
doMainInit := (i == 0 && name == "main")
|
||||||
|
doModInit := (i == 1 && f.Name() == "init" && sig.Recv() == nil)
|
||||||
|
p.compileBlock(b, block, off[i], doMainInit, doModInit)
|
||||||
}
|
}
|
||||||
for _, phi := range p.phis {
|
for _, phi := range p.phis {
|
||||||
phi()
|
phi()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return fn
|
return fn, nil, goFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
// funcOf returns a function by name and set ftype = goFunc, cFunc, etc.
|
// funcOf returns a function by name and set ftype = goFunc, cFunc, etc.
|
||||||
// or returns nil and set ftype = llgoCstr, llgoAlloca, llgoUnreachable, etc.
|
// or returns nil and set ftype = llgoCstr, llgoAlloca, llgoUnreachable, etc.
|
||||||
func (p *context) funcOf(fn *ssa.Function) (ret llssa.Function, ftype int) {
|
func (p *context) funcOf(fn *ssa.Function) (aFn llssa.Function, pyFn llssa.PyObjRef, ftype int) {
|
||||||
_, name, ftype := p.funcName(fn, false)
|
pkgTypes, name, ftype := p.funcName(fn, false)
|
||||||
if ftype == llgoInstr {
|
switch ftype {
|
||||||
|
case pyFunc:
|
||||||
|
if kind, mod := pkgKindByScope(pkgTypes.Scope()); kind == PkgPyModule {
|
||||||
|
pkg := p.pkg
|
||||||
|
fnName := pysymPrefix + mod + "." + name
|
||||||
|
if pyFn = pkg.PyObjOf(fnName); pyFn == nil {
|
||||||
|
pyFn = pkg.NewPyFunc(fnName, fn.Signature, true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ftype = ignoredFunc
|
||||||
|
case llgoInstr:
|
||||||
switch name {
|
switch name {
|
||||||
case "cstr":
|
case "cstr":
|
||||||
ftype = llgoCstr
|
ftype = llgoCstr
|
||||||
@@ -288,31 +308,71 @@ func (p *context) funcOf(fn *ssa.Function) (ret llssa.Function, ftype int) {
|
|||||||
ftype = llgoAlloca
|
ftype = llgoAlloca
|
||||||
case "allocaCStr":
|
case "allocaCStr":
|
||||||
ftype = llgoAllocaCStr
|
ftype = llgoAllocaCStr
|
||||||
|
case "stringData":
|
||||||
|
ftype = llgoStringData
|
||||||
case "unreachable":
|
case "unreachable":
|
||||||
ftype = llgoUnreachable
|
ftype = llgoUnreachable
|
||||||
case "bitCastTo64F":
|
|
||||||
ftype = llgoBitCastTo64F
|
|
||||||
case "bitCastTo32F":
|
|
||||||
ftype = llgoBitCastTo32F
|
|
||||||
default:
|
default:
|
||||||
panic("unknown llgo instruction: " + name)
|
panic("unknown llgo instruction: " + name)
|
||||||
}
|
}
|
||||||
} else {
|
default:
|
||||||
pkg := p.pkg
|
pkg := p.pkg
|
||||||
if ret = pkg.FuncOf(name); ret == nil && len(fn.FreeVars) == 0 {
|
if aFn = pkg.FuncOf(name); aFn == nil {
|
||||||
|
if len(fn.FreeVars) > 0 {
|
||||||
|
return nil, nil, ignoredFunc
|
||||||
|
}
|
||||||
sig := fn.Signature
|
sig := fn.Signature
|
||||||
ret = pkg.NewFuncEx(name, sig, llssa.Background(ftype), false)
|
aFn = pkg.NewFuncEx(name, sig, llssa.Background(ftype), false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, doInit bool) llssa.BasicBlock {
|
func modOf(name string) string {
|
||||||
ret := p.fn.Block(block.Index)
|
if pos := strings.LastIndexByte(name, '.'); pos > 0 {
|
||||||
|
return name[:pos]
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, doMainInit, doModInit bool) llssa.BasicBlock {
|
||||||
|
var last int
|
||||||
|
var pyModInit bool
|
||||||
|
var prog = p.prog
|
||||||
|
var pkg = p.pkg
|
||||||
|
var instrs = block.Instrs[n:]
|
||||||
|
var ret = p.fn.Block(block.Index)
|
||||||
b.SetBlock(ret)
|
b.SetBlock(ret)
|
||||||
if doInit {
|
if doModInit {
|
||||||
prog := p.prog
|
if pyModInit = p.pyMod != ""; pyModInit {
|
||||||
pkg := p.pkg
|
last = len(instrs) - 1
|
||||||
|
instrs = instrs[:last]
|
||||||
|
} else {
|
||||||
|
// TODO(xsw): confirm pyMod don't need to call LoadPyModSyms
|
||||||
|
p.inits = append(p.inits, func() {
|
||||||
|
if objs := pkg.PyObjs(); len(objs) > 0 {
|
||||||
|
mods := make(map[string][]llssa.PyObjRef)
|
||||||
|
for name, obj := range objs {
|
||||||
|
modName := modOf(name)
|
||||||
|
mods[modName] = append(mods[modName], obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort by module name
|
||||||
|
modNames := make([]string, 0, len(mods))
|
||||||
|
for modName := range mods {
|
||||||
|
modNames = append(modNames, modName)
|
||||||
|
}
|
||||||
|
sort.Strings(modNames)
|
||||||
|
|
||||||
|
b.SetBlockEx(ret, llssa.AfterInit)
|
||||||
|
for _, modName := range modNames {
|
||||||
|
objs := mods[modName]
|
||||||
|
b.LoadPyModSyms(modName, objs...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else if doMainInit {
|
||||||
fn := p.fn
|
fn := p.fn
|
||||||
argc := pkg.NewVar("__llgo_argc", types.NewPointer(types.Typ[types.Int32]), llssa.InC)
|
argc := pkg.NewVar("__llgo_argc", types.NewPointer(types.Typ[types.Int32]), llssa.InC)
|
||||||
argv := pkg.NewVar("__llgo_argv", types.NewPointer(argvTy), llssa.InC)
|
argv := pkg.NewVar("__llgo_argv", types.NewPointer(argvTy), llssa.InC)
|
||||||
@@ -323,9 +383,23 @@ func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, do
|
|||||||
callRuntimeInit(b, pkg)
|
callRuntimeInit(b, pkg)
|
||||||
b.Call(pkg.FuncOf("main.init").Expr)
|
b.Call(pkg.FuncOf("main.init").Expr)
|
||||||
}
|
}
|
||||||
for _, instr := range block.Instrs[n:] {
|
for _, instr := range instrs {
|
||||||
p.compileInstr(b, instr)
|
p.compileInstr(b, instr)
|
||||||
}
|
}
|
||||||
|
if pyModInit {
|
||||||
|
jump := block.Instrs[n+last].(*ssa.Jump)
|
||||||
|
jumpTo := p.jumpTo(jump)
|
||||||
|
modPath := p.pyMod
|
||||||
|
modName := pysymPrefix + modPath
|
||||||
|
modPtr := pkg.NewPyModVar(modName, true).Expr
|
||||||
|
mod := b.Load(modPtr)
|
||||||
|
cond := b.BinOp(token.NEQ, mod, prog.Null(mod.Type))
|
||||||
|
newBlk := p.fn.MakeBlock()
|
||||||
|
b.If(cond, jumpTo, newBlk)
|
||||||
|
b.SetBlock(newBlk)
|
||||||
|
b.Store(modPtr, b.ImportPyMod(modPath))
|
||||||
|
b.Jump(jumpTo)
|
||||||
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,8 +408,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func callRuntimeInit(b llssa.Builder, pkg llssa.Package) {
|
func callRuntimeInit(b llssa.Builder, pkg llssa.Package) {
|
||||||
sig := types.NewSignatureType(nil, nil, nil, nil, nil, false)
|
fn := pkg.NewFunc(RuntimeInit, llssa.NoArgsNoRet, llssa.InC) // don't need to convert runtime.init
|
||||||
fn := pkg.NewFunc(RuntimeInit, sig, llssa.InC) // don't need to convert runtime.init
|
|
||||||
b.Call(fn.Expr)
|
b.Call(fn.Expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,6 +507,15 @@ func (p *context) allocaCStr(b llssa.Builder, args []ssa.Value) (ret llssa.Expr)
|
|||||||
panic("allocaCStr(s string): invalid arguments")
|
panic("allocaCStr(s string): invalid arguments")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// func stringData(s string) *int8
|
||||||
|
func (p *context) stringData(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
|
||||||
|
if len(args) == 1 {
|
||||||
|
s := p.compileValue(b, args[0])
|
||||||
|
return b.StringData(s)
|
||||||
|
}
|
||||||
|
panic("stringData(s string): invalid arguments")
|
||||||
|
}
|
||||||
|
|
||||||
func isPhi(i ssa.Instruction) bool {
|
func isPhi(i ssa.Instruction) bool {
|
||||||
_, ok := i.(*ssa.Phi)
|
_, ok := i.(*ssa.Phi)
|
||||||
return ok
|
return ok
|
||||||
@@ -441,7 +523,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
|
||||||
@@ -510,11 +592,14 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
|
|||||||
ret = b.BuiltinCall(fn, args...)
|
ret = b.BuiltinCall(fn, args...)
|
||||||
}
|
}
|
||||||
case *ssa.Function:
|
case *ssa.Function:
|
||||||
fn, ftype := p.compileFunction(cv)
|
aFn, pyFn, ftype := p.compileFunction(cv)
|
||||||
switch ftype {
|
switch ftype {
|
||||||
case goFunc, cFunc:
|
case goFunc, cFunc:
|
||||||
args := p.compileValues(b, args, kind)
|
args := p.compileValues(b, args, kind)
|
||||||
ret = b.Call(fn.Expr, args...)
|
ret = b.Call(aFn.Expr, args...)
|
||||||
|
case pyFunc:
|
||||||
|
args := p.compileValues(b, args, kind)
|
||||||
|
ret = b.Call(pyFn.Expr, args...)
|
||||||
case llgoCstr:
|
case llgoCstr:
|
||||||
ret = cstr(b, args)
|
ret = cstr(b, args)
|
||||||
case llgoAdvance:
|
case llgoAdvance:
|
||||||
@@ -525,12 +610,10 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
|
|||||||
ret = p.alloca(b, args)
|
ret = p.alloca(b, args)
|
||||||
case llgoAllocaCStr:
|
case llgoAllocaCStr:
|
||||||
ret = p.allocaCStr(b, args)
|
ret = p.allocaCStr(b, args)
|
||||||
|
case llgoStringData:
|
||||||
|
ret = p.stringData(b, args)
|
||||||
case llgoUnreachable: // func unreachable()
|
case llgoUnreachable: // func unreachable()
|
||||||
b.Unreachable()
|
b.Unreachable()
|
||||||
case llgoBitCastTo32F:
|
|
||||||
ret = b.BitCast(p.compileValue(b, args[0]), b.Prog.Type(types.Typ[types.Float32], llssa.InGo))
|
|
||||||
case llgoBitCastTo64F:
|
|
||||||
ret = b.BitCast(p.compileValue(b, args[0]), b.Prog.Float64())
|
|
||||||
default:
|
default:
|
||||||
panic("todo")
|
panic("todo")
|
||||||
}
|
}
|
||||||
@@ -650,6 +733,12 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *context) jumpTo(v *ssa.Jump) llssa.BasicBlock {
|
||||||
|
fn := p.fn
|
||||||
|
succs := v.Block().Succs
|
||||||
|
return fn.Block(succs[0].Index)
|
||||||
|
}
|
||||||
|
|
||||||
func (p *context) compileInstr(b llssa.Builder, instr ssa.Instruction) {
|
func (p *context) compileInstr(b llssa.Builder, instr ssa.Instruction) {
|
||||||
if iv, ok := instr.(instrOrValue); ok {
|
if iv, ok := instr.(instrOrValue); ok {
|
||||||
p.compileInstrOrValue(b, iv, false)
|
p.compileInstrOrValue(b, iv, false)
|
||||||
@@ -673,9 +762,7 @@ func (p *context) compileInstr(b llssa.Builder, instr ssa.Instruction) {
|
|||||||
val := p.compileValue(b, v.Val)
|
val := p.compileValue(b, v.Val)
|
||||||
b.Store(ptr, val)
|
b.Store(ptr, val)
|
||||||
case *ssa.Jump:
|
case *ssa.Jump:
|
||||||
fn := p.fn
|
jmpb := p.jumpTo(v)
|
||||||
succs := v.Block().Succs
|
|
||||||
jmpb := fn.Block(succs[0].Index)
|
|
||||||
b.Jump(jmpb)
|
b.Jump(jmpb)
|
||||||
case *ssa.Return:
|
case *ssa.Return:
|
||||||
var results []llssa.Expr
|
var results []llssa.Expr
|
||||||
@@ -706,12 +793,13 @@ func (p *context) compileInstr(b llssa.Builder, instr ssa.Instruction) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) compileFunction(v *ssa.Function) (llssa.Function, int) {
|
func (p *context) compileFunction(v *ssa.Function) (goFn llssa.Function, pyFn llssa.PyObjRef, kind int) {
|
||||||
// v.Pkg == nil: means auto generated function?
|
// v.Pkg == nil: means auto generated function?
|
||||||
if v.Pkg == p.goPkg || v.Pkg == nil {
|
if v.Pkg == p.goPkg || v.Pkg == nil {
|
||||||
// function in this package
|
// function in this package
|
||||||
if fn := p.compileFuncDecl(p.pkg, v); fn != nil {
|
goFn, pyFn, kind = p.compileFuncDecl(p.pkg, v, true)
|
||||||
return fn, goFunc
|
if kind != ignoredFunc {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return p.funcOf(v)
|
return p.funcOf(v)
|
||||||
@@ -730,8 +818,11 @@ func (p *context) compileValue(b llssa.Builder, v ssa.Value) llssa.Expr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case *ssa.Function:
|
case *ssa.Function:
|
||||||
fn, _ := p.compileFunction(v)
|
aFn, pyFn, _ := p.compileFunction(v)
|
||||||
return fn.Expr
|
if aFn != nil {
|
||||||
|
return aFn.Expr
|
||||||
|
}
|
||||||
|
return pyFn.Expr
|
||||||
case *ssa.Global:
|
case *ssa.Global:
|
||||||
g := p.varOf(v)
|
g := p.varOf(v)
|
||||||
return g.Expr
|
return g.Expr
|
||||||
@@ -814,6 +905,7 @@ func NewPackage(prog llssa.Program, pkg *ssa.Package, files []*ast.File) (ret ll
|
|||||||
types.Unsafe: {kind: PkgDeclOnly}, // TODO(xsw): PkgNoInit or PkgDeclOnly?
|
types.Unsafe: {kind: PkgDeclOnly}, // TODO(xsw): PkgNoInit or PkgDeclOnly?
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
ctx.initPyModule()
|
||||||
ctx.initFiles(pkgPath, files)
|
ctx.initFiles(pkgPath, files)
|
||||||
for _, m := range members {
|
for _, m := range members {
|
||||||
member := m.val
|
member := m.val
|
||||||
@@ -824,7 +916,7 @@ func NewPackage(prog llssa.Program, pkg *ssa.Package, files []*ast.File) (ret ll
|
|||||||
// Do not try to build generic (non-instantiated) functions.
|
// Do not try to build generic (non-instantiated) functions.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ctx.compileFuncDecl(ret, member)
|
ctx.compileFuncDecl(ret, member, false)
|
||||||
case *ssa.Type:
|
case *ssa.Type:
|
||||||
ctx.compileType(ret, member)
|
ctx.compileType(ret, member)
|
||||||
case *ssa.Global:
|
case *ssa.Global:
|
||||||
|
|||||||
@@ -28,8 +28,12 @@ func testCompile(t *testing.T, src, expected string) {
|
|||||||
cltest.TestCompileEx(t, src, "foo.go", expected)
|
cltest.TestCompileEx(t, src, "foo.go", expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFromTestpy(t *testing.T) {
|
||||||
|
cltest.FromDir(t, "", "./_testpy", false)
|
||||||
|
}
|
||||||
|
|
||||||
func TestFromTestlibc(t *testing.T) {
|
func TestFromTestlibc(t *testing.T) {
|
||||||
cltest.FromDir(t, "", "./_testlibc", false)
|
cltest.FromDir(t, "", "./_testlibc", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFromTestrt(t *testing.T) {
|
func TestFromTestrt(t *testing.T) {
|
||||||
@@ -44,6 +48,14 @@ func TestSqlite(t *testing.T) {
|
|||||||
cltest.Pkg(t, "github.com/goplus/llgo/x/sqlite", "../x/sqlite/sqlite.ll")
|
cltest.Pkg(t, "github.com/goplus/llgo/x/sqlite", "../x/sqlite/sqlite.ll")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
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")
|
||||||
}
|
}
|
||||||
|
|||||||
27
cl/import.go
27
cl/import.go
@@ -30,6 +30,8 @@ import (
|
|||||||
"golang.org/x/tools/go/ssa"
|
"golang.org/x/tools/go/ssa"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
type symInfo struct {
|
type symInfo struct {
|
||||||
file string
|
file string
|
||||||
fullName string
|
fullName string
|
||||||
@@ -101,6 +103,8 @@ func pkgKind(v string) (int, string) {
|
|||||||
// return PkgLinkBitCode
|
// return PkgLinkBitCode
|
||||||
if strings.HasPrefix(v, "link:") { // "link: <libpath>"
|
if strings.HasPrefix(v, "link:") { // "link: <libpath>"
|
||||||
return PkgLinkExtern, v[5:]
|
return PkgLinkExtern, v[5:]
|
||||||
|
} else if strings.HasPrefix(v, "py.") { // "py.<module>"
|
||||||
|
return PkgPyModule, v[3:]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return PkgLLGo, ""
|
return PkgLLGo, ""
|
||||||
@@ -210,7 +214,7 @@ func (p *context) initLink(line string, prefix int, f func(inPkgName string) (fu
|
|||||||
} else {
|
} else {
|
||||||
panic(line + ": no specified call convention. eg. //go:linkname Printf C.printf")
|
panic(line + ": no specified call convention. eg. //go:linkname Printf C.printf")
|
||||||
}
|
}
|
||||||
} else {
|
} else if c := inPkgName[0]; c >= 'A' && c <= 'Z' {
|
||||||
fmt.Fprintln(os.Stderr, "==>", line)
|
fmt.Fprintln(os.Stderr, "==>", line)
|
||||||
fmt.Fprintf(os.Stderr, "llgo: linkname %s not found and ignored\n", inPkgName)
|
fmt.Fprintf(os.Stderr, "llgo: linkname %s not found and ignored\n", inPkgName)
|
||||||
}
|
}
|
||||||
@@ -303,6 +307,7 @@ const (
|
|||||||
ignoredFunc = iota
|
ignoredFunc = iota
|
||||||
goFunc = int(llssa.InGo)
|
goFunc = int(llssa.InGo)
|
||||||
cFunc = int(llssa.InC)
|
cFunc = int(llssa.InC)
|
||||||
|
pyFunc = int(llssa.InPython)
|
||||||
llgoInstr = -1
|
llgoInstr = -1
|
||||||
|
|
||||||
llgoInstrBase = 0x80
|
llgoInstrBase = 0x80
|
||||||
@@ -312,8 +317,7 @@ const (
|
|||||||
llgoAllocaCStr = llgoInstrBase + 3
|
llgoAllocaCStr = llgoInstrBase + 3
|
||||||
llgoAdvance = llgoInstrBase + 4
|
llgoAdvance = llgoInstrBase + 4
|
||||||
llgoIndex = llgoInstrBase + 5
|
llgoIndex = llgoInstrBase + 5
|
||||||
llgoBitCastTo32F = llgoInstrBase + 6
|
llgoStringData = llgoInstrBase + 6
|
||||||
llgoBitCastTo64F = llgoInstrBase + 7
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p *context) funcName(fn *ssa.Function, ignore bool) (*types.Package, string, int) {
|
func (p *context) funcName(fn *ssa.Function, ignore bool) (*types.Package, string, int) {
|
||||||
@@ -339,6 +343,9 @@ func (p *context) funcName(fn *ssa.Function, ignore bool) (*types.Package, strin
|
|||||||
if strings.HasPrefix(v, "C.") {
|
if strings.HasPrefix(v, "C.") {
|
||||||
return nil, v[2:], cFunc
|
return nil, v[2:], cFunc
|
||||||
}
|
}
|
||||||
|
if strings.HasPrefix(v, "py.") {
|
||||||
|
return pkg, v[3:], pyFunc
|
||||||
|
}
|
||||||
if strings.HasPrefix(v, "llgo.") {
|
if strings.HasPrefix(v, "llgo.") {
|
||||||
return nil, v[5:], llgoInstr
|
return nil, v[5:], llgoInstr
|
||||||
}
|
}
|
||||||
@@ -391,3 +398,17 @@ func pkgKindByPath(pkgPath string) int {
|
|||||||
}
|
}
|
||||||
return PkgNormal
|
return PkgNormal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const (
|
||||||
|
pysymPrefix = "__llgo_py."
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p *context) initPyModule() {
|
||||||
|
if kind, mod := pkgKindByScope(p.goTyps.Scope()); kind == PkgPyModule {
|
||||||
|
p.pyMod = mod
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -18,3 +18,5 @@ require (
|
|||||||
golang.org/x/mod v0.17.0 // indirect
|
golang.org/x/mod v0.17.0 // indirect
|
||||||
golang.org/x/sync v0.7.0 // indirect
|
golang.org/x/sync v0.7.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
retract v0.8.0
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
wasm "github.com/aykevl/go-wasm"
|
wasm "github.com/aykevl/go-wasm"
|
||||||
"github.com/goplus/llgo/x/ar"
|
"github.com/goplus/llgo/xtool/ar"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Create creates an arcive for static linking from a list of object files
|
// Create creates an arcive for static linking from a list of object files
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import (
|
|||||||
"golang.org/x/tools/go/ssa"
|
"golang.org/x/tools/go/ssa"
|
||||||
|
|
||||||
"github.com/goplus/llgo/cl"
|
"github.com/goplus/llgo/cl"
|
||||||
"github.com/goplus/llgo/x/clang"
|
"github.com/goplus/llgo/xtool/clang"
|
||||||
|
|
||||||
llssa "github.com/goplus/llgo/ssa"
|
llssa "github.com/goplus/llgo/ssa"
|
||||||
)
|
)
|
||||||
@@ -120,18 +120,31 @@ func Do(args []string, conf *Config) {
|
|||||||
cl.SetDebug(cl.DbgFlagAll)
|
cl.SetDebug(cl.DbgFlagAll)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var needRt bool
|
||||||
var rt []*packages.Package
|
var rt []*packages.Package
|
||||||
prog := llssa.NewProgram(nil)
|
prog := llssa.NewProgram(nil)
|
||||||
prog.SetRuntime(func() *types.Package {
|
load := func() []*packages.Package {
|
||||||
rt, err = packages.Load(cfg, llssa.PkgRuntime)
|
if rt == nil {
|
||||||
|
var err error
|
||||||
|
rt, err = packages.Load(cfg, llssa.PkgRuntime, llssa.PkgPython)
|
||||||
check(err)
|
check(err)
|
||||||
|
}
|
||||||
|
return rt
|
||||||
|
}
|
||||||
|
prog.SetRuntime(func() *types.Package {
|
||||||
|
needRt = true
|
||||||
|
rt := load()
|
||||||
return rt[0].Types
|
return rt[0].Types
|
||||||
})
|
})
|
||||||
|
prog.SetPython(func() *types.Package {
|
||||||
|
rt := load()
|
||||||
|
return rt[1].Types
|
||||||
|
})
|
||||||
|
|
||||||
pkgs := buildAllPkgs(prog, initial, mode, verbose)
|
pkgs := buildAllPkgs(prog, initial, mode, verbose)
|
||||||
|
|
||||||
var runtimeFiles []string
|
var runtimeFiles []string
|
||||||
if rt != nil {
|
if needRt {
|
||||||
runtimeFiles = allLinkFiles(rt)
|
runtimeFiles = allLinkFiles(rt)
|
||||||
}
|
}
|
||||||
if mode != ModeBuild {
|
if mode != ModeBuild {
|
||||||
@@ -147,12 +160,22 @@ func Do(args []string, conf *Config) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setNeedRuntime(pkg *packages.Package) {
|
func setNeedRuntimeOrPyInit(pkg *packages.Package, needRuntime, needPyInit bool) {
|
||||||
pkg.ID = "" // just use pkg.Module to mark it needs runtime
|
v := []byte{'0', '0'}
|
||||||
|
if needRuntime {
|
||||||
|
v[0] = '1'
|
||||||
|
}
|
||||||
|
if needPyInit {
|
||||||
|
v[1] = '1'
|
||||||
|
}
|
||||||
|
pkg.ID = string(v) // just use pkg.ID to mark it needs runtime
|
||||||
}
|
}
|
||||||
|
|
||||||
func isNeedRuntime(pkg *packages.Package) bool {
|
func isNeedRuntimeOrPyInit(pkg *packages.Package) (needRuntime, needPyInit bool) {
|
||||||
return pkg.ID == ""
|
if len(pkg.ID) == 2 {
|
||||||
|
return pkg.ID[0] == '1', pkg.ID[1] == '1'
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildAllPkgs(prog llssa.Program, initial []*packages.Package, mode Mode, verbose bool) (pkgs []*aPackage) {
|
func buildAllPkgs(prog llssa.Program, initial []*packages.Package, mode Mode, verbose bool) (pkgs []*aPackage) {
|
||||||
@@ -172,28 +195,29 @@ 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:
|
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)
|
||||||
if prog.NeedRuntime() {
|
setNeedRuntimeOrPyInit(pkg, prog.NeedRuntime, prog.NeedPyInit)
|
||||||
setNeedRuntime(pkg)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@@ -212,27 +236,43 @@ func linkMainPkg(pkg *packages.Package, pkgs []*aPackage, runtimeFiles []string,
|
|||||||
args[1] = app
|
args[1] = app
|
||||||
args[2] = "-Wno-override-module"
|
args[2] = "-Wno-override-module"
|
||||||
needRuntime := false
|
needRuntime := false
|
||||||
|
needPyInit := false
|
||||||
packages.Visit([]*packages.Package{pkg}, nil, func(p *packages.Package) {
|
packages.Visit([]*packages.Package{pkg}, nil, func(p *packages.Package) {
|
||||||
if p.ExportFile != "" && !isRuntimePkg(p.PkgPath) { // skip packages that only contain declarations
|
if p.ExportFile != "" && !isRuntimePkg(p.PkgPath) { // skip packages that only contain declarations
|
||||||
args = appendLinkFiles(args, p.ExportFile)
|
args = appendLinkFiles(args, p.ExportFile)
|
||||||
|
need1, need2 := isNeedRuntimeOrPyInit(p)
|
||||||
if !needRuntime {
|
if !needRuntime {
|
||||||
needRuntime = isNeedRuntime(p)
|
needRuntime = need1
|
||||||
|
}
|
||||||
|
if !needPyInit {
|
||||||
|
needPyInit = need2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if needRuntime && runtimeFiles != nil {
|
|
||||||
args = append(args, runtimeFiles...)
|
var aPkg *aPackage
|
||||||
} else {
|
for _, v := range pkgs {
|
||||||
for _, aPkg := range pkgs {
|
if v.Package == pkg { // found this package
|
||||||
if aPkg.Package == pkg { // make empty runtime.init if no runtime needed
|
aPkg = v
|
||||||
lpkg := aPkg.LPkg
|
|
||||||
lpkg.FuncOf(cl.RuntimeInit).MakeBody(1).Return()
|
|
||||||
if needLLFile(mode) {
|
|
||||||
os.WriteFile(pkg.ExportFile, []byte(lpkg.String()), 0644)
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dirty := false
|
||||||
|
if needRuntime && runtimeFiles != nil {
|
||||||
|
args = append(args, runtimeFiles...)
|
||||||
|
} else {
|
||||||
|
dirty = true
|
||||||
|
fn := aPkg.LPkg.FuncOf(cl.RuntimeInit)
|
||||||
|
fn.MakeBody(1).Return()
|
||||||
|
}
|
||||||
|
if needPyInit {
|
||||||
|
dirty = aPkg.LPkg.PyInit()
|
||||||
|
}
|
||||||
|
|
||||||
|
if dirty && needLLFile(mode) {
|
||||||
|
lpkg := aPkg.LPkg
|
||||||
|
os.WriteFile(pkg.ExportFile, []byte(lpkg.String()), 0644)
|
||||||
}
|
}
|
||||||
|
|
||||||
if verbose || mode != ModeRun {
|
if verbose || mode != ModeRun {
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import (
|
|||||||
"golang.org/x/tools/go/ssa/ssautil"
|
"golang.org/x/tools/go/ssa/ssautil"
|
||||||
|
|
||||||
llssa "github.com/goplus/llgo/ssa"
|
llssa "github.com/goplus/llgo/ssa"
|
||||||
|
cpackages "golang.org/x/tools/go/packages"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Init() {
|
func Init() {
|
||||||
@@ -71,14 +72,17 @@ func Gen(pkgPath, inFile string, src any) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
prog := llssa.NewProgram(nil)
|
prog := llssa.NewProgram(nil)
|
||||||
prog.SetRuntime(func() *types.Package {
|
initRtAndPy(prog, &cpackages.Config{
|
||||||
rt, err := imp.Import(llssa.PkgRuntime)
|
Mode: loadSyntax | cpackages.NeedDeps,
|
||||||
check(err)
|
|
||||||
return rt
|
|
||||||
})
|
})
|
||||||
|
|
||||||
ret, err := cl.NewPackage(prog, ssaPkg, files)
|
ret, err := cl.NewPackage(prog, ssaPkg, files)
|
||||||
check(err)
|
check(err)
|
||||||
|
|
||||||
|
if prog.NeedPyInit { // call PyInit if needed
|
||||||
|
ret.PyInit()
|
||||||
|
}
|
||||||
|
|
||||||
return ret.String()
|
return ret.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,27 @@ const (
|
|||||||
loadSyntax = loadTypes | packages.NeedSyntax | packages.NeedTypesInfo
|
loadSyntax = loadTypes | packages.NeedSyntax | packages.NeedTypesInfo
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func initRtAndPy(prog llssa.Program, cfg *packages.Config) {
|
||||||
|
var pkgRtAndPy []*packages.Package
|
||||||
|
load := func() []*packages.Package {
|
||||||
|
if pkgRtAndPy == nil {
|
||||||
|
var err error
|
||||||
|
pkgRtAndPy, err = packages.Load(cfg, llssa.PkgRuntime, llssa.PkgPython)
|
||||||
|
check(err)
|
||||||
|
}
|
||||||
|
return pkgRtAndPy
|
||||||
|
}
|
||||||
|
|
||||||
|
prog.SetRuntime(func() *types.Package {
|
||||||
|
rt := load()
|
||||||
|
return rt[0].Types
|
||||||
|
})
|
||||||
|
prog.SetPython(func() *types.Package {
|
||||||
|
rt := load()
|
||||||
|
return rt[1].Types
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func GenFrom(fileOrPkg string) string {
|
func GenFrom(fileOrPkg string) string {
|
||||||
cfg := &packages.Config{
|
cfg := &packages.Config{
|
||||||
Mode: loadSyntax | packages.NeedDeps,
|
Mode: loadSyntax | packages.NeedDeps,
|
||||||
@@ -52,11 +73,7 @@ func GenFrom(fileOrPkg string) string {
|
|||||||
ssaPkg.Build()
|
ssaPkg.Build()
|
||||||
|
|
||||||
prog := llssa.NewProgram(nil)
|
prog := llssa.NewProgram(nil)
|
||||||
prog.SetRuntime(func() *types.Package {
|
initRtAndPy(prog, cfg)
|
||||||
rt, err := packages.Load(cfg, llssa.PkgRuntime)
|
|
||||||
check(err)
|
|
||||||
return rt[0].Types
|
|
||||||
})
|
|
||||||
|
|
||||||
if Verbose {
|
if Verbose {
|
||||||
ssaPkg.WriteTo(os.Stderr)
|
ssaPkg.WriteTo(os.Stderr)
|
||||||
@@ -65,6 +82,10 @@ func GenFrom(fileOrPkg string) string {
|
|||||||
ret, err := cl.NewPackage(prog, ssaPkg, pkg.Syntax)
|
ret, err := cl.NewPackage(prog, ssaPkg, pkg.Syntax)
|
||||||
check(err)
|
check(err)
|
||||||
|
|
||||||
|
if prog.NeedPyInit { // call PyInit if needed
|
||||||
|
ret.PyInit()
|
||||||
|
}
|
||||||
|
|
||||||
return ret.String()
|
return ret.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@@ -77,38 +77,18 @@ func CheckI2Int(v Interface, t *Type) (uintptr, bool) {
|
|||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func I2Float64(v Interface, t *Type) float64 {
|
func I2String(v Interface, t *Type) string {
|
||||||
if v.tab._type == t {
|
if v.tab._type == t {
|
||||||
return bitCastTo64F(uint64(uintptr(v.data)))
|
return *(*string)(v.data)
|
||||||
}
|
}
|
||||||
panic("I2Float64: type mismatch")
|
panic("I2String: type mismatch")
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckI2Float64(v Interface, t *Type) (float64, bool) {
|
func CheckI2String(v Interface, t *Type) (string, bool) {
|
||||||
if v.tab._type == t {
|
if v.tab._type == t {
|
||||||
return bitCastTo64F(uint64(uintptr(v.data))), true
|
return *(*string)(v.data), true
|
||||||
}
|
}
|
||||||
return 0, false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
func I2Float32(v Interface, t *Type) float32 {
|
|
||||||
if v.tab._type == t {
|
|
||||||
return bitCastTo32F(uint32(uintptr(v.data)))
|
|
||||||
}
|
|
||||||
panic("I2Float32: type mismatch")
|
|
||||||
}
|
|
||||||
|
|
||||||
func CheckI2Float32(v Interface, t *Type) (float32, bool) {
|
|
||||||
if v.tab._type == t {
|
|
||||||
return bitCastTo32F(uint32(uintptr(v.data))), true
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
//go:linkname bitCastTo64F llgo.bitCastTo64F
|
|
||||||
func bitCastTo64F(uint64) float64
|
|
||||||
|
|
||||||
//go:linkname bitCastTo32F llgo.bitCastTo32F
|
|
||||||
func bitCastTo32F(uint32) float32
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -45,16 +45,6 @@ func NewString(data unsafe.Pointer, len int) String {
|
|||||||
return String{data, len}
|
return String{data, len}
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringLen returns the length of a string.
|
|
||||||
func StringLen(s String) int {
|
|
||||||
return s.len
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringData returns the data pointer of a string.
|
|
||||||
func StringData(s String) unsafe.Pointer {
|
|
||||||
return s.data
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringCat concatenates two strings.
|
// StringCat concatenates two strings.
|
||||||
func StringCat(a, b String) String {
|
func StringCat(a, b String) String {
|
||||||
n := a.len + b.len
|
n := a.len + b.len
|
||||||
|
|||||||
33
py/README.md
Normal file
33
py/README.md
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
Linking Python to Go
|
||||||
|
=====
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
## Demo
|
||||||
|
|
||||||
|
The `_demo` directory contains our demos (it start with `_` to prevent the `go` command from compiling it):
|
||||||
|
|
||||||
|
* [hellopy](_demo/hellopy/hello.go): link Python to Go and say `Hello world`
|
||||||
|
* [clpy](_demo/clpy/cleval.go): compile Python code and eval.
|
||||||
|
* [callpy](_demo/callpy/call.go): call Python standard library function `math.sqrt`.
|
||||||
|
|
||||||
|
### How to run demos
|
||||||
|
|
||||||
|
To run the demos in directory `_demo`, you need to set the `LLGO_LIB_PYTHON` environment variable first. Assuming you use Python 3.12, and the `libpython3.12.so` (or `libpython3.12.dylib` or `python3.12.lib`) file is in the /foo/bar directory, then you need to set `LLGO_LIB_PYTHON` to:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
export LLGO_LIB_PYTHON=/foo/bar/python3.12
|
||||||
|
```
|
||||||
|
|
||||||
|
For example, `/opt/homebrew/Frameworks/Python.framework/Versions/3.12/libpython3.12.dylib` is a typical python lib location under macOS. So we should set it like this:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
export LLGO_LIB_PYTHON=/opt/homebrew/Frameworks/Python.framework/Versions/3.12/python3.12
|
||||||
|
```
|
||||||
|
|
||||||
|
Then you can run the demos in directory `_demo`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd <demo-directory> # eg. cd _demo/hellopy
|
||||||
|
llgo run .
|
||||||
|
```
|
||||||
19
py/_demo/callpy/call.go
Normal file
19
py/_demo/callpy/call.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/py"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
py.Initialize()
|
||||||
|
py.SetProgramName(*c.Argv)
|
||||||
|
math := py.ImportModule(c.Str("math"))
|
||||||
|
sqrt := math.GetAttrString(c.Str("sqrt"))
|
||||||
|
sqrt2 := sqrt.CallOneArg(py.Float(2))
|
||||||
|
c.Printf(c.Str("sqrt(2) = %f\n"), sqrt2.Float64())
|
||||||
|
sqrt2.DecRef()
|
||||||
|
sqrt.DecRef()
|
||||||
|
math.DecRef()
|
||||||
|
py.Finalize()
|
||||||
|
}
|
||||||
23
py/_demo/clpy/cleval.go
Normal file
23
py/_demo/clpy/cleval.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/py"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
py.Initialize()
|
||||||
|
py.SetProgramName(*c.Argv)
|
||||||
|
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.ModuleGetDict()
|
||||||
|
|
||||||
|
result := py.EvalCode(code, gbl, nil)
|
||||||
|
|
||||||
|
result.DecRef()
|
||||||
|
mod.DecRef()
|
||||||
|
code.DecRef()
|
||||||
|
}
|
||||||
|
py.Finalize()
|
||||||
|
}
|
||||||
13
py/_demo/hellopy/hello.go
Normal file
13
py/_demo/hellopy/hello.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/py"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
py.Initialize()
|
||||||
|
py.SetProgramName(*c.Argv)
|
||||||
|
py.RunSimpleString(c.Str(`print('Hello, World!')`))
|
||||||
|
py.Finalize()
|
||||||
|
}
|
||||||
25
py/_pyg/module.c
Normal file
25
py/_pyg/module.c
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
// example:
|
||||||
|
// llgoLoadPyModSyms(mod, "name1", &func1, "name2", &func2, NULL)
|
||||||
|
|
||||||
|
typedef struct PyObject PyObject;
|
||||||
|
|
||||||
|
PyObject* PyObject_GetAttrString(PyObject* mod, const char* attrName);
|
||||||
|
|
||||||
|
void llgoLoadPyModSyms(PyObject* mod, ...) {
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, mod);
|
||||||
|
for (;;) {
|
||||||
|
const char* name = va_arg(ap, const char*);
|
||||||
|
if (name == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
PyObject** pfunc = va_arg(ap, PyObject**);
|
||||||
|
if (*pfunc == NULL) {
|
||||||
|
*pfunc = PyObject_GetAttrString(mod, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
46
py/bytes.go
Normal file
46
py/bytes.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* 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 py
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
// https://docs.python.org/3/c-api/bytes.html
|
||||||
|
|
||||||
|
// String returns a new bytes object from a C string.
|
||||||
|
//
|
||||||
|
//go:linkname FromCStr C.PyBytes_FromString
|
||||||
|
func FromCStr(s *c.Char) *Object
|
||||||
|
|
||||||
|
// FromString returns a new bytes object from a Go string.
|
||||||
|
func FromString(s string) *Object {
|
||||||
|
return stringFromStringAndSize(c.GoStringData(s), uintptr(len(s)))
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname stringFromStringAndSize C.PyBytes_FromStringAndSize
|
||||||
|
func stringFromStringAndSize(s *c.Char, size uintptr) *Object
|
||||||
|
|
||||||
|
// CStr returns the content of a bytes object as a C string.
|
||||||
|
//
|
||||||
|
// llgo:link (*Object).CStr C.PyBytes_AsString
|
||||||
|
func (o *Object) CStr() *c.Char { return nil }
|
||||||
|
|
||||||
|
// llgo:link (*Object).Strlen C.PyBytes_Size
|
||||||
|
func (o *Object) Strlen() uintptr { return 0 }
|
||||||
32
py/float.go
Normal file
32
py/float.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* 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 py
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// https://docs.python.org/3/c-api/float.html
|
||||||
|
|
||||||
|
//go:linkname Float C.PyFloat_FromDouble
|
||||||
|
func Float(v float64) *Object
|
||||||
|
|
||||||
|
//go:linkname FloatFromSring C.PyFloat_FromString
|
||||||
|
func FloatFromSring(v *Object) *Object
|
||||||
|
|
||||||
|
// llgo:link (*Object).Float64 C.PyFloat_AsDouble
|
||||||
|
func (o *Object) Float64() float64 { return 0 }
|
||||||
6
py/llgo.cfg
Normal file
6
py/llgo.cfg
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"cl": [
|
||||||
|
"clang -emit-llvm -S -o module.ll -c _pyg/module.c",
|
||||||
|
"rm llgo_autogen.lla; zip llgo_autogen.lla llgo_autogen.ll module.ll",
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
py/llgo_autogen.lla
Normal file
BIN
py/llgo_autogen.lla
Normal file
Binary file not shown.
BIN
py/math/llgo_autogen.lla
Normal file
BIN
py/math/llgo_autogen.lla
Normal file
Binary file not shown.
30
py/math/math.go
Normal file
30
py/math/math.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* 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 math
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/py"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LLGoPackage = "py.math"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:linkname Sqrt py.sqrt
|
||||||
|
func Sqrt(x *py.Object) *py.Object
|
||||||
56
py/module.go
Normal file
56
py/module.go
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* 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 py
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// 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) *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
|
||||||
|
// from the __builtins__ of the current globals. This means that the import is done using
|
||||||
|
// whatever import hooks are installed in the current environment.
|
||||||
|
//
|
||||||
|
// This function always uses absolute imports.
|
||||||
|
//
|
||||||
|
//go:linkname Import C.PyImport_Import
|
||||||
|
func Import(name *Object) *Object
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// subtype of a module object), SystemError is raised and nil is returned.
|
||||||
|
//
|
||||||
|
// It is recommended extensions use other Module and Object functions rather than directly
|
||||||
|
// manipulate a module’s __dict__.
|
||||||
|
//
|
||||||
|
// llgo:link (*Object).ModuleGetDict C.PyModule_GetDict
|
||||||
|
func (m *Object) ModuleGetDict() *Object { return nil }
|
||||||
|
|
||||||
|
// llgo:link (*Object).ModuleLoadSyms C.llgoLoadPyModSyms
|
||||||
|
func (m *Object) ModuleLoadSyms(__llgo_va_list ...any) {}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
82
py/module.ll
Normal file
82
py/module.ll
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
; ModuleID = '_pyg/module.c'
|
||||||
|
source_filename = "_pyg/module.c"
|
||||||
|
|
||||||
|
%struct.PyObject = type opaque
|
||||||
|
|
||||||
|
; Function Attrs: noinline nounwind optnone ssp uwtable(sync)
|
||||||
|
define void @llgoLoadPyModSyms(%struct.PyObject* noundef %0, ...) #0 {
|
||||||
|
%2 = alloca %struct.PyObject*, align 8
|
||||||
|
%3 = alloca i8*, align 8
|
||||||
|
%4 = alloca i8*, align 8
|
||||||
|
%5 = alloca i8*, align 8
|
||||||
|
%6 = alloca %struct.PyObject**, align 8
|
||||||
|
%7 = alloca %struct.PyObject**, align 8
|
||||||
|
store %struct.PyObject* %0, %struct.PyObject** %2, align 8
|
||||||
|
%8 = bitcast i8** %3 to i8*
|
||||||
|
call void @llvm.va_start(i8* %8)
|
||||||
|
br label %9
|
||||||
|
|
||||||
|
9: ; preds = %26, %1
|
||||||
|
%10 = va_arg i8** %3, i8*
|
||||||
|
store i8* %10, i8** %5, align 8
|
||||||
|
%11 = load i8*, i8** %5, align 8
|
||||||
|
store i8* %11, i8** %4, align 8
|
||||||
|
%12 = load i8*, i8** %4, align 8
|
||||||
|
%13 = icmp eq i8* %12, null
|
||||||
|
br i1 %13, label %14, label %15
|
||||||
|
|
||||||
|
14: ; preds = %9
|
||||||
|
br label %27
|
||||||
|
|
||||||
|
15: ; preds = %9
|
||||||
|
%16 = va_arg i8** %3, %struct.PyObject**
|
||||||
|
store %struct.PyObject** %16, %struct.PyObject*** %7, align 8
|
||||||
|
%17 = load %struct.PyObject**, %struct.PyObject*** %7, align 8
|
||||||
|
store %struct.PyObject** %17, %struct.PyObject*** %6, align 8
|
||||||
|
%18 = load %struct.PyObject**, %struct.PyObject*** %6, align 8
|
||||||
|
%19 = load %struct.PyObject*, %struct.PyObject** %18, align 8
|
||||||
|
%20 = icmp eq %struct.PyObject* %19, null
|
||||||
|
br i1 %20, label %21, label %26
|
||||||
|
|
||||||
|
21: ; preds = %15
|
||||||
|
%22 = load %struct.PyObject*, %struct.PyObject** %2, align 8
|
||||||
|
%23 = load i8*, i8** %4, align 8
|
||||||
|
%24 = call %struct.PyObject* @PyObject_GetAttrString(%struct.PyObject* noundef %22, i8* noundef %23)
|
||||||
|
%25 = load %struct.PyObject**, %struct.PyObject*** %6, align 8
|
||||||
|
store %struct.PyObject* %24, %struct.PyObject** %25, align 8
|
||||||
|
br label %26
|
||||||
|
|
||||||
|
26: ; preds = %21, %15
|
||||||
|
br label %9
|
||||||
|
|
||||||
|
27: ; preds = %14
|
||||||
|
%28 = bitcast i8** %3 to i8*
|
||||||
|
call void @llvm.va_end(i8* %28)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; Function Attrs: nocallback nofree nosync nounwind willreturn
|
||||||
|
declare void @llvm.va_start(i8*) #1
|
||||||
|
|
||||||
|
declare %struct.PyObject* @PyObject_GetAttrString(%struct.PyObject* noundef, i8* noundef) #2
|
||||||
|
|
||||||
|
; Function Attrs: nocallback nofree nosync nounwind willreturn
|
||||||
|
declare void @llvm.va_end(i8*) #1
|
||||||
|
|
||||||
|
attributes #0 = { noinline nounwind optnone ssp uwtable(sync) "frame-pointer"="non-leaf" "min-legal-vector-width"="0" "no-trapping-math"="true" "probe-stack"="__chkstk_darwin" "stack-protector-buffer-size"="8" "target-cpu"="apple-m1" "target-features"="+aes,+crc,+crypto,+dotprod,+fp-armv8,+fp16fml,+fullfp16,+lse,+neon,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+v8.5a,+zcm,+zcz" }
|
||||||
|
attributes #1 = { nocallback nofree nosync nounwind willreturn }
|
||||||
|
attributes #2 = { "frame-pointer"="non-leaf" "no-trapping-math"="true" "probe-stack"="__chkstk_darwin" "stack-protector-buffer-size"="8" "target-cpu"="apple-m1" "target-features"="+aes,+crc,+crypto,+dotprod,+fp-armv8,+fp16fml,+fullfp16,+lse,+neon,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+v8.5a,+zcm,+zcz" }
|
||||||
|
|
||||||
|
!llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6, !7, !8}
|
||||||
|
!llvm.ident = !{!9}
|
||||||
|
|
||||||
|
!0 = !{i32 2, !"SDK Version", [2 x i32] [i32 13, i32 3]}
|
||||||
|
!1 = !{i32 1, !"wchar_size", i32 4}
|
||||||
|
!2 = !{i32 8, !"branch-target-enforcement", i32 0}
|
||||||
|
!3 = !{i32 8, !"sign-return-address", i32 0}
|
||||||
|
!4 = !{i32 8, !"sign-return-address-all", i32 0}
|
||||||
|
!5 = !{i32 8, !"sign-return-address-with-bkey", i32 0}
|
||||||
|
!6 = !{i32 7, !"PIC Level", i32 2}
|
||||||
|
!7 = !{i32 7, !"uwtable", i32 1}
|
||||||
|
!8 = !{i32 7, !"frame-pointer", i32 1}
|
||||||
|
!9 = !{!"Apple clang version 14.0.3 (clang-1403.0.22.14.1)"}
|
||||||
158
py/object.go
Normal file
158
py/object.go
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
/*
|
||||||
|
* 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 py
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Object represents a Python object.
|
||||||
|
type Object struct {
|
||||||
|
Unused [8]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new value based on a format string similar to those accepted by the
|
||||||
|
// PyArg_Parse* family of functions and a sequence of values. Returns the value or
|
||||||
|
// nil in the case of an error; an exception will be raised if nil is returned.
|
||||||
|
// See https://docs.python.org/3/c-api/arg.html#c.Py_BuildValue
|
||||||
|
//
|
||||||
|
//go:linkname BuildValue C.Py_BuildValue
|
||||||
|
func BuildValue(format *c.Char, __llgo_va_list ...any) *Object
|
||||||
|
|
||||||
|
// llgo:link (*Object).DecRef C.Py_DecRef
|
||||||
|
func (o *Object) DecRef() {}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Retrieve an attribute named attrName from object o. Returns the attribute value on success,
|
||||||
|
// or nil on failure. This is the equivalent of the Python expression o.attrName.
|
||||||
|
//
|
||||||
|
// llgo:link (*Object).GetAttr C.PyObject_GetAttr
|
||||||
|
func (o *Object) GetAttr(attrName *Object) *Object { return nil }
|
||||||
|
|
||||||
|
// llgo:link (*Object).GetAttrString C.PyObject_GetAttrString
|
||||||
|
func (o *Object) GetAttrString(attrName *c.Char) *Object { return nil }
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Determine if the object o is callable. Return 1 if the object is callable and
|
||||||
|
// 0 otherwise. This function always succeeds.
|
||||||
|
//
|
||||||
|
// llgo:link (*Object).Callable C.PyCallable_Check
|
||||||
|
func (o *Object) Callable() c.Int { return 0 }
|
||||||
|
|
||||||
|
// Call a callable Python object o, with arguments given by the tuple args, and
|
||||||
|
// named arguments given by the dictionary kwargs.
|
||||||
|
//
|
||||||
|
// args must not be nil; use an empty tuple if no arguments are needed. If no named
|
||||||
|
// arguments are needed, kwargs can be nil.
|
||||||
|
//
|
||||||
|
// Return the result of the call on success, or raise an exception and return nil
|
||||||
|
// on failure.
|
||||||
|
//
|
||||||
|
// This is the equivalent of the Python expression: o(*args, **kwargs).
|
||||||
|
//
|
||||||
|
// llgo:link (*Object).Call C.PyObject_Call
|
||||||
|
func (o *Object) Call(args, kwargs *Object) *Object { return nil }
|
||||||
|
|
||||||
|
// Call a callable Python object callable without any arguments. It is the most
|
||||||
|
// efficient way to call a callable Python object without any argument.
|
||||||
|
//
|
||||||
|
// Return the result of the call on success, or raise an exception and return nil
|
||||||
|
// on failure.
|
||||||
|
//
|
||||||
|
// llgo:link (*Object).CallNoArgs C.PyObject_CallNoArgs
|
||||||
|
func (o *Object) CallNoArgs() *Object { return nil }
|
||||||
|
|
||||||
|
// Call a callable Python object callable with exactly 1 positional argument arg
|
||||||
|
// and no keyword arguments.
|
||||||
|
//
|
||||||
|
// Return the result of the call on success, or raise an exception and return nil
|
||||||
|
// on failure.
|
||||||
|
//
|
||||||
|
// llgo:link (*Object).CallOneArg C.PyObject_CallOneArg
|
||||||
|
func (o *Object) CallOneArg(arg *Object) *Object { return nil }
|
||||||
|
|
||||||
|
// Call a callable Python object o, with arguments given by the tuple args. If no
|
||||||
|
// arguments are needed, then args can be nil.
|
||||||
|
//
|
||||||
|
// Return the result of the call on success, or raise an exception and return nil
|
||||||
|
// on failure.
|
||||||
|
//
|
||||||
|
// This is the equivalent of the Python expression: o(*args).
|
||||||
|
//
|
||||||
|
// llgo:link (*Object).CallObject C.PyObject_CallObject
|
||||||
|
func (o *Object) CallObject(callable, args *Object) *Object { return nil }
|
||||||
|
|
||||||
|
// Call a callable Python object o, with a variable number of C arguments. The C
|
||||||
|
// arguments are described using a py.BuildValue style format string. The format
|
||||||
|
// can be nil, indicating that no arguments are provided.
|
||||||
|
//
|
||||||
|
// Return the result of the call on success, or raise an exception and return nil
|
||||||
|
// on failure.
|
||||||
|
//
|
||||||
|
// This is the equivalent of the Python expression: o(*args).
|
||||||
|
//
|
||||||
|
// Note that if you only pass PyObject* args, (*Object).CallFunctionObjArgs is a
|
||||||
|
// faster alternative.
|
||||||
|
//
|
||||||
|
// llgo:link (*Object).CallFunction C.PyObject_CallFunction
|
||||||
|
func (o *Object) CallFunction(format *c.Char, __llgo_va_list ...any) *Object { return nil }
|
||||||
|
|
||||||
|
// Call a callable Python object o, with a variable number of PyObject* arguments.
|
||||||
|
// The arguments are provided as a variable number of parameters followed by nil.
|
||||||
|
//
|
||||||
|
// Return the result of the call on success, or raise an exception and return nil
|
||||||
|
// on failure.
|
||||||
|
//
|
||||||
|
// This is the equivalent of the Python expression: o(arg1, arg2, ...).
|
||||||
|
//
|
||||||
|
// llgo:link (*Object).CallFunctionObjArgs C.PyObject_CallFunctionObjArgs
|
||||||
|
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 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Object).CallMethodObjArgs C.PyObject_CallMethodObjArgs
|
||||||
|
func (o *Object) CallMethodObjArgs(name *Object, __llgo_va_list ...any) *Object { return nil }
|
||||||
|
|
||||||
|
// llgo:link (*Object).CallMethodNoArgs C.PyObject_CallMethodNoArgs
|
||||||
|
func (o *Object) CallMethodNoArgs(name *Object) *Object { return nil }
|
||||||
|
|
||||||
|
// llgo:link (*Object).CallMethodOneArg C.PyObject_CallMethodOneArg
|
||||||
|
func (o *Object) CallMethodOneArg(name, arg *Object) *Object { return nil }
|
||||||
|
|
||||||
|
// llgo:link (*Object).Vectorcall C.PyObject_Vectorcall
|
||||||
|
func (o *Object) Vectorcall(args **Object, nargs uintptr, kwnames *Object) *Object {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Object).VectorcallDict C.PyObject_VectorcallDict
|
||||||
|
func (o *Object) VectorcallDict(args **Object, nargs uintptr, kwdict *Object) *Object {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Object).VectorcallMethod C.PyObject_VectorcallMethod
|
||||||
|
func (o *Object) VectorcallMethod(name *Object, args **Object, nargs uintptr, kwnames *Object) *Object {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
BIN
py/os/llgo_autogen.lla
Normal file
BIN
py/os/llgo_autogen.lla
Normal file
Binary file not shown.
30
py/os/os.go
Normal file
30
py/os/os.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* 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 os
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/py"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LLGoPackage = "py.os"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:linkname Getcwd py.getcwd
|
||||||
|
func Getcwd() *py.Object
|
||||||
120
py/python.go
Normal file
120
py/python.go
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
* 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 py
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LLGoPackage = "link: $LLGO_LIB_PYTHON"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//go:linkname SetProgramName C.Py_SetProgramName
|
||||||
|
func SetProgramName(name *c.Char)
|
||||||
|
|
||||||
|
//go:linkname Initialize C.Py_Initialize
|
||||||
|
func Initialize()
|
||||||
|
|
||||||
|
// This function works like Initialize() if initsigs is 1.
|
||||||
|
// If initsigs is 0, it skips initialization registration of signal handlers,
|
||||||
|
// which might be useful when Python is embedded.
|
||||||
|
//
|
||||||
|
//go:linkname InitializeEx C.Py_InitializeEx
|
||||||
|
func InitializeEx(initsigs c.Int)
|
||||||
|
|
||||||
|
//go:linkname Finalize C.Py_Finalize
|
||||||
|
func Finalize()
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//go:linkname RunSimpleString C.PyRun_SimpleString
|
||||||
|
func RunSimpleString(command *c.Char) c.Int
|
||||||
|
|
||||||
|
//go:linkname RunSimpleStringFlags C.PyRun_SimpleStringFlags
|
||||||
|
func RunSimpleStringFlags(command *c.Char, flags *CompilerFlags) c.Int
|
||||||
|
|
||||||
|
//go:linkname RunSimpleFile C.PyRun_SimpleFile
|
||||||
|
func RunSimpleFile(fp c.FilePtr, filename *c.Char) c.Int
|
||||||
|
|
||||||
|
//go:linkname RunSimpleFileFlags C.PyRun_SimpleFileFlags
|
||||||
|
func RunSimpleFileFlags(fp c.FilePtr, filename *c.Char, flags *CompilerFlags) c.Int
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type InputType c.Int
|
||||||
|
|
||||||
|
const (
|
||||||
|
SingleInput InputType = 256 // read code from i/o
|
||||||
|
FileInput InputType = 257 // read code from filename
|
||||||
|
EvalInput InputType = 258 // read code from string
|
||||||
|
// FuncTypeInput InputType = 345
|
||||||
|
)
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type CompilerFlags struct {
|
||||||
|
CfFlags c.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname CompileString C.Py_CompileString
|
||||||
|
func CompileString(str, filename *c.Char, start InputType) *Object
|
||||||
|
|
||||||
|
//go:linkname CompileStringFlags C.Py_CompileStringFlags
|
||||||
|
func CompileStringFlags(str, filename *c.Char, start InputType, flags *CompilerFlags) *Object
|
||||||
|
|
||||||
|
//go:linkname CompileStringExFlags C.Py_CompileStringExFlags
|
||||||
|
func CompileStringExFlags(str, filename *c.Char, start InputType, flags *CompilerFlags, optimize c.Int) *Object
|
||||||
|
|
||||||
|
// Parse and compile the Python source code in str, returning the resulting code object.
|
||||||
|
// The start token is given by start; this can be used to constrain the code which can be
|
||||||
|
// compiled and should be py.EvalInput, py.FileInput, or py.SingleInput. The filename
|
||||||
|
// specified by filename is used to construct the code object and may appear in tracebacks
|
||||||
|
// or SyntaxError exception messages. This returns NULL if the code cannot be parsed or
|
||||||
|
// compiled.
|
||||||
|
//
|
||||||
|
// The integer optimize specifies the optimization level of the compiler; a value of -1
|
||||||
|
// selects the optimization level of the interpreter as given by -O options. Explicit levels
|
||||||
|
// are 0 (no optimization; __debug__ is true), 1 (asserts are removed, __debug__ is false) or
|
||||||
|
// 2 (docstrings are removed too).
|
||||||
|
//
|
||||||
|
//go:linkname CompileStringObject C.Py_CompileStringObject
|
||||||
|
func CompileStringObject(str *c.Char, filename *Object, start InputType, flags *CompilerFlags, optimize c.Int) *Object
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// This is a simplified interface to EvalCodeEx, with just the code object, and global and
|
||||||
|
// local variables. The other arguments are set to nil.
|
||||||
|
//
|
||||||
|
//go:linkname EvalCode C.PyEval_EvalCode
|
||||||
|
func EvalCode(code, globals, locals *Object) *Object
|
||||||
|
|
||||||
|
// Evaluate a precompiled code object, given a particular environment for its evaluation.
|
||||||
|
// This environment consists of a dictionary of global variables, a mapping object of local
|
||||||
|
// variables, arrays of arguments, keywords and defaults, a dictionary of default values for
|
||||||
|
// keyword-only arguments and a closure tuple of cells.
|
||||||
|
//
|
||||||
|
//go:linkname EvalCodeEx C.PyEval_EvalCodeEx
|
||||||
|
func EvalCodeEx(
|
||||||
|
code, globals, locals *Object,
|
||||||
|
args *Object, argcount c.Int, kws *Object, kwcount c.Int,
|
||||||
|
defs *Object, defcount c.Int, kwdefs, closure *Object) *Object
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
@@ -22,6 +22,10 @@ import (
|
|||||||
"github.com/goplus/llgo/cl/cltest"
|
"github.com/goplus/llgo/cl/cltest"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestFromTestpy(t *testing.T) {
|
||||||
|
cltest.FromDir(t, "", "../cl/_testpy", false)
|
||||||
|
}
|
||||||
|
|
||||||
func TestFromTestrt(t *testing.T) {
|
func TestFromTestrt(t *testing.T) {
|
||||||
cltest.FromDir(t, "", "../cl/_testrt", true)
|
cltest.FromDir(t, "", "../cl/_testrt", true)
|
||||||
}
|
}
|
||||||
|
|||||||
104
ssa/decl.go
104
ssa/decl.go
@@ -18,6 +18,7 @@ package ssa
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"go/types"
|
"go/types"
|
||||||
|
"log"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/goplus/llvm"
|
"github.com/goplus/llvm"
|
||||||
@@ -68,6 +69,23 @@ type aGlobal struct {
|
|||||||
// variable.
|
// variable.
|
||||||
type Global = *aGlobal
|
type Global = *aGlobal
|
||||||
|
|
||||||
|
// NewVar creates a new global variable.
|
||||||
|
func (p Package) NewVar(name string, typ types.Type, bg Background) Global {
|
||||||
|
if v, ok := p.vars[name]; ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
t := p.Prog.Type(typ, bg)
|
||||||
|
gbl := llvm.AddGlobal(p.mod, t.ll, name)
|
||||||
|
ret := &aGlobal{Expr{gbl, t}}
|
||||||
|
p.vars[name] = ret
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// VarOf returns a global variable by name.
|
||||||
|
func (p Package) VarOf(name string) Global {
|
||||||
|
return p.vars[name]
|
||||||
|
}
|
||||||
|
|
||||||
// Init initializes the global variable with the given value.
|
// Init initializes the global variable with the given value.
|
||||||
func (g Global) Init(v Expr) {
|
func (g Global) Init(v Expr) {
|
||||||
g.impl.SetInitializer(v.impl)
|
g.impl.SetInitializer(v.impl)
|
||||||
@@ -140,6 +158,31 @@ type aFunction struct {
|
|||||||
// Function represents a function or method.
|
// Function represents a function or method.
|
||||||
type Function = *aFunction
|
type Function = *aFunction
|
||||||
|
|
||||||
|
// NewFunc creates a new function.
|
||||||
|
func (p Package) NewFunc(name string, sig *types.Signature, bg Background) Function {
|
||||||
|
return p.NewFuncEx(name, sig, bg, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFuncEx creates a new function.
|
||||||
|
func (p Package) NewFuncEx(name string, sig *types.Signature, bg Background, hasFreeVars bool) Function {
|
||||||
|
if v, ok := p.fns[name]; ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
t := p.Prog.FuncDecl(sig, bg)
|
||||||
|
if debugInstr {
|
||||||
|
log.Println("NewFunc", name, t.raw.Type, "hasFreeVars:", hasFreeVars)
|
||||||
|
}
|
||||||
|
fn := llvm.AddFunction(p.mod, name, t.ll)
|
||||||
|
ret := newFunction(fn, t, p, p.Prog, hasFreeVars)
|
||||||
|
p.fns[name] = ret
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// FuncOf returns a function by name.
|
||||||
|
func (p Package) FuncOf(name string) Function {
|
||||||
|
return p.fns[name]
|
||||||
|
}
|
||||||
|
|
||||||
func newFunction(fn llvm.Value, t Type, pkg Package, prog Program, hasFreeVars bool) Function {
|
func newFunction(fn llvm.Value, t Type, pkg Package, prog Program, hasFreeVars bool) Function {
|
||||||
params, hasVArg := newParams(t, prog)
|
params, hasVArg := newParams(t, prog)
|
||||||
base := 0
|
base := 0
|
||||||
@@ -212,22 +255,71 @@ func (p Function) MakeBody(nblk int) Builder {
|
|||||||
|
|
||||||
// MakeBlocks creates nblk basic blocks for the function.
|
// MakeBlocks creates nblk basic blocks for the function.
|
||||||
func (p Function) MakeBlocks(nblk int) []BasicBlock {
|
func (p Function) MakeBlocks(nblk int) []BasicBlock {
|
||||||
if p.blks == nil {
|
n := len(p.blks)
|
||||||
|
if n == 0 {
|
||||||
p.blks = make([]BasicBlock, 0, nblk)
|
p.blks = make([]BasicBlock, 0, nblk)
|
||||||
}
|
}
|
||||||
n := len(p.blks)
|
|
||||||
f := p.impl
|
|
||||||
for i := 0; i < nblk; i++ {
|
for i := 0; i < nblk; i++ {
|
||||||
label := "_llgo_" + strconv.Itoa(i)
|
p.addBlock(n + i)
|
||||||
blk := llvm.AddBasicBlock(f, label)
|
|
||||||
p.blks = append(p.blks, &aBasicBlock{blk, p, n + i})
|
|
||||||
}
|
}
|
||||||
return p.blks[n:]
|
return p.blks[n:]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p Function) addBlock(idx int) BasicBlock {
|
||||||
|
label := "_llgo_" + strconv.Itoa(idx)
|
||||||
|
blk := llvm.AddBasicBlock(p.impl, label)
|
||||||
|
ret := &aBasicBlock{blk, p, idx}
|
||||||
|
p.blks = append(p.blks, ret)
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeBlock creates a new basic block for the function.
|
||||||
|
func (p Function) MakeBlock() BasicBlock {
|
||||||
|
return p.addBlock(len(p.blks))
|
||||||
|
}
|
||||||
|
|
||||||
// Block returns the ith basic block of the function.
|
// Block returns the ith basic block of the function.
|
||||||
func (p Function) Block(idx int) BasicBlock {
|
func (p Function) Block(idx int) BasicBlock {
|
||||||
return p.blks[idx]
|
return p.blks[idx]
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type aPyObjRef struct {
|
||||||
|
Expr
|
||||||
|
Obj Global
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
if v, ok := p.pyobjs[name]; ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
prog := p.Prog
|
||||||
|
obj := p.NewVar(name, prog.PyObjectPtrPtr().RawType(), InC)
|
||||||
|
if doInit {
|
||||||
|
prog.NeedPyInit = true
|
||||||
|
obj.Init(prog.Null(obj.Type))
|
||||||
|
obj.impl.SetLinkage(llvm.LinkOnceAnyLinkage)
|
||||||
|
}
|
||||||
|
ty := &aType{obj.ll, rawType{types.NewPointer(sig)}, vkPyFuncRef}
|
||||||
|
expr := Expr{obj.impl, ty}
|
||||||
|
ret := &aPyObjRef{expr, obj}
|
||||||
|
p.pyobjs[name] = ret
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// PyObjOf returns a python object by name.
|
||||||
|
func (p Package) PyObjOf(name string) PyObjRef {
|
||||||
|
return p.pyobjs[name]
|
||||||
|
}
|
||||||
|
|
||||||
|
// PyObjs returns all used python objects in this project.
|
||||||
|
func (p Package) PyObjs() map[string]PyObjRef {
|
||||||
|
return p.pyobjs
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
104
ssa/expr.go
104
ssa/expr.go
@@ -24,6 +24,7 @@ import (
|
|||||||
"go/types"
|
"go/types"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/internal/abi"
|
||||||
"github.com/goplus/llvm"
|
"github.com/goplus/llvm"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -257,6 +258,11 @@ var floatPredOpToLLVM = []llvm.FloatPredicate{
|
|||||||
token.GEQ - predOpBase: llvm.FloatOGE,
|
token.GEQ - predOpBase: llvm.FloatOGE,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var boolPredOpToLLVM = []llvm.IntPredicate{
|
||||||
|
token.EQL - predOpBase: llvm.IntEQ,
|
||||||
|
token.NEQ - predOpBase: llvm.IntNE,
|
||||||
|
}
|
||||||
|
|
||||||
// EQL NEQ LSS LEQ GTR GEQ == != < <= < >=
|
// EQL NEQ LSS LEQ GTR GEQ == != < <= < >=
|
||||||
func isPredOp(op token.Token) bool {
|
func isPredOp(op token.Token) bool {
|
||||||
return op >= predOpBase && op <= predOpLast
|
return op >= predOpBase && op <= predOpLast
|
||||||
@@ -289,7 +295,7 @@ func (b Builder) BinOp(op token.Token, x, y Expr) Expr {
|
|||||||
}
|
}
|
||||||
case isLogicOp(op): // op: & | ^ << >> &^
|
case isLogicOp(op): // op: & | ^ << >> &^
|
||||||
if op == token.AND_NOT {
|
if op == token.AND_NOT {
|
||||||
panic("todo")
|
return Expr{b.impl.CreateAnd(x.impl, b.impl.CreateNot(y.impl, ""), ""), x.Type}
|
||||||
}
|
}
|
||||||
kind := x.kind
|
kind := x.kind
|
||||||
llop := logicOpToLLVM[op-logicOpBase]
|
llop := logicOpToLLVM[op-logicOpBase]
|
||||||
@@ -310,7 +316,10 @@ func (b Builder) BinOp(op token.Token, x, y Expr) Expr {
|
|||||||
case vkFloat:
|
case vkFloat:
|
||||||
pred := floatPredOpToLLVM[op-predOpBase]
|
pred := floatPredOpToLLVM[op-predOpBase]
|
||||||
return Expr{llvm.CreateFCmp(b.impl, pred, x.impl, y.impl), tret}
|
return Expr{llvm.CreateFCmp(b.impl, pred, x.impl, y.impl), tret}
|
||||||
case vkString, vkComplex, vkBool:
|
case vkBool:
|
||||||
|
pred := boolPredOpToLLVM[op-predOpBase]
|
||||||
|
return Expr{llvm.CreateICmp(b.impl, pred, x.impl, y.impl), tret}
|
||||||
|
case vkString, vkComplex:
|
||||||
panic("todo")
|
panic("todo")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -598,6 +607,26 @@ func (b Builder) getField(x Expr, idx int) Expr {
|
|||||||
return Expr{fld, tfld}
|
return Expr{fld, tfld}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StringData returns the data pointer of a string.
|
||||||
|
func (b Builder) StringData(x Expr) Expr {
|
||||||
|
if debugInstr {
|
||||||
|
log.Printf("StringData %v\n", x.impl)
|
||||||
|
}
|
||||||
|
prog := b.Prog
|
||||||
|
ptr := llvm.CreateExtractValue(b.impl, x.impl, 0)
|
||||||
|
return Expr{ptr, prog.CStr()}
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringLen returns the length of a string.
|
||||||
|
func (b Builder) StringLen(x Expr) Expr {
|
||||||
|
if debugInstr {
|
||||||
|
log.Printf("StringLen %v\n", x.impl)
|
||||||
|
}
|
||||||
|
prog := b.Prog
|
||||||
|
ptr := llvm.CreateExtractValue(b.impl, x.impl, 1)
|
||||||
|
return Expr{ptr, prog.Int()}
|
||||||
|
}
|
||||||
|
|
||||||
// The IndexAddr instruction yields the address of the element at
|
// The IndexAddr instruction yields the address of the element at
|
||||||
// index `idx` of collection `x`. `idx` is an integer expression.
|
// index `idx` of collection `x`. `idx` is an integer expression.
|
||||||
//
|
//
|
||||||
@@ -649,8 +678,7 @@ func (b Builder) Index(x, idx Expr, addr func(Expr) Expr) Expr {
|
|||||||
panic(fmt.Errorf("invalid operation: cannot index %v", t))
|
panic(fmt.Errorf("invalid operation: cannot index %v", t))
|
||||||
}
|
}
|
||||||
telem = prog.rawType(types.Typ[types.Byte])
|
telem = prog.rawType(types.Typ[types.Byte])
|
||||||
pkg := b.Func.Pkg
|
ptr = b.StringData(x)
|
||||||
ptr = b.InlineCall(pkg.rtFunc("StringData"), x)
|
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
telem = prog.Index(x.Type)
|
telem = prog.Index(x.Type)
|
||||||
if addr != nil {
|
if addr != nil {
|
||||||
@@ -717,7 +745,7 @@ func (b Builder) Slice(x, low, high, max Expr) (ret Expr) {
|
|||||||
panic(fmt.Errorf("invalid operation: cannot slice %v", t))
|
panic(fmt.Errorf("invalid operation: cannot slice %v", t))
|
||||||
}
|
}
|
||||||
if high.IsNil() {
|
if high.IsNil() {
|
||||||
high = b.InlineCall(pkg.rtFunc("StringLen"), x)
|
high = b.StringLen(x)
|
||||||
}
|
}
|
||||||
ret.Type = x.Type
|
ret.Type = x.Type
|
||||||
ret.impl = b.InlineCall(pkg.rtFunc("NewStringSlice"), x, low, high).impl
|
ret.impl = b.InlineCall(pkg.rtFunc("NewStringSlice"), x, low, high).impl
|
||||||
@@ -871,7 +899,7 @@ func (b Builder) AllocaCStr(gostr Expr) (ret Expr) {
|
|||||||
log.Printf("AllocaCStr %v\n", gostr.impl)
|
log.Printf("AllocaCStr %v\n", gostr.impl)
|
||||||
}
|
}
|
||||||
pkg := b.Func.Pkg
|
pkg := b.Func.Pkg
|
||||||
n := b.InlineCall(pkg.rtFunc("StringLen"), gostr)
|
n := b.StringLen(gostr)
|
||||||
n1 := b.BinOp(token.ADD, n, b.Prog.Val(1))
|
n1 := b.BinOp(token.ADD, n, b.Prog.Val(1))
|
||||||
cstr := b.Alloca(n1)
|
cstr := b.Alloca(n1)
|
||||||
return b.InlineCall(pkg.rtFunc("CStrCopy"), cstr, gostr)
|
return b.InlineCall(pkg.rtFunc("CStrCopy"), cstr, gostr)
|
||||||
@@ -1051,7 +1079,7 @@ func (b Builder) MakeInterface(tinter Type, x Expr) (ret Expr) {
|
|||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
kind := tx.Kind()
|
kind := tx.Kind()
|
||||||
switch {
|
switch {
|
||||||
case kind >= types.Int && kind <= types.Uintptr:
|
case kind >= types.Bool && kind <= types.Uintptr:
|
||||||
t := b.InlineCall(pkg.rtFunc("Basic"), prog.Val(int(kind)))
|
t := b.InlineCall(pkg.rtFunc("Basic"), prog.Val(int(kind)))
|
||||||
tptr := prog.Uintptr()
|
tptr := prog.Uintptr()
|
||||||
vptr := Expr{llvm.CreateIntCast(b.impl, x.impl, tptr.ll), tptr}
|
vptr := Expr{llvm.CreateIntCast(b.impl, x.impl, tptr.ll), tptr}
|
||||||
@@ -1118,7 +1146,7 @@ func (b Builder) TypeAssert(x Expr, assertedTyp Type, commaOk bool) (ret Expr) {
|
|||||||
log.Printf("TypeAssert %v, %v, %v\n", x.impl, assertedTyp.raw.Type, commaOk)
|
log.Printf("TypeAssert %v, %v, %v\n", x.impl, assertedTyp.raw.Type, commaOk)
|
||||||
}
|
}
|
||||||
switch assertedTyp.kind {
|
switch assertedTyp.kind {
|
||||||
case vkSigned, vkUnsigned:
|
case vkSigned, vkUnsigned, vkFloat, vkBool:
|
||||||
pkg := b.Func.Pkg
|
pkg := b.Func.Pkg
|
||||||
fnName := "I2Int"
|
fnName := "I2Int"
|
||||||
if commaOk {
|
if commaOk {
|
||||||
@@ -1133,25 +1161,44 @@ func (b Builder) TypeAssert(x Expr, assertedTyp Type, commaOk bool) (ret Expr) {
|
|||||||
panic("todo")
|
panic("todo")
|
||||||
}
|
}
|
||||||
typ := b.InlineCall(pkg.rtFunc("Basic"), b.Prog.Val(int(kind)))
|
typ := b.InlineCall(pkg.rtFunc("Basic"), b.Prog.Val(int(kind)))
|
||||||
return b.InlineCall(fn, x, typ)
|
ret = b.InlineCall(fn, x, typ)
|
||||||
case vkFloat:
|
if kind != types.Uintptr {
|
||||||
var fnName string
|
conv := func(v llvm.Value) llvm.Value {
|
||||||
kind := assertedTyp.raw.Underlying().(*types.Basic).Kind()
|
|
||||||
switch kind {
|
switch kind {
|
||||||
case types.Float32:
|
case types.Float32:
|
||||||
fnName = "I2Float32"
|
v = castInt(b.impl, v, b.Prog.tyInt32())
|
||||||
if commaOk {
|
v = b.impl.CreateBitCast(v, assertedTyp.ll, "")
|
||||||
fnName = "CheckI2Float32"
|
|
||||||
}
|
|
||||||
case types.Float64:
|
case types.Float64:
|
||||||
fnName = "I2Float64"
|
v = b.impl.CreateBitCast(v, assertedTyp.ll, "")
|
||||||
if commaOk {
|
default:
|
||||||
fnName = "CheckI2Float64"
|
v = castInt(b.impl, v, assertedTyp.ll)
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
if !commaOk {
|
||||||
|
ret.Type = assertedTyp
|
||||||
|
ret.impl = conv(ret.impl)
|
||||||
|
} else {
|
||||||
|
ret.Type = b.Prog.toTuple(
|
||||||
|
types.NewTuple(
|
||||||
|
types.NewVar(token.NoPos, nil, "", assertedTyp.RawType()),
|
||||||
|
ret.Type.RawType().(*types.Tuple).At(1),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
val0 := conv(b.impl.CreateExtractValue(ret.impl, 0, ""))
|
||||||
|
val1 := b.impl.CreateExtractValue(ret.impl, 1, "")
|
||||||
|
ret.impl = llvm.ConstStruct([]llvm.Value{val0, val1}, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return
|
||||||
|
case vkString:
|
||||||
pkg := b.Func.Pkg
|
pkg := b.Func.Pkg
|
||||||
|
fnName := "I2String"
|
||||||
|
if commaOk {
|
||||||
|
fnName = "CheckI2String"
|
||||||
|
}
|
||||||
fn := pkg.rtFunc(fnName)
|
fn := pkg.rtFunc(fnName)
|
||||||
typ := b.InlineCall(pkg.rtFunc("Basic"), b.Prog.Val(int(kind)))
|
typ := b.InlineCall(pkg.rtFunc("Basic"), b.Prog.Val(int(abi.String)))
|
||||||
return b.InlineCall(fn, x, typ)
|
return b.InlineCall(fn, x, typ)
|
||||||
}
|
}
|
||||||
panic("todo")
|
panic("todo")
|
||||||
@@ -1176,7 +1223,6 @@ func (b Builder) InlineCall(fn Expr, args ...Expr) (ret Expr) {
|
|||||||
// t4 = t3()
|
// t4 = t3()
|
||||||
// t7 = invoke t5.Println(...t6)
|
// t7 = invoke t5.Println(...t6)
|
||||||
func (b Builder) Call(fn Expr, args ...Expr) (ret Expr) {
|
func (b Builder) Call(fn Expr, args ...Expr) (ret Expr) {
|
||||||
prog := b.Prog
|
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
name := fn.impl.Name()
|
name := fn.impl.Name()
|
||||||
@@ -1191,11 +1237,16 @@ func (b Builder) Call(fn Expr, args ...Expr) (ret Expr) {
|
|||||||
}
|
}
|
||||||
log.Println(b.String())
|
log.Println(b.String())
|
||||||
}
|
}
|
||||||
|
var kind = fn.kind
|
||||||
|
if kind == vkPyFuncRef {
|
||||||
|
return b.pyCall(fn, args)
|
||||||
|
}
|
||||||
var ll llvm.Type
|
var ll llvm.Type
|
||||||
var data Expr
|
var data Expr
|
||||||
var sig *types.Signature
|
var sig *types.Signature
|
||||||
|
var prog = b.Prog
|
||||||
var raw = fn.raw.Type
|
var raw = fn.raw.Type
|
||||||
switch fn.kind {
|
switch kind {
|
||||||
case vkClosure:
|
case vkClosure:
|
||||||
data = b.Field(fn, 1)
|
data = b.Field(fn, 1)
|
||||||
fn = b.Field(fn, 0)
|
fn = b.Field(fn, 0)
|
||||||
@@ -1246,7 +1297,7 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) {
|
|||||||
return b.InlineCall(b.Func.Pkg.rtFunc("SliceLen"), arg)
|
return b.InlineCall(b.Func.Pkg.rtFunc("SliceLen"), arg)
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
if t.Kind() == types.String {
|
if t.Kind() == types.String {
|
||||||
return b.InlineCall(b.Func.Pkg.rtFunc("StringLen"), arg)
|
return b.StringLen(arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1262,11 +1313,4 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) {
|
|||||||
panic("todo")
|
panic("todo")
|
||||||
}
|
}
|
||||||
|
|
||||||
// BitCast bit cast expr to type
|
|
||||||
func (b Builder) BitCast(val Expr, typ Type) (ret Expr) {
|
|
||||||
ret.Type = typ
|
|
||||||
ret.impl = b.impl.CreateBitCast(val.impl, typ.ll, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
248
ssa/package.go
248
ssa/package.go
@@ -19,13 +19,13 @@ package ssa
|
|||||||
import (
|
import (
|
||||||
"go/token"
|
"go/token"
|
||||||
"go/types"
|
"go/types"
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/goplus/llvm"
|
"github.com/goplus/llvm"
|
||||||
"golang.org/x/tools/go/types/typeutil"
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
PkgPython = "github.com/goplus/llgo/py"
|
||||||
PkgRuntime = "github.com/goplus/llgo/internal/runtime"
|
PkgRuntime = "github.com/goplus/llgo/internal/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -103,9 +103,13 @@ type aProgram struct {
|
|||||||
rt *types.Package
|
rt *types.Package
|
||||||
rtget func() *types.Package
|
rtget func() *types.Package
|
||||||
|
|
||||||
|
py *types.Package
|
||||||
|
pyget func() *types.Package
|
||||||
|
|
||||||
target *Target
|
target *Target
|
||||||
td llvm.TargetData
|
td llvm.TargetData
|
||||||
// tm llvm.TargetMachine
|
// tm llvm.TargetMachine
|
||||||
|
named map[string]llvm.Type
|
||||||
|
|
||||||
intType llvm.Type
|
intType llvm.Type
|
||||||
int1Type llvm.Type
|
int1Type llvm.Type
|
||||||
@@ -130,8 +134,16 @@ type aProgram struct {
|
|||||||
uintptrTy Type
|
uintptrTy Type
|
||||||
intTy Type
|
intTy Type
|
||||||
f64Ty Type
|
f64Ty Type
|
||||||
|
pyObjPtr Type
|
||||||
|
pyObjPPtr Type
|
||||||
|
|
||||||
needRuntime bool
|
pyImpTy *types.Signature
|
||||||
|
callNoArgs *types.Signature
|
||||||
|
callOneArg *types.Signature
|
||||||
|
loadPyModS *types.Signature
|
||||||
|
|
||||||
|
NeedRuntime bool
|
||||||
|
NeedPyInit bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Program presents a program.
|
// A Program presents a program.
|
||||||
@@ -154,7 +166,18 @@ func NewProgram(target *Target) Program {
|
|||||||
// TODO(xsw): Finalize may cause panic, so comment it.
|
// TODO(xsw): Finalize may cause panic, so comment it.
|
||||||
ctx.Finalize()
|
ctx.Finalize()
|
||||||
*/
|
*/
|
||||||
return &aProgram{ctx: ctx, gocvt: newGoTypes(), target: target, td: td}
|
return &aProgram{ctx: ctx, gocvt: newGoTypes(), target: target, td: td, named: make(map[string]llvm.Type)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPython sets the Python package.
|
||||||
|
// Its type can be *types.Package or func() *types.Package.
|
||||||
|
func (p Program) SetPython(py any) {
|
||||||
|
switch v := py.(type) {
|
||||||
|
case *types.Package:
|
||||||
|
p.py = v
|
||||||
|
case func() *types.Package:
|
||||||
|
p.pyget = v
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetRuntime sets the runtime.
|
// SetRuntime sets the runtime.
|
||||||
@@ -168,25 +191,33 @@ func (p Program) SetRuntime(runtime any) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NeedRuntime returns if the current package needs runtime.
|
|
||||||
func (p Program) NeedRuntime() bool {
|
|
||||||
return p.needRuntime
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p Program) runtime() *types.Package {
|
func (p Program) runtime() *types.Package {
|
||||||
if p.rt == nil {
|
if p.rt == nil {
|
||||||
p.rt = p.rtget()
|
p.rt = p.rtget()
|
||||||
}
|
}
|
||||||
p.needRuntime = true
|
p.NeedRuntime = true
|
||||||
return p.rt
|
return p.rt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p Program) python() *types.Package {
|
||||||
|
if p.py == nil {
|
||||||
|
p.py = p.pyget()
|
||||||
|
}
|
||||||
|
return p.py
|
||||||
|
}
|
||||||
|
|
||||||
func (p Program) rtNamed(name string) *types.Named {
|
func (p Program) rtNamed(name string) *types.Named {
|
||||||
t := p.runtime().Scope().Lookup(name).Type().(*types.Named)
|
t := p.runtime().Scope().Lookup(name).Type().(*types.Named)
|
||||||
t, _ = p.gocvt.cvtNamed(t)
|
t, _ = p.gocvt.cvtNamed(t)
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p Program) pyNamed(name string) *types.Named {
|
||||||
|
// TODO(xsw): does python type need to convert?
|
||||||
|
t := p.python().Scope().Lookup(name).Type().(*types.Named)
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
func (p Program) rtType(name string) Type {
|
func (p Program) rtType(name string) Type {
|
||||||
return p.rawType(p.rtNamed(name))
|
return p.rawType(p.rtNamed(name))
|
||||||
}
|
}
|
||||||
@@ -227,8 +258,29 @@ func (p Program) NewPackage(name, pkgPath string) Package {
|
|||||||
gbls := make(map[string]Global)
|
gbls := make(map[string]Global)
|
||||||
fns := make(map[string]Function)
|
fns := make(map[string]Function)
|
||||||
stubs := make(map[string]Function)
|
stubs := make(map[string]Function)
|
||||||
p.needRuntime = false
|
pyobjs := make(map[string]PyObjRef)
|
||||||
return &aPackage{mod, gbls, fns, stubs, p}
|
pymods := make(map[string]Global)
|
||||||
|
p.NeedRuntime = false
|
||||||
|
// Don't need reset p.needPyInit here
|
||||||
|
// p.needPyInit = false
|
||||||
|
return &aPackage{mod, gbls, fns, stubs, pyobjs, pymods, p}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PyObjectPtrPtr returns the **py.Object type.
|
||||||
|
func (p Program) PyObjectPtrPtr() Type {
|
||||||
|
if p.pyObjPPtr == nil {
|
||||||
|
p.pyObjPPtr = p.Pointer(p.PyObjectPtr())
|
||||||
|
}
|
||||||
|
return p.pyObjPPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
// PyObjectPtr returns the *py.Object type.
|
||||||
|
func (p Program) PyObjectPtr() Type {
|
||||||
|
if p.pyObjPtr == nil {
|
||||||
|
objPtr := types.NewPointer(p.pyNamed("Object"))
|
||||||
|
p.pyObjPtr = p.rawType(objPtr)
|
||||||
|
}
|
||||||
|
return p.pyObjPtr
|
||||||
}
|
}
|
||||||
|
|
||||||
// Void returns void type.
|
// Void returns void type.
|
||||||
@@ -315,6 +367,8 @@ type aPackage struct {
|
|||||||
vars map[string]Global
|
vars map[string]Global
|
||||||
fns map[string]Function
|
fns map[string]Function
|
||||||
stubs map[string]Function
|
stubs map[string]Function
|
||||||
|
pyobjs map[string]PyObjRef
|
||||||
|
pymods map[string]Global
|
||||||
Prog Program
|
Prog Program
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,40 +381,6 @@ func (p Package) NewConst(name string, val constant.Value) NamedConst {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// NewVar creates a new global variable.
|
|
||||||
func (p Package) NewVar(name string, typ types.Type, bg Background) Global {
|
|
||||||
t := p.Prog.Type(typ, bg)
|
|
||||||
gbl := llvm.AddGlobal(p.mod, t.ll, name)
|
|
||||||
ret := &aGlobal{Expr{gbl, t}}
|
|
||||||
p.vars[name] = ret
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
// VarOf returns a global variable by name.
|
|
||||||
func (p Package) VarOf(name string) Global {
|
|
||||||
return p.vars[name]
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewFunc creates a new function.
|
|
||||||
func (p Package) NewFunc(name string, sig *types.Signature, bg Background) Function {
|
|
||||||
return p.NewFuncEx(name, sig, bg, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewFuncEx creates a new function.
|
|
||||||
func (p Package) NewFuncEx(name string, sig *types.Signature, bg Background, hasFreeVars bool) Function {
|
|
||||||
if v, ok := p.fns[name]; ok {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
t := p.Prog.FuncDecl(sig, bg)
|
|
||||||
if debugInstr {
|
|
||||||
log.Println("NewFunc", name, t.raw.Type, "hasFreeVars:", hasFreeVars)
|
|
||||||
}
|
|
||||||
fn := llvm.AddFunction(p.mod, name, t.ll)
|
|
||||||
ret := newFunction(fn, t, p, p.Prog, hasFreeVars)
|
|
||||||
p.fns[name] = ret
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p Package) rtFunc(fnName string) Expr {
|
func (p Package) rtFunc(fnName string) Expr {
|
||||||
fn := p.Prog.runtime().Scope().Lookup(fnName).(*types.Func)
|
fn := p.Prog.runtime().Scope().Lookup(fnName).(*types.Func)
|
||||||
name := FullName(fn.Pkg(), fnName)
|
name := FullName(fn.Pkg(), fnName)
|
||||||
@@ -368,6 +388,11 @@ func (p Package) rtFunc(fnName string) Expr {
|
|||||||
return p.NewFunc(name, sig, InGo).Expr
|
return p.NewFunc(name, sig, InGo).Expr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p Package) pyFunc(fullName string, sig *types.Signature) Expr {
|
||||||
|
p.Prog.NeedPyInit = true
|
||||||
|
return p.NewFunc(fullName, sig, InC).Expr
|
||||||
|
}
|
||||||
|
|
||||||
func (p Package) closureStub(b Builder, t *types.Struct, v Expr) Expr {
|
func (p Package) closureStub(b Builder, t *types.Struct, v Expr) Expr {
|
||||||
name := v.impl.Name()
|
name := v.impl.Name()
|
||||||
prog := b.Prog
|
prog := b.Prog
|
||||||
@@ -401,11 +426,6 @@ func (p Package) closureStub(b Builder, t *types.Struct, v Expr) Expr {
|
|||||||
return b.aggregateValue(prog.rawType(t), v.impl, nilVal)
|
return b.aggregateValue(prog.rawType(t), v.impl, nilVal)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FuncOf returns a function by name.
|
|
||||||
func (p Package) FuncOf(name string) Function {
|
|
||||||
return p.fns[name]
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
// String returns a string representation of the package.
|
// String returns a string representation of the package.
|
||||||
@@ -454,3 +474,131 @@ func (p *Package) WriteFile(file string) (err error) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
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))
|
||||||
|
p.pyImpTy = types.NewSignatureType(nil, nil, nil, params, results, false)
|
||||||
|
}
|
||||||
|
return p.pyImpTy
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
p.callNoArgs = types.NewSignatureType(nil, nil, nil, params, params, false)
|
||||||
|
}
|
||||||
|
return p.callNoArgs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Program) tyCallOneArg() *types.Signature {
|
||||||
|
if p.callOneArg == nil {
|
||||||
|
objPtr := p.PyObjectPtr().raw.Type
|
||||||
|
paramObjPtr := types.NewParam(token.NoPos, nil, "", objPtr)
|
||||||
|
params := types.NewTuple(paramObjPtr, paramObjPtr)
|
||||||
|
results := types.NewTuple(paramObjPtr)
|
||||||
|
p.callOneArg = types.NewSignatureType(nil, nil, nil, params, results, false)
|
||||||
|
}
|
||||||
|
return p.callOneArg
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Program) tyLoadPyModSyms() *types.Signature {
|
||||||
|
if p.loadPyModS == nil {
|
||||||
|
objPtr := p.PyObjectPtr().raw.Type
|
||||||
|
paramObjPtr := types.NewParam(token.NoPos, nil, "mod", objPtr)
|
||||||
|
params := types.NewTuple(paramObjPtr, VArg())
|
||||||
|
p.loadPyModS = types.NewSignatureType(nil, nil, nil, params, nil, false)
|
||||||
|
}
|
||||||
|
return p.loadPyModS
|
||||||
|
}
|
||||||
|
|
||||||
|
// PyInit initializes Python for a main package.
|
||||||
|
func (p Package) PyInit() bool {
|
||||||
|
if fn := p.FuncOf("main"); fn != nil {
|
||||||
|
b := fn.NewBuilder()
|
||||||
|
b.SetBlockEx(fn.Block(0), AtStart).CallPyInit()
|
||||||
|
b.Dispose()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPyModVar creates a new global variable for a Python module.
|
||||||
|
func (p Package) NewPyModVar(name string, doInit bool) Global {
|
||||||
|
if v, ok := p.pymods[name]; ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
prog := p.Prog
|
||||||
|
objPtr := prog.PyObjectPtrPtr().raw.Type
|
||||||
|
g := p.NewVar(name, objPtr, InC)
|
||||||
|
if doInit {
|
||||||
|
g.Init(prog.Null(g.Type))
|
||||||
|
g.impl.SetLinkage(llvm.LinkOnceAnyLinkage)
|
||||||
|
}
|
||||||
|
p.pymods[name] = g
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImportPyMod imports a Python module.
|
||||||
|
func (b Builder) ImportPyMod(path string) Expr {
|
||||||
|
pkg := b.Func.Pkg
|
||||||
|
fnImp := pkg.pyFunc("PyImport_ImportModule", b.Prog.tyImportPyModule())
|
||||||
|
return b.Call(fnImp, b.CStr(path))
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadPyModSyms loads python objects from specified module.
|
||||||
|
func (b Builder) LoadPyModSyms(modName string, objs ...PyObjRef) Expr {
|
||||||
|
pkg := b.Func.Pkg
|
||||||
|
fnLoad := pkg.pyFunc("llgoLoadPyModSyms", b.Prog.tyLoadPyModSyms())
|
||||||
|
modPtr := pkg.NewPyModVar(modName, false).Expr
|
||||||
|
mod := b.Load(modPtr)
|
||||||
|
args := make([]Expr, 1, len(objs)*2+2)
|
||||||
|
args[0] = mod
|
||||||
|
nbase := len(modName) + 1
|
||||||
|
for _, o := range objs {
|
||||||
|
fullName := o.impl.Name()
|
||||||
|
name := fullName[nbase:]
|
||||||
|
args = append(args, b.CStr(name))
|
||||||
|
args = append(args, o.Expr)
|
||||||
|
}
|
||||||
|
prog := b.Prog
|
||||||
|
args = append(args, prog.Null(prog.CStr()))
|
||||||
|
return b.Call(fnLoad, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b Builder) pyCall(fn Expr, args []Expr) (ret Expr) {
|
||||||
|
prog := b.Prog
|
||||||
|
pkg := b.Func.Pkg
|
||||||
|
fn = b.Load(fn)
|
||||||
|
sig := fn.raw.Type.(*types.Signature)
|
||||||
|
params := sig.Params()
|
||||||
|
n := params.Len()
|
||||||
|
switch n {
|
||||||
|
case 0:
|
||||||
|
call := pkg.pyFunc("PyObject_CallNoArgs", prog.tyCallNoArgs())
|
||||||
|
ret = b.Call(call, fn)
|
||||||
|
case 1:
|
||||||
|
call := pkg.pyFunc("PyObject_CallOneArg", prog.tyCallOneArg())
|
||||||
|
ret = b.Call(call, fn, args[0])
|
||||||
|
default:
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// CallPyInit calls Py_Initialize.
|
||||||
|
func (b Builder) CallPyInit() (ret Expr) {
|
||||||
|
fn := b.Func.Pkg.pyFunc("Py_Initialize", NoArgsNoRet)
|
||||||
|
return b.Call(fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
NoArgsNoRet = types.NewSignatureType(nil, nil, nil, nil, nil, false)
|
||||||
|
)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -25,6 +25,34 @@ import (
|
|||||||
"github.com/goplus/llvm"
|
"github.com/goplus/llvm"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestSetBlock(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r == nil {
|
||||||
|
t.Log("SetBlock: no error?")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
fn := &aFunction{}
|
||||||
|
b := &aBuilder{Func: fn}
|
||||||
|
b.SetBlock(&aBasicBlock{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetBlockEx(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r == nil {
|
||||||
|
t.Log("SetBlockEx: no error?")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
fn := &aFunction{}
|
||||||
|
b := &aBuilder{Func: fn}
|
||||||
|
b.SetBlockEx(&aBasicBlock{fn: fn}, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetPython(t *testing.T) {
|
||||||
|
prog := NewProgram(nil)
|
||||||
|
typ := types.NewPackage("foo", "foo")
|
||||||
|
prog.SetPython(typ)
|
||||||
|
}
|
||||||
|
|
||||||
func TestClosureCtx(t *testing.T) {
|
func TestClosureCtx(t *testing.T) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r == nil {
|
if r := recover(); r == nil {
|
||||||
@@ -106,10 +134,32 @@ func assertPkg(t *testing.T, p Package, expected string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPyFunc(t *testing.T) {
|
||||||
|
prog := NewProgram(nil)
|
||||||
|
py := types.NewPackage("foo", "foo")
|
||||||
|
o := types.NewTypeName(0, py, "Object", nil)
|
||||||
|
types.NewNamed(o, types.Typ[types.Int], nil)
|
||||||
|
py.Scope().Insert(o)
|
||||||
|
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 {
|
||||||
|
t.Fatal("NewPyFunc(a) failed")
|
||||||
|
}
|
||||||
|
foo := pkg.NewPyModVar("foo", false)
|
||||||
|
if pkg.NewPyModVar("foo", false) != foo {
|
||||||
|
t.Fatal("NewPyModVar(foo) failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestVar(t *testing.T) {
|
func TestVar(t *testing.T) {
|
||||||
prog := NewProgram(nil)
|
prog := NewProgram(nil)
|
||||||
pkg := prog.NewPackage("bar", "foo/bar")
|
pkg := prog.NewPackage("bar", "foo/bar")
|
||||||
a := pkg.NewVar("a", types.Typ[types.Int], InGo)
|
a := pkg.NewVar("a", types.Typ[types.Int], InGo)
|
||||||
|
if pkg.NewVar("a", types.Typ[types.Int], InGo) != a {
|
||||||
|
t.Fatal("NewVar(a) failed")
|
||||||
|
}
|
||||||
a.Init(prog.Val(100))
|
a.Init(prog.Val(100))
|
||||||
b := pkg.NewVar("b", types.Typ[types.Int], InGo)
|
b := pkg.NewVar("b", types.Typ[types.Int], InGo)
|
||||||
b.Init(a.Expr)
|
b.Init(a.Expr)
|
||||||
@@ -149,7 +199,7 @@ source_filename = "foo/bar"
|
|||||||
|
|
||||||
@a = external global {}
|
@a = external global {}
|
||||||
`)
|
`)
|
||||||
if prog.NeedRuntime() {
|
if prog.NeedRuntime {
|
||||||
t.Fatal("NeedRuntime?")
|
t.Fatal("NeedRuntime?")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"go/types"
|
"go/types"
|
||||||
"log"
|
"log"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/goplus/llvm"
|
"github.com/goplus/llvm"
|
||||||
)
|
)
|
||||||
@@ -57,18 +58,67 @@ type aBuilder struct {
|
|||||||
// Builder represents a builder for creating instructions in a function.
|
// Builder represents a builder for creating instructions in a function.
|
||||||
type Builder = *aBuilder
|
type Builder = *aBuilder
|
||||||
|
|
||||||
// SetBlock sets the current block to the specified basic block.
|
// Dispose disposes of the builder.
|
||||||
|
func (b Builder) Dispose() {
|
||||||
|
b.impl.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetBlock means SetBlockEx(blk, AtEnd).
|
||||||
func (b Builder) SetBlock(blk BasicBlock) Builder {
|
func (b Builder) SetBlock(blk BasicBlock) Builder {
|
||||||
if b.Func != blk.fn {
|
|
||||||
panic("mismatched function")
|
|
||||||
}
|
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Printf("Block _llgo_%v:\n", blk.idx)
|
log.Printf("Block _llgo_%v:\n", blk.idx)
|
||||||
}
|
}
|
||||||
b.impl.SetInsertPointAtEnd(blk.impl)
|
b.SetBlockEx(blk, AtEnd)
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type InsertPoint int
|
||||||
|
|
||||||
|
const (
|
||||||
|
AtEnd InsertPoint = iota
|
||||||
|
AtStart
|
||||||
|
AfterInit
|
||||||
|
)
|
||||||
|
|
||||||
|
// SetBlockEx sets blk as current basic block and pos as its insert point.
|
||||||
|
func (b Builder) SetBlockEx(blk BasicBlock, pos InsertPoint) Builder {
|
||||||
|
if b.Func != blk.fn {
|
||||||
|
panic("mismatched function")
|
||||||
|
}
|
||||||
|
switch pos {
|
||||||
|
case AtEnd:
|
||||||
|
b.impl.SetInsertPointAtEnd(blk.impl)
|
||||||
|
case AtStart:
|
||||||
|
b.impl.SetInsertPointBefore(blk.impl.FirstInstruction())
|
||||||
|
case AfterInit:
|
||||||
|
b.impl.SetInsertPointBefore(instrAfterInit(blk.impl))
|
||||||
|
default:
|
||||||
|
panic("SetBlockEx: invalid pos")
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func instrAfterInit(blk llvm.BasicBlock) llvm.Value {
|
||||||
|
instr := blk.FirstInstruction()
|
||||||
|
for {
|
||||||
|
instr = llvm.NextInstruction(instr)
|
||||||
|
if notInit(instr) {
|
||||||
|
return instr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func notInit(instr llvm.Value) bool {
|
||||||
|
switch op := instr.InstructionOpcode(); op {
|
||||||
|
case llvm.Call:
|
||||||
|
if n := instr.OperandsCount(); n == 1 {
|
||||||
|
fn := instr.Operand(0)
|
||||||
|
return !strings.HasSuffix(fn.Name(), ".init")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// Panic emits a panic instruction.
|
// Panic emits a panic instruction.
|
||||||
func (b Builder) Panic(v Expr) {
|
func (b Builder) Panic(v Expr) {
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ const (
|
|||||||
vkFuncDecl
|
vkFuncDecl
|
||||||
vkFuncPtr
|
vkFuncPtr
|
||||||
vkClosure
|
vkClosure
|
||||||
|
vkPyFuncRef
|
||||||
vkTuple
|
vkTuple
|
||||||
vkPhisExpr = -1
|
vkPhisExpr = -1
|
||||||
)
|
)
|
||||||
@@ -188,6 +189,10 @@ func (p Program) tyInt64() llvm.Type {
|
|||||||
return p.int64Type
|
return p.int64Type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p Program) toTuple(typ *types.Tuple) Type {
|
||||||
|
return &aType{p.toLLVMTuple(typ), rawType{typ}, vkTuple}
|
||||||
|
}
|
||||||
|
|
||||||
func (p Program) toType(raw types.Type) Type {
|
func (p Program) toType(raw types.Type) Type {
|
||||||
typ := rawType{raw}
|
typ := rawType{raw}
|
||||||
switch t := raw.(type) {
|
switch t := raw.(type) {
|
||||||
@@ -251,7 +256,11 @@ func (p Program) toType(raw types.Type) Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) toLLVMNamedStruct(name string, raw *types.Struct) llvm.Type {
|
func (p Program) toLLVMNamedStruct(name string, raw *types.Struct) llvm.Type {
|
||||||
|
if typ, ok := p.named[name]; ok {
|
||||||
|
return typ
|
||||||
|
}
|
||||||
t := p.ctx.StructCreateNamed(name)
|
t := p.ctx.StructCreateNamed(name)
|
||||||
|
p.named[name] = t
|
||||||
fields := p.toLLVMFields(raw)
|
fields := p.toLLVMFields(raw)
|
||||||
t.StructSetBody(fields, false)
|
t.StructSetBody(fields, false)
|
||||||
return t
|
return t
|
||||||
|
|||||||
@@ -27,11 +27,13 @@ import (
|
|||||||
|
|
||||||
type goTypes struct {
|
type goTypes struct {
|
||||||
typs map[unsafe.Pointer]unsafe.Pointer
|
typs map[unsafe.Pointer]unsafe.Pointer
|
||||||
|
named map[string]*types.Named
|
||||||
}
|
}
|
||||||
|
|
||||||
func newGoTypes() goTypes {
|
func newGoTypes() goTypes {
|
||||||
typs := make(map[unsafe.Pointer]unsafe.Pointer)
|
typs := make(map[unsafe.Pointer]unsafe.Pointer)
|
||||||
return goTypes{typs}
|
named := make(map[string]*types.Named)
|
||||||
|
return goTypes{typs, named}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Background int
|
type Background int
|
||||||
@@ -40,6 +42,7 @@ const (
|
|||||||
inUnknown Background = iota
|
inUnknown Background = iota
|
||||||
InGo
|
InGo
|
||||||
InC
|
InC
|
||||||
|
InPython
|
||||||
)
|
)
|
||||||
|
|
||||||
// Type convert a Go/C type into raw type.
|
// Type convert a Go/C type into raw type.
|
||||||
@@ -54,8 +57,11 @@ func (p Program) Type(typ types.Type, bg Background) Type {
|
|||||||
|
|
||||||
// FuncDecl converts a Go/C function declaration into raw type.
|
// FuncDecl converts a Go/C function declaration into raw type.
|
||||||
func (p Program) FuncDecl(sig *types.Signature, bg Background) Type {
|
func (p Program) FuncDecl(sig *types.Signature, bg Background) Type {
|
||||||
|
recv := sig.Recv()
|
||||||
if bg == InGo {
|
if bg == InGo {
|
||||||
sig = p.gocvt.cvtFunc(sig, sig.Recv())
|
sig = p.gocvt.cvtFunc(sig, recv)
|
||||||
|
} else if recv != nil { // even in C, we need to add ctx for method
|
||||||
|
sig = FuncAddCtx(recv, sig)
|
||||||
}
|
}
|
||||||
return &aType{p.toLLVMFunc(sig), rawType{sig}, vkFuncDecl}
|
return &aType{p.toLLVMFunc(sig), rawType{sig}, vkFuncDecl}
|
||||||
}
|
}
|
||||||
@@ -115,10 +121,16 @@ func (p goTypes) cvtNamed(t *types.Named) (raw *types.Named, cvt bool) {
|
|||||||
defer func() {
|
defer func() {
|
||||||
p.typs[unsafe.Pointer(t)] = unsafe.Pointer(raw)
|
p.typs[unsafe.Pointer(t)] = unsafe.Pointer(raw)
|
||||||
}()
|
}()
|
||||||
|
id := t.String()
|
||||||
|
if named, ok := p.named[id]; ok {
|
||||||
|
return named, false
|
||||||
|
}
|
||||||
|
named := types.NewNamed(t.Obj(), types.Typ[types.Int], nil)
|
||||||
|
p.named[id] = named
|
||||||
|
defer delete(p.named, id)
|
||||||
if tund, cvt := p.cvtType(t.Underlying()); cvt {
|
if tund, cvt := p.cvtType(t.Underlying()); cvt {
|
||||||
old := t.Obj()
|
named.SetUnderlying(tund)
|
||||||
obj := types.NewTypeName(old.Pos(), old.Pkg(), old.Name(), nil)
|
return named, true
|
||||||
return types.NewNamed(obj, tund, nil), true
|
|
||||||
}
|
}
|
||||||
return t, false
|
return t, false
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
@@ -8,7 +8,7 @@ source_filename = "github.com/goplus/llgo/x/sqlite"
|
|||||||
define ptr @"(*github.com/goplus/llgo/x/sqlite.Errno).Errstr"(ptr %0) {
|
define ptr @"(*github.com/goplus/llgo/x/sqlite.Errno).Errstr"(ptr %0) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%1 = load i32, ptr %0, align 4
|
%1 = load i32, ptr %0, align 4
|
||||||
%2 = call ptr @sqlite3_errstr()
|
%2 = call ptr @sqlite3_errstr(i32 %1)
|
||||||
ret ptr %2
|
ret ptr %2
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,8 +35,8 @@ _llgo_0:
|
|||||||
define { ptr, i32 } @"(*github.com/goplus/llgo/x/sqlite.Sqlite3).Prepare"(ptr %0, %"github.com/goplus/llgo/internal/runtime.String" %1, ptr %2) {
|
define { ptr, i32 } @"(*github.com/goplus/llgo/x/sqlite.Sqlite3).Prepare"(ptr %0, %"github.com/goplus/llgo/internal/runtime.String" %1, ptr %2) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 8)
|
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 8)
|
||||||
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.StringData"(%"github.com/goplus/llgo/internal/runtime.String" %1)
|
%4 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %1, 0
|
||||||
%5 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %1)
|
%5 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %1, 1
|
||||||
%6 = trunc i64 %5 to i32
|
%6 = trunc i64 %5 to i32
|
||||||
%7 = call i32 @sqlite3_prepare(ptr %0, ptr %4, i32 %6, ptr %3, ptr %2)
|
%7 = call i32 @sqlite3_prepare(ptr %0, ptr %4, i32 %6, ptr %3, ptr %2)
|
||||||
%8 = load ptr, ptr %3, align 8
|
%8 = load ptr, ptr %3, align 8
|
||||||
@@ -48,8 +48,8 @@ _llgo_0:
|
|||||||
define { ptr, i32 } @"(*github.com/goplus/llgo/x/sqlite.Sqlite3).PrepareV2"(ptr %0, %"github.com/goplus/llgo/internal/runtime.String" %1, ptr %2) {
|
define { ptr, i32 } @"(*github.com/goplus/llgo/x/sqlite.Sqlite3).PrepareV2"(ptr %0, %"github.com/goplus/llgo/internal/runtime.String" %1, ptr %2) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 8)
|
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 8)
|
||||||
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.StringData"(%"github.com/goplus/llgo/internal/runtime.String" %1)
|
%4 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %1, 0
|
||||||
%5 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %1)
|
%5 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %1, 1
|
||||||
%6 = trunc i64 %5 to i32
|
%6 = trunc i64 %5 to i32
|
||||||
%7 = call i32 @sqlite3_prepare_v2(ptr %0, ptr %4, i32 %6, ptr %3, ptr %2)
|
%7 = call i32 @sqlite3_prepare_v2(ptr %0, ptr %4, i32 %6, ptr %3, ptr %2)
|
||||||
%8 = load ptr, ptr %3, align 8
|
%8 = load ptr, ptr %3, align 8
|
||||||
@@ -61,8 +61,8 @@ _llgo_0:
|
|||||||
define { ptr, i32 } @"(*github.com/goplus/llgo/x/sqlite.Sqlite3).PrepareV3"(ptr %0, %"github.com/goplus/llgo/internal/runtime.String" %1, i32 %2, ptr %3) {
|
define { ptr, i32 } @"(*github.com/goplus/llgo/x/sqlite.Sqlite3).PrepareV3"(ptr %0, %"github.com/goplus/llgo/internal/runtime.String" %1, i32 %2, ptr %3) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 8)
|
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 8)
|
||||||
%5 = call ptr @"github.com/goplus/llgo/internal/runtime.StringData"(%"github.com/goplus/llgo/internal/runtime.String" %1)
|
%5 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %1, 0
|
||||||
%6 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %1)
|
%6 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %1, 1
|
||||||
%7 = trunc i64 %6 to i32
|
%7 = trunc i64 %6 to i32
|
||||||
%8 = call i32 @sqlite3_prepare_v3(ptr %0, ptr %5, i32 %7, i32 %2, ptr %4, ptr %3)
|
%8 = call i32 @sqlite3_prepare_v3(ptr %0, ptr %5, i32 %7, i32 %2, ptr %4, ptr %3)
|
||||||
%9 = load ptr, ptr %4, align 8
|
%9 = load ptr, ptr %4, align 8
|
||||||
@@ -84,7 +84,7 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
declare ptr @sqlite3_errstr()
|
declare ptr @sqlite3_errstr(i32)
|
||||||
|
|
||||||
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
|
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
|
||||||
|
|
||||||
@@ -92,12 +92,8 @@ declare i32 @sqlite3_open(ptr, ptr)
|
|||||||
|
|
||||||
declare i32 @sqlite3_open_v2(ptr, ptr, i32, ptr)
|
declare i32 @sqlite3_open_v2(ptr, ptr, i32, ptr)
|
||||||
|
|
||||||
declare ptr @"github.com/goplus/llgo/internal/runtime.StringData"(%"github.com/goplus/llgo/internal/runtime.String")
|
declare i32 @sqlite3_prepare(ptr, ptr, i32, ptr, ptr)
|
||||||
|
|
||||||
declare i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String")
|
declare i32 @sqlite3_prepare_v2(ptr, ptr, i32, ptr, ptr)
|
||||||
|
|
||||||
declare i32 @sqlite3_prepare(ptr, i32, ptr, ptr)
|
declare i32 @sqlite3_prepare_v3(ptr, ptr, i32, i32, ptr, ptr)
|
||||||
|
|
||||||
declare i32 @sqlite3_prepare_v2(ptr, i32, ptr, ptr)
|
|
||||||
|
|
||||||
declare i32 @sqlite3_prepare_v3(ptr, i32, i32, ptr, ptr)
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/goplus/llgo/x/clang/ast"
|
"github.com/goplus/llgo/xtool/clang/ast"
|
||||||
jsoniter "github.com/json-iterator/go"
|
jsoniter "github.com/json-iterator/go"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/goplus/llgo/x/clang/pathutil"
|
"github.com/goplus/llgo/xtool/clang/pathutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -26,9 +26,9 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/goplus/gogen"
|
"github.com/goplus/gogen"
|
||||||
"github.com/goplus/llgo/x/clang/types/scanner"
|
"github.com/goplus/llgo/xtool/clang/types/scanner"
|
||||||
|
|
||||||
ctypes "github.com/goplus/llgo/x/clang/types"
|
ctypes "github.com/goplus/llgo/xtool/clang/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
2
x/env/llvm/llvm.go → xtool/env/llvm/llvm.go
vendored
2
x/env/llvm/llvm.go → xtool/env/llvm/llvm.go
vendored
@@ -19,7 +19,7 @@ package llvm
|
|||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/goplus/llgo/x/nm"
|
"github.com/goplus/llgo/xtool/nm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Env struct {
|
type Env struct {
|
||||||
Reference in New Issue
Block a user