diff --git a/chore/gentests/gentests.go b/chore/gentests/gentests.go new file mode 100644 index 00000000..f839dfc8 --- /dev/null +++ b/chore/gentests/gentests.go @@ -0,0 +1,57 @@ +/* + * 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 main + +import ( + "fmt" + "os" + "strings" + + "github.com/goplus/llgo/internal/llgen" + "github.com/goplus/mod" +) + +func main() { + dir, _, err := mod.FindGoMod(".") + check(err) + + llgen.Verbose = false + + llgenDir(dir + "/cl/_testrt") + llgenDir(dir+"/cl/_testdata", "") +} + +func llgenDir(dir string, pkgPath ...string) { + fis, err := os.ReadDir(dir) + check(err) + for _, fi := range fis { + name := fi.Name() + if !fi.IsDir() || strings.HasPrefix(name, "_") { + continue + } + testDir := dir + "/" + name + fmt.Fprintln(os.Stderr, "llgen", testDir) + os.Chdir(testDir) + llgen.SmartDoFile("in.go", pkgPath...) + } +} + +func check(err error) { + if err != nil { + panic(err) + } +} diff --git a/chore/llgen/llgen.go b/chore/llgen/llgen.go index 3473fa1d..ec27e29b 100644 --- a/chore/llgen/llgen.go +++ b/chore/llgen/llgen.go @@ -19,8 +19,6 @@ package main import ( "fmt" "os" - "path/filepath" - "strings" "github.com/goplus/llgo/internal/llgen" ) @@ -31,24 +29,6 @@ func main() { return } - inFile := os.Args[1] - - dir, _ := filepath.Split(inFile) - fname := "llgo_autogen.ll" - if inCompilerDir(dir) { - fname = "out.ll" - } - outFile := dir + fname - llgen.Init() - if len(os.Args) >= 3 { - llgen.Do(os.Args[2], inFile, outFile) - } else { - llgen.DoFile(inFile, outFile) - } -} - -func inCompilerDir(dir string) bool { - dir, _ = filepath.Abs(dir) - return strings.Contains(filepath.ToSlash(dir), "/llgo/cl/") + llgen.SmartDoFile(os.Args[1], os.Args[2:]...) } diff --git a/cl/_testdata/fncall/out.ll b/cl/_testdata/fncall/out.ll index 4adec91a..7b3c8d0b 100644 --- a/cl/_testdata/fncall/out.ll +++ b/cl/_testdata/fncall/out.ll @@ -18,6 +18,7 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0 define void @main() { _llgo_0: + call void @"github.com/goplus/llgo/internal/runtime.init"() call void @main.init() %0 = call i64 @main.max(i64 1, i64 2) ret void @@ -34,3 +35,5 @@ _llgo_1: ; preds = %_llgo_0 _llgo_2: ; preds = %_llgo_0 ret i64 %1 } + +declare void @"github.com/goplus/llgo/internal/runtime.init"() diff --git a/cl/_testdata/importpkg/out.ll b/cl/_testdata/importpkg/out.ll index 8aa4cbb1..6ee8cd05 100644 --- a/cl/_testdata/importpkg/out.ll +++ b/cl/_testdata/importpkg/out.ll @@ -27,6 +27,7 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0 define void @main() { _llgo_0: + call void @"github.com/goplus/llgo/internal/runtime.init"() call void @main.init() %0 = call i64 @"github.com/goplus/llgo/cl/internal/stdio.Max"(i64 2, i64 100) call void (ptr, ...) @printf(ptr @main.hello) @@ -35,6 +36,8 @@ _llgo_0: declare void @"github.com/goplus/llgo/cl/internal/stdio.init"() +declare void @"github.com/goplus/llgo/internal/runtime.init"() + declare i64 @"github.com/goplus/llgo/cl/internal/stdio.Max"(i64, i64) declare void @printf(ptr, ...) diff --git a/cl/_testdata/method/out.ll b/cl/_testdata/method/out.ll index b4734045..3f7b91f5 100644 --- a/cl/_testdata/method/out.ll +++ b/cl/_testdata/method/out.ll @@ -42,6 +42,7 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0 define void @main() { _llgo_0: + call void @"github.com/goplus/llgo/internal/runtime.init"() call void @main.init() %0 = call i64 @"(main.T).Add"(i64 1, i64 2) call void (ptr, ...) @printf(ptr @main.format, i64 %0) @@ -49,3 +50,5 @@ _llgo_0: } declare void @printf(ptr, ...) + +declare void @"github.com/goplus/llgo/internal/runtime.init"() diff --git a/cl/_testdata/printf/out.ll b/cl/_testdata/printf/out.ll index 65ac64ae..d2f6551e 100644 --- a/cl/_testdata/printf/out.ll +++ b/cl/_testdata/printf/out.ll @@ -26,9 +26,12 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0 define void @main() { _llgo_0: + call void @"github.com/goplus/llgo/internal/runtime.init"() call void @main.init() call void (ptr, ...) @printf(ptr @main.hello) ret void } declare void @printf(ptr, ...) + +declare void @"github.com/goplus/llgo/internal/runtime.init"() diff --git a/cl/_testdata/printval/out.ll b/cl/_testdata/printval/out.ll index e7fe3bd9..a27337a7 100644 --- a/cl/_testdata/printval/out.ll +++ b/cl/_testdata/printval/out.ll @@ -29,9 +29,12 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0 define void @main() { _llgo_0: + call void @"github.com/goplus/llgo/internal/runtime.init"() call void @main.init() call void (ptr, ...) @printf(ptr @main.format, i64 100) ret void } declare void @printf(ptr, ...) + +declare void @"github.com/goplus/llgo/internal/runtime.init"() diff --git a/cl/_testdata/ptrmthd/out.ll b/cl/_testdata/ptrmthd/out.ll index 25fe6d7a..18f6bc04 100644 --- a/cl/_testdata/ptrmthd/out.ll +++ b/cl/_testdata/ptrmthd/out.ll @@ -35,9 +35,12 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0 define void @main() { _llgo_0: + call void @"github.com/goplus/llgo/internal/runtime.init"() call void @main.init() call void @"(*main.T).Print"(ptr @main.format, i64 100) ret void } declare void @printf(ptr, ...) + +declare void @"github.com/goplus/llgo/internal/runtime.init"() diff --git a/cl/_testdata/untyped/out.ll b/cl/_testdata/untyped/out.ll index fd8b4d8e..eb1cb11c 100644 --- a/cl/_testdata/untyped/out.ll +++ b/cl/_testdata/untyped/out.ll @@ -20,6 +20,7 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0 define void @main() { _llgo_0: + call void @"github.com/goplus/llgo/internal/runtime.init"() call void @main.init() br i1 false, label %_llgo_1, label %_llgo_2 @@ -30,3 +31,5 @@ _llgo_1: ; preds = %_llgo_0 _llgo_2: ; preds = %_llgo_1, %_llgo_0 ret void } + +declare void @"github.com/goplus/llgo/internal/runtime.init"() diff --git a/cl/_testdata/varinit/out.ll b/cl/_testdata/varinit/out.ll index 9aebe715..d631ebc5 100644 --- a/cl/_testdata/varinit/out.ll +++ b/cl/_testdata/varinit/out.ll @@ -20,6 +20,7 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0 define void @main() { _llgo_0: + call void @"github.com/goplus/llgo/internal/runtime.init"() call void @main.init() %0 = load i64, ptr @main.a, align 4 %1 = add i64 %0, 1 @@ -27,3 +28,5 @@ _llgo_0: %2 = load i64, ptr @main.a, align 4 ret void } + +declare void @"github.com/goplus/llgo/internal/runtime.init"() diff --git a/cl/_testrt/alloca/in.go b/cl/_testrt/alloca/in.go index 5550ac64..95a3dcf1 100644 --- a/cl/_testrt/alloca/in.go +++ b/cl/_testrt/alloca/in.go @@ -1,14 +1,12 @@ package main import ( - "unsafe" - "github.com/goplus/llgo/internal/runtime/c" ) func main() { s := c.Str("Hi\n") s2 := c.Alloca(4) - c.Memcpy(s2, unsafe.Pointer(s), 4) + c.Memcpy(s2, c.Pointer(s), 4) c.Printf(c.Str("%s"), s2) } diff --git a/cl/_testrt/alloca/out.ll b/cl/_testrt/alloca/out.ll index 3a0f3101..f7c596ee 100644 --- a/cl/_testrt/alloca/out.ll +++ b/cl/_testrt/alloca/out.ll @@ -20,6 +20,7 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0 define void @main() { _llgo_0: + call void @"github.com/goplus/llgo/internal/runtime.init"() call void @main.init() %0 = alloca i8, i64 4, align 1 %1 = call ptr @memcpy(ptr %0, ptr @0, i64 4) @@ -27,6 +28,8 @@ _llgo_0: ret void } +declare void @"github.com/goplus/llgo/internal/runtime.init"() + declare ptr @memcpy(ptr, ptr, i64) declare i32 @printf(ptr, ...) diff --git a/cl/_testrt/allocstr/out.ll b/cl/_testrt/allocstr/out.ll index 5a3a68b3..8713016e 100644 --- a/cl/_testrt/allocstr/out.ll +++ b/cl/_testrt/allocstr/out.ll @@ -28,6 +28,7 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0 define void @main() { _llgo_0: + call void @"github.com/goplus/llgo/internal/runtime.init"() call void @main.init() %0 = call %"github.com/goplus/llgo/internal/runtime.String" @main.hello() %1 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %0) @@ -40,6 +41,8 @@ _llgo_0: declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr, i64) +declare void @"github.com/goplus/llgo/internal/runtime.init"() + declare i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.Slice") declare ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr, %"github.com/goplus/llgo/internal/runtime.String") diff --git a/cl/_testrt/any/out.ll b/cl/_testrt/any/out.ll index cb4e49d9..3824cf96 100644 --- a/cl/_testrt/any/out.ll +++ b/cl/_testrt/any/out.ll @@ -29,6 +29,7 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0 define void @main() { _llgo_0: + call void @"github.com/goplus/llgo/internal/runtime.init"() call void @main.init() %0 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2) %1 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %0, i64 100) @@ -41,6 +42,8 @@ declare i64 @"github.com/goplus/llgo/internal/runtime.I2Int"(%"github.com/goplus 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 i32 @printf(ptr, ...) diff --git a/cl/_testrt/builtin/out.ll b/cl/_testrt/builtin/out.ll index 7588a13e..ee999eb5 100644 --- a/cl/_testrt/builtin/out.ll +++ b/cl/_testrt/builtin/out.ll @@ -26,6 +26,7 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0 define void @main() { _llgo_0: + call void @"github.com/goplus/llgo/internal/runtime.init"() call void @main.init() %0 = call ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 16) %1 = getelementptr inbounds i64, ptr %0, i64 0 @@ -52,6 +53,8 @@ _llgo_0: ret void } +declare void @"github.com/goplus/llgo/internal/runtime.init"() + declare ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64) declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice"(ptr, i64, i64) diff --git a/cl/_testrt/cstr/out.ll b/cl/_testrt/cstr/out.ll index f7b5d255..969ca268 100644 --- a/cl/_testrt/cstr/out.ll +++ b/cl/_testrt/cstr/out.ll @@ -19,9 +19,12 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0 define void @main() { _llgo_0: + call void @"github.com/goplus/llgo/internal/runtime.init"() call void @main.init() call void (ptr, ...) @printf(ptr @0) ret void } declare void @printf(ptr, ...) + +declare void @"github.com/goplus/llgo/internal/runtime.init"() diff --git a/cl/_testrt/gblarray/in.go b/cl/_testrt/gblarray/in.go new file mode 100644 index 00000000..3b60cf24 --- /dev/null +++ b/cl/_testrt/gblarray/in.go @@ -0,0 +1,35 @@ +package main + +import ( + "github.com/goplus/llgo/internal/abi" + "github.com/goplus/llgo/internal/runtime" + "github.com/goplus/llgo/internal/runtime/c" +) + +func Basic(kind abi.Kind) *abi.Type { + return basicTypes[kind] +} + +var ( + basicTypes = [...]*abi.Type{ + abi.String: basicType(abi.String), + } + sizeBasicTypes = [...]uintptr{ + abi.String: 16, + } +) + +func basicType(kind abi.Kind) *abi.Type { + return &abi.Type{ + Size_: sizeBasicTypes[kind], + Hash: uint32(kind), + Kind_: uint8(kind), + } +} + +func main() { + t := Basic(abi.String) + t2 := runtime.Basic(abi.String) + c.Printf(c.Str("Kind: %d, Size: %d\n"), int(t.Kind_), t.Size_) + c.Printf(c.Str("Kind: %d, Size: %d\n"), int(t2.Kind_), t2.Size_) +} diff --git a/cl/_testrt/gblarray/out.ll b/cl/_testrt/gblarray/out.ll new file mode 100644 index 00000000..773b0723 --- /dev/null +++ b/cl/_testrt/gblarray/out.ll @@ -0,0 +1,82 @@ +; ModuleID = 'main' +source_filename = "main" + +%"github.com/goplus/llgo/internal/abi.Type" = type { i64, i64, i32, i8, i8, i8, i8, ptr, ptr, i32, i32 } + +@main.basicTypes = global ptr null +@"main.init$guard" = global ptr null +@main.sizeBasicTypes = global ptr null +@0 = private unnamed_addr constant [20 x i8] c"Kind: %d, Size: %d\0A\00", align 1 +@1 = private unnamed_addr constant [20 x i8] c"Kind: %d, Size: %d\0A\00", align 1 + +define ptr @main.Basic(i64 %0) { +_llgo_0: + %1 = getelementptr inbounds ptr, ptr @main.basicTypes, i64 %0 + %2 = load ptr, ptr %1, align 8 + ret ptr %2 +} + +define ptr @main.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 @main.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 2 + %6 = trunc i64 %0 to i32 + %7 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %1, i32 0, i32 6 + %8 = trunc i64 %0 to i8 + store i64 %4, ptr %2, align 4 + store i32 %6, ptr %5, align 4 + store i8 %8, ptr %7, align 1 + ret ptr %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/internal/abi.init"() + call void @"github.com/goplus/llgo/internal/runtime.init"() + store i64 16, ptr getelementptr inbounds (i64, ptr @main.sizeBasicTypes, i64 24), align 4 + %1 = call ptr @main.basicType(i64 24) + store ptr %1, ptr getelementptr inbounds (ptr, ptr @main.basicTypes, i64 24), align 8 + br label %_llgo_2 + +_llgo_2: ; preds = %_llgo_1, %_llgo_0 + ret void +} + +define void @main() { +_llgo_0: + call void @"github.com/goplus/llgo/internal/runtime.init"() + call void @main.init() + %0 = call ptr @main.Basic(i64 24) + %1 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 24) + %2 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %0, i32 0, i32 6 + %3 = load i8, ptr %2, align 1 + %4 = sext i8 %3 to i64 + %5 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %0, i32 0, i32 0 + %6 = load i64, ptr %5, align 4 + %7 = call i32 (ptr, ...) @printf(ptr @0, i64 %4, i64 %6) + %8 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %1, i32 0, i32 6 + %9 = load i8, ptr %8, align 1 + %10 = sext i8 %9 to i64 + %11 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %1, i32 0, i32 0 + %12 = load i64, ptr %11, align 4 + %13 = call i32 (ptr, ...) @printf(ptr @1, i64 %10, i64 %12) + ret void +} + +declare ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64) + +declare void @"github.com/goplus/llgo/internal/abi.init"() + +declare void @"github.com/goplus/llgo/internal/runtime.init"() + +declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64) + +declare i32 @printf(ptr, ...) diff --git a/cl/_testrt/hello/out.ll b/cl/_testrt/hello/out.ll index c8e0b5f1..4f920ffa 100644 --- a/cl/_testrt/hello/out.ll +++ b/cl/_testrt/hello/out.ll @@ -29,12 +29,15 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0 define void @main() { _llgo_0: + call void @"github.com/goplus/llgo/internal/runtime.init"() call void @main.init() %0 = call i32 @strlen(ptr @main.format) call void (ptr, ...) @printf(ptr @main.format, i32 %0) ret void } +declare void @"github.com/goplus/llgo/internal/runtime.init"() + declare i32 @strlen(ptr) declare void @printf(ptr, ...) diff --git a/cl/_testrt/map/out.ll b/cl/_testrt/map/out.ll index 1cfe17c1..7f1f90f0 100644 --- a/cl/_testrt/map/out.ll +++ b/cl/_testrt/map/out.ll @@ -18,9 +18,12 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0 define void @main() { _llgo_0: + call void @"github.com/goplus/llgo/internal/runtime.init"() call void @main.init() %0 = call ptr @"github.com/goplus/llgo/internal/runtime.MakeSmallMap"() ret void } +declare void @"github.com/goplus/llgo/internal/runtime.init"() + declare ptr @"github.com/goplus/llgo/internal/runtime.MakeSmallMap"() diff --git a/cl/_testrt/panic/in.go b/cl/_testrt/panic/in.go new file mode 100644 index 00000000..d9411234 --- /dev/null +++ b/cl/_testrt/panic/in.go @@ -0,0 +1,5 @@ +package main + +func main() { + panic("panic message") +} diff --git a/cl/_testrt/panic/out.ll b/cl/_testrt/panic/out.ll new file mode 100644 index 00000000..155cfb20 --- /dev/null +++ b/cl/_testrt/panic/out.ll @@ -0,0 +1,39 @@ +; ModuleID = 'main' +source_filename = "main" + +%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 } +%"github.com/goplus/llgo/internal/runtime.iface" = type { ptr, ptr } + +@"main.init$guard" = global ptr null +@0 = private unnamed_addr constant [14 x i8] c"panic message\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() { +_llgo_0: + call void @"github.com/goplus/llgo/internal/runtime.init"() + call void @main.init() + %0 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @0, i64 13) + %1 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %0) + call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %1) + unreachable +} + +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 %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String") + +declare void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface") diff --git a/cl/_testrt/strlen/out.ll b/cl/_testrt/strlen/out.ll index 130d120f..a3aab0c6 100644 --- a/cl/_testrt/strlen/out.ll +++ b/cl/_testrt/strlen/out.ll @@ -29,6 +29,7 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0 define void @main() { _llgo_0: + call void @"github.com/goplus/llgo/internal/runtime.init"() call void @main.init() %0 = call i32 @strlen(ptr @main.format) call void (ptr, ...) @printf(ptr @main.format, i32 %0) @@ -38,3 +39,5 @@ _llgo_0: declare void @printf(ptr, ...) declare i32 @strlen(ptr) + +declare void @"github.com/goplus/llgo/internal/runtime.init"() diff --git a/cl/_testrt/struct/out.ll b/cl/_testrt/struct/out.ll index a8e29724..adead9a3 100644 --- a/cl/_testrt/struct/out.ll +++ b/cl/_testrt/struct/out.ll @@ -56,6 +56,7 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0 define void @main() { _llgo_0: + call void @"github.com/goplus/llgo/internal/runtime.init"() call void @main.init() %0 = alloca %main.Foo, align 8 %1 = getelementptr inbounds %main.Foo, ptr %0, i32 0, i32 0 @@ -68,3 +69,5 @@ _llgo_0: } declare void @printf(ptr, ...) + +declare void @"github.com/goplus/llgo/internal/runtime.init"() diff --git a/cl/_testrt/sum/out.ll b/cl/_testrt/sum/out.ll index 10750baf..1b390114 100644 --- a/cl/_testrt/sum/out.ll +++ b/cl/_testrt/sum/out.ll @@ -21,6 +21,7 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0 define void @main() { _llgo_0: + call void @"github.com/goplus/llgo/internal/runtime.init"() call void @main.init() %0 = call ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 16) %1 = getelementptr inbounds i64, ptr %0, i64 0 @@ -60,6 +61,8 @@ _llgo_3: ; preds = %_llgo_1 ret i64 %2 } +declare void @"github.com/goplus/llgo/internal/runtime.init"() + declare ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64) declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice"(ptr, i64, i64) diff --git a/cl/_testrt/typalias/out.ll b/cl/_testrt/typalias/out.ll index 3e2d16f8..d902282b 100644 --- a/cl/_testrt/typalias/out.ll +++ b/cl/_testrt/typalias/out.ll @@ -45,6 +45,7 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0 define void @main() { _llgo_0: + call void @"github.com/goplus/llgo/internal/runtime.init"() call void @main.init() %0 = call ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 16) %1 = getelementptr inbounds { i32, i1 }, ptr %0, i32 0, i32 0 @@ -57,4 +58,6 @@ _llgo_0: declare void @printf(ptr, ...) +declare void @"github.com/goplus/llgo/internal/runtime.init"() + declare ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64) diff --git a/cl/_testrt/unreachable/out.ll b/cl/_testrt/unreachable/out.ll index 1692ce52..c8127892 100644 --- a/cl/_testrt/unreachable/out.ll +++ b/cl/_testrt/unreachable/out.ll @@ -25,10 +25,13 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0 define void @main() { _llgo_0: + call void @"github.com/goplus/llgo/internal/runtime.init"() call void @main.init() call void @main.foo() %0 = call i32 (ptr, ...) @printf(ptr @0) ret void } +declare void @"github.com/goplus/llgo/internal/runtime.init"() + declare i32 @printf(ptr, ...) diff --git a/cl/compile.go b/cl/compile.go index 1bf1f593..c70c59c6 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -231,8 +231,9 @@ func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, doInit bo ret := p.fn.Block(block.Index) b.SetBlock(ret) if doInit { - fn := p.pkg.FuncOf("main.init") - b.Call(fn.Expr) + pkg := p.pkg + callRuntimeInit(b, pkg) + b.Call(pkg.FuncOf("main.init").Expr) } for _, instr := range block.Instrs { p.compileInstr(b, instr) @@ -240,6 +241,15 @@ func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, doInit bo return ret } +const ( + RuntimeInit = llssa.PkgRuntime + ".init" +) + +func callRuntimeInit(b llssa.Builder, pkg llssa.Package) { + fn := pkg.NewFunc(RuntimeInit, types.NewSignatureType(nil, nil, nil, nil, nil, false)) + b.Call(fn.Expr) +} + func isAny(t types.Type) bool { if t, ok := t.(*types.Interface); ok { return t.Empty() diff --git a/internal/build/build.go b/internal/build/build.go index 0d92d55a..34a5947b 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -185,7 +185,7 @@ func linkMainPkg(pkg *packages.Package, runtimeFiles []string, conf *Config, mod args[2] = "-Wno-override-module" needRuntime := false packages.Visit([]*packages.Package{pkg}, nil, func(p *packages.Package) { - if p.ExportFile != "" { // skip packages that only contain declarations + if p.ExportFile != "" && !isRuntimePkg(p.PkgPath) { // skip packages that only contain declarations args = append(args, p.ExportFile+".ll") if !needRuntime { needRuntime = isNeedRuntime(p) @@ -206,7 +206,9 @@ func linkMainPkg(pkg *packages.Package, runtimeFiles []string, conf *Config, mod }() // TODO(xsw): show work - // fmt.Fprintln(os.Stderr, "clang", args) + if verbose { + fmt.Fprintln(os.Stderr, "clang", args) + } err := clang.New("").Exec(args...) check(err) @@ -328,17 +330,24 @@ func allLinkFiles(rt []*packages.Package) (outFiles []string) { outFiles = make([]string, 0, len(rt)) root := rootLLGo(rt[0]) packages.Visit(rt, nil, func(p *packages.Package) { - if hasLinkFile(p) { - outFile := filepath.Join(root+p.PkgPath[len(llgoModPath):], "llgo_autogen.ll") + pkgPath := p.PkgPath + if isRuntimePkg(pkgPath) { + outFile := filepath.Join(root+pkgPath[len(llgoModPath):], "llgo_autogen.ll") outFiles = append(outFiles, outFile) } }) return } -func hasLinkFile(pkg *packages.Package) bool { - if isPkgInLLGo(pkg.PkgPath) { - return cl.PkgKindOf(pkg.Types) != cl.PkgDeclOnly +const ( + pkgAbi = llgoModPath + "/internal/abi" + pkgRuntime = llgoModPath + "/internal/runtime" +) + +func isRuntimePkg(pkgPath string) bool { + switch pkgPath { + case pkgRuntime, pkgAbi: + return true } return false } @@ -352,6 +361,7 @@ const ( llgoModPath = "github.com/goplus/llgo" ) +/* func isPkgInLLGo(pkgPath string) bool { return isPkgInMod(pkgPath, llgoModPath) } @@ -363,6 +373,7 @@ func isPkgInMod(pkgPath, modPath string) bool { } return false } +*/ func check(err error) { if err != nil { diff --git a/internal/llgen/llgen.go b/internal/llgen/llgen.go index f33a007b..d56b809e 100644 --- a/internal/llgen/llgen.go +++ b/internal/llgen/llgen.go @@ -66,7 +66,9 @@ func Gen(pkgPath, inFile string, src any) string { &types.Config{Importer: imp}, fset, pkg, files, ssa.SanityCheckFunctions) check(err) - ssaPkg.WriteTo(os.Stderr) + if Verbose { + ssaPkg.WriteTo(os.Stderr) + } prog := llssa.NewProgram(nil) ret, err := cl.NewPackage(prog, ssaPkg, files) @@ -80,3 +82,7 @@ func check(err error) { panic(err) } } + +var ( + Verbose = true +) diff --git a/internal/llgen/llgenf.go b/internal/llgen/llgenf.go index 16990ae7..7326e468 100644 --- a/internal/llgen/llgenf.go +++ b/internal/llgen/llgenf.go @@ -19,6 +19,8 @@ package llgen import ( "go/types" "os" + "path/filepath" + "strings" "github.com/goplus/llgo/cl" "golang.org/x/tools/go/packages" @@ -55,6 +57,10 @@ func GenFrom(fileOrPkg string) string { return rt[0].Types }) + if Verbose { + ssaPkg.WriteTo(os.Stderr) + } + ret, err := cl.NewPackage(prog, ssaPkg, pkg.Syntax) check(err) @@ -66,3 +72,23 @@ func DoFile(fileOrPkg, outFile string) { err := os.WriteFile(outFile, []byte(ret), 0644) check(err) } + +func SmartDoFile(inFile string, pkgPath ...string) { + dir, _ := filepath.Split(inFile) + fname := "llgo_autogen.ll" + if inCompilerDir(dir) { + fname = "out.ll" + } + outFile := dir + fname + + if len(pkgPath) > 0 { + Do(pkgPath[0], inFile, outFile) + } else { + DoFile(inFile, outFile) + } +} + +func inCompilerDir(dir string) bool { + dir, _ = filepath.Abs(dir) + return strings.Contains(filepath.ToSlash(dir), "/llgo/cl/") +} diff --git a/internal/runtime/c/c.go b/internal/runtime/c/c.go index 9b77a734..79763a1b 100644 --- a/internal/runtime/c/c.go +++ b/internal/runtime/c/c.go @@ -23,26 +23,32 @@ const ( LLGoPackage = "decl" ) +type ( + Char = int8 + Int = C.int + Pointer = unsafe.Pointer +) + //go:linkname Str llgo.cstr -func Str(string) *int8 +func Str(string) *Char //go:linkname Alloca llgo.alloca -func Alloca(size uintptr) unsafe.Pointer +func Alloca(size uintptr) Pointer //go:linkname AllocaCStr llgo.allocaCStr -func AllocaCStr(s string) *int8 +func AllocaCStr(s string) *Char //go:linkname Unreachable llgo.unreachable func Unreachable() //go:linkname Rand C.rand -func Rand() C.int +func Rand() Int //go:linkname Malloc C.malloc -func Malloc(size uintptr) unsafe.Pointer +func Malloc(size uintptr) Pointer //go:linkname Memcpy C.memcpy -func Memcpy(dst, src unsafe.Pointer, n uintptr) unsafe.Pointer +func Memcpy(dst, src Pointer, n uintptr) Pointer //go:linkname Printf C.printf -func Printf(format *int8, __llgo_va_list ...any) C.int +func Printf(format *Char, __llgo_va_list ...any) Int diff --git a/internal/runtime/llgo_autogen.ll b/internal/runtime/llgo_autogen.ll index dfd13bdd..2cde6fb9 100644 --- a/internal/runtime/llgo_autogen.ll +++ b/internal/runtime/llgo_autogen.ll @@ -1,18 +1,23 @@ ; ModuleID = 'github.com/goplus/llgo/internal/runtime' source_filename = "github.com/goplus/llgo/internal/runtime" +%"github.com/goplus/llgo/internal/abi.Type" = type { i64, i64, i32, i8, i8, i8, i8, ptr, ptr, i32, i32 } %"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 } %"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.Slice" = type { ptr, i64, i64 } -%"github.com/goplus/llgo/internal/abi.Type" = type { i64, i64, i32, i8, i8, i8, i8, ptr, ptr, i32, i32 } %"github.com/goplus/llgo/internal/runtime.hmap" = type { i64, i8, i8, i16, i32, ptr, ptr, i64, ptr } @"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 -@0 = private unnamed_addr constant [21 x i8] c"I2Int: type mismatch\00", align 1 +@0 = private unnamed_addr constant [27 x i8] c"Basic: %p, %d, %d, %d, %d\0A\00", align 1 +@1 = private unnamed_addr constant [21 x i8] c"I2Int: type mismatch\00", align 1 +@2 = private unnamed_addr constant [27 x i8] c"MakeAnyString(%p): %d, %d\0A\00", align 1 +@3 = private unnamed_addr constant [11 x i8] c"Panic(%d)\0A\00", align 1 +@4 = private unnamed_addr constant [11 x i8] c"panic: %s\0A\00", align 1 +@5 = private unnamed_addr constant [31 x i8] c"basicType: %p, %d, %d, %d, %d\0A\00", align 1 define ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 %0) { _llgo_0: @@ -24,6 +29,16 @@ 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 + %3 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %2, i32 0, i32 2 + %4 = load i32, ptr %3, align 4 + %5 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %2, i32 0, i32 6 + %6 = load i8, ptr %5, align 1 + %7 = sext i8 %6 to i32 + %8 = trunc i64 %0 to i32 + %9 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %2, i32 0, i32 0 + %10 = load i64, ptr %9, align 4 + %11 = trunc i64 %10 to i32 + %12 = call i32 (ptr, ...) @printf(ptr @0, ptr %2, i32 %4, i32 %7, i32 %8, i32 %11) ret ptr %2 } @@ -106,53 +121,54 @@ _llgo_1: ; preds = %_llgo_0 ret i64 %10 _llgo_2: ; preds = %_llgo_0 - %11 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @0, i64 20) + %11 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @1, i64 20) %12 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %11) + call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %12) unreachable } 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 + %2 = call ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 16) + %3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %2, i32 0, i32 0 + %4 = load ptr, ptr @"github.com/goplus/llgo/internal/runtime.TyAny", align 8 + %5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %2, i32 0, i32 1 + %6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %2, i32 0, i32 2 + %7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %2, i32 0, i32 4 + %8 = getelementptr inbounds i64, ptr %7, i64 0 store ptr %4, ptr %3, align 8 + store ptr %0, ptr %5, align 8 + store i32 0, ptr %6, align 4 + store i64 0, ptr %8, align 4 + %9 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8 + %10 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %9, i32 0, i32 0 + %11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %9, i32 0, i32 1 + store ptr %2, ptr %10, align 8 store ptr %1, ptr %11, align 8 - %12 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, align 8 + %12 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %9, 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 - %12 = inttoptr i64 %1 to ptr + %2 = call ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 16) + %3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %2, i32 0, i32 0 + %4 = load ptr, ptr @"github.com/goplus/llgo/internal/runtime.TyAny", align 8 + %5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %2, i32 0, i32 1 + %6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %2, i32 0, i32 2 + %7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %2, i32 0, i32 4 + %8 = getelementptr inbounds i64, ptr %7, i64 0 store ptr %4, ptr %3, align 8 + store ptr %0, ptr %5, align 8 + store i32 0, ptr %6, align 4 + store i64 0, ptr %8, align 4 + %9 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8 + %10 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %9, i32 0, i32 0 + %11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %9, i32 0, i32 1 + %12 = inttoptr i64 %1 to ptr + store ptr %2, ptr %10, align 8 store ptr %12, ptr %11, align 8 - %13 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, align 8 + %13 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %9, align 8 ret %"github.com/goplus/llgo/internal/runtime.iface" %13 } @@ -160,45 +176,49 @@ define %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo _llgo_0: %1 = call ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 16) store %"github.com/goplus/llgo/internal/runtime.String" %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 + %2 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 24) + %3 = call ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 16) + %4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %3, i32 0, i32 0 + %5 = load ptr, ptr @"github.com/goplus/llgo/internal/runtime.TyAny", align 8 + %6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %3, i32 0, i32 1 + %7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %3, i32 0, i32 2 + %8 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %3, i32 0, i32 4 + %9 = getelementptr inbounds i64, ptr %8, i64 0 + store ptr %5, ptr %4, align 8 + store ptr %2, ptr %6, align 8 + store i32 0, ptr %7, align 4 + store i64 0, ptr %9, align 4 + %10 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %2, i32 0, i32 6 + %11 = load i8, ptr %10, align 1 + %12 = sext i8 %11 to i64 + %13 = call i32 (ptr, ...) @printf(ptr @2, ptr %2, i64 %12, i64 24) + %14 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8 + %15 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %14, i32 0, i32 0 + %16 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %14, i32 0, i32 1 + store ptr %3, ptr %15, align 8 + store ptr %1, ptr %16, align 8 + %17 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %14, align 8 + ret %"github.com/goplus/llgo/internal/runtime.iface" %17 } 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 + %3 = call ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 16) + %4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %3, i32 0, i32 0 + %5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %3, i32 0, i32 1 + %6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %3, i32 0, i32 2 + %7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %3, i32 0, i32 4 + %8 = getelementptr inbounds i64, ptr %7, i64 0 + store ptr %0, ptr %4, align 8 + store ptr %1, ptr %5, align 8 + store i32 0, ptr %6, align 4 + store i64 0, ptr %8, align 4 + %9 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8 + %10 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %9, i32 0, i32 0 + %11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %9, i32 0, i32 1 + store ptr %3, ptr %10, align 8 store ptr %2, ptr %11, align 8 - %12 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %3, align 8 + %12 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %9, align 8 ret %"github.com/goplus/llgo/internal/runtime.iface" %12 } @@ -281,24 +301,64 @@ _llgo_0: ret i64 %3 } +define void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %0) { +_llgo_0: + %1 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8 + store %"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %1, align 8 + %2 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %1, i32 0, i32 0 + %3 = load ptr, ptr %2, align 8 + %4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %3, i32 0, i32 1 + %5 = load ptr, ptr %4, align 8 + %6 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %5, i32 0, i32 6 + %7 = load i8, ptr %6, align 1 + %8 = sext i8 %7 to i64 + %9 = call i32 (ptr, ...) @printf(ptr @3, i64 %8) + %10 = icmp eq i64 %8, 24 + br i1 %10, label %_llgo_2, label %_llgo_1 + +_llgo_1: ; preds = %_llgo_2, %_llgo_0 + ret void + +_llgo_2: ; preds = %_llgo_0 + %11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %1, i32 0, i32 1 + %12 = load ptr, ptr %11, align 8 + %13 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %12, i32 0, i32 1 + %14 = load i64, ptr %13, align 4 + %15 = add i64 %14, 1 + %16 = alloca i8, i64 %15, align 1 + %17 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %12, align 8 + %18 = call ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr %16, %"github.com/goplus/llgo/internal/runtime.String" %17) + %19 = call i32 (ptr, ...) @printf(ptr @4, ptr %18) + br label %_llgo_1 +} + 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 - %6 = trunc i64 %0 to i8 + %5 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %1, i32 0, i32 2 + %6 = trunc i64 %0 to i32 + %7 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %1, i32 0, i32 6 + %8 = trunc i64 %0 to i8 store i64 %4, ptr %2, align 4 - store i8 %6, ptr %5, align 1 + store i32 %6, ptr %5, align 4 + store i8 %8, ptr %7, align 1 + %9 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %1, i32 0, i32 2 + %10 = load i32, ptr %9, align 4 + %11 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %1, i32 0, i32 6 + %12 = load i8, ptr %11, align 1 + %13 = sext i8 %12 to i32 + %14 = trunc i64 %0 to i32 + %15 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %1, i32 0, i32 0 + %16 = load i64, ptr %15, align 4 + %17 = trunc i64 %16 to i32 + %18 = call i32 (ptr, ...) @printf(ptr @5, ptr %1, i32 %10, i32 %13, i32 %14, i32 %17) ret ptr %1 } -define i32 @"github.com/goplus/llgo/internal/runtime.fastrand"() { -_llgo_0: - %0 = call i32 @rand() - ret i32 %0 -} +declare i32 @rand() define void @"github.com/goplus/llgo/internal/runtime.init"() { _llgo_0: @@ -376,7 +436,7 @@ _llgo_0: define ptr @"github.com/goplus/llgo/internal/runtime.makemap_small"() { _llgo_0: %0 = call ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 16) - %1 = call i32 @"github.com/goplus/llgo/internal/runtime.fastrand"() + %1 = call i32 @rand() %2 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.hmap", ptr %0, i32 0, i32 4 store i32 %1, ptr %2, align 4 ret ptr %0 @@ -384,8 +444,8 @@ _llgo_0: declare ptr @malloc(i64) +declare i32 @printf(ptr, ...) + declare ptr @memcpy(ptr, ptr, i64) -declare i32 @rand() - declare void @"github.com/goplus/llgo/internal/abi.init"() diff --git a/internal/runtime/stubs.go b/internal/runtime/stubs.go index 3049817c..ed8b9a8d 100644 --- a/internal/runtime/stubs.go +++ b/internal/runtime/stubs.go @@ -4,14 +4,13 @@ package runtime -import ( - "github.com/goplus/llgo/internal/runtime/c" -) +import _ "unsafe" +//go:linkname fastrand C.rand +func fastrand() uint32 + +/* TODO(xsw): func fastrand() uint32 { - return uint32(c.Rand()) - /* TODO(xsw): - mp := getg().m // Implement wyrand: https://github.com/wangyi-fudan/wyhash // Only the platform that math.Mul64 can be lowered @@ -35,5 +34,5 @@ func fastrand() uint32 { s1 = s1 ^ s0 ^ s1>>7 ^ s0>>16 t[0], t[1] = s0, s1 return s0 + s1 - */ } +*/ diff --git a/internal/runtime/z_c.go b/internal/runtime/z_c.go index 6cca5b99..c6810222 100644 --- a/internal/runtime/z_c.go +++ b/internal/runtime/z_c.go @@ -19,6 +19,7 @@ package runtime import ( "unsafe" + "github.com/goplus/llgo/internal/abi" "github.com/goplus/llgo/internal/runtime/c" ) @@ -27,18 +28,15 @@ func Alloc(size uintptr) unsafe.Pointer { return c.Malloc(size) } -/* -// Panic panics with a value. -func Panic(v Interface) { - c.Printf(c.String("Panic!!!\n")) +// TracePanic prints panic message. +func TracePanic(v Interface) { kind := abi.Kind(v.tab._type.Kind_) + c.Printf(c.Str("Panic(%d)\n"), kind) switch { case kind == abi.String: s := (*String)(v.data) cs := c.Alloca(uintptr(s.len) + 1) - c.Memcpy(cs, s.data, uintptr(s.len)) - (*[1 << 30]int8)(cs)[s.len] = 0 - c.Printf(c.String("%s\n"), cs) + c.Printf(c.Str("panic: %s\n"), CStrCopy(cs, *s)) } + // TODO(xsw): other message type } -*/ diff --git a/internal/runtime/z_iface.go b/internal/runtime/z_iface.go index 2d35d8f9..0c5b7924 100644 --- a/internal/runtime/z_iface.go +++ b/internal/runtime/z_iface.go @@ -20,6 +20,7 @@ import ( "unsafe" "github.com/goplus/llgo/internal/abi" + "github.com/goplus/llgo/internal/runtime/c" ) // ----------------------------------------------------------------------------- @@ -35,29 +36,35 @@ var ( type Interface = iface func MakeAnyInt(typ *Type, data uintptr) Interface { + tab := &itab{inter: TyAny, _type: typ, hash: 0, fun: [1]uintptr{0}} return Interface{ - tab: &itab{inter: TyAny, _type: typ, hash: 0, fun: [1]uintptr{0}}, + tab: tab, data: unsafe.Pointer(data), } } func MakeAnyString(data string) Interface { + typ := Basic(abi.String) + tab := &itab{inter: TyAny, _type: typ, hash: 0, fun: [1]uintptr{0}} + c.Printf(c.Str("MakeAnyString(%p): %d, %d\n"), typ, int(typ.Kind_), abi.String) return Interface{ - tab: &itab{inter: TyAny, _type: Basic(abi.String), hash: 0, fun: [1]uintptr{0}}, + tab: tab, data: unsafe.Pointer(&data), } } func MakeAny(typ *Type, data unsafe.Pointer) Interface { + tab := &itab{inter: TyAny, _type: typ, hash: 0, fun: [1]uintptr{0}} return Interface{ - tab: &itab{inter: TyAny, _type: typ, hash: 0, fun: [1]uintptr{0}}, + tab: tab, data: data, } } func MakeInterface(inter *InterfaceType, typ *Type, data unsafe.Pointer) Interface { + tab := &itab{inter: inter, _type: typ, hash: 0, fun: [1]uintptr{0}} return Interface{ - tab: &itab{inter: inter, _type: typ, hash: 0, fun: [1]uintptr{0}}, + tab: tab, data: data, } } diff --git a/internal/runtime/z_type.go b/internal/runtime/z_type.go index 85ee1b66..349396ae 100644 --- a/internal/runtime/z_type.go +++ b/internal/runtime/z_type.go @@ -20,6 +20,7 @@ import ( "unsafe" "github.com/goplus/llgo/internal/abi" + "github.com/goplus/llgo/internal/runtime/c" ) // ----------------------------------------------------------------------------- @@ -28,7 +29,10 @@ type Kind = abi.Kind type Type = abi.Type func Basic(kind Kind) *Type { - return basicTypes[kind] + ret := basicTypes[kind] + c.Printf(c.Str("Basic: %p, %d, %d, %d, %d\n"), + ret, c.Int(ret.Hash), c.Int(ret.Kind_), c.Int(kind), c.Int(ret.Size_)) + return ret } var ( @@ -76,10 +80,14 @@ var ( ) func basicType(kind abi.Kind) *Type { - return &abi.Type{ + ret := &Type{ Size_: sizeBasicTypes[kind], + Hash: uint32(kind), Kind_: uint8(kind), } + c.Printf(c.Str("basicType: %p, %d, %d, %d, %d\n"), + ret, c.Int(ret.Hash), c.Int(ret.Kind_), c.Int(kind), c.Int(ret.Size_)) + return ret } // ----------------------------------------------------------------------------- diff --git a/ssa/stmt_builder.go b/ssa/stmt_builder.go index 47e50c9d..5d0e75b7 100644 --- a/ssa/stmt_builder.go +++ b/ssa/stmt_builder.go @@ -73,7 +73,9 @@ func (b Builder) Panic(v Expr) { if debugInstr { log.Printf("Panic %v\n", v.impl) } - b.impl.CreateUnreachable() // TODO(xsw): pass v + pkg := b.fn.pkg + b.Call(pkg.rtFunc("TracePanic"), v) + b.impl.CreateUnreachable() } // Unreachable emits an unreachable instruction.