Merge pull request #217 from xushiwei/q

abi.Name; runtime: MakeAnyInt => MakeAnyIntptr; llgo/ssa: AllocU; bui…
This commit is contained in:
xushiwei
2024-05-20 10:25:56 +08:00
committed by GitHub
21 changed files with 497 additions and 110 deletions

View File

@@ -152,7 +152,7 @@ See [github.com/goplus/llgo/py](https://pkg.go.dev/github.com/goplus/llgo/py) fo
LLGo can easily import any libraries from the C ecosystem. Currently, this import process is still manual, but in the future, it will be automated similar to Python library imports.
The currently imported libraries include:
The currently supported libraries include:
* [llama2.c](https://pkg.go.dev/github.com/goplus/llgo/c/llama2)
* [cjson](https://pkg.go.dev/github.com/goplus/llgo/c/cjson)

View File

@@ -0,0 +1,18 @@
package main
import (
"fmt"
"github.com/goplus/llvm"
)
func main() {
llvm.InitializeAllTargetInfos()
llvm.InitializeAllTargets()
llvm.InitializeAllTargetMCs()
llvm.InitializeNativeTarget()
fmt.Println("targets:")
for it := llvm.FirstTarget(); it.C != nil; it = it.NextTarget() {
fmt.Printf("- %s: %s\n", it.Name(), it.Description())
}
}

View File

@@ -99,11 +99,11 @@ _llgo_0:
call void @main.prinfsub(double 1.001000e+02)
call void @main.printnl()
%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.MakeAnyIntptr"(ptr %3, i64 1315859240)
call void @main.printany(%"github.com/goplus/llgo/internal/runtime.iface" %4)
call void @main.printnl()
%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.MakeAnyIntptr"(ptr %5, i64 4746175415993761792)
call void @main.printany(%"github.com/goplus/llgo/internal/runtime.iface" %6)
call void @main.printnl()
br i1 true, label %_llgo_3, label %_llgo_2
@@ -116,7 +116,7 @@ _llgo_1: ; preds = %_llgo_3
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)
%13 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(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)
@@ -130,74 +130,74 @@ _llgo_2: ; preds = %_llgo_3, %_llgo_1,
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)
%21 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(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)
%24 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(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)
%29 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(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)
%32 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(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)
%35 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(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)
%38 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(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)
%41 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(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)
%44 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(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)
%47 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(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)
%50 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(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)
%53 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(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)
%56 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(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)
%59 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(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)
%62 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(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)
%65 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(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)
%68 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(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)
%71 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(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)
@@ -801,9 +801,9 @@ declare void @"github.com/goplus/llgo/internal/runtime.init"()
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.Basic"(i64)
declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr, i64)
declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr, i64)
declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64)
declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String")

View File

@@ -31,15 +31,15 @@ _llgo_0:
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 48)
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i64 0
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2)
%5 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %4, i64 1)
%5 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %4, i64 1)
store %"github.com/goplus/llgo/internal/runtime.iface" %5, ptr %3, align 8
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i64 1
%7 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2)
%8 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %7, i64 2)
%8 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %7, i64 2)
store %"github.com/goplus/llgo/internal/runtime.iface" %8, ptr %6, align 8
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i64 2
%10 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2)
%11 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %10, i64 3)
%11 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %10, i64 3)
store %"github.com/goplus/llgo/internal/runtime.iface" %11, ptr %9, align 8
%12 = 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)
call void @main.test(%"github.com/goplus/llgo/internal/runtime.Slice" %12)
@@ -76,9 +76,9 @@ declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64)
declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr, i64)
declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr, i64)
declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64)
declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr, i64, i64, i64, i64, i64)

View File

