Browse Source

Rewrite basic block creation code

cl-refactor
Paweł Bylica 10 years ago
parent
commit
bb37986cad
  1. 71
      libevmjit/Compiler.cpp

71
libevmjit/Compiler.cpp

@ -40,63 +40,58 @@ Compiler::Compiler(Options const& _options):
void Compiler::createBasicBlocks(bytes const& _bytecode) void Compiler::createBasicBlocks(bytes const& _bytecode)
{ {
// FIXME: Simplify this algorithm. All can be done in one pass /// Helper function that skips push data and finds next iterator (can be the end)
auto skipPushDataAndGetNext = [](bytes::const_iterator _curr, bytes::const_iterator _end)
std::set<ProgramCounter> splitPoints; // Sorted collections of instruction indices where basic blocks start/end
std::vector<ProgramCounter> indirectJumpTargets;
splitPoints.insert(0); // First basic block
for (auto curr = _bytecode.begin(); curr != _bytecode.end(); ++curr)
{ {
ProgramCounter currentPC = curr - _bytecode.begin(); static const auto push1 = static_cast<size_t>(Instruction::PUSH1);
static const auto push32 = static_cast<size_t>(Instruction::PUSH32);
size_t offset = 1;
if (*_curr >= push1 && *_curr <= push32)
offset += std::min<size_t>(*_curr - push1 + 1, (_end - _curr) - 1);
return _curr + offset;
};
auto inst = Instruction(*curr); ProgramCounter beginIdx = 0;
switch (inst) bool nextJumpDest = false;
for (auto curr = _bytecode.begin(), next = curr; curr != _bytecode.end(); curr = next)
{ {
next = skipPushDataAndGetNext(curr, _bytecode.end());
case Instruction::ANY_PUSH: bool isEnd = false;
skipPushData(curr, _bytecode.end()); switch (Instruction(*curr))
break;
case Instruction::JUMPDEST:
{ {
// A basic block starts here.
splitPoints.insert(currentPC);
indirectJumpTargets.push_back(currentPC);
break;
}
case Instruction::JUMP: case Instruction::JUMP:
case Instruction::JUMPI: case Instruction::JUMPI:
case Instruction::RETURN: case Instruction::RETURN:
case Instruction::STOP: case Instruction::STOP:
case Instruction::SUICIDE: case Instruction::SUICIDE:
{ isEnd = true;
// Create a basic block starting at the following instruction. break;
if (curr + 1 < _bytecode.end())
splitPoints.insert(currentPC + 1); case Instruction::JUMPDEST:
nextJumpDest = true;
break; break;
}
default: default:
break; break;
} }
}
for (auto it = splitPoints.cbegin(); it != splitPoints.cend();) assert(next <= _bytecode.end());
if (next == _bytecode.end() || Instruction(*next) == Instruction::JUMPDEST)
isEnd = true;
if (isEnd)
{ {
auto beginInstIdx = *it; auto nextIdx = next - _bytecode.begin();
++it; auto p = basicBlocks.emplace(std::piecewise_construct, std::forward_as_tuple(beginIdx), std::forward_as_tuple(beginIdx, nextIdx, m_mainFunc, m_builder));
auto endInstIdx = it != splitPoints.cend() ? *it : _bytecode.size(); if (nextJumpDest)
basicBlocks.emplace(std::piecewise_construct, std::forward_as_tuple(beginInstIdx), std::forward_as_tuple(beginInstIdx, endInstIdx, m_mainFunc, m_builder)); p.first->second.markAsJumpDest();
nextJumpDest = false;
beginIdx = nextIdx;
}
} }
m_stopBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Stop", m_mainFunc); m_stopBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Stop", m_mainFunc);
for (auto it = indirectJumpTargets.cbegin(); it != indirectJumpTargets.cend(); ++it)
basicBlocks.find(*it)->second.markAsJumpDest();
} }
llvm::BasicBlock* Compiler::getJumpTableBlock() llvm::BasicBlock* Compiler::getJumpTableBlock()
@ -153,7 +148,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(bytes const& _bytecode, std::str
Stack stack(m_builder, runtimeManager); Stack stack(m_builder, runtimeManager);
Arith256 arith(m_builder); Arith256 arith(m_builder);
m_builder.CreateBr(basicBlocks.begin()->second); m_builder.CreateBr(basicBlocks.empty() ? m_stopBB : basicBlocks.begin()->second);
for (auto basicBlockPairIt = basicBlocks.begin(); basicBlockPairIt != basicBlocks.end(); ++basicBlockPairIt) for (auto basicBlockPairIt = basicBlocks.begin(); basicBlockPairIt != basicBlocks.end(); ++basicBlockPairIt)
{ {

Loading…
Cancel
Save