|
|
@ -172,8 +172,52 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode) |
|
|
|
for (auto basicBlockPairIt = basicBlocks.begin(); basicBlockPairIt != basicBlocks.end(); ++basicBlockPairIt) |
|
|
|
{ |
|
|
|
auto& basicBlock = basicBlockPairIt->second; |
|
|
|
auto iterCopy = basicBlockPairIt; |
|
|
|
++iterCopy; |
|
|
|
auto nextBasicBlock = (iterCopy != basicBlocks.end()) ? iterCopy->second.llvm() : nullptr; |
|
|
|
compileBasicBlock(basicBlock, bytecode, memory, ext, gasMeter, nextBasicBlock); |
|
|
|
} |
|
|
|
|
|
|
|
// Code for special blocks:
|
|
|
|
// TODO: move to separate function.
|
|
|
|
// Note: Right now the codegen for special blocks depends only on createBasicBlock(),
|
|
|
|
// not on the codegen for 'regular' blocks. But it has to be done before linkBasicBlocks().
|
|
|
|
m_builder.SetInsertPoint(m_stopBB); |
|
|
|
m_builder.CreateRet(Constant::get(ReturnCode::Stop)); |
|
|
|
|
|
|
|
m_builder.SetInsertPoint(m_badJumpBlock->llvm()); |
|
|
|
m_builder.CreateRet(Constant::get(ReturnCode::BadJumpDestination)); |
|
|
|
|
|
|
|
m_builder.SetInsertPoint(m_jumpTableBlock->llvm()); |
|
|
|
if (m_indirectJumpTargets.size() > 0) |
|
|
|
{ |
|
|
|
auto& stack = m_jumpTableBlock->getStack(); |
|
|
|
|
|
|
|
auto dest = stack.pop(); |
|
|
|
auto switchInstr = m_builder.CreateSwitch(dest, m_badJumpBlock->llvm(), |
|
|
|
m_indirectJumpTargets.size()); |
|
|
|
for (auto it = m_indirectJumpTargets.cbegin(); it != m_indirectJumpTargets.cend(); ++it) |
|
|
|
{ |
|
|
|
auto& bb = *it; |
|
|
|
auto dest = Constant::get(bb->begin()); |
|
|
|
switchInstr->addCase(dest, bb->llvm()); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
m_builder.CreateBr(m_badJumpBlock->llvm()); |
|
|
|
} |
|
|
|
|
|
|
|
linkBasicBlocks(); |
|
|
|
|
|
|
|
return module; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void Compiler::compileBasicBlock(BasicBlock& basicBlock, const bytes& bytecode, Memory& memory, Ext& ext, GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock) |
|
|
|
{ |
|
|
|
auto& stack = basicBlock.getStack(); |
|
|
|
m_builder.SetInsertPoint(basicBlock); |
|
|
|
m_builder.SetInsertPoint(basicBlock.llvm()); |
|
|
|
|
|
|
|
for (auto currentPC = basicBlock.begin(); currentPC != basicBlock.end(); ++currentPC) |
|
|
|
{ |
|
|
@ -557,19 +601,16 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode) |
|
|
|
auto cond = m_builder.CreateICmpNE(val, zero, "nonzero"); |
|
|
|
|
|
|
|
// Assume the basic blocks are properly ordered:
|
|
|
|
auto nextBBIter = basicBlockPairIt; |
|
|
|
++nextBBIter; |
|
|
|
assert (nextBBIter != basicBlocks.end()); |
|
|
|
auto& followBlock = nextBBIter->second; |
|
|
|
assert(nextBasicBlock); // FIXME: JUMPI can be last instruction
|
|
|
|
|
|
|
|
if (targetBlock) |
|
|
|
{ |
|
|
|
stack.pop(); |
|
|
|
m_builder.CreateCondBr(cond, targetBlock->llvm(), followBlock.llvm()); |
|
|
|
m_builder.CreateCondBr(cond, targetBlock->llvm(), nextBasicBlock); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
m_builder.CreateCondBr(cond, m_jumpTableBlock->llvm(), followBlock.llvm()); |
|
|
|
m_builder.CreateCondBr(cond, m_jumpTableBlock->llvm(), nextBasicBlock); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -831,47 +872,10 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode) |
|
|
|
else |
|
|
|
{ |
|
|
|
// Branch to the next block.
|
|
|
|
auto iterCopy = basicBlockPairIt; |
|
|
|
++iterCopy; |
|
|
|
auto& next = iterCopy->second; |
|
|
|
m_builder.CreateBr(next); |
|
|
|
} |
|
|
|
assert(nextBasicBlock); |
|
|
|
m_builder.CreateBr(nextBasicBlock); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Code for special blocks:
|
|
|
|
// TODO: move to separate function.
|
|
|
|
// Note: Right now the codegen for special blocks depends only on createBasicBlock(),
|
|
|
|
// not on the codegen for 'regular' blocks. But it has to be done before linkBasicBlocks().
|
|
|
|
m_builder.SetInsertPoint(m_stopBB); |
|
|
|
m_builder.CreateRet(Constant::get(ReturnCode::Stop)); |
|
|
|
|
|
|
|
m_builder.SetInsertPoint(m_badJumpBlock->llvm()); |
|
|
|
m_builder.CreateRet(Constant::get(ReturnCode::BadJumpDestination)); |
|
|
|
|
|
|
|
m_builder.SetInsertPoint(m_jumpTableBlock->llvm()); |
|
|
|
if (m_indirectJumpTargets.size() > 0) |
|
|
|
{ |
|
|
|
auto& stack = m_jumpTableBlock->getStack(); |
|
|
|
|
|
|
|
auto dest = stack.pop(); |
|
|
|
auto switchInstr = m_builder.CreateSwitch(dest, m_badJumpBlock->llvm(), |
|
|
|
m_indirectJumpTargets.size()); |
|
|
|
for (auto it = m_indirectJumpTargets.cbegin(); it != m_indirectJumpTargets.cend(); ++it) |
|
|
|
{ |
|
|
|
auto& bb = *it; |
|
|
|
auto dest = Constant::get(bb->begin()); |
|
|
|
switchInstr->addCase(dest, bb->llvm()); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
m_builder.CreateBr(m_badJumpBlock->llvm()); |
|
|
|
} |
|
|
|
|
|
|
|
linkBasicBlocks(); |
|
|
|
|
|
|
|
return module; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|