llgo/ssa: PhisExpr
This commit is contained in:
@@ -400,7 +400,7 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
|
|||||||
for i, pred := range preds {
|
for i, pred := range preds {
|
||||||
bblks[i] = p.fn.Block(pred.Index)
|
bblks[i] = p.fn.Block(pred.Index)
|
||||||
}
|
}
|
||||||
phi.AddIncoming(vals, bblks)
|
phi.AddIncoming(b, vals, bblks)
|
||||||
})
|
})
|
||||||
case *ssa.ChangeType:
|
case *ssa.ChangeType:
|
||||||
t := v.Type()
|
t := v.Type()
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ func testCompile(t *testing.T, src, expected string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFromTestrt(t *testing.T) {
|
func TestFromTestrt(t *testing.T) {
|
||||||
cltest.FromDir(t, "", "./_testrt", true)
|
cltest.FromDir(t, "concat", "./_testrt", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFromTestdata(t *testing.T) {
|
func TestFromTestdata(t *testing.T) {
|
||||||
|
|||||||
65
ssa/expr.go
65
ssa/expr.go
@@ -50,12 +50,17 @@ func (v Expr) TypeOf() types.Type {
|
|||||||
|
|
||||||
// Do evaluates the delay expression and returns the result.
|
// Do evaluates the delay expression and returns the result.
|
||||||
func (v Expr) Do() Expr {
|
func (v Expr) Do() Expr {
|
||||||
if vt := v.Type; vt.kind == vkDelayExpr {
|
switch vt := v.Type; vt.kind {
|
||||||
|
case vkDelayExpr:
|
||||||
return vt.t.(delayExprTy)()
|
return vt.t.(delayExprTy)()
|
||||||
|
case vkPhisExpr:
|
||||||
|
panic("unreachable")
|
||||||
}
|
}
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
// DelayExpr returns a delay expression.
|
// DelayExpr returns a delay expression.
|
||||||
func DelayExpr(f func() Expr) Expr {
|
func DelayExpr(f func() Expr) Expr {
|
||||||
return Expr{Type: &aType{t: delayExprTy(f), kind: vkDelayExpr}}
|
return Expr{Type: &aType{t: delayExprTy(f), kind: vkDelayExpr}}
|
||||||
@@ -73,6 +78,24 @@ func (p delayExprTy) String() string {
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type phisExprTy struct {
|
||||||
|
phis []llvm.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p phisExprTy) Underlying() types.Type {
|
||||||
|
panic("don't call")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p phisExprTy) String() string {
|
||||||
|
return "phisExpr"
|
||||||
|
}
|
||||||
|
|
||||||
|
func phisExpr(phis []llvm.Value) Expr {
|
||||||
|
return Expr{Type: &aType{t: &phisExprTy{phis}, kind: vkPhisExpr}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
// Null returns a null constant expression.
|
// Null returns a null constant expression.
|
||||||
func (p Program) Null(t Type) Expr {
|
func (p Program) Null(t Type) Expr {
|
||||||
return Expr{llvm.ConstNull(t.ll), t}
|
return Expr{llvm.ConstNull(t.ll), t}
|
||||||
@@ -337,6 +360,14 @@ func llvmValues(vals []Expr) []llvm.Value {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fieldValues(b llvm.Builder, vals []Expr, fldIdx int) []llvm.Value {
|
||||||
|
ret := make([]llvm.Value, len(vals))
|
||||||
|
for i, v := range vals {
|
||||||
|
ret[i] = llvm.CreateExtractValue(b, v.impl, fldIdx)
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
func llvmBlocks(bblks []BasicBlock) []llvm.BasicBlock {
|
func llvmBlocks(bblks []BasicBlock) []llvm.BasicBlock {
|
||||||
ret := make([]llvm.BasicBlock, len(bblks))
|
ret := make([]llvm.BasicBlock, len(bblks))
|
||||||
for i, v := range bblks {
|
for i, v := range bblks {
|
||||||
@@ -351,15 +382,37 @@ type Phi struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AddIncoming adds incoming values to a phi node.
|
// AddIncoming adds incoming values to a phi node.
|
||||||
func (p Phi) AddIncoming(vals []Expr, bblks []BasicBlock) {
|
func (p Phi) AddIncoming(b Builder, vals []Expr, bblks []BasicBlock) {
|
||||||
v := llvmValues(vals)
|
bs := llvmBlocks(bblks)
|
||||||
b := llvmBlocks(bblks)
|
if p.kind != vkPhisExpr { // normal phi node
|
||||||
p.impl.AddIncoming(v, b)
|
vs := llvmValues(vals)
|
||||||
|
p.impl.AddIncoming(vs, bs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
phis := p.t.(*phisExprTy).phis
|
||||||
|
for i, phi := range phis {
|
||||||
|
flds := fieldValues(b.impl, vals, i)
|
||||||
|
phi.AddIncoming(flds, bs)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Phi returns a phi node.
|
// Phi returns a phi node.
|
||||||
func (b Builder) Phi(t Type) Phi {
|
func (b Builder) Phi(t Type) Phi {
|
||||||
return Phi{Expr{llvm.CreatePHI(b.impl, t.ll), t}}
|
impl := b.impl
|
||||||
|
switch tund := t.t.Underlying().(type) {
|
||||||
|
case *types.Basic:
|
||||||
|
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(phis)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
phi := llvm.CreatePHI(impl, t.ll)
|
||||||
|
return Phi{Expr{phi, t}}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ const (
|
|||||||
vkFunc
|
vkFunc
|
||||||
vkTuple
|
vkTuple
|
||||||
vkDelayExpr = -1
|
vkDelayExpr = -1
|
||||||
|
vkPhisExpr = -2
|
||||||
)
|
)
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user