llgo/ssa: phi node
This commit is contained in:
@@ -142,6 +142,7 @@ type context struct {
|
|||||||
bvals map[ssa.Value]llssa.Expr // block values
|
bvals map[ssa.Value]llssa.Expr // block values
|
||||||
vargs map[*ssa.Alloc][]llssa.Expr // varargs
|
vargs map[*ssa.Alloc][]llssa.Expr // varargs
|
||||||
inits []func()
|
inits []func()
|
||||||
|
phis []func()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) compileType(pkg llssa.Package, t *ssa.Type) {
|
func (p *context) compileType(pkg llssa.Package, t *ssa.Type) {
|
||||||
@@ -203,6 +204,7 @@ func (p *context) compileFunc(pkg llssa.Package, pkgTypes *types.Package, f *ssa
|
|||||||
defer func() {
|
defer func() {
|
||||||
p.fn = nil
|
p.fn = nil
|
||||||
}()
|
}()
|
||||||
|
p.phis = nil
|
||||||
nblk := len(f.Blocks)
|
nblk := len(f.Blocks)
|
||||||
if nblk == 0 { // external function
|
if nblk == 0 { // external function
|
||||||
return
|
return
|
||||||
@@ -219,6 +221,9 @@ func (p *context) compileFunc(pkg llssa.Package, pkgTypes *types.Package, f *ssa
|
|||||||
for i, block := range f.Blocks {
|
for i, block := range f.Blocks {
|
||||||
p.compileBlock(b, block, i == 0 && name == "main")
|
p.compileBlock(b, block, i == 0 && name == "main")
|
||||||
}
|
}
|
||||||
|
for _, phi := range p.phis {
|
||||||
|
phi()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,6 +354,18 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
|
|||||||
case *ssa.UnOp:
|
case *ssa.UnOp:
|
||||||
x := p.compileValue(b, v.X)
|
x := p.compileValue(b, v.X)
|
||||||
ret = b.UnOp(v.Op, x)
|
ret = b.UnOp(v.Op, x)
|
||||||
|
case *ssa.Phi:
|
||||||
|
phi := b.Phi(p.prog.Type(v.Type()))
|
||||||
|
ret = phi.Expr
|
||||||
|
p.phis = append(p.phis, func() {
|
||||||
|
vals := p.compileValues(b, v.Edges, 0)
|
||||||
|
preds := v.Block().Preds
|
||||||
|
bblks := make([]llssa.BasicBlock, len(preds))
|
||||||
|
for i, pred := range preds {
|
||||||
|
bblks[i] = p.fn.Block(pred.Index)
|
||||||
|
}
|
||||||
|
phi.AddIncoming(vals, bblks)
|
||||||
|
})
|
||||||
case *ssa.ChangeType:
|
case *ssa.ChangeType:
|
||||||
t := v.Type()
|
t := v.Type()
|
||||||
x := p.compileValue(b, v.X)
|
x := p.compileValue(b, v.X)
|
||||||
|
|||||||
51
ssa/expr.go
51
ssa/expr.go
@@ -72,16 +72,6 @@ func (p delayExprTy) String() string {
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
func llvmValues(vals []Expr) []llvm.Value {
|
|
||||||
ret := make([]llvm.Value, len(vals))
|
|
||||||
for i, v := range vals {
|
|
||||||
ret[i] = v.impl
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// 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}
|
||||||
@@ -326,6 +316,43 @@ func (b Builder) UnOp(op token.Token, x Expr) Expr {
|
|||||||
panic("todo")
|
panic("todo")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func llvmValues(vals []Expr) []llvm.Value {
|
||||||
|
ret := make([]llvm.Value, len(vals))
|
||||||
|
for i, v := range vals {
|
||||||
|
ret[i] = v.impl
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func llvmBlocks(bblks []BasicBlock) []llvm.BasicBlock {
|
||||||
|
ret := make([]llvm.BasicBlock, len(bblks))
|
||||||
|
for i, v := range bblks {
|
||||||
|
ret[i] = v.impl
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// Phi represents a phi node.
|
||||||
|
type Phi struct {
|
||||||
|
Expr
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddIncoming adds incoming values to a phi node.
|
||||||
|
func (p Phi) AddIncoming(vals []Expr, bblks []BasicBlock) {
|
||||||
|
v := llvmValues(vals)
|
||||||
|
b := llvmBlocks(bblks)
|
||||||
|
p.impl.AddIncoming(v, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Phi returns a phi node.
|
||||||
|
func (b Builder) Phi(t Type) Phi {
|
||||||
|
return Phi{Expr{llvm.CreatePHI(b.impl, t.ll), t}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
// Load returns the value at the pointer ptr.
|
// Load returns the value at the pointer ptr.
|
||||||
func (b Builder) Load(ptr Expr) Expr {
|
func (b Builder) Load(ptr Expr) Expr {
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
@@ -434,6 +461,8 @@ func (b Builder) Slice(x, low, high, max Expr) (ret Expr) {
|
|||||||
panic("todo")
|
panic("todo")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
// The Alloc instruction reserves space for a variable of the given type,
|
// The Alloc instruction reserves space for a variable of the given type,
|
||||||
// zero-initializes it, and yields its address.
|
// zero-initializes it, and yields its address.
|
||||||
//
|
//
|
||||||
@@ -495,6 +524,8 @@ func (b Builder) ArrayAlloca(telem Type, n Expr) (ret Expr) {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
// The ChangeType instruction applies to X a value-preserving type
|
// The ChangeType instruction applies to X a value-preserving type
|
||||||
// change to Type().
|
// change to Type().
|
||||||
//
|
//
|
||||||
|
|||||||
Reference in New Issue
Block a user