From 2cc1bdee19a562b307b04ab1de71d30b0a9e478b Mon Sep 17 00:00:00 2001 From: xushiwei Date: Sun, 28 Apr 2024 12:09:47 +0800 Subject: [PATCH] llgo/ssa: pkg.NewFunc bugfix --- cl/_testcgo/struct/in.go | 2 +- cl/_testcgo/struct/out.ll | 27 +++++++++++++++++++-------- cl/_testcgo/typalias/out.ll | 4 +++- cl/cltest/cltest.go | 13 ++++++++++++- cl/compile_test.go | 6 ++++++ internal/llgen/llgenf.go | 8 ++++---- internal/runtime/iface.go | 5 ----- internal/runtime/slice.go | 15 --------------- internal/runtime/z_slice.go | 10 +++++++++- ssa/package.go | 20 +++++++------------- ssa/stmt_builder.go | 2 +- ssa/type.go | 5 +++-- 12 files changed, 65 insertions(+), 52 deletions(-) delete mode 100644 internal/runtime/iface.go delete mode 100644 internal/runtime/slice.go diff --git a/cl/_testcgo/struct/in.go b/cl/_testcgo/struct/in.go index 74aad81a..71cdeb09 100644 --- a/cl/_testcgo/struct/in.go +++ b/cl/_testcgo/struct/in.go @@ -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) } diff --git a/cl/_testcgo/struct/out.ll b/cl/_testcgo/struct/out.ll index 5142a659..002f5000 100644 --- a/cl/_testcgo/struct/out.ll +++ b/cl/_testcgo/struct/out.ll @@ -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 } diff --git a/cl/_testcgo/typalias/out.ll b/cl/_testcgo/typalias/out.ll index dac39a22..3e2d16f8 100644 --- a/cl/_testcgo/typalias/out.ll +++ b/cl/_testcgo/typalias/out.ll @@ -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) diff --git a/cl/cltest/cltest.go b/cl/cltest/cltest.go index bc6900e8..8ef858f1 100644 --- a/cl/cltest/cltest.go +++ b/cl/cltest/cltest.go @@ -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 { diff --git a/cl/compile_test.go b/cl/compile_test.go index 671f8cba..1acd3786 100644 --- a/cl/compile_test.go +++ b/cl/compile_test.go @@ -35,6 +35,12 @@ 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 diff --git a/internal/llgen/llgenf.go b/internal/llgen/llgenf.go index 203ed23e..b8bc71cb 100644 --- a/internal/llgen/llgenf.go +++ b/internal/llgen/llgenf.go @@ -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) } diff --git a/internal/runtime/iface.go b/internal/runtime/iface.go deleted file mode 100644 index 47bf8fc2..00000000 --- a/internal/runtime/iface.go +++ /dev/null @@ -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 diff --git a/internal/runtime/slice.go b/internal/runtime/slice.go deleted file mode 100644 index 21caa126..00000000 --- a/internal/runtime/slice.go +++ /dev/null @@ -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 -} diff --git a/internal/runtime/z_slice.go b/internal/runtime/z_slice.go index a3f59f6d..4a8e0e40 100644 --- a/internal/runtime/z_slice.go +++ b/internal/runtime/z_slice.go @@ -16,8 +16,16 @@ package runtime +import ( + "unsafe" +) + // Slice is the runtime representation of a slice. -type Slice = slice +type Slice struct { + array unsafe.Pointer + len int + cap int +} // NilSlice returns a nil slice. func NilSlice() Slice { diff --git a/ssa/package.go b/ssa/package.go index edddc5c6..55c09666 100644 --- a/ssa/package.go +++ b/ssa/package.go @@ -187,7 +187,7 @@ func (p Program) NewPackage(name, pkgPath string) Package { // mod.Finalize() fns := make(map[string]Function) gbls := make(map[string]Global) - return &aPackage{mod, fns, gbls, p, nil} + return &aPackage{mod, fns, gbls, p} } // Void returns void type. @@ -267,8 +267,6 @@ type aPackage struct { fns map[string]Function vars map[string]Global prog Program - - abort Function } type Package = *aPackage @@ -294,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) @@ -306,21 +307,14 @@ func (p Package) FuncOf(name string) Function { return p.fns[name] } -func (p Package) rtAbort() Function { - if p.abort == nil { - p.abort = p.NewFunc("abort", types.NewSignatureType(nil, nil, nil, nil, nil, false)) - } - return p.abort +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 } // ----------------------------------------------------------------------------- diff --git a/ssa/stmt_builder.go b/ssa/stmt_builder.go index 9b165cfb..d3a922d5 100644 --- a/ssa/stmt_builder.go +++ b/ssa/stmt_builder.go @@ -74,7 +74,7 @@ func (b Builder) Panic(v Expr) { log.Printf("Panic %v\n", v.impl) } pkg := b.fn.pkg - b.Call(pkg.rtAbort().Expr) + b.Call(pkg.rtAbort()) // TODO(xsw): pass v } // Return emits a return instruction. diff --git a/ssa/type.go b/ssa/type.go index fed294c7..f265d215 100644 --- a/ssa/type.go +++ b/ssa/type.go @@ -123,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) } @@ -253,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}