From 2fd2446330a910ac2cabf4f8e94712853a9cdbbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 5 Dec 2014 12:49:09 +0100 Subject: [PATCH] Simplify ExecutionEngine interface. It is possible to pass raw code instead of LLVM module. --- evmcc/evmcc.cpp | 2 +- libevmjit-cpp/JitVM.cpp | 10 +++------- libevmjit-cpp/JitVM.h | 3 --- libevmjit/Common.h | 27 +++++++++++++++++++++++++++ libevmjit/ExecutionEngine.cpp | 20 ++++++++++++++------ libevmjit/ExecutionEngine.h | 15 ++++++++++----- libevmjit/Ext.cpp | 4 ++-- libevmjit/Runtime.h | 5 ----- libevmjit/RuntimeData.h | 8 ++++---- libevmjit/Stack.cpp | 6 +++--- libevmjit/Type.h | 12 ------------ libevmjit/Utils.h | 14 -------------- 12 files changed, 64 insertions(+), 62 deletions(-) diff --git a/evmcc/evmcc.cpp b/evmcc/evmcc.cpp index 3a72bb4f33..f76b855db1 100644 --- a/evmcc/evmcc.cpp +++ b/evmcc/evmcc.cpp @@ -171,7 +171,7 @@ int main(int argc, char** argv) if (options.count("interpret")) { - auto engine = eth::jit::ExecutionEngine(); + eth::jit::ExecutionEngine engine; u256 gas = initialGas; // Create fake ExtVM interface diff --git a/libevmjit-cpp/JitVM.cpp b/libevmjit-cpp/JitVM.cpp index da945139d8..02aa7dc64c 100644 --- a/libevmjit-cpp/JitVM.cpp +++ b/libevmjit-cpp/JitVM.cpp @@ -1,9 +1,8 @@ #include "JitVM.h" -#include #include #include -#include +#include namespace dev { @@ -14,9 +13,6 @@ bytesConstRef JitVM::go(ExtVMFace& _ext, OnOpFunc const&, uint64_t) { using namespace jit; - Compiler::Options defaultOptions; - auto module = Compiler(defaultOptions).compile(_ext.code); - RuntimeData data = {}; #define set(INDEX, VALUE) data.elems[INDEX] = eth2llvm(VALUE) @@ -40,9 +36,9 @@ bytesConstRef JitVM::go(ExtVMFace& _ext, OnOpFunc const&, uint64_t) ExecutionEngine engine; auto env = reinterpret_cast(&_ext); - auto exitCode = engine.run(std::move(module), &data, env); + auto exitCode = engine.run(_ext.code, &data, env); - switch (static_cast(exitCode)) + switch (exitCode) { case ReturnCode::BadJumpDestination: BOOST_THROW_EXCEPTION(BadJumpDestination()); diff --git a/libevmjit-cpp/JitVM.h b/libevmjit-cpp/JitVM.h index 028dca7a09..4b5fedab0e 100644 --- a/libevmjit-cpp/JitVM.h +++ b/libevmjit-cpp/JitVM.h @@ -1,9 +1,6 @@ - #pragma once -#include #include -#include namespace dev { diff --git a/libevmjit/Common.h b/libevmjit/Common.h index a645d58b11..d98cc0acbe 100644 --- a/libevmjit/Common.h +++ b/libevmjit/Common.h @@ -17,6 +17,33 @@ using bigint = boost::multiprecision::cpp_int; struct NoteChannel {}; // FIXME: Use some log library? +enum class ReturnCode +{ + Stop = 0, + Return = 1, + Suicide = 2, + + BadJumpDestination = 101, + OutOfGas = 102, + StackTooSmall = 103, + BadInstruction = 104, + + LLVMConfigError = 201, + LLVMCompileError = 202, + LLVMLinkError = 203, +}; + +/// Representation of 256-bit value binary compatible with LLVM i256 +// TODO: Replace with h256 +struct i256 +{ + uint64_t a; + uint64_t b; + uint64_t c; + uint64_t d; +}; +static_assert(sizeof(i256) == 32, "Wrong i265 size"); + } } } diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp index ab3f83064f..0d5a851440 100644 --- a/libevmjit/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -24,6 +24,7 @@ #include "Memory.h" #include "Stack.h" #include "Type.h" +#include "Compiler.h" namespace dev { @@ -32,12 +33,19 @@ namespace eth namespace jit { -int ExecutionEngine::run(std::unique_ptr _module, RuntimeData* _data, Env* _env) +ReturnCode ExecutionEngine::run(bytes const& _code, RuntimeData* _data, Env* _env) +{ + Compiler::Options defaultOptions; + auto module = Compiler(defaultOptions).compile(_code); + return run(std::move(module), _data, _env); +} + +ReturnCode ExecutionEngine::run(std::unique_ptr _module, RuntimeData* _data, Env* _env) { auto module = _module.get(); // Keep ownership of the module in _module llvm::sys::PrintStackTraceOnErrorSignal(); - static const auto program = "evmcc"; + static const auto program = "EVM JIT"; llvm::PrettyStackTraceProgram X(1, &program); auto&& context = llvm::getGlobalContext(); @@ -66,10 +74,10 @@ int ExecutionEngine::run(std::unique_ptr _module, RuntimeData* _da auto exec = std::unique_ptr(builder.create()); if (!exec) - return -1; // FIXME: Handle internal errors + return ReturnCode::LLVMConfigError; _module.release(); // Successfully created llvm::ExecutionEngine takes ownership of the module - auto finalizationStartTime = std::chrono::high_resolution_clock::now(); // FIXME: It's not compilation time + auto finalizationStartTime = std::chrono::high_resolution_clock::now(); exec->finalizeObject(); auto finalizationEndTime = std::chrono::high_resolution_clock::now(); clog(JIT) << " + " << std::chrono::duration_cast(finalizationEndTime - finalizationStartTime).count(); @@ -78,7 +86,7 @@ int ExecutionEngine::run(std::unique_ptr _module, RuntimeData* _da auto entryFunc = module->getFunction("main"); if (!entryFunc) - return -2; // FIXME: Handle internal errors + return ReturnCode::LLVMLinkError; ReturnCode returnCode; std::jmp_buf buf; @@ -111,7 +119,7 @@ int ExecutionEngine::run(std::unique_ptr _module, RuntimeData* _da clog(JIT) << "\n"; - return static_cast(returnCode); + return returnCode; } } diff --git a/libevmjit/ExecutionEngine.h b/libevmjit/ExecutionEngine.h index 8d8715a956..3adceb404b 100644 --- a/libevmjit/ExecutionEngine.h +++ b/libevmjit/ExecutionEngine.h @@ -1,9 +1,11 @@ - #pragma once -#include +namespace llvm +{ + class Module; +} -#include "Runtime.h" +#include "RuntimeData.h" namespace dev { @@ -15,9 +17,12 @@ namespace jit class ExecutionEngine { public: - // FIXME: constructor? ExecutionEngine(); + ExecutionEngine() = default; + ExecutionEngine(ExecutionEngine const&) = delete; + void operator=(ExecutionEngine) = delete; - int run(std::unique_ptr module, RuntimeData* _data, Env* _env); + ReturnCode run(bytes const& _code, RuntimeData* _data, Env* _env); + ReturnCode run(std::unique_ptr module, RuntimeData* _data, Env* _env); bytes returnData; }; diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 0271694cb7..3955d21cdd 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -65,7 +65,7 @@ Ext::Ext(RuntimeManager& _runtimeManager, Memory& _memoryMan): m_getExtCode = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, getExtCodeArgsTypes, false), Linkage::ExternalLinkage, "env_getExtCode", module); // Helper function, not client Env interface - llvm::Type* callDataLoadArgsTypes[] = {Type::RuntimePtr, Type::WordPtr, Type::WordPtr}; + llvm::Type* callDataLoadArgsTypes[] = {Type::RuntimeDataPtr, Type::WordPtr, Type::WordPtr}; m_calldataload = llvm::Function::Create(llvm::FunctionType::get(Type::Void, callDataLoadArgsTypes, false), Linkage::ExternalLinkage, "ext_calldataload", module); } @@ -86,7 +86,7 @@ void Ext::sstore(llvm::Value* _index, llvm::Value* _value) llvm::Value* Ext::calldataload(llvm::Value* _index) { m_builder.CreateStore(_index, m_args[0]); - createCall(m_calldataload, getRuntimeManager().getRuntimePtr(), m_args[0], m_args[1]); + createCall(m_calldataload, getRuntimeManager().getDataPtr(), m_args[0], m_args[1]); auto ret = m_builder.CreateLoad(m_args[1]); return Endianness::toNative(m_builder, ret); } diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index 11a995785f..d119d56355 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -27,9 +27,6 @@ using StackImpl = std::vector; using MemoryImpl = bytes; using JmpBufRef = decltype(&jmp_buf{}[0]); -/// VM Environment (ExtVM) opaque type -struct Env; - class Runtime { public: @@ -38,8 +35,6 @@ public: Runtime(const Runtime&) = delete; void operator=(const Runtime&) = delete; - RuntimeData* getDataPtr() { return &m_data; } // FIXME: Remove - StackImpl& getStack() { return m_stack; } MemoryImpl& getMemory() { return m_memory; } Env* getEnvPtr() { return &m_env; } diff --git a/libevmjit/RuntimeData.h b/libevmjit/RuntimeData.h index c166e5ab5d..fc372fee32 100644 --- a/libevmjit/RuntimeData.h +++ b/libevmjit/RuntimeData.h @@ -1,9 +1,6 @@ - #pragma once -#include - -#include "Utils.h" +#include "Common.h" namespace dev @@ -43,6 +40,9 @@ struct RuntimeData byte const* code; }; +/// VM Environment (ExtVM) opaque type +struct Env; + } } } diff --git a/libevmjit/Stack.cpp b/libevmjit/Stack.cpp index f8e9aee705..e92f3dd3fd 100644 --- a/libevmjit/Stack.cpp +++ b/libevmjit/Stack.cpp @@ -109,7 +109,7 @@ extern "C" *(stack.rbegin() + _index) = *_word; } - EXPORT void ext_calldataload(Runtime* _rt, i256* _index, byte* o_value) + EXPORT void ext_calldataload(RuntimeData* _rtData, i256* _index, byte* o_value) { // It asumes all indexes are less than 2^64 @@ -117,8 +117,8 @@ extern "C" if (_index->b || _index->c || _index->d) // if bigger that 2^64 index = std::numeric_limits::max(); // set max to fill with 0 leter - auto data = _rt->getDataPtr()->callData; - auto size = _rt->getDataPtr()->elems[RuntimeData::CallDataSize].a; + auto data = _rtData->callData; + auto size = _rtData->elems[RuntimeData::CallDataSize].a; for (auto i = 0; i < 32; ++i) { if (index < size) diff --git a/libevmjit/Type.h b/libevmjit/Type.h index fd3c905d1d..0a98cb8a12 100644 --- a/libevmjit/Type.h +++ b/libevmjit/Type.h @@ -39,18 +39,6 @@ struct Type static void init(llvm::LLVMContext& _context); }; -enum class ReturnCode -{ - Stop = 0, - Return = 1, - Suicide = 2, - - BadJumpDestination = 101, - OutOfGas = 102, - StackTooSmall = 103, - BadInstruction = 104, -}; - struct Constant { /// Returns word-size constant diff --git a/libevmjit/Utils.h b/libevmjit/Utils.h index 73e01d2eeb..33ff344d6b 100644 --- a/libevmjit/Utils.h +++ b/libevmjit/Utils.h @@ -1,8 +1,5 @@ - #pragma once -#include - #include "Common.h" namespace dev @@ -16,17 +13,6 @@ struct JIT: public NoteChannel { static const char* name() { return "JIT"; } }; #define clog(CHANNEL) std::cerr -/// Representation of 256-bit value binary compatible with LLVM i256 -// TODO: Replace with h256 -struct i256 -{ - uint64_t a; - uint64_t b; - uint64_t c; - uint64_t d; -}; -static_assert(sizeof(i256) == 32, "Wrong i265 size"); - u256 llvm2eth(i256); i256 eth2llvm(u256);