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); const auto next = func.blocks.upper_bound(block.first);
// Normalize block if necessary // 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; block.second = next->first - block.first;
} }

View file

@ -229,20 +229,20 @@ 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 */ // Process blocks
const auto start = m_blocks.at(m_start_addr); for (auto&& block : info.blocks)
m_ir->CreateBr(start);
m_ir->SetInsertPoint(start);
for (m_current_addr = m_start_addr; m_current_addr < m_end_addr;)
{ {
// Preserve current address (m_current_addr may be changed by the decoder) if (!m_blocks.count(block.first))
const u64 addr = m_current_addr;
if (m_blocks.count(m_current_addr))
{ {
continue;
}
// Start block
m_ir->SetInsertPoint(m_blocks.at(block.first));
// Bloat the beginning of each block: check state // 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 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 vblock = BasicBlock::Create(m_context, fmt::format("l0c_%llx", m_current_addr), m_function);
@ -253,43 +253,36 @@ Function* PPUTranslator::TranslateToIR(const ppu_function& info, be_t<u32>* bin,
Call(GetType<void>(), "__check", m_thread, m_ir->getInt64(m_current_addr)); Call(GetType<void>(), "__check", m_thread, m_ir->getInt64(m_current_addr));
m_ir->CreateBr(vblock); m_ir->CreateBr(vblock);
m_ir->SetInsertPoint(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)
{
if (m_ir->GetInsertBlock()->getTerminator())
{
break;
} }
// Translate opcode const u32 op = *(m_bin = bin + (m_current_addr - m_start_addr) / sizeof(u32));
if (!m_ir->GetInsertBlock()->getTerminator())
{
const u32 op = *(m_bin = bin + (addr - m_start_addr) / sizeof(u32));
(this->*(s_ppu_decoder.decode(op)))({op}); (this->*(s_ppu_decoder.decode(op)))({op});
} }
// Get next address // Finalize current block if necessary (create branch to the next address)
if (m_current_addr == addr) m_current_addr += sizeof(u32); if (!m_ir->GetInsertBlock()->getTerminator())
{
// Get next block if necessary
if (m_blocks.count(m_current_addr)) if (m_blocks.count(m_current_addr))
{ {
const auto next = m_blocks.at(m_current_addr); m_ir->CreateBr(m_blocks.at(m_current_addr));
}
// Finalize current block if necessary (create branch to next address) else
if (!m_ir->GetInsertBlock()->getTerminator())
{ {
m_ir->CreateBr(next); Call(GetType<void>(), "__end", m_ir->getInt64(m_current_addr));
}
// Start next block
m_ir->SetInsertPoint(next);
}
}
// Run custom IR generation function
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->CreateUnreachable();
} }
}
}
// Run custom IR generation function (TODO)
if (custom) custom(this);
m_ir->SetInsertPoint(m_jtr); m_ir->SetInsertPoint(m_jtr);
@ -1906,7 +1899,7 @@ void PPUTranslator::BCCTR(ppu_opcode_t op)
std::set<u64> targets; std::set<u64> targets;
// Detect a possible jumptable // 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); 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); m_ir->SetInsertPoint(_default);
Trap(m_current_addr); Call(GetType<void>(), "__end", m_ir->getInt64(m_current_addr));
m_ir->CreateUnreachable();
} }
else else
{ {
@ -2266,7 +2260,7 @@ void PPUTranslator::CMP(ppu_opcode_t op)
void PPUTranslator::TW(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); Trap(m_current_addr);
} }