Browse Source

Use LLVM metadata for keeping information about jump target index.

cl-refactor
Paweł Bylica 10 years ago
parent
commit
406e13dadf
  1. 6
      evmjit/libevmjit/BasicBlock.h
  2. 53
      evmjit/libevmjit/Compiler.cpp

6
evmjit/libevmjit/BasicBlock.h

@ -86,9 +86,6 @@ public:
bool isJumpDest() const { return m_isJumpDest; }
llvm::Value* getJumpTarget() const { return m_jumpTarget; }
void setJumpTarget(llvm::Value* _jumpTarget) { m_jumpTarget = _jumpTarget; }
private:
instr_idx const m_firstInstrIdx = 0; ///< Code index of first instruction in the block
code_iterator const m_begin = {}; ///< Iterator pointing code beginning of the block
@ -99,9 +96,6 @@ private:
/// Is the basic block a valid jump destination.
/// JUMPDEST is the first instruction of the basic block.
bool const m_isJumpDest = false;
/// If block finishes with dynamic jump target index is stored here
llvm::Value* m_jumpTarget = nullptr;
};
}

53
evmjit/libevmjit/Compiler.cpp

@ -108,18 +108,8 @@ void Compiler::fillJumpTable()
auto target = m_builder.CreatePHI(Type::Word, 16, "target");
for (auto pred: llvm::predecessors(m_jumpTableBB))
{
llvm::Value* incomingTarget = nullptr;
for (auto&& p: m_basicBlocks) // FIXME: Fix this stupid search. Use metadata to tag target in the basic block
{
if (p.second.llvm() == &*pred)
{
incomingTarget = p.second.getJumpTarget();
break;
}
}
assert(incomingTarget);
target->addIncoming(incomingTarget, pred);
auto targetMd = llvm::cast<llvm::LocalAsMetadata>(pred->getTerminator()->getMetadata("target")->getOperand(0));
target->addIncoming(targetMd->getValue(), pred);
}
auto switchInst = m_builder.CreateSwitch(target, m_abortBB);
@ -571,44 +561,25 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti
case Instruction::JUMP:
case Instruction::JUMPI:
{
llvm::BasicBlock* targetBlock = nullptr;
auto jumpBlock = m_jumpTableBB;
auto target = stack.pop();
auto jumpInst = (inst == Instruction::JUMP) ?
m_builder.CreateBr(jumpBlock) :
m_builder.CreateCondBr(m_builder.CreateICmpNE(stack.pop(), Constant::get(0), "jump.check"), jumpBlock, _nextBasicBlock);
if (auto constant = llvm::dyn_cast<llvm::ConstantInt>(target))
{
// If target index is a constant do direct jump to the target block.
auto&& c = constant->getValue();
auto targetIdx = c.getActiveBits() <= 64 ? c.getZExtValue() : -1;
auto it = m_basicBlocks.find(targetIdx);
targetBlock = (it != m_basicBlocks.end() && it->second.isJumpDest()) ? it->second.llvm() : m_abortBB;
}
// TODO: Improve; check for constants
if (inst == Instruction::JUMP)
{
if (targetBlock)
{
m_builder.CreateBr(targetBlock);
}
else
{
_basicBlock.setJumpTarget(target);
m_builder.CreateBr(m_jumpTableBB);
}
}
else // JUMPI
{
auto val = stack.pop();
auto zero = Constant::get(0);
auto cond = m_builder.CreateICmpNE(val, zero, "nonzero");
if (targetBlock)
{
m_builder.CreateCondBr(cond, targetBlock, _nextBasicBlock);
jumpInst->setSuccessor(0, (it != m_basicBlocks.end() && it->second.isJumpDest()) ? it->second.llvm() : m_abortBB);
}
else
{
_basicBlock.setJumpTarget(target);
m_builder.CreateCondBr(cond, m_jumpTableBB, _nextBasicBlock);
}
// Attach medatada to branch instruction with information about target index.
auto targetMd = llvm::MDNode::get(jumpInst->getContext(), llvm::LocalAsMetadata::get(target));
jumpInst->setMetadata("target", targetMd);
}
break;
}

Loading…
Cancel
Save