llgo/ssa: pkg.NewFunc bugfix
This commit is contained in:
@@ -13,7 +13,7 @@ type Foo struct {
|
|||||||
|
|
||||||
var format = [...]int8{'H', 'e', 'l', 'l', 'o', ' ', '%', 'd', '\n', 0}
|
var format = [...]int8{'H', 'e', 'l', 'l', 'o', ' ', '%', 'd', '\n', 0}
|
||||||
|
|
||||||
func (p *Foo) Print() {
|
func (p Foo) Print() {
|
||||||
if p.ok {
|
if p.ok {
|
||||||
printf(&format[0], p.A)
|
printf(&format[0], p.A)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,22 +6,32 @@ source_filename = "main"
|
|||||||
@main.format = global ptr null
|
@main.format = global ptr null
|
||||||
@"main.init$guard" = 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:
|
_llgo_0:
|
||||||
%1 = getelementptr inbounds %main.Foo, ptr %0, i32 0, i32 1
|
%1 = alloca %main.Foo, align 8
|
||||||
%2 = load i1, ptr %1, align 1
|
store %main.Foo %0, ptr %1, align 4
|
||||||
br i1 %2, label %_llgo_1, label %_llgo_2
|
%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
|
_llgo_1: ; preds = %_llgo_0
|
||||||
%3 = getelementptr inbounds %main.Foo, ptr %0, i32 0, i32 0
|
%4 = alloca %main.Foo, align 8
|
||||||
%4 = load i32, ptr %3, align 4
|
%5 = getelementptr inbounds %main.Foo, ptr %4, i32 0, i32 0
|
||||||
call void (ptr, ...) @printf(ptr @main.format, i32 %4)
|
%6 = load i32, ptr %5, align 4
|
||||||
|
call void (ptr, ...) @printf(ptr @main.format, i32 %6)
|
||||||
br label %_llgo_2
|
br label %_llgo_2
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
ret void
|
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() {
|
define void @main.init() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%0 = load i1, ptr @"main.init$guard", align 1
|
%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
|
%2 = getelementptr inbounds %main.Foo, ptr %0, i32 0, i32 1
|
||||||
store i32 100, ptr %1, align 4
|
store i32 100, ptr %1, align 4
|
||||||
store i1 true, ptr %2, align 1
|
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
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
define void @main() {
|
define void @main() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
call void @main.init()
|
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
|
%1 = getelementptr inbounds { i32, i1 }, ptr %0, i32 0, i32 0
|
||||||
%2 = getelementptr inbounds { i32, i1 }, ptr %0, i32 0, i32 1
|
%2 = getelementptr inbounds { i32, i1 }, ptr %0, i32 0, i32 1
|
||||||
store i32 100, ptr %1, align 4
|
store i32 100, ptr %1, align 4
|
||||||
@@ -56,3 +56,5 @@ _llgo_0:
|
|||||||
}
|
}
|
||||||
|
|
||||||
declare void @printf(ptr, ...)
|
declare void @printf(ptr, ...)
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64)
|
||||||
|
|||||||
@@ -63,6 +63,17 @@ func FromDir(t *testing.T, sel, relDir string, byLLGen bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Pkg(t *testing.T, pkgPath, outFile string) {
|
||||||
|
b, err := os.ReadFile(outFile)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("ReadFile failed:", err)
|
||||||
|
}
|
||||||
|
expected := string(b)
|
||||||
|
if v := llgen.GenFrom(pkgPath); v != expected {
|
||||||
|
t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func testFrom(t *testing.T, pkgDir, sel string, byLLGen bool) {
|
func testFrom(t *testing.T, pkgDir, sel string, byLLGen bool) {
|
||||||
if sel != "" && !strings.Contains(pkgDir, sel) {
|
if sel != "" && !strings.Contains(pkgDir, sel) {
|
||||||
return
|
return
|
||||||
@@ -76,7 +87,7 @@ func testFrom(t *testing.T, pkgDir, sel string, byLLGen bool) {
|
|||||||
}
|
}
|
||||||
expected := string(b)
|
expected := string(b)
|
||||||
if byLLGen {
|
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)
|
t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -35,6 +35,12 @@ func TestFromTestdata(t *testing.T) {
|
|||||||
cltest.FromDir(t, "", "./_testdata", false)
|
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) {
|
func TestVar(t *testing.T) {
|
||||||
testCompile(t, `package foo
|
testCompile(t, `package foo
|
||||||
|
|
||||||
|
|||||||
@@ -35,11 +35,11 @@ const (
|
|||||||
loadSyntax = loadTypes | packages.NeedSyntax | packages.NeedTypesInfo
|
loadSyntax = loadTypes | packages.NeedSyntax | packages.NeedTypesInfo
|
||||||
)
|
)
|
||||||
|
|
||||||
func GenFromFile(inFile string) string {
|
func GenFrom(fileOrPkg string) string {
|
||||||
cfg := &packages.Config{
|
cfg := &packages.Config{
|
||||||
Mode: loadSyntax,
|
Mode: loadSyntax,
|
||||||
}
|
}
|
||||||
initial, err := packages.Load(cfg, inFile)
|
initial, err := packages.Load(cfg, fileOrPkg)
|
||||||
check(err)
|
check(err)
|
||||||
|
|
||||||
_, pkgs := ssautil.AllPackages(initial, ssa.SanityCheckFunctions)
|
_, pkgs := ssautil.AllPackages(initial, ssa.SanityCheckFunctions)
|
||||||
@@ -61,8 +61,8 @@ func GenFromFile(inFile string) string {
|
|||||||
return ret.String()
|
return ret.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func DoFile(inFile, outFile string) {
|
func DoFile(fileOrPkg, outFile string) {
|
||||||
ret := GenFromFile(inFile)
|
ret := GenFrom(fileOrPkg)
|
||||||
err := os.WriteFile(outFile, []byte(ret), 0644)
|
err := os.WriteFile(outFile, []byte(ret), 0644)
|
||||||
check(err)
|
check(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package runtime
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -16,8 +16,16 @@
|
|||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
// Slice is the runtime representation of a slice.
|
// 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.
|
// NilSlice returns a nil slice.
|
||||||
func NilSlice() Slice {
|
func NilSlice() Slice {
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ func (p Program) NewPackage(name, pkgPath string) Package {
|
|||||||
// mod.Finalize()
|
// mod.Finalize()
|
||||||
fns := make(map[string]Function)
|
fns := make(map[string]Function)
|
||||||
gbls := make(map[string]Global)
|
gbls := make(map[string]Global)
|
||||||
return &aPackage{mod, fns, gbls, p, nil}
|
return &aPackage{mod, fns, gbls, p}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Void returns void type.
|
// Void returns void type.
|
||||||
@@ -267,8 +267,6 @@ type aPackage struct {
|
|||||||
fns map[string]Function
|
fns map[string]Function
|
||||||
vars map[string]Global
|
vars map[string]Global
|
||||||
prog Program
|
prog Program
|
||||||
|
|
||||||
abort Function
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Package = *aPackage
|
type Package = *aPackage
|
||||||
@@ -294,6 +292,9 @@ func (p Package) VarOf(name string) Global {
|
|||||||
|
|
||||||
// NewFunc creates a new function.
|
// NewFunc creates a new function.
|
||||||
func (p Package) NewFunc(name string, sig *types.Signature) 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)
|
t := p.prog.llvmSignature(sig)
|
||||||
fn := llvm.AddFunction(p.mod, name, t.ll)
|
fn := llvm.AddFunction(p.mod, name, t.ll)
|
||||||
ret := newFunction(fn, t, p, p.prog)
|
ret := newFunction(fn, t, p, p.prog)
|
||||||
@@ -306,21 +307,14 @@ func (p Package) FuncOf(name string) Function {
|
|||||||
return p.fns[name]
|
return p.fns[name]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Package) rtAbort() Function {
|
func (p Package) rtAbort() Expr {
|
||||||
if p.abort == nil {
|
return p.NewFunc("abort", types.NewSignatureType(nil, nil, nil, nil, nil, false)).Expr
|
||||||
p.abort = p.NewFunc("abort", types.NewSignatureType(nil, nil, nil, nil, nil, false))
|
|
||||||
}
|
|
||||||
return p.abort
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Package) rtFunc(fnName string) Expr {
|
func (p Package) rtFunc(fnName string) Expr {
|
||||||
fn := p.prog.runtime().Lookup(fnName).(*types.Func)
|
fn := p.prog.runtime().Lookup(fnName).(*types.Func)
|
||||||
name := FullName(fn.Pkg(), fnName)
|
name := FullName(fn.Pkg(), fnName)
|
||||||
v, ok := p.fns[name]
|
return p.NewFunc(name, fn.Type().(*types.Signature)).Expr
|
||||||
if !ok {
|
|
||||||
v = p.NewFunc(name, fn.Type().(*types.Signature))
|
|
||||||
}
|
|
||||||
return v.Expr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ func (b Builder) Panic(v Expr) {
|
|||||||
log.Printf("Panic %v\n", v.impl)
|
log.Printf("Panic %v\n", v.impl)
|
||||||
}
|
}
|
||||||
pkg := b.fn.pkg
|
pkg := b.fn.pkg
|
||||||
b.Call(pkg.rtAbort().Expr)
|
b.Call(pkg.rtAbort()) // TODO(xsw): pass v
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return emits a return instruction.
|
// Return emits a return instruction.
|
||||||
|
|||||||
@@ -123,6 +123,9 @@ func (p Program) Field(typ Type, i int) Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) Type(typ types.Type) 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 {
|
if v := p.typs.At(typ); v != nil {
|
||||||
return v.(Type)
|
return v.(Type)
|
||||||
}
|
}
|
||||||
@@ -253,8 +256,6 @@ func (p Program) toLLVMType(typ types.Type) Type {
|
|||||||
return p.toLLVMStruct(t)
|
return p.toLLVMStruct(t)
|
||||||
case *types.Named:
|
case *types.Named:
|
||||||
return p.toLLVMNamed(t)
|
return p.toLLVMNamed(t)
|
||||||
case *types.Signature:
|
|
||||||
return p.toLLVMFunc(t)
|
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
elem := p.Type(t.Elem())
|
elem := p.Type(t.Elem())
|
||||||
return &aType{llvm.ArrayType(elem.ll, int(t.Len())), typ, vkInvalid}
|
return &aType{llvm.ArrayType(elem.ll, int(t.Len())), typ, vkInvalid}
|
||||||
|
|||||||
Reference in New Issue
Block a user