Browse Source

Merge branch 'develop-evmcc' of github.com:imapp-pl/ethereum into develop-evmcc

cl-refactor
artur-zawlocki 10 years ago
parent
commit
ad43b92d97
  1. 29
      evmcc/BasicBlock.cpp
  2. 2
      evmcc/BasicBlock.h
  3. 3
      evmcc/Compiler.cpp
  4. 41
      evmcc/GasMeter.cpp
  5. 4
      evmcc/GasMeter.h

29
evmcc/BasicBlock.cpp

@ -33,17 +33,27 @@ void BasicBlock::Stack::push(llvm::Value* _value)
llvm::Value* BasicBlock::Stack::pop()
{
if (m_backend.empty())
auto top = get(0);
m_backend.pop_back();
return top;
}
llvm::Value* BasicBlock::Stack::get(size_t _index)
{
if (_index >= m_backend.size())
{
// Create PHI node
if (m_llvmBB->empty())
return llvm::PHINode::Create(Type::i256, 0, {}, m_llvmBB);
return llvm::PHINode::Create(Type::i256, 0, {}, m_llvmBB->getFirstNonPHI());
// Create PHI node for missing values
auto nMissingVals = _index - m_backend.size() + 1;
m_backend.insert(m_backend.begin(), nMissingVals, nullptr);
for (decltype(nMissingVals) i = 0; i < nMissingVals; ++i)
{
m_backend[i] = m_llvmBB->empty() ?
llvm::PHINode::Create(Type::i256, 0, {}, m_llvmBB) :
llvm::PHINode::Create(Type::i256, 0, {}, m_llvmBB->getFirstNonPHI());
}
}
auto top = m_backend.back();
m_backend.pop_back();
return top;
return *(m_backend.rbegin() + _index);
}
void BasicBlock::Stack::dup(size_t _index)
@ -54,7 +64,8 @@ void BasicBlock::Stack::dup(size_t _index)
void BasicBlock::Stack::swap(size_t _index)
{
assert(_index != 0);
std::swap(get(0), get(_index));
get(_index); // Create PHI nodes
std::swap(*m_backend.rbegin(), *(m_backend.rbegin() + _index));
}
}

2
evmcc/BasicBlock.h

@ -21,7 +21,7 @@ public:
llvm::Value* pop();
/// Gets _index'th value from top (counting from 0)
llvm::Value*& get(size_t _index) { return *(m_backend.rbegin() + _index); }
llvm::Value* get(size_t _index);
/// Duplicates _index'th value on stack.
void dup(size_t _index);

3
evmcc/Compiler.cpp

@ -213,8 +213,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
{
auto inst = static_cast<Instruction>(bytecode[currentPC]);
// Disable for now
//gasMeter.check(inst);
gasMeter.check(inst);
switch (inst)
{

41
evmcc/GasMeter.cpp

@ -49,6 +49,33 @@ uint64_t getStepCost(dev::eth::Instruction inst) // TODO: Add this function to F
}
}
bool isCommitTrigger(Instruction _inst)
{
switch (_inst)
{
case Instruction::STOP:
case Instruction::CALLDATACOPY:
case Instruction::CODECOPY:
case Instruction::MLOAD:
case Instruction::MSTORE:
case Instruction::MSTORE8:
case Instruction::SSTORE:
case Instruction::JUMP:
case Instruction::JUMPI:
case Instruction::JUMPDEST:
case Instruction::GAS:
case Instruction::CREATE:
case Instruction::CALL:
case Instruction::CALLCODE:
case Instruction::RETURN:
case Instruction::SUICIDE:
return true;
default:
return false;
}
}
}
GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module):
@ -72,8 +99,20 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module):
void GasMeter::check(Instruction _inst)
{
if (!m_checkCall)
{
m_checkCall = m_builder.CreateCall(m_gasCheckFunc, m_builder.getIntN(256, 0));
}
auto stepCost = getStepCost(_inst);
m_builder.CreateCall(m_gasCheckFunc, m_builder.getIntN(256, stepCost));
m_blockCost += stepCost;
auto isTrigger = isCommitTrigger(_inst);
if (isTrigger)
{
m_checkCall->setArgOperand(0, m_builder.getIntN(256, m_blockCost));
m_checkCall = nullptr;
}
}
}

4
evmcc/GasMeter.h

@ -19,7 +19,11 @@ public:
void check(dev::eth::Instruction _inst);
private:
/// Cumulative gas cost of a block of instructions
/// @TODO Handle overflow
uint64_t m_blockCost = 0;
llvm::IRBuilder<>& m_builder;
llvm::CallInst* m_checkCall;
llvm::GlobalVariable* m_gas;
llvm::Function* m_gasCheckFunc;
};

Loading…
Cancel
Save