@@ -36,7 +36,7 @@ _llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2)
%3 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %2, i64 100)
%3 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %2, i64 100)
%4 = call i64 @main.incVal(%"github.com/goplus/llgo/internal/runtime.iface" %3)
%5 = call i32 (ptr, ...) @printf(ptr @0, i64 %4)
ret i32 0
@@ -48,6 +48,6 @@ declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64)
declare void @"github.com/goplus/llgo/internal/runtime.init"()
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.MakeAnyIntptr"(ptr, i64)
declare i32 @printf(ptr, ...)

View File

@@ -288,7 +288,7 @@ _llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %121)
%122 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 16)
%123 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2)
%124 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %123, i64 100)
%124 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %123, i64 100)
store %"github.com/goplus/llgo/internal/runtime.iface" %124, ptr %122, align 8
%125 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %122, align 8
%126 = ptrtoint ptr %122 to i64
@@ -392,9 +392,9 @@ declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/ll
declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.SliceAppend"(%"github.com/goplus/llgo/internal/runtime.Slice", ptr, i64, i64)
declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64)
declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr, i64)
declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr, i64)
declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64)
declare void @"github.com/goplus/llgo/internal/runtime.PrintBool"(i1)

View File

@@ -32,6 +32,7 @@ import (
"github.com/goplus/gogen/packages"
"github.com/goplus/llgo/cl"
"github.com/goplus/llgo/internal/llgen"
"github.com/goplus/llgo/ssa/ssatest"
"golang.org/x/tools/go/ssa"
"golang.org/x/tools/go/ssa/ssautil"
@@ -139,21 +140,7 @@ func TestCompileEx(t *testing.T, src any, fname, expected string) {
t.Fatal("BuildPackage failed:", err)
}
foo.WriteTo(os.Stderr)
prog := llssa.NewProgram(nil)
prog.SetRuntime(func() *types.Package {
rt, err := imp.Import(llssa.PkgRuntime)
if err != nil {
t.Fatal("load runtime failed:", err)
}
return rt
})
prog.SetPython(func() *types.Package {
rt, err := imp.Import(llssa.PkgPython)
if err != nil {
t.Fatal("load python failed:", err)
}
return rt
})
prog := ssatest.NewProgramEx(t, nil, imp)
ret, err := cl.NewPackage(prog, foo, files)
if err != nil {

2
go.mod
View File

@@ -1,6 +1,6 @@
module github.com/goplus/llgo
go 1.18
go 1.20
require (
github.com/aykevl/go-wasm v0.0.1

Binary file not shown.

View File

@@ -213,36 +213,6 @@ type StructType struct {
Fields []StructField
}
// Name is an encoded type Name with optional extra data.
//
// The first byte is a bit field containing:
//
// 1<<0 the name is exported
// 1<<1 tag data follows the name
// 1<<2 pkgPath nameOff follows the name and tag
// 1<<3 the name is of an embedded (a.k.a. anonymous) field
//
// Following that, there is a varint-encoded length of the name,
// followed by the name itself.
//
// If tag data is present, it also has a varint-encoded length
// followed by the tag itself.
//
// If the import path follows, then 4 bytes at the end of
// the data form a nameOff. The import path is only set for concrete
// methods that are defined in a different package than their type.
//
// If a name starts with "*", then the exported bit represents
// whether the pointed to type is exported.
//
// Note: this encoding must match here and in:
// cmd/compile/internal/reflectdata/reflect.go
// cmd/link/internal/ld/decodesym.go
type Name struct {
Bytes *byte
}
type InterfaceType struct {
Type
PkgPath Name // import path
@@ -330,3 +300,168 @@ func (t *Type) InterfaceType() *InterfaceType {
}
// -----------------------------------------------------------------------------
// addChecked returns p+x.
//
// The whySafe string is ignored, so that the function still inlines
// as efficiently as p+x, but all call sites should use the string to
// record why the addition is safe, which is to say why the addition
// does not cause x to advance to the very end of p's allocation
// and therefore point incorrectly at the next block in memory.
func addChecked(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
_ = whySafe
return unsafe.Pointer(uintptr(p) + x)
}
// Name is an encoded type Name with optional extra data.
//
// The first byte is a bit field containing:
//
// 1<<0 the name is exported
// 1<<1 tag data follows the name
// 1<<2 pkgPath nameOff follows the name and tag
// 1<<3 the name is of an embedded (a.k.a. anonymous) field
//
// Following that, there is a varint-encoded length of the name,
// followed by the name itself.
//
// If tag data is present, it also has a varint-encoded length
// followed by the tag itself.
//
// If the import path follows, then 4 bytes at the end of
// the data form a nameOff. The import path is only set for concrete
// methods that are defined in a different package than their type.
//
// If a name starts with "*", then the exported bit represents
// whether the pointed to type is exported.
//
// Note: this encoding must match here and in:
// cmd/compile/internal/reflectdata/reflect.go
// cmd/link/internal/ld/decodesym.go
type Name struct {
Bytes *byte
}
// DataChecked does pointer arithmetic on n's Bytes, and that arithmetic is asserted to
// be safe for the reason in whySafe (which can appear in a backtrace, etc.)
func (n Name) DataChecked(off int, whySafe string) *byte {
return (*byte)(addChecked(unsafe.Pointer(n.Bytes), uintptr(off), whySafe))
}
// Data does pointer arithmetic on n's Bytes, and that arithmetic is asserted to
// be safe because the runtime made the call (other packages use DataChecked)
func (n Name) Data(off int) *byte {
return (*byte)(addChecked(unsafe.Pointer(n.Bytes), uintptr(off), "the runtime doesn't need to give you a reason"))
}
// IsExported returns "is n exported?"
func (n Name) IsExported() bool {
return (*n.Bytes)&(1<<0) != 0
}
// HasTag returns true iff there is tag data following this name
func (n Name) HasTag() bool {
return (*n.Bytes)&(1<<1) != 0
}
// IsEmbedded returns true iff n is embedded (an anonymous field).
func (n Name) IsEmbedded() bool {
return (*n.Bytes)&(1<<3) != 0
}
// ReadVarint parses a varint as encoded by encoding/binary.
// It returns the number of encoded bytes and the encoded value.
func (n Name) ReadVarint(off int) (int, int) {
v := 0
for i := 0; ; i++ {
x := *n.DataChecked(off+i, "read varint")
v += int(x&0x7f) << (7 * i)
if x&0x80 == 0 {
return i + 1, v
}
}
}
// IsBlank indicates whether n is "_".
func (n Name) IsBlank() bool {
if n.Bytes == nil {
return false
}
_, l := n.ReadVarint(1)
return l == 1 && *n.Data(2) == '_'
}
// writeVarint writes n to buf in varint form. Returns the
// number of bytes written. n must be nonnegative.
// Writes at most 10 bytes.
func writeVarint(buf []byte, n int) int {
for i := 0; ; i++ {
b := byte(n & 0x7f)
n >>= 7
if n == 0 {
buf[i] = b
return i + 1
}
buf[i] = b | 0x80
}
}
// Name returns the tag string for n, or empty if there is none.
func (n Name) Name() string {
if n.Bytes == nil {
return ""
}
i, l := n.ReadVarint(1)
return unsafe.String(n.DataChecked(1+i, "non-empty string"), l)
}
// Tag returns the tag string for n, or empty if there is none.
func (n Name) Tag() string {
if !n.HasTag() {
return ""
}
i, l := n.ReadVarint(1)
i2, l2 := n.ReadVarint(1 + i + l)
return unsafe.String(n.DataChecked(1+i+l+i2, "non-empty string"), l2)
}
func NewName(n, tag string, exported, embedded bool) Name {
if len(n) >= 1<<29 {
panic("abi.NewName: name too long: " + n[:1024] + "...")
}
if len(tag) >= 1<<29 {
panic("abi.NewName: tag too long: " + tag[:1024] + "...")
}
var nameLen [10]byte
var tagLen [10]byte
nameLenLen := writeVarint(nameLen[:], len(n))
tagLenLen := writeVarint(tagLen[:], len(tag))
var bits byte
l := 1 + nameLenLen + len(n)
if exported {
bits |= 1 << 0
}
if len(tag) > 0 {
l += tagLenLen + len(tag)
bits |= 1 << 1
}
if embedded {
bits |= 1 << 3
}
b := make([]byte, l)
b[0] = bits
copy(b[1:], nameLen[:nameLenLen])
copy(b[1+nameLenLen:], n)
if len(tag) > 0 {
tb := b[1+nameLenLen+len(n):]
copy(tb, tagLen[:tagLenLen])
copy(tb[tagLenLen:], tag)
}
return Name{Bytes: &b[0]}
}
// -----------------------------------------------------------------------------

Binary file not shown.

View File

@@ -34,7 +34,7 @@ var (
type Interface = iface
func MakeAnyInt(typ *Type, data uintptr) Interface {
func MakeAnyIntptr(typ *Type, data uintptr) Interface {
tab := &itab{inter: TyAny, _type: typ, hash: 0, fun: [1]uintptr{0}}
return Interface{
tab: tab, data: unsafe.Pointer(data),

View File

@@ -40,6 +40,7 @@ func EmptyString() String {
return String{nil, 0}
}
// TODO(xsw): unsafe.String
// NewString creates a new string.
func NewString(data unsafe.Pointer, len int) String {
return String{data, len}

73
ssa/_abi/abi.go Normal file
View File

@@ -0,0 +1,73 @@
/*
* 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 abi
import (
"crypto/sha256"
"encoding/base64"
"fmt"
"go/types"
"hash"
)
// Builder is a helper for constructing ABI types.
type Builder struct {
h hash.Hash
buf []byte
}
// New creates a new ABI type Builder.
func New() *Builder {
h := sha256.New()
buf := make([]byte, sha256.Size)
return &Builder{h, buf}
}
// TypeName returns the ABI type name for the specified type.
func (b *Builder) TypeName(t types.Type) string {
switch t := t.(type) {
case *types.Basic:
return t.Name()
case *types.Pointer:
return "*" + b.TypeName(t.Elem())
case *types.Struct:
return b.StructName(t)
}
panic("todo")
}
// StructName returns the ABI type name for the specified struct type.
func (b *Builder) StructName(t *types.Struct) string {
hash := b.structHash(t)
return "struct$" + base64.RawURLEncoding.EncodeToString(hash)
}
func (b *Builder) structHash(t *types.Struct) []byte {
h := b.h
h.Reset()
n := t.NumFields()
fmt.Fprintln(h, "struct", n)
for i := 0; i < n; i++ {
f := t.Field(i)
name := f.Name()
if f.Embedded() {
name = "-"
}
fmt.Fprintln(h, name, b.TypeName(f.Type()))
}
return h.Sum(b.buf[:0])
}

View File

@@ -17,9 +17,12 @@
package ssa_test
import (
"go/types"
"testing"
"github.com/goplus/llgo/cl/cltest"
"github.com/goplus/llgo/ssa"
"github.com/goplus/llgo/ssa/ssatest"
)
func TestFromTestpy(t *testing.T) {
@@ -36,9 +39,46 @@ func TestFromTestdata(t *testing.T) {
func TestRuntime(t *testing.T) {
cltest.Pkg(t, "github.com/goplus/llgo/internal/runtime", "../internal/runtime/llgo_autogen.ll")
}
func TestAbi(t *testing.T) {
cltest.Pkg(t, "github.com/goplus/llgo/internal/abi", "../internal/abi/llgo_autogen.ll")
}
func TestMakeInterface(t *testing.T) {
prog := ssatest.NewProgram(t, &ssa.Target{GOARCH: "x86"})
pkg := prog.NewPackage("foo", "foo")
fn := pkg.NewFunc("main", types.NewSignatureType(nil, nil, nil, nil, nil, false), ssa.InC)
b := fn.MakeBody(1)
b.MakeInterface(prog.Any(), prog.IntVal(100, prog.Int64()))
b.MakeInterface(prog.Any(), prog.FloatVal(100, prog.Float64()))
b.Return()
ssatest.Assert(t, pkg, `; ModuleID = 'foo'
source_filename = "foo"
%"github.com/goplus/llgo/internal/runtime.iface" = type { ptr, ptr }
define void @main() {
_llgo_0:
%0 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8)
store i64 100, ptr %0, align 4
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 6)
%2 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAny"(ptr %1, ptr %0)
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8)
store double 1.000000e+02, ptr %3, align 8
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 14)
%5 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAny"(ptr %4, ptr %3)
ret void
}
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64)
declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAny"(ptr, ptr)
declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64)
`)
}
/*
func TestCallback(t *testing.T) {
ctx := llvm.NewContext()

View File

@@ -665,7 +665,18 @@ func (b Builder) Alloc(elem Type, heap bool) (ret Expr) {
return
}
// Alloca allocates space for n bytes.
// AllocU allocates uninitialized space for n*sizeof(elem) bytes.
func (b Builder) AllocU(elem Type, n ...int64) (ret Expr) {
if debugInstr {
log.Printf("AllocU %v, %v\n", elem.raw.Type, n)
}
size := b.SizeOf(elem, n...)
ret = b.InlineCall(b.Pkg.rtFunc("AllocU"), size)
ret.Type = b.Prog.Pointer(elem)
return
}
// Alloca allocates uninitialized space for n bytes.
func (b Builder) Alloca(n Expr) (ret Expr) {
if debugInstr {
log.Printf("Alloca %v\n", n.impl)
@@ -984,9 +995,10 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) {
for i, arg := range args {
if ln && i > 0 {
b.InlineCall(b.Pkg.rtFunc("PrintString"), b.Str(" "))
// TODO(visualfc): maybe use PrintCStr is more efficient
}
var fn string
var typ Type
var typ Type // TODO(visualfc): typ uninitialized in some cases
switch arg.kind {
case vkBool:
fn = "PrintBool"
@@ -1002,6 +1014,8 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) {
case vkSlice:
fn = "PrintSlice"
case vkPtr, vkFuncPtr, vkFuncDecl, vkClosure, vkPyVarRef, vkPyFuncRef:
// TODO(visualfc): vkClosure is not a pointer
// TODO(visualfc): vkPyVarRef, vkPyFuncRef is pointer of pointer
fn = "PrintPointer"
typ = b.Prog.VoidPtr()
case vkString:
@@ -1037,8 +1051,11 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) {
}
}
}
case "String": // unsafe.String
// TODO(xsw): make this a builtin
return b.InlineCall(b.Pkg.rtFunc("NewString"), args[0], args[1])
}
panic("todo")
panic("todo: " + fn)
}
// -----------------------------------------------------------------------------

View File

@@ -27,19 +27,29 @@ import (
// -----------------------------------------------------------------------------
// AbiBasic returns the abi type of the specified basic kind.
func (b Builder) AbiBasic(kind types.BasicKind) Expr {
// abiBasic returns the abi type of the specified basic kind.
func (b Builder) abiBasic(kind types.BasicKind) Expr {
return b.InlineCall(b.Pkg.rtFunc("Basic"), b.Prog.Val(int(kind)))
}
/*
// AbiStruct returns the abi type of the specified struct type.
func (b Builder) AbiStruct(t *types.Struct) Expr {
panic("todo")
// return b.InlineCall(b.Pkg.rtFunc("Struct"), b.Prog.Val(t.NumFields()))
// abiStruct returns the abi type of the specified struct type.
func (b Builder) abiStruct(t *types.Struct) Expr {
// name := "__llgo_" + b.Prog.abi.StructName(t)
}
*/
// AbiType returns the abi type of the specified type.
func (b Builder) AbiType(t Type) Expr {
switch tx := t.raw.Type.(type) {
case *types.Basic:
return b.abiBasic(tx.Kind())
//case *types.Struct:
// return b.abiStruct(tx)
}
panic("todo")
}
// -----------------------------------------------------------------------------
// MakeInterface constructs an instance of an interface type from a
@@ -57,37 +67,66 @@ func (b Builder) AbiStruct(t *types.Struct) Expr {
// t1 = make interface{} <- int (42:int)
// t2 = make Stringer <- t0
func (b Builder) MakeInterface(tinter Type, x Expr) (ret Expr) {
raw := tinter.raw.Type
rawIntf := tinter.raw.Type.Underlying().(*types.Interface)
if debugInstr {
log.Printf("MakeInterface %v, %v\n", raw, x.impl)
log.Printf("MakeInterface %v, %v\n", rawIntf, x.impl)
}
prog := b.Prog
pkg := b.Pkg
switch tx := x.raw.Type.Underlying().(type) {
typ := x.Type
switch tx := typ.raw.Type.Underlying().(type) {
case *types.Basic:
kind := tx.Kind()
switch {
case kind >= types.Bool && kind <= types.Uintptr:
t := b.AbiBasic(kind)
tptr := prog.Uintptr()
vptr := Expr{llvm.CreateIntCast(b.impl, x.impl, tptr.ll), tptr}
return Expr{b.InlineCall(pkg.rtFunc("MakeAnyInt"), t, vptr).impl, tinter}
if prog.is32Bits && (kind == types.Int64 || kind == types.Uint64) {
return b.makeIntfAlloc(tinter, rawIntf, typ, x)
}
return b.makeIntfByIntptr(tinter, rawIntf, typ, x.impl)
case kind == types.Float32:
t := b.AbiBasic(kind)
tptr := prog.Uintptr()
i32 := llvm.CreateBitCast(b.impl, x.impl, prog.tyInt32()) // TODO(xsw): more effective
vptr := Expr{llvm.CreateIntCast(b.impl, i32, tptr.ll), tptr}
return Expr{b.InlineCall(pkg.rtFunc("MakeAnyInt"), t, vptr).impl, tinter}
i32 := llvm.CreateBitCast(b.impl, x.impl, prog.tyInt32())
return b.makeIntfByIntptr(tinter, rawIntf, typ, i32)
case kind == types.Float64:
t := b.AbiBasic(kind)
tptr := prog.Uintptr()
vptr := Expr{llvm.CreateBitCast(b.impl, x.impl, tptr.ll), tptr}
return Expr{b.InlineCall(pkg.rtFunc("MakeAnyInt"), t, vptr).impl, tinter}
if prog.is32Bits {
return b.makeIntfAlloc(tinter, rawIntf, typ, x)
}
i64 := llvm.CreateBitCast(b.impl, x.impl, prog.tyInt64())
return b.makeIntfByIntptr(tinter, rawIntf, typ, i64)
case kind == types.String:
return Expr{b.InlineCall(pkg.rtFunc("MakeAnyString"), x).impl, tinter}
return Expr{b.InlineCall(b.Pkg.rtFunc("MakeAnyString"), x).impl, tinter}
}
// case *types.Struct:
// t := b.AbiStruct(tx)
/* case *types.Struct:
size := int(prog.SizeOf(typ))
if size > prog.PointerSize() {
return b.makeIntfAlloc(tinter, rawIntf, typ, x)
}
tv := prog.ctx.IntType(size * 8)
iv := llvm.CreateBitCast(b.impl, x.impl, tv)
return b.makeIntfByIntptr(tinter, rawIntf, typ, iv) */
}
panic("todo")
}
func (b Builder) makeIntfAlloc(tinter Type, rawIntf *types.Interface, typ Type, x Expr) (ret Expr) {
vptr := b.AllocU(typ)
b.Store(vptr, x)
return b.makeIntfByPtr(tinter, rawIntf, typ, vptr)
}
func (b Builder) makeIntfByPtr(tinter Type, rawIntf *types.Interface, typ Type, vptr Expr) (ret Expr) {
if rawIntf.Empty() {
ret = b.InlineCall(b.Pkg.rtFunc("MakeAny"), b.AbiType(typ), vptr)
ret.Type = tinter
return
}
panic("todo")
}
func (b Builder) makeIntfByIntptr(tinter Type, rawIntf *types.Interface, typ Type, x llvm.Value) (ret Expr) {
if rawIntf.Empty() {
tptr := b.Prog.Uintptr()
x = llvm.CreateIntCast(b.impl, x, tptr.ll)
impl := b.InlineCall(b.Pkg.rtFunc("MakeAnyIntptr"), b.AbiType(typ), Expr{x, tptr}).impl
return Expr{impl, tinter}
}
panic("todo")
}

View File

@@ -99,6 +99,7 @@ type aProgram struct {
ctx llvm.Context
typs typeutil.Map // rawType -> Type
gocvt goTypes
//abi *abi.Builder
rt *types.Package
rtget func() *types.Package
@@ -158,6 +159,7 @@ type aProgram struct {
NeedRuntime bool
NeedPyInit bool
is32Bits bool
}
// A Program presents a program.
@@ -180,7 +182,12 @@ func NewProgram(target *Target) Program {
// TODO(xsw): Finalize may cause panic, so comment it.
ctx.Finalize()
*/
return &aProgram{ctx: ctx, gocvt: newGoTypes(), target: target, td: td, named: make(map[string]llvm.Type)}
is32Bits := (td.PointerSize() == 4 || target.GOARCH == "x86") // TODO(xsw): remove temp code
return &aProgram{
ctx: ctx, gocvt: newGoTypes(), // abi: abi.New(),
target: target, td: td, is32Bits: is32Bits,
named: make(map[string]llvm.Type),
}
}
// SetPython sets the Python package.

View File

@@ -21,10 +21,18 @@ import (
"go/token"
"go/types"
"testing"
"unsafe"
"github.com/goplus/llvm"
)
func TestPointerSize(t *testing.T) {
expected := unsafe.Sizeof(uintptr(0))
if size := NewProgram(nil).PointerSize(); size != int(expected) {
t.Fatal("bad PointerSize:", size)
}
}
func TestSetBlock(t *testing.T) {
defer func() {
if r := recover(); r == nil {

58
ssa/ssatest/ssautil.go Normal file
View File

@@ -0,0 +1,58 @@
/*
* 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 ssatest
import (
"go/token"
"go/types"
"testing"
"github.com/goplus/gogen/packages"
"github.com/goplus/llgo/ssa"
)
func NewProgram(t *testing.T, target *ssa.Target) ssa.Program {
fset := token.NewFileSet()
imp := packages.NewImporter(fset)
return NewProgramEx(t, target, imp)
}
func NewProgramEx(t *testing.T, target *ssa.Target, imp types.Importer) ssa.Program {
prog := ssa.NewProgram(target)
prog.SetRuntime(func() *types.Package {
rt, err := imp.Import(ssa.PkgRuntime)
if err != nil {
t.Fatal("load runtime failed:", err)
}
return rt
})
prog.SetPython(func() *types.Package {
rt, err := imp.Import(ssa.PkgPython)
if err != nil {
t.Fatal("load python failed:", err)
}
return rt
})
return prog
}
func Assert(t *testing.T, p ssa.Package, expected string) {
t.Helper()
if v := p.String(); v != expected {
t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected)
}
}

View File

@@ -99,6 +99,10 @@ func (p Program) SizeOf(typ Type, n ...int64) uint64 {
return size
}
func (p Program) PointerSize() int {
return p.td.PointerSize()
}
func (p Program) Slice(typ Type) Type {
return p.rawType(types.NewSlice(typ.raw.Type))
}