mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-21 20:26:41 +00:00
parent
0961908efa
commit
e52d421955
5 changed files with 89 additions and 49 deletions
|
|
@ -6,8 +6,9 @@
|
||||||
namespace evmcc
|
namespace evmcc
|
||||||
{
|
{
|
||||||
|
|
||||||
BasicBlock::BasicBlock(ProgramCounter _instIdx, llvm::Function* _mainFunc)
|
BasicBlock::BasicBlock(ProgramCounter _beginInstIdx, llvm::Function* _mainFunc):
|
||||||
: m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {"Instr.", std::to_string(_instIdx)}, _mainFunc))
|
m_beginInstIdx(_beginInstIdx),
|
||||||
|
m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {"Instr.", std::to_string(_beginInstIdx)}, _mainFunc))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <llvm/IR/BasicBlock.h>
|
#include <llvm/IR/BasicBlock.h>
|
||||||
|
|
||||||
namespace evmcc
|
namespace evmcc
|
||||||
|
|
@ -9,14 +11,24 @@ using ProgramCounter = uint64_t;
|
||||||
class BasicBlock
|
class BasicBlock
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit BasicBlock(ProgramCounter _instIdx, llvm::Function* _mainFunc);
|
using State = std::vector<llvm::Value*>;
|
||||||
|
|
||||||
|
explicit BasicBlock(ProgramCounter _beginInstIdx, llvm::Function* _mainFunc);
|
||||||
|
|
||||||
BasicBlock(const BasicBlock&) = delete;
|
BasicBlock(const BasicBlock&) = delete;
|
||||||
void operator=(const BasicBlock&) = delete;
|
void operator=(const BasicBlock&) = delete;
|
||||||
|
|
||||||
operator llvm::BasicBlock*() { return m_llvmBB; }
|
operator llvm::BasicBlock*() { return m_llvmBB; }
|
||||||
|
llvm::BasicBlock* llvm() { return m_llvmBB; }
|
||||||
|
|
||||||
|
State& getState() { return m_state; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
ProgramCounter m_beginInstIdx;
|
||||||
llvm::BasicBlock* m_llvmBB;
|
llvm::BasicBlock* m_llvmBB;
|
||||||
|
|
||||||
|
/// Basic black state vector - current/end values and their positions
|
||||||
|
State m_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#include "Compiler.h"
|
#include "Compiler.h"
|
||||||
|
|
||||||
#include <llvm/IR/IRBuilder.h>
|
#include <llvm/IR/IRBuilder.h>
|
||||||
|
#include <llvm/IR/CFG.h>
|
||||||
|
|
||||||
#include <libevmface/Instruction.h>
|
#include <libevmface/Instruction.h>
|
||||||
|
|
||||||
|
|
@ -183,8 +184,8 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
|
||||||
auto memory = Memory(builder, module.get());
|
auto memory = Memory(builder, module.get());
|
||||||
auto ext = Ext(builder, module.get());
|
auto ext = Ext(builder, module.get());
|
||||||
|
|
||||||
llvm::BasicBlock* currentBlock = entryBlock;
|
BasicBlock* currentBlock = &basicBlocks.find(0)->second; // Any value, just to create branch for %entry to %Instr.0
|
||||||
BBStack stack(extStack); // Stack for current block
|
BBStack stack(builder, extStack); // Stack for current block
|
||||||
|
|
||||||
for (auto pc = bytecode.cbegin(); pc != bytecode.cend(); ++pc)
|
for (auto pc = bytecode.cbegin(); pc != bytecode.cend(); ++pc)
|
||||||
{
|
{
|
||||||
|
|
@ -192,6 +193,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
|
||||||
|
|
||||||
ProgramCounter currentPC = pc - bytecode.cbegin();
|
ProgramCounter currentPC = pc - bytecode.cbegin();
|
||||||
|
|
||||||
|
// Change basic block
|
||||||
auto blockIter = basicBlocks.find(currentPC);
|
auto blockIter = basicBlocks.find(currentPC);
|
||||||
if (blockIter != basicBlocks.end())
|
if (blockIter != basicBlocks.end())
|
||||||
{
|
{
|
||||||
|
|
@ -201,8 +203,8 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
|
||||||
builder.CreateBr(nextBlock);
|
builder.CreateBr(nextBlock);
|
||||||
// Insert the next block into the main function.
|
// Insert the next block into the main function.
|
||||||
builder.SetInsertPoint(nextBlock);
|
builder.SetInsertPoint(nextBlock);
|
||||||
currentBlock = nextBlock;
|
currentBlock = &nextBlock;
|
||||||
assert(stack.empty()); // Stack should be empty
|
stack.setBasicBlock(*currentBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(currentBlock != nullptr);
|
assert(currentBlock != nullptr);
|
||||||
|
|
@ -569,7 +571,6 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
|
||||||
// The target address is computed at compile time,
|
// The target address is computed at compile time,
|
||||||
// just pop it without looking...
|
// just pop it without looking...
|
||||||
stack.pop();
|
stack.pop();
|
||||||
stack.reset();
|
|
||||||
|
|
||||||
auto targetBlock = jumpTargets[currentPC];
|
auto targetBlock = jumpTargets[currentPC];
|
||||||
builder.CreateBr(targetBlock);
|
builder.CreateBr(targetBlock);
|
||||||
|
|
@ -589,7 +590,6 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
|
||||||
auto top = stack.pop();
|
auto top = stack.pop();
|
||||||
auto zero = ConstantInt::get(Types.word256, 0);
|
auto zero = ConstantInt::get(Types.word256, 0);
|
||||||
auto cond = builder.CreateICmpNE(top, zero, "nonzero");
|
auto cond = builder.CreateICmpNE(top, zero, "nonzero");
|
||||||
stack.reset();
|
|
||||||
auto targetBlock = jumpTargets[currentPC];
|
auto targetBlock = jumpTargets[currentPC];
|
||||||
auto& followBlock = basicBlocks.find(currentPC + 1)->second;
|
auto& followBlock = basicBlocks.find(currentPC + 1)->second;
|
||||||
builder.CreateCondBr(cond, targetBlock, followBlock);
|
builder.CreateCondBr(cond, targetBlock, followBlock);
|
||||||
|
|
@ -756,7 +756,6 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
|
||||||
ret = builder.CreateOr(ret, size);
|
ret = builder.CreateOr(ret, size);
|
||||||
|
|
||||||
builder.CreateRet(ret);
|
builder.CreateRet(ret);
|
||||||
stack.clear();
|
|
||||||
currentBlock = nullptr;
|
currentBlock = nullptr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -770,7 +769,6 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
|
||||||
case Instruction::STOP:
|
case Instruction::STOP:
|
||||||
{
|
{
|
||||||
builder.CreateRet(builder.getInt64(0));
|
builder.CreateRet(builder.getInt64(0));
|
||||||
stack.clear();
|
|
||||||
currentBlock = nullptr;
|
currentBlock = nullptr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -790,6 +788,39 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
|
||||||
builder.SetInsertPoint(finalBlock);
|
builder.SetInsertPoint(finalBlock);
|
||||||
builder.CreateRet(builder.getInt64(0));
|
builder.CreateRet(builder.getInt64(0));
|
||||||
|
|
||||||
|
auto findBB = [this](llvm::BasicBlock* _llvmBB)
|
||||||
|
{
|
||||||
|
for (auto&& bb : basicBlocks)
|
||||||
|
{
|
||||||
|
if (bb.second.llvm() == _llvmBB)
|
||||||
|
return &bb.second;
|
||||||
|
}
|
||||||
|
return (BasicBlock*)nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Link basic blocks
|
||||||
|
for (auto&& p : basicBlocks)
|
||||||
|
{
|
||||||
|
BasicBlock& bb = p.second;
|
||||||
|
llvm::BasicBlock* llvmBB = bb.llvm();
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
for (auto& inst : *llvmBB)
|
||||||
|
{
|
||||||
|
if (auto phi = llvm::dyn_cast<llvm::PHINode>(&inst))
|
||||||
|
{
|
||||||
|
for (auto preIt = llvm::pred_begin(llvmBB); preIt != llvm::pred_end(llvmBB); ++preIt)
|
||||||
|
{
|
||||||
|
llvm::BasicBlock* preBB = *preIt;
|
||||||
|
auto pbb = findBB(preBB);
|
||||||
|
assert(i < pbb->getState().size()); // TODO: Report error
|
||||||
|
phi->addIncoming(*(pbb->getState().rbegin() + i), preBB);
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include <llvm/IR/Function.h>
|
#include <llvm/IR/Function.h>
|
||||||
|
|
||||||
|
#include "BasicBlock.h"
|
||||||
#include "Runtime.h"
|
#include "Runtime.h"
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
|
@ -20,52 +21,55 @@
|
||||||
namespace evmcc
|
namespace evmcc
|
||||||
{
|
{
|
||||||
|
|
||||||
BBStack::BBStack(Stack& _extStack)
|
BBStack::BBStack(llvm::IRBuilder<>& _builder, Stack& _extStack):
|
||||||
: m_extStack(_extStack)
|
m_extStack(_extStack),
|
||||||
|
m_builder(_builder)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void BBStack::push(llvm::Value* _value)
|
void BBStack::push(llvm::Value* _value)
|
||||||
{
|
{
|
||||||
m_state.push_back(_value);
|
m_block->getState().push_back(_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Value* BBStack::pop()
|
llvm::Value* BBStack::pop()
|
||||||
{
|
{
|
||||||
if (m_state.empty())
|
auto&& state = m_block->getState();
|
||||||
return m_extStack.pop();
|
if (state.empty())
|
||||||
|
{
|
||||||
|
// Create PHI node
|
||||||
|
auto first = m_block->llvm()->getFirstNonPHI();
|
||||||
|
auto llvmBB = m_block->llvm();
|
||||||
|
if (llvmBB->getInstList().empty())
|
||||||
|
return llvm::PHINode::Create(m_builder.getIntNTy(256), 0, {}, m_block->llvm());
|
||||||
|
return llvm::PHINode::Create(m_builder.getIntNTy(256), 0, {}, llvmBB->getFirstNonPHI());
|
||||||
|
}
|
||||||
|
|
||||||
auto top = m_state.back();
|
auto top = state.back();
|
||||||
m_state.pop_back();
|
state.pop_back();
|
||||||
return top;
|
return top;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BBStack::reset()
|
void BBStack::setBasicBlock(BasicBlock& _newBlock)
|
||||||
{
|
{
|
||||||
for (auto&& value : m_state)
|
// Current block keeps end state
|
||||||
m_extStack.push(value);
|
// Just update pointer to current block
|
||||||
m_state.clear();
|
// New block should have empty state
|
||||||
}
|
assert(_newBlock.getState().empty());
|
||||||
|
m_block = &_newBlock;
|
||||||
void BBStack::clear()
|
|
||||||
{
|
|
||||||
m_state.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BBStack::empty() const
|
|
||||||
{
|
|
||||||
return m_state.empty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BBStack::dup(size_t _index)
|
void BBStack::dup(size_t _index)
|
||||||
{
|
{
|
||||||
auto value = *(m_state.rbegin() + _index);
|
auto&& state = m_block->getState();
|
||||||
m_state.push_back(value);
|
auto value = *(state.rbegin() + _index);
|
||||||
|
state.push_back(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BBStack::swap(size_t _index)
|
void BBStack::swap(size_t _index)
|
||||||
{
|
{
|
||||||
assert(_index != 0);
|
assert(_index != 0);
|
||||||
std::swap(*m_state.rbegin(), *(m_state.rbegin() + _index));
|
auto&& state = m_block->getState();
|
||||||
|
std::swap(*state.rbegin(), *(state.rbegin() + _index));
|
||||||
}
|
}
|
||||||
|
|
||||||
Stack::Stack(llvm::IRBuilder<>& _builder, llvm::Module* _module)
|
Stack::Stack(llvm::IRBuilder<>& _builder, llvm::Module* _module)
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
namespace evmcc
|
namespace evmcc
|
||||||
{
|
{
|
||||||
|
class BasicBlock;
|
||||||
|
|
||||||
class Stack
|
class Stack
|
||||||
{
|
{
|
||||||
|
|
@ -36,7 +37,7 @@ private:
|
||||||
class BBStack
|
class BBStack
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BBStack(Stack& _extStack);
|
BBStack(llvm::IRBuilder<>& _builder, Stack& _extStack);
|
||||||
|
|
||||||
void push(llvm::Value* _value);
|
void push(llvm::Value* _value);
|
||||||
llvm::Value* pop();
|
llvm::Value* pop();
|
||||||
|
|
@ -44,23 +45,14 @@ public:
|
||||||
void swap(size_t _index);
|
void swap(size_t _index);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Resets stack on basic block change.
|
Changes current basic block with a new one with empty state.
|
||||||
Values left on local stack are pushed on external stack.
|
|
||||||
Local stack is empty after this operation and compilation of new basic block can be started.
|
|
||||||
*/
|
*/
|
||||||
void reset();
|
void setBasicBlock(BasicBlock& _newBlock);
|
||||||
|
|
||||||
/**
|
|
||||||
Dumps values on stack.
|
|
||||||
*/
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
/// Debug only
|
|
||||||
bool empty() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<llvm::Value*> m_state; ///< Basic black state vector - current values and their positions
|
|
||||||
Stack& m_extStack; ///< External (global) stack
|
Stack& m_extStack; ///< External (global) stack
|
||||||
|
BasicBlock* m_block = nullptr; ///< Current basic block
|
||||||
|
llvm::IRBuilder<>& m_builder;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue