LLVM: block borders fixed

This commit is contained in:
Nekotekina 2017-02-25 21:24:36 +03:00
parent af53ce6f76
commit d0afef47f8
2 changed files with 43 additions and 49 deletions

View file

@ -983,7 +983,7 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
const auto next = func.blocks.upper_bound(block.first);
// Normalize block if necessary
if (next != func.blocks.end())
if (next != func.blocks.end() && block.second > next->first - block.first)
{
block.second = next->first - block.first;
}

View file

@ -229,68 +229,61 @@ Function* PPUTranslator::TranslateToIR(const ppu_function& info, be_t<u32>* bin,
}
}
m_blocks[m_end_addr] = BasicBlock::Create(m_context, "loc_end", m_function);
// Finalize entry block
m_ir->CreateBr(m_blocks.at(m_start_addr));
/* Convert each instruction to LLVM IR */
const auto start = m_blocks.at(m_start_addr);
m_ir->CreateBr(start);
m_ir->SetInsertPoint(start);
for (m_current_addr = m_start_addr; m_current_addr < m_end_addr;)
// Process blocks
for (auto&& block : info.blocks)
{
// Preserve current address (m_current_addr may be changed by the decoder)
const u64 addr = m_current_addr;
if (m_blocks.count(m_current_addr))
if (!m_blocks.count(block.first))
{
// Bloat the beginning of each block: check state
const auto vstate = m_ir->CreateLoad(m_ir->CreateConstGEP2_32(nullptr, m_thread, 0, 1));
const auto vblock = BasicBlock::Create(m_context, fmt::format("l0c_%llx", m_current_addr), m_function);
const auto vcheck = BasicBlock::Create(m_context, fmt::format("lcc_%llx", m_current_addr), m_function);
m_ir->CreateCondBr(m_ir->CreateIsNull(vstate), vblock, vcheck, m_md_unlikely);
m_ir->SetInsertPoint(vcheck);
Call(GetType<void>(), "__check", m_thread, m_ir->getInt64(m_current_addr));
m_ir->CreateBr(vblock);
m_ir->SetInsertPoint(vblock);
continue;
}
// Translate opcode
if (!m_ir->GetInsertBlock()->getTerminator())
// Start block
m_ir->SetInsertPoint(m_blocks.at(block.first));
// Bloat the beginning of each block: check state
const auto vstate = m_ir->CreateLoad(m_ir->CreateConstGEP2_32(nullptr, m_thread, 0, 1));
const auto vblock = BasicBlock::Create(m_context, fmt::format("l0c_%llx", m_current_addr), m_function);
const auto vcheck = BasicBlock::Create(m_context, fmt::format("lcc_%llx", m_current_addr), m_function);
m_ir->CreateCondBr(m_ir->CreateIsNull(vstate), vblock, vcheck, m_md_unlikely);
m_ir->SetInsertPoint(vcheck);
Call(GetType<void>(), "__check", m_thread, m_ir->getInt64(m_current_addr));
m_ir->CreateBr(vblock);
m_ir->SetInsertPoint(vblock);
// Process the instructions
for (m_current_addr = block.first; m_current_addr < block.first + block.second; m_current_addr += 4)
{
const u32 op = *(m_bin = bin + (addr - m_start_addr) / sizeof(u32));
if (m_ir->GetInsertBlock()->getTerminator())
{
break;
}
const u32 op = *(m_bin = bin + (m_current_addr - m_start_addr) / sizeof(u32));
(this->*(s_ppu_decoder.decode(op)))({op});
}
// Get next address
if (m_current_addr == addr) m_current_addr += sizeof(u32);
// Get next block if necessary
if (m_blocks.count(m_current_addr))
// Finalize current block if necessary (create branch to the next address)
if (!m_ir->GetInsertBlock()->getTerminator())
{
const auto next = m_blocks.at(m_current_addr);
// Finalize current block if necessary (create branch to next address)
if (!m_ir->GetInsertBlock()->getTerminator())
if (m_blocks.count(m_current_addr))
{
m_ir->CreateBr(next);
m_ir->CreateBr(m_blocks.at(m_current_addr));
}
else
{
Call(GetType<void>(), "__end", m_ir->getInt64(m_current_addr));
m_ir->CreateUnreachable();
}
// Start next block
m_ir->SetInsertPoint(next);
}
}
// Run custom IR generation function
// Run custom IR generation function (TODO)
if (custom) custom(this);
// Finalize past-the-end block
if (!m_ir->GetInsertBlock()->getTerminator())
{
Call(GetType<void>(), "__end", m_ir->getInt64(m_end_addr));
m_ir->CreateUnreachable();
}
m_ir->SetInsertPoint(m_jtr);
if (m_jtr->use_empty())
@ -1906,7 +1899,7 @@ void PPUTranslator::BCCTR(ppu_opcode_t op)
std::set<u64> targets;
// Detect a possible jumptable
for (u64 jt_addr = (m_current_addr += sizeof(u32)); m_current_addr < m_end_addr; m_current_addr += sizeof(u32))
for (u64 jt_addr = m_current_addr + sizeof(u32), addr = jt_addr; addr < m_end_addr; addr += sizeof(u32))
{
const u64 target = jt_addr + static_cast<s32>(*++m_bin);
@ -1937,7 +1930,8 @@ void PPUTranslator::BCCTR(ppu_opcode_t op)
}
m_ir->SetInsertPoint(_default);
Trap(m_current_addr);
Call(GetType<void>(), "__end", m_ir->getInt64(m_current_addr));
m_ir->CreateUnreachable();
}
else
{
@ -2266,7 +2260,7 @@ void PPUTranslator::CMP(ppu_opcode_t op)
void PPUTranslator::TW(ppu_opcode_t op)
{
UseCondition(m_md_unlikely, CheckTrapCondition(op.bo, GetGpr(op.ra, 32), GetGpr(op.rb, 32)));
if (op.opcode != ppu_instructions::TRAP()) UseCondition(m_md_unlikely, CheckTrapCondition(op.bo, GetGpr(op.ra, 32), GetGpr(op.rb, 32)));
Trap(m_current_addr);
}