diff --git a/include/evmjit/JIT-c.h b/include/evmjit/JIT-c.h new file mode 100644 index 000000000..a92b29090 --- /dev/null +++ b/include/evmjit/JIT-c.h @@ -0,0 +1,66 @@ + +#include "stdint.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct evmjit_i256 +{ + uint64_t words[4]; +} evmjit_i256; + +typedef struct evmjit_runtime_data +{ + int64_t gas; + int64_t gasPrice; + char const* callData; + uint64_t callDataSize; + evmjit_i256 address; + evmjit_i256 caller; + evmjit_i256 origin; + evmjit_i256 callValue; + evmjit_i256 coinBase; + evmjit_i256 difficulty; + evmjit_i256 gasLimit; + uint64_t number; + int64_t timestamp; + char const* code; + uint64_t codeSize; + evmjit_i256 codeHash; +} evmjit_runtime_data; + +typedef enum evmjit_return_code +{ + // Success codes + Stop = 0, + Return = 1, + Suicide = 2, + + // Standard error codes + OutOfGas = -1, + StackUnderflow = -2, + BadJumpDestination = -3, + BadInstruction = -4, + Rejected = -5, ///< Input data (code, gas, block info, etc.) does not meet JIT requirement and execution request has been rejected + + // Internal error codes + LLVMError = -101, + UnexpectedException = -111 +} evmjit_return_code; + +typedef struct evmjit_context evmjit_context; + +evmjit_context* evmjit_create(evmjit_runtime_data* _data, void* _env); + +evmjit_return_code evmjit_exec(evmjit_context* _context); + +void evmjit_destroy(evmjit_context* _context); + + +inline char const* evmjit_get_output(evmjit_runtime_data* _data) { return _data->callData; } +inline uint64_t evmjit_get_output_size(evmjit_runtime_data* _data) { return _data->callDataSize; } + +#ifdef __cplusplus +} +#endif diff --git a/include/evmjit/JIT.h b/include/evmjit/JIT.h index 901c351d9..e74534243 100644 --- a/include/evmjit/JIT.h +++ b/include/evmjit/JIT.h @@ -121,7 +121,7 @@ public: ExecutionContext(RuntimeData& _data, Env* _env) { init(_data, _env); } ExecutionContext(ExecutionContext const&) = delete; ExecutionContext& operator=(ExecutionContext const&) = delete; - EXPORT ~ExecutionContext(); + EXPORT ~ExecutionContext() noexcept; void init(RuntimeData& _data, Env* _env) { m_data = &_data; m_env = _env; } diff --git a/libevmjit/CMakeLists.txt b/libevmjit/CMakeLists.txt index 80108e15b..eddb22dc2 100644 --- a/libevmjit/CMakeLists.txt +++ b/libevmjit/CMakeLists.txt @@ -1,26 +1,27 @@ set(TARGET_NAME evmjit) set(SOURCES - JIT.cpp ${EVMJIT_INCLUDE_DIR}/evmjit/JIT.h - Arith256.cpp Arith256.h - Array.cpp Array.h - BasicBlock.cpp BasicBlock.h - Cache.cpp Cache.h - Common.h - Compiler.cpp Compiler.h - CompilerHelper.cpp CompilerHelper.h - Endianness.cpp Endianness.h - ExecStats.cpp ExecStats.h - Ext.cpp Ext.h - GasMeter.cpp GasMeter.h - Instruction.cpp Instruction.h - interface.cpp interface.h - Memory.cpp Memory.h - Optimizer.cpp Optimizer.h - RuntimeManager.cpp RuntimeManager.h - Stack.cpp Stack.h - Type.cpp Type.h - Utils.cpp Utils.h + JIT.cpp ${EVMJIT_INCLUDE_DIR}/evmjit/JIT.h + JIT-c.cpp ${EVMJIT_INCLUDE_DIR}/evmjit/JIT-c.h + Arith256.cpp Arith256.h + Array.cpp Array.h + BasicBlock.cpp BasicBlock.h + Cache.cpp Cache.h + Common.h + Compiler.cpp Compiler.h + CompilerHelper.cpp CompilerHelper.h + Endianness.cpp Endianness.h + ExecStats.cpp ExecStats.h + Ext.cpp Ext.h + GasMeter.cpp GasMeter.h + Instruction.cpp Instruction.h + #interface.cpp interface.h + Memory.cpp Memory.h + Optimizer.cpp Optimizer.h + RuntimeManager.cpp RuntimeManager.h + Stack.cpp Stack.h + Type.cpp Type.h + Utils.cpp Utils.h ) source_group("" FILES ${SOURCES}) @@ -62,7 +63,7 @@ endif() if(${EVMJIT_VERSION_MAJOR} EQUAL 0) set(EVMJIT_SOVERSION "0.${EVMJIT_VERSION_MINOR}") -else() +else() set(EVMJIT_SOVERSION ${EVMJIT_VERSION_MAJOR}) endif() @@ -73,7 +74,7 @@ configure_file(BuildInfo.h.in ${CMAKE_CURRENT_BINARY_DIR}/gen/BuildInfo.gen.h) message(STATUS "EVM JIT version: ${EVMJIT_VERSION_MAJOR}.${EVMJIT_VERSION_MINOR}.${EVMJIT_VERSION_PATCH} ${EVMJIT_VERSION_PRERELEASE} (${EVMJIT_VERSION_FULL})") add_library(${TARGET_NAME} SHARED ${SOURCES} gen/BuildInfo.gen.h) -set_target_properties(${TARGET_NAME} PROPERTIES +set_target_properties(${TARGET_NAME} PROPERTIES VERSION ${EVMJIT_VERSION} SOVERSION ${EVMJIT_SOVERSION} FOLDER "libs") diff --git a/libevmjit/JIT-c.cpp b/libevmjit/JIT-c.cpp new file mode 100644 index 000000000..2fd578108 --- /dev/null +++ b/libevmjit/JIT-c.cpp @@ -0,0 +1,48 @@ +#include +#include +#include + +extern "C" +{ +using namespace dev::evmjit; + +EXPORT evmjit_context* evmjit_create(evmjit_runtime_data* _data, void* _env) +{ + auto data = reinterpret_cast(_data); + auto env = reinterpret_cast(_env); + + assert(!data && "Pointer to runtime data must not be null"); + if (!data) + return nullptr; + + // TODO: Make sure ExecutionEngine constructor does not throw + make JIT/ExecutionEngine interface all nothrow + auto context = new(std::nothrow) ExecutionContext{*data, env}; + return reinterpret_cast(context); +} + +EXPORT void evmjit_destroy(evmjit_context* _context) +{ + auto context = reinterpret_cast(_context); + delete context; +} + +EXPORT evmjit_return_code evmjit_exec(evmjit_context* _context) +{ + auto context = reinterpret_cast(_context); + + assert(!context && "Invalid context"); + if (!context) + return UnexpectedException; + + try + { + auto returnCode = JIT::exec(*context); + return static_cast(returnCode); + } + catch(...) + { + return UnexpectedException; + } +} + +} diff --git a/libevmjit/JIT.cpp b/libevmjit/JIT.cpp index 53c36dcb2..3cdf26642 100644 --- a/libevmjit/JIT.cpp +++ b/libevmjit/JIT.cpp @@ -227,7 +227,7 @@ ReturnCode JIT::exec(ExecutionContext& _context) extern "C" void ext_free(void* _data) noexcept; -ExecutionContext::~ExecutionContext() +ExecutionContext::~ExecutionContext() noexcept { if (m_memData) ext_free(m_memData); // Use helper free to check memory leaks diff --git a/libevmjit/interface.cpp b/libevmjit/interface.cpp deleted file mode 100644 index 7136f6798..000000000 --- a/libevmjit/interface.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "evmjit/JIT.h" - -extern "C" -{ -using namespace dev::evmjit; - -EXPORT void* evmjit_create(RuntimeData* _data, Env* _env) noexcept -{ - if (!_data) - return nullptr; - - // TODO: Make sure ExecutionEngine constructor does not throw + make JIT/ExecutionEngine interface all nothrow - return new(std::nothrow) ExecutionContext{*_data, _env}; -} - -EXPORT void evmjit_destroy(ExecutionContext* _context) noexcept -{ - delete _context; -} - -EXPORT int evmjit_run(ExecutionContext* _context) noexcept -{ - try - { - auto returnCode = JIT::exec(*_context); - return static_cast(returnCode); - } - catch(...) - { - return static_cast(ReturnCode::UnexpectedException); - } -} - -} diff --git a/libevmjit/interface.h b/libevmjit/interface.h deleted file mode 100644 index 4f4d56610..000000000 --- a/libevmjit/interface.h +++ /dev/null @@ -1,13 +0,0 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -void* evmjit_create(); -int evmjit_run(void* _jit, void* _data, void* _env); -void evmjit_destroy(void* _jit); - - -#ifdef __cplusplus -} -#endif