llgo/ssa: pkg.NewFunc bugfix

This commit is contained in:
xushiwei
2024-04-28 12:09:47 +08:00
parent eb4146d80d
commit 2cc1bdee19
12 changed files with 65 additions and 52 deletions

View File

@@ -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)
}

View File

@@ -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
}

View File

@@ -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)

View File

@@ -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 {

View File

@@ -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

View File

@@ -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)
}

View File

@@ -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

View File

@@ -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
}

View File

@@ -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 {

View File

@@ -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
}
// -----------------------------------------------------------------------------

View File

@@ -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.

View File

@@ -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}