diff --git a/evmjit/CMakeLists.txt b/evmjit/CMakeLists.txt index 26a8010d1..222fa5b72 100644 --- a/evmjit/CMakeLists.txt +++ b/evmjit/CMakeLists.txt @@ -19,6 +19,8 @@ else() set(LLVM_LIBS "-lLLVMBitWriter -lLLVMX86CodeGen -lLLVMSelectionDAG -lLLVMAsmPrinter -lLLVMCodeGen -lLLVMScalarOpts -lLLVMInstCombine -lLLVMTransformUtils -lLLVMipa -lLLVMAnalysis -lLLVMX86AsmParser -lLLVMX86Desc -lLLVMX86Info -lLLVMX86AsmPrinter -lLLVMX86Utils -lLLVMMCJIT -lLLVMTarget -lLLVMRuntimeDyld -lLLVMObject -lLLVMMCParser -lLLVMBitReader -lLLVMExecutionEngine -lLLVMMC -lLLVMCore -lLLVMSupport -lz -lpthread -lffi -ltinfo -ldl -lm") endif() +add_definitions(-D_SCL_SECURE_NO_WARNINGS) # LLVM needs it on Windows + # Boost find_package(Boost REQUIRED) diff --git a/evmjit/libevmjit/BasicBlock.cpp b/evmjit/libevmjit/BasicBlock.cpp index d233ea744..dda0fbc36 100644 --- a/evmjit/libevmjit/BasicBlock.cpp +++ b/evmjit/libevmjit/BasicBlock.cpp @@ -20,20 +20,21 @@ namespace jit const char* BasicBlock::NamePrefix = "Instr."; -BasicBlock::BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder) : - m_beginInstIdx(_beginInstIdx), - m_endInstIdx(_endInstIdx), - m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {NamePrefix, std::to_string(_beginInstIdx)}, _mainFunc)), +BasicBlock::BasicBlock(bytes::const_iterator _begin, bytes::const_iterator _end, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder, bool isJumpDest) : + m_begin(_begin), + m_end(_end), + // TODO: Add begin index to name + m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), NamePrefix, _mainFunc)), m_stack(*this), - m_builder(_builder) + m_builder(_builder), + m_isJumpDest(isJumpDest) {} -BasicBlock::BasicBlock(std::string _name, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder) : - m_beginInstIdx(0), - m_endInstIdx(0), +BasicBlock::BasicBlock(std::string _name, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder, bool isJumpDest) : m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), _name, _mainFunc)), m_stack(*this), - m_builder(_builder) + m_builder(_builder), + m_isJumpDest(isJumpDest) {} BasicBlock::LocalStack::LocalStack(BasicBlock& _owner) : diff --git a/evmjit/libevmjit/BasicBlock.h b/evmjit/libevmjit/BasicBlock.h index 4a789a8ec..7a5364a4e 100644 --- a/evmjit/libevmjit/BasicBlock.h +++ b/evmjit/libevmjit/BasicBlock.h @@ -1,9 +1,7 @@ #pragma once - #include - #include - +#include "Common.h" #include "Stack.h" namespace dev @@ -52,23 +50,21 @@ public: BasicBlock& m_bblock; }; - /// Basic block name prefix. The rest is beging instruction index. + /// Basic block name prefix. The rest is instruction index. static const char* NamePrefix; - explicit BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder); - explicit BasicBlock(std::string _name, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder); + explicit BasicBlock(bytes::const_iterator _begin, bytes::const_iterator _end, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder, bool isJumpDest); + explicit BasicBlock(std::string _name, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder, bool isJumpDest); BasicBlock(const BasicBlock&) = delete; void operator=(const BasicBlock&) = delete; - operator llvm::BasicBlock*() { return m_llvmBB; } llvm::BasicBlock* llvm() { return m_llvmBB; } - ProgramCounter begin() { return m_beginInstIdx; } - ProgramCounter end() { return m_endInstIdx; } + bytes::const_iterator begin() { return m_begin; } + bytes::const_iterator end() { return m_end; } bool isJumpDest() const { return m_isJumpDest; } - void markAsJumpDest() { m_isJumpDest = true; } LocalStack& localStack() { return m_stack; } @@ -85,8 +81,8 @@ public: void dump(std::ostream& os, bool _dotOutput = false); private: - ProgramCounter const m_beginInstIdx; - ProgramCounter const m_endInstIdx; + bytes::const_iterator const m_begin; + bytes::const_iterator const m_end; llvm::BasicBlock* const m_llvmBB; @@ -102,12 +98,12 @@ private: /// the item below the top and so on. The stack grows as the code /// accesses more items on the EVM stack but once a value is put on /// the stack, it will never be replaced. - std::vector m_initialStack = {}; + std::vector m_initialStack; /// This stack tracks the contents of the EVM stack as the basic block /// executes. It may grow on both sides, as the code pushes items on /// top of the stack or changes existing items. - std::vector m_currentStack = {}; + std::vector m_currentStack; /// How many items higher is the current stack than the initial one. /// May be negative. @@ -115,7 +111,7 @@ private: /// Is the basic block a valid jump destination. /// JUMPDEST is the first instruction of the basic block. - bool m_isJumpDest = false; + bool const m_isJumpDest = false; }; } diff --git a/evmjit/libevmjit/Cache.cpp b/evmjit/libevmjit/Cache.cpp index a887d91e9..2311c0496 100644 --- a/evmjit/libevmjit/Cache.cpp +++ b/evmjit/libevmjit/Cache.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -23,6 +24,32 @@ ObjectCache* Cache::getObjectCache() return &objectCache; } +namespace +{ + llvm::MemoryBuffer* lastObject; +} + +std::unique_ptr Cache::getObject(std::string const& id) +{ + assert(!lastObject); + llvm::SmallString<256> cachePath; + llvm::sys::path::system_temp_directory(false, cachePath); + llvm::sys::path::append(cachePath, "evm_objs", id); + + if (auto r = llvm::MemoryBuffer::getFile(cachePath.str(), -1, false)) + lastObject = llvm::MemoryBuffer::getMemBufferCopy(r.get()->getBuffer()); + else if (r.getError() != std::make_error_code(std::errc::no_such_file_or_directory)) + std::cerr << r.getError().message(); // TODO: Add log + + if (lastObject) // if object found create fake module + { + auto module = std::unique_ptr(new llvm::Module(id, llvm::getGlobalContext())); + auto mainFuncType = llvm::FunctionType::get(llvm::IntegerType::get(llvm::getGlobalContext(), 32), {}, false); + auto func = llvm::Function::Create(mainFuncType, llvm::Function::ExternalLinkage, id, module.get()); + } + return nullptr; +} + void ObjectCache::notifyObjectCompiled(llvm::Module const* _module, llvm::MemoryBuffer const* _object) { @@ -43,16 +70,9 @@ void ObjectCache::notifyObjectCompiled(llvm::Module const* _module, llvm::Memory llvm::MemoryBuffer* ObjectCache::getObject(llvm::Module const* _module) { - auto&& id = _module->getModuleIdentifier(); - llvm::SmallString<256> cachePath; - llvm::sys::path::system_temp_directory(false, cachePath); - llvm::sys::path::append(cachePath, "evm_objs", id); - - if (auto r = llvm::MemoryBuffer::getFile(cachePath.str(), -1, false)) - return llvm::MemoryBuffer::getMemBufferCopy(r.get()->getBuffer()); - else if (r.getError() != std::make_error_code(std::errc::no_such_file_or_directory)) - std::cerr << r.getError().message(); // TODO: Add log - return nullptr; + auto o = lastObject; + lastObject = nullptr; + return o; } } diff --git a/evmjit/libevmjit/Cache.h b/evmjit/libevmjit/Cache.h index 80fe47ade..1cad537cd 100644 --- a/evmjit/libevmjit/Cache.h +++ b/evmjit/libevmjit/Cache.h @@ -2,7 +2,6 @@ #include #include -#include #include @@ -34,6 +33,7 @@ class Cache { public: static ObjectCache* getObjectCache(); + static std::unique_ptr getObject(std::string const& id); }; } diff --git a/evmjit/libevmjit/Common.h b/evmjit/libevmjit/Common.h index 436931dcd..1d8451c74 100644 --- a/evmjit/libevmjit/Common.h +++ b/evmjit/libevmjit/Common.h @@ -37,10 +37,10 @@ enum class ReturnCode // TODO: Replace with h256 struct i256 { - uint64_t a; - uint64_t b; - uint64_t c; - uint64_t d; + uint64_t a = 0; + uint64_t b = 0; + uint64_t c = 0; + uint64_t d = 0; }; static_assert(sizeof(i256) == 32, "Wrong i265 size"); diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index abd725c7f..bfcb9cea1 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -40,77 +40,69 @@ Compiler::Compiler(Options const& _options): void Compiler::createBasicBlocks(bytes const& _bytecode) { - // FIXME: Simplify this algorithm. All can be done in one pass - - std::set splitPoints; // Sorted collections of instruction indices where basic blocks start/end - - std::vector indirectJumpTargets; - - splitPoints.insert(0); // First basic block - - for (auto curr = _bytecode.begin(); curr != _bytecode.end(); ++curr) + /// Helper function that skips push data and finds next iterator (can be the end) + auto skipPushDataAndGetNext = [](bytes::const_iterator _curr, bytes::const_iterator _end) { - ProgramCounter currentPC = curr - _bytecode.begin(); - - auto inst = Instruction(*curr); - switch (inst) - { - - case Instruction::ANY_PUSH: - { - readPushData(curr, _bytecode.end()); - break; - } + static const auto push1 = static_cast(Instruction::PUSH1); + static const auto push32 = static_cast(Instruction::PUSH32); + size_t offset = 1; + if (*_curr >= push1 && *_curr <= push32) + offset += std::min(*_curr - push1 + 1, (_end - _curr) - 1); + return _curr + offset; + }; + + auto begin = _bytecode.begin(); + bool nextJumpDest = false; + for (auto curr = begin, next = begin; curr != _bytecode.end(); curr = next) + { + next = skipPushDataAndGetNext(curr, _bytecode.end()); - case Instruction::JUMPDEST: + bool isEnd = false; + switch (Instruction(*curr)) { - // A basic block starts here. - splitPoints.insert(currentPC); - indirectJumpTargets.push_back(currentPC); - break; - } - case Instruction::JUMP: case Instruction::JUMPI: case Instruction::RETURN: case Instruction::STOP: case Instruction::SUICIDE: - { - // Create a basic block starting at the following instruction. - if (curr + 1 < _bytecode.end()) - splitPoints.insert(currentPC + 1); + isEnd = true; + break; + + case Instruction::JUMPDEST: + nextJumpDest = true; break; - } default: break; } - } - for (auto it = splitPoints.cbegin(); it != splitPoints.cend();) - { - auto beginInstIdx = *it; - ++it; - auto endInstIdx = it != splitPoints.cend() ? *it : _bytecode.size(); - basicBlocks.emplace(std::piecewise_construct, std::forward_as_tuple(beginInstIdx), std::forward_as_tuple(beginInstIdx, endInstIdx, m_mainFunc, m_builder)); + assert(next <= _bytecode.end()); + if (next == _bytecode.end() || Instruction(*next) == Instruction::JUMPDEST) + isEnd = true; + + if (isEnd) + { + auto beginIdx = begin - _bytecode.begin(); + m_basicBlocks.emplace(std::piecewise_construct, std::forward_as_tuple(beginIdx), + std::forward_as_tuple(begin, next, m_mainFunc, m_builder, nextJumpDest)); + nextJumpDest = false; + begin = next; + } } m_stopBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Stop", m_mainFunc); - - for (auto it = indirectJumpTargets.cbegin(); it != indirectJumpTargets.cend(); ++it) - basicBlocks.find(*it)->second.markAsJumpDest(); } llvm::BasicBlock* Compiler::getJumpTableBlock() { if (!m_jumpTableBlock) { - m_jumpTableBlock.reset(new BasicBlock("JumpTable", m_mainFunc, m_builder)); + m_jumpTableBlock.reset(new BasicBlock("JumpTable", m_mainFunc, m_builder, true)); InsertPointGuard g{m_builder}; m_builder.SetInsertPoint(m_jumpTableBlock->llvm()); auto dest = m_jumpTableBlock->localStack().pop(); auto switchInstr = m_builder.CreateSwitch(dest, getBadJumpBlock()); - for (auto&& p : basicBlocks) + for (auto&& p : m_basicBlocks) { if (p.second.isJumpDest()) switchInstr->addCase(Constant::get(p.first), p.second.llvm()); @@ -123,7 +115,7 @@ llvm::BasicBlock* Compiler::getBadJumpBlock() { if (!m_badJumpBlock) { - m_badJumpBlock.reset(new BasicBlock("BadJump", m_mainFunc, m_builder)); + m_badJumpBlock.reset(new BasicBlock("BadJump", m_mainFunc, m_builder, true)); InsertPointGuard g{m_builder}; m_builder.SetInsertPoint(m_badJumpBlock->llvm()); m_builder.CreateRet(Constant::get(ReturnCode::BadJumpDestination)); @@ -155,14 +147,14 @@ std::unique_ptr Compiler::compile(bytes const& _bytecode, std::str Stack stack(m_builder, runtimeManager); Arith256 arith(m_builder); - m_builder.CreateBr(basicBlocks.begin()->second); + m_builder.CreateBr(m_basicBlocks.empty() ? m_stopBB : m_basicBlocks.begin()->second.llvm()); - for (auto basicBlockPairIt = basicBlocks.begin(); basicBlockPairIt != basicBlocks.end(); ++basicBlockPairIt) + for (auto basicBlockPairIt = m_basicBlocks.begin(); basicBlockPairIt != m_basicBlocks.end(); ++basicBlockPairIt) { auto& basicBlock = basicBlockPairIt->second; auto iterCopy = basicBlockPairIt; ++iterCopy; - auto nextBasicBlock = (iterCopy != basicBlocks.end()) ? iterCopy->second.llvm() : nullptr; + auto nextBasicBlock = (iterCopy != m_basicBlocks.end()) ? iterCopy->second.llvm() : nullptr; compileBasicBlock(basicBlock, _bytecode, runtimeManager, arith, memory, ext, gasMeter, nextBasicBlock); } @@ -178,7 +170,7 @@ std::unique_ptr Compiler::compile(bytes const& _bytecode, std::str if (m_options.optimizeStack) { std::vector blockList; - for (auto& entry : basicBlocks) + for (auto& entry : m_basicBlocks) blockList.push_back(&entry.second); if (m_jumpTableBlock) @@ -189,7 +181,7 @@ std::unique_ptr Compiler::compile(bytes const& _bytecode, std::str dumpCFGifRequired("blocks-opt.dot"); } - for (auto& entry : basicBlocks) + for (auto& entry : m_basicBlocks) entry.second.synchronizeLocalStack(stack); if (m_jumpTableBlock) m_jumpTableBlock->synchronizeLocalStack(stack); @@ -219,9 +211,9 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode m_builder.SetInsertPoint(_basicBlock.llvm()); auto& stack = _basicBlock.localStack(); - for (auto currentPC = _basicBlock.begin(); currentPC != _basicBlock.end(); ++currentPC) + for (auto it = _basicBlock.begin(); it != _basicBlock.end(); ++it) { - auto inst = static_cast(_bytecode[currentPC]); + auto inst = Instruction(*it); _gasMeter.count(inst); @@ -483,10 +475,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode case Instruction::ANY_PUSH: { - auto curr = _bytecode.begin() + currentPC; // TODO: replace currentPC with iterator - auto value = readPushData(curr, _bytecode.end()); - currentPC = curr - _bytecode.begin(); - + auto value = readPushData(it, _basicBlock.end()); stack.push(Constant::get(value)); break; } @@ -561,24 +550,16 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode if (auto constant = llvm::dyn_cast(target)) { auto&& c = constant->getValue(); - if (c.ult(_bytecode.size())) - { - auto v = c.getZExtValue(); - auto it = basicBlocks.find(v); - if (it != basicBlocks.end() && it->second.isJumpDest()) - targetBlock = it->second.llvm(); - } - - if (!targetBlock) - targetBlock = getBadJumpBlock(); + auto targetIdx = c.getActiveBits() <= 64 ? c.getZExtValue() : -1; + auto it = m_basicBlocks.find(targetIdx); + targetBlock = (it != m_basicBlocks.end() && it->second.isJumpDest()) ? it->second.llvm() : getBadJumpBlock(); } + // TODO: Improve; check for constants if (inst == Instruction::JUMP) { if (targetBlock) { - // The target address is computed at compile time, - // just pop it without looking... m_builder.CreateBr(targetBlock); } else @@ -614,7 +595,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode case Instruction::PC: { - auto value = Constant::get(currentPC); + auto value = Constant::get(it - _bytecode.begin()); stack.push(value); break; } @@ -832,13 +813,13 @@ void Compiler::removeDeadBlocks() do { sthErased = false; - for (auto it = basicBlocks.begin(); it != basicBlocks.end();) + for (auto it = m_basicBlocks.begin(); it != m_basicBlocks.end();) { auto llvmBB = it->second.llvm(); if (llvm::pred_begin(llvmBB) == llvm::pred_end(llvmBB)) { llvmBB->eraseFromParent(); - basicBlocks.erase(it++); + m_basicBlocks.erase(it++); sthErased = true; } else @@ -866,7 +847,7 @@ void Compiler::dumpCFGtoStream(std::ostream& _out) << " entry [share=record, label=\"entry block\"];\n"; std::vector blocks; - for (auto& pair : basicBlocks) + for (auto& pair : m_basicBlocks) blocks.push_back(&pair.second); if (m_jumpTableBlock) blocks.push_back(m_jumpTableBlock.get()); @@ -905,7 +886,7 @@ void Compiler::dumpCFGtoStream(std::ostream& _out) void Compiler::dump() { - for (auto& entry : basicBlocks) + for (auto& entry : m_basicBlocks) entry.second.dump(); if (m_jumpTableBlock != nullptr) m_jumpTableBlock->dump(); diff --git a/evmjit/libevmjit/Compiler.h b/evmjit/libevmjit/Compiler.h index 1c00dc711..720a48cf9 100644 --- a/evmjit/libevmjit/Compiler.h +++ b/evmjit/libevmjit/Compiler.h @@ -20,19 +20,13 @@ public: struct Options { /// Optimize stack operations between basic blocks - bool optimizeStack; + bool optimizeStack = true; /// Rewrite switch instructions to sequences of branches - bool rewriteSwitchToBranches; + bool rewriteSwitchToBranches = true; /// Dump CFG as a .dot file for graphviz - bool dumpCFG; - - Options(): - optimizeStack(true), - rewriteSwitchToBranches(true), - dumpCFG(false) - {} + bool dumpCFG = false; }; using ProgramCounter = uint64_t; @@ -69,7 +63,7 @@ private: llvm::IRBuilder<> m_builder; /// Maps a program counter pc to a basic block that starts at pc (if any). - std::map basicBlocks; + std::map m_basicBlocks; /// Stop basic block - terminates execution with STOP code (0) llvm::BasicBlock* m_stopBB = nullptr; diff --git a/evmjit/libevmjit/ExecutionEngine.cpp b/evmjit/libevmjit/ExecutionEngine.cpp index 862586575..7e99932c3 100644 --- a/evmjit/libevmjit/ExecutionEngine.cpp +++ b/evmjit/libevmjit/ExecutionEngine.cpp @@ -4,8 +4,13 @@ #include #include +#pragma warning(push) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" #include #include +#pragma warning(pop) +#pragma GCC diagnostic pop #include #include #include @@ -69,7 +74,13 @@ ReturnCode ExecutionEngine::run(bytes const& _code, RuntimeData* _data, Env* _en } else { - auto module = Compiler({}).compile(_code, mainFuncName); + bool objectCacheEnabled = true; + auto objectCache = objectCacheEnabled ? Cache::getObjectCache() : nullptr; + std::unique_ptr module; + if (objectCache) + module = Cache::getObject(mainFuncName); + if (!module) + module = Compiler({}).compile(_code, mainFuncName); //module->dump(); if (!ee) { @@ -95,7 +106,8 @@ ReturnCode ExecutionEngine::run(bytes const& _code, RuntimeData* _data, Env* _en module.release(); // Successfully created llvm::ExecutionEngine takes ownership of the module memoryManager.release(); // and memory manager - ee->setObjectCache(Cache::getObjectCache()); + if (objectCache) + ee->setObjectCache(objectCache); entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName); } else diff --git a/evmjit/libevmjit/Ext.cpp b/evmjit/libevmjit/Ext.cpp index c30b0a1e3..cd741ad24 100644 --- a/evmjit/libevmjit/Ext.cpp +++ b/evmjit/libevmjit/Ext.cpp @@ -22,7 +22,9 @@ namespace jit Ext::Ext(RuntimeManager& _runtimeManager, Memory& _memoryMan): RuntimeHelper(_runtimeManager), - m_memoryMan(_memoryMan) + m_memoryMan(_memoryMan), + m_funcs{}, + m_argAllocas{} { m_size = m_builder.CreateAlloca(Type::Size, nullptr, "env.size"); } diff --git a/evmjit/libevmjit/Ext.h b/evmjit/libevmjit/Ext.h index 2850be072..86a8a6190 100644 --- a/evmjit/libevmjit/Ext.h +++ b/evmjit/libevmjit/Ext.h @@ -65,8 +65,8 @@ private: llvm::Value* m_size; llvm::Value* m_data = nullptr; - std::array::value> m_funcs = {}; - std::array m_argAllocas = {}; + std::array::value> m_funcs; + std::array m_argAllocas; size_t m_argCounter = 0; llvm::CallInst* createCall(EnvFunc _funcId, std::initializer_list const& _args); diff --git a/evmjit/libevmjit/GasMeter.cpp b/evmjit/libevmjit/GasMeter.cpp index 39f4560e5..84266111e 100644 --- a/evmjit/libevmjit/GasMeter.cpp +++ b/evmjit/libevmjit/GasMeter.cpp @@ -41,7 +41,7 @@ uint64_t const c_logDataGas = 1; uint64_t const c_logTopicGas = 32; uint64_t const c_copyGas = 1; -uint64_t getStepCost(Instruction inst) // TODO: Add this function to FeeSructure (pull request submitted) +uint64_t getStepCost(Instruction inst) { switch (inst) { diff --git a/evmjit/libevmjit/Instruction.cpp b/evmjit/libevmjit/Instruction.cpp new file mode 100644 index 000000000..fdc40d043 --- /dev/null +++ b/evmjit/libevmjit/Instruction.cpp @@ -0,0 +1,40 @@ + +#include "Instruction.h" +#include + +namespace dev +{ +namespace eth +{ +namespace jit +{ + +llvm::APInt readPushData(bytes::const_iterator& _curr, bytes::const_iterator _end) +{ + auto pushInst = *_curr; + assert(Instruction(pushInst) >= Instruction::PUSH1 && Instruction(pushInst) <= Instruction::PUSH32); + auto numBytes = pushInst - static_cast(Instruction::PUSH1) + 1; + llvm::APInt value(256, 0); + ++_curr; // Point the data + for (decltype(numBytes) i = 0; i < numBytes; ++i) + { + byte b = (_curr != _end) ? *_curr++ : 0; + value <<= 8; + value |= b; + } + --_curr; // Point the last real byte read + return value; +} + +void skipPushData(bytes::const_iterator& _curr, bytes::const_iterator _end) +{ + auto pushInst = *_curr; + assert(Instruction(pushInst) >= Instruction::PUSH1 && Instruction(pushInst) <= Instruction::PUSH32); + auto numBytes = pushInst - static_cast(Instruction::PUSH1) + 1; + --_end; + for (decltype(numBytes) i = 0; i < numBytes && _curr < _end; ++i, ++_curr) {} +} + +} +} +} diff --git a/evmjit/libevmjit/Instruction.h b/evmjit/libevmjit/Instruction.h index 3f84efa08..158490dee 100644 --- a/evmjit/libevmjit/Instruction.h +++ b/evmjit/libevmjit/Instruction.h @@ -160,9 +160,13 @@ enum class Instruction: uint8_t /// Reads PUSH data from pointed fragment of bytecode and constructs number out of it /// Reading out of bytecode means reading 0 -/// @param _curr is updates and points the last real byte read +/// @param _curr is updated and points the last real byte read llvm::APInt readPushData(bytes::const_iterator& _curr, bytes::const_iterator _end); +/// Skips PUSH data in pointed fragment of bytecode. +/// @param _curr is updated and points the last real byte skipped +void skipPushData(bytes::const_iterator& _curr, bytes::const_iterator _end); + #define ANY_PUSH PUSH1: \ case Instruction::PUSH2: \ case Instruction::PUSH3: \ diff --git a/evmjit/libevmjit/Runtime.h b/evmjit/libevmjit/Runtime.h index cedfaaf70..8cc5b7968 100644 --- a/evmjit/libevmjit/Runtime.h +++ b/evmjit/libevmjit/Runtime.h @@ -48,7 +48,7 @@ private: Env& m_env; ///< Pointer to environment proxy. Expected by compiled contract. jmp_buf_ref m_currJmpBuf; ///< Pointer to jump buffer. Expected by compiled contract. byte* m_memoryData = nullptr; - i256 m_memorySize = {}; + i256 m_memorySize; std::jmp_buf m_jmpBuf; StackImpl m_stack; MemoryImpl m_memory; diff --git a/evmjit/libevmjit/Utils.cpp b/evmjit/libevmjit/Utils.cpp index 9d9b3acbb..0fd9c0e41 100644 --- a/evmjit/libevmjit/Utils.cpp +++ b/evmjit/libevmjit/Utils.cpp @@ -1,7 +1,5 @@ -#include #include "Utils.h" -#include "Instruction.h" namespace dev { @@ -37,23 +35,6 @@ i256 eth2llvm(u256 _u) return i; } -llvm::APInt readPushData(bytes::const_iterator& _curr, bytes::const_iterator _end) -{ - auto pushInst = *_curr; - assert(Instruction(pushInst) >= Instruction::PUSH1 && Instruction(pushInst) <= Instruction::PUSH32); - auto numBytes = pushInst - static_cast(Instruction::PUSH1) + 1; - llvm::APInt value(256, 0); - ++_curr; // Point the data - for (decltype(numBytes) i = 0; i < numBytes; ++i) - { - byte b = (_curr != _end) ? *_curr++ : 0; - value <<= 8; - value |= b; - } - --_curr; // Point the last real byte read - return value; -} - } } }