diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..84c048a73c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/build/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 18601b921f..acb113207e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,15 @@ 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") +endif() + +if(APPLE) + set(CMAKE_SHARED_LINKER_FLAGS "-undefined dynamic_lookup") +endif() + # LLVM if(LLVM_DIR) # local LLVM build find_package(LLVM REQUIRED CONFIG) @@ -18,11 +27,18 @@ else() execute_process(COMMAND llvm-config-3.5 --includedir OUTPUT_VARIABLE LLVM_INCLUDE_DIRS) 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) endif() # Boost find_package(Boost REQUIRED) add_subdirectory(libevmjit) -add_subdirectory(libevmjit-cpp) -add_subdirectory(evmcc) + +if(EVMJIT_CPP) + add_subdirectory(libevmjit-cpp) +endif() + +if(EVMJIT_TOOLS) + add_subdirectory(evmcc) +endif() diff --git a/libevmjit/CMakeLists.txt b/libevmjit/CMakeLists.txt index 7c35169a7a..28b501ee3a 100644 --- a/libevmjit/CMakeLists.txt +++ b/libevmjit/CMakeLists.txt @@ -10,7 +10,8 @@ if (NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") set_source_files_properties(Cache.cpp PROPERTIES COMPILE_FLAGS -fno-rtti) endif () -add_library(${TARGET_NAME} ${SOURCES} ${HEADERS}) +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}) diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp index 7e99932c37..71142fbeee 100644 --- a/libevmjit/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -49,7 +49,7 @@ ReturnCode runEntryFunc(EntryFuncPtr _mainFunc, Runtime* _runtime) std::string codeHash(bytes const& _code) { - std::array binHash; + std::array binHash; env_sha3(_code.data(), _code.size(), &binHash); std::ostringstream os; diff --git a/libevmjit/interface.cpp b/libevmjit/interface.cpp new file mode 100644 index 0000000000..eef92d00fd --- /dev/null +++ b/libevmjit/interface.cpp @@ -0,0 +1,34 @@ +#include "interface.h" +#include +#include "ExecutionEngine.h" + +extern "C" +{ + +evmjit_result evmjit_run(void* _data, void* _env) +{ + using namespace dev::eth::jit; + + auto data = static_cast(_data); + + ExecutionEngine engine; + + auto codePtr = data->code; + auto codeSize = data->elems[RuntimeData::CodeSize].a; + bytes bytecode; + bytecode.insert(bytecode.end(), codePtr, codePtr + codeSize); + + auto returnCode = engine.run(bytecode, data, static_cast(_env)); + evmjit_result result = {static_cast(returnCode), 0, nullptr}; + if (returnCode == ReturnCode::Return && !engine.returnData.empty()) + { + // TODO: Optimized returning data. Allocating memory on client side by callback function might be a good idea + result.returnDataSize = engine.returnData.size(); + result.returnData = std::malloc(result.returnDataSize); + std::memcpy(result.returnData, engine.returnData.data(), result.returnDataSize); + } + + return result; +} + +} diff --git a/libevmjit/interface.c b/libevmjit/interface.h similarity index 76% rename from libevmjit/interface.c rename to libevmjit/interface.h index 47589578b6..5d9307ab2b 100644 --- a/libevmjit/interface.c +++ b/libevmjit/interface.h @@ -1,5 +1,20 @@ +#include #include +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct evmjit_result +{ + int32_t returnCode; + uint64_t returnDataSize; + void* returnData; + +} evmjit_result; + +evmjit_result evmjit_run(void* _data, void* _env); + // JIT object opaque type typedef struct evm_jit evm_jit; @@ -9,6 +24,11 @@ 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; @@ -28,3 +48,7 @@ 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