llgo/ssa: phi refactor
This commit is contained in:
16
cl/_testgo/abiname/in.go
Normal file
16
cl/_testgo/abiname/in.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package main
|
||||
|
||||
import "github.com/goplus/llgo/internal/abi"
|
||||
|
||||
// NewPkgName creates a package name.
|
||||
func NewPkgName(pkgPath string) (ret abi.Name) {
|
||||
if len(pkgPath) > 0 {
|
||||
ret = abi.NewName(pkgPath, "", false, false)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func main() {
|
||||
n := NewPkgName("pkgPath")
|
||||
println(n.Name(), n.Tag(), n.IsExported(), n.IsEmbedded(), n.IsBlank())
|
||||
}
|
||||
99
cl/_testgo/abiname/out.ll
Normal file
99
cl/_testgo/abiname/out.ll
Normal file
@@ -0,0 +1,99 @@
|
||||
; ModuleID = 'main'
|
||||
source_filename = "main"
|
||||
|
||||
%"github.com/goplus/llgo/internal/abi.Name" = type { ptr }
|
||||
%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 }
|
||||
|
||||
@"main.init$guard" = global ptr null
|
||||
@0 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
|
||||
@__llgo_argc = global ptr null
|
||||
@__llgo_argv = global ptr null
|
||||
@1 = private unnamed_addr constant [8 x i8] c"pkgPath\00", align 1
|
||||
|
||||
define %"github.com/goplus/llgo/internal/abi.Name" @main.NewPkgName(%"github.com/goplus/llgo/internal/runtime.String" %0) {
|
||||
_llgo_0:
|
||||
%1 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %0, 1
|
||||
%2 = icmp sgt i64 %1, 0
|
||||
br i1 %2, label %_llgo_1, label %_llgo_2
|
||||
|
||||
_llgo_1: ; preds = %_llgo_0
|
||||
%3 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||
%4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %3, i32 0, i32 0
|
||||
store ptr @0, ptr %4, align 8
|
||||
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %3, i32 0, i32 1
|
||||
store i64 0, ptr %5, align 4
|
||||
%6 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %3, align 8
|
||||
%7 = call %"github.com/goplus/llgo/internal/abi.Name" @"github.com/goplus/llgo/internal/abi.NewName"(%"github.com/goplus/llgo/internal/runtime.String" %0, %"github.com/goplus/llgo/internal/runtime.String" %6, i1 false, i1 false)
|
||||
br label %_llgo_2
|
||||
|
||||
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||
%8 = phi ptr [ zeroinitializer, %_llgo_0 ], [ %7, %_llgo_1 ]
|
||||
ret ptr %8
|
||||
}
|
||||
|
||||
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"()
|
||||
br label %_llgo_2
|
||||
|
||||
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||
ret void
|
||||
}
|
||||
|
||||
define i32 @main(i32 %0, ptr %1) {
|
||||
_llgo_0:
|
||||
store i32 %0, ptr @__llgo_argc, align 4
|
||||
store ptr %1, ptr @__llgo_argv, align 8
|
||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||
call void @main.init()
|
||||
%2 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %2, i32 0, i32 0
|
||||
store ptr @1, ptr %3, align 8
|
||||
%4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %2, i32 0, i32 1
|
||||
store i64 7, ptr %4, align 4
|
||||
%5 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %2, align 8
|
||||
%6 = call %"github.com/goplus/llgo/internal/abi.Name" @main.NewPkgName(%"github.com/goplus/llgo/internal/runtime.String" %5)
|
||||
%7 = call %"github.com/goplus/llgo/internal/runtime.String" @"(github.com/goplus/llgo/internal/abi.Name).Name"(%"github.com/goplus/llgo/internal/abi.Name" %6)
|
||||
%8 = call %"github.com/goplus/llgo/internal/runtime.String" @"(github.com/goplus/llgo/internal/abi.Name).Tag"(%"github.com/goplus/llgo/internal/abi.Name" %6)
|
||||
%9 = call i1 @"(github.com/goplus/llgo/internal/abi.Name).IsExported"(%"github.com/goplus/llgo/internal/abi.Name" %6)
|
||||
%10 = call i1 @"(github.com/goplus/llgo/internal/abi.Name).IsEmbedded"(%"github.com/goplus/llgo/internal/abi.Name" %6)
|
||||
%11 = call i1 @"(github.com/goplus/llgo/internal/abi.Name).IsBlank"(%"github.com/goplus/llgo/internal/abi.Name" %6)
|
||||
call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %7)
|
||||
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32)
|
||||
call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %8)
|
||||
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32)
|
||||
call void @"github.com/goplus/llgo/internal/runtime.PrintBool"(i1 %9)
|
||||
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32)
|
||||
call void @"github.com/goplus/llgo/internal/runtime.PrintBool"(i1 %10)
|
||||
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32)
|
||||
call void @"github.com/goplus/llgo/internal/runtime.PrintBool"(i1 %11)
|
||||
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10)
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
declare %"github.com/goplus/llgo/internal/abi.Name" @"github.com/goplus/llgo/internal/abi.NewName"(%"github.com/goplus/llgo/internal/runtime.String", %"github.com/goplus/llgo/internal/runtime.String", i1, i1)
|
||||
|
||||
declare void @"github.com/goplus/llgo/internal/abi.init"()
|
||||
|
||||
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||
|
||||
declare %"github.com/goplus/llgo/internal/runtime.String" @"(github.com/goplus/llgo/internal/abi.Name).Name"(%"github.com/goplus/llgo/internal/abi.Name")
|
||||
|
||||
declare %"github.com/goplus/llgo/internal/runtime.String" @"(github.com/goplus/llgo/internal/abi.Name).Tag"(%"github.com/goplus/llgo/internal/abi.Name")
|
||||
|
||||
declare i1 @"(github.com/goplus/llgo/internal/abi.Name).IsExported"(%"github.com/goplus/llgo/internal/abi.Name")
|
||||
|
||||
declare i1 @"(github.com/goplus/llgo/internal/abi.Name).IsEmbedded"(%"github.com/goplus/llgo/internal/abi.Name")
|
||||
|
||||
declare i1 @"(github.com/goplus/llgo/internal/abi.Name).IsBlank"(%"github.com/goplus/llgo/internal/abi.Name")
|
||||
|
||||
declare void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String")
|
||||
|
||||
declare void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8)
|
||||
|
||||
declare void @"github.com/goplus/llgo/internal/runtime.PrintBool"(i1)
|
||||
@@ -522,7 +522,7 @@ func (p *context) compilePhis(b llssa.Builder, block *ssa.BasicBlock) int {
|
||||
}
|
||||
for i := 0; i < n; i++ {
|
||||
iv := block.Instrs[i].(*ssa.Phi)
|
||||
p.bvals[iv] = rets[i].Do(b)
|
||||
p.bvals[iv] = rets[i]
|
||||
}
|
||||
return n
|
||||
}
|
||||
@@ -784,7 +784,7 @@ func (p *context) compileInstr(b llssa.Builder, instr ssa.Instruction) {
|
||||
val := p.compileValue(b, v.Value)
|
||||
b.MapUpdate(m, key, val)
|
||||
case *ssa.Panic:
|
||||
arg := p.compileValue(b, v.X).Do(b)
|
||||
arg := p.compileValue(b, v.X)
|
||||
b.Panic(arg)
|
||||
default:
|
||||
panic(fmt.Sprintf("compileInstr: unknown instr - %T\n", instr))
|
||||
@@ -856,7 +856,7 @@ func (p *context) compileValues(b llssa.Builder, vals []ssa.Value, hasVArg int)
|
||||
n := len(vals) - hasVArg
|
||||
ret := make([]llssa.Expr, n)
|
||||
for i := 0; i < n; i++ {
|
||||
ret[i] = p.compileValue(b, vals[i]).Do(b)
|
||||
ret[i] = p.compileValue(b, vals[i])
|
||||
}
|
||||
if hasVArg > 0 {
|
||||
ret = p.compileVArg(ret, b, vals[n])
|
||||
|
||||
Binary file not shown.
BIN
internal/runtime/llgo_autogen.lla
Normal file
BIN
internal/runtime/llgo_autogen.lla
Normal file
Binary file not shown.
@@ -26,7 +26,7 @@ import (
|
||||
)
|
||||
|
||||
func TestFromTestgo(t *testing.T) {
|
||||
cltest.FromDir(t, "", "../cl/_testgo", false)
|
||||
cltest.FromDir(t, "abiname", "../cl/_testgo", false)
|
||||
}
|
||||
|
||||
func TestFromTestpy(t *testing.T) {
|
||||
|
||||
118
ssa/expr.go
118
ssa/expr.go
@@ -41,16 +41,6 @@ func (v Expr) IsNil() bool {
|
||||
return v.Type == nil
|
||||
}
|
||||
|
||||
// Do evaluates the delay expression and returns the result.
|
||||
func (v Expr) Do(b Builder) Expr { // TODO(xsw): can we remove this method?
|
||||
switch vt := v.Type; vt.kind {
|
||||
case vkPhisExpr:
|
||||
e := vt.raw.Type.(*phisExprTy)
|
||||
return b.aggregateValue(e.Type, e.phis...)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
type pyVarTy struct {
|
||||
@@ -73,26 +63,6 @@ func pyVarExpr(mod Expr, name string) Expr {
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
type phisExprTy struct {
|
||||
phis []llvm.Value
|
||||
Type
|
||||
}
|
||||
|
||||
func (p phisExprTy) Underlying() types.Type {
|
||||
panic("don't call")
|
||||
}
|
||||
|
||||
func (p phisExprTy) String() string {
|
||||
return "phisExpr"
|
||||
}
|
||||
|
||||
func phisExpr(t Type, phis []llvm.Value) Expr {
|
||||
tphi := &aType{raw: rawType{&phisExprTy{phis, t}}, kind: vkPhisExpr}
|
||||
return Expr{Type: tphi}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
func (p Program) Zero(t Type) Expr {
|
||||
var ret llvm.Value
|
||||
switch u := t.raw.Type.Underlying().(type) {
|
||||
@@ -533,14 +503,6 @@ func llvmFields(vals []Expr, t *types.Struct, b Builder) (ret []llvm.Value) {
|
||||
return
|
||||
}
|
||||
|
||||
func llvmDelayValues(f func(i int) Expr, n int) []llvm.Value {
|
||||
ret := make([]llvm.Value, n)
|
||||
for i := 0; i < n; i++ {
|
||||
ret[i] = f(i).impl
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func llvmPredBlocks(preds []BasicBlock) []llvm.BasicBlock {
|
||||
ret := make([]llvm.BasicBlock, len(preds))
|
||||
for i, v := range preds {
|
||||
@@ -549,21 +511,24 @@ func llvmPredBlocks(preds []BasicBlock) []llvm.BasicBlock {
|
||||
return ret
|
||||
}
|
||||
|
||||
// Phi represents a phi node.
|
||||
type Phi struct {
|
||||
type aPhi struct {
|
||||
Expr
|
||||
phis []llvm.Value
|
||||
}
|
||||
|
||||
// Phi represents a phi node.
|
||||
type Phi = *aPhi
|
||||
|
||||
func (b Builder) newPhi(t Type, phis []llvm.Value) Phi {
|
||||
ret := b.aggregateValue(t, phis...)
|
||||
return &aPhi{ret, phis}
|
||||
}
|
||||
|
||||
// AddIncoming adds incoming values to a phi node.
|
||||
func (p Phi) AddIncoming(b Builder, preds []BasicBlock, f func(i int) Expr) {
|
||||
bs := llvmPredBlocks(preds)
|
||||
if p.kind != vkPhisExpr { // normal phi node
|
||||
vs := llvmDelayValues(f, len(preds))
|
||||
p.impl.AddIncoming(vs, bs)
|
||||
return
|
||||
}
|
||||
e := p.raw.Type.(*phisExprTy)
|
||||
phis := e.phis
|
||||
phis := p.phis
|
||||
if phis != nil {
|
||||
vals := make([][]llvm.Value, len(phis))
|
||||
for iblk, blk := range preds {
|
||||
last := blk.last.LastInstruction()
|
||||
@@ -580,6 +545,15 @@ func (p Phi) AddIncoming(b Builder, preds []BasicBlock, f func(i int) Expr) {
|
||||
for i, phi := range phis {
|
||||
phi.AddIncoming(vals[i], bs)
|
||||
}
|
||||
} else {
|
||||
vals := make([]llvm.Value, len(preds))
|
||||
for iblk, blk := range preds {
|
||||
last := blk.last.LastInstruction()
|
||||
b.impl.SetInsertPointBefore(last)
|
||||
vals[iblk] = f(iblk).impl
|
||||
}
|
||||
p.impl.AddIncoming(vals, bs)
|
||||
}
|
||||
}
|
||||
|
||||
// Phi returns a phi node.
|
||||
@@ -590,17 +564,55 @@ func (b Builder) Phi(t Type) Phi {
|
||||
kind := tund.Kind()
|
||||
switch kind {
|
||||
case types.String:
|
||||
prog := b.Prog
|
||||
phis := make([]llvm.Value, 2)
|
||||
phis[0] = llvm.CreatePHI(impl, prog.tyVoidPtr())
|
||||
phis[1] = llvm.CreatePHI(impl, prog.tyInt())
|
||||
return Phi{phisExpr(t, phis)}
|
||||
phis := createStringPhis(impl, make([]llvm.Value, 0, 2), b.Prog)
|
||||
return b.newPhi(t, phis)
|
||||
}
|
||||
case *types.Struct:
|
||||
phis := createStrucPhis(impl, nil, tund, b.Prog)
|
||||
return b.newPhi(t, phis)
|
||||
default:
|
||||
panic("todo")
|
||||
}
|
||||
phi := llvm.CreatePHI(impl, t.ll)
|
||||
return Phi{Expr{phi, t}}
|
||||
return &aPhi{Expr{phi, t}, nil}
|
||||
}
|
||||
|
||||
func createStringPhis(b llvm.Builder, phis []llvm.Value, prog Program) []llvm.Value {
|
||||
phis = append(phis, llvm.CreatePHI(b, prog.tyVoidPtr()))
|
||||
return append(phis, llvm.CreatePHI(b, prog.tyInt()))
|
||||
}
|
||||
|
||||
func createStrucPhis(b llvm.Builder, phis []llvm.Value, t *types.Struct, prog Program) []llvm.Value {
|
||||
n := t.NumFields()
|
||||
if phis == nil {
|
||||
phis = make([]llvm.Value, 0, n)
|
||||
}
|
||||
for i := 0; i < n; i++ {
|
||||
fld := t.Field(i)
|
||||
switch tfld := fld.Type().Underlying().(type) {
|
||||
case *types.Basic:
|
||||
kind := tfld.Kind()
|
||||
switch kind {
|
||||
case types.String:
|
||||
phis = createStringPhis(b, phis, prog)
|
||||
default:
|
||||
phis = createBasicPhi(b, phis, tfld, prog)
|
||||
}
|
||||
case *types.Pointer:
|
||||
phis = createBasicPhi(b, phis, tfld, prog)
|
||||
case *types.Struct:
|
||||
phis = createStrucPhis(b, phis, tfld, prog)
|
||||
default:
|
||||
panic("todo")
|
||||
}
|
||||
}
|
||||
return phis
|
||||
}
|
||||
|
||||
func createBasicPhi(b llvm.Builder, phis []llvm.Value, t types.Type, prog Program) []llvm.Value {
|
||||
tll := prog.rawType(t).ll
|
||||
phi := llvm.CreatePHI(b, tll)
|
||||
return append(phis, phi)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -109,9 +109,7 @@ func TestCvtType(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUserdefExpr(t *testing.T) {
|
||||
b := &phisExprTy{}
|
||||
c := &pyVarTy{}
|
||||
_ = b.String()
|
||||
_ = c.String()
|
||||
test := func(a types.Type) {
|
||||
defer func() {
|
||||
@@ -121,7 +119,6 @@ func TestUserdefExpr(t *testing.T) {
|
||||
}()
|
||||
a.Underlying()
|
||||
}
|
||||
test(b)
|
||||
test(c)
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,6 @@ const (
|
||||
vkEface
|
||||
vkIface
|
||||
vkStruct
|
||||
vkPhisExpr = -1
|
||||
)
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user