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/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/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/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..046910e5 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" @@ -66,3 +68,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/llgo_autogen.ll b/internal/runtime/llgo_autogen.ll index dfd13bdd..4af3bc58 100644 --- a/internal/runtime/llgo_autogen.ll +++ b/internal/runtime/llgo_autogen.ll @@ -13,6 +13,9 @@ source_filename = "github.com/goplus/llgo/internal/runtime" @"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 +@1 = private unnamed_addr constant [19 x i8] c"MakeAnyString(%p)\0A\00", align 1 +@2 = private unnamed_addr constant [11 x i8] c"Panic(%p)\0A\00", align 1 +@3 = private unnamed_addr constant [11 x i8] c"panic: %s\0A\00", align 1 define ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 %0) { _llgo_0: @@ -108,51 +111,52 @@ _llgo_1: ; preds = %_llgo_0 _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) %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 +164,46 @@ 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 = call i32 (ptr, ...) @printf(ptr @1, ptr %2) + %11 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8 + %12 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %11, i32 0, i32 0 + %13 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %11, i32 0, i32 1 + store ptr %3, ptr %12, align 8 + store ptr %1, ptr %13, align 8 + %14 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %11, align 8 + ret %"github.com/goplus/llgo/internal/runtime.iface" %14 } 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,6 +286,41 @@ _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 = call i32 (ptr, ...) @printf(ptr @2, ptr %5) + %7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %1, i32 0, i32 0 + %8 = load ptr, ptr %7, align 8 + %9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %8, i32 0, i32 1 + %10 = load ptr, ptr %9, align 8 + %11 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %10, i32 0, i32 6 + %12 = load i8, ptr %11, align 1 + %13 = sext i8 %12 to i64 + %14 = icmp eq i64 %13, 24 + br i1 %14, label %_llgo_2, label %_llgo_1 + +_llgo_1: ; preds = %_llgo_2, %_llgo_0 + ret void + +_llgo_2: ; preds = %_llgo_0 + %15 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %1, i32 0, i32 1 + %16 = load ptr, ptr %15, align 8 + %17 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %16, i32 0, i32 1 + %18 = load i64, ptr %17, align 4 + %19 = add i64 %18, 1 + %20 = alloca i8, i64 %19, align 1 + %21 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %16, align 8 + %22 = call ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr %20, %"github.com/goplus/llgo/internal/runtime.String" %21) + %23 = call i32 (ptr, ...) @printf(ptr @3, ptr %22) + 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) @@ -386,6 +426,8 @@ declare ptr @malloc(i64) declare ptr @memcpy(ptr, ptr, i64) +declare i32 @printf(ptr, ...) + declare i32 @rand() declare void @"github.com/goplus/llgo/internal/abi.init"() diff --git a/internal/runtime/z_c.go b/internal/runtime/z_c.go index 6cca5b99..46de4e6a 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) { + c.Printf(c.Str("Panic(%p)\n"), v.tab._type) kind := abi.Kind(v.tab._type.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..c926c3f4 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)\n"), typ) 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/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.