diff --git a/evmcc/bytecode/if1.evm b/evmcc/bytecode/if1.evm deleted file mode 100644 index ee90092945..0000000000 --- a/evmcc/bytecode/if1.evm +++ /dev/null @@ -1 +0,0 @@ -600160805460006080530b6016596003608054601b586002608054 diff --git a/evmcc/evmcc.cpp b/evmcc/evmcc.cpp index 22ba1db50f..9cf7314193 100644 --- a/evmcc/evmcc.cpp +++ b/evmcc/evmcc.cpp @@ -12,9 +12,8 @@ #include #include #include - -#include "Compiler.h" -#include "ExecutionEngine.h" +#include +#include void show_usage() @@ -95,7 +94,7 @@ int main(int argc, char** argv) if (opt_compile) { auto compiler = eth::jit::Compiler(); - auto module = compiler.compile(bytecode); + auto module = compiler.compile({bytecode.data(), bytecode.size()}); llvm::raw_os_ostream out(std::cout); module->print(out, nullptr); @@ -111,9 +110,10 @@ int main(int argc, char** argv) if (opt_interpret) { auto engine = eth::jit::ExecutionEngine(); - auto module = eth::jit::Compiler().compile(bytecode); + auto module = eth::jit::Compiler().compile({bytecode.data(), bytecode.size()}); module->dump(); - auto result = engine.run(std::move(module)); + u256 gas = 10000; + auto result = engine.run(std::move(module), gas); return result; } diff --git a/evmcc/lll/if1.asm b/evmcc/lll/if1.asm deleted file mode 100644 index 4a938adcec..0000000000 --- a/evmcc/lll/if1.asm +++ /dev/null @@ -1,21 +0,0 @@ -.code: - PUSH 1 - PUSH 128 - MSTORE - PUSH 0 - PUSH 128 - MLOAD - GT - PUSH [tag0] - JUMPI - PUSH 3 - PUSH 128 - MSTORE - PUSH [tag1] - JUMP -tag0: - PUSH 2 - PUSH 128 - MSTORE -tag1: - diff --git a/evmcc/lll/if1.lll b/evmcc/lll/if1.lll deleted file mode 100644 index 7984807c1f..0000000000 --- a/evmcc/lll/if1.lll +++ /dev/null @@ -1,5 +0,0 @@ -{ - [i] 1 - - ( if (> @i 0) [i] 2 [i] 3 ) -} diff --git a/evmcc/bytecode/arithmetic_test.evm b/evmcc/test/arith/arith1.evm similarity index 100% rename from evmcc/bytecode/arithmetic_test.evm rename to evmcc/test/arith/arith1.evm diff --git a/evmcc/lll/arithmetic_test.lll b/evmcc/test/arith/arith1.lll similarity index 100% rename from evmcc/lll/arithmetic_test.lll rename to evmcc/test/arith/arith1.lll diff --git a/evmcc/bytecode/fib1.evm b/evmcc/test/arith/fib1.evm similarity index 100% rename from evmcc/bytecode/fib1.evm rename to evmcc/test/arith/fib1.evm diff --git a/evmcc/lll/fib1.lll b/evmcc/test/arith/fib1.lll similarity index 100% rename from evmcc/lll/fib1.lll rename to evmcc/test/arith/fib1.lll diff --git a/evmcc/bytecode/ext_test.evm b/evmcc/test/ext/ext_test.evm similarity index 100% rename from evmcc/bytecode/ext_test.evm rename to evmcc/test/ext/ext_test.evm diff --git a/evmcc/lll/ext_test.lll b/evmcc/test/ext/ext_test.lll similarity index 100% rename from evmcc/lll/ext_test.lll rename to evmcc/test/ext/ext_test.lll diff --git a/evmcc/bytecode/store_test.evm b/evmcc/test/ext/store_test.evm similarity index 100% rename from evmcc/bytecode/store_test.evm rename to evmcc/test/ext/store_test.evm diff --git a/evmcc/lll/store_test.lll b/evmcc/test/ext/store_test.lll similarity index 100% rename from evmcc/lll/store_test.lll rename to evmcc/test/ext/store_test.lll diff --git a/evmcc/bytecode/for1.evm b/evmcc/test/jump/for1.evm similarity index 100% rename from evmcc/bytecode/for1.evm rename to evmcc/test/jump/for1.evm diff --git a/evmcc/lll/for1.lll b/evmcc/test/jump/for1.lll similarity index 100% rename from evmcc/lll/for1.lll rename to evmcc/test/jump/for1.lll diff --git a/evmcc/bytecode/for2.evm b/evmcc/test/jump/for2.evm similarity index 100% rename from evmcc/bytecode/for2.evm rename to evmcc/test/jump/for2.evm diff --git a/evmcc/lll/for2.lll b/evmcc/test/jump/for2.lll similarity index 100% rename from evmcc/lll/for2.lll rename to evmcc/test/jump/for2.lll diff --git a/evmcc/lll/when1.asm b/evmcc/test/jump/when1.asm similarity index 100% rename from evmcc/lll/when1.asm rename to evmcc/test/jump/when1.asm diff --git a/evmcc/bytecode/when1.evm b/evmcc/test/jump/when1.evm similarity index 100% rename from evmcc/bytecode/when1.evm rename to evmcc/test/jump/when1.evm diff --git a/evmcc/lll/when1.lll b/evmcc/test/jump/when1.lll similarity index 100% rename from evmcc/lll/when1.lll rename to evmcc/test/jump/when1.lll diff --git a/evmcc/bytecode/kv.evm b/evmcc/test/kv.evm similarity index 100% rename from evmcc/bytecode/kv.evm rename to evmcc/test/kv.evm diff --git a/evmcc/lll/kv.lll b/evmcc/test/kv.lll similarity index 100% rename from evmcc/lll/kv.lll rename to evmcc/test/kv.lll diff --git a/evmcc/bytecode/byte.evm b/evmcc/test/mem/byte.evm similarity index 100% rename from evmcc/bytecode/byte.evm rename to evmcc/test/mem/byte.evm diff --git a/evmcc/lll/byte.lll b/evmcc/test/mem/byte.lll similarity index 100% rename from evmcc/lll/byte.lll rename to evmcc/test/mem/byte.lll diff --git a/evmcc/bytecode/mem2.evm b/evmcc/test/mem/mem2.evm similarity index 100% rename from evmcc/bytecode/mem2.evm rename to evmcc/test/mem/mem2.evm diff --git a/evmcc/lll/mem2.lll b/evmcc/test/mem/mem2.lll similarity index 100% rename from evmcc/lll/mem2.lll rename to evmcc/test/mem/mem2.lll diff --git a/evmcc/bytecode/memtest1.evm b/evmcc/test/mem/memtest1.evm similarity index 100% rename from evmcc/bytecode/memtest1.evm rename to evmcc/test/mem/memtest1.evm diff --git a/evmcc/lll/memtest1.lll b/evmcc/test/mem/memtest1.lll similarity index 100% rename from evmcc/lll/memtest1.lll rename to evmcc/test/mem/memtest1.lll diff --git a/evmcc/bytecode/return1.evm b/evmcc/test/ret/return1.evm similarity index 100% rename from evmcc/bytecode/return1.evm rename to evmcc/test/ret/return1.evm diff --git a/evmcc/lll/return1.lll b/evmcc/test/ret/return1.lll similarity index 100% rename from evmcc/lll/return1.lll rename to evmcc/test/ret/return1.lll diff --git a/evmcc/bytecode/return2.evm b/evmcc/test/ret/return2.evm similarity index 100% rename from evmcc/bytecode/return2.evm rename to evmcc/test/ret/return2.evm diff --git a/evmcc/lll/return2.lll b/evmcc/test/ret/return2.lll similarity index 100% rename from evmcc/lll/return2.lll rename to evmcc/test/ret/return2.lll diff --git a/evmcc/bytecode/return_test.evm b/evmcc/test/ret/return_test.evm similarity index 100% rename from evmcc/bytecode/return_test.evm rename to evmcc/test/ret/return_test.evm diff --git a/evmcc/lll/return_test.lll b/evmcc/test/ret/return_test.lll similarity index 100% rename from evmcc/lll/return_test.lll rename to evmcc/test/ret/return_test.lll diff --git a/evmcc/bytecode/push_test.evm b/evmcc/test/stack/push_test.evm similarity index 100% rename from evmcc/bytecode/push_test.evm rename to evmcc/test/stack/push_test.evm diff --git a/evmcc/lll/push_test.lll b/evmcc/test/stack/push_test.lll similarity index 100% rename from evmcc/lll/push_test.lll rename to evmcc/test/stack/push_test.lll diff --git a/evmcc/bytecode/stack_test.evm b/evmcc/test/stack/stack_test.evm similarity index 100% rename from evmcc/bytecode/stack_test.evm rename to evmcc/test/stack/stack_test.evm diff --git a/evmcc/lll/stack_test.lll b/evmcc/test/stack/stack_test.lll similarity index 100% rename from evmcc/lll/stack_test.lll rename to evmcc/test/stack/stack_test.lll diff --git a/evmcc/bytecode/stackjump.evm b/evmcc/test/stack/stackjump.evm similarity index 100% rename from evmcc/bytecode/stackjump.evm rename to evmcc/test/stack/stackjump.evm diff --git a/evmcc/lll/stackjump.lll b/evmcc/test/stack/stackjump.lll similarity index 100% rename from evmcc/lll/stackjump.lll rename to evmcc/test/stack/stackjump.lll diff --git a/evmcc/BasicBlock.cpp b/libevmjit/BasicBlock.cpp similarity index 100% rename from evmcc/BasicBlock.cpp rename to libevmjit/BasicBlock.cpp diff --git a/evmcc/BasicBlock.h b/libevmjit/BasicBlock.h similarity index 100% rename from evmcc/BasicBlock.h rename to libevmjit/BasicBlock.h diff --git a/evmcc/Compiler.cpp b/libevmjit/Compiler.cpp similarity index 94% rename from evmcc/Compiler.cpp rename to libevmjit/Compiler.cpp index c2c8376fd6..f3e9121250 100644 --- a/evmcc/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -29,7 +29,7 @@ Compiler::Compiler(): Type::init(m_builder.getContext()); } -void Compiler::createBasicBlocks(const bytes& bytecode) +void Compiler::createBasicBlocks(bytesConstRef bytecode) { std::set splitPoints; // Sorted collections of instruction indices where basic blocks start/end splitPoints.insert(0); // First basic block @@ -38,9 +38,9 @@ void Compiler::createBasicBlocks(const bytes& bytecode) std::vector indirectJumpTargets; boost::dynamic_bitset<> validJumpTargets(bytecode.size()); - for (auto curr = bytecode.cbegin(); curr != bytecode.cend(); ++curr) + for (auto curr = bytecode.begin(); curr != bytecode.end(); ++curr) { - ProgramCounter currentPC = curr - bytecode.cbegin(); + ProgramCounter currentPC = curr - bytecode.begin(); validJumpTargets[currentPC] = 1; auto inst = static_cast(*curr); @@ -51,7 +51,7 @@ void Compiler::createBasicBlocks(const bytes& bytecode) { auto numBytes = static_cast(inst) - static_cast(Instruction::PUSH1) + 1; auto next = curr + numBytes + 1; - if (next >= bytecode.cend()) + if (next >= bytecode.end()) break; auto nextInst = static_cast(*next); @@ -67,12 +67,10 @@ void Compiler::createBasicBlocks(const bytes& bytecode) } // Create a block for the JUMP target. - ProgramCounter targetPC = val.convert_to(); - if (targetPC > bytecode.size()) - targetPC = bytecode.size(); + ProgramCounter targetPC = val < bytecode.size() ? val.convert_to() : bytecode.size(); splitPoints.insert(targetPC); - ProgramCounter jumpPC = (next - bytecode.cbegin()); + ProgramCounter jumpPC = (next - bytecode.begin()); directJumpTargets[jumpPC] = targetPC; } @@ -95,7 +93,7 @@ void Compiler::createBasicBlocks(const bytes& bytecode) case Instruction::SUICIDE: { // Create a basic block starting at the following instruction. - if (curr + 1 < bytecode.cend()) + if (curr + 1 < bytecode.end()) { splitPoints.insert(currentPC + 1); } @@ -130,16 +128,23 @@ void Compiler::createBasicBlocks(const bytes& bytecode) for (auto it = directJumpTargets.cbegin(); it != directJumpTargets.cend(); ++it) { + if (it->second >= bytecode.size()) + { + // Jumping out of code means STOP + m_directJumpTargets[it->first] = m_stopBB; + continue; + } + auto blockIter = basicBlocks.find(it->second); if (blockIter != basicBlocks.end()) { - m_directJumpTargets[it->first] = &(blockIter->second); + m_directJumpTargets[it->first] = blockIter->second.llvm(); } else { std::cerr << "Bad JUMP at PC " << it->first << ": " << it->second << " is not a valid PC\n"; - m_directJumpTargets[it->first] = m_badJumpBlock.get(); + m_directJumpTargets[it->first] = m_badJumpBlock->llvm(); } } @@ -149,7 +154,7 @@ void Compiler::createBasicBlocks(const bytes& bytecode) } } -std::unique_ptr Compiler::compile(const bytes& bytecode) +std::unique_ptr Compiler::compile(bytesConstRef bytecode) { auto module = std::make_unique("main", m_builder.getContext()); @@ -214,7 +219,7 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) } -void Compiler::compileBasicBlock(BasicBlock& basicBlock, const bytes& bytecode, Memory& memory, Ext& ext, GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock) +void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, Memory& memory, Ext& ext, GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock) { auto& stack = basicBlock.getStack(); m_builder.SetInsertPoint(basicBlock.llvm()); @@ -567,7 +572,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, const bytes& bytecode, // 1. this is not the first instruction in the block // 2. m_directJumpTargets[currentPC] is defined (meaning that the previous instruction is a PUSH) // Otherwise generate a indirect jump (a switch). - BasicBlock* targetBlock = nullptr; + llvm::BasicBlock* targetBlock = nullptr; if (currentPC != basicBlock.begin()) { auto pairIter = m_directJumpTargets.find(currentPC); @@ -584,7 +589,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, const bytes& bytecode, // The target address is computed at compile time, // just pop it without looking... stack.pop(); - m_builder.CreateBr(targetBlock->llvm()); + m_builder.CreateBr(targetBlock); } else { @@ -606,7 +611,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, const bytes& bytecode, if (targetBlock) { stack.pop(); - m_builder.CreateCondBr(cond, targetBlock->llvm(), nextBasicBlock); + m_builder.CreateCondBr(cond, targetBlock, nextBasicBlock); } else { @@ -923,10 +928,18 @@ void Compiler::linkBasicBlocks() for (auto it = llvm::po_ext_begin(bb.second.llvm(), visitSet), end = llvm::po_ext_end(bb.second.llvm(), visitSet); it != end; ++it) { - std::cerr << it->getName().str() << std::endl; + // TODO: Use logger + //std::cerr << it->getName().str() << std::endl; completePhiNodes(*it); } } + + // Remove jump table block if not predecessors + if (llvm::pred_begin(m_jumpTableBlock->llvm()) == llvm::pred_end(m_jumpTableBlock->llvm())) + { + m_jumpTableBlock->llvm()->eraseFromParent(); + m_jumpTableBlock.reset(); + } } void Compiler::dumpBasicBlockGraph(std::ostream& out) diff --git a/evmcc/Compiler.h b/libevmjit/Compiler.h similarity index 75% rename from evmcc/Compiler.h rename to libevmjit/Compiler.h index bda1546890..8972322ece 100644 --- a/evmcc/Compiler.h +++ b/libevmjit/Compiler.h @@ -22,16 +22,16 @@ public: Compiler(); - std::unique_ptr compile(const bytes& bytecode); + std::unique_ptr compile(bytesConstRef bytecode); void dumpBasicBlockGraph(std::ostream& out); private: - void createBasicBlocks(const bytes& bytecode); + void createBasicBlocks(bytesConstRef bytecode); - void compileBasicBlock(BasicBlock& basicBlock, const bytes& bytecode, class Memory& memory, class Ext& ext, class GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock); + void compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, class Memory& memory, class Ext& ext, class GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock); void linkBasicBlocks(); @@ -46,7 +46,7 @@ private: /** * Maps a pc at which there is a JUMP or JUMPI to the target block of the jump. */ - std::map m_directJumpTargets; + std::map m_directJumpTargets; /** * A list of possible blocks to which there may be indirect jumps. diff --git a/evmcc/CompilerHelper.cpp b/libevmjit/CompilerHelper.cpp similarity index 100% rename from evmcc/CompilerHelper.cpp rename to libevmjit/CompilerHelper.cpp diff --git a/evmcc/CompilerHelper.h b/libevmjit/CompilerHelper.h similarity index 100% rename from evmcc/CompilerHelper.h rename to libevmjit/CompilerHelper.h diff --git a/evmcc/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp similarity index 75% rename from evmcc/ExecutionEngine.cpp rename to libevmjit/ExecutionEngine.cpp index 6a494f42a6..5390d82dd3 100644 --- a/evmcc/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -36,7 +36,7 @@ ExecutionEngine::ExecutionEngine() extern "C" { EXPORT std::jmp_buf* rt_jmpBuf; } -int ExecutionEngine::run(std::unique_ptr _module) +int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, ExtVMFace* _ext) { auto module = _module.get(); // Keep ownership of the module in _module @@ -81,26 +81,28 @@ int ExecutionEngine::run(std::unique_ptr _module) exec->finalizeObject(); // Create fake ExtVM interface - auto ext = std::make_unique(); - ext->myAddress = Address(1122334455667788); - ext->caller = Address(0xfacefacefaceface); - ext->origin = Address(101010101010101010); - ext->value = 0xabcd; - ext->gasPrice = 1002; - ext->previousBlock.hash = u256(1003); - ext->currentBlock.coinbaseAddress = Address(1004); - ext->currentBlock.timestamp = 1005; - ext->currentBlock.number = 1006; - ext->currentBlock.difficulty = 1007; - ext->currentBlock.gasLimit = 1008; - std::string calldata = "Hello the Beautiful World of Ethereum!"; - ext->data = calldata; - unsigned char fakecode[] = {0x0d, 0x0e, 0x0a, 0x0d, 0x0b, 0x0e, 0xe, 0xf}; - ext->code = decltype(ext->code)(fakecode, 8); + if (!_ext) + { + _ext = new ExtVMFace; + _ext->myAddress = Address(1122334455667788); + _ext->caller = Address(0xfacefacefaceface); + _ext->origin = Address(101010101010101010); + _ext->value = 0xabcd; + _ext->gasPrice = 1002; + _ext->previousBlock.hash = u256(1003); + _ext->currentBlock.coinbaseAddress = Address(1004); + _ext->currentBlock.timestamp = 1005; + _ext->currentBlock.number = 1006; + _ext->currentBlock.difficulty = 1007; + _ext->currentBlock.gasLimit = 1008; + std::string calldata = "Hello the Beautiful World of Ethereum!"; + _ext->data = calldata; + unsigned char fakecode[] = {0x0d, 0x0e, 0x0a, 0x0d, 0x0b, 0x0e, 0xe, 0xf}; + _ext->code = decltype(_ext->code)(fakecode, 8); + } // Init runtime - uint64_t gas = 100; - Runtime runtime(gas, std::move(ext)); + Runtime runtime(_gas, *_ext); auto entryFunc = module->getFunction("main"); if (!entryFunc) @@ -121,11 +123,11 @@ int ExecutionEngine::run(std::unique_ptr _module) else returnCode = static_cast(r); - gas = static_cast(Runtime::getGas()); + _gas = Runtime::getGas(); if (returnCode == ReturnCode::Return) { - auto&& returnData = Memory::getReturnData(); // TODO: It might be better to place is in Runtime interface + returnData = Memory::getReturnData().toVector(); // TODO: It might be better to place is in Runtime interface std::cout << "RETURN [ "; for (auto it = returnData.begin(), end = returnData.end(); it != end; ++it) diff --git a/evmcc/ExecutionEngine.h b/libevmjit/ExecutionEngine.h similarity index 57% rename from evmcc/ExecutionEngine.h rename to libevmjit/ExecutionEngine.h index 158df0283b..15a4e6ef72 100644 --- a/evmcc/ExecutionEngine.h +++ b/libevmjit/ExecutionEngine.h @@ -4,6 +4,7 @@ #include #include +#include namespace dev { @@ -17,7 +18,9 @@ class ExecutionEngine public: ExecutionEngine(); - int run(std::unique_ptr module); + int run(std::unique_ptr module, u256& _gas, ExtVMFace* _ext = nullptr); + + bytes returnData; }; } diff --git a/evmcc/Ext.cpp b/libevmjit/Ext.cpp similarity index 99% rename from evmcc/Ext.cpp rename to libevmjit/Ext.cpp index 5307bc1911..5c4bb7c593 100644 --- a/evmcc/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -61,7 +61,7 @@ Ext::Ext(llvm::IRBuilder<>& _builder): m_arg5 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg5"); m_arg6 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg6"); m_arg7 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg7"); - m_arg7 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg8"); + m_arg8 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg8"); Type* elements[] = { i256Ty, // i256 address; diff --git a/evmcc/Ext.h b/libevmjit/Ext.h similarity index 100% rename from evmcc/Ext.h rename to libevmjit/Ext.h diff --git a/evmcc/GasMeter.cpp b/libevmjit/GasMeter.cpp similarity index 87% rename from evmcc/GasMeter.cpp rename to libevmjit/GasMeter.cpp index 9c83ba8dba..ac7f47d19c 100644 --- a/evmcc/GasMeter.cpp +++ b/libevmjit/GasMeter.cpp @@ -30,26 +30,26 @@ uint64_t getStepCost(Instruction inst) // TODO: Add this function to FeeSructure return 0; case Instruction::SSTORE: - return static_cast(c_sstoreGas); + return static_cast(FeeStructure::c_sstoreGas); case Instruction::SLOAD: - return static_cast(c_sloadGas); + return static_cast(FeeStructure::c_sloadGas); case Instruction::SHA3: - return static_cast(c_sha3Gas); + return static_cast(FeeStructure::c_sha3Gas); case Instruction::BALANCE: - return static_cast(c_sha3Gas); + return static_cast(FeeStructure::c_sha3Gas); case Instruction::CALL: case Instruction::CALLCODE: - return static_cast(c_callGas); + return static_cast(FeeStructure::c_callGas); case Instruction::CREATE: - return static_cast(c_createGas); + return static_cast(FeeStructure::c_createGas); default: // Assumes instruction code is valid - return static_cast(c_stepGas); + return static_cast(FeeStructure::c_stepGas); } } @@ -134,7 +134,7 @@ void GasMeter::countSStore(Ext& _ext, llvm::Value* _index, llvm::Value* _newValu { assert(!m_checkCall); // Everything should've been commited before - static const auto sstoreCost = static_cast(c_sstoreGas); + static const auto sstoreCost = static_cast(FeeStructure::c_sstoreGas); // [ADD] if oldValue == 0 and newValue != 0 => 2*cost // [DEL] if oldValue != 0 and newValue == 0 => 0 @@ -165,19 +165,21 @@ void GasMeter::commitCostBlock(llvm::Value* _additionalCost) // If any uncommited block if (m_checkCall) { - if (m_blockCost == 0 && !_additionalCost) // Do not check 0 + if (m_blockCost == 0) // Do not check 0 { m_checkCall->eraseFromParent(); // Remove the gas check call + m_checkCall = nullptr; 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->setArgOperand(0, Constant::get(m_blockCost)); // Update block cost in gas check call m_checkCall = nullptr; // End cost-block m_blockCost = 0; + + if (_additionalCost) + { + m_builder.CreateCall(m_gasCheckFunc, _additionalCost); + } } assert(m_blockCost == 0); } @@ -185,7 +187,7 @@ void GasMeter::commitCostBlock(llvm::Value* _additionalCost) void GasMeter::checkMemory(llvm::Value* _additionalMemoryInWords, llvm::IRBuilder<>& _builder) { // Memory uses other builder, but that can be changes later - auto cost = _builder.CreateMul(_additionalMemoryInWords, Constant::get(static_cast(c_memoryGas)), "memcost"); + auto cost = _builder.CreateMul(_additionalMemoryInWords, Constant::get(static_cast(FeeStructure::c_memoryGas)), "memcost"); _builder.CreateCall(m_gasCheckFunc, cost); } diff --git a/evmcc/GasMeter.h b/libevmjit/GasMeter.h similarity index 100% rename from evmcc/GasMeter.h rename to libevmjit/GasMeter.h diff --git a/evmcc/Memory.cpp b/libevmjit/Memory.cpp similarity index 100% rename from evmcc/Memory.cpp rename to libevmjit/Memory.cpp diff --git a/evmcc/Memory.h b/libevmjit/Memory.h similarity index 100% rename from evmcc/Memory.h rename to libevmjit/Memory.h diff --git a/evmcc/Runtime.cpp b/libevmjit/Runtime.cpp similarity index 81% rename from evmcc/Runtime.cpp rename to libevmjit/Runtime.cpp index d85f484b3a..448d25f92f 100644 --- a/evmcc/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -19,8 +19,8 @@ extern "C" EXPORT i256 gas; } -Runtime::Runtime(u256 _gas, std::unique_ptr _ext): - m_ext(std::move(_ext)) +Runtime::Runtime(u256 _gas, ExtVMFace& _ext): + m_ext(_ext) { assert(!g_runtime); g_runtime = this; @@ -44,7 +44,7 @@ MemoryImpl& Runtime::getMemory() ExtVMFace& Runtime::getExt() { - return *g_runtime->m_ext; + return g_runtime->m_ext; } u256 Runtime::getGas() diff --git a/evmcc/Runtime.h b/libevmjit/Runtime.h similarity index 86% rename from evmcc/Runtime.h rename to libevmjit/Runtime.h index 0312e305b9..165f47e062 100644 --- a/evmcc/Runtime.h +++ b/libevmjit/Runtime.h @@ -27,7 +27,7 @@ using MemoryImpl = bytes; class Runtime { public: - Runtime(u256 _gas, std::unique_ptr _ext); + Runtime(u256 _gas, ExtVMFace& _ext); ~Runtime(); Runtime(const Runtime&) = delete; @@ -41,7 +41,7 @@ public: private: StackImpl m_stack; MemoryImpl m_memory; - std::unique_ptr m_ext; + ExtVMFace& m_ext; }; } diff --git a/evmcc/Type.cpp b/libevmjit/Type.cpp similarity index 100% rename from evmcc/Type.cpp rename to libevmjit/Type.cpp diff --git a/evmcc/Type.h b/libevmjit/Type.h similarity index 100% rename from evmcc/Type.h rename to libevmjit/Type.h diff --git a/evmcc/Utils.cpp b/libevmjit/Utils.cpp similarity index 100% rename from evmcc/Utils.cpp rename to libevmjit/Utils.cpp diff --git a/evmcc/Utils.h b/libevmjit/Utils.h similarity index 100% rename from evmcc/Utils.h rename to libevmjit/Utils.h diff --git a/libevmjit/VM.cpp b/libevmjit/VM.cpp new file mode 100644 index 0000000000..6b8b3e38bc --- /dev/null +++ b/libevmjit/VM.cpp @@ -0,0 +1,36 @@ + +#include "VM.h" + +#include + +#include "ExecutionEngine.h" +#include "Compiler.h" + +namespace dev +{ +namespace eth +{ +namespace jit +{ + +bytes VM::go(ExtVMFace& _ext) +{ + auto module = Compiler().compile(_ext.code); + + ExecutionEngine engine; + auto exitCode = engine.run(std::move(module), m_gas, &_ext); + + switch (exitCode) + { + case 101: + BOOST_THROW_EXCEPTION(BadJumpDestination()); + case 102: + BOOST_THROW_EXCEPTION(OutOfGas()); + } + + return std::move(engine.returnData); +} + +} +} +} diff --git a/libevmjit/VM.h b/libevmjit/VM.h new file mode 100644 index 0000000000..3e7884b101 --- /dev/null +++ b/libevmjit/VM.h @@ -0,0 +1,32 @@ + +#pragma once + +#include +#include + +namespace dev +{ +namespace eth +{ +namespace jit +{ + +class VM +{ +public: + /// Construct VM object. + explicit VM(u256 _gas = 0): m_gas(_gas) {} + + void reset(u256 _gas = 0) { m_gas = _gas; } + + bytes go(ExtVMFace& _ext); + + u256 gas() const { return m_gas; } + +private: + u256 m_gas = 0; +}; + +} +} +}