@@ -13,7 +13,7 @@ type Foo struct {
|
||||
|
||||
var format = [...]int8{'H', 'e', 'l', 'l', 'o', ' ', '%', 'd', '\n', 0}
|
||||
|
||||
func (p *Foo) Print() {
|
||||
func (p Foo) Print() {
|
||||
if p.ok {
|
||||
printf(&format[0], p.A)
|
||||
}
|
||||
|
||||
@@ -6,22 +6,32 @@ source_filename = "main"
|
||||
@main.format = global ptr null
|
||||
@"main.init$guard" = global ptr null
|
||||
|
||||
define void @"(*main.Foo).Print"(ptr %0) {
|
||||
define void @"(main.Foo).Print"(%main.Foo %0) {
|
||||
_llgo_0:
|
||||
%1 = getelementptr inbounds %main.Foo, ptr %0, i32 0, i32 1
|
||||
%2 = load i1, ptr %1, align 1
|
||||
br i1 %2, label %_llgo_1, label %_llgo_2
|
||||
%1 = alloca %main.Foo, align 8
|
||||
store %main.Foo %0, ptr %1, align 4
|
||||
%2 = getelementptr inbounds %main.Foo, ptr %1, i32 0, i32 1
|
||||
%3 = load i1, ptr %2, align 1
|
||||
br i1 %3, label %_llgo_1, label %_llgo_2
|
||||
|
||||
_llgo_1: ; preds = %_llgo_0
|
||||
%3 = getelementptr inbounds %main.Foo, ptr %0, i32 0, i32 0
|
||||
%4 = load i32, ptr %3, align 4
|
||||
call void (ptr, ...) @printf(ptr @main.format, i32 %4)
|
||||
%4 = alloca %main.Foo, align 8
|
||||
%5 = getelementptr inbounds %main.Foo, ptr %4, i32 0, i32 0
|
||||
%6 = load i32, ptr %5, align 4
|
||||
call void (ptr, ...) @printf(ptr @main.format, i32 %6)
|
||||
br label %_llgo_2
|
||||
|
||||
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @"(*main.Foo).Print"(ptr %0) {
|
||||
_llgo_0:
|
||||
%1 = load %main.Foo, ptr %0, align 4
|
||||
call void @"(main.Foo).Print"(%main.Foo %1)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @main.init() {
|
||||
_llgo_0:
|
||||
%0 = load i1, ptr @"main.init$guard", align 1
|
||||
@@ -53,7 +63,8 @@ _llgo_0:
|
||||
%2 = getelementptr inbounds %main.Foo, ptr %0, i32 0, i32 1
|
||||
store i32 100, ptr %1, align 4
|
||||
store i1 true, ptr %2, align 1
|
||||
call void @"(*main.Foo).Print"(ptr %0)
|
||||
%3 = load %main.Foo, ptr %0, align 4
|
||||
call void @"(main.Foo).Print"(%main.Foo %3)
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||
define void @main() {
|
||||
_llgo_0:
|
||||
call void @main.init()
|
||||
%0 = alloca { i32, i1 }, align 8
|
||||
%0 = call ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 16)
|
||||
%1 = getelementptr inbounds { i32, i1 }, ptr %0, i32 0, i32 0
|
||||
%2 = getelementptr inbounds { i32, i1 }, ptr %0, i32 0, i32 1
|
||||
store i32 100, ptr %1, align 4
|
||||
@@ -56,3 +56,5 @@ _llgo_0:
|
||||
}
|
||||
|
||||
declare void @printf(ptr, ...)
|
||||
|
||||
declare ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64)
|
||||
|
||||
@@ -63,6 +63,17 @@ func FromDir(t *testing.T, sel, relDir string, byLLGen bool) {
|
||||
}
|
||||
}
|
||||
|
||||
func Pkg(t *testing.T, pkgPath, outFile string) {
|
||||
b, err := os.ReadFile(outFile)
|
||||
if err != nil {
|
||||
t.Fatal("ReadFile failed:", err)
|
||||
}
|
||||
expected := string(b)
|
||||
if v := llgen.GenFrom(pkgPath); v != expected {
|
||||
t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func testFrom(t *testing.T, pkgDir, sel string, byLLGen bool) {
|
||||
if sel != "" && !strings.Contains(pkgDir, sel) {
|
||||
return
|
||||
@@ -76,7 +87,7 @@ func testFrom(t *testing.T, pkgDir, sel string, byLLGen bool) {
|
||||
}
|
||||
expected := string(b)
|
||||
if byLLGen {
|
||||
if v := llgen.GenFromFile(in); v != expected {
|
||||
if v := llgen.GenFrom(in); v != expected {
|
||||
t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected)
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -245,14 +245,12 @@ func (p *context) isVArgs(vx ssa.Value) (ret []llssa.Expr, ok bool) {
|
||||
return
|
||||
}
|
||||
|
||||
func (p *context) checkVArgs(v *ssa.Alloc, t types.Type) bool {
|
||||
func (p *context) checkVArgs(v *ssa.Alloc, t *types.Pointer) bool {
|
||||
if v.Comment == "varargs" { // this is a varargs allocation
|
||||
if t, ok := t.(*types.Pointer); ok {
|
||||
if arr, ok := t.Elem().(*types.Array); ok {
|
||||
if isAny(arr.Elem()) {
|
||||
p.vargs[v] = make([]llssa.Expr, arr.Len())
|
||||
return true
|
||||
}
|
||||
if arr, ok := t.Elem().(*types.Array); ok {
|
||||
if isAny(arr.Elem()) {
|
||||
p.vargs[v] = make([]llssa.Expr, arr.Len())
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -300,6 +298,10 @@ func (p *context) compileInstrAndValue(b llssa.Builder, iv instrAndValue) (ret l
|
||||
t := v.Type()
|
||||
x := p.compileValue(b, v.X)
|
||||
ret = b.ChangeType(p.prog.Type(t), x)
|
||||
case *ssa.Convert:
|
||||
t := v.Type()
|
||||
x := p.compileValue(b, v.X)
|
||||
ret = b.Convert(p.prog.Type(t), x)
|
||||
case *ssa.FieldAddr:
|
||||
x := p.compileValue(b, v.X)
|
||||
ret = b.FieldAddr(x, v.Field)
|
||||
@@ -318,11 +320,11 @@ func (p *context) compileInstrAndValue(b llssa.Builder, iv instrAndValue) (ret l
|
||||
}
|
||||
panic("todo")
|
||||
case *ssa.Alloc:
|
||||
t := v.Type()
|
||||
t := v.Type().(*types.Pointer)
|
||||
if p.checkVArgs(v, t) { // varargs: this is a varargs allocation
|
||||
return
|
||||
}
|
||||
ret = b.Alloc(p.prog.Type(t), v.Heap)
|
||||
ret = b.Alloc(t, v.Heap)
|
||||
case *ssa.MakeInterface:
|
||||
const (
|
||||
delayExpr = true // varargs: don't need to convert an expr to any
|
||||
@@ -383,6 +385,9 @@ func (p *context) compileInstr(b llssa.Builder, instr ssa.Instruction) {
|
||||
thenb := fn.Block(succs[0].Index)
|
||||
elseb := fn.Block(succs[1].Index)
|
||||
b.If(cond, thenb, elseb)
|
||||
case *ssa.Panic:
|
||||
arg := p.compileValue(b, v.X).Do()
|
||||
b.Panic(arg)
|
||||
default:
|
||||
panic(fmt.Sprintf("compileInstr: unknown instr - %T\n", instr))
|
||||
}
|
||||
|
||||
@@ -35,6 +35,10 @@ func TestFromTestdata(t *testing.T) {
|
||||
cltest.FromDir(t, "", "./_testdata", false)
|
||||
}
|
||||
|
||||
func TestRuntime(t *testing.T) {
|
||||
cltest.Pkg(t, "github.com/goplus/llgo/internal/runtime", "../internal/runtime/llgo_autogen.ll")
|
||||
}
|
||||
|
||||
func TestVar(t *testing.T) {
|
||||
testCompile(t, `package foo
|
||||
|
||||
|
||||
@@ -35,11 +35,11 @@ const (
|
||||
loadSyntax = loadTypes | packages.NeedSyntax | packages.NeedTypesInfo
|
||||
)
|
||||
|
||||
func GenFromFile(inFile string) string {
|
||||
func GenFrom(fileOrPkg string) string {
|
||||
cfg := &packages.Config{
|
||||
Mode: loadSyntax,
|
||||
}
|
||||
initial, err := packages.Load(cfg, inFile)
|
||||
initial, err := packages.Load(cfg, fileOrPkg)
|
||||
check(err)
|
||||
|
||||
_, pkgs := ssautil.AllPackages(initial, ssa.SanityCheckFunctions)
|
||||
@@ -61,8 +61,8 @@ func GenFromFile(inFile string) string {
|
||||
return ret.String()
|
||||
}
|
||||
|
||||
func DoFile(inFile, outFile string) {
|
||||
ret := GenFromFile(inFile)
|
||||
func DoFile(fileOrPkg, outFile string) {
|
||||
ret := GenFrom(fileOrPkg)
|
||||
err := os.WriteFile(outFile, []byte(ret), 0644)
|
||||
check(err)
|
||||
}
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package runtime
|
||||
404
internal/runtime/llgo_autogen.ll
Normal file
404
internal/runtime/llgo_autogen.ll
Normal file
@@ -0,0 +1,404 @@
|
||||
; ModuleID = 'github.com/goplus/llgo/internal/runtime'
|
||||
source_filename = "github.com/goplus/llgo/internal/runtime"
|
||||
|
||||
%"github.com/goplus/llgo/internal/runtime.iface" = type { ptr, ptr }
|
||||
%"github.com/goplus/llgo/internal/runtime.itab" = type { ptr, ptr, i32, [4 x i8], [1 x i64] }
|
||||
%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 }
|
||||
%"github.com/goplus/llgo/internal/abi.InterfaceType" = type { %"github.com/goplus/llgo/internal/abi.Type", %"github.com/goplus/llgo/internal/abi.Name", %"github.com/goplus/llgo/internal/runtime.Slice" }
|
||||
%"github.com/goplus/llgo/internal/abi.Type" = type { i64, i64, i32, i8, i8, i8, i8, i1 (ptr, ptr), ptr, i32, i32 }
|
||||
%"github.com/goplus/llgo/internal/abi.Name" = type { ptr }
|
||||
%"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 }
|
||||
%"github.com/goplus/llgo/internal/runtime.String.0" = type { ptr, i64 }
|
||||
%"github.com/goplus/llgo/internal/runtime.Slice.1" = type { ptr, i64, i64 }
|
||||
|
||||
@"github.com/goplus/llgo/internal/runtime.TyAny" = global ptr null
|
||||
@"github.com/goplus/llgo/internal/runtime.basicTypes" = global ptr null
|
||||
@"github.com/goplus/llgo/internal/runtime.init$guard" = global ptr null
|
||||
@"github.com/goplus/llgo/internal/runtime.sizeBasicTypes" = global ptr null
|
||||
|
||||
define ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 %0) {
|
||||
_llgo_0:
|
||||
%1 = call ptr @malloc(i64 %0)
|
||||
ret ptr %1
|
||||
}
|
||||
|
||||
define ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 %0) {
|
||||
_llgo_0:
|
||||
%1 = getelementptr inbounds ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 %0
|
||||
%2 = load ptr, ptr %1, align 8
|
||||
ret ptr %2
|
||||
}
|
||||
|
||||
define { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %1) {
|
||||
_llgo_0:
|
||||
%2 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
|
||||
store %"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %2, align 8
|
||||
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i32 0, i32 0
|
||||
%4 = load ptr, ptr %3, align 8
|
||||
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 1
|
||||
%6 = load ptr, ptr %5, align 8
|
||||
%7 = icmp eq ptr %6, %1
|
||||
br i1 %7, label %_llgo_1, label %_llgo_2
|
||||
|
||||
_llgo_1: ; preds = %_llgo_0
|
||||
%8 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
|
||||
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %8, i32 0, i32 1
|
||||
%10 = load ptr, ptr %9, align 8
|
||||
%castInt = sext ptr %10 to i64
|
||||
%mrv = insertvalue { i64, i1 } poison, i64 %castInt, 0
|
||||
%mrv1 = insertvalue { i64, i1 } %mrv, i1 true, 1
|
||||
ret { i64, i1 } %mrv1
|
||||
|
||||
_llgo_2: ; preds = %_llgo_0
|
||||
ret { i64, i1 } zeroinitializer
|
||||
}
|
||||
|
||||
define %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.EmptyString"() {
|
||||
_llgo_0:
|
||||
%0 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %0, i32 0, i32 0
|
||||
%2 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %0, i32 0, i32 1
|
||||
store ptr null, ptr %1, align 8
|
||||
store i64 0, ptr %2, align 4
|
||||
%3 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %0, align 8
|
||||
ret %"github.com/goplus/llgo/internal/runtime.String" %3
|
||||
}
|
||||
|
||||
define i64 @"github.com/goplus/llgo/internal/runtime.I2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %1) {
|
||||
_llgo_0:
|
||||
%2 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
|
||||
store %"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %2, align 8
|
||||
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i32 0, i32 0
|
||||
%4 = load ptr, ptr %3, align 8
|
||||
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 1
|
||||
%6 = load ptr, ptr %5, align 8
|
||||
%7 = icmp eq ptr %6, %1
|
||||
br i1 %7, label %_llgo_1, label %_llgo_2
|
||||
|
||||
_llgo_1: ; preds = %_llgo_0
|
||||
%8 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
|
||||
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %8, i32 0, i32 1
|
||||
%10 = load ptr, ptr %9, align 8
|
||||
%castInt = sext ptr %10 to i64
|
||||
ret i64 %castInt
|
||||
|
||||
_llgo_2: ; preds = %_llgo_0
|
||||
%11 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"([21 x i8] c"I2Int: type mismatch\00")
|
||||
call void @abort()
|
||||
}
|
||||
|
||||
define ptr @"(*github.com/goplus/llgo/internal/abi.InterfaceType).ArrayType"(ptr %0) {
|
||||
_llgo_0:
|
||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr %1)
|
||||
ret ptr %2
|
||||
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
||||
%4 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr %3)
|
||||
ret ptr %4
|
||||
|
||||
_llgo_01: ; No predecessors!
|
||||
}
|
||||
|
||||
define ptr @"(*github.com/goplus/llgo/internal/abi.InterfaceType).Common"(ptr %0) {
|
||||
_llgo_0:
|
||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr %1)
|
||||
ret ptr %2
|
||||
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
||||
%4 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr %3)
|
||||
ret ptr %4
|
||||
|
||||
_llgo_01: ; No predecessors!
|
||||
}
|
||||
|
||||
define ptr @"(*github.com/goplus/llgo/internal/abi.InterfaceType).Elem"(ptr %0) {
|
||||
_llgo_0:
|
||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Elem"(ptr %1)
|
||||
ret ptr %2
|
||||
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
||||
%4 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Elem"(ptr %3)
|
||||
ret ptr %4
|
||||
|
||||
_llgo_01: ; No predecessors!
|
||||
}
|
||||
|
||||
define ptr @"(*github.com/goplus/llgo/internal/abi.InterfaceType).FuncType"(ptr %0) {
|
||||
_llgo_0:
|
||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr %1)
|
||||
ret ptr %2
|
||||
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
||||
%4 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr %3)
|
||||
ret ptr %4
|
||||
|
||||
_llgo_01: ; No predecessors!
|
||||
}
|
||||
|
||||
define ptr @"(*github.com/goplus/llgo/internal/abi.InterfaceType).InterfaceType"(ptr %0) {
|
||||
_llgo_0:
|
||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr %1)
|
||||
ret ptr %2
|
||||
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
||||
%4 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr %3)
|
||||
ret ptr %4
|
||||
|
||||
_llgo_01: ; No predecessors!
|
||||
}
|
||||
|
||||
define i64 @"(*github.com/goplus/llgo/internal/abi.InterfaceType).Kind"(ptr %0) {
|
||||
_llgo_0:
|
||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
||||
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %1)
|
||||
ret i64 %2
|
||||
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
||||
%4 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %3)
|
||||
ret i64 %4
|
||||
|
||||
_llgo_01: ; No predecessors!
|
||||
}
|
||||
|
||||
define i64 @"(*github.com/goplus/llgo/internal/abi.InterfaceType).Len"(ptr %0) {
|
||||
_llgo_0:
|
||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
||||
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Len"(ptr %1)
|
||||
ret i64 %2
|
||||
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
||||
%4 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Len"(ptr %3)
|
||||
ret i64 %4
|
||||
|
||||
_llgo_01: ; No predecessors!
|
||||
}
|
||||
|
||||
define ptr @"(*github.com/goplus/llgo/internal/abi.InterfaceType).MapType"(ptr %0) {
|
||||
_llgo_0:
|
||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr %1)
|
||||
ret ptr %2
|
||||
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
||||
%4 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr %3)
|
||||
ret ptr %4
|
||||
|
||||
_llgo_01: ; No predecessors!
|
||||
}
|
||||
|
||||
define ptr @"(*github.com/goplus/llgo/internal/abi.InterfaceType).StructType"(ptr %0) {
|
||||
_llgo_0:
|
||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr %1)
|
||||
ret ptr %2
|
||||
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
||||
%4 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr %3)
|
||||
ret ptr %4
|
||||
|
||||
_llgo_01: ; No predecessors!
|
||||
}
|
||||
|
||||
define %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAny"(ptr %0, ptr %1) {
|
||||
_llgo_0:
|
||||
%2 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
|
||||
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i32 0, i32 0
|
||||
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 16)
|
||||
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 0
|
||||
%6 = load ptr, ptr @"github.com/goplus/llgo/internal/runtime.TyAny", align 8
|
||||
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 1
|
||||
%8 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 2
|
||||
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 4
|
||||
%10 = getelementptr inbounds i64, ptr %9, i64 0
|
||||
store ptr %6, ptr %5, align 8
|
||||
store ptr %0, ptr %7, align 8
|
||||
store i32 0, ptr %8, align 4
|
||||
store i64 0, ptr %10, align 4
|
||||
%11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i32 0, i32 1
|
||||
store ptr %4, ptr %3, align 8
|
||||
store ptr %1, ptr %11, align 8
|
||||
%12 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, align 8
|
||||
ret %"github.com/goplus/llgo/internal/runtime.iface" %12
|
||||
}
|
||||
|
||||
define %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %0, i64 %1) {
|
||||
_llgo_0:
|
||||
%2 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
|
||||
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i32 0, i32 0
|
||||
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 16)
|
||||
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 0
|
||||
%6 = load ptr, ptr @"github.com/goplus/llgo/internal/runtime.TyAny", align 8
|
||||
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 1
|
||||
%8 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 2
|
||||
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 4
|
||||
%10 = getelementptr inbounds i64, ptr %9, i64 0
|
||||
store ptr %6, ptr %5, align 8
|
||||
store ptr %0, ptr %7, align 8
|
||||
store i32 0, ptr %8, align 4
|
||||
store i64 0, ptr %10, align 4
|
||||
%11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i32 0, i32 1
|
||||
%castPtr = addrspacecast i64 %1 to ptr
|
||||
store ptr %4, ptr %3, align 8
|
||||
store ptr %castPtr, ptr %11, align 8
|
||||
%12 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, align 8
|
||||
ret %"github.com/goplus/llgo/internal/runtime.iface" %12
|
||||
}
|
||||
|
||||
define %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String.0" %0) {
|
||||
_llgo_0:
|
||||
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 16)
|
||||
store %"github.com/goplus/llgo/internal/runtime.String.0" %0, ptr %1, align 8
|
||||
%2 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
|
||||
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i32 0, i32 0
|
||||
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 16)
|
||||
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 0
|
||||
%6 = load ptr, ptr @"github.com/goplus/llgo/internal/runtime.TyAny", align 8
|
||||
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 1
|
||||
%8 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 24)
|
||||
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 2
|
||||
%10 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 4
|
||||
%11 = getelementptr inbounds i64, ptr %10, i64 0
|
||||
store ptr %6, ptr %5, align 8
|
||||
store ptr %8, ptr %7, align 8
|
||||
store i32 0, ptr %9, align 4
|
||||
store i64 0, ptr %11, align 4
|
||||
%12 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i32 0, i32 1
|
||||
store ptr %4, ptr %3, align 8
|
||||
store ptr %1, ptr %12, align 8
|
||||
%13 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, align 8
|
||||
ret %"github.com/goplus/llgo/internal/runtime.iface" %13
|
||||
}
|
||||
|
||||
define %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeInterface"(ptr %0, ptr %1, ptr %2) {
|
||||
_llgo_0:
|
||||
%3 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
|
||||
%4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %3, i32 0, i32 0
|
||||
%5 = call ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 16)
|
||||
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %5, i32 0, i32 0
|
||||
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %5, i32 0, i32 1
|
||||
%8 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %5, i32 0, i32 2
|
||||
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %5, i32 0, i32 4
|
||||
%10 = getelementptr inbounds i64, ptr %9, i64 0
|
||||
store ptr %0, ptr %6, align 8
|
||||
store ptr %1, ptr %7, align 8
|
||||
store i32 0, ptr %8, align 4
|
||||
store i64 0, ptr %10, align 4
|
||||
%11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %3, i32 0, i32 1
|
||||
store ptr %5, ptr %4, align 8
|
||||
store ptr %2, ptr %11, align 8
|
||||
%12 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %3, align 8
|
||||
ret %"github.com/goplus/llgo/internal/runtime.iface" %12
|
||||
}
|
||||
|
||||
declare ptr @malloc(i64)
|
||||
|
||||
define %"github.com/goplus/llgo/internal/runtime.Slice.1" @"github.com/goplus/llgo/internal/runtime.NilSlice"() {
|
||||
_llgo_0:
|
||||
%0 = alloca %"github.com/goplus/llgo/internal/runtime.Slice.1", align 8
|
||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice.1", ptr %0, i32 0, i32 0
|
||||
%2 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice.1", ptr %0, i32 0, i32 1
|
||||
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice.1", ptr %0, i32 0, i32 2
|
||||
store ptr null, ptr %1, align 8
|
||||
store i64 0, ptr %2, align 4
|
||||
store i64 0, ptr %3, align 4
|
||||
%4 = load %"github.com/goplus/llgo/internal/runtime.Slice.1", ptr %0, align 8
|
||||
ret %"github.com/goplus/llgo/internal/runtime.Slice.1" %4
|
||||
}
|
||||
|
||||
declare ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr)
|
||||
|
||||
declare ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr)
|
||||
|
||||
declare ptr @"(*github.com/goplus/llgo/internal/abi.Type).Elem"(ptr)
|
||||
|
||||
declare ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr)
|
||||
|
||||
declare ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr)
|
||||
|
||||
declare i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr)
|
||||
|
||||
declare i64 @"(*github.com/goplus/llgo/internal/abi.Type).Len"(ptr)
|
||||
|
||||
declare ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr)
|
||||
|
||||
declare ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr)
|
||||
|
||||
define ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 %0) {
|
||||
_llgo_0:
|
||||
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 16)
|
||||
%2 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %1, i32 0, i32 0
|
||||
%3 = getelementptr inbounds i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 %0
|
||||
%4 = load i64, ptr %3, align 4
|
||||
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %1, i32 0, i32 6
|
||||
%castInt = trunc i64 %0 to i8
|
||||
store i64 %4, ptr %2, align 4
|
||||
store i8 %castInt, ptr %5, align 1
|
||||
ret ptr %1
|
||||
}
|
||||
|
||||
define void @"github.com/goplus/llgo/internal/runtime.init"() {
|
||||
_llgo_0:
|
||||
%0 = load i1, ptr @"github.com/goplus/llgo/internal/runtime.init$guard", align 1
|
||||
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||
|
||||
_llgo_1: ; preds = %_llgo_0
|
||||
store i1 true, ptr @"github.com/goplus/llgo/internal/runtime.init$guard", align 1
|
||||
call void @"github.com/goplus/llgo/internal/abi.init"()
|
||||
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 16)
|
||||
store ptr %1, ptr @"github.com/goplus/llgo/internal/runtime.TyAny", align 8
|
||||
store i64 1, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 1), align 4
|
||||
store i64 8, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 2), align 4
|
||||
store i64 1, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 3), align 4
|
||||
store i64 2, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 4), align 4
|
||||
store i64 4, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 5), align 4
|
||||
store i64 8, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 6), align 4
|
||||
store i64 8, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 7), align 4
|
||||
store i64 1, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 8), align 4
|
||||
store i64 2, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 9), align 4
|
||||
store i64 4, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 10), align 4
|
||||
store i64 8, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 11), align 4
|
||||
store i64 8, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 12), align 4
|
||||
store i64 4, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 13), align 4
|
||||
store i64 8, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 14), align 4
|
||||
store i64 8, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 15), align 4
|
||||
store i64 16, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 16), align 4
|
||||
store i64 16, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 24), align 4
|
||||
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 1)
|
||||
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 2)
|
||||
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 3)
|
||||
%5 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 4)
|
||||
%6 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 5)
|
||||
%7 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 6)
|
||||
%8 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 7)
|
||||
%9 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 8)
|
||||
%10 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 9)
|
||||
%11 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 10)
|
||||
%12 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 11)
|
||||
%13 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 12)
|
||||
%14 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 13)
|
||||
%15 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 14)
|
||||
%16 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 15)
|
||||
%17 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 16)
|
||||
%18 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 24)
|
||||
store ptr %2, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 1), align 8
|
||||
store ptr %3, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 2), align 8
|
||||
store ptr %4, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 3), align 8
|
||||
store ptr %5, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 4), align 8
|
||||
store ptr %6, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 5), align 8
|
||||
store ptr %7, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 6), align 8
|
||||
store ptr %8, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 7), align 8
|
||||
store ptr %9, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 8), align 8
|
||||
store ptr %10, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 9), align 8
|
||||
store ptr %11, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 10), align 8
|
||||
store ptr %12, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 11), align 8
|
||||
store ptr %13, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 12), align 8
|
||||
store ptr %14, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 13), align 8
|
||||
store ptr %15, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 14), align 8
|
||||
store ptr %16, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 15), align 8
|
||||
store ptr %17, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 16), align 8
|
||||
store ptr %18, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 24), align 8
|
||||
br label %_llgo_2
|
||||
|
||||
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||
ret void
|
||||
}
|
||||
|
||||
declare void @abort()
|
||||
|
||||
declare void @"github.com/goplus/llgo/internal/abi.init"()
|
||||
@@ -1,15 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type slice struct {
|
||||
array unsafe.Pointer
|
||||
len int
|
||||
cap int
|
||||
}
|
||||
31
internal/runtime/z_gc.go
Normal file
31
internal/runtime/z_gc.go
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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 runtime
|
||||
|
||||
import "unsafe"
|
||||
|
||||
const (
|
||||
LLGoPackage = true
|
||||
)
|
||||
|
||||
//go:linkname Malloc C.malloc
|
||||
func Malloc(size uintptr) unsafe.Pointer
|
||||
|
||||
// Alloc allocates memory.
|
||||
func Alloc(size uintptr) unsafe.Pointer {
|
||||
return Malloc(size)
|
||||
}
|
||||
@@ -37,6 +37,13 @@ func MakeAnyInt(typ *Type, data uintptr) Interface {
|
||||
}
|
||||
}
|
||||
|
||||
func MakeAnyString(data string) Interface {
|
||||
return Interface{
|
||||
tab: &itab{inter: TyAny, _type: Basic(abi.String), hash: 0, fun: [1]uintptr{0}},
|
||||
data: unsafe.Pointer(&data),
|
||||
}
|
||||
}
|
||||
|
||||
func MakeAny(typ *Type, data unsafe.Pointer) Interface {
|
||||
return Interface{
|
||||
tab: &itab{inter: TyAny, _type: typ, hash: 0, fun: [1]uintptr{0}},
|
||||
|
||||
@@ -16,8 +16,18 @@
|
||||
|
||||
package runtime
|
||||
|
||||
type Slice = slice
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func MakeEmptySlice() Slice {
|
||||
// Slice is the runtime representation of a slice.
|
||||
type Slice struct {
|
||||
array unsafe.Pointer
|
||||
len int
|
||||
cap int
|
||||
}
|
||||
|
||||
// NilSlice returns a nil slice.
|
||||
func NilSlice() Slice {
|
||||
return Slice{nil, 0, 0}
|
||||
}
|
||||
|
||||
37
internal/runtime/z_string.go
Normal file
37
internal/runtime/z_string.go
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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 runtime
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// String is the runtime representation of a string.
|
||||
// It cannot be used safely or portably and its representation may
|
||||
// change in a later release.
|
||||
//
|
||||
// Unlike reflect.StringHeader, its Data field is sufficient to guarantee the
|
||||
// data it references will not be garbage collected.
|
||||
type String struct {
|
||||
data unsafe.Pointer
|
||||
len int
|
||||
}
|
||||
|
||||
// EmptyString returns an empty string.
|
||||
func EmptyString() String {
|
||||
return String{nil, 0}
|
||||
}
|
||||
@@ -17,15 +17,15 @@
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"go/types"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goplus/llgo/internal/abi"
|
||||
)
|
||||
|
||||
type Kind = abi.Kind
|
||||
type Type = abi.Type
|
||||
|
||||
func Basic(kind types.BasicKind) *Type {
|
||||
func Basic(kind Kind) *Type {
|
||||
return basicTypes[kind]
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ var (
|
||||
abi.Float64: basicType(abi.Float64),
|
||||
abi.Complex64: basicType(abi.Complex64),
|
||||
abi.Complex128: basicType(abi.Complex128),
|
||||
abi.String: basicType(abi.String),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -68,6 +69,7 @@ var (
|
||||
abi.Float64: 8,
|
||||
abi.Complex64: 8,
|
||||
abi.Complex128: 16,
|
||||
abi.String: unsafe.Sizeof(String{}),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -29,3 +29,7 @@ func TestFromTestcgo(t *testing.T) {
|
||||
func TestFromTestdata(t *testing.T) {
|
||||
cltest.FromDir(t, "", "../cl/_testdata", false)
|
||||
}
|
||||
|
||||
func TestRuntime(t *testing.T) {
|
||||
cltest.Pkg(t, "github.com/goplus/llgo/internal/runtime", "../internal/runtime/llgo_autogen.ll")
|
||||
}
|
||||
|
||||
109
ssa/expr.go
109
ssa/expr.go
@@ -23,6 +23,7 @@ import (
|
||||
"go/token"
|
||||
"go/types"
|
||||
"log"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goplus/llvm"
|
||||
)
|
||||
@@ -76,10 +77,26 @@ func llvmValues(vals []Expr) []llvm.Value {
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Null returns a null constant expression.
|
||||
func (p Program) Null(t Type) Expr {
|
||||
return Expr{llvm.ConstNull(t.ll), t}
|
||||
}
|
||||
|
||||
// CStringVal returns a c-style string constant expression.
|
||||
func (p Program) CStringVal(v string) Expr {
|
||||
t := p.CString()
|
||||
return Expr{llvm.ConstString(v, true), t}
|
||||
}
|
||||
|
||||
// StringVal returns string constant expression.
|
||||
func (p Program) StringVal(v string) Expr {
|
||||
t := p.String()
|
||||
cstr := llvm.ConstString(v, true)
|
||||
// TODO(xsw): cstr => gostring
|
||||
return Expr{cstr, t}
|
||||
}
|
||||
|
||||
// BoolVal returns a boolean constant expression.
|
||||
func (p Program) BoolVal(v bool) Expr {
|
||||
t := p.Bool()
|
||||
var bv uint64
|
||||
@@ -90,15 +107,19 @@ func (p Program) BoolVal(v bool) Expr {
|
||||
return Expr{ret, t}
|
||||
}
|
||||
|
||||
// IntVal returns an integer constant expression.
|
||||
func (p Program) IntVal(v uint64, t Type) Expr {
|
||||
ret := llvm.ConstInt(t.ll, v, false)
|
||||
return Expr{ret, t}
|
||||
}
|
||||
|
||||
// Val returns a constant expression.
|
||||
func (p Program) Val(v interface{}) Expr {
|
||||
switch v := v.(type) {
|
||||
case int:
|
||||
return p.IntVal(uint64(v), p.Int())
|
||||
case uintptr:
|
||||
return p.IntVal(uint64(v), p.Uintptr())
|
||||
case bool:
|
||||
return p.BoolVal(v)
|
||||
case float64:
|
||||
@@ -109,17 +130,24 @@ func (p Program) Val(v interface{}) Expr {
|
||||
panic("todo")
|
||||
}
|
||||
|
||||
// Const returns a constant expression.
|
||||
func (b Builder) Const(v constant.Value, typ Type) Expr {
|
||||
prog := b.prog
|
||||
if v == nil {
|
||||
return prog.Null(typ)
|
||||
}
|
||||
switch t := typ.t.(type) {
|
||||
case *types.Basic:
|
||||
kind := t.Kind()
|
||||
switch {
|
||||
case kind == types.Bool:
|
||||
return b.prog.BoolVal(constant.BoolVal(v))
|
||||
return prog.BoolVal(constant.BoolVal(v))
|
||||
case kind >= types.Int && kind <= types.Uintptr:
|
||||
if v, exact := constant.Uint64Val(v); exact {
|
||||
return b.prog.IntVal(v, typ)
|
||||
return prog.IntVal(v, typ)
|
||||
}
|
||||
case kind == types.String:
|
||||
return prog.StringVal(constant.StringVal(v))
|
||||
}
|
||||
}
|
||||
panic("todo")
|
||||
@@ -255,7 +283,7 @@ func (b Builder) BinOp(op token.Token, x, y Expr) Expr {
|
||||
case vkSigned:
|
||||
pred := intPredOpToLLVM[op-predOpBase]
|
||||
return Expr{llvm.CreateICmp(b.impl, pred, x.impl, y.impl), tret}
|
||||
case vkUnsigned:
|
||||
case vkUnsigned, vkPtr:
|
||||
pred := uintPredOpToLLVM[op-predOpBase]
|
||||
return Expr{llvm.CreateICmp(b.impl, pred, x.impl, y.impl), tret}
|
||||
case vkFloat:
|
||||
@@ -375,18 +403,21 @@ func (b Builder) IndexAddr(x, idx Expr) Expr {
|
||||
//
|
||||
// t0 = local int
|
||||
// t1 = new int
|
||||
func (b Builder) Alloc(t Type, heap bool) (ret Expr) {
|
||||
func (b Builder) Alloc(t *types.Pointer, heap bool) (ret Expr) {
|
||||
if debugInstr {
|
||||
log.Printf("Alloc %v, %v\n", t.t, heap)
|
||||
log.Printf("Alloc %v, %v\n", t, heap)
|
||||
}
|
||||
telem := b.prog.Elem(t)
|
||||
prog := b.prog
|
||||
telem := t.Elem()
|
||||
if heap {
|
||||
ret.impl = llvm.CreateAlloca(b.impl, telem.ll)
|
||||
pkg := b.fn.pkg
|
||||
size := unsafe.Sizeof(telem)
|
||||
ret = b.Call(pkg.rtFunc("Alloc"), prog.Val(size))
|
||||
} else {
|
||||
panic("todo")
|
||||
ret.impl = llvm.CreateAlloca(b.impl, prog.Type(telem).ll)
|
||||
}
|
||||
// TODO: zero-initialize
|
||||
ret.Type = t
|
||||
// TODO(xsw): zero-initialize
|
||||
ret.Type = prog.Type(t)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -410,9 +441,6 @@ func (b Builder) Alloc(t Type, heap bool) (ret Expr) {
|
||||
// types in the type set of X.Type() have a value-preserving type
|
||||
// change to all types in the type set of Type().
|
||||
//
|
||||
// Pos() returns the ast.CallExpr.Lparen, if the instruction arose
|
||||
// from an explicit conversion in the source.
|
||||
//
|
||||
// Example printed form:
|
||||
//
|
||||
// t1 = changetype *int <- IntPtr (t0)
|
||||
@@ -422,9 +450,58 @@ func (b Builder) ChangeType(t Type, x Expr) (ret Expr) {
|
||||
}
|
||||
typ := t.t
|
||||
switch typ.(type) {
|
||||
default:
|
||||
ret.impl = b.impl.CreateBitCast(x.impl, t.ll, "bitCast")
|
||||
ret.Type = b.prog.Type(typ)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// The Convert instruction yields the conversion of value X to type
|
||||
// Type(). One or both of those types is basic (but possibly named).
|
||||
//
|
||||
// A conversion may change the value and representation of its operand.
|
||||
// Conversions are permitted:
|
||||
// - between real numeric types.
|
||||
// - between complex numeric types.
|
||||
// - between string and []byte or []rune.
|
||||
// - between pointers and unsafe.Pointer.
|
||||
// - between unsafe.Pointer and uintptr.
|
||||
// - from (Unicode) integer to (UTF-8) string.
|
||||
//
|
||||
// A conversion may imply a type name change also.
|
||||
//
|
||||
// Conversions may to be to or from a type parameter. All types in
|
||||
// the type set of X.Type() can be converted to all types in the type
|
||||
// set of Type().
|
||||
//
|
||||
// This operation cannot fail dynamically.
|
||||
//
|
||||
// Conversions of untyped string/number/bool constants to a specific
|
||||
// representation are eliminated during SSA construction.
|
||||
//
|
||||
// Pos() returns the ast.CallExpr.Lparen, if the instruction arose
|
||||
// from an explicit conversion in the source.
|
||||
//
|
||||
// Example printed form:
|
||||
//
|
||||
// t1 = convert []byte <- string (t0)
|
||||
func (b Builder) Convert(t Type, x Expr) (ret Expr) {
|
||||
typ := t.t
|
||||
ret.Type = b.prog.Type(typ)
|
||||
switch und := typ.Underlying().(type) {
|
||||
case *types.Basic:
|
||||
kind := und.Kind()
|
||||
switch {
|
||||
case kind >= types.Int && kind <= types.Uintptr:
|
||||
ret.impl = b.impl.CreateIntCast(x.impl, t.ll, "castInt")
|
||||
return
|
||||
case kind == types.UnsafePointer:
|
||||
ret.impl = b.impl.CreatePointerCast(x.impl, t.ll, "castPtr")
|
||||
return
|
||||
}
|
||||
case *types.Pointer:
|
||||
ret.impl = b.impl.CreatePointerCast(x.impl, t.ll, "castPtr")
|
||||
ret.Type = b.prog.Type(typ)
|
||||
return
|
||||
}
|
||||
panic("todo")
|
||||
@@ -459,6 +536,9 @@ func (b Builder) MakeInterface(inter types.Type, x Expr, mayDelay bool) (ret Exp
|
||||
case vkSigned, vkUnsigned, vkFloat:
|
||||
fn := pkg.rtFunc("MakeAnyInt")
|
||||
return b.InlineCall(fn, x)
|
||||
case vkString:
|
||||
fn := pkg.rtFunc("MakeAnyString")
|
||||
return b.InlineCall(fn, x)
|
||||
}
|
||||
panic("todo")
|
||||
}
|
||||
@@ -534,6 +614,7 @@ func (b Builder) TypeAssert(x Expr, assertedTyp Type, commaOk bool) (ret Expr) {
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// TODO(xsw): make inline call
|
||||
func (b Builder) InlineCall(fn Expr, args ...Expr) (ret Expr) {
|
||||
return b.Call(fn, args...)
|
||||
}
|
||||
|
||||
@@ -110,14 +110,18 @@ type aProgram struct {
|
||||
voidType llvm.Type
|
||||
voidPtrTy llvm.Type
|
||||
|
||||
rtIfaceTy llvm.Type
|
||||
rtSliceTy llvm.Type
|
||||
rtStringTy llvm.Type
|
||||
rtIfaceTy llvm.Type
|
||||
rtSliceTy llvm.Type
|
||||
|
||||
anyTy Type
|
||||
voidTy Type
|
||||
boolTy Type
|
||||
intTy Type
|
||||
f64Ty Type
|
||||
anyTy Type
|
||||
voidTy Type
|
||||
boolTy Type
|
||||
cstrTy Type
|
||||
stringTy Type
|
||||
uintptrTy Type
|
||||
intTy Type
|
||||
f64Ty Type
|
||||
}
|
||||
|
||||
// A Program presents a program.
|
||||
@@ -169,6 +173,13 @@ func (p Program) rtSlice() llvm.Type {
|
||||
return p.rtSliceTy
|
||||
}
|
||||
|
||||
func (p Program) rtString() llvm.Type {
|
||||
if p.rtStringTy.IsNil() {
|
||||
p.rtStringTy = p.rtType("String").ll
|
||||
}
|
||||
return p.rtStringTy
|
||||
}
|
||||
|
||||
// NewPackage creates a new package.
|
||||
func (p Program) NewPackage(name, pkgPath string) Package {
|
||||
mod := p.ctx.NewModule(pkgPath)
|
||||
@@ -195,6 +206,20 @@ func (p Program) Bool() Type {
|
||||
return p.boolTy
|
||||
}
|
||||
|
||||
func (p Program) CString() Type {
|
||||
if p.cstrTy == nil { // *int8
|
||||
p.cstrTy = p.Type(types.NewPointer(types.Typ[types.Int8]))
|
||||
}
|
||||
return p.cstrTy
|
||||
}
|
||||
|
||||
func (p Program) String() Type {
|
||||
if p.stringTy == nil {
|
||||
p.stringTy = p.Type(types.Typ[types.String])
|
||||
}
|
||||
return p.stringTy
|
||||
}
|
||||
|
||||
// Any returns any type.
|
||||
func (p Program) Any() Type {
|
||||
if p.anyTy == nil {
|
||||
@@ -211,6 +236,14 @@ func (p Program) Int() Type {
|
||||
return p.intTy
|
||||
}
|
||||
|
||||
// Uintptr returns uintptr type.
|
||||
func (p Program) Uintptr() Type {
|
||||
if p.uintptrTy == nil {
|
||||
p.uintptrTy = p.Type(types.Typ[types.Uintptr])
|
||||
}
|
||||
return p.uintptrTy
|
||||
}
|
||||
|
||||
// Float64 returns float64 type.
|
||||
func (p Program) Float64() Type {
|
||||
if p.f64Ty == nil {
|
||||
@@ -259,6 +292,9 @@ func (p Package) VarOf(name string) Global {
|
||||
|
||||
// NewFunc creates a new function.
|
||||
func (p Package) NewFunc(name string, sig *types.Signature) Function {
|
||||
if v, ok := p.fns[name]; ok {
|
||||
return v
|
||||
}
|
||||
t := p.prog.llvmSignature(sig)
|
||||
fn := llvm.AddFunction(p.mod, name, t.ll)
|
||||
ret := newFunction(fn, t, p, p.prog)
|
||||
@@ -271,14 +307,14 @@ func (p Package) FuncOf(name string) Function {
|
||||
return p.fns[name]
|
||||
}
|
||||
|
||||
func (p Package) rtAbort() Expr {
|
||||
return p.NewFunc("abort", types.NewSignatureType(nil, nil, nil, nil, nil, false)).Expr
|
||||
}
|
||||
|
||||
func (p Package) rtFunc(fnName string) Expr {
|
||||
fn := p.prog.runtime().Lookup(fnName).(*types.Func)
|
||||
name := FullName(fn.Pkg(), fnName)
|
||||
v, ok := p.fns[name]
|
||||
if !ok {
|
||||
v = p.NewFunc(name, fn.Type().(*types.Signature))
|
||||
}
|
||||
return v.Expr
|
||||
return p.NewFunc(name, fn.Type().(*types.Signature)).Expr
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -68,6 +68,15 @@ func (b Builder) SetBlock(blk BasicBlock) Builder {
|
||||
return b
|
||||
}
|
||||
|
||||
// Panic emits a panic instruction.
|
||||
func (b Builder) Panic(v Expr) {
|
||||
if debugInstr {
|
||||
log.Printf("Panic %v\n", v.impl)
|
||||
}
|
||||
pkg := b.fn.pkg
|
||||
b.Call(pkg.rtAbort()) // TODO(xsw): pass v
|
||||
}
|
||||
|
||||
// Return emits a return instruction.
|
||||
func (b Builder) Return(results ...Expr) {
|
||||
if debugInstr {
|
||||
|
||||
11
ssa/type.go
11
ssa/type.go
@@ -39,6 +39,7 @@ const (
|
||||
vkComplex
|
||||
vkString
|
||||
vkBool
|
||||
vkPtr
|
||||
vkFunc
|
||||
vkTuple
|
||||
vkDelayExpr = -1
|
||||
@@ -122,6 +123,9 @@ func (p Program) Field(typ Type, i int) Type {
|
||||
}
|
||||
|
||||
func (p Program) Type(typ types.Type) Type {
|
||||
if sig, ok := typ.(*types.Signature); ok { // should methodToFunc
|
||||
return p.llvmSignature(sig)
|
||||
}
|
||||
if v := p.typs.At(typ); v != nil {
|
||||
return v.(Type)
|
||||
}
|
||||
@@ -236,12 +240,13 @@ func (p Program) toLLVMType(typ types.Type) Type {
|
||||
case types.Complex64:
|
||||
case types.Complex128:
|
||||
case types.String:
|
||||
return &aType{p.rtString(), typ, vkString}
|
||||
case types.UnsafePointer:
|
||||
return &aType{p.tyVoidPtr(), typ, vkInvalid}
|
||||
return &aType{p.tyVoidPtr(), typ, vkPtr}
|
||||
}
|
||||
case *types.Pointer:
|
||||
elem := p.Type(t.Elem())
|
||||
return &aType{llvm.PointerType(elem.ll, 0), typ, vkInvalid}
|
||||
return &aType{llvm.PointerType(elem.ll, 0), typ, vkPtr}
|
||||
case *types.Interface:
|
||||
return &aType{p.rtIface(), typ, vkInvalid}
|
||||
case *types.Slice:
|
||||
@@ -251,8 +256,6 @@ func (p Program) toLLVMType(typ types.Type) Type {
|
||||
return p.toLLVMStruct(t)
|
||||
case *types.Named:
|
||||
return p.toLLVMNamed(t)
|
||||
case *types.Signature:
|
||||
return p.toLLVMFunc(t)
|
||||
case *types.Array:
|
||||
elem := p.Type(t.Elem())
|
||||
return &aType{llvm.ArrayType(elem.ll, int(t.Len())), typ, vkInvalid}
|
||||
|
||||
Reference in New Issue
Block a user