diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index fd295d891..c48036d62 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -784,6 +784,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto outOff = stack.pop(); auto outSize = stack.pop(); + gasMeter.commitCostBlock(gas); auto ret = ext.call(gas, receiveAddress, value, inOff, inSize, outOff, outSize); stack.push(ret); break; diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index cd88df646..6295ffe79 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -53,6 +53,9 @@ bool isCostBlockEnd(Instruction _inst) { // Basic block terminators like STOP are not needed on the list // as cost will be commited at the end of basic block + + // CALL & CALLCODE are commited manually + switch (_inst) { case Instruction::CALLDATACOPY: @@ -63,8 +66,6 @@ bool isCostBlockEnd(Instruction _inst) case Instruction::SSTORE: case Instruction::GAS: case Instruction::CREATE: - case Instruction::CALL: - case Instruction::CALLCODE: return true; default: @@ -107,16 +108,24 @@ void GasMeter::count(Instruction _inst) commitCostBlock(); } -void GasMeter::commitCostBlock() +void GasMeter::commitCostBlock(llvm::Value* _additionalCost) { + assert(!_additionalCost || m_checkCall); // _additionalCost => m_checkCall; Must be inside cost-block + // If any uncommited block if (m_checkCall) { - if (m_blockCost > 0) // If any cost - m_checkCall->setArgOperand(0, Constant::get(m_blockCost)); // Update block cost in gas check call - else + if (m_blockCost == 0 && !_additionalCost) // Do not check 0 + { m_checkCall->eraseFromParent(); // Remove the gas check call - + return; + } + + llvm::Value* cost = Constant::get(m_blockCost); + if (_additionalCost) + cost = m_builder.CreateAdd(cost, _additionalCost); + + m_checkCall->setArgOperand(0, cost); // Update block cost in gas check call m_checkCall = nullptr; // End cost-block m_blockCost = 0; } diff --git a/evmcc/GasMeter.h b/evmcc/GasMeter.h index 1fcbe6459..3a1f7ba66 100644 --- a/evmcc/GasMeter.h +++ b/evmcc/GasMeter.h @@ -19,8 +19,9 @@ public: /// Count step cost of instruction void count(dev::eth::Instruction _inst); - /// Finalize cost block by checking gas needed for the block before the block - void commitCostBlock(); + /// Finalize cost-block by checking gas needed for the block before the block + /// @param _additionalCost adds additional cost to cost-block before commit + void commitCostBlock(llvm::Value* _additionalCost = nullptr); /// Generate code that checks the cost of additional memory used by program void checkMemory(llvm::Value* _additionalMemoryInWords, llvm::IRBuilder<>& _builder);