mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-21 20:26:41 +00:00
Basic block compilation in separated function
This commit is contained in:
parent
e094ba9e67
commit
1463897efb
2 changed files with 671 additions and 665 deletions
|
|
@ -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,49 +872,12 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
void Compiler::linkBasicBlocks()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ private:
|
|||
|
||||
void createBasicBlocks(const bytes& bytecode);
|
||||
|
||||
void compileBasicBlock(BasicBlock& basicBlock, const bytes& bytecode, class Memory& memory, class Ext& ext, class GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock);
|
||||
|
||||
void linkBasicBlocks();
|
||||
|
||||
llvm::IRBuilder<> m_builder;
|
||||
|
|
|
|||
Loading…
Reference in a new issue