From 80ee5c9a646456f2bb6d68fda4a9ae1436d9a373 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 16 Jan 2015 00:46:20 +0100 Subject: [PATCH 01/20] Enforce -fPIC for archives in evmjit --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c8897efd9..25c62ff2f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set_property(GLOBAL PROPERTY USE_FOLDERS ON) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") else () - set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wno-unknown-pragmas -Wextra") + set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wno-unknown-pragmas -Wextra -fPIC") endif() if(APPLE) From c7116998ae35d3dd59cd5938ff372361d9a9f7a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 16 Jan 2015 01:11:43 +0100 Subject: [PATCH 02/20] Make evmjit dependency of LLVM private --- libevmjit/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libevmjit/CMakeLists.txt b/libevmjit/CMakeLists.txt index 01c1e881b..c1acfc409 100644 --- a/libevmjit/CMakeLists.txt +++ b/libevmjit/CMakeLists.txt @@ -17,7 +17,7 @@ set_property(TARGET ${TARGET_NAME} PROPERTY FOLDER "libs") include_directories(${LLVM_INCLUDE_DIRS}) include_directories(${Boost_INCLUDE_DIRS}) -target_link_libraries(${TARGET_NAME} ${LLVM_LIBS}) +target_link_libraries(${TARGET_NAME} PRIVATE ${LLVM_LIBS}) #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti") From a2492d498332939950708321781d9d64fe94319f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 16 Jan 2015 12:43:24 +0100 Subject: [PATCH 03/20] Correct std::array intialization (again!) --- libevmjit/Ext.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index aae68f43a..7d084a450 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -23,12 +23,9 @@ namespace jit Ext::Ext(RuntimeManager& _runtimeManager, Memory& _memoryMan): RuntimeHelper(_runtimeManager), m_memoryMan(_memoryMan) -#ifdef __MSCVER - , - m_funcs({}), // The only std::array initialization that works in both Visual Studio & GCC - m_argAllocas({}) -#endif { + m_funcs = decltype(m_funcs)(); + m_argAllocas = decltype(m_argAllocas)(); m_size = m_builder.CreateAlloca(Type::Size, nullptr, "env.size"); } From f78fbbf50e59cff018e9aa88a93451ee93e742ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 16 Jan 2015 15:54:58 +0100 Subject: [PATCH 04/20] Fix BYTE instruction --- libevmjit/Compiler.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 26c78b4ca..39d480491 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -394,7 +394,8 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode value = Endianness::toBE(m_builder, value); auto bytes = m_builder.CreateBitCast(value, llvm::VectorType::get(Type::Byte, 32), "bytes"); - auto byte = m_builder.CreateExtractElement(bytes, byteNum, "byte"); + auto safeByteNum = m_builder.CreateZExt(m_builder.CreateTrunc(byteNum, m_builder.getIntNTy(5)), Type::lowPrecision); // Trim index, large values can crash + auto byte = m_builder.CreateExtractElement(bytes, safeByteNum, "byte"); value = m_builder.CreateZExt(byte, Type::Word); auto byteNumValid = m_builder.CreateICmpULT(byteNum, Constant::get(32)); From 683de935787cfa0401f20604868cfb1997563030 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 16 Jan 2015 15:56:05 +0100 Subject: [PATCH 05/20] Rename env_getExtCode -> env_extcode according to other renames --- libevmjit-cpp/Env.cpp | 2 +- libevmjit/Ext.cpp | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/libevmjit-cpp/Env.cpp b/libevmjit-cpp/Env.cpp index 6320aa222..90474c7e4 100644 --- a/libevmjit-cpp/Env.cpp +++ b/libevmjit-cpp/Env.cpp @@ -89,7 +89,7 @@ extern "C" *o_hash = hash; } - EXPORT byte const* env_getExtCode(ExtVMFace* _env, h256* _addr256, uint64_t* o_size) + EXPORT byte const* env_extcode(ExtVMFace* _env, h256* _addr256, uint64_t* o_size) { auto addr = right160(*_addr256); auto& code = _env->codeAt(addr); diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 7d084a450..a37a6fe99 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -5,9 +5,6 @@ #include #include -//#include -//#include - #include "RuntimeManager.h" #include "Memory.h" #include "Type.h" @@ -71,7 +68,6 @@ llvm::Value* Ext::getArgAlloca() getBuilder().SetInsertPoint(getMainFunction()->front().getFirstNonPHI()); a = getBuilder().CreateAlloca(Type::Word, nullptr, "arg"); } - return a; } From 0f53e2153a594f41148a4c9716a5194538088937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 16 Jan 2015 16:06:35 +0100 Subject: [PATCH 06/20] Environment variable options for EVM JIT: export EVMJIT_CACHE_OFF=1 disables cache export EVMJIT_DUMP_MODULE=1 dumps LLVM module to standard output --- libevmjit/ExecutionEngine.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp index 71142fbee..1f87c8b58 100644 --- a/libevmjit/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -19,6 +19,14 @@ #include "Compiler.h" #include "Cache.h" +#if defined(NDEBUG) +#define DEBUG_ENV_OPTION(name) false +#else +#include +#define DEBUG_ENV_OPTION(name) (std::getenv(#name) != nullptr) +#endif + + extern "C" void env_sha3(dev::eth::jit::byte const* _begin, uint64_t _size, std::array* o_hash); namespace dev @@ -64,6 +72,8 @@ std::string codeHash(bytes const& _code) ReturnCode ExecutionEngine::run(bytes const& _code, RuntimeData* _data, Env* _env) { static std::unique_ptr ee; // TODO: Use Managed Objects from LLVM? + static auto debugDumpModule = DEBUG_ENV_OPTION(EVMJIT_DUMP_MODULE); + static bool objectCacheEnabled = !DEBUG_ENV_OPTION(EVMJIT_CACHE_OFF); auto mainFuncName = codeHash(_code); EntryFuncPtr entryFuncPtr{}; @@ -74,14 +84,14 @@ ReturnCode ExecutionEngine::run(bytes const& _code, RuntimeData* _data, Env* _en } else { - 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 (debugDumpModule) + module->dump(); if (!ee) { llvm::InitializeNativeTarget(); @@ -92,7 +102,7 @@ ReturnCode ExecutionEngine::run(bytes const& _code, RuntimeData* _data, Env* _en builder.setUseMCJIT(true); std::unique_ptr memoryManager(new llvm::SectionMemoryManager); builder.setMCJITMemoryManager(memoryManager.get()); - builder.setOptLevel(llvm::CodeGenOpt::Default); + builder.setOptLevel(llvm::CodeGenOpt::None); auto triple = llvm::Triple(llvm::sys::getProcessTriple()); if (triple.getOS() == llvm::Triple::OSType::Win32) From 5152596cbd4787f93e064aec139b4b7ee5b27f9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 16 Jan 2015 18:02:36 +0100 Subject: [PATCH 07/20] JUMPI fix: an additional item was left on stack when condition is false --- libevmjit/BasicBlock.h | 6 ++++++ libevmjit/Compiler.cpp | 26 +++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/libevmjit/BasicBlock.h b/libevmjit/BasicBlock.h index 3591a6f54..cda4f89bd 100644 --- a/libevmjit/BasicBlock.h +++ b/libevmjit/BasicBlock.h @@ -66,6 +66,9 @@ public: bool isJumpDest() const { return m_isJumpDest; } + llvm::Value* getJumpTarget() const { return m_jumpTarget; } + void setJumpTarget(llvm::Value* _jumpTarget) { m_jumpTarget = _jumpTarget; } + LocalStack& localStack() { return m_stack; } /// Optimization: propagates values between local stacks in basic blocks @@ -112,6 +115,9 @@ private: /// Is the basic block a valid jump destination. /// JUMPDEST is the first instruction of the basic block. bool const m_isJumpDest = false; + + /// If block finishes with dynamic jump target index is stored here + llvm::Value* m_jumpTarget = nullptr; }; } diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 39d480491..1d00fd225 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -100,7 +100,7 @@ llvm::BasicBlock* Compiler::getJumpTableBlock() 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 dest = m_builder.CreatePHI(Type::Word, 8, "target"); auto switchInstr = m_builder.CreateSwitch(dest, getBadJumpBlock()); for (auto&& p : m_basicBlocks) { @@ -165,6 +165,26 @@ std::unique_ptr Compiler::compile(bytes const& _bytecode, std::str removeDeadBlocks(); + // Link jump table target index + if (m_jumpTableBlock) + { + auto phi = llvm::cast(&m_jumpTableBlock->llvm()->getInstList().front()); + for (auto predIt = llvm::pred_begin(m_jumpTableBlock->llvm()); predIt != llvm::pred_end(m_jumpTableBlock->llvm()); ++predIt) + { + BasicBlock* pred = nullptr; + for (auto&& p : m_basicBlocks) + { + if (p.second.llvm() == *predIt) + { + pred = &p.second; + break; + } + } + + phi->addIncoming(pred->getJumpTarget(), pred->llvm()); + } + } + dumpCFGifRequired("blocks-init.dot"); if (m_options.optimizeStack) @@ -565,7 +585,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode } else { - stack.push(target); + _basicBlock.setJumpTarget(target); m_builder.CreateBr(getJumpTableBlock()); } } @@ -581,7 +601,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode } else { - stack.push(target); + _basicBlock.setJumpTarget(target); m_builder.CreateCondBr(cond, getJumpTableBlock(), _nextBasicBlock); } } From 84b6251181acf5580fd07771cc9e202c8bba8233 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 16 Jan 2015 22:06:07 +0100 Subject: [PATCH 08/20] Remove env_sha3 symbol reference in evmjit shared library to be build with no unresolved symbols --- CMakeLists.txt | 9 +++++---- libevmjit/ExecutionEngine.cpp | 22 +++++++++++----------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 25c62ff2f..519346007 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,13 +4,14 @@ project(evmjit) set_property(GLOBAL PROPERTY USE_FOLDERS ON) -if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") -else () +if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") +else() set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wno-unknown-pragmas -Wextra -fPIC") endif() -if(APPLE) - set(CMAKE_SHARED_LINKER_FLAGS "-undefined dynamic_lookup") +if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + # Do not allow unresovled symbols in shared library (default on linux) + set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined") endif() # LLVM diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp index 1f87c8b58..b6b140fd5 100644 --- a/libevmjit/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -26,9 +26,6 @@ #define DEBUG_ENV_OPTION(name) (std::getenv(#name) != nullptr) #endif - -extern "C" void env_sha3(dev::eth::jit::byte const* _begin, uint64_t _size, std::array* o_hash); - namespace dev { namespace eth @@ -57,14 +54,17 @@ ReturnCode runEntryFunc(EntryFuncPtr _mainFunc, Runtime* _runtime) std::string codeHash(bytes const& _code) { - std::array binHash; - env_sha3(_code.data(), _code.size(), &binHash); - - std::ostringstream os; - for (auto i: binHash) - os << std::hex << std::setfill('0') << std::setw(2) << (int)(std::make_unsigned::type)i; - - return os.str(); + uint32_t hash = 0; + for (auto b : _code) + { + hash += b; + hash += (hash << 10); + hash ^= (hash >> 6); + } + hash += (hash << 3); + hash ^= (hash >> 11); + hash += (hash << 15); + return std::to_string(hash); } } From 0ba08331389a5365ab72aff74515092e13622d9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 16 Jan 2015 22:41:47 +0100 Subject: [PATCH 09/20] Limited old cached objects detection --- libevmjit/Cache.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/libevmjit/Cache.cpp b/libevmjit/Cache.cpp index 0b725bc24..0e6fb517a 100644 --- a/libevmjit/Cache.cpp +++ b/libevmjit/Cache.cpp @@ -36,6 +36,20 @@ std::unique_ptr Cache::getObject(std::string const& id) llvm::sys::path::system_temp_directory(false, cachePath); llvm::sys::path::append(cachePath, "evm_objs", id); +#if defined(__GNUC__) && !defined(NDEBUG) + llvm::sys::fs::file_status st; + auto err = llvm::sys::fs::status(cachePath.str(), st); + if (err) + return nullptr; + auto mtime = st.getLastModificationTime().toEpochTime(); + + std::tm tm; + strptime(__DATE__ __TIME__, " %b %d %Y %H:%M:%S", &tm); + auto btime = (uint64_t)std::mktime(&tm); + if (btime > mtime) + return nullptr; +#endif + 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)) From 003ba383c3d0817170263c3ddb4296df45217109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Sun, 18 Jan 2015 16:54:06 +0100 Subject: [PATCH 10/20] Do not copy return data inside JIT --- libevmjit-cpp/JitVM.cpp | 2 +- libevmjit/Common.h | 1 + libevmjit/ExecutionEngine.cpp | 5 ++++- libevmjit/ExecutionEngine.h | 8 +++++++- libevmjit/Runtime.cpp | 6 +++--- libevmjit/Runtime.h | 9 +-------- libevmjit/interface.cpp | 6 +++--- 7 files changed, 20 insertions(+), 17 deletions(-) diff --git a/libevmjit-cpp/JitVM.cpp b/libevmjit-cpp/JitVM.cpp index dda8133a8..f1bba9e7f 100644 --- a/libevmjit-cpp/JitVM.cpp +++ b/libevmjit-cpp/JitVM.cpp @@ -50,7 +50,7 @@ bytesConstRef JitVM::go(ExtVMFace& _ext, OnOpFunc const&, uint64_t) } m_gas = llvm2eth(m_data.elems[RuntimeData::Gas]); - return {m_engine.returnData.data(), m_engine.returnData.size()}; // TODO: This all bytesConstRef is problematic, review. + return {std::get<0>(m_engine.returnData), std::get<1>(m_engine.returnData)}; } } diff --git a/libevmjit/Common.h b/libevmjit/Common.h index 1d8451c74..2d35b21ac 100644 --- a/libevmjit/Common.h +++ b/libevmjit/Common.h @@ -12,6 +12,7 @@ namespace jit using byte = uint8_t; using bytes = std::vector; +using bytes_ref = std::tuple; using u256 = boost::multiprecision::uint256_t; using bigint = boost::multiprecision::cpp_int; diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp index b6b140fd5..ee92a6ba9 100644 --- a/libevmjit/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -136,7 +136,10 @@ ReturnCode ExecutionEngine::run(bytes const& _code, RuntimeData* _data, Env* _en auto returnCode = runEntryFunc(entryFuncPtr, &runtime); if (returnCode == ReturnCode::Return) - this->returnData = runtime.getReturnData(); + { + returnData = runtime.getReturnData(); // Save reference to return data + std::swap(m_memory, runtime.getMemory()); // Take ownership of memory + } auto executionEndTime = std::chrono::high_resolution_clock::now(); clog(JIT) << " + " << std::chrono::duration_cast(executionEndTime - executionStartTime).count() << " ms\n"; diff --git a/libevmjit/ExecutionEngine.h b/libevmjit/ExecutionEngine.h index 559701bba..52e3b29fa 100644 --- a/libevmjit/ExecutionEngine.h +++ b/libevmjit/ExecutionEngine.h @@ -18,7 +18,13 @@ public: ReturnCode run(bytes const& _code, RuntimeData* _data, Env* _env); - bytes returnData; + /// Reference to returned data (RETURN opcode used) + bytes_ref returnData; + +private: + /// After execution, if RETURN used, memory is moved there + /// to allow client copy the returned data + bytes m_memory; }; } diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 911dc469d..443c19ba6 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -18,7 +18,7 @@ Runtime::Runtime(RuntimeData* _data, Env* _env) : m_currJmpBuf(m_jmpBuf) {} -bytes Runtime::getReturnData() const // FIXME: Reconsider returning by copy +bytes_ref Runtime::getReturnData() const { // TODO: Handle large indexes auto offset = static_cast(llvm2eth(m_data.elems[RuntimeData::ReturnDataOffset])); @@ -28,8 +28,8 @@ bytes Runtime::getReturnData() const // FIXME: Reconsider returning by copy if (offset + size > m_memory.size()) return {}; - auto dataBeg = m_memory.begin() + offset; - return {dataBeg, dataBeg + size}; + auto dataBeg = m_memory.data() + offset; + return bytes_ref{dataBeg, size}; } } diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index f97efa128..df1bde7fd 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -2,15 +2,8 @@ #pragma once #include -#include - -#include "Instruction.h" -#include "CompilerHelper.h" -#include "Utils.h" -#include "Type.h" #include "RuntimeData.h" - #ifdef _MSC_VER #define EXPORT __declspec(dllexport) #else @@ -40,7 +33,7 @@ public: MemoryImpl& getMemory() { return m_memory; } Env* getEnvPtr() { return &m_env; } - bytes getReturnData() const; + bytes_ref getReturnData() const; jmp_buf_ref getJmpBuf() { return m_jmpBuf; } private: diff --git a/libevmjit/interface.cpp b/libevmjit/interface.cpp index eef92d00f..7f334fa14 100644 --- a/libevmjit/interface.cpp +++ b/libevmjit/interface.cpp @@ -20,12 +20,12 @@ evmjit_result evmjit_run(void* _data, void* _env) auto returnCode = engine.run(bytecode, data, static_cast(_env)); evmjit_result result = {static_cast(returnCode), 0, nullptr}; - if (returnCode == ReturnCode::Return && !engine.returnData.empty()) + if (returnCode == ReturnCode::Return && std::get<0>(engine.returnData)) { // TODO: Optimized returning data. Allocating memory on client side by callback function might be a good idea - result.returnDataSize = engine.returnData.size(); + result.returnDataSize = std::get<1>(engine.returnData); result.returnData = std::malloc(result.returnDataSize); - std::memcpy(result.returnData, engine.returnData.data(), result.returnDataSize); + std::memcpy(result.returnData, std::get<0>(engine.returnData), result.returnDataSize); } return result; From de186f1ed1bf3555d9bf92fc56650b68748904d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 19 Jan 2015 13:53:31 +0100 Subject: [PATCH 11/20] Internal mul256 implementation --- libevmjit/Arith256.cpp | 56 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/libevmjit/Arith256.cpp b/libevmjit/Arith256.cpp index b5319bda7..4cbded861 100644 --- a/libevmjit/Arith256.cpp +++ b/libevmjit/Arith256.cpp @@ -118,6 +118,56 @@ namespace else return (u256)(c_end + _u); } + + using uint128 = __uint128_t; + +// uint128 add(uint128 a, uint128 b) { return a + b; } +// uint128 mul(uint128 a, uint128 b) { return a * b; } +// +// uint128 mulq(uint64_t x, uint64_t y) +// { +// return (uint128)x * (uint128)y; +// } +// +// uint128 addc(uint64_t x, uint64_t y) +// { +// return (uint128)x * (uint128)y; +// } + + struct uint256 + { + uint64_t lo; + uint64_t mid; + uint128 hi; + }; + +// uint256 add(uint256 x, uint256 y) +// { +// auto lo = (uint128) x.lo + y.lo; +// auto mid = (uint128) x.mid + y.mid + (lo >> 64); +// return {lo, mid, x.hi + y.hi + (mid >> 64)}; +// } + + uint256 mul(uint256 x, uint256 y) + { + auto t1 = (uint128) x.lo * y.lo; + auto t2 = (uint128) x.lo * y.mid; + auto t3 = x.lo * y.hi; + auto t4 = (uint128) x.mid * y.lo; + auto t5 = (uint128) x.mid * y.mid; + auto t6 = x.mid * y.hi; + auto t7 = x.hi * y.lo; + auto t8 = x.hi * y.mid; + + auto lo = (uint64_t) t1; + auto m1 = (t1 >> 64) + (uint64_t) t2; + auto m2 = (uint64_t) m1; + auto mid = (uint128) m2 + (uint64_t) t4; + auto hi = (t2 >> 64) + t3 + (t4 >> 64) + t5 + (t6 << 64) + t7 + + (t8 << 64) + (m1 >> 64) + (mid >> 64); + + return {lo, (uint64_t)mid, hi}; + } } } @@ -130,11 +180,9 @@ extern "C" using namespace dev::eth::jit; - EXPORT void arith_mul(i256* _arg1, i256* _arg2, i256* o_result) + EXPORT void arith_mul(uint256* _arg1, uint256* _arg2, uint256* o_result) { - auto arg1 = llvm2eth(*_arg1); - auto arg2 = llvm2eth(*_arg2); - *o_result = eth2llvm(arg1 * arg2); + *o_result = mul(*_arg1, *_arg2); } EXPORT void arith_div(i256* _arg1, i256* _arg2, i256* o_result) From 100de855ecb0e115ee89258e1114c890a4d47541 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 19 Jan 2015 14:59:01 +0100 Subject: [PATCH 12/20] Implementation of DIV & MOD with gmp library --- libevmjit/Arith256.cpp | 57 +++++++++++++++++++++++++++++++++++----- libevmjit/CMakeLists.txt | 1 + 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/libevmjit/Arith256.cpp b/libevmjit/Arith256.cpp index 4cbded861..621f11650 100644 --- a/libevmjit/Arith256.cpp +++ b/libevmjit/Arith256.cpp @@ -1,8 +1,10 @@ #include "Arith256.h" #include "Runtime.h" #include "Type.h" +#include "Endianness.h" #include +#include namespace dev { @@ -63,6 +65,8 @@ llvm::Value* Arith256::mul(llvm::Value* _arg1, llvm::Value* _arg2) llvm::Value* Arith256::div(llvm::Value* _arg1, llvm::Value* _arg2) { + + //return Endianness::toNative(m_builder, binaryOp(m_div, Endianness::toBE(m_builder, _arg1), Endianness::toBE(m_builder, _arg2))); return binaryOp(m_div, _arg1, _arg2); } @@ -168,6 +172,29 @@ namespace return {lo, (uint64_t)mid, hi}; } + + bool isZero(i256 const* _n) + { + return _n->a == 0 && _n->b == 0 && _n->c == 0 && _n->d == 0; + } + + const auto nLimbs = sizeof(i256) / sizeof(mp_limb_t); + + int countLimbs(i256 const* _n) + { + static const auto limbsInWord = sizeof(_n->a) / sizeof(mp_limb_t); + static_assert(limbsInWord == 1, "E?"); + + int l = nLimbs; + if (_n->d != 0) return l; + l -= limbsInWord; + if (_n->c != 0) return l; + l -= limbsInWord; + if (_n->b != 0) return l; + l -= limbsInWord; + if (_n->a != 0) return l; + return 0; + } } } @@ -187,16 +214,34 @@ extern "C" EXPORT void arith_div(i256* _arg1, i256* _arg2, i256* o_result) { - auto arg1 = llvm2eth(*_arg1); - auto arg2 = llvm2eth(*_arg2); - *o_result = eth2llvm(arg2 == 0 ? arg2 : arg1 / arg2); + *o_result = {}; + if (isZero(_arg2)) + return; + + mpz_t x{nLimbs, countLimbs(_arg1), reinterpret_cast(_arg1)}; + mpz_t y{nLimbs, countLimbs(_arg2), reinterpret_cast(_arg2)}; + mpz_t z{nLimbs, 0, reinterpret_cast(o_result)}; + + mpz_tdiv_q(z, x, y); + +// auto arg1 = llvm2eth(*_arg1); +// auto arg2 = llvm2eth(*_arg2); +// auto res = arg2 == 0 ? arg2 : arg1 / arg2; +// std::cout << "DIV " << arg1 << "/" << arg2 << " = " << res << std::endl; +// gmp_printf("GMP %Zd / %Zd = %Zd\n", x, y, z); } EXPORT void arith_mod(i256* _arg1, i256* _arg2, i256* o_result) { - auto arg1 = llvm2eth(*_arg1); - auto arg2 = llvm2eth(*_arg2); - *o_result = eth2llvm(arg2 == 0 ? arg2 : arg1 % arg2); + *o_result = {}; + if (isZero(_arg2)) + return; + + mpz_t x{nLimbs, countLimbs(_arg1), reinterpret_cast(_arg1)}; + mpz_t y{nLimbs, countLimbs(_arg2), reinterpret_cast(_arg2)}; + mpz_t z{nLimbs, 0, reinterpret_cast(o_result)}; + + mpz_tdiv_r(z, x, y); } EXPORT void arith_sdiv(i256* _arg1, i256* _arg2, i256* o_result) diff --git a/libevmjit/CMakeLists.txt b/libevmjit/CMakeLists.txt index c1acfc409..96ec873f5 100644 --- a/libevmjit/CMakeLists.txt +++ b/libevmjit/CMakeLists.txt @@ -18,6 +18,7 @@ include_directories(${LLVM_INCLUDE_DIRS}) include_directories(${Boost_INCLUDE_DIRS}) target_link_libraries(${TARGET_NAME} PRIVATE ${LLVM_LIBS}) +target_link_libraries(${TARGET_NAME} PRIVATE gmp) #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti") From 939e94a101e861c6a7d4da6ab27264ca9ec84d06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 19 Jan 2015 15:20:50 +0100 Subject: [PATCH 13/20] Implementation of EXP with gmp --- libevmjit/Arith256.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/libevmjit/Arith256.cpp b/libevmjit/Arith256.cpp index 621f11650..65179db8c 100644 --- a/libevmjit/Arith256.cpp +++ b/libevmjit/Arith256.cpp @@ -260,10 +260,17 @@ extern "C" EXPORT void arith_exp(i256* _arg1, i256* _arg2, i256* o_result) { - bigint left = llvm2eth(*_arg1); - bigint right = llvm2eth(*_arg2); - auto ret = static_cast(boost::multiprecision::powm(left, right, bigint(2) << 256)); - *o_result = eth2llvm(ret); + *o_result = {}; + + static mp_limb_t mod_limbs[nLimbs + 1] = {}; + mod_limbs[nLimbs] = 1; + static const mpz_t mod{nLimbs + 1, nLimbs + 1, &mod_limbs[0]}; + + mpz_t x{nLimbs, countLimbs(_arg1), reinterpret_cast(_arg1)}; + mpz_t y{nLimbs, countLimbs(_arg2), reinterpret_cast(_arg2)}; + mpz_t z{nLimbs, 0, reinterpret_cast(o_result)}; + + mpz_powm(z, x, y, mod); } EXPORT void arith_mulmod(i256* _arg1, i256* _arg2, i256* _arg3, i256* o_result) From a2822a37bf326ad12cd2afdce8273de96d8a3408 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 19 Jan 2015 15:39:59 +0100 Subject: [PATCH 14/20] Implementation of ADDMOD & MULMOD with gmp --- libevmjit/Arith256.cpp | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/libevmjit/Arith256.cpp b/libevmjit/Arith256.cpp index 65179db8c..0926c8563 100644 --- a/libevmjit/Arith256.cpp +++ b/libevmjit/Arith256.cpp @@ -275,24 +275,36 @@ extern "C" EXPORT void arith_mulmod(i256* _arg1, i256* _arg2, i256* _arg3, i256* o_result) { - auto arg1 = llvm2eth(*_arg1); - auto arg2 = llvm2eth(*_arg2); - auto arg3 = llvm2eth(*_arg3); - if (arg3 != 0) - *o_result = eth2llvm(u256((bigint(arg1) * bigint(arg2)) % arg3)); - else - *o_result = {}; + *o_result = {}; + if (isZero(_arg3)) + return; + + mpz_t x{nLimbs, countLimbs(_arg1), reinterpret_cast(_arg1)}; + mpz_t y{nLimbs, countLimbs(_arg2), reinterpret_cast(_arg2)}; + mpz_t m{nLimbs, countLimbs(_arg3), reinterpret_cast(_arg3)}; + mpz_t z{nLimbs, 0, reinterpret_cast(o_result)}; + static mp_limb_t p_limbs[nLimbs * 2] = {}; + static mpz_t p{nLimbs * 2, 0, &p_limbs[0]}; + + mpz_mul(p, x, y); + mpz_tdiv_r(z, p, m); } EXPORT void arith_addmod(i256* _arg1, i256* _arg2, i256* _arg3, i256* o_result) { - auto arg1 = llvm2eth(*_arg1); - auto arg2 = llvm2eth(*_arg2); - auto arg3 = llvm2eth(*_arg3); - if (arg3 != 0) - *o_result = eth2llvm(u256((bigint(arg1) + bigint(arg2)) % arg3)); - else - *o_result = {}; + *o_result = {}; + if (isZero(_arg3)) + return; + + mpz_t x{nLimbs, countLimbs(_arg1), reinterpret_cast(_arg1)}; + mpz_t y{nLimbs, countLimbs(_arg2), reinterpret_cast(_arg2)}; + mpz_t m{nLimbs, countLimbs(_arg3), reinterpret_cast(_arg3)}; + mpz_t z{nLimbs, 0, reinterpret_cast(o_result)}; + static mp_limb_t s_limbs[nLimbs + 1] = {}; + static mpz_t s{nLimbs + 1, 0, &s_limbs[0]}; + + mpz_add(s, x, y); + mpz_tdiv_r(z, s, m); } } From b3bad237570f15c4bcb05847672c029889cea4a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 19 Jan 2015 18:09:55 +0100 Subject: [PATCH 15/20] Implementation of SDIV & SMOD with gmp --- libevmjit/Arith256.cpp | 55 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/libevmjit/Arith256.cpp b/libevmjit/Arith256.cpp index 0926c8563..c33a3cf3a 100644 --- a/libevmjit/Arith256.cpp +++ b/libevmjit/Arith256.cpp @@ -180,6 +180,14 @@ namespace const auto nLimbs = sizeof(i256) / sizeof(mp_limb_t); + // FIXME: Not thread-safe + static mp_limb_t mod_limbs[] = {0, 0, 0, 0, 1}; + static_assert(sizeof(mod_limbs) / sizeof(mod_limbs[0]) == nLimbs + 1, "mp_limb_t size mismatch"); + static const mpz_t mod{nLimbs + 1, nLimbs + 1, &mod_limbs[0]}; + + static mp_limb_t tmp_limbs[nLimbs + 2]; + static mpz_t tmp{nLimbs + 2, 0, &tmp_limbs[0]}; + int countLimbs(i256 const* _n) { static const auto limbsInWord = sizeof(_n->a) / sizeof(mp_limb_t); @@ -195,6 +203,25 @@ namespace if (_n->a != 0) return l; return 0; } + + void u2s(mpz_t _u) + { + if (static_cast::type>(_u->_mp_d[nLimbs - 1]) < 0) + { + mpz_sub(tmp, mod, _u); + mpz_set(_u, tmp); + _u->_mp_size = -_u->_mp_size; + } + } + + void s2u(mpz_t _s) + { + if (_s->_mp_size < 0) + { + mpz_add(tmp, mod, _s); + mpz_set(_s, tmp); + } + } } } @@ -246,16 +273,32 @@ extern "C" EXPORT void arith_sdiv(i256* _arg1, i256* _arg2, i256* o_result) { - auto arg1 = llvm2eth(*_arg1); - auto arg2 = llvm2eth(*_arg2); - *o_result = eth2llvm(arg2 == 0 ? arg2 : s2u(u2s(arg1) / u2s(arg2))); + *o_result = {}; + if (isZero(_arg2)) + return; + + mpz_t x{nLimbs, countLimbs(_arg1), reinterpret_cast(_arg1)}; + mpz_t y{nLimbs, countLimbs(_arg2), reinterpret_cast(_arg2)}; + mpz_t z{nLimbs, 0, reinterpret_cast(o_result)}; + u2s(x); + u2s(y); + mpz_tdiv_q(z, x, y); + s2u(z); } EXPORT void arith_smod(i256* _arg1, i256* _arg2, i256* o_result) { - auto arg1 = llvm2eth(*_arg1); - auto arg2 = llvm2eth(*_arg2); - *o_result = eth2llvm(arg2 == 0 ? arg2 : s2u(u2s(arg1) % u2s(arg2))); + *o_result = {}; + if (isZero(_arg2)) + return; + + mpz_t x{nLimbs, countLimbs(_arg1), reinterpret_cast(_arg1)}; + mpz_t y{nLimbs, countLimbs(_arg2), reinterpret_cast(_arg2)}; + mpz_t z{nLimbs, 0, reinterpret_cast(o_result)}; + u2s(x); + u2s(y); + mpz_tdiv_r(z, x, y); + s2u(z); } EXPORT void arith_exp(i256* _arg1, i256* _arg2, i256* o_result) From a21362a7f84f0ef36d1889178857dda4105313aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 19 Jan 2015 18:29:16 +0100 Subject: [PATCH 16/20] Removing boost dependency from libevmjit --- libevmjit-cpp/Env.cpp | 3 +-- libevmjit-cpp/JitVM.cpp | 32 ++++++++++++++++---------------- libevmjit-cpp/Utils.h | 38 ++++++++++++++++++++++++++++++++++++++ libevmjit/Arith256.cpp | 21 --------------------- libevmjit/Common.h | 1 - libevmjit/Runtime.cpp | 4 ++-- libevmjit/RuntimeData.h | 3 --- libevmjit/Utils.cpp | 26 -------------------------- libevmjit/Utils.h | 3 --- 9 files changed, 57 insertions(+), 74 deletions(-) create mode 100644 libevmjit-cpp/Utils.h diff --git a/libevmjit-cpp/Env.cpp b/libevmjit-cpp/Env.cpp index 90474c7e4..f89897792 100644 --- a/libevmjit-cpp/Env.cpp +++ b/libevmjit-cpp/Env.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include "Utils.h" extern "C" { @@ -16,7 +16,6 @@ extern "C" using namespace dev; using namespace dev::eth; using jit::i256; - using jit::eth2llvm; EXPORT void env_sload(ExtVMFace* _env, i256* _index, i256* o_value) { diff --git a/libevmjit-cpp/JitVM.cpp b/libevmjit-cpp/JitVM.cpp index f1bba9e7f..ededbff52 100644 --- a/libevmjit-cpp/JitVM.cpp +++ b/libevmjit-cpp/JitVM.cpp @@ -2,7 +2,7 @@ #include "JitVM.h" #include #include -#include +#include "Utils.h" namespace dev { @@ -13,28 +13,28 @@ bytesConstRef JitVM::go(ExtVMFace& _ext, OnOpFunc const&, uint64_t) { using namespace jit; - m_data.set(RuntimeData::Gas, m_gas); - m_data.set(RuntimeData::Address, fromAddress(_ext.myAddress)); - m_data.set(RuntimeData::Caller, fromAddress(_ext.caller)); - m_data.set(RuntimeData::Origin, fromAddress(_ext.origin)); - m_data.set(RuntimeData::CallValue, _ext.value); - m_data.set(RuntimeData::CallDataSize, _ext.data.size()); - m_data.set(RuntimeData::GasPrice, _ext.gasPrice); - m_data.set(RuntimeData::CoinBase, fromAddress(_ext.currentBlock.coinbaseAddress)); - m_data.set(RuntimeData::TimeStamp, _ext.currentBlock.timestamp); - m_data.set(RuntimeData::Number, _ext.currentBlock.number); - m_data.set(RuntimeData::Difficulty, _ext.currentBlock.difficulty); - m_data.set(RuntimeData::GasLimit, _ext.currentBlock.gasLimit); - m_data.set(RuntimeData::CodeSize, _ext.code.size()); + m_data.elems[RuntimeData::Gas] = eth2llvm(m_gas); + m_data.elems[RuntimeData::Address] = eth2llvm(fromAddress(_ext.myAddress)); + m_data.elems[RuntimeData::Caller] = eth2llvm(fromAddress(_ext.caller)); + m_data.elems[RuntimeData::Origin] = eth2llvm(fromAddress(_ext.origin)); + m_data.elems[RuntimeData::CallValue] = eth2llvm(_ext.value); + m_data.elems[RuntimeData::CallDataSize] = eth2llvm(_ext.data.size()); + m_data.elems[RuntimeData::GasPrice] = eth2llvm(_ext.gasPrice); + m_data.elems[RuntimeData::CoinBase] = eth2llvm(fromAddress(_ext.currentBlock.coinbaseAddress)); + m_data.elems[RuntimeData::TimeStamp] = eth2llvm(_ext.currentBlock.timestamp); + m_data.elems[RuntimeData::Number] = eth2llvm(_ext.currentBlock.number); + m_data.elems[RuntimeData::Difficulty] = eth2llvm(_ext.currentBlock.difficulty); + m_data.elems[RuntimeData::GasLimit] = eth2llvm(_ext.currentBlock.gasLimit); + m_data.elems[RuntimeData::CodeSize] = eth2llvm(_ext.code.size()); m_data.callData = _ext.data.data(); - m_data.code = _ext.code.data(); + m_data.code = _ext.code.data(); auto env = reinterpret_cast(&_ext); auto exitCode = m_engine.run(_ext.code, &m_data, env); switch (exitCode) { case ReturnCode::Suicide: - _ext.suicide(right160(m_data.get(RuntimeData::SuicideDestAddress))); + _ext.suicide(right160(llvm2eth(m_data.elems[RuntimeData::SuicideDestAddress]))); break; case ReturnCode::BadJumpDestination: diff --git a/libevmjit-cpp/Utils.h b/libevmjit-cpp/Utils.h new file mode 100644 index 000000000..ac796920b --- /dev/null +++ b/libevmjit-cpp/Utils.h @@ -0,0 +1,38 @@ +#pragma once + +#include + +namespace dev +{ +namespace eth +{ + +inline u256 llvm2eth(jit::i256 _i) +{ + u256 u = 0; + u |= _i.d; + u <<= 64; + u |= _i.c; + u <<= 64; + u |= _i.b; + u <<= 64; + u |= _i.a; + return u; +} + +inline jit::i256 eth2llvm(u256 _u) +{ + jit::i256 i; + u256 mask = 0xFFFFFFFFFFFFFFFF; + i.a = static_cast(_u & mask); + _u >>= 64; + i.b = static_cast(_u & mask); + _u >>= 64; + i.c = static_cast(_u & mask); + _u >>= 64; + i.d = static_cast(_u & mask); + return i; +} + +} +} diff --git a/libevmjit/Arith256.cpp b/libevmjit/Arith256.cpp index c33a3cf3a..adb6cf9d5 100644 --- a/libevmjit/Arith256.cpp +++ b/libevmjit/Arith256.cpp @@ -102,27 +102,6 @@ llvm::Value* Arith256::mulmod(llvm::Value* _arg1, llvm::Value* _arg2, llvm::Valu namespace { - using s256 = boost::multiprecision::int256_t; - - inline s256 u2s(u256 _u) - { - static const bigint c_end = (bigint)1 << 256; - static const u256 c_send = (u256)1 << 255; - if (_u < c_send) - return (s256)_u; - else - return (s256)-(c_end - _u); - } - - inline u256 s2u(s256 _u) - { - static const bigint c_end = (bigint)1 << 256; - if (_u >= 0) - return (u256)_u; - else - return (u256)(c_end + _u); - } - using uint128 = __uint128_t; // uint128 add(uint128 a, uint128 b) { return a + b; } diff --git a/libevmjit/Common.h b/libevmjit/Common.h index 2d35b21ac..179c7ab38 100644 --- a/libevmjit/Common.h +++ b/libevmjit/Common.h @@ -35,7 +35,6 @@ enum class ReturnCode }; /// Representation of 256-bit value binary compatible with LLVM i256 -// TODO: Replace with h256 struct i256 { uint64_t a = 0; diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 443c19ba6..989c053dc 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -21,8 +21,8 @@ Runtime::Runtime(RuntimeData* _data, Env* _env) : bytes_ref Runtime::getReturnData() const { // TODO: Handle large indexes - auto offset = static_cast(llvm2eth(m_data.elems[RuntimeData::ReturnDataOffset])); - auto size = static_cast(llvm2eth(m_data.elems[RuntimeData::ReturnDataSize])); + auto offset = static_cast(m_data.elems[RuntimeData::ReturnDataOffset].a); + auto size = static_cast(m_data.elems[RuntimeData::ReturnDataSize].a); assert(offset + size <= m_memory.size() || size == 0); if (offset + size > m_memory.size()) diff --git a/libevmjit/RuntimeData.h b/libevmjit/RuntimeData.h index bb52f7864..a71cd468b 100644 --- a/libevmjit/RuntimeData.h +++ b/libevmjit/RuntimeData.h @@ -38,9 +38,6 @@ struct RuntimeData i256 elems[_size] = {}; byte const* callData = nullptr; byte const* code = nullptr; - - void set(Index _index, u256 _value) { elems[_index] = eth2llvm(_value); } - u256 get(Index _index) { return llvm2eth(elems[_index]); } }; /// VM Environment (ExtVM) opaque type diff --git a/libevmjit/Utils.cpp b/libevmjit/Utils.cpp index 0fd9c0e41..5f7f75bfd 100644 --- a/libevmjit/Utils.cpp +++ b/libevmjit/Utils.cpp @@ -8,32 +8,6 @@ namespace eth namespace jit { -u256 llvm2eth(i256 _i) -{ - u256 u = 0; - u |= _i.d; - u <<= 64; - u |= _i.c; - u <<= 64; - u |= _i.b; - u <<= 64; - u |= _i.a; - return u; -} - -i256 eth2llvm(u256 _u) -{ - i256 i; - u256 mask = 0xFFFFFFFFFFFFFFFF; - i.a = static_cast(_u & mask); - _u >>= 64; - i.b = static_cast(_u & mask); - _u >>= 64; - i.c = static_cast(_u & mask); - _u >>= 64; - i.d = static_cast(_u & mask); - return i; -} } } diff --git a/libevmjit/Utils.h b/libevmjit/Utils.h index f672365c6..1e6705667 100644 --- a/libevmjit/Utils.h +++ b/libevmjit/Utils.h @@ -14,9 +14,6 @@ struct JIT: public NoteChannel { static const char* name() { return "JIT"; } }; //#define clog(CHANNEL) std::cerr #define clog(CHANNEL) std::ostream(nullptr) -u256 llvm2eth(i256); -i256 eth2llvm(u256); - } } } From 3dcf30463b961e3fe47b48b2024bbf3d5b5ce675 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 19 Jan 2015 18:39:19 +0100 Subject: [PATCH 17/20] Removing boost dependency from libevmjit --- CMakeLists.txt | 3 --- libevmjit-cpp/CMakeLists.txt | 3 +++ libevmjit/CMakeLists.txt | 1 - libevmjit/Common.h | 4 +--- libevmjit/Compiler.cpp | 1 + libevmjit/interface.cpp | 2 +- 6 files changed, 6 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 519346007..4888de523 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,9 +32,6 @@ else() link_directories(/usr/lib/llvm-3.5/lib) endif() -# Boost -find_package(Boost REQUIRED) - add_subdirectory(libevmjit) if(EVMJIT_CPP) diff --git a/libevmjit-cpp/CMakeLists.txt b/libevmjit-cpp/CMakeLists.txt index 25be95177..58375e4ee 100644 --- a/libevmjit-cpp/CMakeLists.txt +++ b/libevmjit-cpp/CMakeLists.txt @@ -1,5 +1,8 @@ set(TARGET_NAME evmjit-cpp) +# Boost +find_package(Boost REQUIRED) + set(SOURCES Env.cpp JitVM.cpp JitVM.h diff --git a/libevmjit/CMakeLists.txt b/libevmjit/CMakeLists.txt index 96ec873f5..1990ec398 100644 --- a/libevmjit/CMakeLists.txt +++ b/libevmjit/CMakeLists.txt @@ -15,7 +15,6 @@ add_library(${TARGET_NAME} SHARED ${SOURCES} ${HEADERS}) set_property(TARGET ${TARGET_NAME} PROPERTY FOLDER "libs") include_directories(${LLVM_INCLUDE_DIRS}) -include_directories(${Boost_INCLUDE_DIRS}) target_link_libraries(${TARGET_NAME} PRIVATE ${LLVM_LIBS}) target_link_libraries(${TARGET_NAME} PRIVATE gmp) diff --git a/libevmjit/Common.h b/libevmjit/Common.h index 179c7ab38..d0c582236 100644 --- a/libevmjit/Common.h +++ b/libevmjit/Common.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include namespace dev { @@ -13,8 +13,6 @@ namespace jit using byte = uint8_t; using bytes = std::vector; using bytes_ref = std::tuple; -using u256 = boost::multiprecision::uint256_t; -using bigint = boost::multiprecision::cpp_int; struct NoteChannel {}; // FIXME: Use some log library? diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 1d00fd225..6286ef92f 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include diff --git a/libevmjit/interface.cpp b/libevmjit/interface.cpp index 7f334fa14..5d2b97c2d 100644 --- a/libevmjit/interface.cpp +++ b/libevmjit/interface.cpp @@ -1,5 +1,5 @@ #include "interface.h" -#include +#include #include "ExecutionEngine.h" extern "C" From 25d8873440780fbc3e9c5e4c7a94863b1dcacfb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 20 Jan 2015 15:17:12 +0100 Subject: [PATCH 18/20] Merge commit '3dcf30463b961e3fe47b48b2024bbf3d5b5ce675' into evmjit Conflicts: evmjit/CMakeLists.txt evmjit/libevmjit-cpp/CMakeLists.txt evmjit/libevmjit-cpp/Env.cpp evmjit/libevmjit-cpp/JitVM.cpp evmjit/libevmjit/Arith256.cpp evmjit/libevmjit/BasicBlock.cpp evmjit/libevmjit/BasicBlock.h evmjit/libevmjit/CMakeLists.txt evmjit/libevmjit/Cache.cpp evmjit/libevmjit/Common.h evmjit/libevmjit/Compiler.cpp evmjit/libevmjit/ExecutionEngine.cpp evmjit/libevmjit/ExecutionEngine.h evmjit/libevmjit/Ext.cpp evmjit/libevmjit/Ext.h evmjit/libevmjit/Runtime.cpp evmjit/libevmjit/Runtime.h evmjit/libevmjit/RuntimeData.h evmjit/libevmjit/Utils.cpp evmjit/libevmjit/Utils.h evmjit/libevmjit/interface.cpp --- CMakeLists.txt | 17 ++- libevmjit-cpp/CMakeLists.txt | 3 + libevmjit-cpp/Env.cpp | 5 +- libevmjit-cpp/JitVM.cpp | 34 ++--- libevmjit-cpp/Utils.h | 38 ++++++ libevmjit/Arith256.cpp | 230 +++++++++++++++++++++++++++------- libevmjit/BasicBlock.cpp | 15 +-- libevmjit/BasicBlock.h | 8 +- libevmjit/CMakeLists.txt | 12 +- libevmjit/Cache.cpp | 14 +++ libevmjit/Common.h | 6 +- libevmjit/Compiler.cpp | 34 ++++- libevmjit/ExecutionEngine.cpp | 39 ++++-- libevmjit/ExecutionEngine.h | 8 +- libevmjit/Ext.cpp | 16 +-- libevmjit/Ext.h | 4 +- libevmjit/Runtime.cpp | 10 +- libevmjit/Runtime.h | 11 +- libevmjit/RuntimeData.h | 3 - libevmjit/Utils.cpp | 26 ---- libevmjit/Utils.h | 3 - libevmjit/interface.cpp | 8 +- 22 files changed, 365 insertions(+), 179 deletions(-) create mode 100644 libevmjit-cpp/Utils.h diff --git a/CMakeLists.txt b/CMakeLists.txt index acb113207..4888de523 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,17 +4,18 @@ project(evmjit) set_property(GLOBAL PROPERTY USE_FOLDERS ON) -if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") -else () - set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wno-unknown-pragmas -Wextra -DSHAREDLIB -fPIC") +if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") +else() + set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wno-unknown-pragmas -Wextra -fPIC") endif() -if(APPLE) - set(CMAKE_SHARED_LINKER_FLAGS "-undefined dynamic_lookup") +if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + # Do not allow unresovled symbols in shared library (default on linux) + set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined") endif() # LLVM -if(LLVM_DIR) # local LLVM build +if(LLVM_DIR OR APPLE) # local LLVM build find_package(LLVM REQUIRED CONFIG) message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") @@ -28,11 +29,9 @@ else() message(STATUS "LLVM include dirs: ${LLVM_INCLUDE_DIRS}") 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") add_definitions(-D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS) + link_directories(/usr/lib/llvm-3.5/lib) endif() -# Boost -find_package(Boost REQUIRED) - add_subdirectory(libevmjit) if(EVMJIT_CPP) diff --git a/libevmjit-cpp/CMakeLists.txt b/libevmjit-cpp/CMakeLists.txt index 25be95177..58375e4ee 100644 --- a/libevmjit-cpp/CMakeLists.txt +++ b/libevmjit-cpp/CMakeLists.txt @@ -1,5 +1,8 @@ set(TARGET_NAME evmjit-cpp) +# Boost +find_package(Boost REQUIRED) + set(SOURCES Env.cpp JitVM.cpp JitVM.h diff --git a/libevmjit-cpp/Env.cpp b/libevmjit-cpp/Env.cpp index 6320aa222..f89897792 100644 --- a/libevmjit-cpp/Env.cpp +++ b/libevmjit-cpp/Env.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include "Utils.h" extern "C" { @@ -16,7 +16,6 @@ extern "C" using namespace dev; using namespace dev::eth; using jit::i256; - using jit::eth2llvm; EXPORT void env_sload(ExtVMFace* _env, i256* _index, i256* o_value) { @@ -89,7 +88,7 @@ extern "C" *o_hash = hash; } - EXPORT byte const* env_getExtCode(ExtVMFace* _env, h256* _addr256, uint64_t* o_size) + EXPORT byte const* env_extcode(ExtVMFace* _env, h256* _addr256, uint64_t* o_size) { auto addr = right160(*_addr256); auto& code = _env->codeAt(addr); diff --git a/libevmjit-cpp/JitVM.cpp b/libevmjit-cpp/JitVM.cpp index dda8133a8..ededbff52 100644 --- a/libevmjit-cpp/JitVM.cpp +++ b/libevmjit-cpp/JitVM.cpp @@ -2,7 +2,7 @@ #include "JitVM.h" #include #include -#include +#include "Utils.h" namespace dev { @@ -13,28 +13,28 @@ bytesConstRef JitVM::go(ExtVMFace& _ext, OnOpFunc const&, uint64_t) { using namespace jit; - m_data.set(RuntimeData::Gas, m_gas); - m_data.set(RuntimeData::Address, fromAddress(_ext.myAddress)); - m_data.set(RuntimeData::Caller, fromAddress(_ext.caller)); - m_data.set(RuntimeData::Origin, fromAddress(_ext.origin)); - m_data.set(RuntimeData::CallValue, _ext.value); - m_data.set(RuntimeData::CallDataSize, _ext.data.size()); - m_data.set(RuntimeData::GasPrice, _ext.gasPrice); - m_data.set(RuntimeData::CoinBase, fromAddress(_ext.currentBlock.coinbaseAddress)); - m_data.set(RuntimeData::TimeStamp, _ext.currentBlock.timestamp); - m_data.set(RuntimeData::Number, _ext.currentBlock.number); - m_data.set(RuntimeData::Difficulty, _ext.currentBlock.difficulty); - m_data.set(RuntimeData::GasLimit, _ext.currentBlock.gasLimit); - m_data.set(RuntimeData::CodeSize, _ext.code.size()); + m_data.elems[RuntimeData::Gas] = eth2llvm(m_gas); + m_data.elems[RuntimeData::Address] = eth2llvm(fromAddress(_ext.myAddress)); + m_data.elems[RuntimeData::Caller] = eth2llvm(fromAddress(_ext.caller)); + m_data.elems[RuntimeData::Origin] = eth2llvm(fromAddress(_ext.origin)); + m_data.elems[RuntimeData::CallValue] = eth2llvm(_ext.value); + m_data.elems[RuntimeData::CallDataSize] = eth2llvm(_ext.data.size()); + m_data.elems[RuntimeData::GasPrice] = eth2llvm(_ext.gasPrice); + m_data.elems[RuntimeData::CoinBase] = eth2llvm(fromAddress(_ext.currentBlock.coinbaseAddress)); + m_data.elems[RuntimeData::TimeStamp] = eth2llvm(_ext.currentBlock.timestamp); + m_data.elems[RuntimeData::Number] = eth2llvm(_ext.currentBlock.number); + m_data.elems[RuntimeData::Difficulty] = eth2llvm(_ext.currentBlock.difficulty); + m_data.elems[RuntimeData::GasLimit] = eth2llvm(_ext.currentBlock.gasLimit); + m_data.elems[RuntimeData::CodeSize] = eth2llvm(_ext.code.size()); m_data.callData = _ext.data.data(); - m_data.code = _ext.code.data(); + m_data.code = _ext.code.data(); auto env = reinterpret_cast(&_ext); auto exitCode = m_engine.run(_ext.code, &m_data, env); switch (exitCode) { case ReturnCode::Suicide: - _ext.suicide(right160(m_data.get(RuntimeData::SuicideDestAddress))); + _ext.suicide(right160(llvm2eth(m_data.elems[RuntimeData::SuicideDestAddress]))); break; case ReturnCode::BadJumpDestination: @@ -50,7 +50,7 @@ bytesConstRef JitVM::go(ExtVMFace& _ext, OnOpFunc const&, uint64_t) } m_gas = llvm2eth(m_data.elems[RuntimeData::Gas]); - return {m_engine.returnData.data(), m_engine.returnData.size()}; // TODO: This all bytesConstRef is problematic, review. + return {std::get<0>(m_engine.returnData), std::get<1>(m_engine.returnData)}; } } diff --git a/libevmjit-cpp/Utils.h b/libevmjit-cpp/Utils.h new file mode 100644 index 000000000..ac796920b --- /dev/null +++ b/libevmjit-cpp/Utils.h @@ -0,0 +1,38 @@ +#pragma once + +#include + +namespace dev +{ +namespace eth +{ + +inline u256 llvm2eth(jit::i256 _i) +{ + u256 u = 0; + u |= _i.d; + u <<= 64; + u |= _i.c; + u <<= 64; + u |= _i.b; + u <<= 64; + u |= _i.a; + return u; +} + +inline jit::i256 eth2llvm(u256 _u) +{ + jit::i256 i; + u256 mask = 0xFFFFFFFFFFFFFFFF; + i.a = static_cast(_u & mask); + _u >>= 64; + i.b = static_cast(_u & mask); + _u >>= 64; + i.c = static_cast(_u & mask); + _u >>= 64; + i.d = static_cast(_u & mask); + return i; +} + +} +} diff --git a/libevmjit/Arith256.cpp b/libevmjit/Arith256.cpp index b5319bda7..adb6cf9d5 100644 --- a/libevmjit/Arith256.cpp +++ b/libevmjit/Arith256.cpp @@ -1,8 +1,10 @@ #include "Arith256.h" #include "Runtime.h" #include "Type.h" +#include "Endianness.h" #include +#include namespace dev { @@ -63,6 +65,8 @@ llvm::Value* Arith256::mul(llvm::Value* _arg1, llvm::Value* _arg2) llvm::Value* Arith256::div(llvm::Value* _arg1, llvm::Value* _arg2) { + + //return Endianness::toNative(m_builder, binaryOp(m_div, Endianness::toBE(m_builder, _arg1), Endianness::toBE(m_builder, _arg2))); return binaryOp(m_div, _arg1, _arg2); } @@ -98,25 +102,104 @@ llvm::Value* Arith256::mulmod(llvm::Value* _arg1, llvm::Value* _arg2, llvm::Valu namespace { - using s256 = boost::multiprecision::int256_t; + using uint128 = __uint128_t; + +// uint128 add(uint128 a, uint128 b) { return a + b; } +// uint128 mul(uint128 a, uint128 b) { return a * b; } +// +// uint128 mulq(uint64_t x, uint64_t y) +// { +// return (uint128)x * (uint128)y; +// } +// +// uint128 addc(uint64_t x, uint64_t y) +// { +// return (uint128)x * (uint128)y; +// } + + struct uint256 + { + uint64_t lo; + uint64_t mid; + uint128 hi; + }; + +// uint256 add(uint256 x, uint256 y) +// { +// auto lo = (uint128) x.lo + y.lo; +// auto mid = (uint128) x.mid + y.mid + (lo >> 64); +// return {lo, mid, x.hi + y.hi + (mid >> 64)}; +// } + + uint256 mul(uint256 x, uint256 y) + { + auto t1 = (uint128) x.lo * y.lo; + auto t2 = (uint128) x.lo * y.mid; + auto t3 = x.lo * y.hi; + auto t4 = (uint128) x.mid * y.lo; + auto t5 = (uint128) x.mid * y.mid; + auto t6 = x.mid * y.hi; + auto t7 = x.hi * y.lo; + auto t8 = x.hi * y.mid; + + auto lo = (uint64_t) t1; + auto m1 = (t1 >> 64) + (uint64_t) t2; + auto m2 = (uint64_t) m1; + auto mid = (uint128) m2 + (uint64_t) t4; + auto hi = (t2 >> 64) + t3 + (t4 >> 64) + t5 + (t6 << 64) + t7 + + (t8 << 64) + (m1 >> 64) + (mid >> 64); + + return {lo, (uint64_t)mid, hi}; + } - inline s256 u2s(u256 _u) + bool isZero(i256 const* _n) { - static const bigint c_end = (bigint)1 << 256; - static const u256 c_send = (u256)1 << 255; - if (_u < c_send) - return (s256)_u; - else - return (s256)-(c_end - _u); + return _n->a == 0 && _n->b == 0 && _n->c == 0 && _n->d == 0; } - inline u256 s2u(s256 _u) + const auto nLimbs = sizeof(i256) / sizeof(mp_limb_t); + + // FIXME: Not thread-safe + static mp_limb_t mod_limbs[] = {0, 0, 0, 0, 1}; + static_assert(sizeof(mod_limbs) / sizeof(mod_limbs[0]) == nLimbs + 1, "mp_limb_t size mismatch"); + static const mpz_t mod{nLimbs + 1, nLimbs + 1, &mod_limbs[0]}; + + static mp_limb_t tmp_limbs[nLimbs + 2]; + static mpz_t tmp{nLimbs + 2, 0, &tmp_limbs[0]}; + + int countLimbs(i256 const* _n) { - static const bigint c_end = (bigint)1 << 256; - if (_u >= 0) - return (u256)_u; - else - return (u256)(c_end + _u); + static const auto limbsInWord = sizeof(_n->a) / sizeof(mp_limb_t); + static_assert(limbsInWord == 1, "E?"); + + int l = nLimbs; + if (_n->d != 0) return l; + l -= limbsInWord; + if (_n->c != 0) return l; + l -= limbsInWord; + if (_n->b != 0) return l; + l -= limbsInWord; + if (_n->a != 0) return l; + return 0; + } + + void u2s(mpz_t _u) + { + if (static_cast::type>(_u->_mp_d[nLimbs - 1]) < 0) + { + mpz_sub(tmp, mod, _u); + mpz_set(_u, tmp); + _u->_mp_size = -_u->_mp_size; + } + } + + void s2u(mpz_t _s) + { + if (_s->_mp_size < 0) + { + mpz_add(tmp, mod, _s); + mpz_set(_s, tmp); + } } } @@ -130,69 +213,120 @@ extern "C" using namespace dev::eth::jit; - EXPORT void arith_mul(i256* _arg1, i256* _arg2, i256* o_result) + EXPORT void arith_mul(uint256* _arg1, uint256* _arg2, uint256* o_result) { - auto arg1 = llvm2eth(*_arg1); - auto arg2 = llvm2eth(*_arg2); - *o_result = eth2llvm(arg1 * arg2); + *o_result = mul(*_arg1, *_arg2); } EXPORT void arith_div(i256* _arg1, i256* _arg2, i256* o_result) { - auto arg1 = llvm2eth(*_arg1); - auto arg2 = llvm2eth(*_arg2); - *o_result = eth2llvm(arg2 == 0 ? arg2 : arg1 / arg2); + *o_result = {}; + if (isZero(_arg2)) + return; + + mpz_t x{nLimbs, countLimbs(_arg1), reinterpret_cast(_arg1)}; + mpz_t y{nLimbs, countLimbs(_arg2), reinterpret_cast(_arg2)}; + mpz_t z{nLimbs, 0, reinterpret_cast(o_result)}; + + mpz_tdiv_q(z, x, y); + +// auto arg1 = llvm2eth(*_arg1); +// auto arg2 = llvm2eth(*_arg2); +// auto res = arg2 == 0 ? arg2 : arg1 / arg2; +// std::cout << "DIV " << arg1 << "/" << arg2 << " = " << res << std::endl; +// gmp_printf("GMP %Zd / %Zd = %Zd\n", x, y, z); } EXPORT void arith_mod(i256* _arg1, i256* _arg2, i256* o_result) { - auto arg1 = llvm2eth(*_arg1); - auto arg2 = llvm2eth(*_arg2); - *o_result = eth2llvm(arg2 == 0 ? arg2 : arg1 % arg2); + *o_result = {}; + if (isZero(_arg2)) + return; + + mpz_t x{nLimbs, countLimbs(_arg1), reinterpret_cast(_arg1)}; + mpz_t y{nLimbs, countLimbs(_arg2), reinterpret_cast(_arg2)}; + mpz_t z{nLimbs, 0, reinterpret_cast(o_result)}; + + mpz_tdiv_r(z, x, y); } EXPORT void arith_sdiv(i256* _arg1, i256* _arg2, i256* o_result) { - auto arg1 = llvm2eth(*_arg1); - auto arg2 = llvm2eth(*_arg2); - *o_result = eth2llvm(arg2 == 0 ? arg2 : s2u(u2s(arg1) / u2s(arg2))); + *o_result = {}; + if (isZero(_arg2)) + return; + + mpz_t x{nLimbs, countLimbs(_arg1), reinterpret_cast(_arg1)}; + mpz_t y{nLimbs, countLimbs(_arg2), reinterpret_cast(_arg2)}; + mpz_t z{nLimbs, 0, reinterpret_cast(o_result)}; + u2s(x); + u2s(y); + mpz_tdiv_q(z, x, y); + s2u(z); } EXPORT void arith_smod(i256* _arg1, i256* _arg2, i256* o_result) { - auto arg1 = llvm2eth(*_arg1); - auto arg2 = llvm2eth(*_arg2); - *o_result = eth2llvm(arg2 == 0 ? arg2 : s2u(u2s(arg1) % u2s(arg2))); + *o_result = {}; + if (isZero(_arg2)) + return; + + mpz_t x{nLimbs, countLimbs(_arg1), reinterpret_cast(_arg1)}; + mpz_t y{nLimbs, countLimbs(_arg2), reinterpret_cast(_arg2)}; + mpz_t z{nLimbs, 0, reinterpret_cast(o_result)}; + u2s(x); + u2s(y); + mpz_tdiv_r(z, x, y); + s2u(z); } EXPORT void arith_exp(i256* _arg1, i256* _arg2, i256* o_result) { - bigint left = llvm2eth(*_arg1); - bigint right = llvm2eth(*_arg2); - auto ret = static_cast(boost::multiprecision::powm(left, right, bigint(2) << 256)); - *o_result = eth2llvm(ret); + *o_result = {}; + + static mp_limb_t mod_limbs[nLimbs + 1] = {}; + mod_limbs[nLimbs] = 1; + static const mpz_t mod{nLimbs + 1, nLimbs + 1, &mod_limbs[0]}; + + mpz_t x{nLimbs, countLimbs(_arg1), reinterpret_cast(_arg1)}; + mpz_t y{nLimbs, countLimbs(_arg2), reinterpret_cast(_arg2)}; + mpz_t z{nLimbs, 0, reinterpret_cast(o_result)}; + + mpz_powm(z, x, y, mod); } EXPORT void arith_mulmod(i256* _arg1, i256* _arg2, i256* _arg3, i256* o_result) { - auto arg1 = llvm2eth(*_arg1); - auto arg2 = llvm2eth(*_arg2); - auto arg3 = llvm2eth(*_arg3); - if (arg3 != 0) - *o_result = eth2llvm(u256((bigint(arg1) * bigint(arg2)) % arg3)); - else - *o_result = {}; + *o_result = {}; + if (isZero(_arg3)) + return; + + mpz_t x{nLimbs, countLimbs(_arg1), reinterpret_cast(_arg1)}; + mpz_t y{nLimbs, countLimbs(_arg2), reinterpret_cast(_arg2)}; + mpz_t m{nLimbs, countLimbs(_arg3), reinterpret_cast(_arg3)}; + mpz_t z{nLimbs, 0, reinterpret_cast(o_result)}; + static mp_limb_t p_limbs[nLimbs * 2] = {}; + static mpz_t p{nLimbs * 2, 0, &p_limbs[0]}; + + mpz_mul(p, x, y); + mpz_tdiv_r(z, p, m); } EXPORT void arith_addmod(i256* _arg1, i256* _arg2, i256* _arg3, i256* o_result) { - auto arg1 = llvm2eth(*_arg1); - auto arg2 = llvm2eth(*_arg2); - auto arg3 = llvm2eth(*_arg3); - if (arg3 != 0) - *o_result = eth2llvm(u256((bigint(arg1) + bigint(arg2)) % arg3)); - else - *o_result = {}; + *o_result = {}; + if (isZero(_arg3)) + return; + + mpz_t x{nLimbs, countLimbs(_arg1), reinterpret_cast(_arg1)}; + mpz_t y{nLimbs, countLimbs(_arg2), reinterpret_cast(_arg2)}; + mpz_t m{nLimbs, countLimbs(_arg3), reinterpret_cast(_arg3)}; + mpz_t z{nLimbs, 0, reinterpret_cast(o_result)}; + static mp_limb_t s_limbs[nLimbs + 1] = {}; + static mpz_t s{nLimbs + 1, 0, &s_limbs[0]}; + + mpz_add(s, x, y); + mpz_tdiv_r(z, s, m); } } diff --git a/libevmjit/BasicBlock.cpp b/libevmjit/BasicBlock.cpp index dda0fbc36..5868c0f43 100644 --- a/libevmjit/BasicBlock.cpp +++ b/libevmjit/BasicBlock.cpp @@ -168,16 +168,13 @@ void BasicBlock::synchronizeLocalStack(Stack& _evmStack) if (val == nullptr) continue; - assert(llvm::isa(val)); llvm::PHINode* phi = llvm::cast(val); - if (! phi->use_empty()) - { - // Insert call to get() just before the PHI node and replace - // the uses of PHI with the uses of this new instruction. - m_builder.SetInsertPoint(phi); - auto newVal = _evmStack.get(idx); - phi->replaceAllUsesWith(newVal); - } + // Insert call to get() just before the PHI node and replace + // the uses of PHI with the uses of this new instruction. + m_builder.SetInsertPoint(phi); + auto newVal = _evmStack.get(idx); // OPT: Value may be never user but we need to check stack heigth + // It is probably a good idea to keep heigth as a local variable accesible by LLVM directly + phi->replaceAllUsesWith(newVal); phi->eraseFromParent(); } diff --git a/libevmjit/BasicBlock.h b/libevmjit/BasicBlock.h index 7a5364a4e..cda4f89bd 100644 --- a/libevmjit/BasicBlock.h +++ b/libevmjit/BasicBlock.h @@ -57,7 +57,7 @@ public: explicit BasicBlock(std::string _name, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder, bool isJumpDest); BasicBlock(const BasicBlock&) = delete; - void operator=(const BasicBlock&) = delete; + BasicBlock& operator=(const BasicBlock&) = delete; llvm::BasicBlock* llvm() { return m_llvmBB; } @@ -66,6 +66,9 @@ public: bool isJumpDest() const { return m_isJumpDest; } + llvm::Value* getJumpTarget() const { return m_jumpTarget; } + void setJumpTarget(llvm::Value* _jumpTarget) { m_jumpTarget = _jumpTarget; } + LocalStack& localStack() { return m_stack; } /// Optimization: propagates values between local stacks in basic blocks @@ -112,6 +115,9 @@ private: /// Is the basic block a valid jump destination. /// JUMPDEST is the first instruction of the basic block. bool const m_isJumpDest = false; + + /// If block finishes with dynamic jump target index is stored here + llvm::Value* m_jumpTarget = nullptr; }; } diff --git a/libevmjit/CMakeLists.txt b/libevmjit/CMakeLists.txt index 28b501ee3..1990ec398 100644 --- a/libevmjit/CMakeLists.txt +++ b/libevmjit/CMakeLists.txt @@ -2,24 +2,24 @@ set(TARGET_NAME evmjit) file(GLOB SOURCES "*.cpp") file(GLOB HEADERS "*.h") +set(INTERFACE_HEADERS interface.h) source_group("" FILES ${HEADERS}) source_group("" FILES ${SOURCES}) if (NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") # Disable rtti for Cache as LLVM has no rtti set_source_files_properties(Cache.cpp PROPERTIES COMPILE_FLAGS -fno-rtti) -endif () +endif() -link_directories(/usr/lib/llvm-3.5/lib) add_library(${TARGET_NAME} SHARED ${SOURCES} ${HEADERS}) set_property(TARGET ${TARGET_NAME} PROPERTY FOLDER "libs") include_directories(${LLVM_INCLUDE_DIRS}) -include_directories(${Boost_INCLUDE_DIRS}) -target_link_libraries(${TARGET_NAME} ${LLVM_LIBS}) +target_link_libraries(${TARGET_NAME} PRIVATE ${LLVM_LIBS}) +target_link_libraries(${TARGET_NAME} PRIVATE gmp) #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti") -#install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) -#install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) +install(TARGETS ${TARGET_NAME} LIBRARY DESTINATION lib) +install(FILES ${INTERFACE_HEADERS} DESTINATION include/${TARGET_NAME}) diff --git a/libevmjit/Cache.cpp b/libevmjit/Cache.cpp index 0b725bc24..0e6fb517a 100644 --- a/libevmjit/Cache.cpp +++ b/libevmjit/Cache.cpp @@ -36,6 +36,20 @@ std::unique_ptr Cache::getObject(std::string const& id) llvm::sys::path::system_temp_directory(false, cachePath); llvm::sys::path::append(cachePath, "evm_objs", id); +#if defined(__GNUC__) && !defined(NDEBUG) + llvm::sys::fs::file_status st; + auto err = llvm::sys::fs::status(cachePath.str(), st); + if (err) + return nullptr; + auto mtime = st.getLastModificationTime().toEpochTime(); + + std::tm tm; + strptime(__DATE__ __TIME__, " %b %d %Y %H:%M:%S", &tm); + auto btime = (uint64_t)std::mktime(&tm); + if (btime > mtime) + return nullptr; +#endif + 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)) diff --git a/libevmjit/Common.h b/libevmjit/Common.h index 1d8451c74..d0c582236 100644 --- a/libevmjit/Common.h +++ b/libevmjit/Common.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include namespace dev { @@ -12,8 +12,7 @@ namespace jit using byte = uint8_t; using bytes = std::vector; -using u256 = boost::multiprecision::uint256_t; -using bigint = boost::multiprecision::cpp_int; +using bytes_ref = std::tuple; struct NoteChannel {}; // FIXME: Use some log library? @@ -34,7 +33,6 @@ enum class ReturnCode }; /// Representation of 256-bit value binary compatible with LLVM i256 -// TODO: Replace with h256 struct i256 { uint64_t a = 0; diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index bfcb9cea1..6286ef92f 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -100,7 +101,7 @@ llvm::BasicBlock* Compiler::getJumpTableBlock() 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 dest = m_builder.CreatePHI(Type::Word, 8, "target"); auto switchInstr = m_builder.CreateSwitch(dest, getBadJumpBlock()); for (auto&& p : m_basicBlocks) { @@ -165,6 +166,26 @@ std::unique_ptr Compiler::compile(bytes const& _bytecode, std::str removeDeadBlocks(); + // Link jump table target index + if (m_jumpTableBlock) + { + auto phi = llvm::cast(&m_jumpTableBlock->llvm()->getInstList().front()); + for (auto predIt = llvm::pred_begin(m_jumpTableBlock->llvm()); predIt != llvm::pred_end(m_jumpTableBlock->llvm()); ++predIt) + { + BasicBlock* pred = nullptr; + for (auto&& p : m_basicBlocks) + { + if (p.second.llvm() == *predIt) + { + pred = &p.second; + break; + } + } + + phi->addIncoming(pred->getJumpTarget(), pred->llvm()); + } + } + dumpCFGifRequired("blocks-init.dot"); if (m_options.optimizeStack) @@ -394,7 +415,8 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode value = Endianness::toBE(m_builder, value); auto bytes = m_builder.CreateBitCast(value, llvm::VectorType::get(Type::Byte, 32), "bytes"); - auto byte = m_builder.CreateExtractElement(bytes, byteNum, "byte"); + auto safeByteNum = m_builder.CreateZExt(m_builder.CreateTrunc(byteNum, m_builder.getIntNTy(5)), Type::lowPrecision); // Trim index, large values can crash + auto byte = m_builder.CreateExtractElement(bytes, safeByteNum, "byte"); value = m_builder.CreateZExt(byte, Type::Word); auto byteNumValid = m_builder.CreateICmpULT(byteNum, Constant::get(32)); @@ -564,7 +586,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode } else { - stack.push(target); + _basicBlock.setJumpTarget(target); m_builder.CreateBr(getJumpTableBlock()); } } @@ -580,7 +602,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode } else { - stack.push(target); + _basicBlock.setJumpTarget(target); m_builder.CreateCondBr(cond, getJumpTableBlock(), _nextBasicBlock); } } @@ -644,7 +666,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode case Instruction::EXTCODESIZE: { auto addr = stack.pop(); - auto codeRef = _ext.getExtCode(addr); + auto codeRef = _ext.extcode(addr); stack.push(codeRef.size); break; } @@ -682,7 +704,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode auto srcIdx = stack.pop(); auto reqBytes = stack.pop(); - auto codeRef = _ext.getExtCode(addr); + auto codeRef = _ext.extcode(addr); _memory.copyBytes(codeRef.ptr, codeRef.size, srcIdx, destMemIdx, reqBytes); break; diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp index 71142fbee..ee92a6ba9 100644 --- a/libevmjit/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -19,7 +19,12 @@ #include "Compiler.h" #include "Cache.h" -extern "C" void env_sha3(dev::eth::jit::byte const* _begin, uint64_t _size, std::array* o_hash); +#if defined(NDEBUG) +#define DEBUG_ENV_OPTION(name) false +#else +#include +#define DEBUG_ENV_OPTION(name) (std::getenv(#name) != nullptr) +#endif namespace dev { @@ -49,14 +54,17 @@ ReturnCode runEntryFunc(EntryFuncPtr _mainFunc, Runtime* _runtime) std::string codeHash(bytes const& _code) { - std::array binHash; - env_sha3(_code.data(), _code.size(), &binHash); - - std::ostringstream os; - for (auto i: binHash) - os << std::hex << std::setfill('0') << std::setw(2) << (int)(std::make_unsigned::type)i; - - return os.str(); + uint32_t hash = 0; + for (auto b : _code) + { + hash += b; + hash += (hash << 10); + hash ^= (hash >> 6); + } + hash += (hash << 3); + hash ^= (hash >> 11); + hash += (hash << 15); + return std::to_string(hash); } } @@ -64,6 +72,8 @@ std::string codeHash(bytes const& _code) ReturnCode ExecutionEngine::run(bytes const& _code, RuntimeData* _data, Env* _env) { static std::unique_ptr ee; // TODO: Use Managed Objects from LLVM? + static auto debugDumpModule = DEBUG_ENV_OPTION(EVMJIT_DUMP_MODULE); + static bool objectCacheEnabled = !DEBUG_ENV_OPTION(EVMJIT_CACHE_OFF); auto mainFuncName = codeHash(_code); EntryFuncPtr entryFuncPtr{}; @@ -74,14 +84,14 @@ ReturnCode ExecutionEngine::run(bytes const& _code, RuntimeData* _data, Env* _en } else { - 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 (debugDumpModule) + module->dump(); if (!ee) { llvm::InitializeNativeTarget(); @@ -92,7 +102,7 @@ ReturnCode ExecutionEngine::run(bytes const& _code, RuntimeData* _data, Env* _en builder.setUseMCJIT(true); std::unique_ptr memoryManager(new llvm::SectionMemoryManager); builder.setMCJITMemoryManager(memoryManager.get()); - builder.setOptLevel(llvm::CodeGenOpt::Default); + builder.setOptLevel(llvm::CodeGenOpt::None); auto triple = llvm::Triple(llvm::sys::getProcessTriple()); if (triple.getOS() == llvm::Triple::OSType::Win32) @@ -126,7 +136,10 @@ ReturnCode ExecutionEngine::run(bytes const& _code, RuntimeData* _data, Env* _en auto returnCode = runEntryFunc(entryFuncPtr, &runtime); if (returnCode == ReturnCode::Return) - this->returnData = runtime.getReturnData(); + { + returnData = runtime.getReturnData(); // Save reference to return data + std::swap(m_memory, runtime.getMemory()); // Take ownership of memory + } auto executionEndTime = std::chrono::high_resolution_clock::now(); clog(JIT) << " + " << std::chrono::duration_cast(executionEndTime - executionStartTime).count() << " ms\n"; diff --git a/libevmjit/ExecutionEngine.h b/libevmjit/ExecutionEngine.h index 559701bba..52e3b29fa 100644 --- a/libevmjit/ExecutionEngine.h +++ b/libevmjit/ExecutionEngine.h @@ -18,7 +18,13 @@ public: ReturnCode run(bytes const& _code, RuntimeData* _data, Env* _env); - bytes returnData; + /// Reference to returned data (RETURN opcode used) + bytes_ref returnData; + +private: + /// After execution, if RETURN used, memory is moved there + /// to allow client copy the returned data + bytes m_memory; }; } diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index f0767d9e0..a37a6fe99 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -5,9 +5,6 @@ #include #include -//#include -//#include - #include "RuntimeManager.h" #include "Memory.h" #include "Type.h" @@ -22,10 +19,10 @@ namespace jit Ext::Ext(RuntimeManager& _runtimeManager, Memory& _memoryMan): RuntimeHelper(_runtimeManager), - m_memoryMan(_memoryMan), - m_funcs({}), // The only std::array initialization that works in both Visual Studio & GCC - m_argAllocas({}) + m_memoryMan(_memoryMan) { + m_funcs = decltype(m_funcs)(); + m_argAllocas = decltype(m_argAllocas)(); m_size = m_builder.CreateAlloca(Type::Size, nullptr, "env.size"); } @@ -48,7 +45,7 @@ std::array::value> const& getEnvFuncDescs() FuncDesc{"env_call", getFunctionType(Type::Bool, {Type::EnvPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::BytePtr, Type::Size, Type::BytePtr, Type::Size, Type::WordPtr})}, FuncDesc{"env_log", getFunctionType(Type::Void, {Type::EnvPtr, Type::BytePtr, Type::Size, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr})}, FuncDesc{"env_blockhash", getFunctionType(Type::Void, {Type::EnvPtr, Type::WordPtr, Type::WordPtr})}, - FuncDesc{"env_getExtCode", getFunctionType(Type::BytePtr, {Type::EnvPtr, Type::WordPtr, Type::Size->getPointerTo()})}, + FuncDesc{"env_extcode", getFunctionType(Type::BytePtr, {Type::EnvPtr, Type::WordPtr, Type::Size->getPointerTo()})}, FuncDesc{"ext_calldataload", getFunctionType(Type::Void, {Type::RuntimeDataPtr, Type::WordPtr, Type::WordPtr})}, }}; @@ -71,7 +68,6 @@ llvm::Value* Ext::getArgAlloca() getBuilder().SetInsertPoint(getMainFunction()->front().getFirstNonPHI()); a = getBuilder().CreateAlloca(Type::Word, nullptr, "arg"); } - return a; } @@ -166,10 +162,10 @@ llvm::Value* Ext::sha3(llvm::Value* _inOff, llvm::Value* _inSize) return hash; } -MemoryRef Ext::getExtCode(llvm::Value* _addr) +MemoryRef Ext::extcode(llvm::Value* _addr) { auto addr = Endianness::toBE(m_builder, _addr); - auto code = createCall(EnvFunc::getExtCode, {getRuntimeManager().getEnvPtr(), byPtr(addr), m_size}); + auto code = createCall(EnvFunc::extcode, {getRuntimeManager().getEnvPtr(), byPtr(addr), m_size}); auto codeSize = m_builder.CreateLoad(m_size); auto codeSize256 = m_builder.CreateZExt(codeSize, Type::Word); return {code, codeSize256}; diff --git a/libevmjit/Ext.h b/libevmjit/Ext.h index 86a8a6190..2601d32ab 100644 --- a/libevmjit/Ext.h +++ b/libevmjit/Ext.h @@ -34,7 +34,7 @@ enum class EnvFunc call, log, blockhash, - getExtCode, + extcode, calldataload, // Helper function, not client Env interface _size @@ -55,7 +55,7 @@ public: llvm::Value* blockhash(llvm::Value* _number); llvm::Value* sha3(llvm::Value* _inOff, llvm::Value* _inSize); - MemoryRef getExtCode(llvm::Value* _addr); + MemoryRef extcode(llvm::Value* _addr); void log(llvm::Value* _memIdx, llvm::Value* _numBytes, std::array const& _topics); diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 911dc469d..989c053dc 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -18,18 +18,18 @@ Runtime::Runtime(RuntimeData* _data, Env* _env) : m_currJmpBuf(m_jmpBuf) {} -bytes Runtime::getReturnData() const // FIXME: Reconsider returning by copy +bytes_ref Runtime::getReturnData() const { // TODO: Handle large indexes - auto offset = static_cast(llvm2eth(m_data.elems[RuntimeData::ReturnDataOffset])); - auto size = static_cast(llvm2eth(m_data.elems[RuntimeData::ReturnDataSize])); + auto offset = static_cast(m_data.elems[RuntimeData::ReturnDataOffset].a); + auto size = static_cast(m_data.elems[RuntimeData::ReturnDataSize].a); assert(offset + size <= m_memory.size() || size == 0); if (offset + size > m_memory.size()) return {}; - auto dataBeg = m_memory.begin() + offset; - return {dataBeg, dataBeg + size}; + auto dataBeg = m_memory.data() + offset; + return bytes_ref{dataBeg, size}; } } diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index 8cc5b7968..df1bde7fd 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -2,15 +2,8 @@ #pragma once #include -#include - -#include "Instruction.h" -#include "CompilerHelper.h" -#include "Utils.h" -#include "Type.h" #include "RuntimeData.h" - #ifdef _MSC_VER #define EXPORT __declspec(dllexport) #else @@ -34,13 +27,13 @@ public: Runtime(RuntimeData* _data, Env* _env); Runtime(const Runtime&) = delete; - void operator=(const Runtime&) = delete; + Runtime& operator=(const Runtime&) = delete; StackImpl& getStack() { return m_stack; } MemoryImpl& getMemory() { return m_memory; } Env* getEnvPtr() { return &m_env; } - bytes getReturnData() const; + bytes_ref getReturnData() const; jmp_buf_ref getJmpBuf() { return m_jmpBuf; } private: diff --git a/libevmjit/RuntimeData.h b/libevmjit/RuntimeData.h index bb52f7864..a71cd468b 100644 --- a/libevmjit/RuntimeData.h +++ b/libevmjit/RuntimeData.h @@ -38,9 +38,6 @@ struct RuntimeData i256 elems[_size] = {}; byte const* callData = nullptr; byte const* code = nullptr; - - void set(Index _index, u256 _value) { elems[_index] = eth2llvm(_value); } - u256 get(Index _index) { return llvm2eth(elems[_index]); } }; /// VM Environment (ExtVM) opaque type diff --git a/libevmjit/Utils.cpp b/libevmjit/Utils.cpp index 0fd9c0e41..5f7f75bfd 100644 --- a/libevmjit/Utils.cpp +++ b/libevmjit/Utils.cpp @@ -8,32 +8,6 @@ namespace eth namespace jit { -u256 llvm2eth(i256 _i) -{ - u256 u = 0; - u |= _i.d; - u <<= 64; - u |= _i.c; - u <<= 64; - u |= _i.b; - u <<= 64; - u |= _i.a; - return u; -} - -i256 eth2llvm(u256 _u) -{ - i256 i; - u256 mask = 0xFFFFFFFFFFFFFFFF; - i.a = static_cast(_u & mask); - _u >>= 64; - i.b = static_cast(_u & mask); - _u >>= 64; - i.c = static_cast(_u & mask); - _u >>= 64; - i.d = static_cast(_u & mask); - return i; -} } } diff --git a/libevmjit/Utils.h b/libevmjit/Utils.h index f672365c6..1e6705667 100644 --- a/libevmjit/Utils.h +++ b/libevmjit/Utils.h @@ -14,9 +14,6 @@ struct JIT: public NoteChannel { static const char* name() { return "JIT"; } }; //#define clog(CHANNEL) std::cerr #define clog(CHANNEL) std::ostream(nullptr) -u256 llvm2eth(i256); -i256 eth2llvm(u256); - } } } diff --git a/libevmjit/interface.cpp b/libevmjit/interface.cpp index eef92d00f..5d2b97c2d 100644 --- a/libevmjit/interface.cpp +++ b/libevmjit/interface.cpp @@ -1,5 +1,5 @@ #include "interface.h" -#include +#include #include "ExecutionEngine.h" extern "C" @@ -20,12 +20,12 @@ evmjit_result evmjit_run(void* _data, void* _env) auto returnCode = engine.run(bytecode, data, static_cast(_env)); evmjit_result result = {static_cast(returnCode), 0, nullptr}; - if (returnCode == ReturnCode::Return && !engine.returnData.empty()) + if (returnCode == ReturnCode::Return && std::get<0>(engine.returnData)) { // TODO: Optimized returning data. Allocating memory on client side by callback function might be a good idea - result.returnDataSize = engine.returnData.size(); + result.returnDataSize = std::get<1>(engine.returnData); result.returnData = std::malloc(result.returnDataSize); - std::memcpy(result.returnData, engine.returnData.data(), result.returnDataSize); + std::memcpy(result.returnData, std::get<0>(engine.returnData), result.returnDataSize); } return result; From cc89778189fcf7d1638a4f04591862c6f2c0fda5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 22 Jan 2015 15:32:12 +0100 Subject: [PATCH 19/20] Cleanup JIT interface header file --- libevmjit/interface.h | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/libevmjit/interface.h b/libevmjit/interface.h index 5d9307ab2..4cac78d56 100644 --- a/libevmjit/interface.h +++ b/libevmjit/interface.h @@ -15,40 +15,6 @@ typedef struct evmjit_result evmjit_result evmjit_run(void* _data, void* _env); -// JIT object opaque type -typedef struct evm_jit evm_jit; - -// Contract execution return code -typedef int evm_jit_return_code; - -// Host-endian 256-bit integer type -typedef struct i256 i256; - -struct i256 -{ - char b[33]; -}; - -// Big-endian right aligned 256-bit hash -typedef struct h256 h256; - -// Runtime data struct - must be provided by external language (Go, C++, Python) -typedef struct evm_jit_rt evm_jit_rt; - -// Runtime callback functions - implementations must be provided by external language (Go, C++, Python) -void evm_jit_rt_sload(evm_jit_rt* _rt, i256* _index, i256* _ret); -void evm_jit_rt_sstore(evm_jit_rt* _rt, i256* _index, i256* _value); -void evm_jit_rt_balance(evm_jit_rt* _rt, h256* _address, i256* _ret); -// And so on... - -evm_jit* evm_jit_create(evm_jit_rt* _runtime_data); - -evm_jit_return_code evm_jit_execute(evm_jit* _jit); - -void evm_jit_get_return_data(evm_jit* _jit, char* _return_data_offset, size_t* _return_data_size); - -void evm_jit_destroy(evm_jit* _jit); - #ifdef __cplusplus } #endif From fb3dbcf341dcf10640773278e0aede4c8c285c7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 22 Jan 2015 17:33:11 +0100 Subject: [PATCH 20/20] Insert evmjit_run function declaration directly to vm_jit.go file --- libevmjit/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libevmjit/CMakeLists.txt b/libevmjit/CMakeLists.txt index 1990ec398..575ea5ed7 100644 --- a/libevmjit/CMakeLists.txt +++ b/libevmjit/CMakeLists.txt @@ -22,4 +22,4 @@ target_link_libraries(${TARGET_NAME} PRIVATE gmp) #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti") install(TARGETS ${TARGET_NAME} LIBRARY DESTINATION lib) -install(FILES ${INTERFACE_HEADERS} DESTINATION include/${TARGET_NAME}) +#install(FILES ${INTERFACE_HEADERS} DESTINATION include/${TARGET_NAME})