llgo/ssa.Phi: AddIncoming fix

This commit is contained in:
xushiwei
2024-05-24 09:20:58 +08:00
parent 97e38255c6
commit 056ad51c24
12 changed files with 555 additions and 470 deletions

View File

@@ -274,7 +274,7 @@ func (p Function) NewBuilder() Builder {
b := prog.ctx.NewBuilder()
// TODO(xsw): Finalize may cause panic, so comment it.
// b.Finalize()
return &aBuilder{b, p, p.Pkg, prog}
return &aBuilder{b, nil, p, p.Pkg, prog}
}
// HasBody reports whether the function has a body.
@@ -287,7 +287,7 @@ func (p Function) HasBody() bool {
func (p Function) MakeBody(nblk int) Builder {
p.MakeBlocks(nblk)
b := p.NewBuilder()
b.impl.SetInsertPointAtEnd(p.blks[0].impl)
b.impl.SetInsertPointAtEnd(p.blks[0].last)
return b
}
@@ -306,7 +306,7 @@ func (p Function) MakeBlocks(nblk int) []BasicBlock {
func (p Function) addBlock(idx int) BasicBlock {
label := "_llgo_" + strconv.Itoa(idx)
blk := llvm.AddBasicBlock(p.impl, label)
ret := &aBasicBlock{blk, p, idx}
ret := &aBasicBlock{blk, blk, p, idx}
p.blks = append(p.blks, ret)
return ret
}

View File

@@ -517,10 +517,10 @@ func llvmDelayValues(f func(i int) Expr, n int) []llvm.Value {
return ret
}
func llvmBlocks(bblks []BasicBlock) []llvm.BasicBlock {
ret := make([]llvm.BasicBlock, len(bblks))
for i, v := range bblks {
ret[i] = v.impl
func llvmPredBlocks(preds []BasicBlock) []llvm.BasicBlock {
ret := make([]llvm.BasicBlock, len(preds))
for i, v := range preds {
ret[i] = v.last
}
return ret
}
@@ -531,24 +531,24 @@ type Phi struct {
}
// AddIncoming adds incoming values to a phi node.
func (p Phi) AddIncoming(b Builder, bblks []BasicBlock, f func(i int) Expr) {
bs := llvmBlocks(bblks)
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(bblks))
vs := llvmDelayValues(f, len(preds))
p.impl.AddIncoming(vs, bs)
return
}
e := p.raw.Type.(*phisExprTy)
phis := e.phis
vals := make([][]llvm.Value, len(phis))
for iblk, blk := range bblks {
last := blk.impl.LastInstruction()
for iblk, blk := range preds {
last := blk.last.LastInstruction()
b.impl.SetInsertPointBefore(last)
impl := b.impl
val := f(iblk).impl
for i := range phis {
if iblk == 0 {
vals[i] = make([]llvm.Value, len(bblks))
vals[i] = make([]llvm.Value, len(preds))
}
vals[i][iblk] = llvm.CreateExtractValue(impl, val, i)
}

View File

@@ -61,13 +61,14 @@ func (b Builder) abiStruct(t *types.Struct) Expr {
eq := b.BinOp(token.EQL, b.Load(expr), b.Prog.Null(expr.Type))
blks = b.Func.MakeBlocks(2)
b.If(eq, blks[0], blks[1])
b.SetBlock(blks[0])
b.SetBlockEx(blks[0], AtEnd, false)
}
tabi := b.structOf(t)
b.Store(expr, tabi)
if pub {
b.Jump(blks[1])
b.SetBlock(blks[1])
b.SetBlockEx(blks[1], AtEnd, false)
b.blk.last = blks[1].last
}
})
}
@@ -279,9 +280,10 @@ func (b Builder) TypeAssert(x Expr, assertedTyp Type, commaOk bool) Expr {
}
blks := b.Func.MakeBlocks(2)
b.If(eq, blks[0], blks[1])
b.SetBlock(blks[1])
b.SetBlockEx(blks[1], AtEnd, false)
b.Panic(b.Str("type assertion failed"))
b.SetBlock(blks[0])
b.SetBlockEx(blks[0], AtEnd, false)
b.blk.last = blks[0].last
return b.valFromData(assertedTyp, b.faceData(x.impl))
}

View File

@@ -559,7 +559,7 @@ func (p Package) AfterInit(b Builder, ret BasicBlock) {
doAbiInit := len(p.abiini) > 0
doPyLoadModSyms := p.pyHasModSyms()
if doAbiInit || doPyLoadModSyms {
b.SetBlockEx(ret, afterInit)
b.SetBlockEx(ret, afterInit, false)
if doAbiInit {
sigAbiInit := types.NewSignatureType(nil, nil, nil, nil, nil, false)
fn := p.NewFunc(p.abi.Pkg+".init$abi", sigAbiInit, InC)
@@ -743,7 +743,7 @@ func (p Program) tyGetAttrString() *types.Signature {
func (p Package) PyInit() bool {
if fn := p.FuncOf("main"); fn != nil {
b := fn.NewBuilder()
b.SetBlockEx(fn.Block(0), AtStart).callPyInit()
b.SetBlockEx(fn.Block(0), AtStart, false).callPyInit()
b.Dispose()
return true
}

View File

@@ -52,7 +52,7 @@ func TestSetBlockEx(t *testing.T) {
}()
fn := &aFunction{}
b := &aBuilder{Func: fn}
b.SetBlockEx(&aBasicBlock{fn: fn}, -1)
b.SetBlockEx(&aBasicBlock{fn: fn}, -1, false)
}
func TestSetPython(t *testing.T) {

View File

@@ -29,9 +29,10 @@ import (
// -----------------------------------------------------------------------------
type aBasicBlock struct {
impl llvm.BasicBlock
fn Function
idx int
first llvm.BasicBlock
last llvm.BasicBlock
fn Function
idx int
}
// BasicBlock represents a basic block in a function.
@@ -51,6 +52,7 @@ func (p BasicBlock) Index() int {
type aBuilder struct {
impl llvm.Builder
blk BasicBlock
Func Function
Pkg Package
Prog Program
@@ -64,12 +66,12 @@ func (b Builder) Dispose() {
b.impl.Dispose()
}
// SetBlock means SetBlockEx(blk, AtEnd).
// SetBlock means SetBlockEx(blk, AtEnd, true).
func (b Builder) SetBlock(blk BasicBlock) Builder {
if debugInstr {
log.Printf("Block _llgo_%v:\n", blk.idx)
}
b.SetBlockEx(blk, AtEnd)
b.SetBlockEx(blk, AtEnd, true)
return b
}
@@ -82,20 +84,23 @@ const (
)
// SetBlockEx sets blk as current basic block and pos as its insert point.
func (b Builder) SetBlockEx(blk BasicBlock, pos InsertPoint) Builder {
func (b Builder) SetBlockEx(blk BasicBlock, pos InsertPoint, setBlk bool) Builder {
if b.Func != blk.fn {
panic("mismatched function")
}
switch pos {
case AtEnd:
b.impl.SetInsertPointAtEnd(blk.impl)
b.impl.SetInsertPointAtEnd(blk.last)
case AtStart:
b.impl.SetInsertPointBefore(blk.impl.FirstInstruction())
b.impl.SetInsertPointBefore(blk.first.FirstInstruction())
case afterInit:
b.impl.SetInsertPointBefore(instrAfterInit(blk.impl))
b.impl.SetInsertPointBefore(instrAfterInit(blk.first))
default:
panic("SetBlockEx: invalid pos")
}
if setBlk {
b.blk = blk
}
return b
}
@@ -184,7 +189,7 @@ func (b Builder) Jump(jmpb BasicBlock) {
if debugInstr {
log.Printf("Jump _llgo_%v\n", jmpb.idx)
}
b.impl.CreateBr(jmpb.impl)
b.impl.CreateBr(jmpb.first)
}
// If emits an if instruction.
@@ -195,7 +200,7 @@ func (b Builder) If(cond Expr, thenb, elseb BasicBlock) {
if debugInstr {
log.Printf("If %v, _llgo_%v, _llgo_%v\n", cond.impl, thenb.idx, elseb.idx)
}
b.impl.CreateCondBr(cond.impl, thenb.impl, elseb.impl)
b.impl.CreateCondBr(cond.impl, thenb.first, elseb.first)
}
// The MapUpdate instruction updates the association of Map[Key] to