From 0a78fe0756bc94c3f2113c3ee0ffe9c88c819302 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 25 Sep 2014 11:07:49 +0200 Subject: [PATCH 001/641] Init of evmcc - EVM Code Compiler --- CMakeLists.txt | 5 ++ evmcc/CMakeLists.txt | 49 ++++++++++++ evmcc/bytecode/kv.evm | 1 + evmcc/evmcc.cpp | 180 ++++++++++++++++++++++++++++++++++++++++++ evmcc/lll/kv.lll | 10 +++ 5 files changed, 245 insertions(+) create mode 100644 evmcc/CMakeLists.txt create mode 100644 evmcc/bytecode/kv.evm create mode 100644 evmcc/evmcc.cpp create mode 100644 evmcc/lll/kv.lll diff --git a/CMakeLists.txt b/CMakeLists.txt index 46cc0753f..d69e1e958 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -374,6 +374,11 @@ if (NOT LANGUAGES) endif() endif() +if (EVMCC) + add_subdirectory(evmcc) +endif() + + set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SRC_LIST BuildInfo.h) diff --git a/evmcc/CMakeLists.txt b/evmcc/CMakeLists.txt new file mode 100644 index 000000000..b91b2d257 --- /dev/null +++ b/evmcc/CMakeLists.txt @@ -0,0 +1,49 @@ +cmake_policy(SET CMP0015 NEW) + +aux_source_directory(. SRC_LIST) + +include_directories(..) + +set(EXECUTABLE evmcc) + +add_executable(${EXECUTABLE} ${SRC_LIST}) + +target_link_libraries(${EXECUTABLE} evmface) +target_link_libraries(${EXECUTABLE} devcore) + +if ("${TARGET_PLATFORM}" STREQUAL "w64") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") + target_link_libraries(${EXECUTABLE} gcc) + target_link_libraries(${EXECUTABLE} gdi32) + target_link_libraries(${EXECUTABLE} ws2_32) + target_link_libraries(${EXECUTABLE} mswsock) + target_link_libraries(${EXECUTABLE} shlwapi) + target_link_libraries(${EXECUTABLE} iphlpapi) + target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) + set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) +elseif (UNIX) +else () + find_package(Threads REQUIRED) + target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) +endif () + +# LLVM specific commands + +find_package(LLVM REQUIRED CONFIG) + +message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") +message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + +include_directories(${LLVM_INCLUDE_DIRS}) +add_definitions(${LLVM_DEFINITIONS}) + +llvm_map_components_to_libnames(llvm_libs support core irreader) +target_link_libraries(etc ${llvm_libs}) + +# end of LLVM specific commands + + + +install( TARGETS ${EXECUTABLE} DESTINATION bin ) + +cmake_policy(SET CMP0015 NEW) diff --git a/evmcc/bytecode/kv.evm b/evmcc/bytecode/kv.evm new file mode 100644 index 000000000..55141ea59 --- /dev/null +++ b/evmcc/bytecode/kv.evm @@ -0,0 +1 @@ +33604557602a8060106000396000f200604556330e0f602a59366080530a0f602a59602060805301356080533557604060805301608054600958 diff --git a/evmcc/evmcc.cpp b/evmcc/evmcc.cpp new file mode 100644 index 000000000..94fcb956b --- /dev/null +++ b/evmcc/evmcc.cpp @@ -0,0 +1,180 @@ +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include + +using namespace dev; + +class EVMCCompiler +{ + +private: + + struct + { + llvm::Type* word8; + llvm::Type* word8ptr; + llvm::Type* word256; + llvm::Type* word256ptr; + llvm::Type* word256arr; + llvm::Type* size; + } Types; + +public: + + EVMCCompiler() + { + auto& context = llvm::getGlobalContext(); + Types.word8 = llvm::Type::getInt8Ty(context); + Types.word8ptr = llvm::Type::getInt8PtrTy(context); + Types.word256 = llvm::Type::getIntNTy(context, 256); + Types.word256ptr = Types.word256->getPointerTo(); + Types.word256arr = llvm::ArrayType::get(Types.word256, 100); + Types.size = llvm::Type::getInt64Ty(context); + } + + void compile(const bytes& bytecode) + { + using namespace llvm; + + auto& context = getGlobalContext(); + + Module* module = new Module("main", context); + IRBuilder<> builder(context); + + // Create globals for memory, memory size, stack and stack top + auto memory = new GlobalVariable(*module, Types.word8ptr, false, + GlobalValue::LinkageTypes::PrivateLinkage, + Constant::getNullValue(Types.word8ptr), "memory"); + auto memSize = new GlobalVariable(*module, Types.size, false, + GlobalValue::LinkageTypes::PrivateLinkage, + ConstantInt::get(Types.size, 0), "memsize"); + auto stack = new GlobalVariable(*module, Types.word256arr, false, + GlobalValue::LinkageTypes::PrivateLinkage, + ConstantAggregateZero::get(Types.word256arr), "stack"); + auto stackTop = new GlobalVariable(*module, Types.size, false, + GlobalValue::LinkageTypes::PrivateLinkage, + ConstantInt::get(Types.size, 0), "stackTop"); + + // Create value for void* malloc(size_t) + std::vector mallocArgTypes = { Types.size }; + Value* mallocVal = Function::Create(FunctionType::get(Types.word8ptr, mallocArgTypes, false), + GlobalValue::LinkageTypes::ExternalLinkage, "malloc", module); + + // Create main function + FunctionType* funcType = FunctionType::get(llvm::Type::getInt32Ty(context), false); + Function* mainFunc = Function::Create(funcType, Function::ExternalLinkage, "main", module); + + BasicBlock* entryBlock = BasicBlock::Create(context, "entry", mainFunc); + builder.SetInsertPoint(entryBlock); + + // Initialize memory with call to malloc, update memsize + std::vector mallocMemArgs = { ConstantInt::get(Types.size, 100) }; + auto mallocMemCall = builder.CreateCall(mallocVal, mallocMemArgs, "malloc_mem"); + builder.CreateStore(mallocMemCall, memory); + builder.CreateStore(ConstantInt::get(Types.size, 100), memSize); + + /* + std::vector mallocStackArgs = { ConstantInt::get(sizeTy, 200) }; + auto mallocStackCall = builder.CreateCall(mallocVal, mallocStackArgs, "malloc_stack"); + auto mallocCast = builder.CreatePointerBitCastOrAddrSpaceCast(mallocStackCall, int256ptr); + builder.CreateStore(mallocCast, stackVal); + */ + + builder.CreateRet(ConstantInt::get(Type::getInt32Ty(context), 0)); + + module->dump(); + } + +}; + +void show_usage() +{ + // FIXME: Use arg[0] as program name? + std::cerr << "usage: evmcc (-b|-c|-d)+ \n"; +} + +int main(int argc, char** argv) +{ + + std::string input_file; + bool opt_dissassemble = false; + bool opt_show_bytes = false; + bool opt_compile = false; + bool opt_unknown = false; + + for (int i = 1; i < argc; i++) + { + std::string option = argv[i]; + if (option == "-b") + { + opt_show_bytes = true; + } + else if (option == "-c") + { + opt_compile = true; + } + else if (option == "-d") + { + opt_dissassemble = true; + } + else if (option[0] != '-' && input_file.empty()) + { + input_file = option; + } + else + { + opt_unknown = true; + break; + } + } + + if (opt_unknown || + input_file.empty() || + (!opt_show_bytes && !opt_compile && !opt_dissassemble)) + { + show_usage(); + exit(1); + } + + std::ifstream ifs(input_file); + if (!ifs.is_open()) + { + std::cerr << "cannot open file " << input_file << std::endl; + exit(1); + } + + std::string src((std::istreambuf_iterator(ifs)), + (std::istreambuf_iterator())); + + boost::algorithm::trim(src); + + bytes bytecode = fromHex(src); + + if (opt_show_bytes) + { + std::cout << dev::memDump(bytecode) << std::endl; + } + + if (opt_dissassemble) + { + std::string assembly = eth::disassemble(bytecode); + std::cout << assembly << std::endl; + } + + if (opt_compile) + { + EVMCCompiler().compile(bytecode); + } + + return 0; +} diff --git a/evmcc/lll/kv.lll b/evmcc/lll/kv.lll new file mode 100644 index 000000000..c62d9fa70 --- /dev/null +++ b/evmcc/lll/kv.lll @@ -0,0 +1,10 @@ +{ + [[69]] (caller) + (return 0 (lll + (when (= (caller) @@69) + (for {} (< @i (calldatasize)) [i](+ @i 64) + [[ (calldataload @i) ]] (calldataload (+ @i 32)) + ) + ) + 0)) +} From a3a33112be79ba72eac1a8cd07f15a3a9345374c Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Thu, 25 Sep 2014 10:46:12 +0100 Subject: [PATCH 002/641] etc --> evmcc in cmakefile --- evmcc/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evmcc/CMakeLists.txt b/evmcc/CMakeLists.txt index b91b2d257..550492583 100644 --- a/evmcc/CMakeLists.txt +++ b/evmcc/CMakeLists.txt @@ -38,7 +38,7 @@ include_directories(${LLVM_INCLUDE_DIRS}) add_definitions(${LLVM_DEFINITIONS}) llvm_map_components_to_libnames(llvm_libs support core irreader) -target_link_libraries(etc ${llvm_libs}) +target_link_libraries(evmcc ${llvm_libs}) # end of LLVM specific commands From 76975a1b42ba7a06f787bac4b25a9b8f314c7433 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 25 Sep 2014 18:14:00 +0200 Subject: [PATCH 003/641] Visual Studio project config for evmcc --- windows/Ethereum.sln | 2 + windows/evmcc.vcxproj | 170 ++++++++++++++++++++++++++++++++++ windows/evmcc.vcxproj.filters | 6 ++ 3 files changed, 178 insertions(+) create mode 100644 windows/evmcc.vcxproj create mode 100644 windows/evmcc.vcxproj.filters diff --git a/windows/Ethereum.sln b/windows/Ethereum.sln index 26fe794c2..96b5f4c9e 100644 --- a/windows/Ethereum.sln +++ b/windows/Ethereum.sln @@ -37,6 +37,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sc", "Sc.vcxproj", "{90068D EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lllc", "Lllc.vcxproj", "{255BDC68-B8DB-465F-8220-981E77684189}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "evmcc", "evmcc.vcxproj", "{D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 diff --git a/windows/evmcc.vcxproj b/windows/evmcc.vcxproj new file mode 100644 index 000000000..f521a8264 --- /dev/null +++ b/windows/evmcc.vcxproj @@ -0,0 +1,170 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D} + Win32Proj + evmcc + + + + Application + true + v120 + Unicode + + + Application + true + v120 + + + Application + false + v120 + true + Unicode + + + Application + false + v120 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + true + ..\..\_build\$(ProjectName)\$(Platform)_$(Configuration)\ + ..\..\_build\$(ProjectName)\$(Platform)_$(Configuration)\ + + + true + + + false + ..\..\_build\$(ProjectName)\$(Platform)_$(Configuration)\ + ..\..\_build\$(ProjectName)\$(Platform)_$(Configuration)\ + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + true + ../ + + + Console + true + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + true + ../../llvm-3.5.0/include;../../builds/llvm3.5/include;%(AdditionalIncludeDirectories) + 4068;4244;4267;4800 + + + Console + true + ../../builds/llvm3.5/Debug/lib;../../_build/LibEthereum/x64_Debug;%(AdditionalLibraryDirectories) + LibEthereum.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + true + ../../llvm-3.5.0/include;../../builds/llvm3.5/include;%(AdditionalIncludeDirectories) + 4068;4244;4267;4800 + + + Console + true + true + true + ../../builds/llvm3.5/Debug/lib;../../_build/LibEthereum/x64_Debug;%(AdditionalLibraryDirectories) + LibEthereum.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) + + + + + + \ No newline at end of file diff --git a/windows/evmcc.vcxproj.filters b/windows/evmcc.vcxproj.filters new file mode 100644 index 000000000..6be5386a1 --- /dev/null +++ b/windows/evmcc.vcxproj.filters @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file From f4c7a514e9255dec382743e6f19f1419738054ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 26 Sep 2014 11:12:16 +0200 Subject: [PATCH 004/641] Fixing evmcc Visual Studio project settings --- windows/Ethereum.sln | 14 ++++++-------- windows/evmcc.vcxproj | 4 ++++ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/windows/Ethereum.sln b/windows/Ethereum.sln index 96b5f4c9e..c894b8a79 100644 --- a/windows/Ethereum.sln +++ b/windows/Ethereum.sln @@ -111,14 +111,6 @@ Global {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Release|Win32.Build.0 = Release|Win32 {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Release|x64.ActiveCfg = Release|x64 {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Release|x64.Build.0 = Release|x64 - {326EF470-463F-4751-A22A-48BBAAD8B143}.Debug|Win32.ActiveCfg = Debug|Win32 - {326EF470-463F-4751-A22A-48BBAAD8B143}.Debug|Win32.Build.0 = Debug|Win32 - {326EF470-463F-4751-A22A-48BBAAD8B143}.Debug|x64.ActiveCfg = Debug|x64 - {326EF470-463F-4751-A22A-48BBAAD8B143}.Debug|x64.Build.0 = Debug|x64 - {326EF470-463F-4751-A22A-48BBAAD8B143}.Release|Win32.ActiveCfg = Release|Win32 - {326EF470-463F-4751-A22A-48BBAAD8B143}.Release|Win32.Build.0 = Release|Win32 - {326EF470-463F-4751-A22A-48BBAAD8B143}.Release|x64.ActiveCfg = Release|x64 - {326EF470-463F-4751-A22A-48BBAAD8B143}.Release|x64.Build.0 = Release|x64 {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Debug|Win32.ActiveCfg = Debug|Win32 {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Debug|Win32.Build.0 = Debug|Win32 {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Debug|x64.ActiveCfg = Debug|x64 @@ -175,6 +167,12 @@ Global {255BDC68-B8DB-465F-8220-981E77684189}.Release|Win32.Build.0 = Release|Win32 {255BDC68-B8DB-465F-8220-981E77684189}.Release|x64.ActiveCfg = Release|x64 {255BDC68-B8DB-465F-8220-981E77684189}.Release|x64.Build.0 = Release|x64 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|Win32.ActiveCfg = Debug|Win32 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|Win32.Build.0 = Debug|Win32 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|x64.ActiveCfg = Debug|x64 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|Win32.ActiveCfg = Release|Win32 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|Win32.Build.0 = Release|Win32 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|x64.ActiveCfg = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/windows/evmcc.vcxproj b/windows/evmcc.vcxproj index f521a8264..5b09e5f0d 100644 --- a/windows/evmcc.vcxproj +++ b/windows/evmcc.vcxproj @@ -104,6 +104,8 @@ Console true + ../../builds/llvm3.5/Debug/lib;../../_build/LibEthereum/x64_Debug;%(AdditionalLibraryDirectories) + LibEthereum.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) @@ -140,6 +142,8 @@ true true true + ../../builds/llvm3.5/Debug/lib;../../_build/LibEthereum/x64_Debug;%(AdditionalLibraryDirectories) + LibEthereum.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) From f378909442c2b64217c710080dbf9ea2eaa2c594 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 26 Sep 2014 11:14:37 +0200 Subject: [PATCH 005/641] Moving Compiler to separated files --- evmcc/Compiler.cpp | 75 +++++++++++++++++++++++++++ evmcc/Compiler.h | 34 +++++++++++++ evmcc/evmcc.cpp | 96 +++-------------------------------- windows/evmcc.vcxproj | 4 ++ windows/evmcc.vcxproj.filters | 4 ++ 5 files changed, 124 insertions(+), 89 deletions(-) create mode 100644 evmcc/Compiler.cpp create mode 100644 evmcc/Compiler.h diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp new file mode 100644 index 000000000..209e79c6f --- /dev/null +++ b/evmcc/Compiler.cpp @@ -0,0 +1,75 @@ + +#include "Compiler.h" + +#include +#include + +namespace evmcc +{ + +Compiler::Compiler() +{ + auto& context = llvm::getGlobalContext(); + Types.word8 = llvm::Type::getInt8Ty(context); + Types.word8ptr = llvm::Type::getInt8PtrTy(context); + Types.word256 = llvm::Type::getIntNTy(context, 256); + Types.word256ptr = Types.word256->getPointerTo(); + Types.word256arr = llvm::ArrayType::get(Types.word256, 100); + Types.size = llvm::Type::getInt64Ty(context); +} + + +void Compiler::compile(const dev::bytes& bytecode) +{ + using namespace llvm; + + auto& context = getGlobalContext(); + + Module* module = new Module("main", context); + IRBuilder<> builder(context); + + // Create globals for memory, memory size, stack and stack top + auto memory = new GlobalVariable(*module, Types.word8ptr, false, + GlobalValue::LinkageTypes::PrivateLinkage, + Constant::getNullValue(Types.word8ptr), "memory"); + auto memSize = new GlobalVariable(*module, Types.size, false, + GlobalValue::LinkageTypes::PrivateLinkage, + ConstantInt::get(Types.size, 0), "memsize"); + auto stack = new GlobalVariable(*module, Types.word256arr, false, + GlobalValue::LinkageTypes::PrivateLinkage, + ConstantAggregateZero::get(Types.word256arr), "stack"); + auto stackTop = new GlobalVariable(*module, Types.size, false, + GlobalValue::LinkageTypes::PrivateLinkage, + ConstantInt::get(Types.size, 0), "stackTop"); + + // Create value for void* malloc(size_t) + std::vector mallocArgTypes = { Types.size }; + Value* mallocVal = Function::Create(FunctionType::get(Types.word8ptr, mallocArgTypes, false), + GlobalValue::LinkageTypes::ExternalLinkage, "malloc", module); + + // Create main function + FunctionType* funcType = FunctionType::get(llvm::Type::getInt32Ty(context), false); + Function* mainFunc = Function::Create(funcType, Function::ExternalLinkage, "main", module); + + BasicBlock* entryBlock = BasicBlock::Create(context, "entry", mainFunc); + builder.SetInsertPoint(entryBlock); + + // Initialize memory with call to malloc, update memsize + std::vector mallocMemArgs = { ConstantInt::get(Types.size, 100) }; + auto mallocMemCall = builder.CreateCall(mallocVal, mallocMemArgs, "malloc_mem"); + builder.CreateStore(mallocMemCall, memory); + builder.CreateStore(ConstantInt::get(Types.size, 100), memSize); + + /* + std::vector mallocStackArgs = { ConstantInt::get(sizeTy, 200) }; + auto mallocStackCall = builder.CreateCall(mallocVal, mallocStackArgs, "malloc_stack"); + auto mallocCast = builder.CreatePointerBitCastOrAddrSpaceCast(mallocStackCall, int256ptr); + builder.CreateStore(mallocCast, stackVal); + */ + + builder.CreateRet(ConstantInt::get(Type::getInt32Ty(context), 0)); + + module->dump(); +} + +} \ No newline at end of file diff --git a/evmcc/Compiler.h b/evmcc/Compiler.h new file mode 100644 index 000000000..1e6cca57f --- /dev/null +++ b/evmcc/Compiler.h @@ -0,0 +1,34 @@ + +#pragma once + +#include + +#include + +namespace evmcc +{ + +class Compiler +{ + +private: + + struct + { + llvm::Type* word8; + llvm::Type* word8ptr; + llvm::Type* word256; + llvm::Type* word256ptr; + llvm::Type* word256arr; + llvm::Type* size; + } Types; + +public: + + Compiler(); + + void compile(const dev::bytes& bytecode); + +}; + +} \ No newline at end of file diff --git a/evmcc/evmcc.cpp b/evmcc/evmcc.cpp index 94fcb956b..fc0b03a99 100644 --- a/evmcc/evmcc.cpp +++ b/evmcc/evmcc.cpp @@ -1,101 +1,19 @@ -#include -#include - -#include -#include -#include - -#include #include #include #include #include -using namespace dev; - -class EVMCCompiler -{ - -private: - - struct - { - llvm::Type* word8; - llvm::Type* word8ptr; - llvm::Type* word256; - llvm::Type* word256ptr; - llvm::Type* word256arr; - llvm::Type* size; - } Types; +#include -public: +#include +#include +#include - EVMCCompiler() - { - auto& context = llvm::getGlobalContext(); - Types.word8 = llvm::Type::getInt8Ty(context); - Types.word8ptr = llvm::Type::getInt8PtrTy(context); - Types.word256 = llvm::Type::getIntNTy(context, 256); - Types.word256ptr = Types.word256->getPointerTo(); - Types.word256arr = llvm::ArrayType::get(Types.word256, 100); - Types.size = llvm::Type::getInt64Ty(context); - } +#include "Compiler.h" - void compile(const bytes& bytecode) - { - using namespace llvm; - - auto& context = getGlobalContext(); - - Module* module = new Module("main", context); - IRBuilder<> builder(context); - - // Create globals for memory, memory size, stack and stack top - auto memory = new GlobalVariable(*module, Types.word8ptr, false, - GlobalValue::LinkageTypes::PrivateLinkage, - Constant::getNullValue(Types.word8ptr), "memory"); - auto memSize = new GlobalVariable(*module, Types.size, false, - GlobalValue::LinkageTypes::PrivateLinkage, - ConstantInt::get(Types.size, 0), "memsize"); - auto stack = new GlobalVariable(*module, Types.word256arr, false, - GlobalValue::LinkageTypes::PrivateLinkage, - ConstantAggregateZero::get(Types.word256arr), "stack"); - auto stackTop = new GlobalVariable(*module, Types.size, false, - GlobalValue::LinkageTypes::PrivateLinkage, - ConstantInt::get(Types.size, 0), "stackTop"); - - // Create value for void* malloc(size_t) - std::vector mallocArgTypes = { Types.size }; - Value* mallocVal = Function::Create(FunctionType::get(Types.word8ptr, mallocArgTypes, false), - GlobalValue::LinkageTypes::ExternalLinkage, "malloc", module); - - // Create main function - FunctionType* funcType = FunctionType::get(llvm::Type::getInt32Ty(context), false); - Function* mainFunc = Function::Create(funcType, Function::ExternalLinkage, "main", module); - - BasicBlock* entryBlock = BasicBlock::Create(context, "entry", mainFunc); - builder.SetInsertPoint(entryBlock); - - // Initialize memory with call to malloc, update memsize - std::vector mallocMemArgs = { ConstantInt::get(Types.size, 100) }; - auto mallocMemCall = builder.CreateCall(mallocVal, mallocMemArgs, "malloc_mem"); - builder.CreateStore(mallocMemCall, memory); - builder.CreateStore(ConstantInt::get(Types.size, 100), memSize); - - /* - std::vector mallocStackArgs = { ConstantInt::get(sizeTy, 200) }; - auto mallocStackCall = builder.CreateCall(mallocVal, mallocStackArgs, "malloc_stack"); - auto mallocCast = builder.CreatePointerBitCastOrAddrSpaceCast(mallocStackCall, int256ptr); - builder.CreateStore(mallocCast, stackVal); - */ - - builder.CreateRet(ConstantInt::get(Type::getInt32Ty(context), 0)); - - module->dump(); - } +using namespace dev; -}; void show_usage() { @@ -173,7 +91,7 @@ int main(int argc, char** argv) if (opt_compile) { - EVMCCompiler().compile(bytecode); + evmcc::Compiler().compile(bytecode); } return 0; diff --git a/windows/evmcc.vcxproj b/windows/evmcc.vcxproj index 5b09e5f0d..d82699495 100644 --- a/windows/evmcc.vcxproj +++ b/windows/evmcc.vcxproj @@ -19,8 +19,12 @@ + + + + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D} Win32Proj diff --git a/windows/evmcc.vcxproj.filters b/windows/evmcc.vcxproj.filters index 6be5386a1..7c10c71cc 100644 --- a/windows/evmcc.vcxproj.filters +++ b/windows/evmcc.vcxproj.filters @@ -2,5 +2,9 @@ + + + + \ No newline at end of file From ec7609f0ad9f00e81612cba10877a3d9672c544f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 26 Sep 2014 11:37:18 +0200 Subject: [PATCH 006/641] ExecutionEngine stub and -i program option for interpreting EVM Code --- evmcc/ExecutionEngine.cpp | 18 ++++++++++++++++++ evmcc/ExecutionEngine.h | 17 +++++++++++++++++ evmcc/evmcc.cpp | 29 ++++++++++++++++------------- windows/evmcc.vcxproj | 2 ++ windows/evmcc.vcxproj.filters | 2 ++ 5 files changed, 55 insertions(+), 13 deletions(-) create mode 100644 evmcc/ExecutionEngine.cpp create mode 100644 evmcc/ExecutionEngine.h diff --git a/evmcc/ExecutionEngine.cpp b/evmcc/ExecutionEngine.cpp new file mode 100644 index 000000000..2fe56f373 --- /dev/null +++ b/evmcc/ExecutionEngine.cpp @@ -0,0 +1,18 @@ + +#include "ExecutionEngine.h" + +namespace evmcc +{ + +ExecutionEngine::ExecutionEngine() +{ + +} + + +int ExecutionEngine::run(const dev::bytes& bytecode) +{ + return 0; +} + +} \ No newline at end of file diff --git a/evmcc/ExecutionEngine.h b/evmcc/ExecutionEngine.h new file mode 100644 index 000000000..e0c2693fa --- /dev/null +++ b/evmcc/ExecutionEngine.h @@ -0,0 +1,17 @@ + +#pragma once + +#include + +namespace evmcc +{ + +class ExecutionEngine +{ +public: + ExecutionEngine(); + + int run(const dev::bytes& bytecode); +}; + +} \ No newline at end of file diff --git a/evmcc/evmcc.cpp b/evmcc/evmcc.cpp index fc0b03a99..a7ed341a0 100644 --- a/evmcc/evmcc.cpp +++ b/evmcc/evmcc.cpp @@ -11,6 +11,7 @@ #include #include "Compiler.h" +#include "ExecutionEngine.h" using namespace dev; @@ -27,28 +28,23 @@ int main(int argc, char** argv) std::string input_file; bool opt_dissassemble = false; bool opt_show_bytes = false; - bool opt_compile = false; + bool opt_compile = false; + bool opt_interpret = false; bool opt_unknown = false; for (int i = 1; i < argc; i++) { std::string option = argv[i]; if (option == "-b") - { opt_show_bytes = true; - } else if (option == "-c") - { opt_compile = true; - } else if (option == "-d") - { - opt_dissassemble = true; - } - else if (option[0] != '-' && input_file.empty()) - { - input_file = option; - } + opt_dissassemble = true; + else if (option == "-i") + opt_interpret = true; + else if (option[0] != '-' && input_file.empty()) + input_file = option; else { opt_unknown = true; @@ -58,7 +54,7 @@ int main(int argc, char** argv) if (opt_unknown || input_file.empty() || - (!opt_show_bytes && !opt_compile && !opt_dissassemble)) + (!opt_show_bytes && !opt_compile && !opt_dissassemble && !opt_interpret)) { show_usage(); exit(1); @@ -94,5 +90,12 @@ int main(int argc, char** argv) evmcc::Compiler().compile(bytecode); } + if (opt_interpret) + { + auto engine = evmcc::ExecutionEngine(); + auto result = engine.run(bytecode); + return result; + } + return 0; } diff --git a/windows/evmcc.vcxproj b/windows/evmcc.vcxproj index d82699495..22df8b85d 100644 --- a/windows/evmcc.vcxproj +++ b/windows/evmcc.vcxproj @@ -21,9 +21,11 @@ + + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D} diff --git a/windows/evmcc.vcxproj.filters b/windows/evmcc.vcxproj.filters index 7c10c71cc..34635bd78 100644 --- a/windows/evmcc.vcxproj.filters +++ b/windows/evmcc.vcxproj.filters @@ -3,8 +3,10 @@ + + \ No newline at end of file From 75d7b8592efcea738f06fd28c2bebfa70ba867c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 26 Sep 2014 12:13:13 +0200 Subject: [PATCH 007/641] Remove public LLVM dependency in Compiler --- evmcc/Compiler.cpp | 10 ++++++++++ evmcc/Compiler.h | 15 --------------- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 209e79c6f..6ef70d4fe 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -7,6 +7,16 @@ namespace evmcc { +struct +{ + llvm::Type* word8; + llvm::Type* word8ptr; + llvm::Type* word256; + llvm::Type* word256ptr; + llvm::Type* word256arr; + llvm::Type* size; +} Types; + Compiler::Compiler() { auto& context = llvm::getGlobalContext(); diff --git a/evmcc/Compiler.h b/evmcc/Compiler.h index 1e6cca57f..6801a89d4 100644 --- a/evmcc/Compiler.h +++ b/evmcc/Compiler.h @@ -1,8 +1,6 @@ #pragma once -#include - #include namespace evmcc @@ -10,19 +8,6 @@ namespace evmcc class Compiler { - -private: - - struct - { - llvm::Type* word8; - llvm::Type* word8ptr; - llvm::Type* word256; - llvm::Type* word256ptr; - llvm::Type* word256arr; - llvm::Type* size; - } Types; - public: Compiler(); From 9ddc25a664e24165035f2c304a6491607f82fe11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 26 Sep 2014 15:18:56 +0200 Subject: [PATCH 008/641] Implementation of ExecutionEngine with LLVM MCJIT --- evmcc/Compiler.cpp | 13 ++++---- evmcc/Compiler.h | 4 ++- evmcc/ExecutionEngine.cpp | 67 +++++++++++++++++++++++++++++++++++++-- evmcc/ExecutionEngine.h | 4 ++- evmcc/evmcc.cpp | 6 ++-- windows/evmcc.vcxproj | 16 +++++++--- 6 files changed, 93 insertions(+), 17 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 6ef70d4fe..fa3349ea2 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -2,7 +2,6 @@ #include "Compiler.h" #include -#include namespace evmcc { @@ -29,13 +28,13 @@ Compiler::Compiler() } -void Compiler::compile(const dev::bytes& bytecode) +std::unique_ptr Compiler::compile(const dev::bytes& bytecode) { using namespace llvm; auto& context = getGlobalContext(); - Module* module = new Module("main", context); + auto module = std::make_unique("main", context); IRBuilder<> builder(context); // Create globals for memory, memory size, stack and stack top @@ -55,11 +54,11 @@ void Compiler::compile(const dev::bytes& bytecode) // Create value for void* malloc(size_t) std::vector mallocArgTypes = { Types.size }; Value* mallocVal = Function::Create(FunctionType::get(Types.word8ptr, mallocArgTypes, false), - GlobalValue::LinkageTypes::ExternalLinkage, "malloc", module); + GlobalValue::LinkageTypes::ExternalLinkage, "malloc", module.get()); // Create main function FunctionType* funcType = FunctionType::get(llvm::Type::getInt32Ty(context), false); - Function* mainFunc = Function::Create(funcType, Function::ExternalLinkage, "main", module); + Function* mainFunc = Function::Create(funcType, Function::ExternalLinkage, "main", module.get()); BasicBlock* entryBlock = BasicBlock::Create(context, "entry", mainFunc); builder.SetInsertPoint(entryBlock); @@ -77,9 +76,9 @@ void Compiler::compile(const dev::bytes& bytecode) builder.CreateStore(mallocCast, stackVal); */ - builder.CreateRet(ConstantInt::get(Type::getInt32Ty(context), 0)); + builder.CreateRet(ConstantInt::get(Type::getInt32Ty(context), 13)); - module->dump(); + return module; } } \ No newline at end of file diff --git a/evmcc/Compiler.h b/evmcc/Compiler.h index 6801a89d4..ae7033ac0 100644 --- a/evmcc/Compiler.h +++ b/evmcc/Compiler.h @@ -1,6 +1,8 @@ #pragma once +#include + #include namespace evmcc @@ -12,7 +14,7 @@ public: Compiler(); - void compile(const dev::bytes& bytecode); + std::unique_ptr compile(const dev::bytes& bytecode); }; diff --git a/evmcc/ExecutionEngine.cpp b/evmcc/ExecutionEngine.cpp index 2fe56f373..e59d6024a 100644 --- a/evmcc/ExecutionEngine.cpp +++ b/evmcc/ExecutionEngine.cpp @@ -1,6 +1,18 @@ #include "ExecutionEngine.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + namespace evmcc { @@ -10,9 +22,60 @@ ExecutionEngine::ExecutionEngine() } -int ExecutionEngine::run(const dev::bytes& bytecode) +int ExecutionEngine::run(std::unique_ptr _module) { - return 0; + auto module = _module.get(); // Keep ownership of the module in _module + + llvm::sys::PrintStackTraceOnErrorSignal(); + static const auto program = "evmcc"; + llvm::PrettyStackTraceProgram X(1, &program); + + auto&& context = llvm::getGlobalContext(); + + llvm::InitializeNativeTarget(); + llvm::InitializeNativeTargetAsmPrinter(); + llvm::InitializeNativeTargetAsmParser(); + + std::string errorMsg; + llvm::EngineBuilder builder(module); + //builder.setMArch(MArch); + //builder.setMCPU(MCPU); + //builder.setMAttrs(MAttrs); + //builder.setRelocationModel(RelocModel); + //builder.setCodeModel(CMModel); + builder.setErrorStr(&errorMsg); + builder.setEngineKind(llvm::EngineKind::JIT); + builder.setUseMCJIT(true); + builder.setMCJITMemoryManager(new llvm::SectionMemoryManager()); + builder.setOptLevel(llvm::CodeGenOpt::None); + + auto triple = llvm::Triple(llvm::sys::getProcessTriple()); + if (triple.getOS() == llvm::Triple::OSType::Win32) + triple.setObjectFormat(llvm::Triple::ObjectFormatType::ELF); // MCJIT does not support COFF format + module->setTargetTriple(triple.str()); + + auto exec = std::unique_ptr(builder.create()); + if (!exec) + { + if (!errorMsg.empty()) + std::cerr << "error creating EE: " << errorMsg << std::endl; + else + std::cerr << "unknown error creating llvm::ExecutionEngine" << std::endl; + exit(1); + } + _module.release(); // Successfully created llvm::ExecutionEngine takes ownership of the module + exec->finalizeObject(); + + auto entryFunc = module->getFunction("main"); + if (!entryFunc) + { + std::cerr << "main function not found\n"; + exit(1); + } + + auto result = exec->runFunction(entryFunc, {}); + auto intResult = result.IntVal.getZExtValue(); + return intResult; } } \ No newline at end of file diff --git a/evmcc/ExecutionEngine.h b/evmcc/ExecutionEngine.h index e0c2693fa..1bdf8c564 100644 --- a/evmcc/ExecutionEngine.h +++ b/evmcc/ExecutionEngine.h @@ -1,6 +1,8 @@ #pragma once +#include + #include namespace evmcc @@ -11,7 +13,7 @@ class ExecutionEngine public: ExecutionEngine(); - int run(const dev::bytes& bytecode); + int run(std::unique_ptr module); }; } \ No newline at end of file diff --git a/evmcc/evmcc.cpp b/evmcc/evmcc.cpp index a7ed341a0..bdc3681db 100644 --- a/evmcc/evmcc.cpp +++ b/evmcc/evmcc.cpp @@ -87,13 +87,15 @@ int main(int argc, char** argv) if (opt_compile) { - evmcc::Compiler().compile(bytecode); + evmcc::Compiler().compile(bytecode)->dump(); } if (opt_interpret) { auto engine = evmcc::ExecutionEngine(); - auto result = engine.run(bytecode); + auto module = evmcc::Compiler().compile(bytecode); + module->dump(); + auto result = engine.run(std::move(module)); return result; } diff --git a/windows/evmcc.vcxproj b/windows/evmcc.vcxproj index 22df8b85d..c75167852 100644 --- a/windows/evmcc.vcxproj +++ b/windows/evmcc.vcxproj @@ -85,17 +85,21 @@ true ..\..\_build\$(ProjectName)\$(Platform)_$(Configuration)\ ..\..\_build\$(ProjectName)\$(Platform)_$(Configuration)\ + false true + false false ..\..\_build\$(ProjectName)\$(Platform)_$(Configuration)\ ..\..\_build\$(ProjectName)\$(Platform)_$(Configuration)\ + false false + false @@ -106,12 +110,13 @@ WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) true ../ + false Console true ../../builds/llvm3.5/Debug/lib;../../_build/LibEthereum/x64_Debug;%(AdditionalLibraryDirectories) - LibEthereum.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) + LibEthereum.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) @@ -124,12 +129,13 @@ true ../../llvm-3.5.0/include;../../builds/llvm3.5/include;%(AdditionalIncludeDirectories) 4068;4244;4267;4800 + false Console true ../../builds/llvm3.5/Debug/lib;../../_build/LibEthereum/x64_Debug;%(AdditionalLibraryDirectories) - LibEthereum.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) + LibEthereum.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) @@ -142,6 +148,7 @@ true WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) true + false Console @@ -149,7 +156,7 @@ true true ../../builds/llvm3.5/Debug/lib;../../_build/LibEthereum/x64_Debug;%(AdditionalLibraryDirectories) - LibEthereum.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) + LibEthereum.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) @@ -164,6 +171,7 @@ true ../../llvm-3.5.0/include;../../builds/llvm3.5/include;%(AdditionalIncludeDirectories) 4068;4244;4267;4800 + false Console @@ -171,7 +179,7 @@ true true ../../builds/llvm3.5/Debug/lib;../../_build/LibEthereum/x64_Debug;%(AdditionalLibraryDirectories) - LibEthereum.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) + LibEthereum.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) From b47adc68c79ec9c52833a1f095e77565309b5dbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 26 Sep 2014 17:23:22 +0200 Subject: [PATCH 009/641] Staring with Stack helper --- evmcc/Compiler.cpp | 23 +++++++++++++++--- evmcc/Stack.cpp | 46 +++++++++++++++++++++++++++++++++++ windows/evmcc.vcxproj | 1 + windows/evmcc.vcxproj.filters | 1 + 4 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 evmcc/Stack.cpp diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index fa3349ea2..7478dd683 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -14,6 +14,7 @@ struct llvm::Type* word256ptr; llvm::Type* word256arr; llvm::Type* size; + llvm::Type* Void; } Types; Compiler::Compiler() @@ -25,6 +26,7 @@ Compiler::Compiler() Types.word256ptr = Types.word256->getPointerTo(); Types.word256arr = llvm::ArrayType::get(Types.word256, 100); Types.size = llvm::Type::getInt64Ty(context); + Types.Void = llvm::Type::getVoidTy(context); } @@ -44,7 +46,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto memSize = new GlobalVariable(*module, Types.size, false, GlobalValue::LinkageTypes::PrivateLinkage, ConstantInt::get(Types.size, 0), "memsize"); - auto stack = new GlobalVariable(*module, Types.word256arr, false, + auto stack2 = new GlobalVariable(*module, Types.word256arr, false, GlobalValue::LinkageTypes::PrivateLinkage, ConstantAggregateZero::get(Types.word256arr), "stack"); auto stackTop = new GlobalVariable(*module, Types.size, false, @@ -52,10 +54,16 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) ConstantInt::get(Types.size, 0), "stackTop"); // Create value for void* malloc(size_t) - std::vector mallocArgTypes = { Types.size }; - Value* mallocVal = Function::Create(FunctionType::get(Types.word8ptr, mallocArgTypes, false), + auto mallocVal = Function::Create(FunctionType::get(Types.word8ptr, { Types.size }, false), GlobalValue::LinkageTypes::ExternalLinkage, "malloc", module.get()); + // Create stack_create declaration + auto stackCreate = Function::Create(FunctionType::get(Types.word8ptr, false), + GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_create", module.get()); + + auto stackPush = Function::Create(FunctionType::get(Types.Void, std::vector{ Types.word8ptr, Types.word256 }, false), + GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_push", module.get()); + // Create main function FunctionType* funcType = FunctionType::get(llvm::Type::getInt32Ty(context), false); Function* mainFunc = Function::Create(funcType, Function::ExternalLinkage, "main", module.get()); @@ -69,6 +77,15 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) builder.CreateStore(mallocMemCall, memory); builder.CreateStore(ConstantInt::get(Types.size, 100), memSize); + auto stack = builder.CreateCall(stackCreate, "stack"); + + uint64_t words[] = { 1, 2, 3, 4 }; + auto val = llvm::APInt(256, 4, words); + auto c = ConstantInt::get(Types.word256, val); + + Value* args[] = { stack, c }; + builder.CreateCall(stackPush, args); + /* std::vector mallocStackArgs = { ConstantInt::get(sizeTy, 200) }; auto mallocStackCall = builder.CreateCall(mallocVal, mallocStackArgs, "malloc_stack"); diff --git a/evmcc/Stack.cpp b/evmcc/Stack.cpp new file mode 100644 index 000000000..e3faffd7e --- /dev/null +++ b/evmcc/Stack.cpp @@ -0,0 +1,46 @@ + +#include +#include +#include +#include + +#ifdef _MSC_VER + #define EXPORT __declspec(dllexport) +#else + #define EXPORT +#endif + +struct i256 +{ + uint64_t a; + uint64_t b; + uint64_t c; + uint64_t d; +}; + +using Stack = std::vector; + +extern "C" +{ + +EXPORT void* evmccrt_stack_create() +{ + std::cerr << "STACK create: "; + auto stack = new Stack; + std::cerr << stack << "\n"; + return stack; +} + +EXPORT void evmccrt_stack_push(void* _stack, uint64_t _partA, uint64_t _partB, uint64_t _partC, uint64_t _partD) +{ + std::cerr << "STACK push: " << _partA << " (" << std::hex << std::setfill('0') + << std::setw(16) << _partD << " " + << std::setw(16) << _partC << " " + << std::setw(16) << _partB << " " + << std::setw(16) << _partA; + auto stack = static_cast(_stack); + stack->push_back({_partA, _partB, _partC, _partD}); + std::cerr << ")\n"; +} + +} // extern "C" diff --git a/windows/evmcc.vcxproj b/windows/evmcc.vcxproj index c75167852..82a7b4c56 100644 --- a/windows/evmcc.vcxproj +++ b/windows/evmcc.vcxproj @@ -22,6 +22,7 @@ + diff --git a/windows/evmcc.vcxproj.filters b/windows/evmcc.vcxproj.filters index 34635bd78..f4be3b7d4 100644 --- a/windows/evmcc.vcxproj.filters +++ b/windows/evmcc.vcxproj.filters @@ -4,6 +4,7 @@ + From cb143c44c32f878b36e07c49f07e8521aa26269a Mon Sep 17 00:00:00 2001 From: Tim Hughes Date: Sat, 27 Sep 2014 13:20:19 +0100 Subject: [PATCH 010/641] Fixed size_t to bool warning and internal compiler error with MSVC. --- eth/main.cpp | 8 +++++++- libwebthree/WebThree.h | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index a9ea43f14..03be8b969 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -300,7 +300,13 @@ int main(int argc, char** argv) cout << credits(); NetworkPreferences netPrefs(listenPort, publicIP, upnp, useLocal); - dev::WebThreeDirect web3("Ethereum(++)/" + clientName + "v" + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), dbPath, false, mode == NodeMode::Full ? set{"eth", "shh"} : set{}, netPrefs); + dev::WebThreeDirect web3( + "Ethereum(++)/" + clientName + "v" + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), + dbPath, + false, + mode == NodeMode::Full ? set{"eth", "shh"} : set(), + netPrefs + ); web3.setIdealPeerCount(peers); eth::Client* c = mode == NodeMode::Full ? web3.ethereum() : nullptr; diff --git a/libwebthree/WebThree.h b/libwebthree/WebThree.h index 06717ee26..cae6fd6f8 100644 --- a/libwebthree/WebThree.h +++ b/libwebthree/WebThree.h @@ -93,7 +93,7 @@ public: void connect(std::string const& _seedHost, unsigned short _port = 30303); /// Is the network subsystem up? - bool haveNetwork() { return peerCount(); } + bool haveNetwork() { return peerCount() != 0; } /// Save peers dev::bytes savePeers(); From a23fea0917459494322c3077f4ff8a46cb53a67b Mon Sep 17 00:00:00 2001 From: Tim Hughes Date: Sat, 27 Sep 2014 13:23:02 +0100 Subject: [PATCH 011/641] Suppress warnings from boost mpl during moc compile. --- alethzero/MainWin.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index ce1a9b670..7aee0c376 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -21,6 +21,9 @@ #pragma once +#ifdef Q_MOC_RUN +#define BOOST_MPL_IF_HPP_INCLUDED +#endif #include #include From 6857416c09d783519798cb034048232be544df01 Mon Sep 17 00:00:00 2001 From: Tim Hughes Date: Sat, 27 Sep 2014 13:23:19 +0100 Subject: [PATCH 012/641] Update MSVC projects. --- libdevcore/_libdevcore.cpp | 2 ++ windows/Alethzero.vcxproj | 3 ++- windows/Alethzero.vcxproj.filters | 2 ++ windows/LibEthereum.vcxproj | 30 ++++++++++++++++++++++++++++- windows/LibEthereum.vcxproj.filters | 27 ++++++++++++++++++++++++++ 5 files changed, 62 insertions(+), 2 deletions(-) diff --git a/libdevcore/_libdevcore.cpp b/libdevcore/_libdevcore.cpp index 4160a7602..1b34a5911 100644 --- a/libdevcore/_libdevcore.cpp +++ b/libdevcore/_libdevcore.cpp @@ -6,5 +6,7 @@ #include "FixedHash.cpp" #include "Guards.cpp" #include "Log.cpp" +#include "RangeMask.cpp" #include "RLP.cpp" +#include "Worker.cpp" #endif diff --git a/windows/Alethzero.vcxproj b/windows/Alethzero.vcxproj index d418e5d03..38dbd6265 100644 --- a/windows/Alethzero.vcxproj +++ b/windows/Alethzero.vcxproj @@ -176,6 +176,7 @@ + @@ -307,4 +308,4 @@ - + \ No newline at end of file diff --git a/windows/Alethzero.vcxproj.filters b/windows/Alethzero.vcxproj.filters index e8f008522..ef47bdba0 100644 --- a/windows/Alethzero.vcxproj.filters +++ b/windows/Alethzero.vcxproj.filters @@ -11,6 +11,7 @@ + @@ -31,5 +32,6 @@ Windows + \ No newline at end of file diff --git a/windows/LibEthereum.vcxproj b/windows/LibEthereum.vcxproj index 134171843..db1362363 100644 --- a/windows/LibEthereum.vcxproj +++ b/windows/LibEthereum.vcxproj @@ -49,12 +49,24 @@ true true + + true + true + true + true + true true true true + + true + true + true + true + @@ -90,6 +102,7 @@ + @@ -159,6 +172,7 @@ true + true true @@ -223,6 +237,12 @@ true true + + true + true + true + true + true true @@ -235,6 +255,12 @@ true true + + true + true + true + true + @@ -289,6 +315,7 @@ + @@ -376,6 +403,7 @@ true true + true true @@ -527,4 +555,4 @@ - + \ No newline at end of file diff --git a/windows/LibEthereum.vcxproj.filters b/windows/LibEthereum.vcxproj.filters index b6e2dc070..848b8308d 100644 --- a/windows/LibEthereum.vcxproj.filters +++ b/windows/LibEthereum.vcxproj.filters @@ -178,6 +178,18 @@ libethereum + + libdevcore + + + libdevcore + + + libethereum + + + libwebthree + @@ -390,6 +402,18 @@ libethereum + + libdevcore + + + libdevcore + + + libethereum + + + libwebthree + @@ -422,5 +446,8 @@ {36748e80-c977-4fee-84e6-699c039dff87} + + {d838fece-fc20-42f6-bff5-97c236159b80} + \ No newline at end of file From c3b165684c6b437905a6fe3e6cd80a2c6233afd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zaw=C5=82ocki?= Date: Sat, 27 Sep 2014 14:58:50 +0200 Subject: [PATCH 013/641] evmcc's CMakeLists updated: * added std=c++14 for gcc (required for std::make_unique) * added required llvm libnames --- evmcc/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/evmcc/CMakeLists.txt b/evmcc/CMakeLists.txt index 550492583..82647ca02 100644 --- a/evmcc/CMakeLists.txt +++ b/evmcc/CMakeLists.txt @@ -22,6 +22,7 @@ if ("${TARGET_PLATFORM}" STREQUAL "w64") target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) elseif (UNIX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") else () find_package(Threads REQUIRED) target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) @@ -37,7 +38,7 @@ message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") include_directories(${LLVM_INCLUDE_DIRS}) add_definitions(${LLVM_DEFINITIONS}) -llvm_map_components_to_libnames(llvm_libs support core irreader) +llvm_map_components_to_libnames(llvm_libs core support mcjit x86asmparser x86codegen) target_link_libraries(evmcc ${llvm_libs}) # end of LLVM specific commands From 26a952cd1d367e33cda1abe193362367f01a2f28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 29 Sep 2014 14:39:17 +0200 Subject: [PATCH 014/641] Stack interface and implementation --- evmcc/Compiler.cpp | 23 +++---- evmcc/Stack.cpp | 118 ++++++++++++++++++++++++++++++---- evmcc/Stack.h | 26 ++++++++ windows/evmcc.vcxproj | 1 + windows/evmcc.vcxproj.filters | 1 + 5 files changed, 145 insertions(+), 24 deletions(-) create mode 100644 evmcc/Stack.h diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 7478dd683..4c3a8a5f2 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -3,6 +3,8 @@ #include +#include "Stack.h" + namespace evmcc { @@ -49,7 +51,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto stack2 = new GlobalVariable(*module, Types.word256arr, false, GlobalValue::LinkageTypes::PrivateLinkage, ConstantAggregateZero::get(Types.word256arr), "stack"); - auto stackTop = new GlobalVariable(*module, Types.size, false, + auto stackTop2 = new GlobalVariable(*module, Types.size, false, GlobalValue::LinkageTypes::PrivateLinkage, ConstantInt::get(Types.size, 0), "stackTop"); @@ -57,13 +59,6 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto mallocVal = Function::Create(FunctionType::get(Types.word8ptr, { Types.size }, false), GlobalValue::LinkageTypes::ExternalLinkage, "malloc", module.get()); - // Create stack_create declaration - auto stackCreate = Function::Create(FunctionType::get(Types.word8ptr, false), - GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_create", module.get()); - - auto stackPush = Function::Create(FunctionType::get(Types.Void, std::vector{ Types.word8ptr, Types.word256 }, false), - GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_push", module.get()); - // Create main function FunctionType* funcType = FunctionType::get(llvm::Type::getInt32Ty(context), false); Function* mainFunc = Function::Create(funcType, Function::ExternalLinkage, "main", module.get()); @@ -77,14 +72,20 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) builder.CreateStore(mallocMemCall, memory); builder.CreateStore(ConstantInt::get(Types.size, 100), memSize); - auto stack = builder.CreateCall(stackCreate, "stack"); + auto stack = Stack(builder, module.get()); uint64_t words[] = { 1, 2, 3, 4 }; auto val = llvm::APInt(256, 4, words); auto c = ConstantInt::get(Types.word256, val); - Value* args[] = { stack, c }; - builder.CreateCall(stackPush, args); + stack.push(c); + stack.push(ConstantInt::get(Types.word256, 0x1122334455667788)); + + auto top = stack.top(); + stack.push(top); // dup + + stack.pop(); + /* std::vector mallocStackArgs = { ConstantInt::get(sizeTy, 200) }; diff --git a/evmcc/Stack.cpp b/evmcc/Stack.cpp index e3faffd7e..d23456de6 100644 --- a/evmcc/Stack.cpp +++ b/evmcc/Stack.cpp @@ -1,8 +1,13 @@ +#include "Stack.h" + #include #include #include #include +#include + +#include #ifdef _MSC_VER #define EXPORT __declspec(dllexport) @@ -10,6 +15,9 @@ #define EXPORT #endif +namespace evmcc +{ + struct i256 { uint64_t a; @@ -17,30 +25,114 @@ struct i256 uint64_t c; uint64_t d; }; +static_assert(sizeof(i256) == 32, "Wrong i265 size"); + +using StackImpl = std::vector; + + +Stack::Stack(llvm::IRBuilder<>& _builder, llvm::Module* _module) + : m_builder(_builder) +{ + // TODO: Clean up LLVM types + auto stackPtrTy = m_builder.getInt8PtrTy(); + auto i256Ty = m_builder.getIntNTy(256); + auto i256PtrTy = i256Ty->getPointerTo(); + auto voidTy = m_builder.getVoidTy(); + + auto stackCreate = llvm::Function::Create(llvm::FunctionType::get(stackPtrTy, false), + llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_create", _module); + + llvm::Type* argsTypes[] = {stackPtrTy, i256PtrTy}; + auto funcType = llvm::FunctionType::get(voidTy, argsTypes, false); + m_stackPush = llvm::Function::Create(funcType, + llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_push", _module); -using Stack = std::vector; + m_stackTop = llvm::Function::Create(funcType, + llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_top", _module); + + m_stackPop = llvm::Function::Create(funcType, + llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_pop", _module); + + m_args[0] = m_builder.CreateCall(stackCreate, "stack.ptr"); + m_args[1] = m_builder.CreateAlloca(i256Ty, nullptr, "stack.val"); +} + + +void Stack::push(llvm::Value* _value) +{ + m_builder.CreateStore(_value, m_args[1]); // copy value to memory + m_builder.CreateCall(m_stackPush, m_args); +} + + +llvm::Value* Stack::top() +{ + m_builder.CreateCall(m_stackTop, m_args); + return m_builder.CreateLoad(m_args[1]); +} + + +llvm::Value* Stack::pop() +{ + m_builder.CreateCall(m_stackPop, m_args); + return m_builder.CreateLoad(m_args[1]); +} + + +void debugStack(const char* op, const i256& word) +{ + std::cerr << "STACK " << std::setw(4) << std::setfill(' ') << op << ": " + << std::dec << word.a + << " HEX: " << std::hex << std::setfill('0'); + if (word.b || word.c || word.d) + { + std::cerr << std::setw(16) << word.d << " " + << std::setw(16) << word.c << " " + << std::setw(16) << word.b << " "; + } + std::cerr << std::setw(16) << word.a << "\n"; +} + +} extern "C" { + using namespace evmcc; EXPORT void* evmccrt_stack_create() { - std::cerr << "STACK create: "; - auto stack = new Stack; - std::cerr << stack << "\n"; + auto stack = new StackImpl; + std::cerr << "STACK create\n"; return stack; } -EXPORT void evmccrt_stack_push(void* _stack, uint64_t _partA, uint64_t _partB, uint64_t _partC, uint64_t _partD) +EXPORT void evmccrt_stack_push(void* _stack, void* _pWord) +{ + auto stack = static_cast(_stack); + auto word = static_cast(_pWord); + debugStack("push", *word); + stack->push_back(*word); +} + +EXPORT void evmccrt_stack_top(void* _stack, void* _pWord) +{ + auto stack = static_cast(_stack); + assert(!stack->empty()); + auto word = &stack->back(); + debugStack("top", *word); + auto outWord = static_cast(_pWord); + *outWord = *word; +} + +EXPORT void evmccrt_stack_pop(void* _stack, void* _pWord) { - std::cerr << "STACK push: " << _partA << " (" << std::hex << std::setfill('0') - << std::setw(16) << _partD << " " - << std::setw(16) << _partC << " " - << std::setw(16) << _partB << " " - << std::setw(16) << _partA; - auto stack = static_cast(_stack); - stack->push_back({_partA, _partB, _partC, _partD}); - std::cerr << ")\n"; + auto stack = static_cast(_stack); + assert(!stack->empty()); + auto word = &stack->back(); + debugStack("pop", *word); + auto outWord = static_cast(_pWord); + stack->pop_back(); + *outWord = *word; } } // extern "C" diff --git a/evmcc/Stack.h b/evmcc/Stack.h new file mode 100644 index 000000000..e8b6a8e2d --- /dev/null +++ b/evmcc/Stack.h @@ -0,0 +1,26 @@ + +#pragma once + +#include + +namespace evmcc +{ + +class Stack +{ +public: + Stack(llvm::IRBuilder<>& _builder, llvm::Module* _module); + + void push(llvm::Value* _value); + llvm::Value* top(); + llvm::Value* pop(); + +private: + llvm::IRBuilder<>& m_builder; + llvm::Value* m_args[2]; + llvm::Function* m_stackPush; + llvm::Function* m_stackTop; + llvm::Function* m_stackPop; +}; + +} \ No newline at end of file diff --git a/windows/evmcc.vcxproj b/windows/evmcc.vcxproj index 82a7b4c56..3a1869cd5 100644 --- a/windows/evmcc.vcxproj +++ b/windows/evmcc.vcxproj @@ -27,6 +27,7 @@ + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D} diff --git a/windows/evmcc.vcxproj.filters b/windows/evmcc.vcxproj.filters index f4be3b7d4..7db055ebf 100644 --- a/windows/evmcc.vcxproj.filters +++ b/windows/evmcc.vcxproj.filters @@ -9,5 +9,6 @@ + \ No newline at end of file From 9051a2198ac8486ca3f22ca062332e6d32a5dc3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 29 Sep 2014 15:33:07 +0200 Subject: [PATCH 015/641] Output compilation (option -c) result to standard output by default --- evmcc/evmcc.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/evmcc/evmcc.cpp b/evmcc/evmcc.cpp index bdc3681db..222bcffb3 100644 --- a/evmcc/evmcc.cpp +++ b/evmcc/evmcc.cpp @@ -6,6 +6,8 @@ #include +#include + #include #include #include @@ -87,7 +89,9 @@ int main(int argc, char** argv) if (opt_compile) { - evmcc::Compiler().compile(bytecode)->dump(); + auto module = evmcc::Compiler().compile(bytecode); + llvm::raw_os_ostream out(std::cout); + module->print(out, nullptr); } if (opt_interpret) From a9bdd81d49afa84168157a0ca60f6067d68a7dd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 29 Sep 2014 17:17:39 +0200 Subject: [PATCH 016/641] PUSH instruction implementation --- evmcc/Compiler.cpp | 123 +++++++++++++++++++++-------------- evmcc/bytecode/push_test.evm | 1 + evmcc/lll/push_test.lll | 35 ++++++++++ 3 files changed, 110 insertions(+), 49 deletions(-) create mode 100644 evmcc/bytecode/push_test.evm create mode 100644 evmcc/lll/push_test.lll diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 4c3a8a5f2..854492ee3 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -3,6 +3,8 @@ #include +#include + #include "Stack.h" namespace evmcc @@ -37,64 +39,87 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) using namespace llvm; auto& context = getGlobalContext(); - auto module = std::make_unique("main", context); IRBuilder<> builder(context); - // Create globals for memory, memory size, stack and stack top - auto memory = new GlobalVariable(*module, Types.word8ptr, false, - GlobalValue::LinkageTypes::PrivateLinkage, - Constant::getNullValue(Types.word8ptr), "memory"); - auto memSize = new GlobalVariable(*module, Types.size, false, - GlobalValue::LinkageTypes::PrivateLinkage, - ConstantInt::get(Types.size, 0), "memsize"); - auto stack2 = new GlobalVariable(*module, Types.word256arr, false, - GlobalValue::LinkageTypes::PrivateLinkage, - ConstantAggregateZero::get(Types.word256arr), "stack"); - auto stackTop2 = new GlobalVariable(*module, Types.size, false, - GlobalValue::LinkageTypes::PrivateLinkage, - ConstantInt::get(Types.size, 0), "stackTop"); - - // Create value for void* malloc(size_t) - auto mallocVal = Function::Create(FunctionType::get(Types.word8ptr, { Types.size }, false), - GlobalValue::LinkageTypes::ExternalLinkage, "malloc", module.get()); - // Create main function - FunctionType* funcType = FunctionType::get(llvm::Type::getInt32Ty(context), false); - Function* mainFunc = Function::Create(funcType, Function::ExternalLinkage, "main", module.get()); + auto mainFuncType = FunctionType::get(llvm::Type::getInt32Ty(context), false); + auto mainFunc = Function::Create(mainFuncType, Function::ExternalLinkage, "main", module.get()); - BasicBlock* entryBlock = BasicBlock::Create(context, "entry", mainFunc); + auto entryBlock = BasicBlock::Create(context, "entry", mainFunc); builder.SetInsertPoint(entryBlock); - // Initialize memory with call to malloc, update memsize - std::vector mallocMemArgs = { ConstantInt::get(Types.size, 100) }; - auto mallocMemCall = builder.CreateCall(mallocVal, mallocMemArgs, "malloc_mem"); - builder.CreateStore(mallocMemCall, memory); - builder.CreateStore(ConstantInt::get(Types.size, 100), memSize); - + // Init stack auto stack = Stack(builder, module.get()); - uint64_t words[] = { 1, 2, 3, 4 }; - auto val = llvm::APInt(256, 4, words); - auto c = ConstantInt::get(Types.word256, val); - - stack.push(c); - stack.push(ConstantInt::get(Types.word256, 0x1122334455667788)); - - auto top = stack.top(); - stack.push(top); // dup - - stack.pop(); - - - /* - std::vector mallocStackArgs = { ConstantInt::get(sizeTy, 200) }; - auto mallocStackCall = builder.CreateCall(mallocVal, mallocStackArgs, "malloc_stack"); - auto mallocCast = builder.CreatePointerBitCastOrAddrSpaceCast(mallocStackCall, int256ptr); - builder.CreateStore(mallocCast, stackVal); - */ - - builder.CreateRet(ConstantInt::get(Type::getInt32Ty(context), 13)); + for (auto pc = bytecode.cbegin(); pc != bytecode.cend(); ++pc) + { + using dev::eth::Instruction; + + auto inst = static_cast(*pc); + switch (inst) + { + case Instruction::PUSH1: + case Instruction::PUSH2: + case Instruction::PUSH3: + case Instruction::PUSH4: + case Instruction::PUSH5: + case Instruction::PUSH6: + case Instruction::PUSH7: + case Instruction::PUSH8: + case Instruction::PUSH9: + case Instruction::PUSH10: + case Instruction::PUSH11: + case Instruction::PUSH12: + case Instruction::PUSH13: + case Instruction::PUSH14: + case Instruction::PUSH15: + case Instruction::PUSH16: + case Instruction::PUSH17: + case Instruction::PUSH18: + case Instruction::PUSH19: + case Instruction::PUSH20: + case Instruction::PUSH21: + case Instruction::PUSH22: + case Instruction::PUSH23: + case Instruction::PUSH24: + case Instruction::PUSH25: + case Instruction::PUSH26: + case Instruction::PUSH27: + case Instruction::PUSH28: + case Instruction::PUSH29: + case Instruction::PUSH30: + case Instruction::PUSH31: + case Instruction::PUSH32: + { + auto numBytes = static_cast(inst) - static_cast(Instruction::PUSH1) + 1; + auto value = llvm::APInt(256, 0); + for (decltype(numBytes) i = 0; i < numBytes; ++i) // TODO: Use pc as iterator + { + ++pc; + value <<= 8; + value |= *pc; + } + auto c = builder.getInt(value); + stack.push(c); + break; + } + } + } + + //uint64_t words[] = { 1, 2, 3, 4 }; + //auto val = llvm::APInt(256, 4, words); + //auto c = ConstantInt::get(Types.word256, val); + + //stack.push(c); + //stack.push(ConstantInt::get(Types.word256, 0x1122334455667788)); + + //auto top = stack.top(); + //stack.push(top); // dup + + //stack.pop(); + + builder.CreateRet(ConstantInt::get(Type::getInt32Ty(context), 0)); return module; } diff --git a/evmcc/bytecode/push_test.evm b/evmcc/bytecode/push_test.evm new file mode 100644 index 000000000..d624cee1d --- /dev/null +++ b/evmcc/bytecode/push_test.evm @@ -0,0 +1 @@ +60656107d26204a0c763026921f4640bc5588eb165372d0f1dca6e661ba1d901961c71670c55f7bc23038e3868056bc75e2d630fffff69021e19e0c9bab24000016a085d1c6e8050f0ea1c71bd6b0688be36543f3c36e638e37a6c03d41f73d55d0d482ae55555376dc76810d0fe03c91964d31c71c6f46e615dd0360c07d931663b14e38e38b16f2da3f99955a3adcf27ebb1caaaaaaa6e7014ccba6a8bb1ed35bd86bf065c71c71c2b7109491c5d4781b79c9009de6bfb8e38e38de8720414a0f6fdec81304d4c563e740bffffffffa573118427b3b4a05bc8a8a4de8459868000000000017406eb15e7331e727940d4ac54b7cdca1c71c71c71bd750567a91c9fefc96ebaa626a22f98c5e638e38e38e37a76032abd16c5b68006e15d5aa307e383f4e55555555555377701a6427bdc4f0d58eab5f48a3ec67f64e21c71c71c71c6f478080dd0a0c9b9ff2c2a0c740b06853a0a980ee38e38e38e38b17903c679cb5e8f2f9cb3b5d6652b0e7334f746faaaaaaaaaaaaa6e7a01b873815917ebb2bf3b890a1af495d6235bae3c71c71c71c71c2b7b07ae4cca96e1a55dfa49c85ad3c3e60e426b92fb8e38e38e38e38de87c036018bf074e292bcc7d6c8bea0f9699443046178bffffffffffffffa57d0e7d34c64a9c85d4460dbbca87196b61618a4bd2168000000000000000017e05b901f48a5b994d6572502bc4ea43140486666416aa1c71c71c71c71c71bd7f047889870c178fc477414ea231d70467a388fffe31b4e638e38e38e38e38e37a diff --git a/evmcc/lll/push_test.lll b/evmcc/lll/push_test.lll new file mode 100644 index 000000000..832daaec1 --- /dev/null +++ b/evmcc/lll/push_test.lll @@ -0,0 +1,35 @@ + +(asm +101 ;; PUSH1 +2002 ;; PUSH2 +303303 ;; PUSH3 +40444404 ;; PUSH4 +50555555505 ;; PUSH5 +60666666666606 +7777777777777777 +888888888888888888 +99999999999999999999 +10000000000000000000001 +10111111111111111111111101 +2022222222222222222222222202 +303333333333333333333333333303 +4044444444444444444444444444444404 +505555555555555555555555555555555505 +60666666666666666666666666666666666606 +7077777777777777777777777777777777777707 +808888888888888888888888888888888888888808 +90999999999999999999999999999999999999999909 +100000000000000000000000000000000000000000000001 +10111111111111111111111111111111111111111111111101 +2022222222222222222222222222222222222222222222222202 +303333333333333333333333333333333333333333333333333303 +40444444444444444444444444444444444444444444444444444404 +50555555555555555555555555555555555555555555555555555555505 +6066666666666666666666666666666666666666666666666666666666606 +707777777777777777777777777777777777777777777777777777777777707 +808888888888888888888888888888888888888888888888888888888888888808 +90999999999999999999999999999999999999999999999999999999999999999909 +100000000000000000000000000000000000000000000000000000000000000000000001 +10111111111111111111111111111111111111111111111111111111111111111111111101 +2022222222222222222222222222222222222222222222222222222222222222222222222202 ;; PUSH32 +) \ No newline at end of file From 646f954ac6985d22d37eceb37a4b139cfd868309 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 30 Sep 2014 09:32:53 +0200 Subject: [PATCH 017/641] POP and DUP* instructions --- evmcc/Compiler.cpp | 42 +++++++++++++++++++++++++---------- evmcc/Stack.cpp | 37 ++++++++++++++++++------------ evmcc/Stack.h | 5 +++-- evmcc/bytecode/stack_test.evm | 1 + evmcc/lll/stack_test.lll | 22 ++++++++++++++++++ 5 files changed, 79 insertions(+), 28 deletions(-) create mode 100644 evmcc/bytecode/stack_test.evm create mode 100644 evmcc/lll/stack_test.lll diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 854492ee3..454c61450 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -59,6 +59,12 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto inst = static_cast(*pc); switch (inst) { + case Instruction::POP: + { + stack.pop(); + break; + } + case Instruction::PUSH1: case Instruction::PUSH2: case Instruction::PUSH3: @@ -104,20 +110,32 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) stack.push(c); break; } - } - } - - //uint64_t words[] = { 1, 2, 3, 4 }; - //auto val = llvm::APInt(256, 4, words); - //auto c = ConstantInt::get(Types.word256, val); - //stack.push(c); - //stack.push(ConstantInt::get(Types.word256, 0x1122334455667788)); - - //auto top = stack.top(); - //stack.push(top); // dup + case Instruction::DUP1: + case Instruction::DUP2: + case Instruction::DUP3: + case Instruction::DUP4: + case Instruction::DUP5: + case Instruction::DUP6: + case Instruction::DUP7: + case Instruction::DUP8: + case Instruction::DUP9: + case Instruction::DUP10: + case Instruction::DUP11: + case Instruction::DUP12: + case Instruction::DUP13: + case Instruction::DUP14: + case Instruction::DUP15: + case Instruction::DUP16: + { + auto index = static_cast(inst) - static_cast(Instruction::DUP1); + auto value = stack.get(index); + stack.push(value); + break; + } - //stack.pop(); + } + } builder.CreateRet(ConstantInt::get(Type::getInt32Ty(context), 0)); diff --git a/evmcc/Stack.cpp b/evmcc/Stack.cpp index d23456de6..4c5a19e8a 100644 --- a/evmcc/Stack.cpp +++ b/evmcc/Stack.cpp @@ -47,12 +47,14 @@ Stack::Stack(llvm::IRBuilder<>& _builder, llvm::Module* _module) m_stackPush = llvm::Function::Create(funcType, llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_push", _module); - m_stackTop = llvm::Function::Create(funcType, - llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_top", _module); - m_stackPop = llvm::Function::Create(funcType, llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_pop", _module); + llvm::Type* getArgsTypes[] = {stackPtrTy, m_builder.getInt32Ty(), i256PtrTy}; + auto getFuncType = llvm::FunctionType::get(voidTy, getArgsTypes); + m_stackGet = llvm::Function::Create(getFuncType, + llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_get", _module); + m_args[0] = m_builder.CreateCall(stackCreate, "stack.ptr"); m_args[1] = m_builder.CreateAlloca(i256Ty, nullptr, "stack.val"); } @@ -65,20 +67,27 @@ void Stack::push(llvm::Value* _value) } -llvm::Value* Stack::top() +llvm::Value* Stack::pop() { - m_builder.CreateCall(m_stackTop, m_args); + m_builder.CreateCall(m_stackPop, m_args); return m_builder.CreateLoad(m_args[1]); } -llvm::Value* Stack::pop() +llvm::Value* Stack::get(uint32_t _index) { - m_builder.CreateCall(m_stackPop, m_args); + llvm::Value* args[] = {m_args[0], m_builder.getInt32(_index), m_args[1]}; + m_builder.CreateCall(m_stackGet, args); return m_builder.CreateLoad(m_args[1]); } +llvm::Value* Stack::top() +{ + return get(0); +} + + void debugStack(const char* op, const i256& word) { std::cerr << "STACK " << std::setw(4) << std::setfill(' ') << op << ": " @@ -114,24 +123,24 @@ EXPORT void evmccrt_stack_push(void* _stack, void* _pWord) stack->push_back(*word); } -EXPORT void evmccrt_stack_top(void* _stack, void* _pWord) +EXPORT void evmccrt_stack_pop(void* _stack, void* _pWord) { auto stack = static_cast(_stack); assert(!stack->empty()); auto word = &stack->back(); - debugStack("top", *word); + debugStack("pop", *word); auto outWord = static_cast(_pWord); + stack->pop_back(); *outWord = *word; } -EXPORT void evmccrt_stack_pop(void* _stack, void* _pWord) +EXPORT void evmccrt_stack_get(void* _stack, uint32_t _index, void* _pWord) { auto stack = static_cast(_stack); - assert(!stack->empty()); - auto word = &stack->back(); - debugStack("pop", *word); + assert(_index < stack->size()); + auto word = &(*stack)[stack->size() - _index - 1]; + debugStack("get", *word); auto outWord = static_cast(_pWord); - stack->pop_back(); *outWord = *word; } diff --git a/evmcc/Stack.h b/evmcc/Stack.h index e8b6a8e2d..e4d93bd8c 100644 --- a/evmcc/Stack.h +++ b/evmcc/Stack.h @@ -12,15 +12,16 @@ public: Stack(llvm::IRBuilder<>& _builder, llvm::Module* _module); void push(llvm::Value* _value); - llvm::Value* top(); llvm::Value* pop(); + llvm::Value* top(); + llvm::Value* get(uint32_t _index); private: llvm::IRBuilder<>& m_builder; llvm::Value* m_args[2]; llvm::Function* m_stackPush; - llvm::Function* m_stackTop; llvm::Function* m_stackPop; + llvm::Function* m_stackGet; }; } \ No newline at end of file diff --git a/evmcc/bytecode/stack_test.evm b/evmcc/bytecode/stack_test.evm new file mode 100644 index 000000000..6eba9fdca --- /dev/null +++ b/evmcc/bytecode/stack_test.evm @@ -0,0 +1 @@ +65372d0f1dca6e661925338e3e5c2b808280848184505050505050506104576108ae8182 diff --git a/evmcc/lll/stack_test.lll b/evmcc/lll/stack_test.lll new file mode 100644 index 000000000..0edf06624 --- /dev/null +++ b/evmcc/lll/stack_test.lll @@ -0,0 +1,22 @@ + +(asm +60666666666606 +7077777777777707 +DUP1 +DUP3 +DUP1 +DUP5 +DUP2 +DUP5 +POP +POP +POP +POP +POP +POP +POP +1111 +2222 +DUP2 +DUP3 +) \ No newline at end of file From 2eabdb0ceda6891ca2dad79801461f22570562a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 30 Sep 2014 10:05:43 +0200 Subject: [PATCH 018/641] SWAP* instructions --- evmcc/Compiler.cpp | 25 ++++++++++++++++++++ evmcc/Stack.cpp | 43 ++++++++++++++++++++++++++--------- evmcc/Stack.h | 2 ++ evmcc/bytecode/stack_test.evm | 2 +- evmcc/lll/stack_test.lll | 4 +++- 5 files changed, 63 insertions(+), 13 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 454c61450..0b1793244 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -134,6 +134,31 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::SWAP1: + case Instruction::SWAP2: + case Instruction::SWAP3: + case Instruction::SWAP4: + case Instruction::SWAP5: + case Instruction::SWAP6: + case Instruction::SWAP7: + case Instruction::SWAP8: + case Instruction::SWAP9: + case Instruction::SWAP10: + case Instruction::SWAP11: + case Instruction::SWAP12: + case Instruction::SWAP13: + case Instruction::SWAP14: + case Instruction::SWAP15: + case Instruction::SWAP16: + { + auto index = static_cast(inst) - static_cast(Instruction::SWAP1) + 1; + auto loValue = stack.get(index); + auto hiValue = stack.get(0); + stack.set(index, hiValue); + stack.set(0, loValue); + break; + } + } } diff --git a/evmcc/Stack.cpp b/evmcc/Stack.cpp index 4c5a19e8a..f0af2087a 100644 --- a/evmcc/Stack.cpp +++ b/evmcc/Stack.cpp @@ -55,6 +55,9 @@ Stack::Stack(llvm::IRBuilder<>& _builder, llvm::Module* _module) m_stackGet = llvm::Function::Create(getFuncType, llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_get", _module); + m_stackSet = llvm::Function::Create(getFuncType, + llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_set", _module); + m_args[0] = m_builder.CreateCall(stackCreate, "stack.ptr"); m_args[1] = m_builder.CreateAlloca(i256Ty, nullptr, "stack.val"); } @@ -82,24 +85,33 @@ llvm::Value* Stack::get(uint32_t _index) } +void Stack::set(uint32_t _index, llvm::Value* _value) +{ + m_builder.CreateStore(_value, m_args[1]); // copy value to memory + llvm::Value* args[] = {m_args[0], m_builder.getInt32(_index), m_args[1]}; + m_builder.CreateCall(m_stackSet, args); +} + + llvm::Value* Stack::top() { return get(0); } -void debugStack(const char* op, const i256& word) +void debugStack(const char* _op, const i256& _word, uint32_t _index = 0) { - std::cerr << "STACK " << std::setw(4) << std::setfill(' ') << op << ": " - << std::dec << word.a - << " HEX: " << std::hex << std::setfill('0'); - if (word.b || word.c || word.d) + std::cerr << "STACK " << std::setw(4) << std::setfill(' ') << _op + << " [" << std::setw(2) << std::setfill('0') << _index << "] " + << std::dec << _word.a + << " HEX: " << std::hex; + if (_word.b || _word.c || _word.d) { - std::cerr << std::setw(16) << word.d << " " - << std::setw(16) << word.c << " " - << std::setw(16) << word.b << " "; + std::cerr << std::setw(16) << _word.d << " " + << std::setw(16) << _word.c << " " + << std::setw(16) << _word.b << " "; } - std::cerr << std::setw(16) << word.a << "\n"; + std::cerr << std::setw(16) << _word.a << "\n"; } } @@ -138,10 +150,19 @@ EXPORT void evmccrt_stack_get(void* _stack, uint32_t _index, void* _pWord) { auto stack = static_cast(_stack); assert(_index < stack->size()); - auto word = &(*stack)[stack->size() - _index - 1]; - debugStack("get", *word); + auto word = stack->rbegin() + _index; + debugStack("get", *word, _index); auto outWord = static_cast(_pWord); *outWord = *word; } +EXPORT void evmccrt_stack_set(void* _stack, uint32_t _index, void* _pWord) +{ + auto stack = static_cast(_stack); + auto word = static_cast(_pWord); + assert(_index < stack->size()); + *(stack->rbegin() + _index) = *word; + debugStack("set", *word, _index); +} + } // extern "C" diff --git a/evmcc/Stack.h b/evmcc/Stack.h index e4d93bd8c..a25de56e6 100644 --- a/evmcc/Stack.h +++ b/evmcc/Stack.h @@ -15,6 +15,7 @@ public: llvm::Value* pop(); llvm::Value* top(); llvm::Value* get(uint32_t _index); + void set(uint32_t _index, llvm::Value* _value); private: llvm::IRBuilder<>& m_builder; @@ -22,6 +23,7 @@ private: llvm::Function* m_stackPush; llvm::Function* m_stackPop; llvm::Function* m_stackGet; + llvm::Function* m_stackSet; }; } \ No newline at end of file diff --git a/evmcc/bytecode/stack_test.evm b/evmcc/bytecode/stack_test.evm index 6eba9fdca..02417c967 100644 --- a/evmcc/bytecode/stack_test.evm +++ b/evmcc/bytecode/stack_test.evm @@ -1 +1 @@ -65372d0f1dca6e661925338e3e5c2b808280848184505050505050506104576108ae8182 +65372d0f1dca6e661925338e3e5c2b808280848184505050505050506104576108ae81819290 diff --git a/evmcc/lll/stack_test.lll b/evmcc/lll/stack_test.lll index 0edf06624..e6581563c 100644 --- a/evmcc/lll/stack_test.lll +++ b/evmcc/lll/stack_test.lll @@ -18,5 +18,7 @@ POP 1111 2222 DUP2 -DUP3 +DUP2 +SWAP3 +SWAP1 ) \ No newline at end of file From 4ec1ebc82cc5d3c63fe29489e9f0ffc56fd84701 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 30 Sep 2014 11:26:58 +0200 Subject: [PATCH 019/641] Basic arithmetic, limited precision for MUL, DIV and MOD. --- evmcc/Compiler.cpp | 83 ++++++++++++++++++++++++++++++ evmcc/bytecode/arithmetic_test.evm | 1 + evmcc/bytecode/fib1.evm | 1 + evmcc/lll/arithmetic_test.lll | 29 +++++++++++ evmcc/lll/fib1.lll | 57 ++++++++++++++++++++ 5 files changed, 171 insertions(+) create mode 100644 evmcc/bytecode/arithmetic_test.evm create mode 100644 evmcc/bytecode/fib1.evm create mode 100644 evmcc/lll/arithmetic_test.lll create mode 100644 evmcc/lll/fib1.lll diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 0b1793244..3cd12833f 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -19,6 +19,7 @@ struct llvm::Type* word256arr; llvm::Type* size; llvm::Type* Void; + llvm::Type* WordLowPrecision; } Types; Compiler::Compiler() @@ -31,6 +32,9 @@ Compiler::Compiler() Types.word256arr = llvm::ArrayType::get(Types.word256, 100); Types.size = llvm::Type::getInt64Ty(context); Types.Void = llvm::Type::getVoidTy(context); + + // TODO: Use 64-bit for now. In 128-bit compiler-rt library functions are required + Types.WordLowPrecision = llvm::Type::getIntNTy(context, 64); } @@ -59,6 +63,85 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto inst = static_cast(*pc); switch (inst) { + + case Instruction::ADD: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto result = builder.CreateAdd(lhs, rhs); + stack.push(result); + break; + } + + case Instruction::SUB: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto result = builder.CreateSub(lhs, rhs); + stack.push(result); + break; + } + + case Instruction::MUL: + { + auto lhs256 = stack.pop(); + auto rhs256 = stack.pop(); + auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); + auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); + auto res128 = builder.CreateMul(lhs128, rhs128); + auto res256 = builder.CreateZExt(res128, Types.word256); + stack.push(res256); + break; + } + + case Instruction::DIV: + { + auto lhs256 = stack.pop(); + auto rhs256 = stack.pop(); + auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); + auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); + auto res128 = builder.CreateUDiv(lhs128, rhs128); + auto res256 = builder.CreateZExt(res128, Types.word256); + stack.push(res256); + break; + } + + case Instruction::SDIV: + { + auto lhs256 = stack.pop(); + auto rhs256 = stack.pop(); + auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); + auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); + auto res128 = builder.CreateSDiv(lhs128, rhs128); + auto res256 = builder.CreateSExt(res128, Types.word256); + stack.push(res256); + break; + } + + case Instruction::MOD: + { + auto lhs256 = stack.pop(); + auto rhs256 = stack.pop(); + auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); + auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); + auto res128 = builder.CreateURem(lhs128, rhs128); + auto res256 = builder.CreateZExt(res128, Types.word256); + stack.push(res256); + break; + } + + case Instruction::SMOD: + { + auto lhs256 = stack.pop(); + auto rhs256 = stack.pop(); + auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); + auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); + auto res128 = builder.CreateSRem(lhs128, rhs128); + auto res256 = builder.CreateSExt(res128, Types.word256); + stack.push(res256); + break; + } + case Instruction::POP: { stack.pop(); diff --git a/evmcc/bytecode/arithmetic_test.evm b/evmcc/bytecode/arithmetic_test.evm new file mode 100644 index 000000000..67e86b310 --- /dev/null +++ b/evmcc/bytecode/arithmetic_test.evm @@ -0,0 +1 @@ +60016001900160070260050160029004600490066021900560150160030260059007600303 diff --git a/evmcc/bytecode/fib1.evm b/evmcc/bytecode/fib1.evm new file mode 100644 index 000000000..4c141314e --- /dev/null +++ b/evmcc/bytecode/fib1.evm @@ -0,0 +1 @@ +60016001818101818101818101818101818101818101818101818101818101818101818101818101818101818101818101818101818101 diff --git a/evmcc/lll/arithmetic_test.lll b/evmcc/lll/arithmetic_test.lll new file mode 100644 index 000000000..e2c14d4c7 --- /dev/null +++ b/evmcc/lll/arithmetic_test.lll @@ -0,0 +1,29 @@ + +(asm +1 +1 +SWAP1 +ADD ;; 2 +7 +MUL ;; 14 +5 +ADD ;; 19 +2 +SWAP1 +DIV ;; 9 +4 +SWAP1 +MOD ;; 1 +33 +SWAP1 +SDIV;; 0 +21 +ADD ;; 21 +3 +MUL ;; 63 +5 +SWAP1 +SMOD;; 3 +3 +SUB ;; 0 +) \ No newline at end of file diff --git a/evmcc/lll/fib1.lll b/evmcc/lll/fib1.lll new file mode 100644 index 000000000..286bed275 --- /dev/null +++ b/evmcc/lll/fib1.lll @@ -0,0 +1,57 @@ +;; Fibbonacci unrolled + +(asm +1 +1 +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +) \ No newline at end of file From 72bb2d3e0cdbfb0aed369c1f022496992e66ab6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 30 Sep 2014 11:27:53 +0200 Subject: [PATCH 020/641] Fix stack set/get bad function signature --- evmcc/Stack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evmcc/Stack.cpp b/evmcc/Stack.cpp index f0af2087a..aa02a846e 100644 --- a/evmcc/Stack.cpp +++ b/evmcc/Stack.cpp @@ -51,7 +51,7 @@ Stack::Stack(llvm::IRBuilder<>& _builder, llvm::Module* _module) llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_pop", _module); llvm::Type* getArgsTypes[] = {stackPtrTy, m_builder.getInt32Ty(), i256PtrTy}; - auto getFuncType = llvm::FunctionType::get(voidTy, getArgsTypes); + auto getFuncType = llvm::FunctionType::get(voidTy, getArgsTypes, false); m_stackGet = llvm::Function::Create(getFuncType, llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_get", _module); From 6eab61a1aed3c03b2f5b9a157e25f64ed814aadc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 30 Sep 2014 17:11:50 +0200 Subject: [PATCH 021/641] Starting ExtVM binary interface --- evmcc/Compiler.cpp | 3 ++ evmcc/ExecutionEngine.cpp | 5 ++++ evmcc/Ext.cpp | 52 +++++++++++++++++++++++++++++++++++ evmcc/Ext.h | 22 +++++++++++++++ windows/evmcc.vcxproj | 6 ++-- windows/evmcc.vcxproj.filters | 2 ++ 6 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 evmcc/Ext.cpp create mode 100644 evmcc/Ext.h diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 3cd12833f..4237b59aa 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -6,6 +6,7 @@ #include #include "Stack.h" +#include "Ext.h" namespace evmcc { @@ -56,6 +57,8 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) // Init stack auto stack = Stack(builder, module.get()); + auto ext = Ext(builder); + for (auto pc = bytecode.cbegin(); pc != bytecode.cend(); ++pc) { using dev::eth::Instruction; diff --git a/evmcc/ExecutionEngine.cpp b/evmcc/ExecutionEngine.cpp index e59d6024a..3b3205af4 100644 --- a/evmcc/ExecutionEngine.cpp +++ b/evmcc/ExecutionEngine.cpp @@ -13,6 +13,8 @@ #include #include +#include "Ext.h" + namespace evmcc { @@ -66,6 +68,9 @@ int ExecutionEngine::run(std::unique_ptr _module) _module.release(); // Successfully created llvm::ExecutionEngine takes ownership of the module exec->finalizeObject(); + auto ext = std::make_unique(); + Ext::init(std::move(ext)); + auto entryFunc = module->getFunction("main"); if (!entryFunc) { diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp new file mode 100644 index 000000000..1384694be --- /dev/null +++ b/evmcc/Ext.cpp @@ -0,0 +1,52 @@ + +#include "Ext.h" + +#include +#include + +#ifdef _MSC_VER +#define EXPORT __declspec(dllexport) +#else +#define EXPORT +#endif + +using namespace llvm; +using llvm::types::i; +using Linkage = llvm::GlobalValue::LinkageTypes; + +namespace evmcc +{ + +std::unique_ptr g_ext; + +void Ext::init(std::unique_ptr _ext) +{ + g_ext = std::move(_ext); +} + +Ext::Ext(llvm::IRBuilder<>& _builder) + : m_builder(_builder) +{ + auto module = m_builder.GetInsertBlock()->getParent()->getParent(); + auto&& ctx = _builder.getContext(); + + Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_store", module); + Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_setStore", module); +} + +extern "C" +{ + +EXPORT void ext_store(void* _index, void* _value) +{ + +} + +EXPORT void ext_setStore(void* _index, void* _value) +{ + +} + +} + +} \ No newline at end of file diff --git a/evmcc/Ext.h b/evmcc/Ext.h new file mode 100644 index 000000000..f1c88d849 --- /dev/null +++ b/evmcc/Ext.h @@ -0,0 +1,22 @@ + +#include + +#include + +namespace evmcc +{ + + + +class Ext +{ +public: + Ext(llvm::IRBuilder<>& _builder); + static void init(std::unique_ptr _ext); + +private: + llvm::IRBuilder<>& m_builder; +}; + + +} \ No newline at end of file diff --git a/windows/evmcc.vcxproj b/windows/evmcc.vcxproj index 3a1869cd5..d10235ee3 100644 --- a/windows/evmcc.vcxproj +++ b/windows/evmcc.vcxproj @@ -22,11 +22,13 @@ + + @@ -136,8 +138,8 @@ Console true - ../../builds/llvm3.5/Debug/lib;../../_build/LibEthereum/x64_Debug;%(AdditionalLibraryDirectories) - LibEthereum.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) + ../../builds/llvm3.5/Debug/lib;../../_build/LibEthereum/x64_Debug;../../_build/LibSecp256k1/x64_Debug;../../_build/LibCryptoPP/x64_Debug;%(AdditionalLibraryDirectories) + LibEthereum.lib;LibSecp256k1.lib;LibCryptoPP.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) diff --git a/windows/evmcc.vcxproj.filters b/windows/evmcc.vcxproj.filters index 7db055ebf..7b0ee824a 100644 --- a/windows/evmcc.vcxproj.filters +++ b/windows/evmcc.vcxproj.filters @@ -5,10 +5,12 @@ + + \ No newline at end of file From 8a63213b6ba0c19492790b21ee655f1038dd6f0c Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Tue, 30 Sep 2014 21:32:21 +0100 Subject: [PATCH 022/641] initial implementation of memory --- evmcc/Compiler.cpp | 42 ++++--------- evmcc/Compiler.h | 2 +- evmcc/Memory.cpp | 145 +++++++++++++++++++++++++++++++++++++++++++++ evmcc/Memory.h | 26 ++++++++ 4 files changed, 182 insertions(+), 33 deletions(-) create mode 100644 evmcc/Memory.cpp create mode 100644 evmcc/Memory.h diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 4c3a8a5f2..1114bde52 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -3,6 +3,7 @@ #include +#include "Memory.h" #include "Stack.h" namespace evmcc @@ -41,24 +42,6 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto module = std::make_unique("main", context); IRBuilder<> builder(context); - // Create globals for memory, memory size, stack and stack top - auto memory = new GlobalVariable(*module, Types.word8ptr, false, - GlobalValue::LinkageTypes::PrivateLinkage, - Constant::getNullValue(Types.word8ptr), "memory"); - auto memSize = new GlobalVariable(*module, Types.size, false, - GlobalValue::LinkageTypes::PrivateLinkage, - ConstantInt::get(Types.size, 0), "memsize"); - auto stack2 = new GlobalVariable(*module, Types.word256arr, false, - GlobalValue::LinkageTypes::PrivateLinkage, - ConstantAggregateZero::get(Types.word256arr), "stack"); - auto stackTop2 = new GlobalVariable(*module, Types.size, false, - GlobalValue::LinkageTypes::PrivateLinkage, - ConstantInt::get(Types.size, 0), "stackTop"); - - // Create value for void* malloc(size_t) - auto mallocVal = Function::Create(FunctionType::get(Types.word8ptr, { Types.size }, false), - GlobalValue::LinkageTypes::ExternalLinkage, "malloc", module.get()); - // Create main function FunctionType* funcType = FunctionType::get(llvm::Type::getInt32Ty(context), false); Function* mainFunc = Function::Create(funcType, Function::ExternalLinkage, "main", module.get()); @@ -66,13 +49,9 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) BasicBlock* entryBlock = BasicBlock::Create(context, "entry", mainFunc); builder.SetInsertPoint(entryBlock); - // Initialize memory with call to malloc, update memsize - std::vector mallocMemArgs = { ConstantInt::get(Types.size, 100) }; - auto mallocMemCall = builder.CreateCall(mallocVal, mallocMemArgs, "malloc_mem"); - builder.CreateStore(mallocMemCall, memory); - builder.CreateStore(ConstantInt::get(Types.size, 100), memSize); auto stack = Stack(builder, module.get()); + auto memory = Memory(builder, module.get()); uint64_t words[] = { 1, 2, 3, 4 }; auto val = llvm::APInt(256, 4, words); @@ -83,20 +62,19 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto top = stack.top(); stack.push(top); // dup - stack.pop(); + auto index = ConstantInt::get(Types.word256, 123); + memory.storeWord(index, c); - /* - std::vector mallocStackArgs = { ConstantInt::get(sizeTy, 200) }; - auto mallocStackCall = builder.CreateCall(mallocVal, mallocStackArgs, "malloc_stack"); - auto mallocCast = builder.CreatePointerBitCastOrAddrSpaceCast(mallocStackCall, int256ptr); - builder.CreateStore(mallocCast, stackVal); - */ + memory.dump(123, 123+32); - builder.CreateRet(ConstantInt::get(Type::getInt32Ty(context), 13)); + auto index2 = ConstantInt::get(Types.word256, 123 + 16); + auto byte = memory.loadByte(index2); + auto result = builder.CreateZExt(byte, builder.getInt32Ty()); + builder.CreateRet(result); // should return 3 return module; } -} \ No newline at end of file +} diff --git a/evmcc/Compiler.h b/evmcc/Compiler.h index ae7033ac0..5a07e685d 100644 --- a/evmcc/Compiler.h +++ b/evmcc/Compiler.h @@ -18,4 +18,4 @@ public: }; -} \ No newline at end of file +} diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp new file mode 100644 index 000000000..9e3c2942e --- /dev/null +++ b/evmcc/Memory.cpp @@ -0,0 +1,145 @@ +#include "Memory.h" + +#include +#include +#include +#include +#include + +#include + +#include + +#ifdef _MSC_VER + #define EXPORT __declspec(dllexport) +#else + #define EXPORT +#endif + +namespace evmcc +{ + +struct i256 +{ + uint64_t a; + uint64_t b; + uint64_t c; + uint64_t d; +}; +static_assert(sizeof(i256) == 32, "Wrong i256 size"); + +using MemoryImpl = dev::bytes; + + +Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module) + : m_builder(_builder) +{ + auto memoryCreate = llvm::Function::Create(llvm::FunctionType::get(m_builder.getVoidTy(), false), + llvm::GlobalValue::LinkageTypes::ExternalLinkage, + "evmccrt_memory_create", _module); + m_builder.CreateCall(memoryCreate); + + + auto memRequireTy = llvm::FunctionType::get(m_builder.getInt8PtrTy(), m_builder.getInt64Ty(), false); + m_memRequire = llvm::Function::Create(memRequireTy, + llvm::GlobalValue::LinkageTypes::ExternalLinkage, + "evmccrt_memory_require", _module); + + auto i64Ty = m_builder.getInt64Ty(); + std::vector argTypes = {i64Ty, i64Ty}; + auto dumpTy = llvm::FunctionType::get(m_builder.getVoidTy(), llvm::ArrayRef(argTypes), false); + m_memDump = llvm::Function::Create(dumpTy, llvm::GlobalValue::LinkageTypes::ExternalLinkage, + "evmccrt_memory_dump", _module); +} + + +llvm::Value* Memory::loadByte(llvm::Value* _addr) +{ + // trunc _addr (an i256) to i64 index and use it to index the memory + auto index = m_builder.CreateTrunc(_addr, m_builder.getInt64Ty(), "index"); + + // load from evmccrt_memory_require()[index] + auto base = m_builder.CreateCall(m_memRequire, index, "base"); + auto ptr = m_builder.CreateGEP(base, index, "ptr"); + auto byte = m_builder.CreateLoad(ptr, "byte"); + return byte; +} + +void Memory::storeWord(llvm::Value* _addr, llvm::Value* _word) +{ + auto index = m_builder.CreateTrunc(_addr, m_builder.getInt64Ty(), "index"); + auto index32 = m_builder.CreateAdd(index, llvm::ConstantInt::get(m_builder.getInt64Ty(), 32), "index32"); + + auto base = m_builder.CreateCall(m_memRequire, index32, "base"); + auto ptr = m_builder.CreateGEP(base, index, "ptr"); + + auto i256ptrTy = m_builder.getIntNTy(256)->getPointerTo(); + auto wordPtr = m_builder.CreateBitCast(ptr, i256ptrTy, "wordptr"); + m_builder.CreateStore(_word, wordPtr); +} + +void Memory::storeByte(llvm::Value* _addr, llvm::Value* _byte) +{ + auto index = m_builder.CreateTrunc(_addr, m_builder.getInt64Ty(), "index"); + + auto base = m_builder.CreateCall(m_memRequire, index, "base"); + auto ptr = m_builder.CreateGEP(base, index, "ptr"); + m_builder.CreateStore(_byte, ptr); +} + +void Memory::dump(uint64_t _begin, uint64_t _end) +{ + auto beginVal = llvm::ConstantInt::get(m_builder.getInt64Ty(), _begin); + auto endVal = llvm::ConstantInt::get(m_builder.getInt64Ty(), _end); + + std::vector args = {beginVal, endVal}; + m_builder.CreateCall(m_memDump, llvm::ArrayRef(args)); +} + +} // namespace evmcc + +extern "C" +{ + using namespace evmcc; + +EXPORT MemoryImpl* evmccrt_memory; + +EXPORT void evmccrt_memory_create(void) +{ + evmccrt_memory = new MemoryImpl(1); + std::cerr << "MEMORY: create(), initial size = " << evmccrt_memory->size() + << std::endl; +} + +// Resizes memory to contain at least _size bytes and returns the base address. +EXPORT void* evmccrt_memory_require(uint64_t _size) +{ + std::cerr << "MEMORY: require(), current size = " << evmccrt_memory->size() + << ", required size = " << _size + << std::endl; + + if (evmccrt_memory->size() < _size) + evmccrt_memory->resize(_size); + + return &(*evmccrt_memory)[0]; +} + +EXPORT void evmccrt_memory_dump(uint64_t _begin, uint64_t _end) +{ + std::cerr << "Memory dump from " << std::hex << _begin << " to " << std::hex << _end << ":"; + if (_end <= _begin) + return; + + _begin = _begin / 16 * 16; + for (size_t i = _begin; i < _end; i++) + { + if ((i - _begin) % 16 == 0) + std::cerr << '\n' << std::dec << i << ": "; + + uint8_t b = (*evmccrt_memory)[i]; + std::cerr << std::hex << std::setw(2) << static_cast(b) << ' '; + } + std::cerr << std::endl; +} + +} // extern "C" diff --git a/evmcc/Memory.h b/evmcc/Memory.h new file mode 100644 index 000000000..16a7ab4ca --- /dev/null +++ b/evmcc/Memory.h @@ -0,0 +1,26 @@ +#pragma once + +#include + +namespace evmcc +{ + +class Memory +{ +public: + Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module); + + llvm::Value* loadByte(llvm::Value* _addr); + void storeWord(llvm::Value* _addr, llvm::Value* _word); + void storeByte(llvm::Value* _addr, llvm::Value* _byte); + + void dump(uint64_t _begin, uint64_t _end); + +private: + llvm::IRBuilder<>& m_builder; + + llvm::Function* m_memRequire; + llvm::Function* m_memDump; +}; + +} From afb0de7f02262ee8c2555a3b7aad9f72fdd3d3fa Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Tue, 30 Sep 2014 23:50:15 +0200 Subject: [PATCH 023/641] added ethcore to libs required by evmcc --- evmcc/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/evmcc/CMakeLists.txt b/evmcc/CMakeLists.txt index 82647ca02..14fbe52e7 100644 --- a/evmcc/CMakeLists.txt +++ b/evmcc/CMakeLists.txt @@ -10,6 +10,7 @@ add_executable(${EXECUTABLE} ${SRC_LIST}) target_link_libraries(${EXECUTABLE} evmface) target_link_libraries(${EXECUTABLE} devcore) +target_link_libraries(${EXECUTABLE} ethcore) if ("${TARGET_PLATFORM}" STREQUAL "w64") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") From 362acacfa289260bcc156591750301bf4452973c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 1 Oct 2014 10:28:46 +0200 Subject: [PATCH 024/641] Set/get values in Ext store - SSTORE & SLOAD --- evmcc/Compiler.cpp | 16 ++++++++++++++++ evmcc/Ext.cpp | 35 +++++++++++++++++++++++++++++------ evmcc/Ext.h | 9 +++++++++ evmcc/Stack.cpp | 11 ++--------- evmcc/Utils.cpp | 34 ++++++++++++++++++++++++++++++++++ evmcc/Utils.h | 24 ++++++++++++++++++++++++ evmcc/bytecode/store_test.evm | 1 + evmcc/lll/stack_test.lll | 26 +++++--------------------- evmcc/lll/store_test.lll | 14 ++++++++++++++ windows/evmcc.vcxproj | 4 ++++ windows/evmcc.vcxproj.filters | 4 ++++ 11 files changed, 142 insertions(+), 36 deletions(-) create mode 100644 evmcc/Utils.cpp create mode 100644 evmcc/Utils.h create mode 100644 evmcc/bytecode/store_test.evm create mode 100644 evmcc/lll/store_test.lll diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index ab16c50f1..00f2fb00b 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -247,6 +247,22 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::SLOAD: + { + auto index = stack.pop(); + auto value = ext.store(index); + stack.push(value); + break; + } + + case Instruction::SSTORE: + { + auto index = stack.pop(); + auto value = stack.pop(); + ext.setStore(index, value); + break; + } + } } diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index 1384694be..35606f67f 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -4,6 +4,8 @@ #include #include +#include "Utils.h" + #ifdef _MSC_VER #define EXPORT __declspec(dllexport) #else @@ -30,21 +32,42 @@ Ext::Ext(llvm::IRBuilder<>& _builder) auto module = m_builder.GetInsertBlock()->getParent()->getParent(); auto&& ctx = _builder.getContext(); - Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_store", module); - Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_setStore", module); + m_args[0] = m_builder.CreateAlloca(m_builder.getIntNTy(256), nullptr, "ext.index"); + m_args[1] = m_builder.CreateAlloca(m_builder.getIntNTy(256), nullptr, "ext.value"); + + m_store = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_store", module); + m_setStore = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_setStore", module); } -extern "C" +llvm::Value* Ext::store(llvm::Value* _index) { + m_builder.CreateStore(_index, m_args[0]); + m_builder.CreateCall(m_store, m_args); + return m_builder.CreateLoad(m_args[1]); +} -EXPORT void ext_store(void* _index, void* _value) +void Ext::setStore(llvm::Value* _index, llvm::Value* _value) { - + m_builder.CreateStore(_index, m_args[0]); + m_builder.CreateStore(_value, m_args[1]); + m_builder.CreateCall(m_setStore, m_args); } -EXPORT void ext_setStore(void* _index, void* _value) +extern "C" { +EXPORT void ext_store(i256* _index, i256* _value) +{ + auto index = llvm2eth(*_index); + auto value = g_ext->store(index); + *_value = eth2llvm(value); +} + +EXPORT void ext_setStore(i256* _index, i256* _value) +{ + auto index = llvm2eth(*_index); + auto value = llvm2eth(*_value); + g_ext->setStore(index, value); } } diff --git a/evmcc/Ext.h b/evmcc/Ext.h index f1c88d849..4de1c6645 100644 --- a/evmcc/Ext.h +++ b/evmcc/Ext.h @@ -1,4 +1,6 @@ +#pragma once + #include #include @@ -14,8 +16,15 @@ public: Ext(llvm::IRBuilder<>& _builder); static void init(std::unique_ptr _ext); + llvm::Value* store(llvm::Value* _index); + void setStore(llvm::Value* _index, llvm::Value* _value); + private: llvm::IRBuilder<>& m_builder; + + llvm::Value* m_args[2]; + llvm::Function* m_store; + llvm::Function* m_setStore; }; diff --git a/evmcc/Stack.cpp b/evmcc/Stack.cpp index aa02a846e..877b192d9 100644 --- a/evmcc/Stack.cpp +++ b/evmcc/Stack.cpp @@ -9,6 +9,8 @@ #include +#include "Utils.h" + #ifdef _MSC_VER #define EXPORT __declspec(dllexport) #else @@ -18,15 +20,6 @@ namespace evmcc { -struct i256 -{ - uint64_t a; - uint64_t b; - uint64_t c; - uint64_t d; -}; -static_assert(sizeof(i256) == 32, "Wrong i265 size"); - using StackImpl = std::vector; diff --git a/evmcc/Utils.cpp b/evmcc/Utils.cpp new file mode 100644 index 000000000..cef08a283 --- /dev/null +++ b/evmcc/Utils.cpp @@ -0,0 +1,34 @@ + +#include "Utils.h" + +namespace evmcc +{ + +dev::u256 llvm2eth(i256 _i) +{ + dev::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(dev::u256 _u) +{ + i256 i; + dev::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; +} + +} \ No newline at end of file diff --git a/evmcc/Utils.h b/evmcc/Utils.h new file mode 100644 index 000000000..065698448 --- /dev/null +++ b/evmcc/Utils.h @@ -0,0 +1,24 @@ + +#pragma once + +#include + +#include + +namespace evmcc +{ + +/// Representation of 256-bit value binary compatible with LLVM i256 +struct i256 +{ + uint64_t a; + uint64_t b; + uint64_t c; + uint64_t d; +}; +static_assert(sizeof(i256) == 32, "Wrong i265 size"); + +dev::u256 llvm2eth(i256); +i256 eth2llvm(dev::u256); + +} \ No newline at end of file diff --git a/evmcc/bytecode/store_test.evm b/evmcc/bytecode/store_test.evm new file mode 100644 index 000000000..54c9419b5 --- /dev/null +++ b/evmcc/bytecode/store_test.evm @@ -0,0 +1 @@ +607b607c60015760005760015660005603 diff --git a/evmcc/lll/stack_test.lll b/evmcc/lll/stack_test.lll index e6581563c..fdf83594c 100644 --- a/evmcc/lll/stack_test.lll +++ b/evmcc/lll/stack_test.lll @@ -1,24 +1,8 @@ (asm -60666666666606 -7077777777777707 -DUP1 -DUP3 -DUP1 -DUP5 -DUP2 -DUP5 -POP -POP -POP -POP -POP -POP -POP -1111 -2222 -DUP2 -DUP2 -SWAP3 -SWAP1 +123 +SSTORE +SLOAD +123 +SUB ) \ No newline at end of file diff --git a/evmcc/lll/store_test.lll b/evmcc/lll/store_test.lll new file mode 100644 index 000000000..c40471c40 --- /dev/null +++ b/evmcc/lll/store_test.lll @@ -0,0 +1,14 @@ + +(asm +123 +124 +1 +SSTORE +0 +SSTORE +1 +SLOAD +0 +SLOAD +SUB +) \ No newline at end of file diff --git a/windows/evmcc.vcxproj b/windows/evmcc.vcxproj index d10235ee3..7959c5a1b 100644 --- a/windows/evmcc.vcxproj +++ b/windows/evmcc.vcxproj @@ -23,13 +23,17 @@ + + + + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D} diff --git a/windows/evmcc.vcxproj.filters b/windows/evmcc.vcxproj.filters index 7b0ee824a..99c43b89b 100644 --- a/windows/evmcc.vcxproj.filters +++ b/windows/evmcc.vcxproj.filters @@ -6,11 +6,15 @@ + + + + \ No newline at end of file From bd3cd40e96fb6390a8020ab610c43b0bda5b25e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 1 Oct 2014 10:43:48 +0200 Subject: [PATCH 025/641] Improve stack binary interface --- evmcc/Stack.cpp | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/evmcc/Stack.cpp b/evmcc/Stack.cpp index 877b192d9..2e9bb495c 100644 --- a/evmcc/Stack.cpp +++ b/evmcc/Stack.cpp @@ -120,42 +120,34 @@ EXPORT void* evmccrt_stack_create() return stack; } -EXPORT void evmccrt_stack_push(void* _stack, void* _pWord) +EXPORT void evmccrt_stack_push(StackImpl* _stack, i256* _word) { - auto stack = static_cast(_stack); - auto word = static_cast(_pWord); - debugStack("push", *word); - stack->push_back(*word); + debugStack("push", *_word); + _stack->push_back(*_word); } -EXPORT void evmccrt_stack_pop(void* _stack, void* _pWord) +EXPORT void evmccrt_stack_pop(StackImpl* _stack, i256* _outWord) { - auto stack = static_cast(_stack); - assert(!stack->empty()); - auto word = &stack->back(); + assert(!_stack->empty()); + auto word = &_stack->back(); debugStack("pop", *word); - auto outWord = static_cast(_pWord); - stack->pop_back(); - *outWord = *word; + _stack->pop_back(); + *_outWord = *word; } -EXPORT void evmccrt_stack_get(void* _stack, uint32_t _index, void* _pWord) +EXPORT void evmccrt_stack_get(StackImpl* _stack, uint32_t _index, i256* _outWord) { - auto stack = static_cast(_stack); - assert(_index < stack->size()); - auto word = stack->rbegin() + _index; + assert(_index < _stack->size()); + auto word = _stack->rbegin() + _index; debugStack("get", *word, _index); - auto outWord = static_cast(_pWord); - *outWord = *word; + *_outWord = *word; } -EXPORT void evmccrt_stack_set(void* _stack, uint32_t _index, void* _pWord) +EXPORT void evmccrt_stack_set(StackImpl* _stack, uint32_t _index, i256* _word) { - auto stack = static_cast(_stack); - auto word = static_cast(_pWord); - assert(_index < stack->size()); - *(stack->rbegin() + _index) = *word; - debugStack("set", *word, _index); + assert(_index < _stack->size()); + *(_stack->rbegin() + _index) = *_word; + debugStack("set", *_word, _index); } } // extern "C" From 10e5182860a814cd631d7bd34331d1d74bbad465 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 1 Oct 2014 12:23:10 +0200 Subject: [PATCH 026/641] Send Ext static data to running contract. ADDRESS instruction --- evmcc/Compiler.cpp | 7 +++++ evmcc/ExecutionEngine.cpp | 1 + evmcc/Ext.cpp | 59 ++++++++++++++++++++++++++++++++++--- evmcc/Ext.h | 4 +++ evmcc/bytecode/ext_test.evm | 1 + evmcc/lll/ext_test.lll | 4 +++ 6 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 evmcc/bytecode/ext_test.evm create mode 100644 evmcc/lll/ext_test.lll diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 00f2fb00b..0bbcafafb 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -263,6 +263,13 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::ADDRESS: + { + auto value = ext.address(); + stack.push(value); + break; + } + } } diff --git a/evmcc/ExecutionEngine.cpp b/evmcc/ExecutionEngine.cpp index 3b3205af4..2b305e04a 100644 --- a/evmcc/ExecutionEngine.cpp +++ b/evmcc/ExecutionEngine.cpp @@ -69,6 +69,7 @@ int ExecutionEngine::run(std::unique_ptr _module) exec->finalizeObject(); auto ext = std::make_unique(); + ext->myAddress = dev::Address(1122334455667788); Ext::init(std::move(ext)); auto entryFunc = module->getFunction("main"); diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index 35606f67f..c6658f80c 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -19,6 +19,12 @@ using Linkage = llvm::GlobalValue::LinkageTypes; namespace evmcc { +// TODO: Copy of dev::eth::fromAddress in VM.h +inline dev::u256 fromAddress(dev::Address _a) +{ + return (dev::u160)_a; +} + std::unique_ptr g_ext; void Ext::init(std::unique_ptr _ext) @@ -26,17 +32,45 @@ void Ext::init(std::unique_ptr _ext) g_ext = std::move(_ext); } +struct ExtData +{ + i256 address; + i256 caller; + i256 origin; + i256 callvalue; + i256 gasprice; + i256 calldatasize; + const byte* calldata; +}; + Ext::Ext(llvm::IRBuilder<>& _builder) : m_builder(_builder) { auto module = m_builder.GetInsertBlock()->getParent()->getParent(); auto&& ctx = _builder.getContext(); - m_args[0] = m_builder.CreateAlloca(m_builder.getIntNTy(256), nullptr, "ext.index"); - m_args[1] = m_builder.CreateAlloca(m_builder.getIntNTy(256), nullptr, "ext.value"); - - m_store = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_store", module); + auto i256Ty = m_builder.getIntNTy(256); + m_args[0] = m_builder.CreateAlloca(i256Ty, nullptr, "ext.index"); + m_args[1] = m_builder.CreateAlloca(i256Ty, nullptr, "ext.value"); + + Type* elements[] = { + i256Ty, + i256Ty, + i256Ty, + i256Ty, + i256Ty, + i256Ty, + m_builder.getInt8PtrTy() + }; + auto extDataTy = StructType::create(elements, "ext.Data"); + + m_data = m_builder.CreateAlloca(extDataTy, nullptr, "ext.data"); + + m_init = Function::Create(FunctionType::get(m_builder.getVoidTy(), extDataTy->getPointerTo(), false), Linkage::ExternalLinkage, "ext_init", module); + m_store = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_store", module); m_setStore = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_setStore", module); + + m_builder.CreateCall(m_init, m_data); } llvm::Value* Ext::store(llvm::Value* _index) @@ -53,9 +87,26 @@ void Ext::setStore(llvm::Value* _index, llvm::Value* _value) m_builder.CreateCall(m_setStore, m_args); } +Value* Ext::address() +{ + auto valuePtr = m_builder.CreateStructGEP(m_data, 0); + return m_builder.CreateLoad(valuePtr); +} + extern "C" { +EXPORT void ext_init(ExtData* _extData) +{ + _extData->address = eth2llvm(fromAddress(g_ext->myAddress)); + _extData->caller = eth2llvm(fromAddress(g_ext->caller)); + _extData->origin = eth2llvm(fromAddress(g_ext->origin)); + _extData->callvalue = eth2llvm(g_ext->value); + _extData->gasprice = eth2llvm(g_ext->gasPrice); + _extData->calldatasize = eth2llvm(g_ext->data.size()); + _extData->calldata = g_ext->data.data(); +} + EXPORT void ext_store(i256* _index, i256* _value) { auto index = llvm2eth(*_index); diff --git a/evmcc/Ext.h b/evmcc/Ext.h index 4de1c6645..f1e6ccc66 100644 --- a/evmcc/Ext.h +++ b/evmcc/Ext.h @@ -19,10 +19,14 @@ public: llvm::Value* store(llvm::Value* _index); void setStore(llvm::Value* _index, llvm::Value* _value); + llvm::Value* address(); + private: llvm::IRBuilder<>& m_builder; llvm::Value* m_args[2]; + llvm::Value* m_data; + llvm::Function* m_init; llvm::Function* m_store; llvm::Function* m_setStore; }; diff --git a/evmcc/bytecode/ext_test.evm b/evmcc/bytecode/ext_test.evm new file mode 100644 index 000000000..64bb6b746 --- /dev/null +++ b/evmcc/bytecode/ext_test.evm @@ -0,0 +1 @@ +30 diff --git a/evmcc/lll/ext_test.lll b/evmcc/lll/ext_test.lll new file mode 100644 index 000000000..627f6f96e --- /dev/null +++ b/evmcc/lll/ext_test.lll @@ -0,0 +1,4 @@ + +(asm +ADDRESS +) \ No newline at end of file From 696f6ae62eac4af03cd05cb6e000c2a162b4b16b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 1 Oct 2014 12:44:45 +0200 Subject: [PATCH 027/641] Accessing Ext static data: CALLER, ORIGIN, CALLVALUE, CALLDATASIZE, GASPRICE --- evmcc/Compiler.cpp | 35 +++++++++++++++++++++++++++++++++++ evmcc/ExecutionEngine.cpp | 6 ++++++ evmcc/Ext.cpp | 11 +++++++++-- evmcc/Ext.h | 8 ++++++++ evmcc/bytecode/ext_test.evm | 2 +- evmcc/lll/ext_test.lll | 5 +++++ 6 files changed, 64 insertions(+), 3 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 0bbcafafb..77aaaa92f 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -270,6 +270,41 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::CALLER: + { + auto value = ext.caller(); + stack.push(value); + break; + } + + case Instruction::ORIGIN: + { + auto value = ext.origin(); + stack.push(value); + break; + } + + case Instruction::CALLVALUE: + { + auto value = ext.callvalue(); + stack.push(value); + break; + } + + case Instruction::CALLDATASIZE: + { + auto value = ext.calldatasize(); + stack.push(value); + break; + } + + case Instruction::GASPRICE: + { + auto value = ext.gasprice(); + stack.push(value); + break; + } + } } diff --git a/evmcc/ExecutionEngine.cpp b/evmcc/ExecutionEngine.cpp index 2b305e04a..9011ac694 100644 --- a/evmcc/ExecutionEngine.cpp +++ b/evmcc/ExecutionEngine.cpp @@ -70,6 +70,12 @@ int ExecutionEngine::run(std::unique_ptr _module) auto ext = std::make_unique(); ext->myAddress = dev::Address(1122334455667788); + ext->caller = dev::Address(0xfacefacefaceface); + ext->origin = dev::Address(101010101010101010); + ext->value = 0xabcd; + ext->gasPrice = 1002; + std::string calldata = "Hello World!"; + ext->data = calldata; Ext::init(std::move(ext)); auto entryFunc = module->getFunction("main"); diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index c6658f80c..309ef21a3 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -87,12 +87,19 @@ void Ext::setStore(llvm::Value* _index, llvm::Value* _value) m_builder.CreateCall(m_setStore, m_args); } -Value* Ext::address() +Value* Ext::getDataElem(unsigned _index, const Twine& _name) { - auto valuePtr = m_builder.CreateStructGEP(m_data, 0); + auto valuePtr = m_builder.CreateStructGEP(m_data, _index, _name); return m_builder.CreateLoad(valuePtr); } +Value* Ext::address() { return getDataElem(0, "address"); } +Value* Ext::caller() { return getDataElem(1, "caller"); } +Value* Ext::origin() { return getDataElem(2, "origin"); } +Value* Ext::callvalue() { return getDataElem(3, "callvalue"); } +Value* Ext::calldatasize() { return getDataElem(5, "calldatasize"); } +Value* Ext::gasprice() { return getDataElem(4, "gasprice"); } + extern "C" { diff --git a/evmcc/Ext.h b/evmcc/Ext.h index f1e6ccc66..60efe9f6f 100644 --- a/evmcc/Ext.h +++ b/evmcc/Ext.h @@ -20,6 +20,14 @@ public: void setStore(llvm::Value* _index, llvm::Value* _value); llvm::Value* address(); + llvm::Value* caller(); + llvm::Value* origin(); + llvm::Value* callvalue(); + llvm::Value* calldatasize(); + llvm::Value* gasprice(); + +private: + llvm::Value* getDataElem(unsigned _index, const llvm::Twine& _name = ""); private: llvm::IRBuilder<>& m_builder; diff --git a/evmcc/bytecode/ext_test.evm b/evmcc/bytecode/ext_test.evm index 64bb6b746..afbe4e752 100644 --- a/evmcc/bytecode/ext_test.evm +++ b/evmcc/bytecode/ext_test.evm @@ -1 +1 @@ -30 +30333234363a diff --git a/evmcc/lll/ext_test.lll b/evmcc/lll/ext_test.lll index 627f6f96e..27dceabde 100644 --- a/evmcc/lll/ext_test.lll +++ b/evmcc/lll/ext_test.lll @@ -1,4 +1,9 @@ (asm ADDRESS +CALLER +ORIGIN +CALLVALUE +CALLDATASIZE +GASPRICE ) \ No newline at end of file From 9ee462570bb4741ead8d42da386797d72d766b44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 1 Oct 2014 14:23:49 +0200 Subject: [PATCH 028/641] Push call data on stack - CALLDATALOAD --- evmcc/Compiler.cpp | 8 ++++++++ evmcc/ExecutionEngine.cpp | 2 +- evmcc/Ext.cpp | 18 ++++++++++++++++++ evmcc/Ext.h | 3 +++ evmcc/Utils.h | 1 + evmcc/bytecode/ext_test.evm | 2 +- evmcc/lll/ext_test.lll | 6 ++++++ 7 files changed, 38 insertions(+), 2 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 77aaaa92f..1b3edd8bd 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -298,6 +298,14 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::CALLDATALOAD: + { + auto index = stack.pop(); + auto value = ext.calldataload(index); + stack.push(value); + break; + } + case Instruction::GASPRICE: { auto value = ext.gasprice(); diff --git a/evmcc/ExecutionEngine.cpp b/evmcc/ExecutionEngine.cpp index 9011ac694..616bde402 100644 --- a/evmcc/ExecutionEngine.cpp +++ b/evmcc/ExecutionEngine.cpp @@ -74,7 +74,7 @@ int ExecutionEngine::run(std::unique_ptr _module) ext->origin = dev::Address(101010101010101010); ext->value = 0xabcd; ext->gasPrice = 1002; - std::string calldata = "Hello World!"; + std::string calldata = "Hello the Beautiful World of Ethereum!"; ext->data = calldata; Ext::init(std::move(ext)); diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index 309ef21a3..0c38f73d3 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -69,6 +69,7 @@ Ext::Ext(llvm::IRBuilder<>& _builder) m_init = Function::Create(FunctionType::get(m_builder.getVoidTy(), extDataTy->getPointerTo(), false), Linkage::ExternalLinkage, "ext_init", module); m_store = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_store", module); m_setStore = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_setStore", module); + m_calldataload = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_calldataload", module); m_builder.CreateCall(m_init, m_data); } @@ -100,6 +101,13 @@ Value* Ext::callvalue() { return getDataElem(3, "callvalue"); } Value* Ext::calldatasize() { return getDataElem(5, "calldatasize"); } Value* Ext::gasprice() { return getDataElem(4, "gasprice"); } +Value* Ext::calldataload(Value* _index) +{ + m_builder.CreateStore(_index, m_args[0]); + m_builder.CreateCall(m_calldataload, m_args); + return m_builder.CreateLoad(m_args[1]); +} + extern "C" { @@ -128,6 +136,16 @@ EXPORT void ext_setStore(i256* _index, i256* _value) g_ext->setStore(index, value); } +EXPORT void ext_calldataload(i256* _index, i256* _value) +{ + auto index = static_cast(llvm2eth(*_index)); + assert(index + 31 > index); // TODO: Handle large index + auto b = reinterpret_cast(_value); + for (size_t i = index, j = 31; i <= index + 31; ++i, --j) + b[j] = i < g_ext->data.size() ? g_ext->data[i] : 0; + // TODO: It all can be done by adding padding to data or by using min() algorithm without branch +} + } } \ No newline at end of file diff --git a/evmcc/Ext.h b/evmcc/Ext.h index 60efe9f6f..a579dca81 100644 --- a/evmcc/Ext.h +++ b/evmcc/Ext.h @@ -26,6 +26,8 @@ public: llvm::Value* calldatasize(); llvm::Value* gasprice(); + llvm::Value* calldataload(llvm::Value* _index); + private: llvm::Value* getDataElem(unsigned _index, const llvm::Twine& _name = ""); @@ -37,6 +39,7 @@ private: llvm::Function* m_init; llvm::Function* m_store; llvm::Function* m_setStore; + llvm::Function* m_calldataload; }; diff --git a/evmcc/Utils.h b/evmcc/Utils.h index 065698448..8233ac9e3 100644 --- a/evmcc/Utils.h +++ b/evmcc/Utils.h @@ -9,6 +9,7 @@ namespace evmcc { /// Representation of 256-bit value binary compatible with LLVM i256 +// TODO: Replace with h256 struct i256 { uint64_t a; diff --git a/evmcc/bytecode/ext_test.evm b/evmcc/bytecode/ext_test.evm index afbe4e752..ccca5e56b 100644 --- a/evmcc/bytecode/ext_test.evm +++ b/evmcc/bytecode/ext_test.evm @@ -1 +1 @@ -30333234363a +30333234363a600035602635601335 diff --git a/evmcc/lll/ext_test.lll b/evmcc/lll/ext_test.lll index 27dceabde..f6680f2a7 100644 --- a/evmcc/lll/ext_test.lll +++ b/evmcc/lll/ext_test.lll @@ -6,4 +6,10 @@ ORIGIN CALLVALUE CALLDATASIZE GASPRICE +0 +CALLDATALOAD +38 +CALLDATALOAD +19 +CALLDATALOAD ) \ No newline at end of file From 638bb9390cc0e32819a58b6378cc9b4d302e2e8c Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Wed, 1 Oct 2014 15:46:46 +0200 Subject: [PATCH 029/641] Implemented MLOAD, MSTORE, MSTORE8 and MSIZE --- evmcc/Compiler.cpp | 31 ++++++++++++++++++++ evmcc/Memory.cpp | 64 +++++++++++++++++++++++++++++++++--------- evmcc/Memory.h | 6 ++-- evmcc/lll/memtest1.lll | 17 +++++++++++ 4 files changed, 103 insertions(+), 15 deletions(-) create mode 100644 evmcc/lll/memtest1.lll diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 77aaaa92f..2b27c6e32 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -247,6 +247,37 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::MLOAD: + { + auto addr = stack.pop(); + auto word = memory.loadWord(addr); + stack.push(word); + break; + } + + case Instruction::MSTORE: + { + auto addr = stack.pop(); + auto word = stack.pop(); + memory.storeWord(addr, word); + break; + } + + case Instruction::MSTORE8: + { + auto addr = stack.pop(); + auto word = stack.pop(); + memory.storeByte(addr, word); + break; + } + + case Instruction::MSIZE: + { + auto word = memory.getSize(); + stack.push(word); + break; + } + case Instruction::SLOAD: { auto index = stack.pop(); diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index 9e3c2942e..bba929576 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -34,18 +34,25 @@ using MemoryImpl = dev::bytes; Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module) : m_builder(_builder) { - auto memoryCreate = llvm::Function::Create(llvm::FunctionType::get(m_builder.getVoidTy(), false), + auto voidTy = m_builder.getVoidTy(); + auto i64Ty = m_builder.getInt64Ty(); + + auto memoryCreate = llvm::Function::Create(llvm::FunctionType::get(voidTy, false), llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_memory_create", _module); m_builder.CreateCall(memoryCreate); - auto memRequireTy = llvm::FunctionType::get(m_builder.getInt8PtrTy(), m_builder.getInt64Ty(), false); + auto memRequireTy = llvm::FunctionType::get(m_builder.getInt8PtrTy(), i64Ty, false); m_memRequire = llvm::Function::Create(memRequireTy, llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_memory_require", _module); - auto i64Ty = m_builder.getInt64Ty(); + auto memSizeTy = llvm::FunctionType::get(i64Ty, false); + m_memSize = llvm::Function::Create(memSizeTy, + llvm::GlobalValue::LinkageTypes::ExternalLinkage, + "evmccrt_memory_size", _module); + std::vector argTypes = {i64Ty, i64Ty}; auto dumpTy = llvm::FunctionType::get(m_builder.getVoidTy(), llvm::ArrayRef(argTypes), false); m_memDump = llvm::Function::Create(dumpTy, llvm::GlobalValue::LinkageTypes::ExternalLinkage, @@ -53,7 +60,7 @@ Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module) } -llvm::Value* Memory::loadByte(llvm::Value* _addr) +llvm::Value* Memory::loadWord(llvm::Value* _addr) { // trunc _addr (an i256) to i64 index and use it to index the memory auto index = m_builder.CreateTrunc(_addr, m_builder.getInt64Ty(), "index"); @@ -61,7 +68,12 @@ llvm::Value* Memory::loadByte(llvm::Value* _addr) // load from evmccrt_memory_require()[index] auto base = m_builder.CreateCall(m_memRequire, index, "base"); auto ptr = m_builder.CreateGEP(base, index, "ptr"); - auto byte = m_builder.CreateLoad(ptr, "byte"); + + auto i256ptrTy = m_builder.getIntNTy(256)->getPointerTo(); + auto wordPtr = m_builder.CreateBitCast(ptr, i256ptrTy, "wordptr"); + auto byte = m_builder.CreateLoad(wordPtr, "word"); + + dump(0); return byte; } @@ -76,19 +88,34 @@ void Memory::storeWord(llvm::Value* _addr, llvm::Value* _word) auto i256ptrTy = m_builder.getIntNTy(256)->getPointerTo(); auto wordPtr = m_builder.CreateBitCast(ptr, i256ptrTy, "wordptr"); m_builder.CreateStore(_word, wordPtr); + + dump(0); } -void Memory::storeByte(llvm::Value* _addr, llvm::Value* _byte) +void Memory::storeByte(llvm::Value* _addr, llvm::Value* _word) { + auto byte = m_builder.CreateTrunc(_word, m_builder.getInt8Ty(), "byte"); auto index = m_builder.CreateTrunc(_addr, m_builder.getInt64Ty(), "index"); auto base = m_builder.CreateCall(m_memRequire, index, "base"); auto ptr = m_builder.CreateGEP(base, index, "ptr"); - m_builder.CreateStore(_byte, ptr); + m_builder.CreateStore(byte, ptr); + + dump(0); +} + +llvm::Value* Memory::getSize() +{ + auto size = m_builder.CreateCall(m_memSize, "mem.size"); + auto word = m_builder.CreateZExt(size, m_builder.getIntNTy(256), "mem.wsize"); + return word; } void Memory::dump(uint64_t _begin, uint64_t _end) { + if (getenv("EVMCC_DEBUG_MEMORY") == nullptr) + return; + auto beginVal = llvm::ConstantInt::get(m_builder.getInt64Ty(), _begin); auto endVal = llvm::ConstantInt::get(m_builder.getInt64Ty(), _end); @@ -106,26 +133,37 @@ EXPORT MemoryImpl* evmccrt_memory; EXPORT void evmccrt_memory_create(void) { - evmccrt_memory = new MemoryImpl(1); + evmccrt_memory = new MemoryImpl(); std::cerr << "MEMORY: create(), initial size = " << evmccrt_memory->size() << std::endl; } -// Resizes memory to contain at least _size bytes and returns the base address. -EXPORT void* evmccrt_memory_require(uint64_t _size) +// Resizes memory to contain at least _index + 1 bytes and returns the base address. +EXPORT uint8_t* evmccrt_memory_require(uint64_t _index) { + uint64_t size = _index + 1; + std::cerr << "MEMORY: require(), current size = " << evmccrt_memory->size() - << ", required size = " << _size + << ", required size = " << size << std::endl; - if (evmccrt_memory->size() < _size) - evmccrt_memory->resize(_size); + if (evmccrt_memory->size() < size) + evmccrt_memory->resize(size); return &(*evmccrt_memory)[0]; } +EXPORT uint64_t evmccrt_memory_size() +{ + return (evmccrt_memory->size() + 31) / 32; +} + EXPORT void evmccrt_memory_dump(uint64_t _begin, uint64_t _end) { + if (_end == 0) + _end = evmccrt_memory->size(); + + std::cerr << "Active memory size: " << evmccrt_memory_size() << " words\n"; std::cerr << "Memory dump from " << std::hex << _begin << " to " << std::hex << _end << ":"; if (_end <= _begin) return; diff --git a/evmcc/Memory.h b/evmcc/Memory.h index 16a7ab4ca..8fbbe0a58 100644 --- a/evmcc/Memory.h +++ b/evmcc/Memory.h @@ -10,17 +10,19 @@ class Memory public: Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module); - llvm::Value* loadByte(llvm::Value* _addr); + llvm::Value* loadWord(llvm::Value* _addr); void storeWord(llvm::Value* _addr, llvm::Value* _word); void storeByte(llvm::Value* _addr, llvm::Value* _byte); + llvm::Value* getSize(); - void dump(uint64_t _begin, uint64_t _end); + void dump(uint64_t _begin, uint64_t _end = 0); private: llvm::IRBuilder<>& m_builder; llvm::Function* m_memRequire; llvm::Function* m_memDump; + llvm::Function* m_memSize; }; } diff --git a/evmcc/lll/memtest1.lll b/evmcc/lll/memtest1.lll new file mode 100644 index 000000000..016e4075f --- /dev/null +++ b/evmcc/lll/memtest1.lll @@ -0,0 +1,17 @@ + +(asm ;; [] +2 +0 +MSTORE8 ;; [02] +3 +1 +MSTORE8 ;; [02 03] +0 +MLOAD ;; [2 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] +1 +MLOAD ;; [2 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] +ADD +2 +MSTORE ;; [2 3 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + ;; 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ] +) From 65908ab5e86df6ca9db1b6a4dbf74cae75f98950 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Wed, 1 Oct 2014 16:32:59 +0200 Subject: [PATCH 030/641] fixed bug in memory handling --- evmcc/Memory.cpp | 34 ++++++++++++++++++++-------------- evmcc/bytecode/memtest1.evm | 1 + evmcc/lll/memtest1.lll | 9 +++++---- 3 files changed, 26 insertions(+), 18 deletions(-) create mode 100644 evmcc/bytecode/memtest1.evm diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index bba929576..219dfe7fa 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -63,10 +63,11 @@ Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module) llvm::Value* Memory::loadWord(llvm::Value* _addr) { // trunc _addr (an i256) to i64 index and use it to index the memory - auto index = m_builder.CreateTrunc(_addr, m_builder.getInt64Ty(), "index"); + auto index = m_builder.CreateTrunc(_addr, m_builder.getInt64Ty(), "mem.index"); + auto index31 = m_builder.CreateAdd(index, llvm::ConstantInt::get(m_builder.getInt64Ty(), 31), "mem.index.31"); // load from evmccrt_memory_require()[index] - auto base = m_builder.CreateCall(m_memRequire, index, "base"); + auto base = m_builder.CreateCall(m_memRequire, index31, "base"); auto ptr = m_builder.CreateGEP(base, index, "ptr"); auto i256ptrTy = m_builder.getIntNTy(256)->getPointerTo(); @@ -79,10 +80,10 @@ llvm::Value* Memory::loadWord(llvm::Value* _addr) void Memory::storeWord(llvm::Value* _addr, llvm::Value* _word) { - auto index = m_builder.CreateTrunc(_addr, m_builder.getInt64Ty(), "index"); - auto index32 = m_builder.CreateAdd(index, llvm::ConstantInt::get(m_builder.getInt64Ty(), 32), "index32"); + auto index = m_builder.CreateTrunc(_addr, m_builder.getInt64Ty(), "mem.index"); + auto index31 = m_builder.CreateAdd(index, llvm::ConstantInt::get(m_builder.getInt64Ty(), 31), "mem.index31"); - auto base = m_builder.CreateCall(m_memRequire, index32, "base"); + auto base = m_builder.CreateCall(m_memRequire, index31, "base"); auto ptr = m_builder.CreateGEP(base, index, "ptr"); auto i256ptrTy = m_builder.getIntNTy(256)->getPointerTo(); @@ -141,21 +142,24 @@ EXPORT void evmccrt_memory_create(void) // Resizes memory to contain at least _index + 1 bytes and returns the base address. EXPORT uint8_t* evmccrt_memory_require(uint64_t _index) { - uint64_t size = _index + 1; + uint64_t requiredSize = (_index / 32 + 1) * 32; - std::cerr << "MEMORY: require(), current size = " << evmccrt_memory->size() - << ", required size = " << size - << std::endl; + if (evmccrt_memory->size() < requiredSize) + { + std::cerr << "MEMORY: current size: " << std::dec + << evmccrt_memory->size() << " bytes, required size: " + << requiredSize << " bytes" + << std::endl; - if (evmccrt_memory->size() < size) - evmccrt_memory->resize(size); + evmccrt_memory->resize(requiredSize); + } return &(*evmccrt_memory)[0]; } EXPORT uint64_t evmccrt_memory_size() { - return (evmccrt_memory->size() + 31) / 32; + return evmccrt_memory->size() / 32; } EXPORT void evmccrt_memory_dump(uint64_t _begin, uint64_t _end) @@ -163,8 +167,10 @@ EXPORT void evmccrt_memory_dump(uint64_t _begin, uint64_t _end) if (_end == 0) _end = evmccrt_memory->size(); - std::cerr << "Active memory size: " << evmccrt_memory_size() << " words\n"; - std::cerr << "Memory dump from " << std::hex << _begin << " to " << std::hex << _end << ":"; + std::cerr << "MEMORY: active size: " << std::dec + << evmccrt_memory_size() << " words\n"; + std::cerr << "MEMORY: dump from " << std::dec + << _begin << " to " << _end << ":"; if (_end <= _begin) return; diff --git a/evmcc/bytecode/memtest1.evm b/evmcc/bytecode/memtest1.evm new file mode 100644 index 000000000..0506bf928 --- /dev/null +++ b/evmcc/bytecode/memtest1.evm @@ -0,0 +1 @@ +6002600055600360015560005360015301600254 diff --git a/evmcc/lll/memtest1.lll b/evmcc/lll/memtest1.lll index 016e4075f..4b4389ad8 100644 --- a/evmcc/lll/memtest1.lll +++ b/evmcc/lll/memtest1.lll @@ -9,9 +9,10 @@ MSTORE8 ;; [02 03] 0 MLOAD ;; [2 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] 1 -MLOAD ;; [2 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] +MLOAD ;; [2 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + ;; 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] ADD 2 -MSTORE ;; [2 3 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 - ;; 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ] -) +MSTORE ;; [2 3 5 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + ;; 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] +) \ No newline at end of file From f41550077a084183e69b70404c6f7b89f0acdb5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 1 Oct 2014 16:48:02 +0200 Subject: [PATCH 031/641] Implementing RETURN and STOP instructions --- evmcc/Compiler.cpp | 48 ++++++++++++++++++++++++++++++++++--- evmcc/ExecutionEngine.cpp | 10 ++++++-- evmcc/Memory.cpp | 15 ++++-------- evmcc/bytecode/ext_test.evm | 2 +- evmcc/lll/ext_test.lll | 5 ++++ 5 files changed, 63 insertions(+), 17 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 1b3edd8bd..e258f840d 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -49,7 +49,10 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) IRBuilder<> builder(context); // Create main function - auto mainFuncType = FunctionType::get(llvm::Type::getInt32Ty(context), false); + const auto i32Ty = builder.getInt32Ty(); + Type* retTypeElems[] = {i32Ty, i32Ty}; + auto retType = StructType::create(retTypeElems, "MemRef", true); + auto mainFuncType = FunctionType::get(builder.getInt64Ty(), false); auto mainFunc = Function::Create(mainFuncType, Function::ExternalLinkage, "main", module.get()); auto entryBlock = BasicBlock::Create(context, "entry", mainFunc); @@ -61,7 +64,9 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto ext = Ext(builder); - for (auto pc = bytecode.cbegin(); pc != bytecode.cend(); ++pc) + auto userRet = false; + auto finished = false; + for (auto pc = bytecode.cbegin(); pc != bytecode.cend() && !finished; ++pc) { using dev::eth::Instruction; @@ -313,10 +318,47 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::CODESIZE: + { + auto value = builder.getIntN(256, bytecode.size()); + stack.push(value); + break; + } + + case Instruction::RETURN: + { + auto index = stack.pop(); + auto size = stack.pop(); + + // MCJIT does not support returning structs + //auto index32 = builder.CreateTrunc(index, i32Ty, "index32"); + //auto size32 = builder.CreateTrunc(size, i32Ty, "size32"); + //auto ret = builder.CreateInsertValue(UndefValue::get(retType), index32, 0, "ret"); + //ret = builder.CreateInsertValue(ret, size32, 1, "ret"); + + auto ret = builder.CreateTrunc(index, builder.getInt64Ty()); + ret = builder.CreateShl(ret, 32); + size = builder.CreateTrunc(size, i32Ty); + size = builder.CreateZExt(size, builder.getInt64Ty()); + ret = builder.CreateOr(ret, size); + + builder.CreateRet(ret); + finished = true; + userRet = true; + break; + } + + case Instruction::STOP: + { + finished = true; + break; + } + } } - builder.CreateRet(ConstantInt::get(Type::getInt32Ty(context), 0)); + if (!userRet) + builder.CreateRet(builder.getInt64(0)); return module; } diff --git a/evmcc/ExecutionEngine.cpp b/evmcc/ExecutionEngine.cpp index 616bde402..410e80a0b 100644 --- a/evmcc/ExecutionEngine.cpp +++ b/evmcc/ExecutionEngine.cpp @@ -86,8 +86,14 @@ int ExecutionEngine::run(std::unique_ptr _module) } auto result = exec->runFunction(entryFunc, {}); - auto intResult = result.IntVal.getZExtValue(); - return intResult; + if (auto intResult = result.IntVal.getZExtValue()) + { + auto index = intResult >> 32; + auto size = 0xFFFFFFFF & intResult; + // TODO: Get the data from memory + return 10; + } + return 0; } } \ No newline at end of file diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index 9e3c2942e..7c8d2d54a 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -10,6 +10,8 @@ #include +#include "Utils.h" + #ifdef _MSC_VER #define EXPORT __declspec(dllexport) #else @@ -19,15 +21,6 @@ namespace evmcc { -struct i256 -{ - uint64_t a; - uint64_t b; - uint64_t c; - uint64_t d; -}; -static_assert(sizeof(i256) == 32, "Wrong i256 size"); - using MemoryImpl = dev::bytes; @@ -102,7 +95,7 @@ extern "C" { using namespace evmcc; -EXPORT MemoryImpl* evmccrt_memory; +static MemoryImpl* evmccrt_memory; EXPORT void evmccrt_memory_create(void) { @@ -121,7 +114,7 @@ EXPORT void* evmccrt_memory_require(uint64_t _size) if (evmccrt_memory->size() < _size) evmccrt_memory->resize(_size); - return &(*evmccrt_memory)[0]; + return evmccrt_memory->data(); } EXPORT void evmccrt_memory_dump(uint64_t _begin, uint64_t _end) diff --git a/evmcc/bytecode/ext_test.evm b/evmcc/bytecode/ext_test.evm index ccca5e56b..5bcc94ba1 100644 --- a/evmcc/bytecode/ext_test.evm +++ b/evmcc/bytecode/ext_test.evm @@ -1 +1 @@ -30333234363a600035602635601335 +30333234363a600035602635601335380060016002f2 diff --git a/evmcc/lll/ext_test.lll b/evmcc/lll/ext_test.lll index f6680f2a7..f32bfb440 100644 --- a/evmcc/lll/ext_test.lll +++ b/evmcc/lll/ext_test.lll @@ -12,4 +12,9 @@ CALLDATALOAD CALLDATALOAD 19 CALLDATALOAD +CODESIZE +STOP +1 +2 +RETURN ) \ No newline at end of file From f6759913e4aad3c577067ae089f0890fe93b73b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 1 Oct 2014 17:30:04 +0200 Subject: [PATCH 032/641] Print returned memory to standard output --- evmcc/Compiler.cpp | 2 +- evmcc/ExecutionEngine.cpp | 10 +++++++++- evmcc/Memory.cpp | 34 ++++++++++++++++------------------ evmcc/Memory.h | 6 +++++- evmcc/bytecode/return_test.evm | 1 + evmcc/lll/return_test.lll | 15 +++++++++++++++ 6 files changed, 47 insertions(+), 21 deletions(-) create mode 100644 evmcc/bytecode/return_test.evm create mode 100644 evmcc/lll/return_test.lll diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 51d74bb2f..c55b33cc6 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -60,7 +60,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) // Init stack and memory auto stack = Stack(builder, module.get()); - auto memory = Memory(builder, module.get()); + auto memory = Memory(builder); auto ext = Ext(builder); diff --git a/evmcc/ExecutionEngine.cpp b/evmcc/ExecutionEngine.cpp index 410e80a0b..4d847388e 100644 --- a/evmcc/ExecutionEngine.cpp +++ b/evmcc/ExecutionEngine.cpp @@ -14,6 +14,7 @@ #include #include "Ext.h" +#include "Memory.h" namespace evmcc { @@ -68,6 +69,8 @@ int ExecutionEngine::run(std::unique_ptr _module) _module.release(); // Successfully created llvm::ExecutionEngine takes ownership of the module exec->finalizeObject(); + auto&& memory = Memory::init(); + auto ext = std::make_unique(); ext->myAddress = dev::Address(1122334455667788); ext->caller = dev::Address(0xfacefacefaceface); @@ -90,7 +93,12 @@ int ExecutionEngine::run(std::unique_ptr _module) { auto index = intResult >> 32; auto size = 0xFFFFFFFF & intResult; - // TODO: Get the data from memory + + std::cout << "RETURN [ "; + for (dev::bytes::const_iterator it = memory.cbegin() + index, end = it + size; it != end; ++it) + std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)*it << " "; + std::cout << "]"; + return 10; } return 0; diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index 9897496de..2a1a0f727 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -23,33 +23,40 @@ namespace evmcc using MemoryImpl = dev::bytes; +static MemoryImpl* evmccrt_memory; + -Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module) +Memory::Memory(llvm::IRBuilder<>& _builder) : m_builder(_builder) { auto voidTy = m_builder.getVoidTy(); auto i64Ty = m_builder.getInt64Ty(); - - auto memoryCreate = llvm::Function::Create(llvm::FunctionType::get(voidTy, false), - llvm::GlobalValue::LinkageTypes::ExternalLinkage, - "evmccrt_memory_create", _module); - m_builder.CreateCall(memoryCreate); + auto module = _builder.GetInsertBlock()->getParent()->getParent(); auto memRequireTy = llvm::FunctionType::get(m_builder.getInt8PtrTy(), i64Ty, false); m_memRequire = llvm::Function::Create(memRequireTy, llvm::GlobalValue::LinkageTypes::ExternalLinkage, - "evmccrt_memory_require", _module); + "evmccrt_memory_require", module); auto memSizeTy = llvm::FunctionType::get(i64Ty, false); m_memSize = llvm::Function::Create(memSizeTy, llvm::GlobalValue::LinkageTypes::ExternalLinkage, - "evmccrt_memory_size", _module); + "evmccrt_memory_size", module); std::vector argTypes = {i64Ty, i64Ty}; auto dumpTy = llvm::FunctionType::get(m_builder.getVoidTy(), llvm::ArrayRef(argTypes), false); m_memDump = llvm::Function::Create(dumpTy, llvm::GlobalValue::LinkageTypes::ExternalLinkage, - "evmccrt_memory_dump", _module); + "evmccrt_memory_dump", module); +} + +const dev::bytes& Memory::init() +{ + evmccrt_memory = new MemoryImpl(); + std::cerr << "MEMORY: create(), initial size = " << evmccrt_memory->size() + << std::endl; + + return *evmccrt_memory; } @@ -123,15 +130,6 @@ extern "C" { using namespace evmcc; -static MemoryImpl* evmccrt_memory; - -EXPORT void evmccrt_memory_create(void) -{ - evmccrt_memory = new MemoryImpl(); - std::cerr << "MEMORY: create(), initial size = " << evmccrt_memory->size() - << std::endl; -} - // Resizes memory to contain at least _index + 1 bytes and returns the base address. EXPORT uint8_t* evmccrt_memory_require(uint64_t _index) { diff --git a/evmcc/Memory.h b/evmcc/Memory.h index 8fbbe0a58..b36386325 100644 --- a/evmcc/Memory.h +++ b/evmcc/Memory.h @@ -2,13 +2,17 @@ #include +#include + namespace evmcc { class Memory { public: - Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module); + Memory(llvm::IRBuilder<>& _builder); + + static const dev::bytes& init(); llvm::Value* loadWord(llvm::Value* _addr); void storeWord(llvm::Value* _addr, llvm::Value* _word); diff --git a/evmcc/bytecode/return_test.evm b/evmcc/bytecode/return_test.evm new file mode 100644 index 000000000..977cf7c19 --- /dev/null +++ b/evmcc/bytecode/return_test.evm @@ -0,0 +1 @@ +60016064546002608454600360a45460606064f2 diff --git a/evmcc/lll/return_test.lll b/evmcc/lll/return_test.lll new file mode 100644 index 000000000..c87a2d812 --- /dev/null +++ b/evmcc/lll/return_test.lll @@ -0,0 +1,15 @@ + +(asm +1 +100 +MSTORE +2 +132 +MSTORE +3 +164 +MSTORE +96 +100 +RETURN +) \ No newline at end of file From ca49fe4897e53507fddbedd3024ee5ad09c0066b Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Thu, 2 Oct 2014 11:00:28 +0200 Subject: [PATCH 033/641] initial implementation of JUMP/JUMPI (untested) --- evmcc/Compiler.cpp | 171 ++++++++++++++++++++++++++++++++++++++++++++- evmcc/Compiler.h | 16 +++++ 2 files changed, 184 insertions(+), 3 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 2a13e4a64..87c96a20d 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -39,6 +39,117 @@ Compiler::Compiler() Types.WordLowPrecision = llvm::Type::getIntNTy(context, 64); } +llvm::BasicBlock* Compiler::getOrCreateBasicBlockAtPC(ProgramCounter pc) +{ + llvm::BasicBlock* block = nullptr; + auto blockIter = basicBlocks.find(pc); + if (blockIter == basicBlocks.cend()) + { + // Create a basic block at targetPC. + std::ostringstream oss; + oss << "instr." << pc; + block = llvm::BasicBlock::Create(llvm::getGlobalContext(), oss.str()); + basicBlocks[pc] = block; + } + else + { + block = blockIter->second; + } + return block; +} + +void Compiler::createBasicBlocks(const dev::bytes& bytecode) +{ + for (auto curr = bytecode.cbegin(); curr != bytecode.cend(); ++curr) + { + using dev::eth::Instruction; + + auto inst = static_cast(*curr); + switch (inst) + { + case Instruction::PUSH1: + case Instruction::PUSH2: + case Instruction::PUSH3: + case Instruction::PUSH4: + case Instruction::PUSH5: + case Instruction::PUSH6: + case Instruction::PUSH7: + case Instruction::PUSH8: + case Instruction::PUSH9: + case Instruction::PUSH10: + case Instruction::PUSH11: + case Instruction::PUSH12: + case Instruction::PUSH13: + case Instruction::PUSH14: + case Instruction::PUSH15: + case Instruction::PUSH16: + case Instruction::PUSH17: + case Instruction::PUSH18: + case Instruction::PUSH19: + case Instruction::PUSH20: + case Instruction::PUSH21: + case Instruction::PUSH22: + case Instruction::PUSH23: + case Instruction::PUSH24: + case Instruction::PUSH25: + case Instruction::PUSH26: + case Instruction::PUSH27: + case Instruction::PUSH28: + case Instruction::PUSH29: + case Instruction::PUSH30: + case Instruction::PUSH31: + case Instruction::PUSH32: + { + auto numBytes = static_cast(inst) - static_cast(Instruction::PUSH1) + 1; + auto next = curr + numBytes + 1; + if (next == bytecode.cend()) + break; + + auto nextInst = static_cast(*next); + + if (nextInst == Instruction::JUMP || nextInst == Instruction::JUMPI) + { + // Compute target PC of the jump. + dev::u256 val = 0; + for (auto iter = curr + 1; iter < next; ++iter) + { + val <<= 8; + val |= *iter; + } + + // Create a block for the JUMP target. + ProgramCounter targetPC = val.convert_to(); + auto targetBlock = getOrCreateBasicBlockAtPC(targetPC); + + ProgramCounter jumpPC = (next - bytecode.cbegin()); + jumpTargets[jumpPC] = targetBlock; + + // Create a block following the JUMP. + if (next + 1 < bytecode.cend()) + { + ProgramCounter nextPC = (next + 1 - bytecode.cbegin()); + getOrCreateBasicBlockAtPC(nextPC); + } + + curr += 1; // skip over JUMP + } + + curr += numBytes; + break; + } + + case Instruction::JUMP: + case Instruction::JUMPI: + { + std::cerr << "JUMP/JUMPI at " << (curr - bytecode.cbegin()) << " not preceded by PUSH\n"; + std::exit(1); + } + + default: + break; + } + } +} std::unique_ptr Compiler::compile(const dev::bytes& bytecode) { @@ -52,23 +163,77 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto mainFuncType = FunctionType::get(llvm::Type::getInt32Ty(context), false); auto mainFunc = Function::Create(mainFuncType, Function::ExternalLinkage, "main", module.get()); - auto entryBlock = BasicBlock::Create(context, "entry", mainFunc); - builder.SetInsertPoint(entryBlock); - // Init stack and memory auto stack = Stack(builder, module.get()); auto memory = Memory(builder, module.get()); auto ext = Ext(builder); + // Create the basic blocks. + auto entryBlock = BasicBlock::Create(context, "entry", mainFunc); + basicBlocks[0] = entryBlock; + createBasicBlocks(bytecode); + + BasicBlock* currentBlock = nullptr; + for (auto pc = bytecode.cbegin(); pc != bytecode.cend(); ++pc) { using dev::eth::Instruction; + ProgramCounter currentPC = pc - bytecode.cbegin(); + + auto blockIter = basicBlocks.find(currentPC); + if (blockIter != basicBlocks.end()) + { + auto nextBlock = blockIter->second; + if (currentBlock != nullptr) + { + // Terminate the current block by jumping to the next one. + builder.CreateBr(nextBlock); + } + // Insert the next block into the main function. + if (nextBlock != entryBlock) + mainFunc->getBasicBlockList().push_back(nextBlock); + builder.SetInsertPoint(nextBlock); + currentBlock = nextBlock; + } + + assert(currentBlock != nullptr); + auto inst = static_cast(*pc); switch (inst) { + case Instruction::JUMP: + { + // The target address is computed at compile time, + // just pop it without looking... + stack.pop(); + + auto targetBlock = jumpTargets[currentPC]; + builder.CreateBr(targetBlock); + + currentBlock = nullptr; + break; + } + + case Instruction::JUMPI: + { + assert(pc + 1 < bytecode.cend()); + + // The target address is computed at compile time, + // just pop it without looking... + stack.pop(); + + auto cond = stack.pop(); + auto targetBlock = jumpTargets[currentPC]; + auto followBlock = basicBlocks[currentPC + 1]; + builder.CreateCondBr(cond, targetBlock, followBlock); + + currentBlock = nullptr; + break; + } + case Instruction::ADD: { auto lhs = stack.pop(); diff --git a/evmcc/Compiler.h b/evmcc/Compiler.h index 5a07e685d..6e9fd8443 100644 --- a/evmcc/Compiler.h +++ b/evmcc/Compiler.h @@ -12,10 +12,26 @@ class Compiler { public: + using ProgramCounter = uint64_t; + Compiler(); std::unique_ptr compile(const dev::bytes& bytecode); +private: + + llvm::BasicBlock* getOrCreateBasicBlockAtPC(ProgramCounter pc); + void createBasicBlocks(const dev::bytes& bytecode); + + /** + * Maps a program counter pc to a basic block which starts at pc (if any). + */ + std::map basicBlocks; + + /** + * Maps a pc at which there is a JUMP or JUMPI to the target block of the jump. + */ + std::map jumpTargets; }; } From d11127c94d8900b84983339eb0d1d487a2643621 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Thu, 2 Oct 2014 11:14:09 +0200 Subject: [PATCH 034/641] Added Module* constructor argument to Memory and Ext. --- evmcc/Compiler.cpp | 11 +++++------ evmcc/Ext.cpp | 5 ++--- evmcc/Ext.h | 4 ++-- evmcc/Memory.cpp | 4 +--- evmcc/Memory.h | 2 +- 5 files changed, 11 insertions(+), 15 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 0dae87213..6c5229056 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -166,17 +166,16 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto mainFuncType = FunctionType::get(builder.getInt64Ty(), false); auto mainFunc = Function::Create(mainFuncType, Function::ExternalLinkage, "main", module.get()); - // Init stack and memory - auto stack = Stack(builder, module.get()); - auto memory = Memory(builder); - - auto ext = Ext(builder); - // Create the basic blocks. auto entryBlock = BasicBlock::Create(context, "entry", mainFunc); basicBlocks[0] = entryBlock; createBasicBlocks(bytecode); + // Init runtime structures. + auto stack = Stack(builder, module.get()); + auto memory = Memory(builder, module.get()); + auto ext = Ext(builder, module.get()); + auto userRet = false; auto finished = false; diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index 0c38f73d3..e3bb17af6 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -43,10 +43,9 @@ struct ExtData const byte* calldata; }; -Ext::Ext(llvm::IRBuilder<>& _builder) +Ext::Ext(llvm::IRBuilder<>& _builder, llvm::Module* module) : m_builder(_builder) { - auto module = m_builder.GetInsertBlock()->getParent()->getParent(); auto&& ctx = _builder.getContext(); auto i256Ty = m_builder.getIntNTy(256); @@ -148,4 +147,4 @@ EXPORT void ext_calldataload(i256* _index, i256* _value) } -} \ No newline at end of file +} diff --git a/evmcc/Ext.h b/evmcc/Ext.h index a579dca81..8c08acdfe 100644 --- a/evmcc/Ext.h +++ b/evmcc/Ext.h @@ -13,7 +13,7 @@ namespace evmcc class Ext { public: - Ext(llvm::IRBuilder<>& _builder); + Ext(llvm::IRBuilder<>& _builder, llvm::Module* module); static void init(std::unique_ptr _ext); llvm::Value* store(llvm::Value* _index); @@ -43,4 +43,4 @@ private: }; -} \ No newline at end of file +} diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index 2a1a0f727..fd7727b59 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -26,13 +26,11 @@ using MemoryImpl = dev::bytes; static MemoryImpl* evmccrt_memory; -Memory::Memory(llvm::IRBuilder<>& _builder) +Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* module) : m_builder(_builder) { auto voidTy = m_builder.getVoidTy(); auto i64Ty = m_builder.getInt64Ty(); - auto module = _builder.GetInsertBlock()->getParent()->getParent(); - auto memRequireTy = llvm::FunctionType::get(m_builder.getInt8PtrTy(), i64Ty, false); m_memRequire = llvm::Function::Create(memRequireTy, diff --git a/evmcc/Memory.h b/evmcc/Memory.h index b36386325..87ce27ed0 100644 --- a/evmcc/Memory.h +++ b/evmcc/Memory.h @@ -10,7 +10,7 @@ namespace evmcc class Memory { public: - Memory(llvm::IRBuilder<>& _builder); + Memory(llvm::IRBuilder<>& _builder, llvm::Module* module); static const dev::bytes& init(); From 0d283dfa7c62811400e219353a39731fd3892c7c Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Thu, 2 Oct 2014 11:45:54 +0200 Subject: [PATCH 035/641] fixed implementation of JUMPI (cond casted to bool) --- evmcc/Compiler.cpp | 76 ++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 39 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 6c5229056..1ce211e98 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -169,6 +169,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) // Create the basic blocks. auto entryBlock = BasicBlock::Create(context, "entry", mainFunc); basicBlocks[0] = entryBlock; + builder.SetInsertPoint(entryBlock); createBasicBlocks(bytecode); // Init runtime structures. @@ -179,7 +180,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto userRet = false; auto finished = false; - BasicBlock* currentBlock = nullptr; + BasicBlock* currentBlock = entryBlock; for (auto pc = bytecode.cbegin(); pc != bytecode.cend(); ++pc) { @@ -188,17 +189,13 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) ProgramCounter currentPC = pc - bytecode.cbegin(); auto blockIter = basicBlocks.find(currentPC); - if (blockIter != basicBlocks.end()) + if (currentPC > 0 && blockIter != basicBlocks.end()) { auto nextBlock = blockIter->second; - if (currentBlock != nullptr) - { - // Terminate the current block by jumping to the next one. - builder.CreateBr(nextBlock); - } + // Terminate the current block by jumping to the next one. + builder.CreateBr(nextBlock); // Insert the next block into the main function. - if (nextBlock != entryBlock) - mainFunc->getBasicBlockList().push_back(nextBlock); + mainFunc->getBasicBlockList().push_back(nextBlock); builder.SetInsertPoint(nextBlock); currentBlock = nextBlock; } @@ -209,36 +206,6 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) switch (inst) { - case Instruction::JUMP: - { - // The target address is computed at compile time, - // just pop it without looking... - stack.pop(); - - auto targetBlock = jumpTargets[currentPC]; - builder.CreateBr(targetBlock); - - currentBlock = nullptr; - break; - } - - case Instruction::JUMPI: - { - assert(pc + 1 < bytecode.cend()); - - // The target address is computed at compile time, - // just pop it without looking... - stack.pop(); - - auto cond = stack.pop(); - auto targetBlock = jumpTargets[currentPC]; - auto followBlock = basicBlocks[currentPC + 1]; - builder.CreateCondBr(cond, targetBlock, followBlock); - - currentBlock = nullptr; - break; - } - case Instruction::ADD: { auto lhs = stack.pop(); @@ -464,6 +431,37 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::JUMP: + { + // The target address is computed at compile time, + // just pop it without looking... + stack.pop(); + + auto targetBlock = jumpTargets[currentPC]; + builder.CreateBr(targetBlock); + + currentBlock = nullptr; + break; + } + + case Instruction::JUMPI: + { + assert(pc + 1 < bytecode.cend()); + + // The target address is computed at compile time, + // just pop it without looking... + stack.pop(); + + auto top = stack.pop(); + auto cond = builder.CreateTrunc(top, builder.getInt1Ty(), "cond"); + auto targetBlock = jumpTargets[currentPC]; + auto followBlock = basicBlocks[currentPC + 1]; + builder.CreateCondBr(cond, targetBlock, followBlock); + + currentBlock = nullptr; + break; + } + case Instruction::ADDRESS: { auto value = ext.address(); From d843ec660ad0300e6a63d8a7930dcb5abf05984f Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Thu, 2 Oct 2014 12:22:47 +0200 Subject: [PATCH 036/641] fixes for JUMP/JUMPI (generating final basic block) implementation of NOT --- evmcc/Compiler.cpp | 35 +++++++++++++++++++++++++++++++---- evmcc/bytecode/if1.evm | 1 + evmcc/lll/if1.asm | 21 +++++++++++++++++++++ evmcc/lll/if1.lll | 5 +++++ 4 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 evmcc/bytecode/if1.evm create mode 100644 evmcc/lll/if1.asm create mode 100644 evmcc/lll/if1.lll diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 1ce211e98..d5f39e053 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -60,6 +60,8 @@ llvm::BasicBlock* Compiler::getOrCreateBasicBlockAtPC(ProgramCounter pc) void Compiler::createBasicBlocks(const dev::bytes& bytecode) { + getOrCreateBasicBlockAtPC(0); + for (auto curr = bytecode.cbegin(); curr != bytecode.cend(); ++curr) { using dev::eth::Instruction; @@ -168,7 +170,6 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) // Create the basic blocks. auto entryBlock = BasicBlock::Create(context, "entry", mainFunc); - basicBlocks[0] = entryBlock; builder.SetInsertPoint(entryBlock); createBasicBlocks(bytecode); @@ -189,11 +190,12 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) ProgramCounter currentPC = pc - bytecode.cbegin(); auto blockIter = basicBlocks.find(currentPC); - if (currentPC > 0 && blockIter != basicBlocks.end()) + if (blockIter != basicBlocks.end()) { auto nextBlock = blockIter->second; // Terminate the current block by jumping to the next one. - builder.CreateBr(nextBlock); + if (currentBlock != nullptr) + builder.CreateBr(nextBlock); // Insert the next block into the main function. mainFunc->getBasicBlockList().push_back(nextBlock); builder.SetInsertPoint(nextBlock); @@ -284,6 +286,16 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::NOT: + { + auto top = stack.pop(); + auto zero = ConstantInt::get(Types.word256, 0); + auto nonzero = builder.CreateICmpNE(top, zero, "nonzero"); + auto result = builder.CreateZExt(nonzero, Types.word256); + stack.push(result); + break; + } + case Instruction::POP: { stack.pop(); @@ -453,7 +465,8 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) stack.pop(); auto top = stack.pop(); - auto cond = builder.CreateTrunc(top, builder.getInt1Ty(), "cond"); + auto zero = ConstantInt::get(Types.word256, 0); + auto cond = builder.CreateICmpNE(top, zero, "nonzero"); auto targetBlock = jumpTargets[currentPC]; auto followBlock = basicBlocks[currentPC + 1]; builder.CreateCondBr(cond, targetBlock, followBlock); @@ -551,6 +564,20 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) } } + // Generate final basic block (may be jumped to). + auto finalPC = bytecode.size(); + auto it = basicBlocks.find(finalPC); + if (it != basicBlocks.end()) + { + auto finalBlock = it->second; + + if (currentBlock != nullptr) + builder.CreateBr(finalBlock); + + mainFunc->getBasicBlockList().push_back(finalBlock); + builder.SetInsertPoint(finalBlock); + } + if (!userRet) builder.CreateRet(builder.getInt64(0)); diff --git a/evmcc/bytecode/if1.evm b/evmcc/bytecode/if1.evm new file mode 100644 index 000000000..ee9009294 --- /dev/null +++ b/evmcc/bytecode/if1.evm @@ -0,0 +1 @@ +600160805460006080530b6016596003608054601b586002608054 diff --git a/evmcc/lll/if1.asm b/evmcc/lll/if1.asm new file mode 100644 index 000000000..4a938adce --- /dev/null +++ b/evmcc/lll/if1.asm @@ -0,0 +1,21 @@ +.code: + PUSH 1 + PUSH 128 + MSTORE + PUSH 0 + PUSH 128 + MLOAD + GT + PUSH [tag0] + JUMPI + PUSH 3 + PUSH 128 + MSTORE + PUSH [tag1] + JUMP +tag0: + PUSH 2 + PUSH 128 + MSTORE +tag1: + diff --git a/evmcc/lll/if1.lll b/evmcc/lll/if1.lll new file mode 100644 index 000000000..a807b697d --- /dev/null +++ b/evmcc/lll/if1.lll @@ -0,0 +1,5 @@ +{ + [i] 1 + + ( if (> @i 0) [i] 2 [i] 3 ) +} \ No newline at end of file From 01cc09a2796e08b054d8bace30dea1d0fa1551ad Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Thu, 2 Oct 2014 12:36:12 +0200 Subject: [PATCH 037/641] fixed implementation of NOT --- evmcc/Compiler.cpp | 4 ++-- evmcc/bytecode/when1.evm | 1 + evmcc/lll/when1.asm | 10 ++++++++++ evmcc/lll/when1.lll | 2 ++ 4 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 evmcc/bytecode/when1.evm create mode 100644 evmcc/lll/when1.asm create mode 100644 evmcc/lll/when1.lll diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index d5f39e053..f327f86ed 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -290,8 +290,8 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) { auto top = stack.pop(); auto zero = ConstantInt::get(Types.word256, 0); - auto nonzero = builder.CreateICmpNE(top, zero, "nonzero"); - auto result = builder.CreateZExt(nonzero, Types.word256); + auto iszero = builder.CreateICmpEQ(top, zero, "iszero"); + auto result = builder.CreateZExt(iszero, Types.word256); stack.push(result); break; } diff --git a/evmcc/bytecode/when1.evm b/evmcc/bytecode/when1.evm new file mode 100644 index 000000000..303b02623 --- /dev/null +++ b/evmcc/bytecode/when1.evm @@ -0,0 +1 @@ +60010f600b59600d608054 diff --git a/evmcc/lll/when1.asm b/evmcc/lll/when1.asm new file mode 100644 index 000000000..01d41c266 --- /dev/null +++ b/evmcc/lll/when1.asm @@ -0,0 +1,10 @@ +.code: + PUSH 1 + NOT + PUSH [tag0] + JUMPI + PUSH 13 + PUSH 128 + MSTORE +tag0: + diff --git a/evmcc/lll/when1.lll b/evmcc/lll/when1.lll new file mode 100644 index 000000000..990a6e64a --- /dev/null +++ b/evmcc/lll/when1.lll @@ -0,0 +1,2 @@ +(when (> 1 0) [i] 13) + \ No newline at end of file From e5ff13180c7ed268d0b4b9b2279446d7fe129622 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 2 Oct 2014 13:04:06 +0200 Subject: [PATCH 038/641] BALANCE --- evmcc/Compiler.cpp | 8 ++++++++ evmcc/Ext.cpp | 23 +++++++++++++++++++++++ evmcc/Ext.h | 5 +++++ evmcc/bytecode/ext_test.evm | 2 +- evmcc/lll/ext_test.lll | 1 + 5 files changed, 38 insertions(+), 1 deletion(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index c55b33cc6..0a9c50fc6 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -306,6 +306,14 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::BALANCE: + { + auto address = stack.pop(); + auto value = ext.balance(address); + stack.push(value); + break; + } + case Instruction::CALLER: { auto value = ext.caller(); diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index 0c38f73d3..a9013cbc5 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -3,6 +3,7 @@ #include #include +#include #include "Utils.h" @@ -15,6 +16,7 @@ using namespace llvm; using llvm::types::i; using Linkage = llvm::GlobalValue::LinkageTypes; +using dev::h256; namespace evmcc { @@ -70,6 +72,8 @@ Ext::Ext(llvm::IRBuilder<>& _builder) m_store = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_store", module); m_setStore = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_setStore", module); m_calldataload = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_calldataload", module); + m_balance = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_balance", module); + m_bswap = Intrinsic::getDeclaration(module, Intrinsic::bswap, i256Ty); m_builder.CreateCall(m_init, m_data); } @@ -108,6 +112,19 @@ Value* Ext::calldataload(Value* _index) return m_builder.CreateLoad(m_args[1]); } +Value* Ext::bswap(Value* _value) +{ + return m_builder.CreateCall(m_bswap, _value); +} + +Value* Ext::balance(Value* _address) +{ + auto address = bswap(_address); // to BigEndian // TODO: I don't get it. It seems not needed + m_builder.CreateStore(address, m_args[0]); + m_builder.CreateCall(m_balance, m_args); + return m_builder.CreateLoad(m_args[1]); +} + extern "C" { @@ -146,6 +163,12 @@ EXPORT void ext_calldataload(i256* _index, i256* _value) // TODO: It all can be done by adding padding to data or by using min() algorithm without branch } +EXPORT void ext_balance(h256* _address, i256* _value) +{ + auto u = g_ext->balance(dev::right160(*_address)); + *_value = eth2llvm(u); +} + } } \ No newline at end of file diff --git a/evmcc/Ext.h b/evmcc/Ext.h index a579dca81..1685ba259 100644 --- a/evmcc/Ext.h +++ b/evmcc/Ext.h @@ -26,11 +26,14 @@ public: llvm::Value* calldatasize(); llvm::Value* gasprice(); + llvm::Value* balance(llvm::Value* _address); llvm::Value* calldataload(llvm::Value* _index); private: llvm::Value* getDataElem(unsigned _index, const llvm::Twine& _name = ""); + llvm::Value* bswap(llvm::Value*); + private: llvm::IRBuilder<>& m_builder; @@ -40,6 +43,8 @@ private: llvm::Function* m_store; llvm::Function* m_setStore; llvm::Function* m_calldataload; + llvm::Function* m_balance; + llvm::Function* m_bswap; }; diff --git a/evmcc/bytecode/ext_test.evm b/evmcc/bytecode/ext_test.evm index 5bcc94ba1..cdd04807f 100644 --- a/evmcc/bytecode/ext_test.evm +++ b/evmcc/bytecode/ext_test.evm @@ -1 +1 @@ -30333234363a600035602635601335380060016002f2 +3031333234363a600035602635601335380060016002f2 diff --git a/evmcc/lll/ext_test.lll b/evmcc/lll/ext_test.lll index f32bfb440..b0f3a4adb 100644 --- a/evmcc/lll/ext_test.lll +++ b/evmcc/lll/ext_test.lll @@ -1,6 +1,7 @@ (asm ADDRESS +BALANCE CALLER ORIGIN CALLVALUE From 8df1050fcbb2e0aa028a610cb2395e8caf5b3cf0 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Thu, 2 Oct 2014 13:35:04 +0200 Subject: [PATCH 039/641] - implemented LT, GT - new tests for jumps and comparisons --- evmcc/Compiler.cpp | 20 ++++++++++++++++++++ evmcc/bytecode/for1.evm | 1 + evmcc/bytecode/for2.evm | 1 + evmcc/lll/for1.lll | 3 +++ evmcc/lll/for2.lll | 3 +++ 5 files changed, 28 insertions(+) create mode 100644 evmcc/bytecode/for1.evm create mode 100644 evmcc/bytecode/for2.evm create mode 100644 evmcc/lll/for1.lll create mode 100644 evmcc/lll/for2.lll diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index f327f86ed..bb4d65971 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -286,6 +286,26 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::LT: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res1 = builder.CreateICmpULT(lhs, rhs); + auto res256 = builder.CreateZExt(res1, Types.word256); + stack.push(res256); + break; + } + + case Instruction::GT: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res1 = builder.CreateICmpUGT(lhs, rhs); + auto res256 = builder.CreateZExt(res1, Types.word256); + stack.push(res256); + break; + } + case Instruction::NOT: { auto top = stack.pop(); diff --git a/evmcc/bytecode/for1.evm b/evmcc/bytecode/for1.evm new file mode 100644 index 000000000..f8e65cbf2 --- /dev/null +++ b/evmcc/bytecode/for1.evm @@ -0,0 +1 @@ +600a60805460006080530b0f60255960a0536080530160a054600160805303608054600558 diff --git a/evmcc/bytecode/for2.evm b/evmcc/bytecode/for2.evm new file mode 100644 index 000000000..628297778 --- /dev/null +++ b/evmcc/bytecode/for2.evm @@ -0,0 +1 @@ +6000608054600a6080530a0f60255960a0536080530160a054600160805301608054600558 diff --git a/evmcc/lll/for1.lll b/evmcc/lll/for1.lll new file mode 100644 index 000000000..419fc9b54 --- /dev/null +++ b/evmcc/lll/for1.lll @@ -0,0 +1,3 @@ +(for [i]:10 (> @i 0) [i](- @i 1) + [j](+ @i @j) +) diff --git a/evmcc/lll/for2.lll b/evmcc/lll/for2.lll new file mode 100644 index 000000000..de17d65ac --- /dev/null +++ b/evmcc/lll/for2.lll @@ -0,0 +1,3 @@ +(for [i]:0 (< @i 10) [i](+ @i 1) + [j](+ @i @j) +) From 9479a70b00bf88e18047565ec54cf282400c0318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 2 Oct 2014 13:58:57 +0200 Subject: [PATCH 040/641] Block Information instructions: PREVHASH, COINBASE, TIMESTAMP, NUMBER, DIFFICULTY, GASLIMIT --- evmcc/Compiler.cpp | 44 +++++++++++++++++++++++++++++++++- evmcc/ExecutionEngine.cpp | 6 +++++ evmcc/Ext.cpp | 48 +++++++++++++++++++++++++++---------- evmcc/Ext.h | 6 +++++ evmcc/bytecode/ext_test.evm | 2 +- evmcc/lll/ext_test.lll | 7 ++++++ 6 files changed, 99 insertions(+), 14 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index ccdf0b951..39483bc7f 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -183,7 +183,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) BasicBlock* currentBlock = entryBlock; - for (auto pc = bytecode.cbegin(); pc != bytecode.cend(); ++pc) + for (auto pc = bytecode.cbegin(); pc != bytecode.cend() && !finished; ++pc) { using dev::eth::Instruction; @@ -540,6 +540,48 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::PREVHASH: + { + auto value = ext.prevhash(); + stack.push(value); + break; + } + + case Instruction::COINBASE: + { + auto value = ext.coinbase(); + stack.push(value); + break; + } + + case Instruction::TIMESTAMP: + { + auto value = ext.timestamp(); + stack.push(value); + break; + } + + case Instruction::NUMBER: + { + auto value = ext.number(); + stack.push(value); + break; + } + + case Instruction::DIFFICULTY: + { + auto value = ext.difficulty(); + stack.push(value); + break; + } + + case Instruction::GASLIMIT: + { + auto value = ext.gaslimit(); + stack.push(value); + break; + } + case Instruction::RETURN: { auto index = stack.pop(); diff --git a/evmcc/ExecutionEngine.cpp b/evmcc/ExecutionEngine.cpp index 4d847388e..b9a71827a 100644 --- a/evmcc/ExecutionEngine.cpp +++ b/evmcc/ExecutionEngine.cpp @@ -77,6 +77,12 @@ int ExecutionEngine::run(std::unique_ptr _module) ext->origin = dev::Address(101010101010101010); ext->value = 0xabcd; ext->gasPrice = 1002; + ext->previousBlock.hash = dev::u256(1003); + ext->currentBlock.coinbaseAddress = dev::Address(1004); + ext->currentBlock.timestamp = 1005; + ext->currentBlock.number = 1006; + ext->currentBlock.difficulty = 1007; + ext->currentBlock.gasLimit = 1008; std::string calldata = "Hello the Beautiful World of Ethereum!"; ext->data = calldata; Ext::init(std::move(ext)); diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index 6ae84a286..5690b8ccd 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -34,14 +34,20 @@ void Ext::init(std::unique_ptr _ext) g_ext = std::move(_ext); } -struct ExtData +struct ExtData { i256 address; i256 caller; i256 origin; i256 callvalue; - i256 gasprice; i256 calldatasize; + i256 gasprice; + i256 prevhash; + i256 coinbase; + i256 timestamp; + i256 number; + i256 difficulty; + i256 gaslimit; const byte* calldata; }; @@ -55,13 +61,19 @@ Ext::Ext(llvm::IRBuilder<>& _builder, llvm::Module* module) m_args[1] = m_builder.CreateAlloca(i256Ty, nullptr, "ext.value"); Type* elements[] = { - i256Ty, - i256Ty, - i256Ty, - i256Ty, - i256Ty, - i256Ty, - m_builder.getInt8PtrTy() + i256Ty, // i256 address; + i256Ty, // i256 caller; + i256Ty, // i256 origin; + i256Ty, // i256 callvalue; + i256Ty, // i256 calldatasize; + i256Ty, // i256 gasprice; + i256Ty, // i256 prevhash; + i256Ty, // i256 coinbase; + i256Ty, // i256 timestamp; + i256Ty, // i256 number; + i256Ty, // i256 difficulty; + i256Ty, // i256 gaslimit; + //m_builder.getInt8PtrTy() }; auto extDataTy = StructType::create(elements, "ext.Data"); @@ -101,8 +113,14 @@ Value* Ext::address() { return getDataElem(0, "address"); } Value* Ext::caller() { return getDataElem(1, "caller"); } Value* Ext::origin() { return getDataElem(2, "origin"); } Value* Ext::callvalue() { return getDataElem(3, "callvalue"); } -Value* Ext::calldatasize() { return getDataElem(5, "calldatasize"); } -Value* Ext::gasprice() { return getDataElem(4, "gasprice"); } +Value* Ext::calldatasize() { return getDataElem(4, "calldatasize"); } +Value* Ext::gasprice() { return getDataElem(5, "gasprice"); } +Value* Ext::prevhash() { return getDataElem(6, "prevhash"); } +Value* Ext::coinbase() { return getDataElem(7, "coinbase"); } +Value* Ext::timestamp() { return getDataElem(8, "timestamp"); } +Value* Ext::number() { return getDataElem(9, "number"); } +Value* Ext::difficulty() { return getDataElem(10, "difficulty"); } +Value* Ext::gaslimit() { return getDataElem(11, "gaslimit"); } Value* Ext::calldataload(Value* _index) { @@ -135,7 +153,13 @@ EXPORT void ext_init(ExtData* _extData) _extData->callvalue = eth2llvm(g_ext->value); _extData->gasprice = eth2llvm(g_ext->gasPrice); _extData->calldatasize = eth2llvm(g_ext->data.size()); - _extData->calldata = g_ext->data.data(); + _extData->prevhash = eth2llvm(g_ext->previousBlock.hash); + _extData->coinbase = eth2llvm(fromAddress(g_ext->currentBlock.coinbaseAddress)); + _extData->timestamp = eth2llvm(g_ext->currentBlock.timestamp); + _extData->number = eth2llvm(g_ext->currentBlock.number); + _extData->difficulty = eth2llvm(g_ext->currentBlock.difficulty); + _extData->gaslimit = eth2llvm(g_ext->currentBlock.gasLimit); + //_extData->calldata = g_ext->data.data(); } EXPORT void ext_store(i256* _index, i256* _value) diff --git a/evmcc/Ext.h b/evmcc/Ext.h index 138028927..c44e5899b 100644 --- a/evmcc/Ext.h +++ b/evmcc/Ext.h @@ -25,6 +25,12 @@ public: llvm::Value* callvalue(); llvm::Value* calldatasize(); llvm::Value* gasprice(); + llvm::Value* prevhash(); + llvm::Value* coinbase(); + llvm::Value* timestamp(); + llvm::Value* number(); + llvm::Value* difficulty(); + llvm::Value* gaslimit(); llvm::Value* balance(llvm::Value* _address); llvm::Value* calldataload(llvm::Value* _index); diff --git a/evmcc/bytecode/ext_test.evm b/evmcc/bytecode/ext_test.evm index cdd04807f..c4a833296 100644 --- a/evmcc/bytecode/ext_test.evm +++ b/evmcc/bytecode/ext_test.evm @@ -1 +1 @@ -3031333234363a600035602635601335380060016002f2 +3031333234363a40414243444536600035602635601335380060016002f2 diff --git a/evmcc/lll/ext_test.lll b/evmcc/lll/ext_test.lll index b0f3a4adb..85c0b236e 100644 --- a/evmcc/lll/ext_test.lll +++ b/evmcc/lll/ext_test.lll @@ -7,6 +7,13 @@ ORIGIN CALLVALUE CALLDATASIZE GASPRICE +PREVHASH +COINBASE +TIMESTAMP +NUMBER +DIFFICULTY +GASLIMIT +CALLDATASIZE 0 CALLDATALOAD 38 From 397763be63e41d9593f1cbf5993309d75b6a3fee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 2 Oct 2014 14:18:50 +0200 Subject: [PATCH 041/641] PC instructions --- evmcc/Compiler.cpp | 7 +++++++ evmcc/bytecode/ext_test.evm | 2 +- evmcc/lll/ext_test.lll | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index e66aad25d..06dbbec72 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -495,6 +495,13 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::PC: + { + auto value = builder.getIntN(256, currentPC); + stack.push(value); + break; + } + case Instruction::ADDRESS: { auto value = ext.address(); diff --git a/evmcc/bytecode/ext_test.evm b/evmcc/bytecode/ext_test.evm index c4a833296..d1e373df0 100644 --- a/evmcc/bytecode/ext_test.evm +++ b/evmcc/bytecode/ext_test.evm @@ -1 +1 @@ -3031333234363a40414243444536600035602635601335380060016002f2 +5a3031333234363a4041424344455a36600035602635601335380060016002f2 diff --git a/evmcc/lll/ext_test.lll b/evmcc/lll/ext_test.lll index 85c0b236e..1a1dde653 100644 --- a/evmcc/lll/ext_test.lll +++ b/evmcc/lll/ext_test.lll @@ -1,5 +1,6 @@ (asm +PC ADDRESS BALANCE CALLER @@ -13,6 +14,7 @@ TIMESTAMP NUMBER DIFFICULTY GASLIMIT +PC CALLDATASIZE 0 CALLDATALOAD From 7c46d7946c749f73ee27e52f9aebf5276a42dffd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 2 Oct 2014 15:03:59 +0200 Subject: [PATCH 042/641] Bitwise operators: AND, OR, XOR --- evmcc/Compiler.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 06dbbec72..2f15d087d 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -315,6 +315,33 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) stack.push(result); break; } + + case Instruction::AND: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = builder.CreateAnd(lhs, rhs); + stack.push(res); + break; + } + + case Instruction::OR: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = builder.CreateOr(lhs, rhs); + stack.push(res); + break; + } + + case Instruction::XOR: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = builder.CreateXor(lhs, rhs); + stack.push(res); + break; + } case Instruction::POP: { From b92c8a6c102120f9f64a1380c755b078bb1480fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 2 Oct 2014 15:44:00 +0200 Subject: [PATCH 043/641] TODO: implement BYTE --- evmcc/Compiler.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 2f15d087d..5b3da6a5c 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -343,6 +343,29 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::BYTE: + { + auto byteNum = stack.pop(); + + // TODO + //auto value = stack.pop(); + + /* + if (byteNum < 32) - use select + { + value <<= byteNum*8; + value >>= (31-byteNum)*8; + push value + } + else + { + push 0 + } + */ + + break; + } + case Instruction::POP: { stack.pop(); From b39692ba72061cb1db546a74a4a1830e67ef23b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 2 Oct 2014 17:30:39 +0200 Subject: [PATCH 044/641] BYTE instruction implementation (with bug on BYTE 0) --- evmcc/Compiler.cpp | 27 ++++++----- evmcc/bytecode/byte.evm | 1 + evmcc/lll/byte.lll | 105 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+), 11 deletions(-) create mode 100644 evmcc/bytecode/byte.evm create mode 100644 evmcc/lll/byte.lll diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 5b3da6a5c..4b22c0241 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -345,24 +345,29 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) case Instruction::BYTE: { - auto byteNum = stack.pop(); - - // TODO - //auto value = stack.pop(); + const auto byteNum = stack.pop(); + auto value = stack.pop(); /* if (byteNum < 32) - use select { - value <<= byteNum*8; - value >>= (31-byteNum)*8; - push value - } - else - { - push 0 + value <<= byteNum*8 + value >>= 31*8 + push value } + else push 0 */ + // TODO: Shifting by 0 gives wrong results as of this bug http://llvm.org/bugs/show_bug.cgi?id=16439 + + auto shbits = builder.CreateShl(byteNum, builder.getIntN(256, 3)); + value = builder.CreateShl(value, shbits); + value = builder.CreateLShr(value, builder.getIntN(256, 31 * 8)); + + auto byteNumValid = builder.CreateICmpULT(byteNum, builder.getIntN(256, 32)); + value = builder.CreateSelect(byteNumValid, value, builder.getIntN(256, 0)); + stack.push(value); + break; } diff --git a/evmcc/bytecode/byte.evm b/evmcc/bytecode/byte.evm new file mode 100644 index 000000000..ab63431ee --- /dev/null +++ b/evmcc/bytecode/byte.evm @@ -0,0 +1 @@ +7f112233445566778899001122334455667788990011223344556677889900aabb6000137f112233445566778899001122334455667788990011223344556677889900aabb6001137f112233445566778899001122334455667788990011223344556677889900aabb6002137f112233445566778899001122334455667788990011223344556677889900aabb6003137f112233445566778899001122334455667788990011223344556677889900aabb6004137f112233445566778899001122334455667788990011223344556677889900aabb6005137f112233445566778899001122334455667788990011223344556677889900aabb6006137f112233445566778899001122334455667788990011223344556677889900aabb6007137f112233445566778899001122334455667788990011223344556677889900aabb6008137f112233445566778899001122334455667788990011223344556677889900aabb6009137f112233445566778899001122334455667788990011223344556677889900aabb600a137f112233445566778899001122334455667788990011223344556677889900aabb600b137f112233445566778899001122334455667788990011223344556677889900aabb600c137f112233445566778899001122334455667788990011223344556677889900aabb600d137f112233445566778899001122334455667788990011223344556677889900aabb600e137f112233445566778899001122334455667788990011223344556677889900aabb600f137f112233445566778899001122334455667788990011223344556677889900aabb6010137f112233445566778899001122334455667788990011223344556677889900aabb6011137f112233445566778899001122334455667788990011223344556677889900aabb6012137f112233445566778899001122334455667788990011223344556677889900aabb6013137f112233445566778899001122334455667788990011223344556677889900aabb6014137f112233445566778899001122334455667788990011223344556677889900aabb6015137f112233445566778899001122334455667788990011223344556677889900aabb6016137f112233445566778899001122334455667788990011223344556677889900aabb6017137f112233445566778899001122334455667788990011223344556677889900aabb6018137f112233445566778899001122334455667788990011223344556677889900aabb6019137f112233445566778899001122334455667788990011223344556677889900aabb601a137f112233445566778899001122334455667788990011223344556677889900aabb601b137f112233445566778899001122334455667788990011223344556677889900aabb601c137f112233445566778899001122334455667788990011223344556677889900aabb601d137f112233445566778899001122334455667788990011223344556677889900aabb601e137f112233445566778899001122334455667788990011223344556677889900aabb601f137f112233445566778899001122334455667788990011223344556677889900aabb6020137f112233445566778899001122334455667788990011223344556677889900aabb6107de13 diff --git a/evmcc/lll/byte.lll b/evmcc/lll/byte.lll new file mode 100644 index 000000000..95b0f99dc --- /dev/null +++ b/evmcc/lll/byte.lll @@ -0,0 +1,105 @@ + +(asm +0x112233445566778899001122334455667788990011223344556677889900aabb +0 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +1 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +2 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +3 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +4 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +5 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +6 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +7 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +8 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +9 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +10 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +11 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +12 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +13 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +14 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +15 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +16 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +17 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +18 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +19 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +20 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +21 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +22 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +23 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +24 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +25 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +26 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +27 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +28 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +29 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +30 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +31 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +32 +BYTE +0x112233445566778899001122334455667788990011223344556677889900aabb +2014 +BYTE +) \ No newline at end of file From 24a99ef798cc9b4e14f1a5342359a435f5b589d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 3 Oct 2014 11:04:39 +0200 Subject: [PATCH 045/641] Runtime class that inits and keeps stack, memory and ExtVM interface --- evmcc/Compiler.cpp | 6 ++--- evmcc/ExecutionEngine.cpp | 12 +++++----- evmcc/Ext.cpp | 44 +++++++++++++++-------------------- evmcc/Memory.cpp | 31 +++++++----------------- evmcc/Memory.h | 2 -- evmcc/Runtime.cpp | 36 ++++++++++++++++++++++++++++ evmcc/Runtime.h | 35 ++++++++++++++++++++++++++++ evmcc/Stack.cpp | 14 +++++------ windows/evmcc.vcxproj | 2 ++ windows/evmcc.vcxproj.filters | 2 ++ 10 files changed, 118 insertions(+), 66 deletions(-) create mode 100644 evmcc/Runtime.cpp create mode 100644 evmcc/Runtime.h diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 4b22c0241..4b50b2302 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -351,9 +351,9 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) /* if (byteNum < 32) - use select { - value <<= byteNum*8 - value >>= 31*8 - push value + value <<= byteNum*8 + value >>= 31*8 + push value } else push 0 */ diff --git a/evmcc/ExecutionEngine.cpp b/evmcc/ExecutionEngine.cpp index b9a71827a..6983b9cda 100644 --- a/evmcc/ExecutionEngine.cpp +++ b/evmcc/ExecutionEngine.cpp @@ -13,8 +13,7 @@ #include #include -#include "Ext.h" -#include "Memory.h" +#include "Runtime.h" namespace evmcc { @@ -69,8 +68,7 @@ int ExecutionEngine::run(std::unique_ptr _module) _module.release(); // Successfully created llvm::ExecutionEngine takes ownership of the module exec->finalizeObject(); - auto&& memory = Memory::init(); - + // Create fake ExtVM interface auto ext = std::make_unique(); ext->myAddress = dev::Address(1122334455667788); ext->caller = dev::Address(0xfacefacefaceface); @@ -85,7 +83,9 @@ int ExecutionEngine::run(std::unique_ptr _module) ext->currentBlock.gasLimit = 1008; std::string calldata = "Hello the Beautiful World of Ethereum!"; ext->data = calldata; - Ext::init(std::move(ext)); + + // Init runtime + Runtime runtime(std::move(ext)); auto entryFunc = module->getFunction("main"); if (!entryFunc) @@ -101,7 +101,7 @@ int ExecutionEngine::run(std::unique_ptr _module) auto size = 0xFFFFFFFF & intResult; std::cout << "RETURN [ "; - for (dev::bytes::const_iterator it = memory.cbegin() + index, end = it + size; it != end; ++it) + for (dev::bytes::const_iterator it = Runtime::getMemory().cbegin() + index, end = it + size; it != end; ++it) std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)*it << " "; std::cout << "]"; diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index 5690b8ccd..0ec9c532a 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -5,7 +5,7 @@ #include #include -#include "Utils.h" +#include "Runtime.h" #ifdef _MSC_VER #define EXPORT __declspec(dllexport) @@ -27,13 +27,6 @@ inline dev::u256 fromAddress(dev::Address _a) return (dev::u160)_a; } -std::unique_ptr g_ext; - -void Ext::init(std::unique_ptr _ext) -{ - g_ext = std::move(_ext); -} - struct ExtData { i256 address; @@ -147,25 +140,26 @@ extern "C" EXPORT void ext_init(ExtData* _extData) { - _extData->address = eth2llvm(fromAddress(g_ext->myAddress)); - _extData->caller = eth2llvm(fromAddress(g_ext->caller)); - _extData->origin = eth2llvm(fromAddress(g_ext->origin)); - _extData->callvalue = eth2llvm(g_ext->value); - _extData->gasprice = eth2llvm(g_ext->gasPrice); - _extData->calldatasize = eth2llvm(g_ext->data.size()); - _extData->prevhash = eth2llvm(g_ext->previousBlock.hash); - _extData->coinbase = eth2llvm(fromAddress(g_ext->currentBlock.coinbaseAddress)); - _extData->timestamp = eth2llvm(g_ext->currentBlock.timestamp); - _extData->number = eth2llvm(g_ext->currentBlock.number); - _extData->difficulty = eth2llvm(g_ext->currentBlock.difficulty); - _extData->gaslimit = eth2llvm(g_ext->currentBlock.gasLimit); - //_extData->calldata = g_ext->data.data(); + auto&& ext = Runtime::getExt(); + _extData->address = eth2llvm(fromAddress(ext.myAddress)); + _extData->caller = eth2llvm(fromAddress(ext.caller)); + _extData->origin = eth2llvm(fromAddress(ext.origin)); + _extData->callvalue = eth2llvm(ext.value); + _extData->gasprice = eth2llvm(ext.gasPrice); + _extData->calldatasize = eth2llvm(ext.data.size()); + _extData->prevhash = eth2llvm(ext.previousBlock.hash); + _extData->coinbase = eth2llvm(fromAddress(ext.currentBlock.coinbaseAddress)); + _extData->timestamp = eth2llvm(ext.currentBlock.timestamp); + _extData->number = eth2llvm(ext.currentBlock.number); + _extData->difficulty = eth2llvm(ext.currentBlock.difficulty); + _extData->gaslimit = eth2llvm(ext.currentBlock.gasLimit); + //_extData->calldata = ext.data.data(); } EXPORT void ext_store(i256* _index, i256* _value) { auto index = llvm2eth(*_index); - auto value = g_ext->store(index); + auto value = Runtime::getExt().store(index); *_value = eth2llvm(value); } @@ -173,7 +167,7 @@ EXPORT void ext_setStore(i256* _index, i256* _value) { auto index = llvm2eth(*_index); auto value = llvm2eth(*_value); - g_ext->setStore(index, value); + Runtime::getExt().setStore(index, value); } EXPORT void ext_calldataload(i256* _index, i256* _value) @@ -182,13 +176,13 @@ EXPORT void ext_calldataload(i256* _index, i256* _value) assert(index + 31 > index); // TODO: Handle large index auto b = reinterpret_cast(_value); for (size_t i = index, j = 31; i <= index + 31; ++i, --j) - b[j] = i < g_ext->data.size() ? g_ext->data[i] : 0; + b[j] = i < Runtime::getExt().data.size() ? Runtime::getExt().data[i] : 0; // TODO: It all can be done by adding padding to data or by using min() algorithm without branch } EXPORT void ext_balance(h256* _address, i256* _value) { - auto u = g_ext->balance(dev::right160(*_address)); + auto u = Runtime::getExt().balance(dev::right160(*_address)); *_value = eth2llvm(u); } diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index fd7727b59..e3bbd5d40 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -10,7 +10,7 @@ #include -#include "Utils.h" +#include "Runtime.h" #ifdef _MSC_VER #define EXPORT __declspec(dllexport) @@ -21,11 +21,6 @@ namespace evmcc { -using MemoryImpl = dev::bytes; - -static MemoryImpl* evmccrt_memory; - - Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* module) : m_builder(_builder) { @@ -48,15 +43,6 @@ Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* module) "evmccrt_memory_dump", module); } -const dev::bytes& Memory::init() -{ - evmccrt_memory = new MemoryImpl(); - std::cerr << "MEMORY: create(), initial size = " << evmccrt_memory->size() - << std::endl; - - return *evmccrt_memory; -} - llvm::Value* Memory::loadWord(llvm::Value* _addr) { @@ -132,29 +118,30 @@ extern "C" EXPORT uint8_t* evmccrt_memory_require(uint64_t _index) { uint64_t requiredSize = (_index / 32 + 1) * 32; + auto&& memory = Runtime::getMemory(); - if (evmccrt_memory->size() < requiredSize) + if (memory.size() < requiredSize) { std::cerr << "MEMORY: current size: " << std::dec - << evmccrt_memory->size() << " bytes, required size: " + << memory.size() << " bytes, required size: " << requiredSize << " bytes" << std::endl; - evmccrt_memory->resize(requiredSize); + memory.resize(requiredSize); } - return evmccrt_memory->data(); + return memory.data(); } EXPORT uint64_t evmccrt_memory_size() { - return evmccrt_memory->size() / 32; + return Runtime::getMemory().size() / 32; } EXPORT void evmccrt_memory_dump(uint64_t _begin, uint64_t _end) { if (_end == 0) - _end = evmccrt_memory->size(); + _end = Runtime::getMemory().size(); std::cerr << "MEMORY: active size: " << std::dec << evmccrt_memory_size() << " words\n"; @@ -169,7 +156,7 @@ EXPORT void evmccrt_memory_dump(uint64_t _begin, uint64_t _end) if ((i - _begin) % 16 == 0) std::cerr << '\n' << std::dec << i << ": "; - uint8_t b = (*evmccrt_memory)[i]; + auto b = Runtime::getMemory()[i]; std::cerr << std::hex << std::setw(2) << static_cast(b) << ' '; } std::cerr << std::endl; diff --git a/evmcc/Memory.h b/evmcc/Memory.h index 87ce27ed0..da6662fef 100644 --- a/evmcc/Memory.h +++ b/evmcc/Memory.h @@ -12,8 +12,6 @@ class Memory public: Memory(llvm::IRBuilder<>& _builder, llvm::Module* module); - static const dev::bytes& init(); - llvm::Value* loadWord(llvm::Value* _addr); void storeWord(llvm::Value* _addr, llvm::Value* _word); void storeByte(llvm::Value* _addr, llvm::Value* _byte); diff --git a/evmcc/Runtime.cpp b/evmcc/Runtime.cpp new file mode 100644 index 000000000..9d0738f05 --- /dev/null +++ b/evmcc/Runtime.cpp @@ -0,0 +1,36 @@ + +#include "Runtime.h" + +namespace evmcc +{ + +static Runtime* g_runtime; + +Runtime::Runtime(std::unique_ptr _ext) + : m_ext(std::move(_ext)) +{ + assert(!g_runtime); + g_runtime = this; +} + +Runtime::~Runtime() +{ + g_runtime = nullptr; +} + +StackImpl& Runtime::getStack() +{ + return g_runtime->m_stack; +} + +MemoryImpl& Runtime::getMemory() +{ + return g_runtime->m_memory; +} + +dev::eth::ExtVMFace& Runtime::getExt() +{ + return *g_runtime->m_ext; +} + +} \ No newline at end of file diff --git a/evmcc/Runtime.h b/evmcc/Runtime.h new file mode 100644 index 000000000..71c917b9d --- /dev/null +++ b/evmcc/Runtime.h @@ -0,0 +1,35 @@ + +#pragma once + +#include + +#include + +#include "Utils.h" + +namespace evmcc +{ + +using StackImpl = std::vector; +using MemoryImpl = dev::bytes; + +class Runtime +{ +public: + Runtime(std::unique_ptr _ext); + ~Runtime(); + + Runtime(const Runtime&) = delete; + void operator=(const Runtime&) = delete; + + static StackImpl& getStack(); + static MemoryImpl& getMemory(); + static dev::eth::ExtVMFace& getExt(); + +private: + StackImpl m_stack; + MemoryImpl m_memory; + std::unique_ptr m_ext; +}; + +} \ No newline at end of file diff --git a/evmcc/Stack.cpp b/evmcc/Stack.cpp index 2e9bb495c..540c4bedc 100644 --- a/evmcc/Stack.cpp +++ b/evmcc/Stack.cpp @@ -9,7 +9,7 @@ #include -#include "Utils.h" +#include "Runtime.h" #ifdef _MSC_VER #define EXPORT __declspec(dllexport) @@ -20,9 +20,6 @@ namespace evmcc { -using StackImpl = std::vector; - - Stack::Stack(llvm::IRBuilder<>& _builder, llvm::Module* _module) : m_builder(_builder) { @@ -115,7 +112,8 @@ extern "C" EXPORT void* evmccrt_stack_create() { - auto stack = new StackImpl; + // TODO: Simplify stack pointer passing + auto stack = &Runtime::getStack(); std::cerr << "STACK create\n"; return stack; } @@ -130,7 +128,7 @@ EXPORT void evmccrt_stack_pop(StackImpl* _stack, i256* _outWord) { assert(!_stack->empty()); auto word = &_stack->back(); - debugStack("pop", *word); + //debugStack("pop", *word); _stack->pop_back(); *_outWord = *word; } @@ -139,7 +137,7 @@ EXPORT void evmccrt_stack_get(StackImpl* _stack, uint32_t _index, i256* _outWord { assert(_index < _stack->size()); auto word = _stack->rbegin() + _index; - debugStack("get", *word, _index); + //debugStack("get", *word, _index); *_outWord = *word; } @@ -147,7 +145,7 @@ EXPORT void evmccrt_stack_set(StackImpl* _stack, uint32_t _index, i256* _word) { assert(_index < _stack->size()); *(_stack->rbegin() + _index) = *_word; - debugStack("set", *_word, _index); + //debugStack("set", *_word, _index); } } // extern "C" diff --git a/windows/evmcc.vcxproj b/windows/evmcc.vcxproj index 7959c5a1b..c3add28cd 100644 --- a/windows/evmcc.vcxproj +++ b/windows/evmcc.vcxproj @@ -24,6 +24,7 @@ + @@ -32,6 +33,7 @@ + diff --git a/windows/evmcc.vcxproj.filters b/windows/evmcc.vcxproj.filters index 99c43b89b..de7fd20bf 100644 --- a/windows/evmcc.vcxproj.filters +++ b/windows/evmcc.vcxproj.filters @@ -8,6 +8,7 @@ + @@ -16,5 +17,6 @@ + \ No newline at end of file From 09341eaf84e1abe8a1dcebca6fababca335d8007 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 3 Oct 2014 11:21:07 +0200 Subject: [PATCH 046/641] Stack functions simplified --- evmcc/Stack.cpp | 61 +++++++++++++++++++------------------------------ evmcc/Stack.h | 2 +- 2 files changed, 25 insertions(+), 38 deletions(-) diff --git a/evmcc/Stack.cpp b/evmcc/Stack.cpp index 540c4bedc..ef99d603b 100644 --- a/evmcc/Stack.cpp +++ b/evmcc/Stack.cpp @@ -29,18 +29,14 @@ Stack::Stack(llvm::IRBuilder<>& _builder, llvm::Module* _module) auto i256PtrTy = i256Ty->getPointerTo(); auto voidTy = m_builder.getVoidTy(); - auto stackCreate = llvm::Function::Create(llvm::FunctionType::get(stackPtrTy, false), - llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_create", _module); - - llvm::Type* argsTypes[] = {stackPtrTy, i256PtrTy}; - auto funcType = llvm::FunctionType::get(voidTy, argsTypes, false); + auto funcType = llvm::FunctionType::get(voidTy, i256PtrTy, false); m_stackPush = llvm::Function::Create(funcType, llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_push", _module); m_stackPop = llvm::Function::Create(funcType, llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_pop", _module); - llvm::Type* getArgsTypes[] = {stackPtrTy, m_builder.getInt32Ty(), i256PtrTy}; + llvm::Type* getArgsTypes[] = {m_builder.getInt32Ty(), i256PtrTy}; auto getFuncType = llvm::FunctionType::get(voidTy, getArgsTypes, false); m_stackGet = llvm::Function::Create(getFuncType, llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_get", _module); @@ -48,37 +44,36 @@ Stack::Stack(llvm::IRBuilder<>& _builder, llvm::Module* _module) m_stackSet = llvm::Function::Create(getFuncType, llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_set", _module); - m_args[0] = m_builder.CreateCall(stackCreate, "stack.ptr"); - m_args[1] = m_builder.CreateAlloca(i256Ty, nullptr, "stack.val"); + m_stackVal = m_builder.CreateAlloca(i256Ty, nullptr, "stack.val"); } void Stack::push(llvm::Value* _value) { - m_builder.CreateStore(_value, m_args[1]); // copy value to memory - m_builder.CreateCall(m_stackPush, m_args); + m_builder.CreateStore(_value, m_stackVal); // copy value to memory + m_builder.CreateCall(m_stackPush, m_stackVal); } llvm::Value* Stack::pop() { - m_builder.CreateCall(m_stackPop, m_args); - return m_builder.CreateLoad(m_args[1]); + m_builder.CreateCall(m_stackPop, m_stackVal); + return m_builder.CreateLoad(m_stackVal); } llvm::Value* Stack::get(uint32_t _index) { - llvm::Value* args[] = {m_args[0], m_builder.getInt32(_index), m_args[1]}; + llvm::Value* args[] = {m_builder.getInt32(_index), m_stackVal}; m_builder.CreateCall(m_stackGet, args); - return m_builder.CreateLoad(m_args[1]); + return m_builder.CreateLoad(m_stackVal); } void Stack::set(uint32_t _index, llvm::Value* _value) { - m_builder.CreateStore(_value, m_args[1]); // copy value to memory - llvm::Value* args[] = {m_args[0], m_builder.getInt32(_index), m_args[1]}; + m_builder.CreateStore(_value, m_stackVal); // copy value to memory + llvm::Value* args[] = {m_builder.getInt32(_index), m_stackVal}; m_builder.CreateCall(m_stackSet, args); } @@ -110,41 +105,33 @@ extern "C" { using namespace evmcc; -EXPORT void* evmccrt_stack_create() -{ - // TODO: Simplify stack pointer passing - auto stack = &Runtime::getStack(); - std::cerr << "STACK create\n"; - return stack; -} - -EXPORT void evmccrt_stack_push(StackImpl* _stack, i256* _word) +EXPORT void evmccrt_stack_push(i256* _word) { - debugStack("push", *_word); - _stack->push_back(*_word); + //debugStack("push", *_word); + Runtime::getStack().push_back(*_word); } -EXPORT void evmccrt_stack_pop(StackImpl* _stack, i256* _outWord) +EXPORT void evmccrt_stack_pop(i256* _outWord) { - assert(!_stack->empty()); - auto word = &_stack->back(); + assert(!Runtime::getStack().empty()); + auto word = &Runtime::getStack().back(); //debugStack("pop", *word); - _stack->pop_back(); + Runtime::getStack().pop_back(); *_outWord = *word; } -EXPORT void evmccrt_stack_get(StackImpl* _stack, uint32_t _index, i256* _outWord) +EXPORT void evmccrt_stack_get(uint32_t _index, i256* _outWord) { - assert(_index < _stack->size()); - auto word = _stack->rbegin() + _index; + assert(_index < Runtime::getStack().size()); + auto word = Runtime::getStack().rbegin() + _index; //debugStack("get", *word, _index); *_outWord = *word; } -EXPORT void evmccrt_stack_set(StackImpl* _stack, uint32_t _index, i256* _word) +EXPORT void evmccrt_stack_set(uint32_t _index, i256* _word) { - assert(_index < _stack->size()); - *(_stack->rbegin() + _index) = *_word; + assert(_index < Runtime::getStack().size()); + *(Runtime::getStack().rbegin() + _index) = *_word; //debugStack("set", *_word, _index); } diff --git a/evmcc/Stack.h b/evmcc/Stack.h index a25de56e6..53e935a8a 100644 --- a/evmcc/Stack.h +++ b/evmcc/Stack.h @@ -19,7 +19,7 @@ public: private: llvm::IRBuilder<>& m_builder; - llvm::Value* m_args[2]; + llvm::Value* m_stackVal; llvm::Function* m_stackPush; llvm::Function* m_stackPop; llvm::Function* m_stackGet; From f34340d4c1c89ad92d8bbf88881f3b73aa0ab564 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Fri, 3 Oct 2014 11:30:15 +0200 Subject: [PATCH 047/641] - fixes for RETURN and STOP - codegen for SLT, SGT, EQ and NEG --- evmcc/Compiler.cpp | 83 +++++++++++++++++++++++++++++--------- evmcc/bytecode/return1.evm | 1 + evmcc/lll/return1.lll | 6 +++ 3 files changed, 71 insertions(+), 19 deletions(-) create mode 100644 evmcc/bytecode/return1.evm create mode 100644 evmcc/lll/return1.lll diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 4b22c0241..796db093e 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -61,6 +61,7 @@ llvm::BasicBlock* Compiler::getOrCreateBasicBlockAtPC(ProgramCounter pc) void Compiler::createBasicBlocks(const dev::bytes& bytecode) { getOrCreateBasicBlockAtPC(0); + getOrCreateBasicBlockAtPC(bytecode.size()); for (auto curr = bytecode.cbegin(); curr != bytecode.cend(); ++curr) { @@ -147,6 +148,18 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode) std::exit(1); } + case Instruction::RETURN: + case Instruction::STOP: + { + // Create a basic block starting at the following instruction. + if (curr + 1 < bytecode.cend()) + { + ProgramCounter nextPC = (curr + 1 - bytecode.cbegin()); + getOrCreateBasicBlockAtPC(nextPC); + } + break; + } + default: break; } @@ -178,12 +191,9 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto memory = Memory(builder, module.get()); auto ext = Ext(builder, module.get()); - auto userRet = false; - auto finished = false; - BasicBlock* currentBlock = entryBlock; - for (auto pc = bytecode.cbegin(); pc != bytecode.cend() && !finished; ++pc) + for (auto pc = bytecode.cbegin(); pc != bytecode.cend(); ++pc) { using dev::eth::Instruction; @@ -286,6 +296,15 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::NEG: + { + auto top = stack.pop(); + auto zero = ConstantInt::get(Types.word256, 0); + auto res = builder.CreateSub(zero, top); + stack.push(res); + break; + } + case Instruction::LT: { auto lhs = stack.pop(); @@ -306,6 +325,36 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::SLT: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res1 = builder.CreateICmpSLT(lhs, rhs); + auto res256 = builder.CreateZExt(res1, Types.word256); + stack.push(res256); + break; + } + + case Instruction::SGT: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res1 = builder.CreateICmpSGT(lhs, rhs); + auto res256 = builder.CreateZExt(res1, Types.word256); + stack.push(res256); + break; + } + + case Instruction::EQ: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res1 = builder.CreateICmpEQ(lhs, rhs); + auto res256 = builder.CreateZExt(res1, Types.word256); + stack.push(res256); + break; + } + case Instruction::NOT: { auto top = stack.pop(); @@ -682,36 +731,32 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) ret = builder.CreateOr(ret, size); builder.CreateRet(ret); - finished = true; - userRet = true; + currentBlock = nullptr; break; } case Instruction::STOP: { - finished = true; + builder.CreateRet(builder.getInt64(0)); + currentBlock = nullptr; break; } } } - // Generate final basic block (may be jumped to). + // Generate the final basic block. auto finalPC = bytecode.size(); auto it = basicBlocks.find(finalPC); - if (it != basicBlocks.end()) - { - auto finalBlock = it->second; + assert(it != basicBlocks.end()); + auto finalBlock = it->second; - if (currentBlock != nullptr) - builder.CreateBr(finalBlock); - - mainFunc->getBasicBlockList().push_back(finalBlock); - builder.SetInsertPoint(finalBlock); - } + if (currentBlock != nullptr) + builder.CreateBr(finalBlock); - if (!userRet) - builder.CreateRet(builder.getInt64(0)); + mainFunc->getBasicBlockList().push_back(finalBlock); + builder.SetInsertPoint(finalBlock); + builder.CreateRet(builder.getInt64(0)); return module; } diff --git a/evmcc/bytecode/return1.evm b/evmcc/bytecode/return1.evm new file mode 100644 index 000000000..8092cb007 --- /dev/null +++ b/evmcc/bytecode/return1.evm @@ -0,0 +1 @@ +600160805460006080530b601b59600160005460206000f2602a58602760005460206000f26002608054 diff --git a/evmcc/lll/return1.lll b/evmcc/lll/return1.lll new file mode 100644 index 000000000..159d15ca3 --- /dev/null +++ b/evmcc/lll/return1.lll @@ -0,0 +1,6 @@ +;; code should return 39 +;; i should remain 1 +{ + [i] 1 + ( if (> @i 0) { (return 39) [i] 2 } (return 1) ) +} \ No newline at end of file From cdebe9f9f72445a221a5e36d747c159ce39e5b34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 3 Oct 2014 13:19:35 +0200 Subject: [PATCH 048/641] CREATE instruction. Still needs some work with ExtVM interface. [#79510898] --- evmcc/Compiler.cpp | 11 +++++++++++ evmcc/Ext.cpp | 39 ++++++++++++++++++++++++++++++++++++- evmcc/Ext.h | 4 ++++ evmcc/bytecode/ext_test.evm | 2 +- evmcc/lll/ext_test.lll | 7 +++++++ 5 files changed, 61 insertions(+), 2 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 0c0076a80..acb7be26d 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -712,6 +712,17 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) stack.push(value); break; } + + case Instruction::CREATE: + { + auto endowment = stack.pop(); + auto initOff = stack.pop(); + auto initSize = stack.pop(); + + auto address = ext.create(endowment, initOff, initSize); + stack.push(address); + break; + } case Instruction::RETURN: { diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index 0ec9c532a..4ef0dc3f8 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -17,6 +17,7 @@ using namespace llvm; using llvm::types::i; using Linkage = llvm::GlobalValue::LinkageTypes; using dev::h256; +using dev::u256; namespace evmcc { @@ -52,6 +53,8 @@ Ext::Ext(llvm::IRBuilder<>& _builder, llvm::Module* module) auto i256Ty = m_builder.getIntNTy(256); m_args[0] = m_builder.CreateAlloca(i256Ty, nullptr, "ext.index"); m_args[1] = m_builder.CreateAlloca(i256Ty, nullptr, "ext.value"); + m_arg2 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg2"); + m_arg3 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg3"); Type* elements[] = { i256Ty, // i256 address; @@ -77,8 +80,10 @@ Ext::Ext(llvm::IRBuilder<>& _builder, llvm::Module* module) m_setStore = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_setStore", module); m_calldataload = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_calldataload", module); m_balance = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_balance", module); + m_create = Function::Create(TypeBuilder*, i<256>*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_create", module); m_bswap = Intrinsic::getDeclaration(module, Intrinsic::bswap, i256Ty); + m_builder.CreateCall(m_init, m_data); } @@ -129,12 +134,24 @@ Value* Ext::bswap(Value* _value) Value* Ext::balance(Value* _address) { - auto address = bswap(_address); // to BigEndian // TODO: I don't get it. It seems not needed + auto address = bswap(_address); // to BE m_builder.CreateStore(address, m_args[0]); m_builder.CreateCall(m_balance, m_args); return m_builder.CreateLoad(m_args[1]); } +Value* Ext::create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize) +{ + m_builder.CreateStore(_endowment, m_args[0]); + m_builder.CreateStore(_initOff, m_arg2); + m_builder.CreateStore(_initSize, m_arg3); + Value* args[] = {m_args[0], m_arg2, m_arg3, m_args[1]}; + m_builder.CreateCall(m_create, args); + Value* address = m_builder.CreateLoad(m_args[1]); + address = bswap(address); // to LE + return address; +} + extern "C" { @@ -186,6 +203,26 @@ EXPORT void ext_balance(h256* _address, i256* _value) *_value = eth2llvm(u); } +EXPORT void ext_create(i256* _endowment, i256* _initOff, i256* _initSize, h256* _address) +{ + auto&& ext = Runtime::getExt(); + auto endowment = llvm2eth(*_endowment); + auto initOff = static_cast(llvm2eth(*_initOff)); + auto initSize = static_cast(llvm2eth(*_initSize)); + + if (ext.balance(ext.myAddress) >= endowment) + { + ext.subBalance(endowment); + u256 gas; // TODO: Handle gas + auto&& initRef = dev::bytesConstRef(Runtime::getMemory().data() + initOff, initSize); + auto&& onOp = dev::bytesConstRef(); // TODO: Handle that thing + h256 address = ext.create(endowment, &gas, initRef, onOp); + *_address = address; + } + else + *_address = {}; +} + } } diff --git a/evmcc/Ext.h b/evmcc/Ext.h index c44e5899b..aa6016253 100644 --- a/evmcc/Ext.h +++ b/evmcc/Ext.h @@ -34,6 +34,7 @@ public: llvm::Value* balance(llvm::Value* _address); llvm::Value* calldataload(llvm::Value* _index); + llvm::Value* create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize); private: llvm::Value* getDataElem(unsigned _index, const llvm::Twine& _name = ""); @@ -44,12 +45,15 @@ private: llvm::IRBuilder<>& m_builder; llvm::Value* m_args[2]; + llvm::Value* m_arg2; + llvm::Value* m_arg3; llvm::Value* m_data; llvm::Function* m_init; llvm::Function* m_store; llvm::Function* m_setStore; llvm::Function* m_calldataload; llvm::Function* m_balance; + llvm::Function* m_create; llvm::Function* m_bswap; }; diff --git a/evmcc/bytecode/ext_test.evm b/evmcc/bytecode/ext_test.evm index d1e373df0..97ef267d6 100644 --- a/evmcc/bytecode/ext_test.evm +++ b/evmcc/bytecode/ext_test.evm @@ -1 +1 @@ -5a3031333234363a4041424344455a36600035602635601335380060016002f2 +5a3031333234363a4041424344455a36600035602635601335387f1111222233334444555566667777888899990000aaaabbbbccccddddeeeeffff600054602060006000f00060016002f2 diff --git a/evmcc/lll/ext_test.lll b/evmcc/lll/ext_test.lll index 1a1dde653..60a8bc332 100644 --- a/evmcc/lll/ext_test.lll +++ b/evmcc/lll/ext_test.lll @@ -23,6 +23,13 @@ CALLDATALOAD 19 CALLDATALOAD CODESIZE +0x1111222233334444555566667777888899990000aaaabbbbccccddddeeeeffff +0 +MSTORE +32 +0 +0 +CREATE STOP 1 2 From a33863d931cd999b759f99b92719bec674ec13c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 3 Oct 2014 15:19:47 +0200 Subject: [PATCH 049/641] CALL instruction. Still needs gas counting and callback support. [Delivers #79510898] --- evmcc/Compiler.cpp | 15 +++++++++++ evmcc/Ext.cpp | 53 +++++++++++++++++++++++++++++++++++-- evmcc/Ext.h | 6 +++++ evmcc/bytecode/ext_test.evm | 2 +- evmcc/lll/ext_test.lll | 8 ++++++ 5 files changed, 81 insertions(+), 3 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index acb7be26d..5227fa5cb 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -724,6 +724,21 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::CALL: + { + auto gas = stack.pop(); + auto receiveAddress = stack.pop(); + auto value = stack.pop(); + auto inOff = stack.pop(); + auto inSize = stack.pop(); + auto outOff = stack.pop(); + auto outSize = stack.pop(); + + auto ret = ext.call(gas, receiveAddress, value, inOff, inSize, outOff, outSize); + stack.push(ret); + break; + } + case Instruction::RETURN: { auto index = stack.pop(); diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index 4ef0dc3f8..e82a91ae9 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -51,10 +51,15 @@ Ext::Ext(llvm::IRBuilder<>& _builder, llvm::Module* module) auto&& ctx = _builder.getContext(); auto i256Ty = m_builder.getIntNTy(256); + auto i256PtrTy = i256Ty->getPointerTo(); m_args[0] = m_builder.CreateAlloca(i256Ty, nullptr, "ext.index"); m_args[1] = m_builder.CreateAlloca(i256Ty, nullptr, "ext.value"); m_arg2 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg2"); m_arg3 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg3"); + m_arg4 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg4"); + m_arg5 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg5"); + m_arg6 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg6"); + m_arg7 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg7"); Type* elements[] = { i256Ty, // i256 address; @@ -81,6 +86,8 @@ Ext::Ext(llvm::IRBuilder<>& _builder, llvm::Module* module) m_calldataload = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_calldataload", module); m_balance = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_balance", module); m_create = Function::Create(TypeBuilder*, i<256>*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_create", module); + Type* args[] = {i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy}; + m_call = Function::Create(FunctionType::get(m_builder.getVoidTy(), args, false), Linkage::ExternalLinkage, "ext_call", module); m_bswap = Intrinsic::getDeclaration(module, Intrinsic::bswap, i256Ty); @@ -152,6 +159,21 @@ Value* Ext::create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* return address; } +llvm::Value* Ext::call(llvm::Value* _gas, llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize) +{ + m_builder.CreateStore(_gas, m_args[0]); + auto receiveAddress = bswap(_receiveAddress); // to BE + m_builder.CreateStore(receiveAddress, m_arg2); + m_builder.CreateStore(_value, m_arg3); + m_builder.CreateStore(_inOff, m_arg4); + m_builder.CreateStore(_inSize, m_arg5); + m_builder.CreateStore(_outOff, m_arg6); + m_builder.CreateStore(_outSize, m_arg7); + llvm::Value* args[] = {m_args[0], m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_args[1]}; + m_builder.CreateCall(m_call, args); + return m_builder.CreateLoad(m_args[1]); +} + extern "C" { @@ -207,13 +229,13 @@ EXPORT void ext_create(i256* _endowment, i256* _initOff, i256* _initSize, h256* { auto&& ext = Runtime::getExt(); auto endowment = llvm2eth(*_endowment); - auto initOff = static_cast(llvm2eth(*_initOff)); - auto initSize = static_cast(llvm2eth(*_initSize)); if (ext.balance(ext.myAddress) >= endowment) { ext.subBalance(endowment); u256 gas; // TODO: Handle gas + auto initOff = static_cast(llvm2eth(*_initOff)); + auto initSize = static_cast(llvm2eth(*_initSize)); auto&& initRef = dev::bytesConstRef(Runtime::getMemory().data() + initOff, initSize); auto&& onOp = dev::bytesConstRef(); // TODO: Handle that thing h256 address = ext.create(endowment, &gas, initRef, onOp); @@ -223,6 +245,33 @@ EXPORT void ext_create(i256* _endowment, i256* _initOff, i256* _initSize, h256* *_address = {}; } + + +EXPORT void ext_call(i256* _gas, h256* _receiveAddress, i256* _value, i256* _inOff, i256* _inSize, i256* _outOff, i256* _outSize, i256* _ret) +{ + auto&& ext = Runtime::getExt(); + auto value = llvm2eth(*_value); + + auto ret = false; + if (ext.balance(ext.myAddress) >= value) + { + ext.subBalance(value); + auto gas = llvm2eth(*_gas); + auto receiveAddress = dev::right160(*_receiveAddress); + auto inOff = static_cast(llvm2eth(*_inOff)); + auto inSize = static_cast(llvm2eth(*_inSize)); + auto outOff = static_cast(llvm2eth(*_outOff)); + auto outSize = static_cast(llvm2eth(*_outSize)); + auto&& inRef = dev::bytesConstRef(Runtime::getMemory().data() + inOff, inSize); + auto&& outRef = dev::bytesConstRef(Runtime::getMemory().data() + outOff, outSize); + dev::eth::OnOpFunc onOp{}; // TODO: Handle that thing + auto ret = ext.call(receiveAddress, value, inRef, &gas, outRef, onOp, {}, receiveAddress); + } + + // m_gas += gas; // TODO: Handle gas + _ret->a = ret ? 1 : 0; +} + } } diff --git a/evmcc/Ext.h b/evmcc/Ext.h index aa6016253..88fad15a1 100644 --- a/evmcc/Ext.h +++ b/evmcc/Ext.h @@ -35,6 +35,7 @@ public: llvm::Value* balance(llvm::Value* _address); llvm::Value* calldataload(llvm::Value* _index); llvm::Value* create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize); + llvm::Value* call(llvm::Value* _gas, llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize); private: llvm::Value* getDataElem(unsigned _index, const llvm::Twine& _name = ""); @@ -47,6 +48,10 @@ private: llvm::Value* m_args[2]; llvm::Value* m_arg2; llvm::Value* m_arg3; + llvm::Value* m_arg4; + llvm::Value* m_arg5; + llvm::Value* m_arg6; + llvm::Value* m_arg7; llvm::Value* m_data; llvm::Function* m_init; llvm::Function* m_store; @@ -54,6 +59,7 @@ private: llvm::Function* m_calldataload; llvm::Function* m_balance; llvm::Function* m_create; + llvm::Function* m_call; llvm::Function* m_bswap; }; diff --git a/evmcc/bytecode/ext_test.evm b/evmcc/bytecode/ext_test.evm index 97ef267d6..e8da21f45 100644 --- a/evmcc/bytecode/ext_test.evm +++ b/evmcc/bytecode/ext_test.evm @@ -1 +1 @@ -5a3031333234363a4041424344455a36600035602635601335387f1111222233334444555566667777888899990000aaaabbbbccccddddeeeeffff600054602060006000f00060016002f2 +5a3031333234363a4041424344455a36600035602635601335387f1111222233334444555566667777888899990000aaaabbbbccccddddeeeeffff600054602060006000f06020600060206000600030610bb8f10060016002f2 diff --git a/evmcc/lll/ext_test.lll b/evmcc/lll/ext_test.lll index 60a8bc332..5e359cb7f 100644 --- a/evmcc/lll/ext_test.lll +++ b/evmcc/lll/ext_test.lll @@ -30,6 +30,14 @@ MSTORE 0 0 CREATE +32 +0 +32 +0 +0 +ADDRESS +3000 +CALL STOP 1 2 From 1835251b5249c37f9d317109a606096062a82853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 6 Oct 2014 09:42:19 +0200 Subject: [PATCH 050/641] SUICIDE instruction [Delivers #79510898] --- evmcc/Compiler.cpp | 7 +++++++ evmcc/Ext.cpp | 13 +++++++++++++ evmcc/Ext.h | 2 ++ evmcc/bytecode/ext_test.evm | 2 +- evmcc/lll/ext_test.lll | 3 ++- 5 files changed, 25 insertions(+), 2 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 5227fa5cb..48b74e501 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -150,6 +150,7 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode) case Instruction::RETURN: case Instruction::STOP: + case Instruction::SUICIDE: { // Create a basic block starting at the following instruction. if (curr + 1 < bytecode.cend()) @@ -761,6 +762,12 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::SUICIDE: + { + auto address = stack.pop(); + ext.suicide(address); + // Fall through + } case Instruction::STOP: { builder.CreateRet(builder.getInt64(0)); diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index e82a91ae9..9fad58fa7 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -85,6 +85,7 @@ Ext::Ext(llvm::IRBuilder<>& _builder, llvm::Module* module) m_setStore = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_setStore", module); m_calldataload = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_calldataload", module); m_balance = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_balance", module); + m_suicide = Function::Create(TypeBuilder*), true>::get(ctx), Linkage::ExternalLinkage, "ext_suicide", module); m_create = Function::Create(TypeBuilder*, i<256>*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_create", module); Type* args[] = {i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy}; m_call = Function::Create(FunctionType::get(m_builder.getVoidTy(), args, false), Linkage::ExternalLinkage, "ext_call", module); @@ -147,6 +148,13 @@ Value* Ext::balance(Value* _address) return m_builder.CreateLoad(m_args[1]); } +void Ext::suicide(Value* _address) +{ + auto address = bswap(_address); // to BE + m_builder.CreateStore(address, m_args[0]); + m_builder.CreateCall(m_suicide, m_args[0]); +} + Value* Ext::create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize) { m_builder.CreateStore(_endowment, m_args[0]); @@ -225,6 +233,11 @@ EXPORT void ext_balance(h256* _address, i256* _value) *_value = eth2llvm(u); } +EXPORT void ext_suicide(h256* _address) +{ + Runtime::getExt().suicide(dev::right160(*_address)); +} + EXPORT void ext_create(i256* _endowment, i256* _initOff, i256* _initSize, h256* _address) { auto&& ext = Runtime::getExt(); diff --git a/evmcc/Ext.h b/evmcc/Ext.h index 88fad15a1..c2c9f8455 100644 --- a/evmcc/Ext.h +++ b/evmcc/Ext.h @@ -33,6 +33,7 @@ public: llvm::Value* gaslimit(); llvm::Value* balance(llvm::Value* _address); + void suicide(llvm::Value* _address); llvm::Value* calldataload(llvm::Value* _index); llvm::Value* create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize); llvm::Value* call(llvm::Value* _gas, llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize); @@ -58,6 +59,7 @@ private: llvm::Function* m_setStore; llvm::Function* m_calldataload; llvm::Function* m_balance; + llvm::Function* m_suicide; llvm::Function* m_create; llvm::Function* m_call; llvm::Function* m_bswap; diff --git a/evmcc/bytecode/ext_test.evm b/evmcc/bytecode/ext_test.evm index e8da21f45..6c99e8fa0 100644 --- a/evmcc/bytecode/ext_test.evm +++ b/evmcc/bytecode/ext_test.evm @@ -1 +1 @@ -5a3031333234363a4041424344455a36600035602635601335387f1111222233334444555566667777888899990000aaaabbbbccccddddeeeeffff600054602060006000f06020600060206000600030610bb8f10060016002f2 +5a3031333234363a4041424344455a36600035602635601335387f1111222233334444555566667777888899990000aaaabbbbccccddddeeeeffff600054602060006000f06020600060206000600030610bb8f130ff60016002f2 diff --git a/evmcc/lll/ext_test.lll b/evmcc/lll/ext_test.lll index 5e359cb7f..0625afadc 100644 --- a/evmcc/lll/ext_test.lll +++ b/evmcc/lll/ext_test.lll @@ -38,7 +38,8 @@ CREATE ADDRESS 3000 CALL -STOP +ADDRESS +SUICIDE 1 2 RETURN From fe38de867e33f286138cace91b7a81866a97f29f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 6 Oct 2014 10:47:31 +0200 Subject: [PATCH 051/641] SHA3 instruction [Delivers #79534494] --- evmcc/Compiler.cpp | 8 ++++++++ evmcc/Ext.cpp | 23 +++++++++++++++++++++++ evmcc/Ext.h | 3 +++ evmcc/bytecode/ext_test.evm | 2 +- evmcc/lll/ext_test.lll | 9 +++++++++ 5 files changed, 44 insertions(+), 1 deletion(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 48b74e501..4fead05c0 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -421,6 +421,14 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::SHA3: + { + auto inOff = stack.pop(); + auto inSize = stack.pop(); + auto hash = ext.sha3(inOff, inSize); + stack.push(hash); + } + case Instruction::POP: { stack.pop(); diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index 9fad58fa7..8266bd728 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -5,6 +5,8 @@ #include #include +#include + #include "Runtime.h" #ifdef _MSC_VER @@ -90,6 +92,7 @@ Ext::Ext(llvm::IRBuilder<>& _builder, llvm::Module* module) Type* args[] = {i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy}; m_call = Function::Create(FunctionType::get(m_builder.getVoidTy(), args, false), Linkage::ExternalLinkage, "ext_call", module); m_bswap = Intrinsic::getDeclaration(module, Intrinsic::bswap, i256Ty); + m_sha3 = Function::Create(TypeBuilder*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_sha3", module); m_builder.CreateCall(m_init, m_data); @@ -182,6 +185,17 @@ llvm::Value* Ext::call(llvm::Value* _gas, llvm::Value* _receiveAddress, llvm::Va return m_builder.CreateLoad(m_args[1]); } +llvm::Value* Ext::sha3(llvm::Value* _inOff, llvm::Value* _inSize) +{ + m_builder.CreateStore(_inOff, m_args[0]); + m_builder.CreateStore(_inSize, m_arg2); + llvm::Value* args[] = {m_args[0], m_arg2, m_args[1]}; + m_builder.CreateCall(m_sha3, args); + Value* hash = m_builder.CreateLoad(m_args[1]); + hash = bswap(hash); // to LE + return hash; +} + extern "C" { @@ -285,6 +299,15 @@ EXPORT void ext_call(i256* _gas, h256* _receiveAddress, i256* _value, i256* _inO _ret->a = ret ? 1 : 0; } +EXPORT void ext_sha3(i256* _inOff, i256* _inSize, i256* _ret) +{ + auto inOff = static_cast(llvm2eth(*_inOff)); + auto inSize = static_cast(llvm2eth(*_inSize)); + auto dataRef = dev::bytesConstRef(Runtime::getMemory().data() + inOff, inSize); + auto hash = dev::eth::sha3(dataRef); + *_ret = *reinterpret_cast(&hash); +} + } } diff --git a/evmcc/Ext.h b/evmcc/Ext.h index c2c9f8455..7801d0540 100644 --- a/evmcc/Ext.h +++ b/evmcc/Ext.h @@ -38,6 +38,8 @@ public: llvm::Value* create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize); llvm::Value* call(llvm::Value* _gas, llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize); + llvm::Value* sha3(llvm::Value* _inOff, llvm::Value* _inSize); + private: llvm::Value* getDataElem(unsigned _index, const llvm::Twine& _name = ""); @@ -63,6 +65,7 @@ private: llvm::Function* m_create; llvm::Function* m_call; llvm::Function* m_bswap; + llvm::Function* m_sha3; }; diff --git a/evmcc/bytecode/ext_test.evm b/evmcc/bytecode/ext_test.evm index 6c99e8fa0..580bd9675 100644 --- a/evmcc/bytecode/ext_test.evm +++ b/evmcc/bytecode/ext_test.evm @@ -1 +1 @@ -5a3031333234363a4041424344455a36600035602635601335387f1111222233334444555566667777888899990000aaaabbbbccccddddeeeeffff600054602060006000f06020600060206000600030610bb8f130ff60016002f2 +5a3031333234363a4041424344455a36600035602635601335387f1111222233334444555566667777888899990000aaaabbbbccccddddeeeeffff600054602060006000f06020600060206000600030610bb8f1600053611000545b60200260002030ff60016002f2 diff --git a/evmcc/lll/ext_test.lll b/evmcc/lll/ext_test.lll index 0625afadc..3287ae95f 100644 --- a/evmcc/lll/ext_test.lll +++ b/evmcc/lll/ext_test.lll @@ -38,6 +38,15 @@ CREATE ADDRESS 3000 CALL +0 +MLOAD +4096 +MSTORE +MSIZE +32 +MUL +0 +SHA3 ADDRESS SUICIDE 1 From 1bd7ade08b73c638de0d87b886a4a38fdefdef65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 6 Oct 2014 15:58:57 +0200 Subject: [PATCH 052/641] Basic stack implementation for basic block. Values on stack are not preserved between basic blocks (jumps) --- evmcc/Compiler.cpp | 16 +++++++--------- evmcc/Stack.cpp | 24 ++++++++++++++++++++++++ evmcc/Stack.h | 22 ++++++++++++++++++++++ 3 files changed, 53 insertions(+), 9 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 4fead05c0..26b23bff0 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -188,11 +188,12 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) createBasicBlocks(bytecode); // Init runtime structures. - auto stack = Stack(builder, module.get()); + auto globalStack = Stack(builder, module.get()); auto memory = Memory(builder, module.get()); auto ext = Ext(builder, module.get()); BasicBlock* currentBlock = entryBlock; + BBStack stack; // Stack for current block for (auto pc = bytecode.cbegin(); pc != bytecode.cend(); ++pc) { @@ -211,6 +212,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) mainFunc->getBasicBlockList().push_back(nextBlock); builder.SetInsertPoint(nextBlock); currentBlock = nextBlock; + stack = BBStack(); // Reset stack } assert(currentBlock != nullptr); @@ -498,9 +500,8 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) case Instruction::DUP15: case Instruction::DUP16: { - auto index = static_cast(inst) - static_cast(Instruction::DUP1); - auto value = stack.get(index); - stack.push(value); + auto index = static_cast(inst) - static_cast(Instruction::DUP1); + stack.dup(index); break; } @@ -521,11 +522,8 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) case Instruction::SWAP15: case Instruction::SWAP16: { - auto index = static_cast(inst) - static_cast(Instruction::SWAP1) + 1; - auto loValue = stack.get(index); - auto hiValue = stack.get(0); - stack.set(index, hiValue); - stack.set(0, loValue); + auto index = static_cast(inst) - static_cast(Instruction::SWAP1) + 1; + stack.swap(index); break; } diff --git a/evmcc/Stack.cpp b/evmcc/Stack.cpp index ef99d603b..6a4cf4d61 100644 --- a/evmcc/Stack.cpp +++ b/evmcc/Stack.cpp @@ -20,6 +20,30 @@ namespace evmcc { +void BBStack::push(llvm::Value* _value) +{ + m_state.push_back(_value); +} + +llvm::Value* BBStack::pop() +{ + auto top = m_state.back(); + m_state.pop_back(); + return top; +} + +void BBStack::dup(size_t _index) +{ + auto value = *(m_state.rbegin() + _index); + m_state.push_back(value); +} + +void BBStack::swap(size_t _index) +{ + assert(_index != 0); + std::swap(*m_state.rbegin(), *(m_state.rbegin() + _index)); +} + Stack::Stack(llvm::IRBuilder<>& _builder, llvm::Module* _module) : m_builder(_builder) { diff --git a/evmcc/Stack.h b/evmcc/Stack.h index 53e935a8a..6336f3412 100644 --- a/evmcc/Stack.h +++ b/evmcc/Stack.h @@ -1,6 +1,8 @@ #pragma once +#include + #include namespace evmcc @@ -26,4 +28,24 @@ private: llvm::Function* m_stackSet; }; +/** + Stack adapter for Basic Block + + Transforms stack to SSA: tracks values and their positions on the imaginary stack used inside a basic block. + */ +class BBStack +{ +public: + //BBStack(llvm::IRBuilder<>& _builder, llvm::Module* _module); + + void push(llvm::Value* _value); + llvm::Value* pop(); + void dup(size_t _index); + void swap(size_t _index); + +private: + std::vector m_state; ///< Basic black state vector - current values and their positions +}; + + } \ No newline at end of file From 3fa3bc8b308bca6f9163d58dee4801ad2e3c6747 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 7 Oct 2014 09:24:55 +0200 Subject: [PATCH 053/641] Pop entry state of basic block from external stack, push exit state to external stack. [Delivers #80113346] --- evmcc/Compiler.cpp | 10 +++++++--- evmcc/ExecutionEngine.cpp | 2 +- evmcc/Stack.cpp | 24 ++++++++++++++++++++++++ evmcc/Stack.h | 18 +++++++++++++++++- evmcc/bytecode/stackjump.evm | 1 + 5 files changed, 50 insertions(+), 5 deletions(-) create mode 100644 evmcc/bytecode/stackjump.evm diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 26b23bff0..3a0da880d 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -188,12 +188,12 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) createBasicBlocks(bytecode); // Init runtime structures. - auto globalStack = Stack(builder, module.get()); + auto extStack = Stack(builder, module.get()); auto memory = Memory(builder, module.get()); auto ext = Ext(builder, module.get()); BasicBlock* currentBlock = entryBlock; - BBStack stack; // Stack for current block + BBStack stack(extStack); // Stack for current block for (auto pc = bytecode.cbegin(); pc != bytecode.cend(); ++pc) { @@ -212,7 +212,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) mainFunc->getBasicBlockList().push_back(nextBlock); builder.SetInsertPoint(nextBlock); currentBlock = nextBlock; - stack = BBStack(); // Reset stack + assert(stack.empty()); // Stack should be empty } assert(currentBlock != nullptr); @@ -579,6 +579,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) // The target address is computed at compile time, // just pop it without looking... stack.pop(); + stack.reset(); auto targetBlock = jumpTargets[currentPC]; builder.CreateBr(targetBlock); @@ -598,6 +599,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto top = stack.pop(); auto zero = ConstantInt::get(Types.word256, 0); auto cond = builder.CreateICmpNE(top, zero, "nonzero"); + stack.reset(); auto targetBlock = jumpTargets[currentPC]; auto followBlock = basicBlocks[currentPC + 1]; builder.CreateCondBr(cond, targetBlock, followBlock); @@ -764,6 +766,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) ret = builder.CreateOr(ret, size); builder.CreateRet(ret); + stack.clear(); currentBlock = nullptr; break; } @@ -777,6 +780,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) case Instruction::STOP: { builder.CreateRet(builder.getInt64(0)); + stack.clear(); currentBlock = nullptr; break; } diff --git a/evmcc/ExecutionEngine.cpp b/evmcc/ExecutionEngine.cpp index 6983b9cda..6d9d85a4c 100644 --- a/evmcc/ExecutionEngine.cpp +++ b/evmcc/ExecutionEngine.cpp @@ -103,7 +103,7 @@ int ExecutionEngine::run(std::unique_ptr _module) std::cout << "RETURN [ "; for (dev::bytes::const_iterator it = Runtime::getMemory().cbegin() + index, end = it + size; it != end; ++it) std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)*it << " "; - std::cout << "]"; + std::cout << "]\n"; return 10; } diff --git a/evmcc/Stack.cpp b/evmcc/Stack.cpp index 6a4cf4d61..b4fb2cd23 100644 --- a/evmcc/Stack.cpp +++ b/evmcc/Stack.cpp @@ -20,6 +20,10 @@ namespace evmcc { +BBStack::BBStack(Stack& _extStack) + : m_extStack(_extStack) +{} + void BBStack::push(llvm::Value* _value) { m_state.push_back(_value); @@ -27,11 +31,31 @@ void BBStack::push(llvm::Value* _value) llvm::Value* BBStack::pop() { + if (m_state.empty()) + return m_extStack.pop(); + auto top = m_state.back(); m_state.pop_back(); return top; } +void BBStack::reset() +{ + for (auto&& value : m_state) + m_extStack.push(value); + m_state.clear(); +} + +void BBStack::clear() +{ + m_state.clear(); +} + +bool BBStack::empty() const +{ + return m_state.empty(); +} + void BBStack::dup(size_t _index) { auto value = *(m_state.rbegin() + _index); diff --git a/evmcc/Stack.h b/evmcc/Stack.h index 6336f3412..c420ad0bb 100644 --- a/evmcc/Stack.h +++ b/evmcc/Stack.h @@ -36,15 +36,31 @@ private: class BBStack { public: - //BBStack(llvm::IRBuilder<>& _builder, llvm::Module* _module); + BBStack(Stack& _extStack); void push(llvm::Value* _value); llvm::Value* pop(); void dup(size_t _index); void swap(size_t _index); + /** + Resets stack on basic block change. + Values left on local stack are pushed on external stack. + Local stack is empty after this operation and compilation of new basic block can be started. + */ + void reset(); + + /** + Dumps values on stack. + */ + void clear(); + + /// Debug only + bool empty() const; + private: std::vector m_state; ///< Basic black state vector - current values and their positions + Stack& m_extStack; ///< External (global) stack }; diff --git a/evmcc/bytecode/stackjump.evm b/evmcc/bytecode/stackjump.evm new file mode 100644 index 000000000..baddec42e --- /dev/null +++ b/evmcc/bytecode/stackjump.evm @@ -0,0 +1 @@ +600460066009601358600a036000545b6000f260005401600958 \ No newline at end of file From 5bf462e03ddab160a7d537b0a2b00f1817a85450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 7 Oct 2014 12:14:55 +0200 Subject: [PATCH 054/641] Introducing BasicBlock class. It is a wrapper for llvm::BasicBlock to provide additional information needed by EVM compiler. For now the order of basic blocks might not match bytecode. [#80113672] --- evmcc/BasicBlock.cpp | 13 ++++++++++++ evmcc/BasicBlock.h | 22 ++++++++++++++++++++ evmcc/Compiler.cpp | 39 +++++++++++++---------------------- evmcc/Compiler.h | 13 ++++++++++-- windows/evmcc.vcxproj | 2 ++ windows/evmcc.vcxproj.filters | 2 ++ 6 files changed, 64 insertions(+), 27 deletions(-) create mode 100644 evmcc/BasicBlock.cpp create mode 100644 evmcc/BasicBlock.h diff --git a/evmcc/BasicBlock.cpp b/evmcc/BasicBlock.cpp new file mode 100644 index 000000000..51c3fe310 --- /dev/null +++ b/evmcc/BasicBlock.cpp @@ -0,0 +1,13 @@ + +#include "BasicBlock.h" + +#include + +namespace evmcc +{ + +BasicBlock::BasicBlock(ProgramCounter _instIdx, llvm::Function* _mainFunc) + : m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {"Instr.", std::to_string(_instIdx)}, _mainFunc)) +{} + +} \ No newline at end of file diff --git a/evmcc/BasicBlock.h b/evmcc/BasicBlock.h new file mode 100644 index 000000000..ad5033ed7 --- /dev/null +++ b/evmcc/BasicBlock.h @@ -0,0 +1,22 @@ + +#include + +namespace evmcc +{ + +using ProgramCounter = uint64_t; + +class BasicBlock +{ +public: + explicit BasicBlock(ProgramCounter _instIdx, llvm::Function* _mainFunc); + BasicBlock(const BasicBlock&) = delete; + void operator=(const BasicBlock&) = delete; + + operator llvm::BasicBlock*() { return m_llvmBB; } + +private: + llvm::BasicBlock* m_llvmBB; +}; + +} \ No newline at end of file diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 3a0da880d..25ae8aa9e 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -39,23 +39,15 @@ Compiler::Compiler() Types.WordLowPrecision = llvm::Type::getIntNTy(context, 64); } -llvm::BasicBlock* Compiler::getOrCreateBasicBlockAtPC(ProgramCounter pc) +BasicBlock& Compiler::getOrCreateBasicBlockAtPC(ProgramCounter pc) { - llvm::BasicBlock* block = nullptr; auto blockIter = basicBlocks.find(pc); - if (blockIter == basicBlocks.cend()) + if (blockIter == basicBlocks.end()) { - // Create a basic block at targetPC. - std::ostringstream oss; - oss << "instr." << pc; - block = llvm::BasicBlock::Create(llvm::getGlobalContext(), oss.str()); - basicBlocks[pc] = block; + // Create a basic block at target pc directly in collection + blockIter = basicBlocks.emplace(std::piecewise_construct, std::forward_as_tuple(pc), std::forward_as_tuple(pc, m_mainFunc)).first; } - else - { - block = blockIter->second; - } - return block; + return blockIter->second; } void Compiler::createBasicBlocks(const dev::bytes& bytecode) @@ -122,7 +114,7 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode) // Create a block for the JUMP target. ProgramCounter targetPC = val.convert_to(); - auto targetBlock = getOrCreateBasicBlockAtPC(targetPC); + auto& targetBlock = getOrCreateBasicBlockAtPC(targetPC); ProgramCounter jumpPC = (next - bytecode.cbegin()); jumpTargets[jumpPC] = targetBlock; @@ -177,13 +169,12 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) // Create main function const auto i32Ty = builder.getInt32Ty(); - Type* retTypeElems[] = {i32Ty, i32Ty}; - auto retType = StructType::create(retTypeElems, "MemRef", true); - auto mainFuncType = FunctionType::get(builder.getInt64Ty(), false); - auto mainFunc = Function::Create(mainFuncType, Function::ExternalLinkage, "main", module.get()); + //Type* retTypeElems[] = {i32Ty, i32Ty}; + //auto retType = StructType::create(retTypeElems, "MemRef", true); + m_mainFunc = Function::Create(FunctionType::get(builder.getInt64Ty(), false), Function::ExternalLinkage, "main", module.get()); // Create the basic blocks. - auto entryBlock = BasicBlock::Create(context, "entry", mainFunc); + auto entryBlock = llvm::BasicBlock::Create(context, "entry", m_mainFunc); builder.SetInsertPoint(entryBlock); createBasicBlocks(bytecode); @@ -192,7 +183,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto memory = Memory(builder, module.get()); auto ext = Ext(builder, module.get()); - BasicBlock* currentBlock = entryBlock; + llvm::BasicBlock* currentBlock = entryBlock; BBStack stack(extStack); // Stack for current block for (auto pc = bytecode.cbegin(); pc != bytecode.cend(); ++pc) @@ -204,12 +195,11 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto blockIter = basicBlocks.find(currentPC); if (blockIter != basicBlocks.end()) { - auto nextBlock = blockIter->second; + auto& nextBlock = blockIter->second; // Terminate the current block by jumping to the next one. if (currentBlock != nullptr) builder.CreateBr(nextBlock); // Insert the next block into the main function. - mainFunc->getBasicBlockList().push_back(nextBlock); builder.SetInsertPoint(nextBlock); currentBlock = nextBlock; assert(stack.empty()); // Stack should be empty @@ -601,7 +591,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto cond = builder.CreateICmpNE(top, zero, "nonzero"); stack.reset(); auto targetBlock = jumpTargets[currentPC]; - auto followBlock = basicBlocks[currentPC + 1]; + auto& followBlock = basicBlocks.find(currentPC + 1)->second; builder.CreateCondBr(cond, targetBlock, followBlock); currentBlock = nullptr; @@ -792,12 +782,11 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto finalPC = bytecode.size(); auto it = basicBlocks.find(finalPC); assert(it != basicBlocks.end()); - auto finalBlock = it->second; + auto& finalBlock = it->second; if (currentBlock != nullptr) builder.CreateBr(finalBlock); - mainFunc->getBasicBlockList().push_back(finalBlock); builder.SetInsertPoint(finalBlock); builder.CreateRet(builder.getInt64(0)); diff --git a/evmcc/Compiler.h b/evmcc/Compiler.h index 6e9fd8443..1404a99c5 100644 --- a/evmcc/Compiler.h +++ b/evmcc/Compiler.h @@ -5,6 +5,8 @@ #include +#include "BasicBlock.h" + namespace evmcc { @@ -20,18 +22,25 @@ public: private: - llvm::BasicBlock* getOrCreateBasicBlockAtPC(ProgramCounter pc); + BasicBlock& getOrCreateBasicBlockAtPC(ProgramCounter pc); void createBasicBlocks(const dev::bytes& bytecode); /** * Maps a program counter pc to a basic block which starts at pc (if any). */ - std::map basicBlocks; + std::map basicBlocks; /** * Maps a pc at which there is a JUMP or JUMPI to the target block of the jump. */ std::map jumpTargets; + +private: + /// Collection of basic blocks in program + //std::vector m_basicBlocks; + + /// Main program function + llvm::Function* m_mainFunc; }; } diff --git a/windows/evmcc.vcxproj b/windows/evmcc.vcxproj index c3add28cd..8226abb6c 100644 --- a/windows/evmcc.vcxproj +++ b/windows/evmcc.vcxproj @@ -19,6 +19,7 @@ + @@ -29,6 +30,7 @@ + diff --git a/windows/evmcc.vcxproj.filters b/windows/evmcc.vcxproj.filters index de7fd20bf..05f375ac5 100644 --- a/windows/evmcc.vcxproj.filters +++ b/windows/evmcc.vcxproj.filters @@ -9,6 +9,7 @@ + @@ -18,5 +19,6 @@ + \ No newline at end of file From 07659c441a954dc1730ba9d4e15e07c6de8193ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 7 Oct 2014 15:34:02 +0200 Subject: [PATCH 055/641] Link basic blocks with phi functions [#80113672] --- evmcc/BasicBlock.cpp | 5 +++-- evmcc/BasicBlock.h | 14 +++++++++++- evmcc/Compiler.cpp | 47 ++++++++++++++++++++++++++++++++------- evmcc/Stack.cpp | 52 ++++++++++++++++++++++++-------------------- evmcc/Stack.h | 20 +++++------------ 5 files changed, 89 insertions(+), 49 deletions(-) diff --git a/evmcc/BasicBlock.cpp b/evmcc/BasicBlock.cpp index 51c3fe310..19e1d68ec 100644 --- a/evmcc/BasicBlock.cpp +++ b/evmcc/BasicBlock.cpp @@ -6,8 +6,9 @@ namespace evmcc { -BasicBlock::BasicBlock(ProgramCounter _instIdx, llvm::Function* _mainFunc) - : m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {"Instr.", std::to_string(_instIdx)}, _mainFunc)) +BasicBlock::BasicBlock(ProgramCounter _beginInstIdx, llvm::Function* _mainFunc): + m_beginInstIdx(_beginInstIdx), + m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {"Instr.", std::to_string(_beginInstIdx)}, _mainFunc)) {} } \ No newline at end of file diff --git a/evmcc/BasicBlock.h b/evmcc/BasicBlock.h index ad5033ed7..793dfaea2 100644 --- a/evmcc/BasicBlock.h +++ b/evmcc/BasicBlock.h @@ -1,4 +1,6 @@ +#include + #include namespace evmcc @@ -9,14 +11,24 @@ using ProgramCounter = uint64_t; class BasicBlock { public: - explicit BasicBlock(ProgramCounter _instIdx, llvm::Function* _mainFunc); + using State = std::vector; + + explicit BasicBlock(ProgramCounter _beginInstIdx, llvm::Function* _mainFunc); + BasicBlock(const BasicBlock&) = delete; void operator=(const BasicBlock&) = delete; operator llvm::BasicBlock*() { return m_llvmBB; } + llvm::BasicBlock* llvm() { return m_llvmBB; } + + State& getState() { return m_state; } private: + ProgramCounter m_beginInstIdx; llvm::BasicBlock* m_llvmBB; + + /// Basic black state vector - current/end values and their positions + State m_state; }; } \ No newline at end of file diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 25ae8aa9e..18b0a1d3b 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -2,6 +2,7 @@ #include "Compiler.h" #include +#include #include @@ -183,8 +184,8 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto memory = Memory(builder, module.get()); auto ext = Ext(builder, module.get()); - llvm::BasicBlock* currentBlock = entryBlock; - BBStack stack(extStack); // Stack for current block + BasicBlock* currentBlock = &basicBlocks.find(0)->second; // Any value, just to create branch for %entry to %Instr.0 + BBStack stack(builder, extStack); // Stack for current block for (auto pc = bytecode.cbegin(); pc != bytecode.cend(); ++pc) { @@ -192,6 +193,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) ProgramCounter currentPC = pc - bytecode.cbegin(); + // Change basic block auto blockIter = basicBlocks.find(currentPC); if (blockIter != basicBlocks.end()) { @@ -201,8 +203,8 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) builder.CreateBr(nextBlock); // Insert the next block into the main function. builder.SetInsertPoint(nextBlock); - currentBlock = nextBlock; - assert(stack.empty()); // Stack should be empty + currentBlock = &nextBlock; + stack.setBasicBlock(*currentBlock); } assert(currentBlock != nullptr); @@ -569,7 +571,6 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) // The target address is computed at compile time, // just pop it without looking... stack.pop(); - stack.reset(); auto targetBlock = jumpTargets[currentPC]; builder.CreateBr(targetBlock); @@ -589,7 +590,6 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto top = stack.pop(); auto zero = ConstantInt::get(Types.word256, 0); auto cond = builder.CreateICmpNE(top, zero, "nonzero"); - stack.reset(); auto targetBlock = jumpTargets[currentPC]; auto& followBlock = basicBlocks.find(currentPC + 1)->second; builder.CreateCondBr(cond, targetBlock, followBlock); @@ -756,7 +756,6 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) ret = builder.CreateOr(ret, size); builder.CreateRet(ret); - stack.clear(); currentBlock = nullptr; break; } @@ -770,7 +769,6 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) case Instruction::STOP: { builder.CreateRet(builder.getInt64(0)); - stack.clear(); currentBlock = nullptr; break; } @@ -790,6 +788,39 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) builder.SetInsertPoint(finalBlock); builder.CreateRet(builder.getInt64(0)); + auto findBB = [this](llvm::BasicBlock* _llvmBB) + { + for (auto&& bb : basicBlocks) + { + if (bb.second.llvm() == _llvmBB) + return &bb.second; + } + return (BasicBlock*)nullptr; + }; + + // Link basic blocks + for (auto&& p : basicBlocks) + { + BasicBlock& bb = p.second; + llvm::BasicBlock* llvmBB = bb.llvm(); + + size_t i = 0; + for (auto& inst : *llvmBB) + { + if (auto phi = llvm::dyn_cast(&inst)) + { + for (auto preIt = llvm::pred_begin(llvmBB); preIt != llvm::pred_end(llvmBB); ++preIt) + { + llvm::BasicBlock* preBB = *preIt; + auto pbb = findBB(preBB); + assert(i < pbb->getState().size()); // TODO: Report error + phi->addIncoming(*(pbb->getState().rbegin() + i), preBB); + } + ++i; + } + } + } + return module; } diff --git a/evmcc/Stack.cpp b/evmcc/Stack.cpp index b4fb2cd23..1a453d396 100644 --- a/evmcc/Stack.cpp +++ b/evmcc/Stack.cpp @@ -9,6 +9,7 @@ #include +#include "BasicBlock.h" #include "Runtime.h" #ifdef _MSC_VER @@ -20,52 +21,55 @@ namespace evmcc { -BBStack::BBStack(Stack& _extStack) - : m_extStack(_extStack) +BBStack::BBStack(llvm::IRBuilder<>& _builder, Stack& _extStack): + m_extStack(_extStack), + m_builder(_builder) {} void BBStack::push(llvm::Value* _value) { - m_state.push_back(_value); + m_block->getState().push_back(_value); } llvm::Value* BBStack::pop() { - if (m_state.empty()) - return m_extStack.pop(); + auto&& state = m_block->getState(); + if (state.empty()) + { + // Create PHI node + auto first = m_block->llvm()->getFirstNonPHI(); + auto llvmBB = m_block->llvm(); + if (llvmBB->getInstList().empty()) + return llvm::PHINode::Create(m_builder.getIntNTy(256), 0, {}, m_block->llvm()); + return llvm::PHINode::Create(m_builder.getIntNTy(256), 0, {}, llvmBB->getFirstNonPHI()); + } - auto top = m_state.back(); - m_state.pop_back(); + auto top = state.back(); + state.pop_back(); return top; } -void BBStack::reset() -{ - for (auto&& value : m_state) - m_extStack.push(value); - m_state.clear(); -} - -void BBStack::clear() -{ - m_state.clear(); -} - -bool BBStack::empty() const +void BBStack::setBasicBlock(BasicBlock& _newBlock) { - return m_state.empty(); + // Current block keeps end state + // Just update pointer to current block + // New block should have empty state + assert(_newBlock.getState().empty()); + m_block = &_newBlock; } void BBStack::dup(size_t _index) { - auto value = *(m_state.rbegin() + _index); - m_state.push_back(value); + auto&& state = m_block->getState(); + auto value = *(state.rbegin() + _index); + state.push_back(value); } void BBStack::swap(size_t _index) { assert(_index != 0); - std::swap(*m_state.rbegin(), *(m_state.rbegin() + _index)); + auto&& state = m_block->getState(); + std::swap(*state.rbegin(), *(state.rbegin() + _index)); } Stack::Stack(llvm::IRBuilder<>& _builder, llvm::Module* _module) diff --git a/evmcc/Stack.h b/evmcc/Stack.h index c420ad0bb..06deff814 100644 --- a/evmcc/Stack.h +++ b/evmcc/Stack.h @@ -7,6 +7,7 @@ namespace evmcc { +class BasicBlock; class Stack { @@ -36,7 +37,7 @@ private: class BBStack { public: - BBStack(Stack& _extStack); + BBStack(llvm::IRBuilder<>& _builder, Stack& _extStack); void push(llvm::Value* _value); llvm::Value* pop(); @@ -44,23 +45,14 @@ public: void swap(size_t _index); /** - Resets stack on basic block change. - Values left on local stack are pushed on external stack. - Local stack is empty after this operation and compilation of new basic block can be started. + Changes current basic block with a new one with empty state. */ - void reset(); - - /** - Dumps values on stack. - */ - void clear(); - - /// Debug only - bool empty() const; + void setBasicBlock(BasicBlock& _newBlock); private: - std::vector m_state; ///< Basic black state vector - current values and their positions Stack& m_extStack; ///< External (global) stack + BasicBlock* m_block = nullptr; ///< Current basic block + llvm::IRBuilder<>& m_builder; }; From d9c1617e60720601eaac7fa22c71027fa776b813 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 7 Oct 2014 15:44:46 +0200 Subject: [PATCH 056/641] Correct the order of basic blocks --- evmcc/Compiler.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 18b0a1d3b..e951788e6 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -53,8 +53,7 @@ BasicBlock& Compiler::getOrCreateBasicBlockAtPC(ProgramCounter pc) void Compiler::createBasicBlocks(const dev::bytes& bytecode) { - getOrCreateBasicBlockAtPC(0); - getOrCreateBasicBlockAtPC(bytecode.size()); + getOrCreateBasicBlockAtPC(0); // First basic block for (auto curr = bytecode.cbegin(); curr != bytecode.cend(); ++curr) { @@ -113,13 +112,6 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode) val |= *iter; } - // Create a block for the JUMP target. - ProgramCounter targetPC = val.convert_to(); - auto& targetBlock = getOrCreateBasicBlockAtPC(targetPC); - - ProgramCounter jumpPC = (next - bytecode.cbegin()); - jumpTargets[jumpPC] = targetBlock; - // Create a block following the JUMP. if (next + 1 < bytecode.cend()) { @@ -127,6 +119,13 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode) getOrCreateBasicBlockAtPC(nextPC); } + // Create a block for the JUMP target. + ProgramCounter targetPC = val.convert_to(); + auto& targetBlock = getOrCreateBasicBlockAtPC(targetPC); + + ProgramCounter jumpPC = (next - bytecode.cbegin()); + jumpTargets[jumpPC] = targetBlock; + curr += 1; // skip over JUMP } @@ -158,6 +157,8 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode) break; } } + + getOrCreateBasicBlockAtPC(bytecode.size()); // Final basic block } std::unique_ptr Compiler::compile(const dev::bytes& bytecode) From bf7ca5cd013fc8c79ba21e50bf7096c87c2ad0c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 7 Oct 2014 15:47:08 +0200 Subject: [PATCH 057/641] Cleanups: move basic block linking to separated function --- evmcc/Compiler.cpp | 11 +++++++++-- evmcc/Compiler.h | 2 ++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index e951788e6..7fccadbf1 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -789,6 +789,15 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) builder.SetInsertPoint(finalBlock); builder.CreateRet(builder.getInt64(0)); + linkBasicBlocks(); + + return module; +} + + +void Compiler::linkBasicBlocks() +{ + /// Helper function that finds basic block given LLVM basic block pointer auto findBB = [this](llvm::BasicBlock* _llvmBB) { for (auto&& bb : basicBlocks) @@ -821,8 +830,6 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) } } } - - return module; } } diff --git a/evmcc/Compiler.h b/evmcc/Compiler.h index 1404a99c5..de73fb7a5 100644 --- a/evmcc/Compiler.h +++ b/evmcc/Compiler.h @@ -25,6 +25,8 @@ private: BasicBlock& getOrCreateBasicBlockAtPC(ProgramCounter pc); void createBasicBlocks(const dev::bytes& bytecode); + void linkBasicBlocks(); + /** * Maps a program counter pc to a basic block which starts at pc (if any). */ From b644ff2d71b07a36609c6a878a6f8e638c74947d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 7 Oct 2014 16:03:05 +0200 Subject: [PATCH 058/641] Stack cleanups --- evmcc/Compiler.cpp | 2 +- evmcc/Stack.cpp | 11 +++-------- evmcc/Stack.h | 21 +++++++++++++++------ 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 7fccadbf1..1be4a3746 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -186,7 +186,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto ext = Ext(builder, module.get()); BasicBlock* currentBlock = &basicBlocks.find(0)->second; // Any value, just to create branch for %entry to %Instr.0 - BBStack stack(builder, extStack); // Stack for current block + BBStack stack; // Stack for current block for (auto pc = bytecode.cbegin(); pc != bytecode.cend(); ++pc) { diff --git a/evmcc/Stack.cpp b/evmcc/Stack.cpp index 1a453d396..1b8577159 100644 --- a/evmcc/Stack.cpp +++ b/evmcc/Stack.cpp @@ -21,11 +21,6 @@ namespace evmcc { -BBStack::BBStack(llvm::IRBuilder<>& _builder, Stack& _extStack): - m_extStack(_extStack), - m_builder(_builder) -{} - void BBStack::push(llvm::Value* _value) { m_block->getState().push_back(_value); @@ -37,11 +32,11 @@ llvm::Value* BBStack::pop() if (state.empty()) { // Create PHI node - auto first = m_block->llvm()->getFirstNonPHI(); + auto i256Ty = llvm::Type::getIntNTy(m_block->llvm()->getContext(), 256); auto llvmBB = m_block->llvm(); if (llvmBB->getInstList().empty()) - return llvm::PHINode::Create(m_builder.getIntNTy(256), 0, {}, m_block->llvm()); - return llvm::PHINode::Create(m_builder.getIntNTy(256), 0, {}, llvmBB->getFirstNonPHI()); + return llvm::PHINode::Create(i256Ty, 0, {}, m_block->llvm()); + return llvm::PHINode::Create(i256Ty, 0, {}, llvmBB->getFirstNonPHI()); } auto top = state.back(); diff --git a/evmcc/Stack.h b/evmcc/Stack.h index 06deff814..430389ef9 100644 --- a/evmcc/Stack.h +++ b/evmcc/Stack.h @@ -37,22 +37,31 @@ private: class BBStack { public: - BBStack(llvm::IRBuilder<>& _builder, Stack& _extStack); + BBStack() = default; + BBStack(const BBStack&) = delete; + void operator=(const BBStack&) = delete; + + /** + Changes current basic block (if any) with a new one with empty state. + */ + void setBasicBlock(BasicBlock& _newBlock); void push(llvm::Value* _value); llvm::Value* pop(); + + /** + Duplicates _index'th value on stack. + */ void dup(size_t _index); - void swap(size_t _index); /** - Changes current basic block with a new one with empty state. + Swaps _index'th value on stack with a value on stack top. + @param _index Index of value to be swaped. Cannot be 0. */ - void setBasicBlock(BasicBlock& _newBlock); + void swap(size_t _index); private: - Stack& m_extStack; ///< External (global) stack BasicBlock* m_block = nullptr; ///< Current basic block - llvm::IRBuilder<>& m_builder; }; From 0e7ae8ece92e086557c61315dab8f626c2490f68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 7 Oct 2014 16:09:50 +0200 Subject: [PATCH 059/641] Remove external stack --- evmcc/Compiler.cpp | 1 - evmcc/Stack.cpp | 130 +-------------------------------------------- evmcc/Stack.h | 24 +-------- 3 files changed, 3 insertions(+), 152 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 1be4a3746..e5fe6db8b 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -181,7 +181,6 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) createBasicBlocks(bytecode); // Init runtime structures. - auto extStack = Stack(builder, module.get()); auto memory = Memory(builder, module.get()); auto ext = Ext(builder, module.get()); diff --git a/evmcc/Stack.cpp b/evmcc/Stack.cpp index 1b8577159..86b39316c 100644 --- a/evmcc/Stack.cpp +++ b/evmcc/Stack.cpp @@ -1,22 +1,11 @@ #include "Stack.h" -#include -#include -#include -#include #include -#include +#include #include "BasicBlock.h" -#include "Runtime.h" - -#ifdef _MSC_VER - #define EXPORT __declspec(dllexport) -#else - #define EXPORT -#endif namespace evmcc { @@ -49,7 +38,7 @@ void BBStack::setBasicBlock(BasicBlock& _newBlock) // Current block keeps end state // Just update pointer to current block // New block should have empty state - assert(_newBlock.getState().empty()); + assert(_newBlock.getState().empty()); m_block = &_newBlock; } @@ -67,119 +56,4 @@ void BBStack::swap(size_t _index) std::swap(*state.rbegin(), *(state.rbegin() + _index)); } -Stack::Stack(llvm::IRBuilder<>& _builder, llvm::Module* _module) - : m_builder(_builder) -{ - // TODO: Clean up LLVM types - auto stackPtrTy = m_builder.getInt8PtrTy(); - auto i256Ty = m_builder.getIntNTy(256); - auto i256PtrTy = i256Ty->getPointerTo(); - auto voidTy = m_builder.getVoidTy(); - - auto funcType = llvm::FunctionType::get(voidTy, i256PtrTy, false); - m_stackPush = llvm::Function::Create(funcType, - llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_push", _module); - - m_stackPop = llvm::Function::Create(funcType, - llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_pop", _module); - - llvm::Type* getArgsTypes[] = {m_builder.getInt32Ty(), i256PtrTy}; - auto getFuncType = llvm::FunctionType::get(voidTy, getArgsTypes, false); - m_stackGet = llvm::Function::Create(getFuncType, - llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_get", _module); - - m_stackSet = llvm::Function::Create(getFuncType, - llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_set", _module); - - m_stackVal = m_builder.CreateAlloca(i256Ty, nullptr, "stack.val"); -} - - -void Stack::push(llvm::Value* _value) -{ - m_builder.CreateStore(_value, m_stackVal); // copy value to memory - m_builder.CreateCall(m_stackPush, m_stackVal); -} - - -llvm::Value* Stack::pop() -{ - m_builder.CreateCall(m_stackPop, m_stackVal); - return m_builder.CreateLoad(m_stackVal); -} - - -llvm::Value* Stack::get(uint32_t _index) -{ - llvm::Value* args[] = {m_builder.getInt32(_index), m_stackVal}; - m_builder.CreateCall(m_stackGet, args); - return m_builder.CreateLoad(m_stackVal); -} - - -void Stack::set(uint32_t _index, llvm::Value* _value) -{ - m_builder.CreateStore(_value, m_stackVal); // copy value to memory - llvm::Value* args[] = {m_builder.getInt32(_index), m_stackVal}; - m_builder.CreateCall(m_stackSet, args); -} - - -llvm::Value* Stack::top() -{ - return get(0); } - - -void debugStack(const char* _op, const i256& _word, uint32_t _index = 0) -{ - std::cerr << "STACK " << std::setw(4) << std::setfill(' ') << _op - << " [" << std::setw(2) << std::setfill('0') << _index << "] " - << std::dec << _word.a - << " HEX: " << std::hex; - if (_word.b || _word.c || _word.d) - { - std::cerr << std::setw(16) << _word.d << " " - << std::setw(16) << _word.c << " " - << std::setw(16) << _word.b << " "; - } - std::cerr << std::setw(16) << _word.a << "\n"; -} - -} - -extern "C" -{ - using namespace evmcc; - -EXPORT void evmccrt_stack_push(i256* _word) -{ - //debugStack("push", *_word); - Runtime::getStack().push_back(*_word); -} - -EXPORT void evmccrt_stack_pop(i256* _outWord) -{ - assert(!Runtime::getStack().empty()); - auto word = &Runtime::getStack().back(); - //debugStack("pop", *word); - Runtime::getStack().pop_back(); - *_outWord = *word; -} - -EXPORT void evmccrt_stack_get(uint32_t _index, i256* _outWord) -{ - assert(_index < Runtime::getStack().size()); - auto word = Runtime::getStack().rbegin() + _index; - //debugStack("get", *word, _index); - *_outWord = *word; -} - -EXPORT void evmccrt_stack_set(uint32_t _index, i256* _word) -{ - assert(_index < Runtime::getStack().size()); - *(Runtime::getStack().rbegin() + _index) = *_word; - //debugStack("set", *_word, _index); -} - -} // extern "C" diff --git a/evmcc/Stack.h b/evmcc/Stack.h index 430389ef9..cc29a0074 100644 --- a/evmcc/Stack.h +++ b/evmcc/Stack.h @@ -1,34 +1,12 @@ #pragma once -#include - -#include +#include namespace evmcc { class BasicBlock; -class Stack -{ -public: - Stack(llvm::IRBuilder<>& _builder, llvm::Module* _module); - - void push(llvm::Value* _value); - llvm::Value* pop(); - llvm::Value* top(); - llvm::Value* get(uint32_t _index); - void set(uint32_t _index, llvm::Value* _value); - -private: - llvm::IRBuilder<>& m_builder; - llvm::Value* m_stackVal; - llvm::Function* m_stackPush; - llvm::Function* m_stackPop; - llvm::Function* m_stackGet; - llvm::Function* m_stackSet; -}; - /** Stack adapter for Basic Block From 0cba3d90054716d6c62f1f312818ba54e553c839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 7 Oct 2014 17:27:45 +0200 Subject: [PATCH 060/641] Improve basic blocks linking implementation --- evmcc/BasicBlock.cpp | 4 +++- evmcc/BasicBlock.h | 2 ++ evmcc/Compiler.cpp | 32 ++++++++++++++------------------ evmcc/Stack.cpp | 2 +- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/evmcc/BasicBlock.cpp b/evmcc/BasicBlock.cpp index 19e1d68ec..9bdd6d31d 100644 --- a/evmcc/BasicBlock.cpp +++ b/evmcc/BasicBlock.cpp @@ -6,9 +6,11 @@ namespace evmcc { +const char* BasicBlock::NamePrefix = "Instr."; + BasicBlock::BasicBlock(ProgramCounter _beginInstIdx, llvm::Function* _mainFunc): m_beginInstIdx(_beginInstIdx), - m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {"Instr.", std::to_string(_beginInstIdx)}, _mainFunc)) + m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {NamePrefix, std::to_string(_beginInstIdx)}, _mainFunc)) {} } \ No newline at end of file diff --git a/evmcc/BasicBlock.h b/evmcc/BasicBlock.h index 793dfaea2..83df5da24 100644 --- a/evmcc/BasicBlock.h +++ b/evmcc/BasicBlock.h @@ -13,6 +13,8 @@ class BasicBlock public: using State = std::vector; + static const char* NamePrefix; + explicit BasicBlock(ProgramCounter _beginInstIdx, llvm::Function* _mainFunc); BasicBlock(const BasicBlock&) = delete; diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index e5fe6db8b..2ae7ab1e7 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -797,14 +797,13 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) void Compiler::linkBasicBlocks() { /// Helper function that finds basic block given LLVM basic block pointer - auto findBB = [this](llvm::BasicBlock* _llvmBB) + auto findBasicBlock = [this](llvm::BasicBlock* _llbb) -> BasicBlock& { - for (auto&& bb : basicBlocks) - { - if (bb.second.llvm() == _llvmBB) - return &bb.second; - } - return (BasicBlock*)nullptr; + // Name is used to get basic block index (index of first instruction) + // TODO: If basicBlocs are still a map - multikey map can be used + auto&& idxStr = _llbb->getName().substr(sizeof(BasicBlock::NamePrefix) - 2); + auto idx = std::stoul(idxStr); + return basicBlocks.find(idx)->second; }; // Link basic blocks @@ -813,19 +812,16 @@ void Compiler::linkBasicBlocks() BasicBlock& bb = p.second; llvm::BasicBlock* llvmBB = bb.llvm(); - size_t i = 0; - for (auto& inst : *llvmBB) + size_t valueIdx = 0; + auto firstNonPhi = llvmBB->getFirstNonPHI(); + for (auto instIt = llvmBB->begin(); &*instIt != firstNonPhi; ++instIt, ++valueIdx) { - if (auto phi = llvm::dyn_cast(&inst)) + auto phi = llvm::cast(instIt); + for (auto predIt = llvm::pred_begin(llvmBB); predIt != llvm::pred_end(llvmBB); ++predIt) { - for (auto preIt = llvm::pred_begin(llvmBB); preIt != llvm::pred_end(llvmBB); ++preIt) - { - llvm::BasicBlock* preBB = *preIt; - auto pbb = findBB(preBB); - assert(i < pbb->getState().size()); // TODO: Report error - phi->addIncoming(*(pbb->getState().rbegin() + i), preBB); - } - ++i; + auto& predBB = findBasicBlock(*predIt); + assert(valueIdx < predBB.getState().size()); // TODO: Report error + phi->addIncoming(*(predBB.getState().rbegin() + valueIdx), predBB); } } } diff --git a/evmcc/Stack.cpp b/evmcc/Stack.cpp index 86b39316c..fc359f103 100644 --- a/evmcc/Stack.cpp +++ b/evmcc/Stack.cpp @@ -23,7 +23,7 @@ llvm::Value* BBStack::pop() // Create PHI node auto i256Ty = llvm::Type::getIntNTy(m_block->llvm()->getContext(), 256); auto llvmBB = m_block->llvm(); - if (llvmBB->getInstList().empty()) + if (llvmBB->empty()) return llvm::PHINode::Create(i256Ty, 0, {}, m_block->llvm()); return llvm::PHINode::Create(i256Ty, 0, {}, llvmBB->getFirstNonPHI()); } From 40ebe55a20f5d8ac5bc09123243fd8d66abc7dc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 7 Oct 2014 18:44:42 +0200 Subject: [PATCH 061/641] Provide end instruction to basic block --- evmcc/BasicBlock.cpp | 3 ++- evmcc/BasicBlock.h | 5 ++++- evmcc/Compiler.cpp | 41 ++++++++++++++++------------------------- evmcc/Compiler.h | 7 +++---- evmcc/Stack.h | 1 + 5 files changed, 26 insertions(+), 31 deletions(-) diff --git a/evmcc/BasicBlock.cpp b/evmcc/BasicBlock.cpp index 9bdd6d31d..487de0239 100644 --- a/evmcc/BasicBlock.cpp +++ b/evmcc/BasicBlock.cpp @@ -8,8 +8,9 @@ namespace evmcc const char* BasicBlock::NamePrefix = "Instr."; -BasicBlock::BasicBlock(ProgramCounter _beginInstIdx, llvm::Function* _mainFunc): +BasicBlock::BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx, llvm::Function* _mainFunc) : m_beginInstIdx(_beginInstIdx), + m_endInstIdx(_endInstIdx), m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {NamePrefix, std::to_string(_beginInstIdx)}, _mainFunc)) {} diff --git a/evmcc/BasicBlock.h b/evmcc/BasicBlock.h index 83df5da24..c842841f9 100644 --- a/evmcc/BasicBlock.h +++ b/evmcc/BasicBlock.h @@ -15,7 +15,7 @@ public: static const char* NamePrefix; - explicit BasicBlock(ProgramCounter _beginInstIdx, llvm::Function* _mainFunc); + explicit BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx, llvm::Function* _mainFunc); BasicBlock(const BasicBlock&) = delete; void operator=(const BasicBlock&) = delete; @@ -25,8 +25,11 @@ public: State& getState() { return m_state; } + void setEnd(ProgramCounter _endInstIdx) { m_endInstIdx = _endInstIdx; } + private: ProgramCounter m_beginInstIdx; + ProgramCounter m_endInstIdx; llvm::BasicBlock* m_llvmBB; /// Basic black state vector - current/end values and their positions diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 2ae7ab1e7..86fe94466 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -40,20 +40,10 @@ Compiler::Compiler() Types.WordLowPrecision = llvm::Type::getIntNTy(context, 64); } -BasicBlock& Compiler::getOrCreateBasicBlockAtPC(ProgramCounter pc) -{ - auto blockIter = basicBlocks.find(pc); - if (blockIter == basicBlocks.end()) - { - // Create a basic block at target pc directly in collection - blockIter = basicBlocks.emplace(std::piecewise_construct, std::forward_as_tuple(pc), std::forward_as_tuple(pc, m_mainFunc)).first; - } - return blockIter->second; -} - void Compiler::createBasicBlocks(const dev::bytes& bytecode) { - getOrCreateBasicBlockAtPC(0); // First basic block + std::set splitPoints; // Sorted collections of instruction indecies where basic blocks start/end + splitPoints.insert(0); // First basic block for (auto curr = bytecode.cbegin(); curr != bytecode.cend(); ++curr) { @@ -116,15 +106,15 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode) if (next + 1 < bytecode.cend()) { ProgramCounter nextPC = (next + 1 - bytecode.cbegin()); - getOrCreateBasicBlockAtPC(nextPC); + splitPoints.insert(nextPC); } // Create a block for the JUMP target. ProgramCounter targetPC = val.convert_to(); - auto& targetBlock = getOrCreateBasicBlockAtPC(targetPC); + splitPoints.insert(targetPC); ProgramCounter jumpPC = (next - bytecode.cbegin()); - jumpTargets[jumpPC] = targetBlock; + jumpTargets[jumpPC] = targetPC; curr += 1; // skip over JUMP } @@ -148,7 +138,7 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode) if (curr + 1 < bytecode.cend()) { ProgramCounter nextPC = (curr + 1 - bytecode.cbegin()); - getOrCreateBasicBlockAtPC(nextPC); + splitPoints.insert(nextPC); } break; } @@ -158,7 +148,14 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode) } } - getOrCreateBasicBlockAtPC(bytecode.size()); // Final basic block + splitPoints.insert(bytecode.size()); // For final block + for (auto it = splitPoints.cbegin(); it != splitPoints.cend();) + { + auto beginInstIdx = *it; + ++it; + auto endInstIdx = it != splitPoints.cend() ? *it : beginInstIdx; // For final block + basicBlocks.emplace(std::piecewise_construct, std::forward_as_tuple(beginInstIdx), std::forward_as_tuple(beginInstIdx, endInstIdx, m_mainFunc)); + } } std::unique_ptr Compiler::compile(const dev::bytes& bytecode) @@ -572,7 +569,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) // just pop it without looking... stack.pop(); - auto targetBlock = jumpTargets[currentPC]; + auto& targetBlock = basicBlocks.find(jumpTargets[currentPC])->second; builder.CreateBr(targetBlock); currentBlock = nullptr; @@ -590,7 +587,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto top = stack.pop(); auto zero = ConstantInt::get(Types.word256, 0); auto cond = builder.CreateICmpNE(top, zero, "nonzero"); - auto targetBlock = jumpTargets[currentPC]; + auto& targetBlock = basicBlocks.find(jumpTargets[currentPC])->second; auto& followBlock = basicBlocks.find(currentPC + 1)->second; builder.CreateCondBr(cond, targetBlock, followBlock); @@ -743,12 +740,6 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto index = stack.pop(); auto size = stack.pop(); - // MCJIT does not support returning structs - //auto index32 = builder.CreateTrunc(index, i32Ty, "index32"); - //auto size32 = builder.CreateTrunc(size, i32Ty, "size32"); - //auto ret = builder.CreateInsertValue(UndefValue::get(retType), index32, 0, "ret"); - //ret = builder.CreateInsertValue(ret, size32, 1, "ret"); - auto ret = builder.CreateTrunc(index, builder.getInt64Ty()); ret = builder.CreateShl(ret, 32); size = builder.CreateTrunc(size, i32Ty); diff --git a/evmcc/Compiler.h b/evmcc/Compiler.h index de73fb7a5..52a6bc9ac 100644 --- a/evmcc/Compiler.h +++ b/evmcc/Compiler.h @@ -22,7 +22,6 @@ public: private: - BasicBlock& getOrCreateBasicBlockAtPC(ProgramCounter pc); void createBasicBlocks(const dev::bytes& bytecode); void linkBasicBlocks(); @@ -33,16 +32,16 @@ private: std::map basicBlocks; /** - * Maps a pc at which there is a JUMP or JUMPI to the target block of the jump. + * Maps a pc at which there is a JUMP or JUMPI to the target pc of the jump. */ - std::map jumpTargets; + std::map jumpTargets; private: /// Collection of basic blocks in program //std::vector m_basicBlocks; /// Main program function - llvm::Function* m_mainFunc; + llvm::Function* m_mainFunc = nullptr; }; } diff --git a/evmcc/Stack.h b/evmcc/Stack.h index cc29a0074..4b81986b0 100644 --- a/evmcc/Stack.h +++ b/evmcc/Stack.h @@ -11,6 +11,7 @@ class BasicBlock; Stack adapter for Basic Block Transforms stack to SSA: tracks values and their positions on the imaginary stack used inside a basic block. + TODO: Integrate into BasicBlock class */ class BBStack { From bec3e0fb361d7b91c128bbb0c35d3b449b665462 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 7 Oct 2014 19:29:56 +0200 Subject: [PATCH 062/641] Cleanup Compiler --- evmcc/BasicBlock.h | 3 +- evmcc/Compiler.cpp | 1030 ++++++++++++++++++++++---------------------- 2 files changed, 511 insertions(+), 522 deletions(-) diff --git a/evmcc/BasicBlock.h b/evmcc/BasicBlock.h index c842841f9..ef53169d8 100644 --- a/evmcc/BasicBlock.h +++ b/evmcc/BasicBlock.h @@ -25,7 +25,8 @@ public: State& getState() { return m_state; } - void setEnd(ProgramCounter _endInstIdx) { m_endInstIdx = _endInstIdx; } + ProgramCounter begin() { return m_beginInstIdx; } + ProgramCounter end() { return m_endInstIdx; } private: ProgramCounter m_beginInstIdx; diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 86fe94466..9d29a166d 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -181,604 +181,592 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto memory = Memory(builder, module.get()); auto ext = Ext(builder, module.get()); - BasicBlock* currentBlock = &basicBlocks.find(0)->second; // Any value, just to create branch for %entry to %Instr.0 - BBStack stack; // Stack for current block + // Jump to first instruction + builder.CreateBr(basicBlocks.begin()->second); - for (auto pc = bytecode.cbegin(); pc != bytecode.cend(); ++pc) + for (auto basicBlockPairIt = basicBlocks.begin(); basicBlockPairIt != basicBlocks.end(); ++basicBlockPairIt) { - using dev::eth::Instruction; - - ProgramCounter currentPC = pc - bytecode.cbegin(); - - // Change basic block - auto blockIter = basicBlocks.find(currentPC); - if (blockIter != basicBlocks.end()) - { - auto& nextBlock = blockIter->second; - // Terminate the current block by jumping to the next one. - if (currentBlock != nullptr) - builder.CreateBr(nextBlock); - // Insert the next block into the main function. - builder.SetInsertPoint(nextBlock); - currentBlock = &nextBlock; - stack.setBasicBlock(*currentBlock); - } + auto& basicBlock = basicBlockPairIt->second; - assert(currentBlock != nullptr); + BBStack stack; + stack.setBasicBlock(basicBlock); + builder.SetInsertPoint(basicBlock); - auto inst = static_cast(*pc); - switch (inst) + for (auto currentPC = basicBlock.begin(); currentPC != basicBlock.end(); ++currentPC) { + using dev::eth::Instruction; + auto inst = static_cast(bytecode[currentPC]); + switch (inst) + { - case Instruction::ADD: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto result = builder.CreateAdd(lhs, rhs); - stack.push(result); - break; - } + case Instruction::ADD: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto result = builder.CreateAdd(lhs, rhs); + stack.push(result); + break; + } - case Instruction::SUB: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto result = builder.CreateSub(lhs, rhs); - stack.push(result); - break; - } + case Instruction::SUB: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto result = builder.CreateSub(lhs, rhs); + stack.push(result); + break; + } - case Instruction::MUL: - { - auto lhs256 = stack.pop(); - auto rhs256 = stack.pop(); - auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); - auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); - auto res128 = builder.CreateMul(lhs128, rhs128); - auto res256 = builder.CreateZExt(res128, Types.word256); - stack.push(res256); - break; - } + case Instruction::MUL: + { + auto lhs256 = stack.pop(); + auto rhs256 = stack.pop(); + auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); + auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); + auto res128 = builder.CreateMul(lhs128, rhs128); + auto res256 = builder.CreateZExt(res128, Types.word256); + stack.push(res256); + break; + } - case Instruction::DIV: - { - auto lhs256 = stack.pop(); - auto rhs256 = stack.pop(); - auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); - auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); - auto res128 = builder.CreateUDiv(lhs128, rhs128); - auto res256 = builder.CreateZExt(res128, Types.word256); - stack.push(res256); - break; - } + case Instruction::DIV: + { + auto lhs256 = stack.pop(); + auto rhs256 = stack.pop(); + auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); + auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); + auto res128 = builder.CreateUDiv(lhs128, rhs128); + auto res256 = builder.CreateZExt(res128, Types.word256); + stack.push(res256); + break; + } - case Instruction::SDIV: - { - auto lhs256 = stack.pop(); - auto rhs256 = stack.pop(); - auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); - auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); - auto res128 = builder.CreateSDiv(lhs128, rhs128); - auto res256 = builder.CreateSExt(res128, Types.word256); - stack.push(res256); - break; - } + case Instruction::SDIV: + { + auto lhs256 = stack.pop(); + auto rhs256 = stack.pop(); + auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); + auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); + auto res128 = builder.CreateSDiv(lhs128, rhs128); + auto res256 = builder.CreateSExt(res128, Types.word256); + stack.push(res256); + break; + } - case Instruction::MOD: - { - auto lhs256 = stack.pop(); - auto rhs256 = stack.pop(); - auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); - auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); - auto res128 = builder.CreateURem(lhs128, rhs128); - auto res256 = builder.CreateZExt(res128, Types.word256); - stack.push(res256); - break; - } + case Instruction::MOD: + { + auto lhs256 = stack.pop(); + auto rhs256 = stack.pop(); + auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); + auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); + auto res128 = builder.CreateURem(lhs128, rhs128); + auto res256 = builder.CreateZExt(res128, Types.word256); + stack.push(res256); + break; + } - case Instruction::SMOD: - { - auto lhs256 = stack.pop(); - auto rhs256 = stack.pop(); - auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); - auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); - auto res128 = builder.CreateSRem(lhs128, rhs128); - auto res256 = builder.CreateSExt(res128, Types.word256); - stack.push(res256); - break; - } + case Instruction::SMOD: + { + auto lhs256 = stack.pop(); + auto rhs256 = stack.pop(); + auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); + auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); + auto res128 = builder.CreateSRem(lhs128, rhs128); + auto res256 = builder.CreateSExt(res128, Types.word256); + stack.push(res256); + break; + } - case Instruction::NEG: - { - auto top = stack.pop(); - auto zero = ConstantInt::get(Types.word256, 0); - auto res = builder.CreateSub(zero, top); - stack.push(res); - break; - } + case Instruction::NEG: + { + auto top = stack.pop(); + auto zero = ConstantInt::get(Types.word256, 0); + auto res = builder.CreateSub(zero, top); + stack.push(res); + break; + } - case Instruction::LT: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res1 = builder.CreateICmpULT(lhs, rhs); - auto res256 = builder.CreateZExt(res1, Types.word256); - stack.push(res256); - break; - } + case Instruction::LT: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res1 = builder.CreateICmpULT(lhs, rhs); + auto res256 = builder.CreateZExt(res1, Types.word256); + stack.push(res256); + break; + } - case Instruction::GT: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res1 = builder.CreateICmpUGT(lhs, rhs); - auto res256 = builder.CreateZExt(res1, Types.word256); - stack.push(res256); - break; - } + case Instruction::GT: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res1 = builder.CreateICmpUGT(lhs, rhs); + auto res256 = builder.CreateZExt(res1, Types.word256); + stack.push(res256); + break; + } - case Instruction::SLT: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res1 = builder.CreateICmpSLT(lhs, rhs); - auto res256 = builder.CreateZExt(res1, Types.word256); - stack.push(res256); - break; - } + case Instruction::SLT: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res1 = builder.CreateICmpSLT(lhs, rhs); + auto res256 = builder.CreateZExt(res1, Types.word256); + stack.push(res256); + break; + } - case Instruction::SGT: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res1 = builder.CreateICmpSGT(lhs, rhs); - auto res256 = builder.CreateZExt(res1, Types.word256); - stack.push(res256); - break; - } + case Instruction::SGT: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res1 = builder.CreateICmpSGT(lhs, rhs); + auto res256 = builder.CreateZExt(res1, Types.word256); + stack.push(res256); + break; + } - case Instruction::EQ: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res1 = builder.CreateICmpEQ(lhs, rhs); - auto res256 = builder.CreateZExt(res1, Types.word256); - stack.push(res256); - break; - } + case Instruction::EQ: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res1 = builder.CreateICmpEQ(lhs, rhs); + auto res256 = builder.CreateZExt(res1, Types.word256); + stack.push(res256); + break; + } - case Instruction::NOT: - { - auto top = stack.pop(); - auto zero = ConstantInt::get(Types.word256, 0); - auto iszero = builder.CreateICmpEQ(top, zero, "iszero"); - auto result = builder.CreateZExt(iszero, Types.word256); - stack.push(result); - break; - } - - case Instruction::AND: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = builder.CreateAnd(lhs, rhs); - stack.push(res); - break; - } + case Instruction::NOT: + { + auto top = stack.pop(); + auto zero = ConstantInt::get(Types.word256, 0); + auto iszero = builder.CreateICmpEQ(top, zero, "iszero"); + auto result = builder.CreateZExt(iszero, Types.word256); + stack.push(result); + break; + } - case Instruction::OR: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = builder.CreateOr(lhs, rhs); - stack.push(res); - break; - } + case Instruction::AND: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = builder.CreateAnd(lhs, rhs); + stack.push(res); + break; + } - case Instruction::XOR: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = builder.CreateXor(lhs, rhs); - stack.push(res); - break; - } + case Instruction::OR: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = builder.CreateOr(lhs, rhs); + stack.push(res); + break; + } - case Instruction::BYTE: - { - const auto byteNum = stack.pop(); - auto value = stack.pop(); + case Instruction::XOR: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = builder.CreateXor(lhs, rhs); + stack.push(res); + break; + } - /* - if (byteNum < 32) - use select + case Instruction::BYTE: { + const auto byteNum = stack.pop(); + auto value = stack.pop(); + + /* + if (byteNum < 32) - use select + { value <<= byteNum*8 value >>= 31*8 push value - } - else push 0 - */ + } + else push 0 + */ - // TODO: Shifting by 0 gives wrong results as of this bug http://llvm.org/bugs/show_bug.cgi?id=16439 - - auto shbits = builder.CreateShl(byteNum, builder.getIntN(256, 3)); - value = builder.CreateShl(value, shbits); - value = builder.CreateLShr(value, builder.getIntN(256, 31 * 8)); + // TODO: Shifting by 0 gives wrong results as of this bug http://llvm.org/bugs/show_bug.cgi?id=16439 - auto byteNumValid = builder.CreateICmpULT(byteNum, builder.getIntN(256, 32)); - value = builder.CreateSelect(byteNumValid, value, builder.getIntN(256, 0)); - stack.push(value); + auto shbits = builder.CreateShl(byteNum, builder.getIntN(256, 3)); + value = builder.CreateShl(value, shbits); + value = builder.CreateLShr(value, builder.getIntN(256, 31 * 8)); - break; - } + auto byteNumValid = builder.CreateICmpULT(byteNum, builder.getIntN(256, 32)); + value = builder.CreateSelect(byteNumValid, value, builder.getIntN(256, 0)); + stack.push(value); - case Instruction::SHA3: - { - auto inOff = stack.pop(); - auto inSize = stack.pop(); - auto hash = ext.sha3(inOff, inSize); - stack.push(hash); - } + break; + } - case Instruction::POP: - { - stack.pop(); - break; - } + case Instruction::SHA3: + { + auto inOff = stack.pop(); + auto inSize = stack.pop(); + auto hash = ext.sha3(inOff, inSize); + stack.push(hash); + } - case Instruction::PUSH1: - case Instruction::PUSH2: - case Instruction::PUSH3: - case Instruction::PUSH4: - case Instruction::PUSH5: - case Instruction::PUSH6: - case Instruction::PUSH7: - case Instruction::PUSH8: - case Instruction::PUSH9: - case Instruction::PUSH10: - case Instruction::PUSH11: - case Instruction::PUSH12: - case Instruction::PUSH13: - case Instruction::PUSH14: - case Instruction::PUSH15: - case Instruction::PUSH16: - case Instruction::PUSH17: - case Instruction::PUSH18: - case Instruction::PUSH19: - case Instruction::PUSH20: - case Instruction::PUSH21: - case Instruction::PUSH22: - case Instruction::PUSH23: - case Instruction::PUSH24: - case Instruction::PUSH25: - case Instruction::PUSH26: - case Instruction::PUSH27: - case Instruction::PUSH28: - case Instruction::PUSH29: - case Instruction::PUSH30: - case Instruction::PUSH31: - case Instruction::PUSH32: - { - auto numBytes = static_cast(inst) - static_cast(Instruction::PUSH1) + 1; - auto value = llvm::APInt(256, 0); - for (decltype(numBytes) i = 0; i < numBytes; ++i) // TODO: Use pc as iterator + case Instruction::POP: { - ++pc; - value <<= 8; - value |= *pc; + stack.pop(); + break; } - auto c = builder.getInt(value); - stack.push(c); - break; - } - case Instruction::DUP1: - case Instruction::DUP2: - case Instruction::DUP3: - case Instruction::DUP4: - case Instruction::DUP5: - case Instruction::DUP6: - case Instruction::DUP7: - case Instruction::DUP8: - case Instruction::DUP9: - case Instruction::DUP10: - case Instruction::DUP11: - case Instruction::DUP12: - case Instruction::DUP13: - case Instruction::DUP14: - case Instruction::DUP15: - case Instruction::DUP16: - { - auto index = static_cast(inst) - static_cast(Instruction::DUP1); - stack.dup(index); - break; - } + case Instruction::PUSH1: + case Instruction::PUSH2: + case Instruction::PUSH3: + case Instruction::PUSH4: + case Instruction::PUSH5: + case Instruction::PUSH6: + case Instruction::PUSH7: + case Instruction::PUSH8: + case Instruction::PUSH9: + case Instruction::PUSH10: + case Instruction::PUSH11: + case Instruction::PUSH12: + case Instruction::PUSH13: + case Instruction::PUSH14: + case Instruction::PUSH15: + case Instruction::PUSH16: + case Instruction::PUSH17: + case Instruction::PUSH18: + case Instruction::PUSH19: + case Instruction::PUSH20: + case Instruction::PUSH21: + case Instruction::PUSH22: + case Instruction::PUSH23: + case Instruction::PUSH24: + case Instruction::PUSH25: + case Instruction::PUSH26: + case Instruction::PUSH27: + case Instruction::PUSH28: + case Instruction::PUSH29: + case Instruction::PUSH30: + case Instruction::PUSH31: + case Instruction::PUSH32: + { + auto numBytes = static_cast(inst)-static_cast(Instruction::PUSH1) + 1; + auto value = llvm::APInt(256, 0); + for (decltype(numBytes) i = 0; i < numBytes; ++i) // TODO: Use pc as iterator + { + ++currentPC; + value <<= 8; + value |= bytecode[currentPC]; + } + auto c = builder.getInt(value); + stack.push(c); + break; + } - case Instruction::SWAP1: - case Instruction::SWAP2: - case Instruction::SWAP3: - case Instruction::SWAP4: - case Instruction::SWAP5: - case Instruction::SWAP6: - case Instruction::SWAP7: - case Instruction::SWAP8: - case Instruction::SWAP9: - case Instruction::SWAP10: - case Instruction::SWAP11: - case Instruction::SWAP12: - case Instruction::SWAP13: - case Instruction::SWAP14: - case Instruction::SWAP15: - case Instruction::SWAP16: - { - auto index = static_cast(inst) - static_cast(Instruction::SWAP1) + 1; - stack.swap(index); - break; - } + case Instruction::DUP1: + case Instruction::DUP2: + case Instruction::DUP3: + case Instruction::DUP4: + case Instruction::DUP5: + case Instruction::DUP6: + case Instruction::DUP7: + case Instruction::DUP8: + case Instruction::DUP9: + case Instruction::DUP10: + case Instruction::DUP11: + case Instruction::DUP12: + case Instruction::DUP13: + case Instruction::DUP14: + case Instruction::DUP15: + case Instruction::DUP16: + { + auto index = static_cast(inst)-static_cast(Instruction::DUP1); + stack.dup(index); + break; + } - case Instruction::MLOAD: - { - auto addr = stack.pop(); - auto word = memory.loadWord(addr); - stack.push(word); - break; - } + case Instruction::SWAP1: + case Instruction::SWAP2: + case Instruction::SWAP3: + case Instruction::SWAP4: + case Instruction::SWAP5: + case Instruction::SWAP6: + case Instruction::SWAP7: + case Instruction::SWAP8: + case Instruction::SWAP9: + case Instruction::SWAP10: + case Instruction::SWAP11: + case Instruction::SWAP12: + case Instruction::SWAP13: + case Instruction::SWAP14: + case Instruction::SWAP15: + case Instruction::SWAP16: + { + auto index = static_cast(inst)-static_cast(Instruction::SWAP1) + 1; + stack.swap(index); + break; + } - case Instruction::MSTORE: - { - auto addr = stack.pop(); - auto word = stack.pop(); - memory.storeWord(addr, word); - break; - } + case Instruction::MLOAD: + { + auto addr = stack.pop(); + auto word = memory.loadWord(addr); + stack.push(word); + break; + } - case Instruction::MSTORE8: - { - auto addr = stack.pop(); - auto word = stack.pop(); - memory.storeByte(addr, word); - break; - } + case Instruction::MSTORE: + { + auto addr = stack.pop(); + auto word = stack.pop(); + memory.storeWord(addr, word); + break; + } - case Instruction::MSIZE: - { - auto word = memory.getSize(); - stack.push(word); - break; - } + case Instruction::MSTORE8: + { + auto addr = stack.pop(); + auto word = stack.pop(); + memory.storeByte(addr, word); + break; + } - case Instruction::SLOAD: - { - auto index = stack.pop(); - auto value = ext.store(index); - stack.push(value); - break; - } + case Instruction::MSIZE: + { + auto word = memory.getSize(); + stack.push(word); + break; + } - case Instruction::SSTORE: - { - auto index = stack.pop(); - auto value = stack.pop(); - ext.setStore(index, value); - break; - } + case Instruction::SLOAD: + { + auto index = stack.pop(); + auto value = ext.store(index); + stack.push(value); + break; + } - case Instruction::JUMP: - { - // The target address is computed at compile time, - // just pop it without looking... - stack.pop(); + case Instruction::SSTORE: + { + auto index = stack.pop(); + auto value = stack.pop(); + ext.setStore(index, value); + break; + } - auto& targetBlock = basicBlocks.find(jumpTargets[currentPC])->second; - builder.CreateBr(targetBlock); + case Instruction::JUMP: + { + // The target address is computed at compile time, + // just pop it without looking... + stack.pop(); - currentBlock = nullptr; - break; - } + auto& targetBlock = basicBlocks.find(jumpTargets[currentPC])->second; + builder.CreateBr(targetBlock); + break; + } - case Instruction::JUMPI: - { - assert(pc + 1 < bytecode.cend()); + case Instruction::JUMPI: + { + assert(currentPC + 1 < bytecode.size()); + + // The target address is computed at compile time, + // just pop it without looking... + stack.pop(); + + auto top = stack.pop(); + auto zero = ConstantInt::get(Types.word256, 0); + auto cond = builder.CreateICmpNE(top, zero, "nonzero"); + auto& targetBlock = basicBlocks.find(jumpTargets[currentPC])->second; + auto& followBlock = basicBlocks.find(currentPC + 1)->second; + builder.CreateCondBr(cond, targetBlock, followBlock); + break; + } - // The target address is computed at compile time, - // just pop it without looking... - stack.pop(); + case Instruction::PC: + { + auto value = builder.getIntN(256, currentPC); + stack.push(value); + break; + } - auto top = stack.pop(); - auto zero = ConstantInt::get(Types.word256, 0); - auto cond = builder.CreateICmpNE(top, zero, "nonzero"); - auto& targetBlock = basicBlocks.find(jumpTargets[currentPC])->second; - auto& followBlock = basicBlocks.find(currentPC + 1)->second; - builder.CreateCondBr(cond, targetBlock, followBlock); + case Instruction::ADDRESS: + { + auto value = ext.address(); + stack.push(value); + break; + } - currentBlock = nullptr; - break; - } + case Instruction::BALANCE: + { + auto address = stack.pop(); + auto value = ext.balance(address); + stack.push(value); + break; + } - case Instruction::PC: - { - auto value = builder.getIntN(256, currentPC); - stack.push(value); - break; - } + case Instruction::CALLER: + { + auto value = ext.caller(); + stack.push(value); + break; + } - case Instruction::ADDRESS: - { - auto value = ext.address(); - stack.push(value); - break; - } + case Instruction::ORIGIN: + { + auto value = ext.origin(); + stack.push(value); + break; + } - case Instruction::BALANCE: - { - auto address = stack.pop(); - auto value = ext.balance(address); - stack.push(value); - break; - } + case Instruction::CALLVALUE: + { + auto value = ext.callvalue(); + stack.push(value); + break; + } - case Instruction::CALLER: - { - auto value = ext.caller(); - stack.push(value); - break; - } + case Instruction::CALLDATASIZE: + { + auto value = ext.calldatasize(); + stack.push(value); + break; + } - case Instruction::ORIGIN: - { - auto value = ext.origin(); - stack.push(value); - break; - } + case Instruction::CALLDATALOAD: + { + auto index = stack.pop(); + auto value = ext.calldataload(index); + stack.push(value); + break; + } - case Instruction::CALLVALUE: - { - auto value = ext.callvalue(); - stack.push(value); - break; - } + case Instruction::GASPRICE: + { + auto value = ext.gasprice(); + stack.push(value); + break; + } - case Instruction::CALLDATASIZE: - { - auto value = ext.calldatasize(); - stack.push(value); - break; - } + case Instruction::CODESIZE: + { + auto value = builder.getIntN(256, bytecode.size()); + stack.push(value); + break; + } - case Instruction::CALLDATALOAD: - { - auto index = stack.pop(); - auto value = ext.calldataload(index); - stack.push(value); - break; - } + case Instruction::PREVHASH: + { + auto value = ext.prevhash(); + stack.push(value); + break; + } - case Instruction::GASPRICE: - { - auto value = ext.gasprice(); - stack.push(value); - break; - } + case Instruction::COINBASE: + { + auto value = ext.coinbase(); + stack.push(value); + break; + } - case Instruction::CODESIZE: - { - auto value = builder.getIntN(256, bytecode.size()); - stack.push(value); - break; - } + case Instruction::TIMESTAMP: + { + auto value = ext.timestamp(); + stack.push(value); + break; + } - case Instruction::PREVHASH: - { - auto value = ext.prevhash(); - stack.push(value); - break; - } + case Instruction::NUMBER: + { + auto value = ext.number(); + stack.push(value); + break; + } - case Instruction::COINBASE: - { - auto value = ext.coinbase(); - stack.push(value); - break; - } + case Instruction::DIFFICULTY: + { + auto value = ext.difficulty(); + stack.push(value); + break; + } - case Instruction::TIMESTAMP: - { - auto value = ext.timestamp(); - stack.push(value); - break; - } + case Instruction::GASLIMIT: + { + auto value = ext.gaslimit(); + stack.push(value); + break; + } - case Instruction::NUMBER: - { - auto value = ext.number(); - stack.push(value); - break; - } + case Instruction::CREATE: + { + auto endowment = stack.pop(); + auto initOff = stack.pop(); + auto initSize = stack.pop(); - case Instruction::DIFFICULTY: - { - auto value = ext.difficulty(); - stack.push(value); - break; - } + auto address = ext.create(endowment, initOff, initSize); + stack.push(address); + break; + } - case Instruction::GASLIMIT: - { - auto value = ext.gaslimit(); - stack.push(value); - break; - } - - case Instruction::CREATE: - { - auto endowment = stack.pop(); - auto initOff = stack.pop(); - auto initSize = stack.pop(); + case Instruction::CALL: + { + auto gas = stack.pop(); + auto receiveAddress = stack.pop(); + auto value = stack.pop(); + auto inOff = stack.pop(); + auto inSize = stack.pop(); + auto outOff = stack.pop(); + auto outSize = stack.pop(); + + auto ret = ext.call(gas, receiveAddress, value, inOff, inSize, outOff, outSize); + stack.push(ret); + break; + } - auto address = ext.create(endowment, initOff, initSize); - stack.push(address); - break; - } + case Instruction::RETURN: + { + auto index = stack.pop(); + auto size = stack.pop(); - case Instruction::CALL: - { - auto gas = stack.pop(); - auto receiveAddress = stack.pop(); - auto value = stack.pop(); - auto inOff = stack.pop(); - auto inSize = stack.pop(); - auto outOff = stack.pop(); - auto outSize = stack.pop(); - - auto ret = ext.call(gas, receiveAddress, value, inOff, inSize, outOff, outSize); - stack.push(ret); - break; - } + auto ret = builder.CreateTrunc(index, builder.getInt64Ty()); + ret = builder.CreateShl(ret, 32); + size = builder.CreateTrunc(size, i32Ty); + size = builder.CreateZExt(size, builder.getInt64Ty()); + ret = builder.CreateOr(ret, size); - case Instruction::RETURN: - { - auto index = stack.pop(); - auto size = stack.pop(); + builder.CreateRet(ret); + break; + } - auto ret = builder.CreateTrunc(index, builder.getInt64Ty()); - ret = builder.CreateShl(ret, 32); - size = builder.CreateTrunc(size, i32Ty); - size = builder.CreateZExt(size, builder.getInt64Ty()); - ret = builder.CreateOr(ret, size); + case Instruction::SUICIDE: + { + auto address = stack.pop(); + ext.suicide(address); + // Fall through + } + case Instruction::STOP: + { + builder.CreateRet(builder.getInt64(0)); + break; + } - builder.CreateRet(ret); - currentBlock = nullptr; - break; - } + } - case Instruction::SUICIDE: - { - auto address = stack.pop(); - ext.suicide(address); - // Fall through - } - case Instruction::STOP: - { - builder.CreateRet(builder.getInt64(0)); - currentBlock = nullptr; - break; } + if (!builder.GetInsertBlock()->getTerminator()) // If block not terminated + { + if (basicBlock.begin() == bytecode.size()) // Special final block + { + builder.CreateRet(builder.getInt64(0)); + } + else + { + auto iterCopy = basicBlockPairIt; + ++iterCopy; + auto& next = iterCopy->second; + builder.CreateBr(next); + } } } - // Generate the final basic block. - auto finalPC = bytecode.size(); - auto it = basicBlocks.find(finalPC); - assert(it != basicBlocks.end()); - auto& finalBlock = it->second; - - if (currentBlock != nullptr) - builder.CreateBr(finalBlock); - - builder.SetInsertPoint(finalBlock); - builder.CreateRet(builder.getInt64(0)); - linkBasicBlocks(); return module; From 66123e8b35bfabee15073ff09a8ddccfc62959a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 8 Oct 2014 12:45:46 +0200 Subject: [PATCH 063/641] JUMP test in assembly --- evmcc/lll/stackjump.lll | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 evmcc/lll/stackjump.lll diff --git a/evmcc/lll/stackjump.lll b/evmcc/lll/stackjump.lll new file mode 100644 index 000000000..f5da5e733 --- /dev/null +++ b/evmcc/lll/stackjump.lll @@ -0,0 +1,3 @@ +(asm +0x4 0x6 0x9 0x13 JUMP 0xa SUB 0x0 MSTORE MSIZE 0x0 RETURN 0x0 MSTORE ADD 0x9 JUMP +) From 0ec77d681c94fdf5cf2fad8978dcd7f654925db5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 8 Oct 2014 14:56:26 +0200 Subject: [PATCH 064/641] Make the Stack an integral part of BasicBlock --- evmcc/BasicBlock.cpp | 37 +++++++++++++++++++++- evmcc/BasicBlock.h | 51 +++++++++++++++++++++++++----- evmcc/Compiler.cpp | 9 ++---- evmcc/Stack.cpp | 59 ----------------------------------- evmcc/Stack.h | 47 ---------------------------- windows/evmcc.vcxproj | 2 -- windows/evmcc.vcxproj.filters | 2 -- 7 files changed, 82 insertions(+), 125 deletions(-) delete mode 100644 evmcc/Stack.cpp delete mode 100644 evmcc/Stack.h diff --git a/evmcc/BasicBlock.cpp b/evmcc/BasicBlock.cpp index 487de0239..e5cdf386f 100644 --- a/evmcc/BasicBlock.cpp +++ b/evmcc/BasicBlock.cpp @@ -2,6 +2,7 @@ #include "BasicBlock.h" #include +#include namespace evmcc { @@ -11,7 +12,41 @@ const char* BasicBlock::NamePrefix = "Instr."; BasicBlock::BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx, llvm::Function* _mainFunc) : m_beginInstIdx(_beginInstIdx), m_endInstIdx(_endInstIdx), - m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {NamePrefix, std::to_string(_beginInstIdx)}, _mainFunc)) + m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {NamePrefix, std::to_string(_beginInstIdx)}, _mainFunc)), + m_stack(m_llvmBB) {} + +void BasicBlock::Stack::push(llvm::Value* _value) +{ + m_backend.push_back(_value); +} + +llvm::Value* BasicBlock::Stack::pop() +{ + if (m_backend.empty()) + { + // Create PHI node + auto i256Ty = llvm::Type::getIntNTy(m_llvmBB->getContext(), 256); + if (m_llvmBB->empty()) + return llvm::PHINode::Create(i256Ty, 0, {}, m_llvmBB); + return llvm::PHINode::Create(i256Ty, 0, {}, m_llvmBB->getFirstNonPHI()); + } + + auto top = m_backend.back(); + m_backend.pop_back(); + return top; +} + +void BasicBlock::Stack::dup(size_t _index) +{ + m_backend.push_back(get(_index)); +} + +void BasicBlock::Stack::swap(size_t _index) +{ + assert(_index != 0); + std::swap(get(0), get(_index)); +} + } \ No newline at end of file diff --git a/evmcc/BasicBlock.h b/evmcc/BasicBlock.h index ef53169d8..500ddb95b 100644 --- a/evmcc/BasicBlock.h +++ b/evmcc/BasicBlock.h @@ -6,13 +6,47 @@ namespace evmcc { -using ProgramCounter = uint64_t; +using ProgramCounter = uint64_t; // TODO: Rename class BasicBlock { public: - using State = std::vector; + class Stack + { + public: + /// Pushes value on stack + void push(llvm::Value* _value); + /// Pops and returns top value + llvm::Value* pop(); + + /// Gets _index'th value from top (counting from 0) + llvm::Value*& get(size_t _index) { return *(m_backend.rbegin() + _index); } + + /// Duplicates _index'th value on stack. + void dup(size_t _index); + + /// Swaps _index'th value on stack with a value on stack top. + /// @param _index Index of value to be swaped. Cannot be 0. + void swap(size_t _index); + + /// Size of the stack + size_t size() const { return m_backend.size(); } + + private: + Stack(llvm::BasicBlock* _llvmBB) : m_llvmBB(_llvmBB) {} + Stack(const Stack&) = delete; + void operator=(const Stack&) = delete; + friend BasicBlock; + + private: + std::vector m_backend; + + /// LLVM Basic Block where phi nodes are inserted + llvm::BasicBlock* const m_llvmBB; + }; + + /// Basic block name prefix. The rest is beging instruction index. static const char* NamePrefix; explicit BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx, llvm::Function* _mainFunc); @@ -23,18 +57,19 @@ public: operator llvm::BasicBlock*() { return m_llvmBB; } llvm::BasicBlock* llvm() { return m_llvmBB; } - State& getState() { return m_state; } + Stack& getStack() { return m_stack; } ProgramCounter begin() { return m_beginInstIdx; } ProgramCounter end() { return m_endInstIdx; } private: - ProgramCounter m_beginInstIdx; - ProgramCounter m_endInstIdx; - llvm::BasicBlock* m_llvmBB; + ProgramCounter const m_beginInstIdx; + ProgramCounter const m_endInstIdx; + llvm::BasicBlock* const m_llvmBB; - /// Basic black state vector - current/end values and their positions - State m_state; + /// Basic black state vector (stack) - current/end values and their positions on stack + /// @internal Must be AFTER m_llvmBB + Stack m_stack; }; } \ No newline at end of file diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 9d29a166d..c46dd72c5 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -7,7 +7,6 @@ #include #include "Memory.h" -#include "Stack.h" #include "Ext.h" namespace evmcc @@ -187,9 +186,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) for (auto basicBlockPairIt = basicBlocks.begin(); basicBlockPairIt != basicBlocks.end(); ++basicBlockPairIt) { auto& basicBlock = basicBlockPairIt->second; - - BBStack stack; - stack.setBasicBlock(basicBlock); + auto& stack = basicBlock.getStack(); builder.SetInsertPoint(basicBlock); for (auto currentPC = basicBlock.begin(); currentPC != basicBlock.end(); ++currentPC) @@ -799,8 +796,8 @@ void Compiler::linkBasicBlocks() for (auto predIt = llvm::pred_begin(llvmBB); predIt != llvm::pred_end(llvmBB); ++predIt) { auto& predBB = findBasicBlock(*predIt); - assert(valueIdx < predBB.getState().size()); // TODO: Report error - phi->addIncoming(*(predBB.getState().rbegin() + valueIdx), predBB); + assert(valueIdx < predBB.getStack().size()); // TODO: Report error + phi->addIncoming(predBB.getStack().get(valueIdx), predBB); } } } diff --git a/evmcc/Stack.cpp b/evmcc/Stack.cpp deleted file mode 100644 index fc359f103..000000000 --- a/evmcc/Stack.cpp +++ /dev/null @@ -1,59 +0,0 @@ - -#include "Stack.h" - -#include - -#include - -#include "BasicBlock.h" - -namespace evmcc -{ - -void BBStack::push(llvm::Value* _value) -{ - m_block->getState().push_back(_value); -} - -llvm::Value* BBStack::pop() -{ - auto&& state = m_block->getState(); - if (state.empty()) - { - // Create PHI node - auto i256Ty = llvm::Type::getIntNTy(m_block->llvm()->getContext(), 256); - auto llvmBB = m_block->llvm(); - if (llvmBB->empty()) - return llvm::PHINode::Create(i256Ty, 0, {}, m_block->llvm()); - return llvm::PHINode::Create(i256Ty, 0, {}, llvmBB->getFirstNonPHI()); - } - - auto top = state.back(); - state.pop_back(); - return top; -} - -void BBStack::setBasicBlock(BasicBlock& _newBlock) -{ - // Current block keeps end state - // Just update pointer to current block - // New block should have empty state - assert(_newBlock.getState().empty()); - m_block = &_newBlock; -} - -void BBStack::dup(size_t _index) -{ - auto&& state = m_block->getState(); - auto value = *(state.rbegin() + _index); - state.push_back(value); -} - -void BBStack::swap(size_t _index) -{ - assert(_index != 0); - auto&& state = m_block->getState(); - std::swap(*state.rbegin(), *(state.rbegin() + _index)); -} - -} diff --git a/evmcc/Stack.h b/evmcc/Stack.h deleted file mode 100644 index 4b81986b0..000000000 --- a/evmcc/Stack.h +++ /dev/null @@ -1,47 +0,0 @@ - -#pragma once - -#include - -namespace evmcc -{ -class BasicBlock; - -/** - Stack adapter for Basic Block - - Transforms stack to SSA: tracks values and their positions on the imaginary stack used inside a basic block. - TODO: Integrate into BasicBlock class - */ -class BBStack -{ -public: - BBStack() = default; - BBStack(const BBStack&) = delete; - void operator=(const BBStack&) = delete; - - /** - Changes current basic block (if any) with a new one with empty state. - */ - void setBasicBlock(BasicBlock& _newBlock); - - void push(llvm::Value* _value); - llvm::Value* pop(); - - /** - Duplicates _index'th value on stack. - */ - void dup(size_t _index); - - /** - Swaps _index'th value on stack with a value on stack top. - @param _index Index of value to be swaped. Cannot be 0. - */ - void swap(size_t _index); - -private: - BasicBlock* m_block = nullptr; ///< Current basic block -}; - - -} \ No newline at end of file diff --git a/windows/evmcc.vcxproj b/windows/evmcc.vcxproj index 8226abb6c..ecf23fa05 100644 --- a/windows/evmcc.vcxproj +++ b/windows/evmcc.vcxproj @@ -26,7 +26,6 @@ - @@ -36,7 +35,6 @@ - diff --git a/windows/evmcc.vcxproj.filters b/windows/evmcc.vcxproj.filters index 05f375ac5..29ff77ba5 100644 --- a/windows/evmcc.vcxproj.filters +++ b/windows/evmcc.vcxproj.filters @@ -4,7 +4,6 @@ - @@ -14,7 +13,6 @@ - From 1a4cbdabef571bdfe2fcaba024f53fe8f64fbfc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 9 Oct 2014 09:33:31 +0200 Subject: [PATCH 065/641] EXP instruction. [Delivers #79736422] --- evmcc/Compiler.cpp | 9 +++++++++ evmcc/Ext.cpp | 18 ++++++++++++++++++ evmcc/Ext.h | 2 ++ evmcc/bytecode/arithmetic_test.evm | 2 +- evmcc/lll/arithmetic_test.lll | 8 ++++++++ 5 files changed, 38 insertions(+), 1 deletion(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index c46dd72c5..880487705 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -274,6 +274,15 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::EXP: + { + auto left = stack.pop(); + auto right = stack.pop(); + auto ret = ext.exp(left, right); + stack.push(ret); + break; + } + case Instruction::NEG: { auto top = stack.pop(); diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index 8266bd728..121103354 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -93,6 +93,7 @@ Ext::Ext(llvm::IRBuilder<>& _builder, llvm::Module* module) m_call = Function::Create(FunctionType::get(m_builder.getVoidTy(), args, false), Linkage::ExternalLinkage, "ext_call", module); m_bswap = Intrinsic::getDeclaration(module, Intrinsic::bswap, i256Ty); m_sha3 = Function::Create(TypeBuilder*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_sha3", module); + m_exp = Function::Create(TypeBuilder*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_exp", module); m_builder.CreateCall(m_init, m_data); @@ -196,6 +197,15 @@ llvm::Value* Ext::sha3(llvm::Value* _inOff, llvm::Value* _inSize) return hash; } +llvm::Value* Ext::exp(llvm::Value* _left, llvm::Value* _right) +{ + m_builder.CreateStore(_left, m_args[0]); + m_builder.CreateStore(_right, m_arg2); + llvm::Value* args[] = {m_args[0], m_arg2, m_args[1]}; + m_builder.CreateCall(m_exp, args); + return m_builder.CreateLoad(m_args[1]); +} + extern "C" { @@ -308,6 +318,14 @@ EXPORT void ext_sha3(i256* _inOff, i256* _inSize, i256* _ret) *_ret = *reinterpret_cast(&hash); } +EXPORT void ext_exp(i256* _left, i256* _right, i256* _ret) +{ + dev::bigint left = llvm2eth(*_left); + dev::bigint right = llvm2eth(*_right); + auto ret = static_cast(boost::multiprecision::powm(left, right, dev::bigint(2) << 256)); + *_ret = eth2llvm(ret); +} + } } diff --git a/evmcc/Ext.h b/evmcc/Ext.h index 7801d0540..302991854 100644 --- a/evmcc/Ext.h +++ b/evmcc/Ext.h @@ -39,6 +39,7 @@ public: llvm::Value* call(llvm::Value* _gas, llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize); llvm::Value* sha3(llvm::Value* _inOff, llvm::Value* _inSize); + llvm::Value* exp(llvm::Value* _left, llvm::Value* _right); private: llvm::Value* getDataElem(unsigned _index, const llvm::Twine& _name = ""); @@ -66,6 +67,7 @@ private: llvm::Function* m_call; llvm::Function* m_bswap; llvm::Function* m_sha3; + llvm::Function* m_exp; }; diff --git a/evmcc/bytecode/arithmetic_test.evm b/evmcc/bytecode/arithmetic_test.evm index 67e86b310..c7a029f52 100644 --- a/evmcc/bytecode/arithmetic_test.evm +++ b/evmcc/bytecode/arithmetic_test.evm @@ -1 +1 @@ -60016001900160070260050160029004600490066021900560150160030260059007600303 +60016001900160070260050160029004600490066021900560150160030260059007600303600960110860005460086000f2 diff --git a/evmcc/lll/arithmetic_test.lll b/evmcc/lll/arithmetic_test.lll index e2c14d4c7..4757a7420 100644 --- a/evmcc/lll/arithmetic_test.lll +++ b/evmcc/lll/arithmetic_test.lll @@ -26,4 +26,12 @@ SWAP1 SMOD;; 3 3 SUB ;; 0 +9 +17 +EXP ;; 17^9 +0 +MSTORE +8 +0 +RETURN ) \ No newline at end of file From 5e3113e49e21818984001febb651e47ed418b83b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 9 Oct 2014 11:37:19 +0200 Subject: [PATCH 066/641] Introducing GasMeter --- evmcc/Compiler.cpp | 4 ++- evmcc/GasMeter.cpp | 49 +++++++++++++++++++++++++++++++++++ evmcc/GasMeter.h | 9 +++++++ windows/evmcc.vcxproj | 2 ++ windows/evmcc.vcxproj.filters | 2 ++ 5 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 evmcc/GasMeter.cpp create mode 100644 evmcc/GasMeter.h diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 880487705..91bc692eb 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -12,6 +12,9 @@ namespace evmcc { +using dev::eth::Instruction; +using namespace dev::eth; // We should move all the JIT code into dev::eth namespace + struct { llvm::Type* word8; @@ -191,7 +194,6 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) for (auto currentPC = basicBlock.begin(); currentPC != basicBlock.end(); ++currentPC) { - using dev::eth::Instruction; auto inst = static_cast(bytecode[currentPC]); switch (inst) { diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp new file mode 100644 index 000000000..3687cfed3 --- /dev/null +++ b/evmcc/GasMeter.cpp @@ -0,0 +1,49 @@ + +#include "GasMeter.h" + +#include +#include + +namespace evmcc +{ + +using namespace dev::eth; // We should move all the JIT code into dev::eth namespace + +namespace +{ + +uint64_t getStepCost(dev::eth::Instruction inst) // TODO: Add this function to FeeSructure +{ + switch (inst) + { + case Instruction::STOP: + case Instruction::SUICIDE: + return 0; + + case Instruction::SSTORE: + return static_cast(c_sstoreGas); + + case Instruction::SLOAD: + return static_cast(c_sloadGas); + + case Instruction::SHA3: + return static_cast(c_sha3Gas); + + case Instruction::BALANCE: + return static_cast(c_sha3Gas); + + case Instruction::CALL: + case Instruction::CALLCODE: + return static_cast(c_callGas); + + case Instruction::CREATE: + return static_cast(c_createGas); + + default: // Assumes instruction code is valid + return static_cast(c_stepGas);; + } +} + +} + +} \ No newline at end of file diff --git a/evmcc/GasMeter.h b/evmcc/GasMeter.h new file mode 100644 index 000000000..c234a4ab6 --- /dev/null +++ b/evmcc/GasMeter.h @@ -0,0 +1,9 @@ + +#pragma once + +#include + +namespace evmcc +{ + +} \ No newline at end of file diff --git a/windows/evmcc.vcxproj b/windows/evmcc.vcxproj index ecf23fa05..2a6eac0c5 100644 --- a/windows/evmcc.vcxproj +++ b/windows/evmcc.vcxproj @@ -24,6 +24,7 @@ + @@ -33,6 +34,7 @@ + diff --git a/windows/evmcc.vcxproj.filters b/windows/evmcc.vcxproj.filters index 29ff77ba5..0fa1fc8c1 100644 --- a/windows/evmcc.vcxproj.filters +++ b/windows/evmcc.vcxproj.filters @@ -9,6 +9,7 @@ + @@ -18,5 +19,6 @@ + \ No newline at end of file From 989afa940604dd8417386010e2607bdc3f9d082f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 9 Oct 2014 12:52:48 +0200 Subject: [PATCH 067/641] Decrement global gas value by instruction step cost [#79942174] --- evmcc/Compiler.cpp | 4 ++++ evmcc/GasMeter.cpp | 22 +++++++++++++++++++++- evmcc/GasMeter.h | 17 +++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 91bc692eb..720570277 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -8,6 +8,7 @@ #include "Memory.h" #include "Ext.h" +#include "GasMeter.h" namespace evmcc { @@ -182,6 +183,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) // Init runtime structures. auto memory = Memory(builder, module.get()); auto ext = Ext(builder, module.get()); + GasMeter gasMeter(builder, module.get()); // Jump to first instruction builder.CreateBr(basicBlocks.begin()->second); @@ -195,6 +197,8 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) for (auto currentPC = basicBlock.begin(); currentPC != basicBlock.end(); ++currentPC) { auto inst = static_cast(bytecode[currentPC]); + gasMeter.check(inst); + switch (inst) { diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index 3687cfed3..af08d13b7 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -1,6 +1,9 @@ #include "GasMeter.h" +#include +#include + #include #include @@ -9,7 +12,7 @@ namespace evmcc using namespace dev::eth; // We should move all the JIT code into dev::eth namespace -namespace +namespace // Helper functions { uint64_t getStepCost(dev::eth::Instruction inst) // TODO: Add this function to FeeSructure @@ -46,4 +49,21 @@ uint64_t getStepCost(dev::eth::Instruction inst) // TODO: Add this function to F } +GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module): + m_builder(_builder) +{ + m_gas = new llvm::GlobalVariable(*_module, m_builder.getIntNTy(256), false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(m_builder.getIntNTy(256)), "gas"); + m_gas->setUnnamedAddr(true); // Address is not important + + //llvm::Function::Create() +} + +void GasMeter::check(Instruction _inst) +{ + auto stepCost = getStepCost(_inst); + auto before = m_builder.CreateLoad(m_gas, "gas.before"); + auto after = m_builder.CreateSub(before, m_builder.getIntN(256, stepCost)); + m_builder.CreateStore(after, m_gas); +} + } \ No newline at end of file diff --git a/evmcc/GasMeter.h b/evmcc/GasMeter.h index c234a4ab6..f50438c9a 100644 --- a/evmcc/GasMeter.h +++ b/evmcc/GasMeter.h @@ -1,9 +1,26 @@ #pragma once +#include + #include namespace evmcc { +class GasMeter +{ +public: + GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* module); + + GasMeter(const GasMeter&) = delete; + void operator=(GasMeter) = delete; + + void check(dev::eth::Instruction _inst); + +private: + llvm::IRBuilder<>& m_builder; + llvm::GlobalVariable* m_gas; +}; + } \ No newline at end of file From f8813b2843bd80cb68059e55ec515f745ae69956 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 9 Oct 2014 13:17:54 +0200 Subject: [PATCH 068/641] Cleanup LLVM types usage --- evmcc/BasicBlock.cpp | 7 ++++--- evmcc/Compiler.cpp | 36 ++++++++++++++++------------------- evmcc/GasMeter.cpp | 4 +++- evmcc/Type.cpp | 16 ++++++++++++++++ evmcc/Type.h | 16 ++++++++++++++++ windows/evmcc.vcxproj | 2 ++ windows/evmcc.vcxproj.filters | 2 ++ 7 files changed, 59 insertions(+), 24 deletions(-) create mode 100644 evmcc/Type.cpp create mode 100644 evmcc/Type.h diff --git a/evmcc/BasicBlock.cpp b/evmcc/BasicBlock.cpp index e5cdf386f..de18dbba0 100644 --- a/evmcc/BasicBlock.cpp +++ b/evmcc/BasicBlock.cpp @@ -4,6 +4,8 @@ #include #include +#include "Type.h" + namespace evmcc { @@ -27,10 +29,9 @@ llvm::Value* BasicBlock::Stack::pop() if (m_backend.empty()) { // Create PHI node - auto i256Ty = llvm::Type::getIntNTy(m_llvmBB->getContext(), 256); if (m_llvmBB->empty()) - return llvm::PHINode::Create(i256Ty, 0, {}, m_llvmBB); - return llvm::PHINode::Create(i256Ty, 0, {}, m_llvmBB->getFirstNonPHI()); + return llvm::PHINode::Create(Type::i256, 0, {}, m_llvmBB); + return llvm::PHINode::Create(Type::i256, 0, {}, m_llvmBB->getFirstNonPHI()); } auto top = m_backend.back(); diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 720570277..d26c7850e 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -6,6 +6,7 @@ #include +#include "Type.h" #include "Memory.h" #include "Ext.h" #include "GasMeter.h" @@ -20,9 +21,6 @@ struct { llvm::Type* word8; llvm::Type* word8ptr; - llvm::Type* word256; - llvm::Type* word256ptr; - llvm::Type* word256arr; llvm::Type* size; llvm::Type* Void; llvm::Type* WordLowPrecision; @@ -30,12 +28,10 @@ struct Compiler::Compiler() { + Type::init(llvm::getGlobalContext()); auto& context = llvm::getGlobalContext(); Types.word8 = llvm::Type::getInt8Ty(context); Types.word8ptr = llvm::Type::getInt8PtrTy(context); - Types.word256 = llvm::Type::getIntNTy(context, 256); - Types.word256ptr = Types.word256->getPointerTo(); - Types.word256arr = llvm::ArrayType::get(Types.word256, 100); Types.size = llvm::Type::getInt64Ty(context); Types.Void = llvm::Type::getVoidTy(context); @@ -227,7 +223,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); auto res128 = builder.CreateMul(lhs128, rhs128); - auto res256 = builder.CreateZExt(res128, Types.word256); + auto res256 = builder.CreateZExt(res128, Type::i256); stack.push(res256); break; } @@ -239,7 +235,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); auto res128 = builder.CreateUDiv(lhs128, rhs128); - auto res256 = builder.CreateZExt(res128, Types.word256); + auto res256 = builder.CreateZExt(res128, Type::i256); stack.push(res256); break; } @@ -251,7 +247,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); auto res128 = builder.CreateSDiv(lhs128, rhs128); - auto res256 = builder.CreateSExt(res128, Types.word256); + auto res256 = builder.CreateSExt(res128, Type::i256); stack.push(res256); break; } @@ -263,7 +259,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); auto res128 = builder.CreateURem(lhs128, rhs128); - auto res256 = builder.CreateZExt(res128, Types.word256); + auto res256 = builder.CreateZExt(res128, Type::i256); stack.push(res256); break; } @@ -275,7 +271,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); auto res128 = builder.CreateSRem(lhs128, rhs128); - auto res256 = builder.CreateSExt(res128, Types.word256); + auto res256 = builder.CreateSExt(res128, Type::i256); stack.push(res256); break; } @@ -292,7 +288,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) case Instruction::NEG: { auto top = stack.pop(); - auto zero = ConstantInt::get(Types.word256, 0); + auto zero = ConstantInt::get(Type::i256, 0); auto res = builder.CreateSub(zero, top); stack.push(res); break; @@ -303,7 +299,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto lhs = stack.pop(); auto rhs = stack.pop(); auto res1 = builder.CreateICmpULT(lhs, rhs); - auto res256 = builder.CreateZExt(res1, Types.word256); + auto res256 = builder.CreateZExt(res1, Type::i256); stack.push(res256); break; } @@ -313,7 +309,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto lhs = stack.pop(); auto rhs = stack.pop(); auto res1 = builder.CreateICmpUGT(lhs, rhs); - auto res256 = builder.CreateZExt(res1, Types.word256); + auto res256 = builder.CreateZExt(res1, Type::i256); stack.push(res256); break; } @@ -323,7 +319,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto lhs = stack.pop(); auto rhs = stack.pop(); auto res1 = builder.CreateICmpSLT(lhs, rhs); - auto res256 = builder.CreateZExt(res1, Types.word256); + auto res256 = builder.CreateZExt(res1, Type::i256); stack.push(res256); break; } @@ -333,7 +329,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto lhs = stack.pop(); auto rhs = stack.pop(); auto res1 = builder.CreateICmpSGT(lhs, rhs); - auto res256 = builder.CreateZExt(res1, Types.word256); + auto res256 = builder.CreateZExt(res1, Type::i256); stack.push(res256); break; } @@ -343,7 +339,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto lhs = stack.pop(); auto rhs = stack.pop(); auto res1 = builder.CreateICmpEQ(lhs, rhs); - auto res256 = builder.CreateZExt(res1, Types.word256); + auto res256 = builder.CreateZExt(res1, Type::i256); stack.push(res256); break; } @@ -351,9 +347,9 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) case Instruction::NOT: { auto top = stack.pop(); - auto zero = ConstantInt::get(Types.word256, 0); + auto zero = ConstantInt::get(Type::i256, 0); auto iszero = builder.CreateICmpEQ(top, zero, "iszero"); - auto result = builder.CreateZExt(iszero, Types.word256); + auto result = builder.CreateZExt(iszero, Type::i256); stack.push(result); break; } @@ -584,7 +580,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) stack.pop(); auto top = stack.pop(); - auto zero = ConstantInt::get(Types.word256, 0); + auto zero = ConstantInt::get(Type::i256, 0); auto cond = builder.CreateICmpNE(top, zero, "nonzero"); auto& targetBlock = basicBlocks.find(jumpTargets[currentPC])->second; auto& followBlock = basicBlocks.find(currentPC + 1)->second; diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index af08d13b7..4fdfde469 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -7,6 +7,8 @@ #include #include +#include "Type.h" + namespace evmcc { @@ -52,7 +54,7 @@ uint64_t getStepCost(dev::eth::Instruction inst) // TODO: Add this function to F GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module): m_builder(_builder) { - m_gas = new llvm::GlobalVariable(*_module, m_builder.getIntNTy(256), false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(m_builder.getIntNTy(256)), "gas"); + m_gas = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::i256), "gas"); m_gas->setUnnamedAddr(true); // Address is not important //llvm::Function::Create() diff --git a/evmcc/Type.cpp b/evmcc/Type.cpp new file mode 100644 index 000000000..c66cd6de6 --- /dev/null +++ b/evmcc/Type.cpp @@ -0,0 +1,16 @@ + +#include "Type.h" + +#include + +namespace evmcc +{ + +llvm::Type* Type::i256; + +void Type::init(llvm::LLVMContext& _context) +{ + i256 = llvm::Type::getIntNTy(_context, 256); +} + +} \ No newline at end of file diff --git a/evmcc/Type.h b/evmcc/Type.h new file mode 100644 index 000000000..0d7f3e428 --- /dev/null +++ b/evmcc/Type.h @@ -0,0 +1,16 @@ + +#pragma once + +#include + +namespace evmcc +{ + +struct Type +{ + static llvm::Type* i256; + + static void init(llvm::LLVMContext& _context); +}; + +} \ No newline at end of file diff --git a/windows/evmcc.vcxproj b/windows/evmcc.vcxproj index 2a6eac0c5..dbd9d1b57 100644 --- a/windows/evmcc.vcxproj +++ b/windows/evmcc.vcxproj @@ -27,6 +27,7 @@ + @@ -37,6 +38,7 @@ + diff --git a/windows/evmcc.vcxproj.filters b/windows/evmcc.vcxproj.filters index 0fa1fc8c1..f84ec6ca3 100644 --- a/windows/evmcc.vcxproj.filters +++ b/windows/evmcc.vcxproj.filters @@ -10,6 +10,7 @@ + @@ -20,5 +21,6 @@ + \ No newline at end of file From 6c7de9fa0b3e4f2d7c63fcea8e0d05b0754570ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 9 Oct 2014 14:44:25 +0200 Subject: [PATCH 069/641] Cleanup LLVM types usage --- evmcc/Compiler.cpp | 36 ++++++++++-------------------------- evmcc/Type.cpp | 2 ++ evmcc/Type.h | 4 ++++ 3 files changed, 16 insertions(+), 26 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index d26c7850e..d1fd3eb1a 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -17,26 +17,10 @@ namespace evmcc using dev::eth::Instruction; using namespace dev::eth; // We should move all the JIT code into dev::eth namespace -struct -{ - llvm::Type* word8; - llvm::Type* word8ptr; - llvm::Type* size; - llvm::Type* Void; - llvm::Type* WordLowPrecision; -} Types; Compiler::Compiler() { Type::init(llvm::getGlobalContext()); - auto& context = llvm::getGlobalContext(); - Types.word8 = llvm::Type::getInt8Ty(context); - Types.word8ptr = llvm::Type::getInt8PtrTy(context); - Types.size = llvm::Type::getInt64Ty(context); - Types.Void = llvm::Type::getVoidTy(context); - - // TODO: Use 64-bit for now. In 128-bit compiler-rt library functions are required - Types.WordLowPrecision = llvm::Type::getIntNTy(context, 64); } void Compiler::createBasicBlocks(const dev::bytes& bytecode) @@ -220,8 +204,8 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) { auto lhs256 = stack.pop(); auto rhs256 = stack.pop(); - auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); - auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); + auto lhs128 = builder.CreateTrunc(lhs256, Type::lowPrecision); + auto rhs128 = builder.CreateTrunc(rhs256, Type::lowPrecision); auto res128 = builder.CreateMul(lhs128, rhs128); auto res256 = builder.CreateZExt(res128, Type::i256); stack.push(res256); @@ -232,8 +216,8 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) { auto lhs256 = stack.pop(); auto rhs256 = stack.pop(); - auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); - auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); + auto lhs128 = builder.CreateTrunc(lhs256, Type::lowPrecision); + auto rhs128 = builder.CreateTrunc(rhs256, Type::lowPrecision); auto res128 = builder.CreateUDiv(lhs128, rhs128); auto res256 = builder.CreateZExt(res128, Type::i256); stack.push(res256); @@ -244,8 +228,8 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) { auto lhs256 = stack.pop(); auto rhs256 = stack.pop(); - auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); - auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); + auto lhs128 = builder.CreateTrunc(lhs256, Type::lowPrecision); + auto rhs128 = builder.CreateTrunc(rhs256, Type::lowPrecision); auto res128 = builder.CreateSDiv(lhs128, rhs128); auto res256 = builder.CreateSExt(res128, Type::i256); stack.push(res256); @@ -256,8 +240,8 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) { auto lhs256 = stack.pop(); auto rhs256 = stack.pop(); - auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); - auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); + auto lhs128 = builder.CreateTrunc(lhs256, Type::lowPrecision); + auto rhs128 = builder.CreateTrunc(rhs256, Type::lowPrecision); auto res128 = builder.CreateURem(lhs128, rhs128); auto res256 = builder.CreateZExt(res128, Type::i256); stack.push(res256); @@ -268,8 +252,8 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) { auto lhs256 = stack.pop(); auto rhs256 = stack.pop(); - auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); - auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); + auto lhs128 = builder.CreateTrunc(lhs256, Type::lowPrecision); + auto rhs128 = builder.CreateTrunc(rhs256, Type::lowPrecision); auto res128 = builder.CreateSRem(lhs128, rhs128); auto res256 = builder.CreateSExt(res128, Type::i256); stack.push(res256); diff --git a/evmcc/Type.cpp b/evmcc/Type.cpp index c66cd6de6..c19c49644 100644 --- a/evmcc/Type.cpp +++ b/evmcc/Type.cpp @@ -7,10 +7,12 @@ namespace evmcc { llvm::Type* Type::i256; +llvm::Type* Type::lowPrecision; void Type::init(llvm::LLVMContext& _context) { i256 = llvm::Type::getIntNTy(_context, 256); + lowPrecision = llvm::Type::getInt64Ty(_context); } } \ No newline at end of file diff --git a/evmcc/Type.h b/evmcc/Type.h index 0d7f3e428..425dae345 100644 --- a/evmcc/Type.h +++ b/evmcc/Type.h @@ -10,6 +10,10 @@ struct Type { static llvm::Type* i256; + /// Type for doing low precision arithmetics where 256-bit precision is not supported by native target + /// @TODO: Use 64-bit for now. In 128-bit compiler-rt library functions are required + static llvm::Type* lowPrecision; + static void init(llvm::LLVMContext& _context); }; From b63b28b0987f34ed02c66d6db6af336710d2e8e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 9 Oct 2014 15:44:41 +0200 Subject: [PATCH 070/641] Generate gas checking function --- evmcc/GasMeter.cpp | 16 ++++++++++++---- evmcc/GasMeter.h | 1 + evmcc/Type.cpp | 2 ++ evmcc/Type.h | 2 ++ 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index 4fdfde469..2006f319f 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -57,15 +57,23 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module): m_gas = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::i256), "gas"); m_gas->setUnnamedAddr(true); // Address is not important - //llvm::Function::Create() + auto pt = m_builder.GetInsertPoint(); + auto bb = m_builder.GetInsertBlock(); + m_gasCheckFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "gas.check", _module); + auto gasCheckBB = llvm::BasicBlock::Create(_builder.getContext(), {}, m_gasCheckFunc); + m_builder.SetInsertPoint(gasCheckBB); + llvm::Value* cost = m_gasCheckFunc->arg_begin(); + llvm::Value* gas = m_builder.CreateLoad(m_gas); + gas = m_builder.CreateSub(gas, cost); + m_builder.CreateStore(gas, m_gas); + m_builder.CreateRetVoid(); + m_builder.SetInsertPoint(bb, pt); } void GasMeter::check(Instruction _inst) { auto stepCost = getStepCost(_inst); - auto before = m_builder.CreateLoad(m_gas, "gas.before"); - auto after = m_builder.CreateSub(before, m_builder.getIntN(256, stepCost)); - m_builder.CreateStore(after, m_gas); + m_builder.CreateCall(m_gasCheckFunc, m_builder.getIntN(256, stepCost)); } } \ No newline at end of file diff --git a/evmcc/GasMeter.h b/evmcc/GasMeter.h index f50438c9a..e2ee26a71 100644 --- a/evmcc/GasMeter.h +++ b/evmcc/GasMeter.h @@ -21,6 +21,7 @@ public: private: llvm::IRBuilder<>& m_builder; llvm::GlobalVariable* m_gas; + llvm::Function* m_gasCheckFunc; }; } \ No newline at end of file diff --git a/evmcc/Type.cpp b/evmcc/Type.cpp index c19c49644..b9063569b 100644 --- a/evmcc/Type.cpp +++ b/evmcc/Type.cpp @@ -8,11 +8,13 @@ namespace evmcc llvm::Type* Type::i256; llvm::Type* Type::lowPrecision; +llvm::Type* Type::Void; void Type::init(llvm::LLVMContext& _context) { i256 = llvm::Type::getIntNTy(_context, 256); lowPrecision = llvm::Type::getInt64Ty(_context); + Void = llvm::Type::getVoidTy(_context); } } \ No newline at end of file diff --git a/evmcc/Type.h b/evmcc/Type.h index 425dae345..32459dca4 100644 --- a/evmcc/Type.h +++ b/evmcc/Type.h @@ -14,6 +14,8 @@ struct Type /// @TODO: Use 64-bit for now. In 128-bit compiler-rt library functions are required static llvm::Type* lowPrecision; + static llvm::Type* Void; + static void init(llvm::LLVMContext& _context); }; From dd3ae798b468b759d302d5336c63a630e3f1b5c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 9 Oct 2014 16:10:12 +0200 Subject: [PATCH 071/641] Disable gas checking for now (does not work and makes IR code hard to read) [#79942174] --- evmcc/Compiler.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index d1fd3eb1a..9a46313b6 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -177,7 +177,9 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) for (auto currentPC = basicBlock.begin(); currentPC != basicBlock.end(); ++currentPC) { auto inst = static_cast(bytecode[currentPC]); - gasMeter.check(inst); + + // Disable for now + //gasMeter.check(inst); switch (inst) { From e9153795393a0cab8fd07d0b9c087dc059c67517 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Fri, 10 Oct 2014 10:01:26 +0100 Subject: [PATCH 072/641] Implementing JUMP/JUMPDEST (work in progress) --- evmcc/BasicBlock.cpp | 9 ++- evmcc/BasicBlock.h | 3 +- evmcc/Compiler.cpp | 179 ++++++++++++++++++++++++++++++++----------- evmcc/Compiler.h | 20 ++++- 4 files changed, 161 insertions(+), 50 deletions(-) diff --git a/evmcc/BasicBlock.cpp b/evmcc/BasicBlock.cpp index e5cdf386f..c7c98aca5 100644 --- a/evmcc/BasicBlock.cpp +++ b/evmcc/BasicBlock.cpp @@ -16,6 +16,13 @@ BasicBlock::BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx, m_stack(m_llvmBB) {} +BasicBlock::BasicBlock(std::string _name, llvm::Function* _mainFunc) : + m_beginInstIdx(0), + m_endInstIdx(0), + m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), _name, _mainFunc)), + m_stack(m_llvmBB) +{} + void BasicBlock::Stack::push(llvm::Value* _value) { @@ -49,4 +56,4 @@ void BasicBlock::Stack::swap(size_t _index) std::swap(get(0), get(_index)); } -} \ No newline at end of file +} diff --git a/evmcc/BasicBlock.h b/evmcc/BasicBlock.h index 500ddb95b..3c47db328 100644 --- a/evmcc/BasicBlock.h +++ b/evmcc/BasicBlock.h @@ -50,6 +50,7 @@ public: static const char* NamePrefix; explicit BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx, llvm::Function* _mainFunc); + explicit BasicBlock(std::string _name, llvm::Function* _mainFunc); BasicBlock(const BasicBlock&) = delete; void operator=(const BasicBlock&) = delete; @@ -72,4 +73,4 @@ private: Stack m_stack; }; -} \ No newline at end of file +} diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 880487705..02c391251 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -1,6 +1,8 @@ #include "Compiler.h" +#include + #include #include @@ -14,17 +16,19 @@ namespace evmcc struct { - llvm::Type* word8; + llvm::IntegerType* word8; llvm::Type* word8ptr; - llvm::Type* word256; + llvm::IntegerType* word256; llvm::Type* word256ptr; llvm::Type* word256arr; - llvm::Type* size; + llvm::IntegerType* size; llvm::Type* Void; llvm::Type* WordLowPrecision; } Types; Compiler::Compiler() + : m_finalBlock(nullptr) + , m_badJumpBlock(nullptr) { auto& context = llvm::getGlobalContext(); Types.word8 = llvm::Type::getInt8Ty(context); @@ -39,15 +43,31 @@ Compiler::Compiler() Types.WordLowPrecision = llvm::Type::getIntNTy(context, 64); } +namespace +{ + void validateSplitPoints(cons dev::bytes& bytecode, std::set splitPoints) + { + + } +} + void Compiler::createBasicBlocks(const dev::bytes& bytecode) { - std::set splitPoints; // Sorted collections of instruction indecies where basic blocks start/end + std::set splitPoints; // Sorted collections of instruction indices where basic blocks start/end splitPoints.insert(0); // First basic block + std::map directJumpTargets; + std::vector indirectJumpTargets; + + boost::dynamic_bitset<> validJumpTargets(bytecode.size()); + for (auto curr = bytecode.cbegin(); curr != bytecode.cend(); ++curr) { using dev::eth::Instruction; + ProgramCounter currentPC = curr - bytecode.cbegin(); + validJumpTargets[currentPC] = 1; + auto inst = static_cast(*curr); switch (inst) { @@ -86,7 +106,7 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode) { auto numBytes = static_cast(inst) - static_cast(Instruction::PUSH1) + 1; auto next = curr + numBytes + 1; - if (next == bytecode.cend()) + if (next >= bytecode.cend()) break; auto nextInst = static_cast(*next); @@ -101,34 +121,30 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode) val |= *iter; } - // Create a block following the JUMP. - if (next + 1 < bytecode.cend()) - { - ProgramCounter nextPC = (next + 1 - bytecode.cbegin()); - splitPoints.insert(nextPC); - } - // Create a block for the JUMP target. ProgramCounter targetPC = val.convert_to(); + if (targetPC > bytecode.size()) + targetPC = bytecode.size(); splitPoints.insert(targetPC); ProgramCounter jumpPC = (next - bytecode.cbegin()); - jumpTargets[jumpPC] = targetPC; - - curr += 1; // skip over JUMP + directJumpTargets[jumpPC] = targetPC; } curr += numBytes; break; } - case Instruction::JUMP: - case Instruction::JUMPI: + case Instruction::JUMPDEST: { - std::cerr << "JUMP/JUMPI at " << (curr - bytecode.cbegin()) << " not preceded by PUSH\n"; - std::exit(1); + // A basic block starts here. + splitPoints.insert(currentPC); + indirectJumpTargets.push_back(currentPC); + break; } + case Instruction::JUMP: + case Instruction::JUMPI: case Instruction::RETURN: case Instruction::STOP: case Instruction::SUICIDE: @@ -136,8 +152,7 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode) // Create a basic block starting at the following instruction. if (curr + 1 < bytecode.cend()) { - ProgramCounter nextPC = (curr + 1 - bytecode.cbegin()); - splitPoints.insert(nextPC); + splitPoints.insert(currentPC + 1); } break; } @@ -147,14 +162,40 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode) } } - splitPoints.insert(bytecode.size()); // For final block - for (auto it = splitPoints.cbegin(); it != splitPoints.cend();) + for (auto it = splitPoints.cbegin(); it != splitPoints.cend() && *it < bytecode.size(); ++it) + { + if (! validJumpTargets[*it]) + { + std::cerr "Jump to invalid PC " << *it << "\n"; + std::exit(1); + } + } + + for (auto it = splitPoints.cbegin(); it != splitPoints.cend() && *it < bytecode.size();) { auto beginInstIdx = *it; ++it; - auto endInstIdx = it != splitPoints.cend() ? *it : beginInstIdx; // For final block + auto endInstIdx = it != splitPoints.cend() ? *it : bytecode.size(); basicBlocks.emplace(std::piecewise_construct, std::forward_as_tuple(beginInstIdx), std::forward_as_tuple(beginInstIdx, endInstIdx, m_mainFunc)); } + + m_finalBlock = std::make_unique("FinalBlock", m_mainFunc); + m_badJumpBlock = std::make_unique("BadJumpBlock", m_mainFunc); + + for (auto it = directJumpTargets.cbegin(); it != directJumpTargets.cend(); ++it) + { + if (it->second >= bytecode.size()) + m_directJumpTargets[it->first] = m_finalBlock.get(); + else + m_directJumpTargets[it->first] = &basicBlocks.find(it->second)->second; + } + for (auto it = indirectJumpTargets.cbegin(); it != indirectJumpTargets.cend(); ++it) + { + if (*it >= bytecode.size()) + m_indirectJumpTargets.push_back(m_finalBlock.get()); + else + m_indirectJumpTargets.push_back(&basicBlocks.find(*it)->second); + } } std::unique_ptr Compiler::compile(const dev::bytes& bytecode) @@ -559,30 +600,69 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) } case Instruction::JUMP: + case Instruction::JUMPI: { - // The target address is computed at compile time, - // just pop it without looking... - stack.pop(); + // Generate direct jump iff: + // 1. this is not the first instruction in the block + // 2. m_directJumpTargets[currentPC] is defined (meaning that the previous instruction is a PUSH) + // Otherwise generate a indirect jump (a switch). + if (currentPC != basicBlock.begin()) + { + auto pairIter = m_directJumpTargets.find(currentPC); + if (pairIter != m_directJumpTargets.end()) + { + auto targetBlock = pairIter->second; + + // The target address is computed at compile time, + // just pop it without looking... + stack.pop(); + + if (inst == Instruction::JUMP) + { + builder.CreateBr(targetBlock->llvm()); + } + else // JUMPI + { + auto top = stack.pop(); + auto zero = ConstantInt::get(Types.word256, 0); + auto cond = builder.CreateICmpNE(top, zero, "nonzero"); + + // Assume the basic blocks are properly ordered: + auto nextBBIter = basicBlockPairIt; + ++nextBBIter; + assert (nextBBIter != basicBlocks.end()); + auto& followBlock = nextBBIter->second; + builder.CreateCondBr(cond, targetBlock->llvm(), followBlock.llvm()); + } + break; + } + } + + if (inst == Instruction::JUMPI) + { + std::cerr << "Indirect JUMPI is not supported yet (at PC " + << currentPC << ")\n"; + std::exit(1); + } + + // Generate switch for indirect jump. + auto dest = stack.pop(); + auto switchInstr = builder.CreateSwitch(dest, m_badJumpBlock->llvm(), + m_indirectJumpTargets.size()); + for (auto it = m_indirectJumpTargets.cbegin(); it != m_indirectJumpTargets.cend(); ++it) + { + auto& bb = *it; + auto dest = ConstantInt::get(Types.word256, bb->begin()); + switchInstr->addCase(dest, bb->llvm()); + } - auto& targetBlock = basicBlocks.find(jumpTargets[currentPC])->second; - builder.CreateBr(targetBlock); break; } - case Instruction::JUMPI: + case Instruction::JUMPDEST: { - assert(currentPC + 1 < bytecode.size()); - - // The target address is computed at compile time, - // just pop it without looking... - stack.pop(); - - auto top = stack.pop(); - auto zero = ConstantInt::get(Types.word256, 0); - auto cond = builder.CreateICmpNE(top, zero, "nonzero"); - auto& targetBlock = basicBlocks.find(jumpTargets[currentPC])->second; - auto& followBlock = basicBlocks.find(currentPC + 1)->second; - builder.CreateCondBr(cond, targetBlock, followBlock); + // Extra asserts just in case. + assert(currentPC == basicBlock.begin()); break; } @@ -754,17 +834,18 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) } } - } if (!builder.GetInsertBlock()->getTerminator()) // If block not terminated { - if (basicBlock.begin() == bytecode.size()) // Special final block + if (basicBlock.end() == bytecode.size()) { - builder.CreateRet(builder.getInt64(0)); + // Branch from the last regular block to the final block. + builder.CreateBr(m_finalBlock->llvm()); } else { + // Branch to the next block. auto iterCopy = basicBlockPairIt; ++iterCopy; auto& next = iterCopy->second; @@ -773,6 +854,14 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) } } + // Code for special blocks: + builder.SetInsertPoint(m_finalBlock->llvm()); + builder.CreateRet(builder.getInt64(0)); + + // TODO: throw an exception or something + builder.SetInsertPoint(m_badJumpBlock->llvm()); + builder.CreateRet(builder.getInt64(1)); + linkBasicBlocks(); return module; diff --git a/evmcc/Compiler.h b/evmcc/Compiler.h index 52a6bc9ac..f57d800a4 100644 --- a/evmcc/Compiler.h +++ b/evmcc/Compiler.h @@ -32,14 +32,28 @@ private: std::map basicBlocks; /** - * Maps a pc at which there is a JUMP or JUMPI to the target pc of the jump. + * Maps a pc at which there is a JUMP or JUMPI to the target block of the jump. */ - std::map jumpTargets; + std::map m_directJumpTargets; + + /** + * A list of possible blocks to which there may be indirect jumps. + */ + std::vector m_indirectJumpTargets; -private: /// Collection of basic blocks in program //std::vector m_basicBlocks; + /** + * Final block for normal (non-exceptional) execution. + */ + std::unique_ptr m_finalBlock; + + /** + * Default destination for indirect jumps. + */ + std::unique_ptr m_badJumpBlock; + /// Main program function llvm::Function* m_mainFunc = nullptr; }; From 209640c1f36db368ade2af76ee98e307bcc7ebf4 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Fri, 10 Oct 2014 10:03:12 +0100 Subject: [PATCH 073/641] test cases for JUMP --- evmcc/test/jump/jump1.evm | 1 + evmcc/test/jump/jump1.lll | 11 +++++++++++ evmcc/test/jump/jump2.evm | 1 + evmcc/test/jump/jump2.lll | 10 ++++++++++ evmcc/test/jump/jump3.evm | 1 + evmcc/test/jump/jump3.lll | 10 ++++++++++ evmcc/test/jump/jump4.evm | 1 + evmcc/test/jump/jump4.lll | 17 +++++++++++++++++ evmcc/test/jump/jump5.evm | 1 + evmcc/test/jump/jump5.lll | 16 ++++++++++++++++ evmcc/test/jump/jump6.evm | 1 + evmcc/test/jump/jump6.lll | 32 ++++++++++++++++++++++++++++++++ 12 files changed, 102 insertions(+) create mode 100644 evmcc/test/jump/jump1.evm create mode 100644 evmcc/test/jump/jump1.lll create mode 100644 evmcc/test/jump/jump2.evm create mode 100644 evmcc/test/jump/jump2.lll create mode 100644 evmcc/test/jump/jump3.evm create mode 100644 evmcc/test/jump/jump3.lll create mode 100644 evmcc/test/jump/jump4.evm create mode 100644 evmcc/test/jump/jump4.lll create mode 100644 evmcc/test/jump/jump5.evm create mode 100644 evmcc/test/jump/jump5.lll create mode 100644 evmcc/test/jump/jump6.evm create mode 100644 evmcc/test/jump/jump6.lll diff --git a/evmcc/test/jump/jump1.evm b/evmcc/test/jump/jump1.evm new file mode 100644 index 000000000..0df9b4036 --- /dev/null +++ b/evmcc/test/jump/jump1.evm @@ -0,0 +1 @@ +600458006001600154 diff --git a/evmcc/test/jump/jump1.lll b/evmcc/test/jump/jump1.lll new file mode 100644 index 000000000..33119edb3 --- /dev/null +++ b/evmcc/test/jump/jump1.lll @@ -0,0 +1,11 @@ +;; Direct JUMP. +;; output: memory[1] == 1 + +(asm +4 ;; 0 +JUMP ;; 2 +STOP ;; 3 +1 ;; 4 +1 ;; 6 +MSTORE ;; 8 +) \ No newline at end of file diff --git a/evmcc/test/jump/jump2.evm b/evmcc/test/jump/jump2.evm new file mode 100644 index 000000000..35d75941d --- /dev/null +++ b/evmcc/test/jump/jump2.evm @@ -0,0 +1 @@ +6008586001600154 diff --git a/evmcc/test/jump/jump2.lll b/evmcc/test/jump/jump2.lll new file mode 100644 index 000000000..a70d50ecb --- /dev/null +++ b/evmcc/test/jump/jump2.lll @@ -0,0 +1,10 @@ +;; Direct JUMP to the end of code. +;; output: memory should have size 0. + +(asm +8 ;; 0 +JUMP ;; 2 +1 ;; 3 +1 ;; 5 +MSTORE ;; 7 +) \ No newline at end of file diff --git a/evmcc/test/jump/jump3.evm b/evmcc/test/jump/jump3.evm new file mode 100644 index 000000000..599d4a764 --- /dev/null +++ b/evmcc/test/jump/jump3.evm @@ -0,0 +1 @@ +602a586001600154 diff --git a/evmcc/test/jump/jump3.lll b/evmcc/test/jump/jump3.lll new file mode 100644 index 000000000..bc897e30c --- /dev/null +++ b/evmcc/test/jump/jump3.lll @@ -0,0 +1,10 @@ +;; Direct JUMP past the end of code. +;; output: memory should have size 0. + +(asm +42 +JUMP +1 +1 +MSTORE +) \ No newline at end of file diff --git a/evmcc/test/jump/jump4.evm b/evmcc/test/jump/jump4.evm new file mode 100644 index 000000000..41713f43e --- /dev/null +++ b/evmcc/test/jump/jump4.evm @@ -0,0 +1 @@ +600b6009580000600558005d6001600154 diff --git a/evmcc/test/jump/jump4.lll b/evmcc/test/jump/jump4.lll new file mode 100644 index 000000000..131baee2d --- /dev/null +++ b/evmcc/test/jump/jump4.lll @@ -0,0 +1,17 @@ +;; Direct JUMP. +;; output: memory[1] = 1 + +(asm +11 ;; 0 +9 ;; 2 +JUMP ;; 4 --> 9 +STOP ;; 5 +STOP ;; 6 +5 ;; 7 +JUMP ;; 9 --> 11 +STOP ;; 10 +JUMPDEST +1 ;; 11 +1 +MSTORE +) \ No newline at end of file diff --git a/evmcc/test/jump/jump5.evm b/evmcc/test/jump/jump5.evm new file mode 100644 index 000000000..c36d9615b --- /dev/null +++ b/evmcc/test/jump/jump5.evm @@ -0,0 +1 @@ +6005600e585d600160015400600f5800 diff --git a/evmcc/test/jump/jump5.lll b/evmcc/test/jump/jump5.lll new file mode 100644 index 000000000..d28b7d4ac --- /dev/null +++ b/evmcc/test/jump/jump5.lll @@ -0,0 +1,16 @@ +;; Direct JUMP. +;; output: memory[1] = 1 + +(asm +5 ;; 0 +14 ;; 2 +JUMP ;; 4 --> 14 +JUMPDEST ;; 5 +1 ;; 6 +1 ;; 8 +MSTORE ;; 10 +STOP ;; 11 +15 ;; 12 +JUMP ;; 14 --> 5 +STOP ;; 15 +) \ No newline at end of file diff --git a/evmcc/test/jump/jump6.evm b/evmcc/test/jump/jump6.evm new file mode 100644 index 000000000..029db7191 --- /dev/null +++ b/evmcc/test/jump/jump6.evm @@ -0,0 +1 @@ +600358600f600d58006014600758005d6001600154005d600260025400 diff --git a/evmcc/test/jump/jump6.lll b/evmcc/test/jump/jump6.lll new file mode 100644 index 000000000..1116aa663 --- /dev/null +++ b/evmcc/test/jump/jump6.lll @@ -0,0 +1,32 @@ +;; Direct JUMP. +;; output: memory[1] = 1 + +;; 0, 2 --> 3 .. 7 --> 13 -*-> 15 .. 19 + +(asm +3 ;; 0 +JUMP ;; 2 + +15 ;; 3 <- start +13 ;; 5 +JUMP ;; 7 <- b +STOP ;; 8 + +20 ;; 9 +7 ;; 11 + +JUMP ;; 13 <- a +STOP ;; 14 + +JUMPDEST ;; 15 <- c +1 ;; 16 +1 ;; 18 +MSTORE ;; 19 +STOP ;; 20 + +JUMPDEST ;; 21 <- d +2 ;; 22 +2 ;; 24 +MSTORE ;; 26 +STOP ;; 27 +) \ No newline at end of file From 936aeab43c6937f6a9510a27794c38fe296ce5f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 10 Oct 2014 14:12:38 +0200 Subject: [PATCH 074/641] Group gas counting into block of instructions called cost-block. [#79942174] --- evmcc/Compiler.cpp | 3 +-- evmcc/GasMeter.cpp | 41 ++++++++++++++++++++++++++++++++++++++++- evmcc/GasMeter.h | 4 ++++ 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 9a46313b6..0e695df06 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -178,8 +178,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) { auto inst = static_cast(bytecode[currentPC]); - // Disable for now - //gasMeter.check(inst); + gasMeter.check(inst); switch (inst) { diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index 2006f319f..a40b8cb5c 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -49,6 +49,33 @@ uint64_t getStepCost(dev::eth::Instruction inst) // TODO: Add this function to F } } +bool isCommitTrigger(Instruction _inst) +{ + switch (_inst) + { + case Instruction::STOP: + case Instruction::CALLDATACOPY: + case Instruction::CODECOPY: + case Instruction::MLOAD: + case Instruction::MSTORE: + case Instruction::MSTORE8: + case Instruction::SSTORE: + case Instruction::JUMP: + case Instruction::JUMPI: + case Instruction::JUMPDEST: + case Instruction::GAS: + case Instruction::CREATE: + case Instruction::CALL: + case Instruction::CALLCODE: + case Instruction::RETURN: + case Instruction::SUICIDE: + return true; + + default: + return false; + } +} + } GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module): @@ -72,8 +99,20 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module): void GasMeter::check(Instruction _inst) { + if (!m_checkCall) + { + m_checkCall = m_builder.CreateCall(m_gasCheckFunc, m_builder.getIntN(256, 0)); + } + auto stepCost = getStepCost(_inst); - m_builder.CreateCall(m_gasCheckFunc, m_builder.getIntN(256, stepCost)); + m_blockCost += stepCost; + + auto isTrigger = isCommitTrigger(_inst); + if (isTrigger) + { + m_checkCall->setArgOperand(0, m_builder.getIntN(256, m_blockCost)); + m_checkCall = nullptr; + } } } \ No newline at end of file diff --git a/evmcc/GasMeter.h b/evmcc/GasMeter.h index e2ee26a71..057391102 100644 --- a/evmcc/GasMeter.h +++ b/evmcc/GasMeter.h @@ -19,7 +19,11 @@ public: void check(dev::eth::Instruction _inst); private: + /// Cumulative gas cost of a block of instructions + /// @TODO Handle overflow + uint64_t m_blockCost = 0; llvm::IRBuilder<>& m_builder; + llvm::CallInst* m_checkCall; llvm::GlobalVariable* m_gas; llvm::Function* m_gasCheckFunc; }; From 85606447d86d14103c4d3d0a4b27d569023af08f Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Fri, 10 Oct 2014 13:35:45 +0100 Subject: [PATCH 075/641] test cases for jumps --- evmcc/test/jump/badjump1.evm | 1 + evmcc/test/jump/badjump1.lll | 9 +++++++++ evmcc/test/jump/call1.ethel | 3 +++ evmcc/test/jump/call1.evm | 1 + evmcc/test/jump/fib1.ethel | 5 +++++ evmcc/test/jump/fib1.evm | 1 + evmcc/test/jump/if1.ethel | 1 + evmcc/test/jump/if1.evm | 1 + evmcc/test/jump/if2.ethel | 1 + evmcc/test/jump/if2.evm | 1 + evmcc/test/jump/indirect1.evm | 1 + evmcc/test/jump/indirect1.lll | 13 +++++++++++++ evmcc/test/jump/indirect2.evm | 1 + evmcc/test/jump/indirect2.lll | 19 +++++++++++++++++++ 14 files changed, 58 insertions(+) create mode 100644 evmcc/test/jump/badjump1.evm create mode 100644 evmcc/test/jump/badjump1.lll create mode 100644 evmcc/test/jump/call1.ethel create mode 100644 evmcc/test/jump/call1.evm create mode 100644 evmcc/test/jump/fib1.ethel create mode 100644 evmcc/test/jump/fib1.evm create mode 100644 evmcc/test/jump/if1.ethel create mode 100644 evmcc/test/jump/if1.evm create mode 100644 evmcc/test/jump/if2.ethel create mode 100644 evmcc/test/jump/if2.evm create mode 100644 evmcc/test/jump/indirect1.evm create mode 100644 evmcc/test/jump/indirect1.lll create mode 100644 evmcc/test/jump/indirect2.evm create mode 100644 evmcc/test/jump/indirect2.lll diff --git a/evmcc/test/jump/badjump1.evm b/evmcc/test/jump/badjump1.evm new file mode 100644 index 000000000..b2a8aad67 --- /dev/null +++ b/evmcc/test/jump/badjump1.evm @@ -0,0 +1 @@ +601b602502585d diff --git a/evmcc/test/jump/badjump1.lll b/evmcc/test/jump/badjump1.lll new file mode 100644 index 000000000..c3f9f8d69 --- /dev/null +++ b/evmcc/test/jump/badjump1.lll @@ -0,0 +1,9 @@ +;; Bad indirect jump. Should go to BadJumpBlock. + +(asm +27 +37 +MUL +JUMP +JUMPDEST +) \ No newline at end of file diff --git a/evmcc/test/jump/call1.ethel b/evmcc/test/jump/call1.ethel new file mode 100644 index 000000000..206fb4c75 --- /dev/null +++ b/evmcc/test/jump/call1.ethel @@ -0,0 +1,3 @@ +let f n = n + 1 + +return f 2 diff --git a/evmcc/test/jump/call1.evm b/evmcc/test/jump/call1.evm new file mode 100644 index 000000000..1f50b683f --- /dev/null +++ b/evmcc/test/jump/call1.evm @@ -0,0 +1 @@ +630000000d60026300000016585d60005460206000f280600101915058 \ No newline at end of file diff --git a/evmcc/test/jump/fib1.ethel b/evmcc/test/jump/fib1.ethel new file mode 100644 index 000000000..6efd4ed2d --- /dev/null +++ b/evmcc/test/jump/fib1.ethel @@ -0,0 +1,5 @@ +let fib n = + if n < 3 then 1 + else fib (n-1) + fib (n-2) + +return fib 5 diff --git a/evmcc/test/jump/fib1.evm b/evmcc/test/jump/fib1.evm new file mode 100644 index 000000000..b5b5bf9c6 --- /dev/null +++ b/evmcc/test/jump/fib1.evm @@ -0,0 +1 @@ +630000000d60056300000016585d60005460206000f28060030a630000004759630000002f816001036300000016585d630000003f836002036300000016585d0163000000495860019350505058 \ No newline at end of file diff --git a/evmcc/test/jump/if1.ethel b/evmcc/test/jump/if1.ethel new file mode 100644 index 000000000..85c3e126b --- /dev/null +++ b/evmcc/test/jump/if1.ethel @@ -0,0 +1 @@ +return if 0 then 1 else 2 \ No newline at end of file diff --git a/evmcc/test/jump/if1.evm b/evmcc/test/jump/if1.evm new file mode 100644 index 000000000..51fbe04bd --- /dev/null +++ b/evmcc/test/jump/if1.evm @@ -0,0 +1 @@ +60006300000010596002630000001258600160005460206000f2 \ No newline at end of file diff --git a/evmcc/test/jump/if2.ethel b/evmcc/test/jump/if2.ethel new file mode 100644 index 000000000..2a58d6365 --- /dev/null +++ b/evmcc/test/jump/if2.ethel @@ -0,0 +1 @@ +return if 1 then 1 else 2 \ No newline at end of file diff --git a/evmcc/test/jump/if2.evm b/evmcc/test/jump/if2.evm new file mode 100644 index 000000000..6d823b374 --- /dev/null +++ b/evmcc/test/jump/if2.evm @@ -0,0 +1 @@ +60016300000010596002630000001258600160005460206000f2 \ No newline at end of file diff --git a/evmcc/test/jump/indirect1.evm b/evmcc/test/jump/indirect1.evm new file mode 100644 index 000000000..ab6928304 --- /dev/null +++ b/evmcc/test/jump/indirect1.evm @@ -0,0 +1 @@ +600460030158005d6001600054 diff --git a/evmcc/test/jump/indirect1.lll b/evmcc/test/jump/indirect1.lll new file mode 100644 index 000000000..1ee7dc347 --- /dev/null +++ b/evmcc/test/jump/indirect1.lll @@ -0,0 +1,13 @@ +;; Indirect JUMP + +(asm +4 ;; 0 +3 ;; 2 +ADD ;; 4 +JUMP ;; 5 +STOP ;; 6 +JUMPDEST ;; 7 +1 +0 +MSTORE +) \ No newline at end of file diff --git a/evmcc/test/jump/indirect2.evm b/evmcc/test/jump/indirect2.evm new file mode 100644 index 000000000..e9697eaa1 --- /dev/null +++ b/evmcc/test/jump/indirect2.evm @@ -0,0 +1 @@ +600860060158005d6001600054005d600260005400 diff --git a/evmcc/test/jump/indirect2.lll b/evmcc/test/jump/indirect2.lll new file mode 100644 index 000000000..9a4db8c14 --- /dev/null +++ b/evmcc/test/jump/indirect2.lll @@ -0,0 +1,19 @@ +;; Indirect JUMP + +(asm +8 ;; 0 +6 ;; 2 +ADD ;; 4 +JUMP ;; 5 +STOP ;; 6 +JUMPDEST ;; 7 +1 ;; 8 +0 ;; 10 +MSTORE ;; 12 +STOP ;; 13 +JUMPDEST ;; 14 +2 +0 +MSTORE +STOP +) \ No newline at end of file From a5e264d385b9d70d69dd1ad7843d2971bcd428ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 10 Oct 2014 14:56:06 +0200 Subject: [PATCH 076/641] Fix stack swap or dup not generating PHI nodes --- evmcc/BasicBlock.cpp | 29 ++++++++++++++++++++--------- evmcc/BasicBlock.h | 2 +- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/evmcc/BasicBlock.cpp b/evmcc/BasicBlock.cpp index 5271c984f..3a2c1c548 100644 --- a/evmcc/BasicBlock.cpp +++ b/evmcc/BasicBlock.cpp @@ -33,17 +33,27 @@ void BasicBlock::Stack::push(llvm::Value* _value) llvm::Value* BasicBlock::Stack::pop() { - if (m_backend.empty()) + auto top = get(0); + m_backend.pop_back(); + return top; +} + +llvm::Value* BasicBlock::Stack::get(size_t _index) +{ + if (_index >= m_backend.size()) { - // Create PHI node - if (m_llvmBB->empty()) - return llvm::PHINode::Create(Type::i256, 0, {}, m_llvmBB); - return llvm::PHINode::Create(Type::i256, 0, {}, m_llvmBB->getFirstNonPHI()); + // Create PHI node for missing values + auto nMissingVals = _index - m_backend.size() + 1; + m_backend.insert(m_backend.begin(), nMissingVals, nullptr); + for (decltype(nMissingVals) i = 0; i < nMissingVals; ++i) + { + m_backend[i] = m_llvmBB->empty() ? + llvm::PHINode::Create(Type::i256, 0, {}, m_llvmBB) : + llvm::PHINode::Create(Type::i256, 0, {}, m_llvmBB->getFirstNonPHI()); + } } - auto top = m_backend.back(); - m_backend.pop_back(); - return top; + return *(m_backend.rbegin() + _index); } void BasicBlock::Stack::dup(size_t _index) @@ -54,7 +64,8 @@ void BasicBlock::Stack::dup(size_t _index) void BasicBlock::Stack::swap(size_t _index) { assert(_index != 0); - std::swap(get(0), get(_index)); + get(_index); // Create PHI nodes + std::swap(*m_backend.rbegin(), *(m_backend.rbegin() + _index)); } } diff --git a/evmcc/BasicBlock.h b/evmcc/BasicBlock.h index 3c47db328..598ab731c 100644 --- a/evmcc/BasicBlock.h +++ b/evmcc/BasicBlock.h @@ -21,7 +21,7 @@ public: llvm::Value* pop(); /// Gets _index'th value from top (counting from 0) - llvm::Value*& get(size_t _index) { return *(m_backend.rbegin() + _index); } + llvm::Value* get(size_t _index); /// Duplicates _index'th value on stack. void dup(size_t _index); From 40e73d035ca0c08eb7bd123491474df07ca56fe6 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Fri, 10 Oct 2014 14:22:21 +0100 Subject: [PATCH 077/641] Indirect jump: jump table generated in separate bblock. --- evmcc/Compiler.cpp | 52 +++++++++++++++++++++++++++++++++++++++++++--- evmcc/Compiler.h | 5 +++++ evmcc/lll/if1.lll | 2 +- 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 0e3603fe6..0d3487e10 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -147,6 +147,7 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode) m_finalBlock = std::make_unique("FinalBlock", m_mainFunc); m_badJumpBlock = std::make_unique("BadJumpBlock", m_mainFunc); + m_jumpTableBlock = std::make_unique("JumpTableBlock", m_mainFunc); for (auto it = directJumpTargets.cbegin(); it != directJumpTargets.cend(); ++it) { @@ -626,6 +627,8 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) std::exit(1); } + builder.CreateBr(m_jumpTableBlock->llvm()); + /* // Generate switch for indirect jump. auto dest = stack.pop(); auto switchInstr = builder.CreateSwitch(dest, m_badJumpBlock->llvm(), @@ -636,7 +639,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto dest = ConstantInt::get(Type::i256, bb->begin()); switchInstr->addCase(dest, bb->llvm()); } - + */ break; } @@ -836,12 +839,35 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) } // Code for special blocks: + // TODO: move to separate function. + // Note: Right now the codegen for special blocks depends only on createBasicBlock(), + // not on the codegen for 'regular' blocks. But it has to be done before linkBasicBlocks(). builder.SetInsertPoint(m_finalBlock->llvm()); builder.CreateRet(builder.getInt64(0)); // TODO: throw an exception or something builder.SetInsertPoint(m_badJumpBlock->llvm()); - builder.CreateRet(builder.getInt64(1)); + builder.CreateRet(builder.getInt64(0)); + + builder.SetInsertPoint(m_jumpTableBlock->llvm()); + if (m_indirectJumpTargets.size() > 0) + { + auto& stack = m_jumpTableBlock->getStack(); + + auto dest = stack.pop(); + auto switchInstr = builder.CreateSwitch(dest, m_badJumpBlock->llvm(), + m_indirectJumpTargets.size()); + for (auto it = m_indirectJumpTargets.cbegin(); it != m_indirectJumpTargets.cend(); ++it) + { + auto& bb = *it; + auto dest = ConstantInt::get(Type::i256, bb->begin()); + switchInstr->addCase(dest, bb->llvm()); + } + } + else + { + builder.CreateRet(builder.getInt64(0)); + } linkBasicBlocks(); @@ -861,10 +887,30 @@ void Compiler::linkBasicBlocks() return basicBlocks.find(idx)->second; }; + auto completePhiNodes = [findBasicBlock](llvm::BasicBlock* _llbb) -> void + { + size_t valueIdx = 0; + auto firstNonPhi = _llbb->getFirstNonPHI(); + for (auto instIt = _llbb->begin(); &*instIt != firstNonPhi; ++instIt, ++valueIdx) + { + auto phi = llvm::cast(instIt); + for (auto predIt = llvm::pred_begin(_llbb); predIt != llvm::pred_end(_llbb); ++predIt) + { + auto& predBB = findBasicBlock(*predIt); + // assert(valueIdx < predBB.getStack().size()); // TODO: Report error + phi->addIncoming(predBB.getStack().get(valueIdx), predBB); + } + } + }; + // Link basic blocks for (auto&& p : basicBlocks) { BasicBlock& bb = p.second; + completePhiNodes(bb.llvm()); + } + completePhiNodes(m_jumpTableBlock->llvm()); + /* llvm::BasicBlock* llvmBB = bb.llvm(); size_t valueIdx = 0; @@ -879,7 +925,7 @@ void Compiler::linkBasicBlocks() phi->addIncoming(predBB.getStack().get(valueIdx), predBB); } } - } + */ } } diff --git a/evmcc/Compiler.h b/evmcc/Compiler.h index f57d800a4..7d0cb4ab6 100644 --- a/evmcc/Compiler.h +++ b/evmcc/Compiler.h @@ -49,6 +49,11 @@ private: */ std::unique_ptr m_finalBlock; + /** + * Block with a jump table. + */ + std::unique_ptr m_jumpTableBlock; + /** * Default destination for indirect jumps. */ diff --git a/evmcc/lll/if1.lll b/evmcc/lll/if1.lll index a807b697d..7984807c1 100644 --- a/evmcc/lll/if1.lll +++ b/evmcc/lll/if1.lll @@ -2,4 +2,4 @@ [i] 1 ( if (> @i 0) [i] 2 [i] 3 ) -} \ No newline at end of file +} From 4b8d51e23e2d62b5e83a134d63e9b5c1e02f93bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 10 Oct 2014 17:17:45 +0200 Subject: [PATCH 078/641] Renames & comments --- evmcc/GasMeter.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index a40b8cb5c..013205ee6 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -49,7 +49,7 @@ uint64_t getStepCost(dev::eth::Instruction inst) // TODO: Add this function to F } } -bool isCommitTrigger(Instruction _inst) +bool isCostBlockEnd(Instruction _inst) { switch (_inst) { @@ -101,17 +101,16 @@ void GasMeter::check(Instruction _inst) { if (!m_checkCall) { + // Create gas check call with mocked block cost at begining of current cost-block m_checkCall = m_builder.CreateCall(m_gasCheckFunc, m_builder.getIntN(256, 0)); } - auto stepCost = getStepCost(_inst); - m_blockCost += stepCost; + m_blockCost += getStepCost(_inst); - auto isTrigger = isCommitTrigger(_inst); - if (isTrigger) - { - m_checkCall->setArgOperand(0, m_builder.getIntN(256, m_blockCost)); - m_checkCall = nullptr; + if (isCostBlockEnd(_inst)) + { + m_checkCall->setArgOperand(0, m_builder.getIntN(256, m_blockCost)); // Update block cost in gas check call + m_checkCall = nullptr; // End cost-block } } From 35605271f16d3e47452116c2e732efd9f92f4c61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 10 Oct 2014 17:23:34 +0200 Subject: [PATCH 079/641] Fix for finding jumpTableBlock --- evmcc/Compiler.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 1e2982b29..806592287 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -879,6 +879,10 @@ void Compiler::linkBasicBlocks() /// Helper function that finds basic block given LLVM basic block pointer auto findBasicBlock = [this](llvm::BasicBlock* _llbb) -> BasicBlock& { + // TODO: Fix for finding jumpTableBlock + if (_llbb == this->m_jumpTableBlock->llvm()) + return *this->m_jumpTableBlock; + // Name is used to get basic block index (index of first instruction) // TODO: If basicBlocs are still a map - multikey map can be used auto&& idxStr = _llbb->getName().substr(sizeof(BasicBlock::NamePrefix) - 2); From 4a1511309c20c48a2d6982aa97f24f3dbda5b96b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 10 Oct 2014 18:56:59 +0200 Subject: [PATCH 080/641] Generate mem.store function and dependencies (currently unused) [#80191662] --- evmcc/Memory.cpp | 60 ++++++++++++++++++++++++++++++++++++++++++++---- evmcc/Memory.h | 8 ++++++- evmcc/Type.cpp | 6 +++++ evmcc/Type.h | 4 ++++ 4 files changed, 73 insertions(+), 5 deletions(-) diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index e3bbd5d40..1a988be0d 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -6,10 +6,12 @@ #include #include +#include #include #include +#include "Type.h" #include "Runtime.h" #ifdef _MSC_VER @@ -21,7 +23,7 @@ namespace evmcc { -Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* module) +Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module) : m_builder(_builder) { auto voidTy = m_builder.getVoidTy(); @@ -30,17 +32,59 @@ Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* module) auto memRequireTy = llvm::FunctionType::get(m_builder.getInt8PtrTy(), i64Ty, false); m_memRequire = llvm::Function::Create(memRequireTy, llvm::GlobalValue::LinkageTypes::ExternalLinkage, - "evmccrt_memory_require", module); + "evmccrt_memory_require", _module); auto memSizeTy = llvm::FunctionType::get(i64Ty, false); m_memSize = llvm::Function::Create(memSizeTy, llvm::GlobalValue::LinkageTypes::ExternalLinkage, - "evmccrt_memory_size", module); + "evmccrt_memory_size", _module); std::vector argTypes = {i64Ty, i64Ty}; auto dumpTy = llvm::FunctionType::get(m_builder.getVoidTy(), llvm::ArrayRef(argTypes), false); m_memDump = llvm::Function::Create(dumpTy, llvm::GlobalValue::LinkageTypes::ExternalLinkage, - "evmccrt_memory_dump", module); + "evmccrt_memory_dump", _module); + + m_data = new llvm::GlobalVariable(*_module, Type::BytePtr, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::BytePtr), "mem.data"); + m_data->setUnnamedAddr(true); // Address is not important + + m_size = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::PrivateLinkage, m_builder.getIntN(256, 0), "mem.size"); + m_size->setUnnamedAddr(true); // Address is not important + + m_resize = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, Type::WordPtr, false), llvm::Function::ExternalLinkage, "mem_resize", _module); + + llvm::Type* storeArgs[] = {Type::i256, Type::i256}; + m_store = llvm::Function::Create(llvm::FunctionType::get(Type::Void, storeArgs, false), llvm::Function::PrivateLinkage, "mem.store", _module); + auto origBB = m_builder.GetInsertBlock(); + auto origPt = m_builder.GetInsertPoint(); + + auto checkBB = llvm::BasicBlock::Create(m_store->getContext(), "check", m_store); + auto resizeBB = llvm::BasicBlock::Create(m_store->getContext(), "resize", m_store); + auto storeBB = llvm::BasicBlock::Create(m_store->getContext(), "store", m_store); + + m_builder.SetInsertPoint(checkBB); + llvm::Value* index = m_store->arg_begin(); + index->setName("index"); + llvm::Value* value = ++m_store->arg_begin(); + value->setName("value"); + auto sizeRequired = m_builder.CreateAdd(index, m_builder.getIntN(256, 32), "sizeRequired"); + auto size = m_builder.CreateLoad(m_size, "size"); + auto resizeNeeded = m_builder.CreateICmpULE(sizeRequired, size, "resizeNeeded"); + m_builder.CreateCondBr(resizeNeeded, resizeBB, storeBB); // OPT branch weights? + + m_builder.SetInsertPoint(resizeBB); + m_builder.CreateStore(sizeRequired, m_size); + llvm::Value* data = m_builder.CreateCall(m_resize, m_size, "data"); + m_builder.CreateStore(data, m_data); + m_builder.CreateBr(storeBB); + + m_builder.SetInsertPoint(storeBB); + data = m_builder.CreateLoad(m_data, "data"); + auto ptr = m_builder.CreateGEP(data, index, "ptr"); + ptr = m_builder.CreateBitCast(ptr, Type::WordPtr, "wordPtr"); + m_builder.CreateStore(value, ptr); + m_builder.CreateRetVoid(); + + m_builder.SetInsertPoint(origBB, origPt); } @@ -114,6 +158,14 @@ extern "C" { using namespace evmcc; +EXPORT uint8_t* mem_resize(i256* _size) +{ + auto size = _size->a; // Trunc to 64-bit + auto& memory = Runtime::getMemory(); + memory.resize(size); + return memory.data(); +} + // Resizes memory to contain at least _index + 1 bytes and returns the base address. EXPORT uint8_t* evmccrt_memory_require(uint64_t _index) { diff --git a/evmcc/Memory.h b/evmcc/Memory.h index da6662fef..a28a3c91e 100644 --- a/evmcc/Memory.h +++ b/evmcc/Memory.h @@ -10,7 +10,7 @@ namespace evmcc class Memory { public: - Memory(llvm::IRBuilder<>& _builder, llvm::Module* module); + Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module); llvm::Value* loadWord(llvm::Value* _addr); void storeWord(llvm::Value* _addr, llvm::Value* _word); @@ -22,6 +22,12 @@ public: private: llvm::IRBuilder<>& m_builder; + llvm::GlobalVariable* m_data; + llvm::GlobalVariable* m_size; + + llvm::Function* m_store; + llvm::Function* m_resize; + llvm::Function* m_memRequire; llvm::Function* m_memDump; llvm::Function* m_memSize; diff --git a/evmcc/Type.cpp b/evmcc/Type.cpp index f5c74c1e9..0c8b6d92e 100644 --- a/evmcc/Type.cpp +++ b/evmcc/Type.cpp @@ -7,13 +7,19 @@ namespace evmcc { llvm::IntegerType* Type::i256; +llvm::PointerType* Type::WordPtr; llvm::IntegerType* Type::lowPrecision; +llvm::IntegerType* Type::Byte; +llvm::PointerType* Type::BytePtr; llvm::Type* Type::Void; void Type::init(llvm::LLVMContext& _context) { i256 = llvm::Type::getIntNTy(_context, 256); + WordPtr = i256->getPointerTo(); lowPrecision = llvm::Type::getInt64Ty(_context); + Byte = llvm::Type::getInt8Ty(_context); + BytePtr = Byte->getPointerTo(); Void = llvm::Type::getVoidTy(_context); } diff --git a/evmcc/Type.h b/evmcc/Type.h index a25d7a9e9..fe4bce335 100644 --- a/evmcc/Type.h +++ b/evmcc/Type.h @@ -9,11 +9,15 @@ namespace evmcc struct Type { static llvm::IntegerType* i256; + static llvm::PointerType* WordPtr; /// Type for doing low precision arithmetics where 256-bit precision is not supported by native target /// @TODO: Use 64-bit for now. In 128-bit compiler-rt library functions are required static llvm::IntegerType* lowPrecision; + static llvm::IntegerType* Byte; + static llvm::PointerType* BytePtr; + static llvm::Type* Void; static void init(llvm::LLVMContext& _context); From 2df83af3be925780211b4a80753c37cbff24742b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 10 Oct 2014 19:06:40 +0200 Subject: [PATCH 081/641] Use mem.store as implementation of MSTORE [#80191662] --- evmcc/Memory.cpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index 1a988be0d..a1d3c9989 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -108,15 +108,7 @@ llvm::Value* Memory::loadWord(llvm::Value* _addr) void Memory::storeWord(llvm::Value* _addr, llvm::Value* _word) { - auto index = m_builder.CreateTrunc(_addr, m_builder.getInt64Ty(), "mem.index"); - auto index31 = m_builder.CreateAdd(index, llvm::ConstantInt::get(m_builder.getInt64Ty(), 31), "mem.index31"); - - auto base = m_builder.CreateCall(m_memRequire, index31, "base"); - auto ptr = m_builder.CreateGEP(base, index, "ptr"); - - auto i256ptrTy = m_builder.getIntNTy(256)->getPointerTo(); - auto wordPtr = m_builder.CreateBitCast(ptr, i256ptrTy, "wordptr"); - m_builder.CreateStore(_word, wordPtr); + m_builder.CreateCall2(m_store, _addr, _word); dump(0); } @@ -160,6 +152,7 @@ extern "C" EXPORT uint8_t* mem_resize(i256* _size) { + assert(false); auto size = _size->a; // Trunc to 64-bit auto& memory = Runtime::getMemory(); memory.resize(size); From 0400b47357d0fc3e71d80f98bc7458c2e10cb026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 10 Oct 2014 19:43:07 +0200 Subject: [PATCH 082/641] store8 function added as implementation of MSTORE8 [#80191662] --- evmcc/Memory.cpp | 77 +++++++++++++++++++++++++----------------------- evmcc/Memory.h | 8 ++++- 2 files changed, 47 insertions(+), 38 deletions(-) diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index a1d3c9989..222db8482 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -51,40 +51,48 @@ Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module) m_size->setUnnamedAddr(true); // Address is not important m_resize = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, Type::WordPtr, false), llvm::Function::ExternalLinkage, "mem_resize", _module); + m_storeWord = createStoreFunc(Type::i256, _module); + m_storeByte = createStoreFunc(Type::Byte, _module); +} + +llvm::Function* Memory::createStoreFunc(llvm::Type* _valueType, llvm::Module* _module) +{ + auto wordValue = _valueType == Type::i256; - llvm::Type* storeArgs[] = {Type::i256, Type::i256}; - m_store = llvm::Function::Create(llvm::FunctionType::get(Type::Void, storeArgs, false), llvm::Function::PrivateLinkage, "mem.store", _module); - auto origBB = m_builder.GetInsertBlock(); - auto origPt = m_builder.GetInsertPoint(); + llvm::Type* storeArgs[] = {Type::i256, _valueType}; + auto name = wordValue ? "store" : "store8"; + auto storeFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, storeArgs, false), llvm::Function::PrivateLinkage, name, _module); - auto checkBB = llvm::BasicBlock::Create(m_store->getContext(), "check", m_store); - auto resizeBB = llvm::BasicBlock::Create(m_store->getContext(), "resize", m_store); - auto storeBB = llvm::BasicBlock::Create(m_store->getContext(), "store", m_store); + auto checkBB = llvm::BasicBlock::Create(storeFunc->getContext(), "check", storeFunc); + auto resizeBB = llvm::BasicBlock::Create(storeFunc->getContext(), "resize", storeFunc); + auto storeBB = llvm::BasicBlock::Create(storeFunc->getContext(), "store", storeFunc); - m_builder.SetInsertPoint(checkBB); - llvm::Value* index = m_store->arg_begin(); + llvm::IRBuilder<> builder(checkBB); + llvm::Value* index = storeFunc->arg_begin(); index->setName("index"); - llvm::Value* value = ++m_store->arg_begin(); + llvm::Value* value = ++storeFunc->arg_begin(); value->setName("value"); - auto sizeRequired = m_builder.CreateAdd(index, m_builder.getIntN(256, 32), "sizeRequired"); - auto size = m_builder.CreateLoad(m_size, "size"); - auto resizeNeeded = m_builder.CreateICmpULE(sizeRequired, size, "resizeNeeded"); - m_builder.CreateCondBr(resizeNeeded, resizeBB, storeBB); // OPT branch weights? - - m_builder.SetInsertPoint(resizeBB); - m_builder.CreateStore(sizeRequired, m_size); - llvm::Value* data = m_builder.CreateCall(m_resize, m_size, "data"); - m_builder.CreateStore(data, m_data); - m_builder.CreateBr(storeBB); - - m_builder.SetInsertPoint(storeBB); - data = m_builder.CreateLoad(m_data, "data"); - auto ptr = m_builder.CreateGEP(data, index, "ptr"); - ptr = m_builder.CreateBitCast(ptr, Type::WordPtr, "wordPtr"); - m_builder.CreateStore(value, ptr); - m_builder.CreateRetVoid(); - - m_builder.SetInsertPoint(origBB, origPt); + auto valueSize = _valueType->getPrimitiveSizeInBits() / 8; + auto sizeRequired = builder.CreateAdd(index, builder.getIntN(256, valueSize), "sizeRequired"); + auto size = builder.CreateLoad(m_size, "size"); + auto resizeNeeded = builder.CreateICmpULE(sizeRequired, size, "resizeNeeded"); + builder.CreateCondBr(resizeNeeded, resizeBB, storeBB); // OPT branch weights? + + builder.SetInsertPoint(resizeBB); + builder.CreateStore(sizeRequired, m_size); + auto newData = builder.CreateCall(m_resize, m_size, "newData"); + builder.CreateStore(newData, m_data); + builder.CreateBr(storeBB); + + builder.SetInsertPoint(storeBB); + auto data = builder.CreateLoad(m_data, "data"); + auto ptr = builder.CreateGEP(data, index, "ptr"); + if (wordValue) + ptr = builder.CreateBitCast(ptr, Type::WordPtr, "wordPtr"); + builder.CreateStore(value, ptr); + builder.CreateRetVoid(); + + return storeFunc; } @@ -108,19 +116,15 @@ llvm::Value* Memory::loadWord(llvm::Value* _addr) void Memory::storeWord(llvm::Value* _addr, llvm::Value* _word) { - m_builder.CreateCall2(m_store, _addr, _word); + m_builder.CreateCall2(m_storeWord, _addr, _word); dump(0); } void Memory::storeByte(llvm::Value* _addr, llvm::Value* _word) { - auto byte = m_builder.CreateTrunc(_word, m_builder.getInt8Ty(), "byte"); - auto index = m_builder.CreateTrunc(_addr, m_builder.getInt64Ty(), "index"); - - auto base = m_builder.CreateCall(m_memRequire, index, "base"); - auto ptr = m_builder.CreateGEP(base, index, "ptr"); - m_builder.CreateStore(byte, ptr); + auto byte = m_builder.CreateTrunc(_word, Type::Byte, "byte"); + m_builder.CreateCall2(m_storeByte, _addr, byte); dump(0); } @@ -152,7 +156,6 @@ extern "C" EXPORT uint8_t* mem_resize(i256* _size) { - assert(false); auto size = _size->a; // Trunc to 64-bit auto& memory = Runtime::getMemory(); memory.resize(size); diff --git a/evmcc/Memory.h b/evmcc/Memory.h index a28a3c91e..f1d75e5b3 100644 --- a/evmcc/Memory.h +++ b/evmcc/Memory.h @@ -11,6 +11,8 @@ class Memory { public: Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module); + Memory(const Memory&) = delete; + void operator=(Memory) = delete; llvm::Value* loadWord(llvm::Value* _addr); void storeWord(llvm::Value* _addr, llvm::Value* _word); @@ -19,13 +21,17 @@ public: void dump(uint64_t _begin, uint64_t _end = 0); +private: + llvm::Function* createStoreFunc(llvm::Type* _type, llvm::Module* _module); + private: llvm::IRBuilder<>& m_builder; llvm::GlobalVariable* m_data; llvm::GlobalVariable* m_size; - llvm::Function* m_store; + llvm::Function* m_storeWord; + llvm::Function* m_storeByte; llvm::Function* m_resize; llvm::Function* m_memRequire; From 48ed393fb3e8cf8b304f1aa6f4612e478f715438 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 10 Oct 2014 20:10:09 +0200 Subject: [PATCH 083/641] mload function added as implementation of MLOAD [#80191662] --- evmcc/Memory.cpp | 67 +++++++++++++++++++++++------------------------- evmcc/Memory.h | 3 ++- 2 files changed, 34 insertions(+), 36 deletions(-) diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index 222db8482..8f03c2144 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -51,67 +51,66 @@ Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module) m_size->setUnnamedAddr(true); // Address is not important m_resize = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, Type::WordPtr, false), llvm::Function::ExternalLinkage, "mem_resize", _module); - m_storeWord = createStoreFunc(Type::i256, _module); - m_storeByte = createStoreFunc(Type::Byte, _module); + m_loadWord = createFunc(false, Type::i256, _module); + m_storeWord = createFunc(true, Type::i256, _module); + m_storeByte = createFunc(true, Type::Byte, _module); } -llvm::Function* Memory::createStoreFunc(llvm::Type* _valueType, llvm::Module* _module) +llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, llvm::Module* _module) { - auto wordValue = _valueType == Type::i256; + auto isWord = _valueType == Type::i256; llvm::Type* storeArgs[] = {Type::i256, _valueType}; - auto name = wordValue ? "store" : "store8"; - auto storeFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, storeArgs, false), llvm::Function::PrivateLinkage, name, _module); + auto name = _isStore ? isWord ? "mstore" : "mstore8" : "mload"; + auto funcType = _isStore ? llvm::FunctionType::get(Type::Void, storeArgs, false) : llvm::FunctionType::get(Type::i256, Type::i256, false); + auto func = llvm::Function::Create(funcType, llvm::Function::PrivateLinkage, name, _module); - auto checkBB = llvm::BasicBlock::Create(storeFunc->getContext(), "check", storeFunc); - auto resizeBB = llvm::BasicBlock::Create(storeFunc->getContext(), "resize", storeFunc); - auto storeBB = llvm::BasicBlock::Create(storeFunc->getContext(), "store", storeFunc); + auto checkBB = llvm::BasicBlock::Create(func->getContext(), "check", func); + auto resizeBB = llvm::BasicBlock::Create(func->getContext(), "resize", func); + auto accessBB = llvm::BasicBlock::Create(func->getContext(), "access", func); llvm::IRBuilder<> builder(checkBB); - llvm::Value* index = storeFunc->arg_begin(); + llvm::Value* index = func->arg_begin(); index->setName("index"); - llvm::Value* value = ++storeFunc->arg_begin(); - value->setName("value"); auto valueSize = _valueType->getPrimitiveSizeInBits() / 8; auto sizeRequired = builder.CreateAdd(index, builder.getIntN(256, valueSize), "sizeRequired"); auto size = builder.CreateLoad(m_size, "size"); auto resizeNeeded = builder.CreateICmpULE(sizeRequired, size, "resizeNeeded"); - builder.CreateCondBr(resizeNeeded, resizeBB, storeBB); // OPT branch weights? + builder.CreateCondBr(resizeNeeded, resizeBB, accessBB); // OPT branch weights? builder.SetInsertPoint(resizeBB); builder.CreateStore(sizeRequired, m_size); auto newData = builder.CreateCall(m_resize, m_size, "newData"); builder.CreateStore(newData, m_data); - builder.CreateBr(storeBB); + builder.CreateBr(accessBB); - builder.SetInsertPoint(storeBB); + builder.SetInsertPoint(accessBB); auto data = builder.CreateLoad(m_data, "data"); auto ptr = builder.CreateGEP(data, index, "ptr"); - if (wordValue) + if (isWord) ptr = builder.CreateBitCast(ptr, Type::WordPtr, "wordPtr"); - builder.CreateStore(value, ptr); - builder.CreateRetVoid(); - - return storeFunc; + if (_isStore) + { + llvm::Value* value = ++func->arg_begin(); + value->setName("value"); + builder.CreateStore(value, ptr); + builder.CreateRetVoid(); + } + else + { + auto ret = builder.CreateLoad(ptr); + builder.CreateRet(ret); + } + return func; } llvm::Value* Memory::loadWord(llvm::Value* _addr) { - // trunc _addr (an i256) to i64 index and use it to index the memory - auto index = m_builder.CreateTrunc(_addr, m_builder.getInt64Ty(), "mem.index"); - auto index31 = m_builder.CreateAdd(index, llvm::ConstantInt::get(m_builder.getInt64Ty(), 31), "mem.index.31"); - - // load from evmccrt_memory_require()[index] - auto base = m_builder.CreateCall(m_memRequire, index31, "base"); - auto ptr = m_builder.CreateGEP(base, index, "ptr"); - - auto i256ptrTy = m_builder.getIntNTy(256)->getPointerTo(); - auto wordPtr = m_builder.CreateBitCast(ptr, i256ptrTy, "wordptr"); - auto byte = m_builder.CreateLoad(wordPtr, "word"); + auto value = m_builder.CreateCall(m_loadWord, _addr); dump(0); - return byte; + return value; } void Memory::storeWord(llvm::Value* _addr, llvm::Value* _word) @@ -131,9 +130,7 @@ void Memory::storeByte(llvm::Value* _addr, llvm::Value* _word) llvm::Value* Memory::getSize() { - auto size = m_builder.CreateCall(m_memSize, "mem.size"); - auto word = m_builder.CreateZExt(size, m_builder.getIntNTy(256), "mem.wsize"); - return word; + return m_builder.CreateLoad(m_size); } void Memory::dump(uint64_t _begin, uint64_t _end) diff --git a/evmcc/Memory.h b/evmcc/Memory.h index f1d75e5b3..2166abd14 100644 --- a/evmcc/Memory.h +++ b/evmcc/Memory.h @@ -22,7 +22,7 @@ public: void dump(uint64_t _begin, uint64_t _end = 0); private: - llvm::Function* createStoreFunc(llvm::Type* _type, llvm::Module* _module); + llvm::Function* createFunc(bool _isStore, llvm::Type* _type, llvm::Module* _module); private: llvm::IRBuilder<>& m_builder; @@ -30,6 +30,7 @@ private: llvm::GlobalVariable* m_data; llvm::GlobalVariable* m_size; + llvm::Function* m_loadWord; llvm::Function* m_storeWord; llvm::Function* m_storeByte; llvm::Function* m_resize; From 01af0e88cd1c0d42d5639b78467a5e4f7b967d85 Mon Sep 17 00:00:00 2001 From: caktux Date: Sun, 12 Oct 2014 02:14:21 -0400 Subject: [PATCH 084/641] build status --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 7529fed50..d1568402c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ ## Ethereum C++ Client. +[![Build +Status](http://build.ethdev.com/buildstatusimage?builder=Linux%20C%2B%2B%20master%20branch)](http://build.ethdev.com/builders/Linux%20C%2B%2B%20master%20branch/builds/-1) master [![Build +Status](http://build.ethdev.com/buildstatusimage?builder=Linux%20C%2B%2B%20develop%20branch)](http://build.ethdev.com/builders/Linux%20C%2B%2B%20develop%20branch/builds/-1) develop + By Gav Wood, 2014. Based on a design by Vitalik Buterin. From 7c157f68f6078e0f004c13ded80949c2bcdea3e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 13 Oct 2014 09:12:22 +0200 Subject: [PATCH 085/641] Wrong resize condition fixed [Delivers #80191662] --- evmcc/Memory.cpp | 2 +- evmcc/bytecode/mem2.evm | 1 + evmcc/lll/mem2.lll | 11 +++++++++++ 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 evmcc/bytecode/mem2.evm create mode 100644 evmcc/lll/mem2.lll diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index 8f03c2144..ba787614e 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -75,7 +75,7 @@ llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, llvm:: auto valueSize = _valueType->getPrimitiveSizeInBits() / 8; auto sizeRequired = builder.CreateAdd(index, builder.getIntN(256, valueSize), "sizeRequired"); auto size = builder.CreateLoad(m_size, "size"); - auto resizeNeeded = builder.CreateICmpULE(sizeRequired, size, "resizeNeeded"); + auto resizeNeeded = builder.CreateICmpULE(size, sizeRequired, "resizeNeeded"); builder.CreateCondBr(resizeNeeded, resizeBB, accessBB); // OPT branch weights? builder.SetInsertPoint(resizeBB); diff --git a/evmcc/bytecode/mem2.evm b/evmcc/bytecode/mem2.evm new file mode 100644 index 000000000..c00de3089 --- /dev/null +++ b/evmcc/bytecode/mem2.evm @@ -0,0 +1 @@ +6001610d80556504409585d6df620493e05462061a8053 diff --git a/evmcc/lll/mem2.lll b/evmcc/lll/mem2.lll new file mode 100644 index 000000000..66c24c1e1 --- /dev/null +++ b/evmcc/lll/mem2.lll @@ -0,0 +1,11 @@ + +(asm ;; [] +1 +3456 +MSTORE8 ;; [02] +4675432994527 +300000 +MSTORE +400000 +MLOAD +) \ No newline at end of file From e1112c11c995037f5f3ded4deeb3dd113155a918 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 13 Oct 2014 10:04:48 +0200 Subject: [PATCH 086/641] MSIZE test --- evmcc/bytecode/mem2.evm | 2 +- evmcc/lll/mem2.lll | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/evmcc/bytecode/mem2.evm b/evmcc/bytecode/mem2.evm index c00de3089..49cc6e8b1 100644 --- a/evmcc/bytecode/mem2.evm +++ b/evmcc/bytecode/mem2.evm @@ -1 +1 @@ -6001610d80556504409585d6df620493e05462061a8053 +6001610d805b01556504409585d6df620493e05462061a80535b01 diff --git a/evmcc/lll/mem2.lll b/evmcc/lll/mem2.lll index 66c24c1e1..5345ee47c 100644 --- a/evmcc/lll/mem2.lll +++ b/evmcc/lll/mem2.lll @@ -2,10 +2,14 @@ (asm ;; [] 1 3456 +MSIZE +ADD MSTORE8 ;; [02] 4675432994527 300000 MSTORE 400000 MLOAD +MSIZE +ADD ) \ No newline at end of file From 48710b5e5cf03926e504adffd8ab8ebbd4b359ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 13 Oct 2014 10:57:12 +0200 Subject: [PATCH 087/641] Count gas for additional memory [#79942174] --- evmcc/Compiler.cpp | 4 ++-- evmcc/GasMeter.cpp | 7 +++++++ evmcc/GasMeter.h | 3 +++ evmcc/Memory.cpp | 22 ++++++++++++++++------ evmcc/Memory.h | 5 +++-- 5 files changed, 31 insertions(+), 10 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 806592287..e532ce9f5 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -196,9 +196,9 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) createBasicBlocks(bytecode); // Init runtime structures. - auto memory = Memory(builder, module.get()); - auto ext = Ext(builder, module.get()); GasMeter gasMeter(builder, module.get()); + Memory memory(builder, module.get(), gasMeter); + Ext ext(builder, module.get()); // Jump to first instruction builder.CreateBr(basicBlocks.begin()->second); diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index 013205ee6..eed9fa0ad 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -114,4 +114,11 @@ void GasMeter::check(Instruction _inst) } } +void GasMeter::checkMemory(llvm::Value* _additionalMemoryInWords, llvm::IRBuilder<>& _builder) +{ + // Memory uses other builder, but that can be changes later + auto cost = _builder.CreateMul(_additionalMemoryInWords, _builder.getIntN(256, static_cast(c_memoryGas)), "memcost"); + _builder.CreateCall(m_gasCheckFunc, cost); +} + } \ No newline at end of file diff --git a/evmcc/GasMeter.h b/evmcc/GasMeter.h index 057391102..73f0d6e1c 100644 --- a/evmcc/GasMeter.h +++ b/evmcc/GasMeter.h @@ -18,6 +18,9 @@ public: void check(dev::eth::Instruction _inst); + /// Generate code that checks the cost of additional memory used by program + void checkMemory(llvm::Value* _additionalMemoryInWords, llvm::IRBuilder<>& _builder); + private: /// Cumulative gas cost of a block of instructions /// @TODO Handle overflow diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index ba787614e..fa21237b7 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -13,6 +13,7 @@ #include "Type.h" #include "Runtime.h" +#include "GasMeter.h" #ifdef _MSC_VER #define EXPORT __declspec(dllexport) @@ -23,8 +24,8 @@ namespace evmcc { -Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module) - : m_builder(_builder) +Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module, GasMeter& _gasMeter): + m_builder(_builder) { auto voidTy = m_builder.getVoidTy(); auto i64Ty = m_builder.getInt64Ty(); @@ -51,12 +52,12 @@ Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module) m_size->setUnnamedAddr(true); // Address is not important m_resize = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, Type::WordPtr, false), llvm::Function::ExternalLinkage, "mem_resize", _module); - m_loadWord = createFunc(false, Type::i256, _module); - m_storeWord = createFunc(true, Type::i256, _module); - m_storeByte = createFunc(true, Type::Byte, _module); + m_loadWord = createFunc(false, Type::i256, _module, _gasMeter); + m_storeWord = createFunc(true, Type::i256, _module, _gasMeter); + m_storeByte = createFunc(true, Type::Byte, _module, _gasMeter); } -llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, llvm::Module* _module) +llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, llvm::Module* _module, GasMeter& _gasMeter) { auto isWord = _valueType == Type::i256; @@ -69,6 +70,7 @@ llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, llvm:: auto resizeBB = llvm::BasicBlock::Create(func->getContext(), "resize", func); auto accessBB = llvm::BasicBlock::Create(func->getContext(), "access", func); + // BB "check" llvm::IRBuilder<> builder(checkBB); llvm::Value* index = func->arg_begin(); index->setName("index"); @@ -78,12 +80,20 @@ llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, llvm:: auto resizeNeeded = builder.CreateICmpULE(size, sizeRequired, "resizeNeeded"); builder.CreateCondBr(resizeNeeded, resizeBB, accessBB); // OPT branch weights? + // BB "resize" builder.SetInsertPoint(resizeBB); + // Check gas first + auto wordsRequired = builder.CreateUDiv(builder.CreateAdd(sizeRequired, builder.getIntN(256, 31)), builder.getIntN(256, 32), "wordsRequired"); + auto words = builder.CreateUDiv(builder.CreateAdd(size, builder.getIntN(256, 31)), builder.getIntN(256, 32), "words"); + auto newWords = builder.CreateSub(wordsRequired, words, "addtionalWords"); + _gasMeter.checkMemory(newWords, builder); + // Resize builder.CreateStore(sizeRequired, m_size); auto newData = builder.CreateCall(m_resize, m_size, "newData"); builder.CreateStore(newData, m_data); builder.CreateBr(accessBB); + // BB "access" builder.SetInsertPoint(accessBB); auto data = builder.CreateLoad(m_data, "data"); auto ptr = builder.CreateGEP(data, index, "ptr"); diff --git a/evmcc/Memory.h b/evmcc/Memory.h index 2166abd14..ed7273c5c 100644 --- a/evmcc/Memory.h +++ b/evmcc/Memory.h @@ -6,11 +6,12 @@ namespace evmcc { +class GasMeter; class Memory { public: - Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module); + Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module, GasMeter& _gasMeter); Memory(const Memory&) = delete; void operator=(Memory) = delete; @@ -22,7 +23,7 @@ public: void dump(uint64_t _begin, uint64_t _end = 0); private: - llvm::Function* createFunc(bool _isStore, llvm::Type* _type, llvm::Module* _module); + llvm::Function* createFunc(bool _isStore, llvm::Type* _type, llvm::Module* _module, GasMeter& _gasMeter); private: llvm::IRBuilder<>& m_builder; From a03d47083ed3474e924dd994eef82e2924045ebd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 13 Oct 2014 11:35:46 +0200 Subject: [PATCH 088/641] Fix block cost counting (counter not reset) --- evmcc/GasMeter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index eed9fa0ad..26921dee3 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -111,6 +111,7 @@ void GasMeter::check(Instruction _inst) { m_checkCall->setArgOperand(0, m_builder.getIntN(256, m_blockCost)); // Update block cost in gas check call m_checkCall = nullptr; // End cost-block + m_blockCost = 0; } } From f6eef07d37f9e23860e731f7997788aa6e928d42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 13 Oct 2014 12:33:41 +0200 Subject: [PATCH 089/641] Use external counter for gas (external linkage global variable) [#79942174] --- evmcc/ExecutionEngine.cpp | 4 +++- evmcc/Ext.cpp | 6 ------ evmcc/GasMeter.cpp | 2 +- evmcc/Memory.cpp | 6 ------ evmcc/Runtime.cpp | 12 ++++++++++-- evmcc/Runtime.h | 10 +++++++++- 6 files changed, 23 insertions(+), 17 deletions(-) diff --git a/evmcc/ExecutionEngine.cpp b/evmcc/ExecutionEngine.cpp index 6d9d85a4c..be45ff838 100644 --- a/evmcc/ExecutionEngine.cpp +++ b/evmcc/ExecutionEngine.cpp @@ -85,7 +85,8 @@ int ExecutionEngine::run(std::unique_ptr _module) ext->data = calldata; // Init runtime - Runtime runtime(std::move(ext)); + uint64_t gas = 1000000; + Runtime runtime(gas, std::move(ext)); auto entryFunc = module->getFunction("main"); if (!entryFunc) @@ -95,6 +96,7 @@ int ExecutionEngine::run(std::unique_ptr _module) } auto result = exec->runFunction(entryFunc, {}); + gas = static_cast(Runtime::getGas()); if (auto intResult = result.IntVal.getZExtValue()) { auto index = intResult >> 32; diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index 121103354..1d309947d 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -9,12 +9,6 @@ #include "Runtime.h" -#ifdef _MSC_VER -#define EXPORT __declspec(dllexport) -#else -#define EXPORT -#endif - using namespace llvm; using llvm::types::i; using Linkage = llvm::GlobalValue::LinkageTypes; diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index 26921dee3..fd68b9d40 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -81,7 +81,7 @@ bool isCostBlockEnd(Instruction _inst) GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module): m_builder(_builder) { - m_gas = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::i256), "gas"); + m_gas = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "gas"); m_gas->setUnnamedAddr(true); // Address is not important auto pt = m_builder.GetInsertPoint(); diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index fa21237b7..8625d7b5b 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -15,12 +15,6 @@ #include "Runtime.h" #include "GasMeter.h" -#ifdef _MSC_VER - #define EXPORT __declspec(dllexport) -#else - #define EXPORT -#endif - namespace evmcc { diff --git a/evmcc/Runtime.cpp b/evmcc/Runtime.cpp index 9d0738f05..a373d9501 100644 --- a/evmcc/Runtime.cpp +++ b/evmcc/Runtime.cpp @@ -6,11 +6,14 @@ namespace evmcc static Runtime* g_runtime; -Runtime::Runtime(std::unique_ptr _ext) - : m_ext(std::move(_ext)) +extern "C" { EXPORT i256 gas; } + +Runtime::Runtime(dev::u256 _gas, std::unique_ptr _ext): + m_ext(std::move(_ext)) { assert(!g_runtime); g_runtime = this; + gas = eth2llvm(_gas); } Runtime::~Runtime() @@ -33,4 +36,9 @@ dev::eth::ExtVMFace& Runtime::getExt() return *g_runtime->m_ext; } +dev::u256 Runtime::getGas() +{ + return llvm2eth(gas); +} + } \ No newline at end of file diff --git a/evmcc/Runtime.h b/evmcc/Runtime.h index 71c917b9d..547e4bcf1 100644 --- a/evmcc/Runtime.h +++ b/evmcc/Runtime.h @@ -7,6 +7,13 @@ #include "Utils.h" + +#ifdef _MSC_VER + #define EXPORT __declspec(dllexport) +#else + #define EXPORT +#endif + namespace evmcc { @@ -16,7 +23,7 @@ using MemoryImpl = dev::bytes; class Runtime { public: - Runtime(std::unique_ptr _ext); + Runtime(dev::u256 _gas, std::unique_ptr _ext); ~Runtime(); Runtime(const Runtime&) = delete; @@ -25,6 +32,7 @@ public: static StackImpl& getStack(); static MemoryImpl& getMemory(); static dev::eth::ExtVMFace& getExt(); + static dev::u256 getGas(); private: StackImpl m_stack; From c0a7d82b216e60204db70146abf82b785be2df66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 13 Oct 2014 12:50:23 +0200 Subject: [PATCH 090/641] Always commit cost blocks [#79942174] --- evmcc/Compiler.cpp | 4 +++- evmcc/GasMeter.cpp | 18 +++++++++++++----- evmcc/GasMeter.h | 6 +++++- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index e532ce9f5..1fc4ef6a1 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -213,7 +213,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) { auto inst = static_cast(bytecode[currentPC]); - gasMeter.check(inst); + gasMeter.count(inst); switch (inst) { @@ -819,6 +819,8 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) } } + gasMeter.commitCostBlock(); + if (!builder.GetInsertBlock()->getTerminator()) // If block not terminated { if (basicBlock.end() == bytecode.size()) diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index fd68b9d40..7ba822e4a 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -97,22 +97,30 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module): m_builder.SetInsertPoint(bb, pt); } -void GasMeter::check(Instruction _inst) +void GasMeter::count(Instruction _inst) { if (!m_checkCall) { // Create gas check call with mocked block cost at begining of current cost-block - m_checkCall = m_builder.CreateCall(m_gasCheckFunc, m_builder.getIntN(256, 0)); + m_checkCall = m_builder.CreateCall(m_gasCheckFunc, llvm::UndefValue::get(Type::i256)); } m_blockCost += getStepCost(_inst); if (isCostBlockEnd(_inst)) - { - m_checkCall->setArgOperand(0, m_builder.getIntN(256, m_blockCost)); // Update block cost in gas check call + commitCostBlock(); +} + +void GasMeter::commitCostBlock() +{ + // If any uncommited block + if (m_checkCall) + { + m_checkCall->setArgOperand(0, m_builder.getIntN(256, m_blockCost)); // Update block cost in gas check call m_checkCall = nullptr; // End cost-block m_blockCost = 0; - } + } + assert(m_blockCost == 0); } void GasMeter::checkMemory(llvm::Value* _additionalMemoryInWords, llvm::IRBuilder<>& _builder) diff --git a/evmcc/GasMeter.h b/evmcc/GasMeter.h index 73f0d6e1c..38f780ca5 100644 --- a/evmcc/GasMeter.h +++ b/evmcc/GasMeter.h @@ -16,7 +16,11 @@ public: GasMeter(const GasMeter&) = delete; void operator=(GasMeter) = delete; - void check(dev::eth::Instruction _inst); + /// Count step cost of instruction + void count(dev::eth::Instruction _inst); + + /// Finalize cost block by checking gas needed for the block before the block + void commitCostBlock(); /// Generate code that checks the cost of additional memory used by program void checkMemory(llvm::Value* _additionalMemoryInWords, llvm::IRBuilder<>& _builder); From c968a3b594ffe349a7bec3a55a061cad3cdcf629 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Mon, 13 Oct 2014 13:33:04 +0100 Subject: [PATCH 091/641] test cases for JUMP(I) --- evmcc/test/jump/badindirect1.evm | 1 + evmcc/test/jump/badindirect1.lll | 9 +++++++++ evmcc/test/jump/badindirect2.evm | 1 + evmcc/test/jump/badindirect2.lll | 12 ++++++++++++ evmcc/test/jump/badjump1.evm | 2 +- evmcc/test/jump/badjump1.lll | 7 ++----- evmcc/test/jump/badjump2.evm | 1 + evmcc/test/jump/badjump2.lll | 9 +++++++++ evmcc/test/jump/indirect2.lll | 4 ++-- evmcc/test/jump/indirect3.evm | 1 + evmcc/test/jump/indirect3.lll | 14 ++++++++++++++ evmcc/test/jump/indirect4.evm | 1 + evmcc/test/jump/indirect4.lll | 15 +++++++++++++++ 13 files changed, 69 insertions(+), 8 deletions(-) create mode 100644 evmcc/test/jump/badindirect1.evm create mode 100644 evmcc/test/jump/badindirect1.lll create mode 100644 evmcc/test/jump/badindirect2.evm create mode 100644 evmcc/test/jump/badindirect2.lll create mode 100644 evmcc/test/jump/badjump2.evm create mode 100644 evmcc/test/jump/badjump2.lll create mode 100644 evmcc/test/jump/indirect3.evm create mode 100644 evmcc/test/jump/indirect3.lll create mode 100644 evmcc/test/jump/indirect4.evm create mode 100644 evmcc/test/jump/indirect4.lll diff --git a/evmcc/test/jump/badindirect1.evm b/evmcc/test/jump/badindirect1.evm new file mode 100644 index 000000000..b2a8aad67 --- /dev/null +++ b/evmcc/test/jump/badindirect1.evm @@ -0,0 +1 @@ +601b602502585d diff --git a/evmcc/test/jump/badindirect1.lll b/evmcc/test/jump/badindirect1.lll new file mode 100644 index 000000000..d6291be68 --- /dev/null +++ b/evmcc/test/jump/badindirect1.lll @@ -0,0 +1,9 @@ +;; Indirect jump out of code + +(asm +27 +37 +MUL +JUMP +JUMPDEST +) \ No newline at end of file diff --git a/evmcc/test/jump/badindirect2.evm b/evmcc/test/jump/badindirect2.evm new file mode 100644 index 000000000..22217523d --- /dev/null +++ b/evmcc/test/jump/badindirect2.evm @@ -0,0 +1 @@ +60016003600302596000600058 diff --git a/evmcc/test/jump/badindirect2.lll b/evmcc/test/jump/badindirect2.lll new file mode 100644 index 000000000..53a6294f7 --- /dev/null +++ b/evmcc/test/jump/badindirect2.lll @@ -0,0 +1,12 @@ +;; Indirect jump into data + +(asm +1 ;; 0 +3 +3 +MUL ;; 6 +JUMPI ;; 7 +0 ;; 8 +0 +JUMP +) \ No newline at end of file diff --git a/evmcc/test/jump/badjump1.evm b/evmcc/test/jump/badjump1.evm index b2a8aad67..5c11a8661 100644 --- a/evmcc/test/jump/badjump1.evm +++ b/evmcc/test/jump/badjump1.evm @@ -1 +1 @@ -601b602502585d +6103e758 diff --git a/evmcc/test/jump/badjump1.lll b/evmcc/test/jump/badjump1.lll index c3f9f8d69..1834a62ef 100644 --- a/evmcc/test/jump/badjump1.lll +++ b/evmcc/test/jump/badjump1.lll @@ -1,9 +1,6 @@ -;; Bad indirect jump. Should go to BadJumpBlock. +;; Direct jump out of code. (asm -27 -37 -MUL +999 JUMP -JUMPDEST ) \ No newline at end of file diff --git a/evmcc/test/jump/badjump2.evm b/evmcc/test/jump/badjump2.evm new file mode 100644 index 000000000..900a1c15a --- /dev/null +++ b/evmcc/test/jump/badjump2.evm @@ -0,0 +1 @@ +6004586000600058 diff --git a/evmcc/test/jump/badjump2.lll b/evmcc/test/jump/badjump2.lll new file mode 100644 index 000000000..ce61276d7 --- /dev/null +++ b/evmcc/test/jump/badjump2.lll @@ -0,0 +1,9 @@ +;; Direct jump into data + +(asm +4 ;; 0 0-3 +JUMP ;; 2 +0 ;; 3 3-4 +0 ;; 5 4-7 +JUMP ;; 6 +) \ No newline at end of file diff --git a/evmcc/test/jump/indirect2.lll b/evmcc/test/jump/indirect2.lll index 9a4db8c14..f2f068630 100644 --- a/evmcc/test/jump/indirect2.lll +++ b/evmcc/test/jump/indirect2.lll @@ -4,14 +4,14 @@ 8 ;; 0 6 ;; 2 ADD ;; 4 -JUMP ;; 5 +JUMP ;; 5 --> 14 STOP ;; 6 JUMPDEST ;; 7 1 ;; 8 0 ;; 10 MSTORE ;; 12 STOP ;; 13 -JUMPDEST ;; 14 +JUMPDEST ;; 14 2 0 MSTORE diff --git a/evmcc/test/jump/indirect3.evm b/evmcc/test/jump/indirect3.evm new file mode 100644 index 000000000..1fb0a356c --- /dev/null +++ b/evmcc/test/jump/indirect3.evm @@ -0,0 +1 @@ +6001600460050159005d6001600054 diff --git a/evmcc/test/jump/indirect3.lll b/evmcc/test/jump/indirect3.lll new file mode 100644 index 000000000..d6a679f9a --- /dev/null +++ b/evmcc/test/jump/indirect3.lll @@ -0,0 +1,14 @@ +;; Indirect JUMP + +(asm +1 ;; 0 +4 ;; 2 +5 ;; 4 +ADD ;; 6 +JUMPI ;; 7 +STOP ;; 8 +JUMPDEST ;; 9 +1 +0 +MSTORE +) \ No newline at end of file diff --git a/evmcc/test/jump/indirect4.evm b/evmcc/test/jump/indirect4.evm new file mode 100644 index 000000000..f0e31a8f4 --- /dev/null +++ b/evmcc/test/jump/indirect4.evm @@ -0,0 +1 @@ +60006007600501596001600054005d00 diff --git a/evmcc/test/jump/indirect4.lll b/evmcc/test/jump/indirect4.lll new file mode 100644 index 000000000..7fbe0b833 --- /dev/null +++ b/evmcc/test/jump/indirect4.lll @@ -0,0 +1,15 @@ +;; Indirect JUMP + +(asm +0 ;; 0 +7 ;; 2 +5 ;; 4 +ADD ;; 6 +JUMPI ;; 7 +1 ;; 8 +0 ;; 9 +MSTORE ;; 10 +STOP ;; 11 +JUMPDEST ;; 12 +STOP +) \ No newline at end of file From 1afcca2d0b3244073a6c4491eccd542e88714562 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Mon, 13 Oct 2014 13:34:25 +0100 Subject: [PATCH 092/641] Implemented indirect JUMPI and fixes for JUMPs to invalid PCs --- evmcc/Compiler.cpp | 107 +++++++++++++++++++++++---------------------- 1 file changed, 54 insertions(+), 53 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 806592287..b6c420d53 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -137,7 +137,16 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode) } } - for (auto it = splitPoints.cbegin(); it != splitPoints.cend() && *it < bytecode.size();) + // Remove split points generated from jumps out of code or into data. + for (auto it = splitPoints.cbegin(); it != splitPoints.cend(); ) + { + if (*it > bytecode.size() || !validJumpTargets[*it]) + it = splitPoints.erase(it); + else + ++it; + } + + for (auto it = splitPoints.cbegin(); it != splitPoints.cend(); ) { auto beginInstIdx = *it; ++it; @@ -151,28 +160,22 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode) for (auto it = directJumpTargets.cbegin(); it != directJumpTargets.cend(); ++it) { - if (it->second >= bytecode.size()) // Jump out of code + auto blockIter = basicBlocks.find(it->second); + if (blockIter != basicBlocks.end()) { - m_directJumpTargets[it->first] = m_finalBlock.get(); + m_directJumpTargets[it->first] = &(blockIter->second); } - else if (!validJumpTargets[it->second]) // Jump into data + else { std::cerr << "Bad JUMP at PC " << it->first << ": " << it->second << " is not a valid PC\n"; m_directJumpTargets[it->first] = m_badJumpBlock.get(); } - else - { - m_directJumpTargets[it->first] = &basicBlocks.find(it->second)->second; - } } for (auto it = indirectJumpTargets.cbegin(); it != indirectJumpTargets.cend(); ++it) { - if (*it >= bytecode.size()) - m_indirectJumpTargets.push_back(m_finalBlock.get()); - else - m_indirectJumpTargets.push_back(&basicBlocks.find(*it)->second); + m_indirectJumpTargets.push_back(&basicBlocks.find(*it)->second); } } @@ -196,8 +199,8 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) createBasicBlocks(bytecode); // Init runtime structures. - auto memory = Memory(builder, module.get()); - auto ext = Ext(builder, module.get()); + Memory memory(builder, module.get()); + Ext ext(builder, module.get()); GasMeter gasMeter(builder, module.get()); // Jump to first instruction @@ -587,58 +590,56 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) // 1. this is not the first instruction in the block // 2. m_directJumpTargets[currentPC] is defined (meaning that the previous instruction is a PUSH) // Otherwise generate a indirect jump (a switch). + BasicBlock* targetBlock = nullptr; if (currentPC != basicBlock.begin()) { auto pairIter = m_directJumpTargets.find(currentPC); if (pairIter != m_directJumpTargets.end()) { - auto targetBlock = pairIter->second; + targetBlock = pairIter->second; + } + } + if (inst == Instruction::JUMP) + { + if (targetBlock) + { // The target address is computed at compile time, // just pop it without looking... stack.pop(); - - if (inst == Instruction::JUMP) - { - builder.CreateBr(targetBlock->llvm()); - } - else // JUMPI - { - auto top = stack.pop(); - auto zero = ConstantInt::get(Type::i256, 0); - auto cond = builder.CreateICmpNE(top, zero, "nonzero"); - - // Assume the basic blocks are properly ordered: - auto nextBBIter = basicBlockPairIt; - ++nextBBIter; - assert (nextBBIter != basicBlocks.end()); - auto& followBlock = nextBBIter->second; - builder.CreateCondBr(cond, targetBlock->llvm(), followBlock.llvm()); - } - break; + builder.CreateBr(targetBlock->llvm()); + } + else + { + // FIXME: this get(0) is a temporary workaround to get some of the jump tests running. + stack.get(0); + builder.CreateBr(m_jumpTableBlock->llvm()); } } - - if (inst == Instruction::JUMPI) + else // JUMPI { - std::cerr << "Indirect JUMPI is not supported yet (at PC " - << currentPC << ")\n"; - std::exit(1); + stack.swap(1); + auto val = stack.pop(); + auto zero = ConstantInt::get(Type::i256, 0); + auto cond = builder.CreateICmpNE(val, zero, "nonzero"); + + // Assume the basic blocks are properly ordered: + auto nextBBIter = basicBlockPairIt; + ++nextBBIter; + assert (nextBBIter != basicBlocks.end()); + auto& followBlock = nextBBIter->second; + + if (targetBlock) + { + stack.pop(); + builder.CreateCondBr(cond, targetBlock->llvm(), followBlock.llvm()); + } + else + { + builder.CreateCondBr(cond, m_jumpTableBlock->llvm(), followBlock.llvm()); + } } - builder.CreateBr(m_jumpTableBlock->llvm()); - /* - // Generate switch for indirect jump. - auto dest = stack.pop(); - auto switchInstr = builder.CreateSwitch(dest, m_badJumpBlock->llvm(), - m_indirectJumpTargets.size()); - for (auto it = m_indirectJumpTargets.cbegin(); it != m_indirectJumpTargets.cend(); ++it) - { - auto& bb = *it; - auto dest = ConstantInt::get(Type::i256, bb->begin()); - switchInstr->addCase(dest, bb->llvm()); - } - */ break; } @@ -865,7 +866,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) } else { - builder.CreateRet(builder.getInt64(0)); + builder.CreateBr(m_badJumpBlock->llvm()); } linkBasicBlocks(); From deb0957087f8aa196cf4fb140b4e3f5c586f2067 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Mon, 13 Oct 2014 14:46:21 +0100 Subject: [PATCH 093/641] test cases for JUMP --- evmcc/test/jump/call1.ethel | 2 ++ evmcc/test/jump/call1.evm | 2 +- evmcc/test/jump/call2.ethel | 5 +++++ evmcc/test/jump/call2.evm | 1 + 4 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 evmcc/test/jump/call2.ethel create mode 100644 evmcc/test/jump/call2.evm diff --git a/evmcc/test/jump/call1.ethel b/evmcc/test/jump/call1.ethel index 206fb4c75..414ad0124 100644 --- a/evmcc/test/jump/call1.ethel +++ b/evmcc/test/jump/call1.ethel @@ -1,3 +1,5 @@ let f n = n + 1 return f 2 + + diff --git a/evmcc/test/jump/call1.evm b/evmcc/test/jump/call1.evm index 1f50b683f..252aaf778 100644 --- a/evmcc/test/jump/call1.evm +++ b/evmcc/test/jump/call1.evm @@ -1 +1 @@ -630000000d60026300000016585d60005460206000f280600101915058 \ No newline at end of file +600760026010585d60005460206000f28060010190509058 \ No newline at end of file diff --git a/evmcc/test/jump/call2.ethel b/evmcc/test/jump/call2.ethel new file mode 100644 index 000000000..bdeb9b734 --- /dev/null +++ b/evmcc/test/jump/call2.ethel @@ -0,0 +1,5 @@ +let f a b = a + b + +return f 2 3 + + diff --git a/evmcc/test/jump/call2.evm b/evmcc/test/jump/call2.evm new file mode 100644 index 000000000..6832e044d --- /dev/null +++ b/evmcc/test/jump/call2.evm @@ -0,0 +1 @@ +6009600260036012585d60005460206000f2818101905090509058 \ No newline at end of file From 3ec44144e5936cf0fd20c01569d65f7274fd360c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 13 Oct 2014 16:05:06 +0200 Subject: [PATCH 094/641] Change basic block linking order to get better results (still not perfect) --- evmcc/Compiler.cpp | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 1fc4ef6a1..4be6066e5 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -5,6 +5,8 @@ #include #include +#include +//#include #include @@ -901,36 +903,26 @@ void Compiler::linkBasicBlocks() auto phi = llvm::cast(instIt); for (auto predIt = llvm::pred_begin(_llbb); predIt != llvm::pred_end(_llbb); ++predIt) { + // TODO: In case entry block is reached - report error auto& predBB = findBasicBlock(*predIt); - // assert(valueIdx < predBB.getStack().size()); // TODO: Report error - phi->addIncoming(predBB.getStack().get(valueIdx), predBB); + auto value = predBB.getStack().get(valueIdx); + phi->addIncoming(value, predBB); } } }; - // Link basic blocks - for (auto&& p : basicBlocks) + + // TODO: It is crappy visiting of basic blocks. + llvm::SmallPtrSet visitSet; + for (auto&& bb : basicBlocks) // TODO: External loop is to visit unreable blocks that can also have phi nodes { - BasicBlock& bb = p.second; - completePhiNodes(bb.llvm()); - } - completePhiNodes(m_jumpTableBlock->llvm()); - /* - llvm::BasicBlock* llvmBB = bb.llvm(); - - size_t valueIdx = 0; - auto firstNonPhi = llvmBB->getFirstNonPHI(); - for (auto instIt = llvmBB->begin(); &*instIt != firstNonPhi; ++instIt, ++valueIdx) + for (auto it = llvm::po_ext_begin(bb.second.llvm(), visitSet), + end = llvm::po_ext_end(bb.second.llvm(), visitSet); it != end; ++it) { - auto phi = llvm::cast(instIt); - for (auto predIt = llvm::pred_begin(llvmBB); predIt != llvm::pred_end(llvmBB); ++predIt) - { - auto& predBB = findBasicBlock(*predIt); - assert(valueIdx < predBB.getStack().size()); // TODO: Report error - phi->addIncoming(predBB.getStack().get(valueIdx), predBB); - } + std::cerr << it->getName().str() << std::endl; + completePhiNodes(*it); } - */ + } } } From 1de697df99c5c67a4a1ea712a4d91d2b20538a1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 13 Oct 2014 16:32:52 +0200 Subject: [PATCH 095/641] Do not commit gas costs on JUMPDEST instruction [#80544260] --- evmcc/GasMeter.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index 7ba822e4a..906b4dcb0 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -51,24 +51,20 @@ uint64_t getStepCost(dev::eth::Instruction inst) // TODO: Add this function to F bool isCostBlockEnd(Instruction _inst) { + // Basic block terminators like STOP are not needed on the list + // as cost will be commited at the end of basic block switch (_inst) { - case Instruction::STOP: case Instruction::CALLDATACOPY: case Instruction::CODECOPY: case Instruction::MLOAD: case Instruction::MSTORE: case Instruction::MSTORE8: case Instruction::SSTORE: - case Instruction::JUMP: - case Instruction::JUMPI: - case Instruction::JUMPDEST: case Instruction::GAS: case Instruction::CREATE: case Instruction::CALL: case Instruction::CALLCODE: - case Instruction::RETURN: - case Instruction::SUICIDE: return true; default: From 0c708339e58051df7423a39a8250eaa5e7c0860e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 13 Oct 2014 16:33:51 +0200 Subject: [PATCH 096/641] Do not check gas cost of value 0 [Delivers #80544260] --- evmcc/GasMeter.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index 906b4dcb0..13d81b080 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -112,7 +112,11 @@ void GasMeter::commitCostBlock() // If any uncommited block if (m_checkCall) { - m_checkCall->setArgOperand(0, m_builder.getIntN(256, m_blockCost)); // Update block cost in gas check call + if (m_blockCost > 0) // If any cost + m_checkCall->setArgOperand(0, m_builder.getIntN(256, m_blockCost)); // Update block cost in gas check call + else + m_checkCall->eraseFromParent(); // Remove the gas check call + m_checkCall = nullptr; // End cost-block m_blockCost = 0; } From 86949720b1a2c7e0f0e08797217236d76d738369 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Mon, 13 Oct 2014 15:37:40 +0100 Subject: [PATCH 097/641] test cases for JUMPS/phi nodes --- evmcc/test/jump/loop1.evm | 1 + evmcc/test/jump/loop1.lll | 27 +++++++++++++++++++++++++++ evmcc/test/jump/loop2.evm | 1 + evmcc/test/jump/loop2.lll | 28 ++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+) create mode 100644 evmcc/test/jump/loop1.evm create mode 100644 evmcc/test/jump/loop1.lll create mode 100644 evmcc/test/jump/loop2.evm create mode 100644 evmcc/test/jump/loop2.lll diff --git a/evmcc/test/jump/loop1.evm b/evmcc/test/jump/loop1.evm new file mode 100644 index 000000000..b209951fa --- /dev/null +++ b/evmcc/test/jump/loop1.evm @@ -0,0 +1 @@ +600a600181038060025900 diff --git a/evmcc/test/jump/loop1.lll b/evmcc/test/jump/loop1.lll new file mode 100644 index 000000000..1d9483eb8 --- /dev/null +++ b/evmcc/test/jump/loop1.lll @@ -0,0 +1,27 @@ +;; Produces 1 2 3 4 5 6 7 8 9 10 on the stack and exits + +(asm +10 + +;; 2 +1 +DUP2 +SUB +DUP1 +2 +JUMPI + +;; stack = 1 2 3 4 5 6 7 8 9 10 +;;0 +;;MSTORE +;;1 +;;MSTORE +;;2 +;;MSTORE +;;3 +;;MSTORE + +STOP +) + + diff --git a/evmcc/test/jump/loop2.evm b/evmcc/test/jump/loop2.evm new file mode 100644 index 000000000..c95047707 --- /dev/null +++ b/evmcc/test/jump/loop2.evm @@ -0,0 +1 @@ +600a80600160800360a060025900 diff --git a/evmcc/test/jump/loop2.lll b/evmcc/test/jump/loop2.lll new file mode 100644 index 000000000..29d5e0ace --- /dev/null +++ b/evmcc/test/jump/loop2.lll @@ -0,0 +1,28 @@ +;; Produces 1 2 3 4 5 6 7 8 9 10 on the stack and exits + +(asm +10 + +;; 2 +DUP1 +1 +SWAP +SUB +DUP +2 +JUMPI + +;; stack = 1 2 3 4 5 6 7 8 9 10 +;;0 +;;MSTORE +;;1 +;;MSTORE +;;2 +;;MSTORE +;;3 +;;MSTORE + +STOP +) + + From b56a815d2cfbe447dc815f37002c4976b9a7c25d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 13 Oct 2014 17:39:27 +0200 Subject: [PATCH 098/641] Report error if static-analysed stack is too small --- evmcc/Compiler.cpp | 26 ++++++++++++++++++-------- evmcc/GasMeter.cpp | 2 +- evmcc/test/jump/loop1.evm | 2 +- evmcc/test/jump/loop1.lll | 12 ++++++------ evmcc/test/jump/loop2.evm | 2 +- evmcc/test/jump/loop2.lll | 16 ++++++++-------- 6 files changed, 35 insertions(+), 25 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 0fa2c5c03..2ee349a9e 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -882,17 +882,22 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) void Compiler::linkBasicBlocks() { /// Helper function that finds basic block given LLVM basic block pointer - auto findBasicBlock = [this](llvm::BasicBlock* _llbb) -> BasicBlock& + auto findBasicBlock = [this](llvm::BasicBlock* _llbb) -> BasicBlock* { // TODO: Fix for finding jumpTableBlock if (_llbb == this->m_jumpTableBlock->llvm()) - return *this->m_jumpTableBlock; + return this->m_jumpTableBlock.get(); + + for (auto&& bb : this->basicBlocks) + if (_llbb == bb.second.llvm()) + return &bb.second; + return nullptr; // Name is used to get basic block index (index of first instruction) // TODO: If basicBlocs are still a map - multikey map can be used - auto&& idxStr = _llbb->getName().substr(sizeof(BasicBlock::NamePrefix) - 2); - auto idx = std::stoul(idxStr); - return basicBlocks.find(idx)->second; + //auto&& idxStr = _llbb->getName().substr(sizeof(BasicBlock::NamePrefix) - 2); + //auto idx = std::stoul(idxStr); + //return basicBlocks.find(idx)->second; }; auto completePhiNodes = [findBasicBlock](llvm::BasicBlock* _llbb) -> void @@ -905,9 +910,14 @@ void Compiler::linkBasicBlocks() for (auto predIt = llvm::pred_begin(_llbb); predIt != llvm::pred_end(_llbb); ++predIt) { // TODO: In case entry block is reached - report error - auto& predBB = findBasicBlock(*predIt); - auto value = predBB.getStack().get(valueIdx); - phi->addIncoming(value, predBB); + auto predBB = findBasicBlock(*predIt); + if (!predBB) + { + std::cerr << "Stack too small in " << _llbb->getName().str() << std::endl; + std::exit(1); + } + auto value = predBB->getStack().get(valueIdx); + phi->addIncoming(value, predBB->llvm()); } } }; diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index 13d81b080..1f0465126 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -45,7 +45,7 @@ uint64_t getStepCost(dev::eth::Instruction inst) // TODO: Add this function to F return static_cast(c_createGas); default: // Assumes instruction code is valid - return static_cast(c_stepGas);; + return static_cast(c_stepGas); } } diff --git a/evmcc/test/jump/loop1.evm b/evmcc/test/jump/loop1.evm index b209951fa..7724d6308 100644 --- a/evmcc/test/jump/loop1.evm +++ b/evmcc/test/jump/loop1.evm @@ -1 +1 @@ -600a600181038060025900 +600a600181038060025960005460015460025400 diff --git a/evmcc/test/jump/loop1.lll b/evmcc/test/jump/loop1.lll index 1d9483eb8..0044ec1fb 100644 --- a/evmcc/test/jump/loop1.lll +++ b/evmcc/test/jump/loop1.lll @@ -12,12 +12,12 @@ DUP1 JUMPI ;; stack = 1 2 3 4 5 6 7 8 9 10 -;;0 -;;MSTORE -;;1 -;;MSTORE -;;2 -;;MSTORE +0 +MSTORE +1 +MSTORE +2 +MSTORE ;;3 ;;MSTORE diff --git a/evmcc/test/jump/loop2.evm b/evmcc/test/jump/loop2.evm index c95047707..faffa4e5b 100644 --- a/evmcc/test/jump/loop2.evm +++ b/evmcc/test/jump/loop2.evm @@ -1 +1 @@ -600a80600160800360a060025900 +600a80600190038060025960005460015460025400 diff --git a/evmcc/test/jump/loop2.lll b/evmcc/test/jump/loop2.lll index 29d5e0ace..9996c52ba 100644 --- a/evmcc/test/jump/loop2.lll +++ b/evmcc/test/jump/loop2.lll @@ -6,19 +6,19 @@ ;; 2 DUP1 1 -SWAP +SWAP1 SUB -DUP +DUP1 2 JUMPI ;; stack = 1 2 3 4 5 6 7 8 9 10 -;;0 -;;MSTORE -;;1 -;;MSTORE -;;2 -;;MSTORE +0 +MSTORE +1 +MSTORE +2 +MSTORE ;;3 ;;MSTORE From 6eb64ddcda93810a3c44f919049e3306deee2bf7 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Mon, 13 Oct 2014 16:57:13 +0100 Subject: [PATCH 099/641] Codegen for GAS --- evmcc/Compiler.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 0fa2c5c03..91758984d 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -659,6 +659,13 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::GAS: + { + auto value = builder.CreateLoad(gasMeter.getLLVMGasVar()); + stack.push(value); + break; + } + case Instruction::ADDRESS: { auto value = ext.address(); From 2031240485a4290345ad2828d84477767b0b1a68 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Mon, 13 Oct 2014 17:22:56 +0100 Subject: [PATCH 100/641] Implemented ADDMOD, MULMOD and GAS [Delivers #80566276] --- evmcc/Compiler.cpp | 30 ++++++++++++++++++++++++++++++ evmcc/GasMeter.cpp | 7 ++++++- evmcc/GasMeter.h | 2 ++ evmcc/test/arith/addmod.evm | 1 + evmcc/test/arith/addmod.lll | 12 ++++++++++++ evmcc/test/arith/mulmod.evm | 1 + evmcc/test/arith/mulmod.lll | 12 ++++++++++++ 7 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 evmcc/test/arith/addmod.evm create mode 100644 evmcc/test/arith/addmod.lll create mode 100644 evmcc/test/arith/mulmod.evm create mode 100644 evmcc/test/arith/mulmod.lll diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 91758984d..b5270d85a 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -434,6 +434,36 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::ADDMOD: + { + auto val1 = stack.pop(); + auto val2 = stack.pop(); + auto sum = builder.CreateAdd(val1, val2); + auto mod = stack.pop(); + + auto sum128 = builder.CreateTrunc(sum, Type::lowPrecision); + auto mod128 = builder.CreateTrunc(mod, Type::lowPrecision); + auto res128 = builder.CreateURem(sum128, mod128); + auto res256 = builder.CreateZExt(res128, Type::i256); + stack.push(res256); + break; + } + + case Instruction::MULMOD: + { + auto val1 = stack.pop(); + auto val2 = stack.pop(); + auto prod = builder.CreateMul(val1, val2); + auto mod = stack.pop(); + + auto prod128 = builder.CreateTrunc(prod, Type::lowPrecision); + auto mod128 = builder.CreateTrunc(mod, Type::lowPrecision); + auto res128 = builder.CreateURem(prod128, mod128); + auto res256 = builder.CreateZExt(res128, Type::i256); + stack.push(res256); + break; + } + case Instruction::SHA3: { auto inOff = stack.pop(); diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index 13d81b080..918be7bf7 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -130,4 +130,9 @@ void GasMeter::checkMemory(llvm::Value* _additionalMemoryInWords, llvm::IRBuilde _builder.CreateCall(m_gasCheckFunc, cost); } -} \ No newline at end of file +llvm::GlobalVariable* GasMeter::getLLVMGasVar() +{ + return m_gas; +} + +} diff --git a/evmcc/GasMeter.h b/evmcc/GasMeter.h index 1fcbe6459..c3ea9f84f 100644 --- a/evmcc/GasMeter.h +++ b/evmcc/GasMeter.h @@ -25,6 +25,8 @@ public: /// Generate code that checks the cost of additional memory used by program void checkMemory(llvm::Value* _additionalMemoryInWords, llvm::IRBuilder<>& _builder); + llvm::GlobalVariable* getLLVMGasVar(); + private: /// Cumulative gas cost of a block of instructions /// @TODO Handle overflow diff --git a/evmcc/test/arith/addmod.evm b/evmcc/test/arith/addmod.evm new file mode 100644 index 000000000..4ca71e065 --- /dev/null +++ b/evmcc/test/arith/addmod.evm @@ -0,0 +1 @@ +60646107b760271460005560006001f2 diff --git a/evmcc/test/arith/addmod.lll b/evmcc/test/arith/addmod.lll new file mode 100644 index 000000000..11a6b2cb9 --- /dev/null +++ b/evmcc/test/arith/addmod.lll @@ -0,0 +1,12 @@ +;; Should return (1975 + 39) `mod` 100 = 14 = 0x0e +(asm +100 +1975 +39 +ADDMOD +0 +MSTORE8 +0 +1 +RETURN +) \ No newline at end of file diff --git a/evmcc/test/arith/mulmod.evm b/evmcc/test/arith/mulmod.evm new file mode 100644 index 000000000..e34a06154 --- /dev/null +++ b/evmcc/test/arith/mulmod.evm @@ -0,0 +1 @@ +6064601b60251560005560006001f2 diff --git a/evmcc/test/arith/mulmod.lll b/evmcc/test/arith/mulmod.lll new file mode 100644 index 000000000..5e87f0843 --- /dev/null +++ b/evmcc/test/arith/mulmod.lll @@ -0,0 +1,12 @@ +;; Should return (27 * 37) `mod` 100 = 99 = 0x63 +(asm +100 +27 +37 +MULMOD +0 +MSTORE8 +0 +1 +RETURN +) \ No newline at end of file From 9c268561bd924484133129e561c26bb542172886 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 13 Oct 2014 18:43:33 +0200 Subject: [PATCH 101/641] Define constants and return codes --- evmcc/Type.cpp | 7 +++++++ evmcc/Type.h | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/evmcc/Type.cpp b/evmcc/Type.cpp index 0c8b6d92e..b71f12868 100644 --- a/evmcc/Type.cpp +++ b/evmcc/Type.cpp @@ -12,6 +12,7 @@ llvm::IntegerType* Type::lowPrecision; llvm::IntegerType* Type::Byte; llvm::PointerType* Type::BytePtr; llvm::Type* Type::Void; +llvm::Type* Type::MainReturn; void Type::init(llvm::LLVMContext& _context) { @@ -21,6 +22,12 @@ void Type::init(llvm::LLVMContext& _context) Byte = llvm::Type::getInt8Ty(_context); BytePtr = Byte->getPointerTo(); Void = llvm::Type::getVoidTy(_context); + MainReturn = llvm::Type::getInt32Ty(_context); +} + +llvm::Constant* Constant::get(ReturnCode _returnCode) +{ + return llvm::ConstantInt::get(Type::MainReturn, static_cast(_returnCode)); } } diff --git a/evmcc/Type.h b/evmcc/Type.h index fe4bce335..4b45a8453 100644 --- a/evmcc/Type.h +++ b/evmcc/Type.h @@ -2,6 +2,7 @@ #pragma once #include +#include namespace evmcc { @@ -20,7 +21,24 @@ struct Type static llvm::Type* Void; + /// Main function return type + static llvm::Type* MainReturn; + static void init(llvm::LLVMContext& _context); }; +enum class ReturnCode +{ + Stop = 0, + Return = 1, + Suicide = 2, + + BadJumpDestination = 101, +}; + +struct Constant +{ + static llvm::Constant* get(ReturnCode _returnCode); +}; + } From f9f08d3223cb8be4fac8b32092219b9b2dbf7492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 13 Oct 2014 18:44:06 +0200 Subject: [PATCH 102/641] Change the way compiled program returns --- evmcc/Compiler.cpp | 19 ++++-------- evmcc/ExecutionEngine.cpp | 10 +++--- evmcc/Memory.cpp | 64 ++++++++++++++++----------------------- evmcc/Memory.h | 9 ++++-- 4 files changed, 45 insertions(+), 57 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 2ee349a9e..8035a4fad 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -190,10 +190,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) IRBuilder<> builder(context); // Create main function - const auto i32Ty = builder.getInt32Ty(); - //Type* retTypeElems[] = {i32Ty, i32Ty}; - //auto retType = StructType::create(retTypeElems, "MemRef", true); - m_mainFunc = Function::Create(FunctionType::get(builder.getInt64Ty(), false), Function::ExternalLinkage, "main", module.get()); + m_mainFunc = Function::Create(FunctionType::get(Type::MainReturn, false), Function::ExternalLinkage, "main", module.get()); // Create the basic blocks. auto entryBlock = llvm::BasicBlock::Create(context, "entry", m_mainFunc); @@ -797,13 +794,9 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto index = stack.pop(); auto size = stack.pop(); - auto ret = builder.CreateTrunc(index, builder.getInt64Ty()); - ret = builder.CreateShl(ret, 32); - size = builder.CreateTrunc(size, i32Ty); - size = builder.CreateZExt(size, builder.getInt64Ty()); - ret = builder.CreateOr(ret, size); + memory.registerReturnData(index, size); - builder.CreateRet(ret); + builder.CreateRet(Constant::get(ReturnCode::Return)); break; } @@ -815,7 +808,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) } case Instruction::STOP: { - builder.CreateRet(builder.getInt64(0)); + builder.CreateRet(Constant::get(ReturnCode::Stop)); break; } @@ -847,11 +840,11 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) // Note: Right now the codegen for special blocks depends only on createBasicBlock(), // not on the codegen for 'regular' blocks. But it has to be done before linkBasicBlocks(). builder.SetInsertPoint(m_finalBlock->llvm()); - builder.CreateRet(builder.getInt64(0)); + builder.CreateRet(Constant::get(ReturnCode::Stop)); // TODO: throw an exception or something builder.SetInsertPoint(m_badJumpBlock->llvm()); - builder.CreateRet(builder.getInt64(0)); + builder.CreateRet(Constant::get(ReturnCode::BadJumpDestination)); builder.SetInsertPoint(m_jumpTableBlock->llvm()); if (m_indirectJumpTargets.size() > 0) diff --git a/evmcc/ExecutionEngine.cpp b/evmcc/ExecutionEngine.cpp index be45ff838..31c87d19b 100644 --- a/evmcc/ExecutionEngine.cpp +++ b/evmcc/ExecutionEngine.cpp @@ -14,6 +14,8 @@ #include #include "Runtime.h" +#include "Memory.h" +#include "Type.h" namespace evmcc { @@ -97,13 +99,13 @@ int ExecutionEngine::run(std::unique_ptr _module) auto result = exec->runFunction(entryFunc, {}); gas = static_cast(Runtime::getGas()); - if (auto intResult = result.IntVal.getZExtValue()) + auto returnCode = static_cast(result.IntVal.getZExtValue()); + if (returnCode == ReturnCode::Return) { - auto index = intResult >> 32; - auto size = 0xFFFFFFFF & intResult; + auto&& returnData = Memory::getReturnData(); std::cout << "RETURN [ "; - for (dev::bytes::const_iterator it = Runtime::getMemory().cbegin() + index, end = it + size; it != end; ++it) + for (auto it = returnData.begin(), end = returnData.end(); it != end; ++it) std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)*it << " "; std::cout << "]\n"; diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index 8625d7b5b..e585a9406 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -21,20 +21,8 @@ namespace evmcc Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module, GasMeter& _gasMeter): m_builder(_builder) { - auto voidTy = m_builder.getVoidTy(); auto i64Ty = m_builder.getInt64Ty(); - - auto memRequireTy = llvm::FunctionType::get(m_builder.getInt8PtrTy(), i64Ty, false); - m_memRequire = llvm::Function::Create(memRequireTy, - llvm::GlobalValue::LinkageTypes::ExternalLinkage, - "evmccrt_memory_require", _module); - - auto memSizeTy = llvm::FunctionType::get(i64Ty, false); - m_memSize = llvm::Function::Create(memSizeTy, - llvm::GlobalValue::LinkageTypes::ExternalLinkage, - "evmccrt_memory_size", _module); - - std::vector argTypes = {i64Ty, i64Ty}; + llvm::Type* argTypes[] = {i64Ty, i64Ty}; auto dumpTy = llvm::FunctionType::get(m_builder.getVoidTy(), llvm::ArrayRef(argTypes), false); m_memDump = llvm::Function::Create(dumpTy, llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_memory_dump", _module); @@ -45,6 +33,12 @@ Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module, GasMeter& _ga m_size = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::PrivateLinkage, m_builder.getIntN(256, 0), "mem.size"); m_size->setUnnamedAddr(true); // Address is not important + m_returnDataOffset = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "mem_returnDataOffset"); + m_returnDataOffset->setUnnamedAddr(true); // Address is not important + + m_returnDataSize = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "mem_returnDataSize"); + m_returnDataSize->setUnnamedAddr(true); // Address is not important + m_resize = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, Type::WordPtr, false), llvm::Function::ExternalLinkage, "mem_resize", _module); m_loadWord = createFunc(false, Type::i256, _module, _gasMeter); m_storeWord = createFunc(true, Type::i256, _module, _gasMeter); @@ -137,6 +131,12 @@ llvm::Value* Memory::getSize() return m_builder.CreateLoad(m_size); } +void Memory::registerReturnData(llvm::Value* _index, llvm::Value* _size) +{ + m_builder.CreateStore(_index, m_returnDataOffset); + m_builder.CreateStore(_size, m_returnDataSize); +} + void Memory::dump(uint64_t _begin, uint64_t _end) { if (getenv("EVMCC_DEBUG_MEMORY") == nullptr) @@ -155,6 +155,9 @@ extern "C" { using namespace evmcc; +EXPORT i256 mem_returnDataOffset; +EXPORT i256 mem_returnDataSize; + EXPORT uint8_t* mem_resize(i256* _size) { auto size = _size->a; // Trunc to 64-bit @@ -163,37 +166,13 @@ EXPORT uint8_t* mem_resize(i256* _size) return memory.data(); } -// Resizes memory to contain at least _index + 1 bytes and returns the base address. -EXPORT uint8_t* evmccrt_memory_require(uint64_t _index) -{ - uint64_t requiredSize = (_index / 32 + 1) * 32; - auto&& memory = Runtime::getMemory(); - - if (memory.size() < requiredSize) - { - std::cerr << "MEMORY: current size: " << std::dec - << memory.size() << " bytes, required size: " - << requiredSize << " bytes" - << std::endl; - - memory.resize(requiredSize); - } - - return memory.data(); -} - -EXPORT uint64_t evmccrt_memory_size() -{ - return Runtime::getMemory().size() / 32; -} - EXPORT void evmccrt_memory_dump(uint64_t _begin, uint64_t _end) { if (_end == 0) _end = Runtime::getMemory().size(); std::cerr << "MEMORY: active size: " << std::dec - << evmccrt_memory_size() << " words\n"; + << Runtime::getMemory().size() / 32 << " words\n"; std::cerr << "MEMORY: dump from " << std::dec << _begin << " to " << _end << ":"; if (_end <= _begin) @@ -212,3 +191,12 @@ EXPORT void evmccrt_memory_dump(uint64_t _begin, uint64_t _end) } } // extern "C" + +dev::bytesConstRef evmcc::Memory::getReturnData() +{ + // TODO: Handle large indexes + auto offset = static_cast(llvm2eth(mem_returnDataOffset)); + auto size = static_cast(llvm2eth(mem_returnDataSize)); + auto& memory = Runtime::getMemory(); + return {memory.data() + offset, size}; +} diff --git a/evmcc/Memory.h b/evmcc/Memory.h index ed7273c5c..c01bd6ef8 100644 --- a/evmcc/Memory.h +++ b/evmcc/Memory.h @@ -20,6 +20,9 @@ public: void storeByte(llvm::Value* _addr, llvm::Value* _byte); llvm::Value* getSize(); + void registerReturnData(llvm::Value* _index, llvm::Value* _size); + static dev::bytesConstRef getReturnData(); + void dump(uint64_t _begin, uint64_t _end = 0); private: @@ -31,14 +34,16 @@ private: llvm::GlobalVariable* m_data; llvm::GlobalVariable* m_size; + /// @TODO: m_data and m_size could be used + llvm::GlobalVariable* m_returnDataOffset; + llvm::GlobalVariable* m_returnDataSize; + llvm::Function* m_loadWord; llvm::Function* m_storeWord; llvm::Function* m_storeByte; llvm::Function* m_resize; - llvm::Function* m_memRequire; llvm::Function* m_memDump; - llvm::Function* m_memSize; }; } From 16023daf0b402094780185088a2467dbaad90c9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 13 Oct 2014 19:09:42 +0200 Subject: [PATCH 103/641] Allocate memory and count gas for RETURN instruction [#79942174] --- evmcc/ExecutionEngine.cpp | 2 +- evmcc/Memory.cpp | 3 +++ evmcc/Type.cpp | 5 +++++ evmcc/Type.h | 3 +++ evmcc/bytecode/return2.evm | 1 + evmcc/lll/return2.lll | 6 ++++++ 6 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 evmcc/bytecode/return2.evm create mode 100644 evmcc/lll/return2.lll diff --git a/evmcc/ExecutionEngine.cpp b/evmcc/ExecutionEngine.cpp index 31c87d19b..0e6df0b24 100644 --- a/evmcc/ExecutionEngine.cpp +++ b/evmcc/ExecutionEngine.cpp @@ -102,7 +102,7 @@ int ExecutionEngine::run(std::unique_ptr _module) auto returnCode = static_cast(result.IntVal.getZExtValue()); if (returnCode == ReturnCode::Return) { - auto&& returnData = Memory::getReturnData(); + auto&& returnData = Memory::getReturnData(); // TODO: It might be better to place is in Runtime interface std::cout << "RETURN [ "; for (auto it = returnData.begin(), end = returnData.end(); it != end; ++it) diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index e585a9406..f6eafb389 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -133,6 +133,9 @@ llvm::Value* Memory::getSize() void Memory::registerReturnData(llvm::Value* _index, llvm::Value* _size) { + auto lastWord = m_builder.CreateAdd(_index, m_builder.CreateSub(_size, Constant::get(32)), "lastWord"); + loadWord(lastWord); // Make sure that memory is allocated and count gas + m_builder.CreateStore(_index, m_returnDataOffset); m_builder.CreateStore(_size, m_returnDataSize); } diff --git a/evmcc/Type.cpp b/evmcc/Type.cpp index b71f12868..4837829b4 100644 --- a/evmcc/Type.cpp +++ b/evmcc/Type.cpp @@ -25,6 +25,11 @@ void Type::init(llvm::LLVMContext& _context) MainReturn = llvm::Type::getInt32Ty(_context); } +llvm::Constant* Constant::get(uint64_t _n) +{ + return llvm::ConstantInt::get(Type::i256, _n); +} + llvm::Constant* Constant::get(ReturnCode _returnCode) { return llvm::ConstantInt::get(Type::MainReturn, static_cast(_returnCode)); diff --git a/evmcc/Type.h b/evmcc/Type.h index 4b45a8453..a8501d897 100644 --- a/evmcc/Type.h +++ b/evmcc/Type.h @@ -38,6 +38,9 @@ enum class ReturnCode struct Constant { + /// Returns word-size constant + static llvm::Constant* get(uint64_t _n); + static llvm::Constant* get(ReturnCode _returnCode); }; diff --git a/evmcc/bytecode/return2.evm b/evmcc/bytecode/return2.evm new file mode 100644 index 000000000..e29da7664 --- /dev/null +++ b/evmcc/bytecode/return2.evm @@ -0,0 +1 @@ +6001620f4240f2 diff --git a/evmcc/lll/return2.lll b/evmcc/lll/return2.lll new file mode 100644 index 000000000..f5ee68f6e --- /dev/null +++ b/evmcc/lll/return2.lll @@ -0,0 +1,6 @@ + +(asm +1 +1000000 +RETURN ;; return 1 byte from index 1M +) \ No newline at end of file From 05952064dc6e8d55bc67af7f7cfa9a47f47f30d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 13 Oct 2014 19:14:33 +0200 Subject: [PATCH 104/641] Use Constant::get() interface to create LLVM constants --- evmcc/Compiler.cpp | 12 ++++++------ evmcc/GasMeter.cpp | 4 ++-- evmcc/Memory.cpp | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 8035a4fad..fd295d891 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -420,12 +420,12 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) // TODO: Shifting by 0 gives wrong results as of this bug http://llvm.org/bugs/show_bug.cgi?id=16439 - auto shbits = builder.CreateShl(byteNum, builder.getIntN(256, 3)); + auto shbits = builder.CreateShl(byteNum, Constant::get(3)); value = builder.CreateShl(value, shbits); - value = builder.CreateLShr(value, builder.getIntN(256, 31 * 8)); + value = builder.CreateLShr(value, Constant::get(31 * 8)); - auto byteNumValid = builder.CreateICmpULT(byteNum, builder.getIntN(256, 32)); - value = builder.CreateSelect(byteNumValid, value, builder.getIntN(256, 0)); + auto byteNumValid = builder.CreateICmpULT(byteNum, Constant::get(32)); + value = builder.CreateSelect(byteNumValid, value, Constant::get(0)); stack.push(value); break; @@ -651,7 +651,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) case Instruction::PC: { - auto value = builder.getIntN(256, currentPC); + auto value = Constant::get(currentPC); stack.push(value); break; } @@ -716,7 +716,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) case Instruction::CODESIZE: { - auto value = builder.getIntN(256, bytecode.size()); + auto value = Constant::get(bytecode.size()); stack.push(value); break; } diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index 1f0465126..cd88df646 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -113,7 +113,7 @@ void GasMeter::commitCostBlock() if (m_checkCall) { if (m_blockCost > 0) // If any cost - m_checkCall->setArgOperand(0, m_builder.getIntN(256, m_blockCost)); // Update block cost in gas check call + m_checkCall->setArgOperand(0, Constant::get(m_blockCost)); // Update block cost in gas check call else m_checkCall->eraseFromParent(); // Remove the gas check call @@ -126,7 +126,7 @@ void GasMeter::commitCostBlock() void GasMeter::checkMemory(llvm::Value* _additionalMemoryInWords, llvm::IRBuilder<>& _builder) { // Memory uses other builder, but that can be changes later - auto cost = _builder.CreateMul(_additionalMemoryInWords, _builder.getIntN(256, static_cast(c_memoryGas)), "memcost"); + auto cost = _builder.CreateMul(_additionalMemoryInWords, Constant::get(static_cast(c_memoryGas)), "memcost"); _builder.CreateCall(m_gasCheckFunc, cost); } diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index f6eafb389..4d4a34928 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -30,7 +30,7 @@ Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module, GasMeter& _ga m_data = new llvm::GlobalVariable(*_module, Type::BytePtr, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::BytePtr), "mem.data"); m_data->setUnnamedAddr(true); // Address is not important - m_size = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::PrivateLinkage, m_builder.getIntN(256, 0), "mem.size"); + m_size = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::PrivateLinkage, Constant::get(0), "mem.size"); m_size->setUnnamedAddr(true); // Address is not important m_returnDataOffset = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "mem_returnDataOffset"); @@ -63,7 +63,7 @@ llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, llvm:: llvm::Value* index = func->arg_begin(); index->setName("index"); auto valueSize = _valueType->getPrimitiveSizeInBits() / 8; - auto sizeRequired = builder.CreateAdd(index, builder.getIntN(256, valueSize), "sizeRequired"); + auto sizeRequired = builder.CreateAdd(index, Constant::get(valueSize), "sizeRequired"); auto size = builder.CreateLoad(m_size, "size"); auto resizeNeeded = builder.CreateICmpULE(size, sizeRequired, "resizeNeeded"); builder.CreateCondBr(resizeNeeded, resizeBB, accessBB); // OPT branch weights? @@ -71,8 +71,8 @@ llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, llvm:: // BB "resize" builder.SetInsertPoint(resizeBB); // Check gas first - auto wordsRequired = builder.CreateUDiv(builder.CreateAdd(sizeRequired, builder.getIntN(256, 31)), builder.getIntN(256, 32), "wordsRequired"); - auto words = builder.CreateUDiv(builder.CreateAdd(size, builder.getIntN(256, 31)), builder.getIntN(256, 32), "words"); + auto wordsRequired = builder.CreateUDiv(builder.CreateAdd(sizeRequired, Constant::get(31)), Constant::get(32), "wordsRequired"); + auto words = builder.CreateUDiv(builder.CreateAdd(size, Constant::get(31)), Constant::get(32), "words"); auto newWords = builder.CreateSub(wordsRequired, words, "addtionalWords"); _gasMeter.checkMemory(newWords, builder); // Resize From a5c239ffc9bf90aad71795cce10ba8ca570a56d6 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Tue, 14 Oct 2014 09:24:33 +0100 Subject: [PATCH 105/641] Fixes in inline asm in some jump tests. --- evmcc/test/jump/loop1.evm | 2 +- evmcc/test/jump/loop1.lll | 16 ++++++++-------- evmcc/test/jump/loop2.evm | 2 +- evmcc/test/jump/loop2.lll | 22 +++++++++++----------- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/evmcc/test/jump/loop1.evm b/evmcc/test/jump/loop1.evm index b209951fa..e7cbc4aa9 100644 --- a/evmcc/test/jump/loop1.evm +++ b/evmcc/test/jump/loop1.evm @@ -1 +1 @@ -600a600181038060025900 +600a600181038060025960005460015460025460035400 diff --git a/evmcc/test/jump/loop1.lll b/evmcc/test/jump/loop1.lll index 1d9483eb8..8ce24e4cd 100644 --- a/evmcc/test/jump/loop1.lll +++ b/evmcc/test/jump/loop1.lll @@ -12,14 +12,14 @@ DUP1 JUMPI ;; stack = 1 2 3 4 5 6 7 8 9 10 -;;0 -;;MSTORE -;;1 -;;MSTORE -;;2 -;;MSTORE -;;3 -;;MSTORE +0 +MSTORE +1 +MSTORE +2 +MSTORE +3 +MSTORE STOP ) diff --git a/evmcc/test/jump/loop2.evm b/evmcc/test/jump/loop2.evm index c95047707..6a55228a8 100644 --- a/evmcc/test/jump/loop2.evm +++ b/evmcc/test/jump/loop2.evm @@ -1 +1 @@ -600a80600160800360a060025900 +600a80600190038060025960005460015460025460035400 diff --git a/evmcc/test/jump/loop2.lll b/evmcc/test/jump/loop2.lll index 29d5e0ace..b53e6713d 100644 --- a/evmcc/test/jump/loop2.lll +++ b/evmcc/test/jump/loop2.lll @@ -5,22 +5,22 @@ ;; 2 DUP1 -1 -SWAP +1 +SWAP1 SUB -DUP +DUP1 2 JUMPI ;; stack = 1 2 3 4 5 6 7 8 9 10 -;;0 -;;MSTORE -;;1 -;;MSTORE -;;2 -;;MSTORE -;;3 -;;MSTORE +0 +MSTORE +1 +MSTORE +2 +MSTORE +3 +MSTORE STOP ) From c5c76cdf99987c84d5d0f8a689bfc72969cde090 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 14 Oct 2014 13:27:45 +0200 Subject: [PATCH 106/641] Count gas for CALL instructions [#79942174] --- evmcc/Compiler.cpp | 1 + evmcc/GasMeter.cpp | 23 ++++++++++++++++------- evmcc/GasMeter.h | 5 +++-- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index fd295d891..c48036d62 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -784,6 +784,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto outOff = stack.pop(); auto outSize = stack.pop(); + gasMeter.commitCostBlock(gas); auto ret = ext.call(gas, receiveAddress, value, inOff, inSize, outOff, outSize); stack.push(ret); break; diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index cd88df646..6295ffe79 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -53,6 +53,9 @@ bool isCostBlockEnd(Instruction _inst) { // Basic block terminators like STOP are not needed on the list // as cost will be commited at the end of basic block + + // CALL & CALLCODE are commited manually + switch (_inst) { case Instruction::CALLDATACOPY: @@ -63,8 +66,6 @@ bool isCostBlockEnd(Instruction _inst) case Instruction::SSTORE: case Instruction::GAS: case Instruction::CREATE: - case Instruction::CALL: - case Instruction::CALLCODE: return true; default: @@ -107,16 +108,24 @@ void GasMeter::count(Instruction _inst) commitCostBlock(); } -void GasMeter::commitCostBlock() +void GasMeter::commitCostBlock(llvm::Value* _additionalCost) { + assert(!_additionalCost || m_checkCall); // _additionalCost => m_checkCall; Must be inside cost-block + // If any uncommited block if (m_checkCall) { - if (m_blockCost > 0) // If any cost - m_checkCall->setArgOperand(0, Constant::get(m_blockCost)); // Update block cost in gas check call - else + if (m_blockCost == 0 && !_additionalCost) // Do not check 0 + { m_checkCall->eraseFromParent(); // Remove the gas check call - + return; + } + + llvm::Value* cost = Constant::get(m_blockCost); + if (_additionalCost) + cost = m_builder.CreateAdd(cost, _additionalCost); + + m_checkCall->setArgOperand(0, cost); // Update block cost in gas check call m_checkCall = nullptr; // End cost-block m_blockCost = 0; } diff --git a/evmcc/GasMeter.h b/evmcc/GasMeter.h index 1fcbe6459..3a1f7ba66 100644 --- a/evmcc/GasMeter.h +++ b/evmcc/GasMeter.h @@ -19,8 +19,9 @@ public: /// Count step cost of instruction void count(dev::eth::Instruction _inst); - /// Finalize cost block by checking gas needed for the block before the block - void commitCostBlock(); + /// Finalize cost-block by checking gas needed for the block before the block + /// @param _additionalCost adds additional cost to cost-block before commit + void commitCostBlock(llvm::Value* _additionalCost = nullptr); /// Generate code that checks the cost of additional memory used by program void checkMemory(llvm::Value* _additionalMemoryInWords, llvm::IRBuilder<>& _builder); From 2999de9f1a2bb6a598bd44ad1a8aeffa2345f45b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 14 Oct 2014 14:29:19 +0200 Subject: [PATCH 107/641] Give back an amount of gas not used by CALL instructions [#79942174] --- evmcc/Compiler.cpp | 1 + evmcc/Ext.cpp | 7 ++++--- evmcc/Ext.h | 2 +- evmcc/GasMeter.cpp | 7 +++++++ evmcc/GasMeter.h | 3 +++ 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index c48036d62..37a4d89a1 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -786,6 +786,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) gasMeter.commitCostBlock(gas); auto ret = ext.call(gas, receiveAddress, value, inOff, inSize, outOff, outSize); + gasMeter.giveBack(gas); stack.push(ret); break; } diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index 1d309947d..878f187f1 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -165,7 +165,7 @@ Value* Ext::create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* return address; } -llvm::Value* Ext::call(llvm::Value* _gas, llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize) +llvm::Value* Ext::call(llvm::Value*& _gas, llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize) { m_builder.CreateStore(_gas, m_args[0]); auto receiveAddress = bswap(_receiveAddress); // to BE @@ -177,6 +177,7 @@ llvm::Value* Ext::call(llvm::Value* _gas, llvm::Value* _receiveAddress, llvm::Va m_builder.CreateStore(_outSize, m_arg7); llvm::Value* args[] = {m_args[0], m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_args[1]}; m_builder.CreateCall(m_call, args); + _gas = m_builder.CreateLoad(m_args[0]); // Return gas return m_builder.CreateLoad(m_args[1]); } @@ -284,10 +285,10 @@ EXPORT void ext_call(i256* _gas, h256* _receiveAddress, i256* _value, i256* _inO auto value = llvm2eth(*_value); auto ret = false; + auto gas = llvm2eth(*_gas); if (ext.balance(ext.myAddress) >= value) { ext.subBalance(value); - auto gas = llvm2eth(*_gas); auto receiveAddress = dev::right160(*_receiveAddress); auto inOff = static_cast(llvm2eth(*_inOff)); auto inSize = static_cast(llvm2eth(*_inSize)); @@ -299,7 +300,7 @@ EXPORT void ext_call(i256* _gas, h256* _receiveAddress, i256* _value, i256* _inO auto ret = ext.call(receiveAddress, value, inRef, &gas, outRef, onOp, {}, receiveAddress); } - // m_gas += gas; // TODO: Handle gas + *_gas = eth2llvm(gas); _ret->a = ret ? 1 : 0; } diff --git a/evmcc/Ext.h b/evmcc/Ext.h index 302991854..778c6d941 100644 --- a/evmcc/Ext.h +++ b/evmcc/Ext.h @@ -36,7 +36,7 @@ public: void suicide(llvm::Value* _address); llvm::Value* calldataload(llvm::Value* _index); llvm::Value* create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize); - llvm::Value* call(llvm::Value* _gas, llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize); + llvm::Value* call(llvm::Value*& _gas, llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize); llvm::Value* sha3(llvm::Value* _inOff, llvm::Value* _inSize); llvm::Value* exp(llvm::Value* _left, llvm::Value* _right); diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index 6295ffe79..d10833ca4 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -108,6 +108,13 @@ void GasMeter::count(Instruction _inst) commitCostBlock(); } +void GasMeter::giveBack(llvm::Value* _gas) +{ + llvm::Value* gasCounter = m_builder.CreateLoad(m_gas, "gas"); + gasCounter = m_builder.CreateAdd(gasCounter, _gas); + m_builder.CreateStore(gasCounter, m_gas); +} + void GasMeter::commitCostBlock(llvm::Value* _additionalCost) { assert(!_additionalCost || m_checkCall); // _additionalCost => m_checkCall; Must be inside cost-block diff --git a/evmcc/GasMeter.h b/evmcc/GasMeter.h index 3a1f7ba66..46fa3522a 100644 --- a/evmcc/GasMeter.h +++ b/evmcc/GasMeter.h @@ -23,6 +23,9 @@ public: /// @param _additionalCost adds additional cost to cost-block before commit void commitCostBlock(llvm::Value* _additionalCost = nullptr); + /// Give back an amount of gas not used by a call + void giveBack(llvm::Value* _gas); + /// Generate code that checks the cost of additional memory used by program void checkMemory(llvm::Value* _additionalMemoryInWords, llvm::IRBuilder<>& _builder); From f0f5833c4ca42ba907f5b9cd86d68a66d2225bfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 14 Oct 2014 15:12:11 +0200 Subject: [PATCH 108/641] Private mem.require function that preallocates memory and counts gas fee --- evmcc/Memory.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++++-- evmcc/Memory.h | 4 ++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index 4d4a34928..cbc349250 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -43,6 +43,43 @@ Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module, GasMeter& _ga m_loadWord = createFunc(false, Type::i256, _module, _gasMeter); m_storeWord = createFunc(true, Type::i256, _module, _gasMeter); m_storeByte = createFunc(true, Type::Byte, _module, _gasMeter); + + m_require = createRequireFunc(_module, _gasMeter); +} + +llvm::Function* Memory::createRequireFunc(llvm::Module* _module, GasMeter& _gasMeter) +{ + auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "mem.require", _module); + + auto checkBB = llvm::BasicBlock::Create(func->getContext(), "check", func); + auto resizeBB = llvm::BasicBlock::Create(func->getContext(), "resize", func); + auto returnBB = llvm::BasicBlock::Create(func->getContext(), "return", func); + + // BB "check" + llvm::IRBuilder<> builder(checkBB); + llvm::Value* sizeRequired = func->arg_begin(); + sizeRequired->setName("sizeRequired"); + auto size = builder.CreateLoad(m_size, "size"); + auto resizeNeeded = builder.CreateICmpULE(size, sizeRequired, "resizeNeeded"); + builder.CreateCondBr(resizeNeeded, resizeBB, returnBB); // OPT branch weights? + + // BB "resize" + builder.SetInsertPoint(resizeBB); + // Check gas first + auto wordsRequired = builder.CreateUDiv(builder.CreateAdd(sizeRequired, Constant::get(31)), Constant::get(32), "wordsRequired"); + auto words = builder.CreateUDiv(builder.CreateAdd(size, Constant::get(31)), Constant::get(32), "words"); + auto newWords = builder.CreateSub(wordsRequired, words, "addtionalWords"); + _gasMeter.checkMemory(newWords, builder); + // Resize + builder.CreateStore(sizeRequired, m_size); + auto newData = builder.CreateCall(m_resize, m_size, "newData"); + builder.CreateStore(newData, m_data); + builder.CreateBr(returnBB); + + // BB "return" + builder.SetInsertPoint(returnBB); + builder.CreateRetVoid(); + return func; } llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, llvm::Module* _module, GasMeter& _gasMeter) @@ -131,10 +168,15 @@ llvm::Value* Memory::getSize() return m_builder.CreateLoad(m_size); } +void Memory::require(llvm::Value* _size) +{ + m_builder.CreateCall(m_require, _size); +} + void Memory::registerReturnData(llvm::Value* _index, llvm::Value* _size) { - auto lastWord = m_builder.CreateAdd(_index, m_builder.CreateSub(_size, Constant::get(32)), "lastWord"); - loadWord(lastWord); // Make sure that memory is allocated and count gas + auto sizeRequired = m_builder.CreateAdd(_index, _size, "sizeRequired"); + require(sizeRequired); // Make sure that memory is allocated and count gas m_builder.CreateStore(_index, m_returnDataOffset); m_builder.CreateStore(_size, m_returnDataSize); diff --git a/evmcc/Memory.h b/evmcc/Memory.h index c01bd6ef8..e973d1016 100644 --- a/evmcc/Memory.h +++ b/evmcc/Memory.h @@ -20,6 +20,8 @@ public: void storeByte(llvm::Value* _addr, llvm::Value* _byte); llvm::Value* getSize(); + void require(llvm::Value* _size); + void registerReturnData(llvm::Value* _index, llvm::Value* _size); static dev::bytesConstRef getReturnData(); @@ -27,6 +29,7 @@ public: private: llvm::Function* createFunc(bool _isStore, llvm::Type* _type, llvm::Module* _module, GasMeter& _gasMeter); + llvm::Function* createRequireFunc(llvm::Module* _module, GasMeter& _gasMeter); private: llvm::IRBuilder<>& m_builder; @@ -41,6 +44,7 @@ private: llvm::Function* m_loadWord; llvm::Function* m_storeWord; llvm::Function* m_storeByte; + llvm::Function* m_require; llvm::Function* m_resize; llvm::Function* m_memDump; From 59000cd85d0688c107b4d5fe4a39efadb058bfbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 14 Oct 2014 15:19:27 +0200 Subject: [PATCH 109/641] Convenient Memory::require() overload --- evmcc/Memory.cpp | 11 ++++++++--- evmcc/Memory.h | 4 ++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index cbc349250..66a18e43f 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -173,10 +173,15 @@ void Memory::require(llvm::Value* _size) m_builder.CreateCall(m_require, _size); } -void Memory::registerReturnData(llvm::Value* _index, llvm::Value* _size) +void Memory::require(llvm::Value* _offset, llvm::Value* _size) { - auto sizeRequired = m_builder.CreateAdd(_index, _size, "sizeRequired"); - require(sizeRequired); // Make sure that memory is allocated and count gas + auto sizeRequired = m_builder.CreateAdd(_offset, _size, "sizeRequired"); + require(sizeRequired); +} + +void Memory::registerReturnData(llvm::Value* _index, llvm::Value* _size) +{ + require(_index, _size); // Make sure that memory is allocated and count gas m_builder.CreateStore(_index, m_returnDataOffset); m_builder.CreateStore(_size, m_returnDataSize); diff --git a/evmcc/Memory.h b/evmcc/Memory.h index e973d1016..8ea9bf082 100644 --- a/evmcc/Memory.h +++ b/evmcc/Memory.h @@ -20,8 +20,12 @@ public: void storeByte(llvm::Value* _addr, llvm::Value* _byte); llvm::Value* getSize(); + /// Requires this amount of memory. And counts gas fee for that memory. void require(llvm::Value* _size); + /// Requires the amount of memory to for data defined by offset and size. And counts gas fee for that memory. + void require(llvm::Value* _offset, llvm::Value* _size); + void registerReturnData(llvm::Value* _index, llvm::Value* _size); static dev::bytesConstRef getReturnData(); From 07882137e3a5893272519979e151bea9c2bad1ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 14 Oct 2014 15:48:27 +0200 Subject: [PATCH 110/641] Use mem.require in mload, mstore & mstore8 --- evmcc/Memory.cpp | 50 ++++++++++++++++-------------------------------- 1 file changed, 16 insertions(+), 34 deletions(-) diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index 66a18e43f..8f4809062 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -40,11 +40,10 @@ Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module, GasMeter& _ga m_returnDataSize->setUnnamedAddr(true); // Address is not important m_resize = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, Type::WordPtr, false), llvm::Function::ExternalLinkage, "mem_resize", _module); + m_require = createRequireFunc(_module, _gasMeter); m_loadWord = createFunc(false, Type::i256, _module, _gasMeter); m_storeWord = createFunc(true, Type::i256, _module, _gasMeter); m_storeByte = createFunc(true, Type::Byte, _module, _gasMeter); - - m_require = createRequireFunc(_module, _gasMeter); } llvm::Function* Memory::createRequireFunc(llvm::Module* _module, GasMeter& _gasMeter) @@ -91,51 +90,34 @@ llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, llvm:: auto funcType = _isStore ? llvm::FunctionType::get(Type::Void, storeArgs, false) : llvm::FunctionType::get(Type::i256, Type::i256, false); auto func = llvm::Function::Create(funcType, llvm::Function::PrivateLinkage, name, _module); - auto checkBB = llvm::BasicBlock::Create(func->getContext(), "check", func); - auto resizeBB = llvm::BasicBlock::Create(func->getContext(), "resize", func); - auto accessBB = llvm::BasicBlock::Create(func->getContext(), "access", func); + auto origBB = m_builder.GetInsertBlock(); + auto origPt = m_builder.GetInsertPoint(); - // BB "check" - llvm::IRBuilder<> builder(checkBB); + m_builder.SetInsertPoint(llvm::BasicBlock::Create(func->getContext(), {}, func)); llvm::Value* index = func->arg_begin(); index->setName("index"); + auto valueSize = _valueType->getPrimitiveSizeInBits() / 8; - auto sizeRequired = builder.CreateAdd(index, Constant::get(valueSize), "sizeRequired"); - auto size = builder.CreateLoad(m_size, "size"); - auto resizeNeeded = builder.CreateICmpULE(size, sizeRequired, "resizeNeeded"); - builder.CreateCondBr(resizeNeeded, resizeBB, accessBB); // OPT branch weights? - - // BB "resize" - builder.SetInsertPoint(resizeBB); - // Check gas first - auto wordsRequired = builder.CreateUDiv(builder.CreateAdd(sizeRequired, Constant::get(31)), Constant::get(32), "wordsRequired"); - auto words = builder.CreateUDiv(builder.CreateAdd(size, Constant::get(31)), Constant::get(32), "words"); - auto newWords = builder.CreateSub(wordsRequired, words, "addtionalWords"); - _gasMeter.checkMemory(newWords, builder); - // Resize - builder.CreateStore(sizeRequired, m_size); - auto newData = builder.CreateCall(m_resize, m_size, "newData"); - builder.CreateStore(newData, m_data); - builder.CreateBr(accessBB); - - // BB "access" - builder.SetInsertPoint(accessBB); - auto data = builder.CreateLoad(m_data, "data"); - auto ptr = builder.CreateGEP(data, index, "ptr"); + this->require(index, Constant::get(valueSize)); + auto data = m_builder.CreateLoad(m_data, "data"); + auto ptr = m_builder.CreateGEP(data, index, "ptr"); if (isWord) - ptr = builder.CreateBitCast(ptr, Type::WordPtr, "wordPtr"); + ptr = m_builder.CreateBitCast(ptr, Type::WordPtr, "wordPtr"); if (_isStore) { llvm::Value* value = ++func->arg_begin(); value->setName("value"); - builder.CreateStore(value, ptr); - builder.CreateRetVoid(); + m_builder.CreateStore(value, ptr); + m_builder.CreateRetVoid(); } else { - auto ret = builder.CreateLoad(ptr); - builder.CreateRet(ret); + auto ret = m_builder.CreateLoad(ptr); + m_builder.CreateRet(ret); } + + m_builder.SetInsertPoint(origBB, origPt); + return func; } From d005896a0b5c33623abad685dca19c8f2768048f Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Tue, 14 Oct 2014 14:52:15 +0100 Subject: [PATCH 111/641] Initial implementation for CALLDATACOPY [Delivers #80644732] --- evmcc/Compiler.cpp | 30 ++++++++++++++++++++++++++++++ evmcc/Ext.cpp | 6 +++--- evmcc/Ext.h | 1 + evmcc/Memory.cpp | 5 +++++ evmcc/Memory.h | 1 + 5 files changed, 40 insertions(+), 3 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 5857040f8..47cbbf5c1 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -736,6 +736,36 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::CALLDATACOPY: + { + auto zero256 = ConstantInt::get(Type::i256, 0); + + auto destMemIdx = stack.pop(); + auto srcDataIdx = stack.pop(); + auto reqByteCount = stack.pop(); + + // FIXME: ensure memory size reqMemSize. + auto reqMemSize = builder.CreateAdd(destMemIdx, reqByteCount); + auto reqMemWord = builder.CreateSub(reqMemSize, ConstantInt::get(Type::i256, 32)); + memory.loadWord(reqMemWord); + + auto memPtr = memory.getData(); + auto destPtr = builder.CreateGEP(memPtr, destMemIdx); + + auto calldataPtr = ext.calldata(); + auto srcPtr = builder.CreateGEP(calldataPtr, srcDataIdx); + + auto calldataSize = ext.calldatasize(); + // remaining data bytes: + auto remDataSize = builder.CreateSub(calldataSize, srcDataIdx); + auto remSizeNegative = builder.CreateICmpSLT(remDataSize, zero256); + auto bytesToCopy = builder.CreateSelect(remSizeNegative, zero256, remDataSize); + + builder.CreateMemCpy(destPtr, srcPtr, bytesToCopy, 0); + + break; + } + case Instruction::CALLDATALOAD: { auto index = stack.pop(); diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index 1d309947d..bb2a54870 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -14,7 +14,6 @@ using llvm::types::i; using Linkage = llvm::GlobalValue::LinkageTypes; using dev::h256; using dev::u256; - namespace evmcc { @@ -70,7 +69,7 @@ Ext::Ext(llvm::IRBuilder<>& _builder, llvm::Module* module) i256Ty, // i256 number; i256Ty, // i256 difficulty; i256Ty, // i256 gaslimit; - //m_builder.getInt8PtrTy() + m_builder.getInt8PtrTy() // byte* calldata }; auto extDataTy = StructType::create(elements, "ext.Data"); @@ -125,6 +124,7 @@ Value* Ext::timestamp() { return getDataElem(8, "timestamp"); } Value* Ext::number() { return getDataElem(9, "number"); } Value* Ext::difficulty() { return getDataElem(10, "difficulty"); } Value* Ext::gaslimit() { return getDataElem(11, "gaslimit"); } +Value* Ext::calldata() { return getDataElem(12, "calldata"); } Value* Ext::calldataload(Value* _index) { @@ -218,7 +218,7 @@ EXPORT void ext_init(ExtData* _extData) _extData->number = eth2llvm(ext.currentBlock.number); _extData->difficulty = eth2llvm(ext.currentBlock.difficulty); _extData->gaslimit = eth2llvm(ext.currentBlock.gasLimit); - //_extData->calldata = ext.data.data(); + _extData->calldata = ext.data.data(); } EXPORT void ext_store(i256* _index, i256* _value) diff --git a/evmcc/Ext.h b/evmcc/Ext.h index 302991854..5c683ffdf 100644 --- a/evmcc/Ext.h +++ b/evmcc/Ext.h @@ -31,6 +31,7 @@ public: llvm::Value* number(); llvm::Value* difficulty(); llvm::Value* gaslimit(); + llvm::Value* calldata(); llvm::Value* balance(llvm::Value* _address); void suicide(llvm::Value* _address); diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index 4d4a34928..0098ed1f9 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -126,6 +126,11 @@ void Memory::storeByte(llvm::Value* _addr, llvm::Value* _word) dump(0); } +llvm::Value* Memory::getData() +{ + return m_builder.CreateLoad(m_data); +} + llvm::Value* Memory::getSize() { return m_builder.CreateLoad(m_size); diff --git a/evmcc/Memory.h b/evmcc/Memory.h index c01bd6ef8..8b22294d7 100644 --- a/evmcc/Memory.h +++ b/evmcc/Memory.h @@ -18,6 +18,7 @@ public: llvm::Value* loadWord(llvm::Value* _addr); void storeWord(llvm::Value* _addr, llvm::Value* _word); void storeByte(llvm::Value* _addr, llvm::Value* _byte); + llvm::Value* getData(); llvm::Value* getSize(); void registerReturnData(llvm::Value* _index, llvm::Value* _size); From 54989e071f7f410d39d87a625e6a8deaf47e7bc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 14 Oct 2014 16:11:39 +0200 Subject: [PATCH 112/641] InsertPointGuard helper class for IRBuilder --- evmcc/GasMeter.cpp | 8 +++----- evmcc/Memory.cpp | 37 ++++++++++++++++++------------------- evmcc/Memory.h | 4 ++-- evmcc/Utils.h | 24 +++++++++++++++++++++++- 4 files changed, 46 insertions(+), 27 deletions(-) diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index d10833ca4..06f6cc49d 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -8,6 +8,7 @@ #include #include "Type.h" +#include "Utils.h" namespace evmcc { @@ -81,17 +82,14 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module): m_gas = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "gas"); m_gas->setUnnamedAddr(true); // Address is not important - auto pt = m_builder.GetInsertPoint(); - auto bb = m_builder.GetInsertBlock(); m_gasCheckFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "gas.check", _module); - auto gasCheckBB = llvm::BasicBlock::Create(_builder.getContext(), {}, m_gasCheckFunc); - m_builder.SetInsertPoint(gasCheckBB); + InsertPointGuard guard(m_builder); + m_builder.SetInsertPoint(llvm::BasicBlock::Create(_builder.getContext(), {}, m_gasCheckFunc)); llvm::Value* cost = m_gasCheckFunc->arg_begin(); llvm::Value* gas = m_builder.CreateLoad(m_gas); gas = m_builder.CreateSub(gas, cost); m_builder.CreateStore(gas, m_gas); m_builder.CreateRetVoid(); - m_builder.SetInsertPoint(bb, pt); } void GasMeter::count(Instruction _inst) diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index 8f4809062..2312fb853 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -54,30 +54,32 @@ llvm::Function* Memory::createRequireFunc(llvm::Module* _module, GasMeter& _gasM auto resizeBB = llvm::BasicBlock::Create(func->getContext(), "resize", func); auto returnBB = llvm::BasicBlock::Create(func->getContext(), "return", func); + InsertPointGuard guard(m_builder); // Restores insert point at function exit + // BB "check" - llvm::IRBuilder<> builder(checkBB); + m_builder.SetInsertPoint(checkBB); llvm::Value* sizeRequired = func->arg_begin(); sizeRequired->setName("sizeRequired"); - auto size = builder.CreateLoad(m_size, "size"); - auto resizeNeeded = builder.CreateICmpULE(size, sizeRequired, "resizeNeeded"); - builder.CreateCondBr(resizeNeeded, resizeBB, returnBB); // OPT branch weights? + auto size = m_builder.CreateLoad(m_size, "size"); + auto resizeNeeded = m_builder.CreateICmpULE(size, sizeRequired, "resizeNeeded"); + m_builder.CreateCondBr(resizeNeeded, resizeBB, returnBB); // OPT branch weights? // BB "resize" - builder.SetInsertPoint(resizeBB); + m_builder.SetInsertPoint(resizeBB); // Check gas first - auto wordsRequired = builder.CreateUDiv(builder.CreateAdd(sizeRequired, Constant::get(31)), Constant::get(32), "wordsRequired"); - auto words = builder.CreateUDiv(builder.CreateAdd(size, Constant::get(31)), Constant::get(32), "words"); - auto newWords = builder.CreateSub(wordsRequired, words, "addtionalWords"); - _gasMeter.checkMemory(newWords, builder); + auto wordsRequired = m_builder.CreateUDiv(m_builder.CreateAdd(sizeRequired, Constant::get(31)), Constant::get(32), "wordsRequired"); + auto words = m_builder.CreateUDiv(m_builder.CreateAdd(size, Constant::get(31)), Constant::get(32), "words"); + auto newWords = m_builder.CreateSub(wordsRequired, words, "addtionalWords"); + _gasMeter.checkMemory(newWords, m_builder); // Resize - builder.CreateStore(sizeRequired, m_size); - auto newData = builder.CreateCall(m_resize, m_size, "newData"); - builder.CreateStore(newData, m_data); - builder.CreateBr(returnBB); + m_builder.CreateStore(sizeRequired, m_size); + auto newData = m_builder.CreateCall(m_resize, m_size, "newData"); + m_builder.CreateStore(newData, m_data); + m_builder.CreateBr(returnBB); // BB "return" - builder.SetInsertPoint(returnBB); - builder.CreateRetVoid(); + m_builder.SetInsertPoint(returnBB); + m_builder.CreateRetVoid(); return func; } @@ -90,8 +92,7 @@ llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, llvm:: auto funcType = _isStore ? llvm::FunctionType::get(Type::Void, storeArgs, false) : llvm::FunctionType::get(Type::i256, Type::i256, false); auto func = llvm::Function::Create(funcType, llvm::Function::PrivateLinkage, name, _module); - auto origBB = m_builder.GetInsertBlock(); - auto origPt = m_builder.GetInsertPoint(); + InsertPointGuard guard(m_builder); // Restores insert point at function exit m_builder.SetInsertPoint(llvm::BasicBlock::Create(func->getContext(), {}, func)); llvm::Value* index = func->arg_begin(); @@ -116,8 +117,6 @@ llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, llvm:: m_builder.CreateRet(ret); } - m_builder.SetInsertPoint(origBB, origPt); - return func; } diff --git a/evmcc/Memory.h b/evmcc/Memory.h index 8ea9bf082..122899c86 100644 --- a/evmcc/Memory.h +++ b/evmcc/Memory.h @@ -45,11 +45,11 @@ private: llvm::GlobalVariable* m_returnDataOffset; llvm::GlobalVariable* m_returnDataSize; + llvm::Function* m_resize; + llvm::Function* m_require; llvm::Function* m_loadWord; llvm::Function* m_storeWord; llvm::Function* m_storeByte; - llvm::Function* m_require; - llvm::Function* m_resize; llvm::Function* m_memDump; }; diff --git a/evmcc/Utils.h b/evmcc/Utils.h index 8233ac9e3..f0224831c 100644 --- a/evmcc/Utils.h +++ b/evmcc/Utils.h @@ -1,7 +1,7 @@ #pragma once -#include +#include #include @@ -22,4 +22,26 @@ static_assert(sizeof(i256) == 32, "Wrong i265 size"); dev::u256 llvm2eth(i256); i256 eth2llvm(dev::u256); +struct InsertPointGuard +{ + InsertPointGuard(llvm::IRBuilder<>& _builder) : + m_builder(_builder), + m_insertBB(m_builder.GetInsertBlock()), + m_insertPt(m_builder.GetInsertPoint()) + {} + + ~InsertPointGuard() + { + m_builder.SetInsertPoint(m_insertBB, m_insertPt); + } + +private: + llvm::IRBuilder<>& m_builder; + llvm::BasicBlock* m_insertBB; + llvm::BasicBlock::iterator m_insertPt; + + InsertPointGuard(const InsertPointGuard&) = delete; + void operator=(InsertPointGuard) = delete; +}; + } \ No newline at end of file From 2b383751b4374a55eb0964c6f097364986ebebb8 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Tue, 14 Oct 2014 15:19:18 +0100 Subject: [PATCH 113/641] Fixes in CALLDATACOPY [Delivers #80644732] --- evmcc/Compiler.cpp | 16 +++++++++------- evmcc/test/ext/calldatacopy1.evm | 1 + evmcc/test/ext/calldatacopy1.lll | 13 +++++++++++++ evmcc/test/ext/calldatacopy2.evm | 1 + evmcc/test/ext/calldatacopy2.lll | 13 +++++++++++++ 5 files changed, 37 insertions(+), 7 deletions(-) create mode 100644 evmcc/test/ext/calldatacopy1.evm create mode 100644 evmcc/test/ext/calldatacopy1.lll create mode 100644 evmcc/test/ext/calldatacopy2.evm create mode 100644 evmcc/test/ext/calldatacopy2.lll diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 3037145c2..3bb0a843c 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -742,24 +742,26 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto destMemIdx = stack.pop(); auto srcDataIdx = stack.pop(); - auto reqByteCount = stack.pop(); + auto reqBytes = stack.pop(); // FIXME: ensure memory size reqMemSize. - auto reqMemSize = builder.CreateAdd(destMemIdx, reqByteCount); - auto reqMemWord = builder.CreateSub(reqMemSize, ConstantInt::get(Type::i256, 32)); - memory.loadWord(reqMemWord); + auto reqMemSize = builder.CreateAdd(destMemIdx, reqBytes, "req_mem_size"); + memory.require(reqMemSize); auto memPtr = memory.getData(); - auto destPtr = builder.CreateGEP(memPtr, destMemIdx); + auto destPtr = builder.CreateGEP(memPtr, destMemIdx, "dest_mem_ptr"); auto calldataPtr = ext.calldata(); - auto srcPtr = builder.CreateGEP(calldataPtr, srcDataIdx); + auto srcPtr = builder.CreateGEP(calldataPtr, srcDataIdx, "src_idx"); auto calldataSize = ext.calldatasize(); // remaining data bytes: auto remDataSize = builder.CreateSub(calldataSize, srcDataIdx); auto remSizeNegative = builder.CreateICmpSLT(remDataSize, zero256); - auto bytesToCopy = builder.CreateSelect(remSizeNegative, zero256, remDataSize); + auto remDataBytes = builder.CreateSelect(remSizeNegative, zero256, remDataSize, "rem_data_bytes"); + + auto tooLittleDataBytes = builder.CreateICmpULT(remDataBytes, reqBytes); + auto bytesToCopy = builder.CreateSelect(tooLittleDataBytes, remDataBytes, reqBytes, "bytes_to_copy"); builder.CreateMemCpy(destPtr, srcPtr, bytesToCopy, 0); diff --git a/evmcc/test/ext/calldatacopy1.evm b/evmcc/test/ext/calldatacopy1.evm new file mode 100644 index 000000000..73c4d76b8 --- /dev/null +++ b/evmcc/test/ext/calldatacopy1.evm @@ -0,0 +1 @@ +60146000600a37600053600a6014f2 diff --git a/evmcc/test/ext/calldatacopy1.lll b/evmcc/test/ext/calldatacopy1.lll new file mode 100644 index 000000000..da3666c71 --- /dev/null +++ b/evmcc/test/ext/calldatacopy1.lll @@ -0,0 +1,13 @@ +(asm +20 ;; byte count +0 ;; source index in calldata array +10 ;; dest index in memory +CALLDATACOPY + +0 +MLOAD ;; to dump memory + +10 +20 +RETURN +) \ No newline at end of file diff --git a/evmcc/test/ext/calldatacopy2.evm b/evmcc/test/ext/calldatacopy2.evm new file mode 100644 index 000000000..e8eea8da7 --- /dev/null +++ b/evmcc/test/ext/calldatacopy2.evm @@ -0,0 +1 @@ +606464e8d4a510006000376000536000600af2 diff --git a/evmcc/test/ext/calldatacopy2.lll b/evmcc/test/ext/calldatacopy2.lll new file mode 100644 index 000000000..6bbea48d8 --- /dev/null +++ b/evmcc/test/ext/calldatacopy2.lll @@ -0,0 +1,13 @@ +(asm +100 ;; byte count +1000000000000 ;; source index in calldata array +0 ;; dest index in memory +CALLDATACOPY + +0 +MLOAD ;; to dump memory + +0 +10 +RETURN +) \ No newline at end of file From 8267b453c7c2204f3b7602bf99facbbccf3ddbf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 14 Oct 2014 16:28:38 +0200 Subject: [PATCH 114/641] Prealloc memory and count gas for SHA3 and CREATE instructions [#79942174] --- evmcc/Compiler.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 37a4d89a1..4bc234455 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -435,6 +435,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) { auto inOff = stack.pop(); auto inSize = stack.pop(); + memory.require(inOff, inSize); auto hash = ext.sha3(inOff, inSize); stack.push(hash); } @@ -768,6 +769,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto endowment = stack.pop(); auto initOff = stack.pop(); auto initSize = stack.pop(); + memory.require(initOff, initSize); auto address = ext.create(endowment, initOff, initSize); stack.push(address); From 52d3a3beb071d3aeff7ae6d895adc95de293c859 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 14 Oct 2014 16:52:53 +0200 Subject: [PATCH 115/641] Prealloc memory and count gas for CALL instruction [#79942174] --- evmcc/Compiler.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index ed1e31ca6..0fc72fd0d 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -745,9 +745,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto srcDataIdx = stack.pop(); auto reqBytes = stack.pop(); - // FIXME: ensure memory size reqMemSize. - auto reqMemSize = builder.CreateAdd(destMemIdx, reqBytes, "req_mem_size"); - memory.require(reqMemSize); + memory.require(destMemIdx, reqBytes); auto memPtr = memory.getData(); auto destPtr = builder.CreateGEP(memPtr, destMemIdx, "dest_mem_ptr"); @@ -856,6 +854,14 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto outSize = stack.pop(); gasMeter.commitCostBlock(gas); + + // Require memory for the max of in and out buffers + auto inSizeReq = builder.CreateAdd(inOff, inSize, "inSizeReq"); + auto outSizeReq = builder.CreateAdd(outOff, outSize, "outSizeReq"); + auto cmp = builder.CreateICmpUGT(inSizeReq, outSizeReq); + auto sizeReq = builder.CreateSelect(cmp, inSizeReq, outSizeReq, "sizeReq"); + memory.require(sizeReq); + auto ret = ext.call(gas, receiveAddress, value, inOff, inSize, outOff, outSize); gasMeter.giveBack(gas); stack.push(ret); From 2e3e764fb5bdb91fb6dedd80b4ec77e1e473aaac Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Tue, 14 Oct 2014 16:06:34 +0100 Subject: [PATCH 116/641] Codegen for CODECOPY. [Delivers #80644732] --- evmcc/Compiler.cpp | 34 ++++++++++++++++---------------- evmcc/ExecutionEngine.cpp | 4 +++- evmcc/Ext.cpp | 16 ++++++++++++--- evmcc/Ext.h | 2 ++ evmcc/test/ext/calldatacopy1.evm | 2 +- evmcc/test/ext/calldatacopy1.lll | 2 +- evmcc/test/ext/codecopy1.evm | 1 + evmcc/test/ext/codecopy1.lll | 13 ++++++++++++ evmcc/test/ext/codecopy2.evm | 1 + evmcc/test/ext/codecopy2.lll | 13 ++++++++++++ evmcc/test/ext/codecopy3.evm | 1 + evmcc/test/ext/codecopy3.lll | 13 ++++++++++++ 12 files changed, 79 insertions(+), 23 deletions(-) create mode 100644 evmcc/test/ext/codecopy1.evm create mode 100644 evmcc/test/ext/codecopy1.lll create mode 100644 evmcc/test/ext/codecopy2.evm create mode 100644 evmcc/test/ext/codecopy2.lll create mode 100644 evmcc/test/ext/codecopy3.evm create mode 100644 evmcc/test/ext/codecopy3.lll diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 3bb0a843c..fe1ccbae0 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -736,32 +736,39 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::CODESIZE: + { + auto value = ext.codesize(); + stack.push(value); + break; + } + case Instruction::CALLDATACOPY: + case Instruction::CODECOPY: { auto zero256 = ConstantInt::get(Type::i256, 0); auto destMemIdx = stack.pop(); - auto srcDataIdx = stack.pop(); + auto srcIdx = stack.pop(); auto reqBytes = stack.pop(); - // FIXME: ensure memory size reqMemSize. auto reqMemSize = builder.CreateAdd(destMemIdx, reqBytes, "req_mem_size"); memory.require(reqMemSize); auto memPtr = memory.getData(); auto destPtr = builder.CreateGEP(memPtr, destMemIdx, "dest_mem_ptr"); - auto calldataPtr = ext.calldata(); - auto srcPtr = builder.CreateGEP(calldataPtr, srcDataIdx, "src_idx"); + auto srcBasePtr = inst == Instruction::CALLDATACOPY ? ext.calldata() : ext.code(); + auto srcPtr = builder.CreateGEP(srcBasePtr, srcIdx, "src_idx"); - auto calldataSize = ext.calldatasize(); + auto srcSize = inst == Instruction::CALLDATACOPY ? ext.calldatasize() : ext.codesize(); // remaining data bytes: - auto remDataSize = builder.CreateSub(calldataSize, srcDataIdx); - auto remSizeNegative = builder.CreateICmpSLT(remDataSize, zero256); - auto remDataBytes = builder.CreateSelect(remSizeNegative, zero256, remDataSize, "rem_data_bytes"); + auto remSrcSize = builder.CreateSub(srcSize, srcIdx); + auto remSizeNegative = builder.CreateICmpSLT(remSrcSize, zero256); + auto remSrcBytes = builder.CreateSelect(remSizeNegative, zero256, remSrcSize, "rem_src_bytes"); - auto tooLittleDataBytes = builder.CreateICmpULT(remDataBytes, reqBytes); - auto bytesToCopy = builder.CreateSelect(tooLittleDataBytes, remDataBytes, reqBytes, "bytes_to_copy"); + auto tooLittleDataBytes = builder.CreateICmpULT(remSrcBytes, reqBytes); + auto bytesToCopy = builder.CreateSelect(tooLittleDataBytes, remSrcBytes, reqBytes, "bytes_to_copy"); builder.CreateMemCpy(destPtr, srcPtr, bytesToCopy, 0); @@ -783,13 +790,6 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } - case Instruction::CODESIZE: - { - auto value = Constant::get(bytecode.size()); - stack.push(value); - break; - } - case Instruction::PREVHASH: { auto value = ext.prevhash(); diff --git a/evmcc/ExecutionEngine.cpp b/evmcc/ExecutionEngine.cpp index 0e6df0b24..23507073a 100644 --- a/evmcc/ExecutionEngine.cpp +++ b/evmcc/ExecutionEngine.cpp @@ -85,6 +85,8 @@ int ExecutionEngine::run(std::unique_ptr _module) ext->currentBlock.gasLimit = 1008; std::string calldata = "Hello the Beautiful World of Ethereum!"; ext->data = calldata; + unsigned char fakecode[] = { 0x0d, 0x0e, 0x0a, 0x0d, 0x0b, 0x0e, 0xe, 0xf }; + ext->code = decltype(ext->code)(fakecode, 8); // Init runtime uint64_t gas = 1000000; @@ -114,4 +116,4 @@ int ExecutionEngine::run(std::unique_ptr _module) return 0; } -} \ No newline at end of file +} diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index 1019a3986..9f72bd0ca 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -37,7 +37,9 @@ struct ExtData i256 number; i256 difficulty; i256 gaslimit; + i256 codesize; const byte* calldata; + const byte* code; }; Ext::Ext(llvm::IRBuilder<>& _builder, llvm::Module* module) @@ -47,6 +49,8 @@ Ext::Ext(llvm::IRBuilder<>& _builder, llvm::Module* module) auto i256Ty = m_builder.getIntNTy(256); auto i256PtrTy = i256Ty->getPointerTo(); + auto i8PtrTy = m_builder.getInt8PtrTy(); + m_args[0] = m_builder.CreateAlloca(i256Ty, nullptr, "ext.index"); m_args[1] = m_builder.CreateAlloca(i256Ty, nullptr, "ext.value"); m_arg2 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg2"); @@ -69,7 +73,10 @@ Ext::Ext(llvm::IRBuilder<>& _builder, llvm::Module* module) i256Ty, // i256 number; i256Ty, // i256 difficulty; i256Ty, // i256 gaslimit; - m_builder.getInt8PtrTy() // byte* calldata + i256Ty, // i256 codesize + i8PtrTy, // byte* calldata + i8PtrTy, // byte* code + }; auto extDataTy = StructType::create(elements, "ext.Data"); @@ -88,7 +95,6 @@ Ext::Ext(llvm::IRBuilder<>& _builder, llvm::Module* module) m_sha3 = Function::Create(TypeBuilder*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_sha3", module); m_exp = Function::Create(TypeBuilder*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_exp", module); - m_builder.CreateCall(m_init, m_data); } @@ -124,7 +130,9 @@ Value* Ext::timestamp() { return getDataElem(8, "timestamp"); } Value* Ext::number() { return getDataElem(9, "number"); } Value* Ext::difficulty() { return getDataElem(10, "difficulty"); } Value* Ext::gaslimit() { return getDataElem(11, "gaslimit"); } -Value* Ext::calldata() { return getDataElem(12, "calldata"); } +Value* Ext::codesize() { return getDataElem(12, "codesize"); } +Value* Ext::calldata() { return getDataElem(13, "calldata"); } +Value* Ext::code() { return getDataElem(14, "code"); } Value* Ext::calldataload(Value* _index) { @@ -219,7 +227,9 @@ EXPORT void ext_init(ExtData* _extData) _extData->number = eth2llvm(ext.currentBlock.number); _extData->difficulty = eth2llvm(ext.currentBlock.difficulty); _extData->gaslimit = eth2llvm(ext.currentBlock.gasLimit); + _extData->codesize = eth2llvm(ext.code.size()); _extData->calldata = ext.data.data(); + _extData->code = ext.code.data(); } EXPORT void ext_store(i256* _index, i256* _value) diff --git a/evmcc/Ext.h b/evmcc/Ext.h index 91eea2c5f..873d941a0 100644 --- a/evmcc/Ext.h +++ b/evmcc/Ext.h @@ -31,7 +31,9 @@ public: llvm::Value* number(); llvm::Value* difficulty(); llvm::Value* gaslimit(); + llvm::Value* codesize(); llvm::Value* calldata(); + llvm::Value* code(); llvm::Value* balance(llvm::Value* _address); void suicide(llvm::Value* _address); diff --git a/evmcc/test/ext/calldatacopy1.evm b/evmcc/test/ext/calldatacopy1.evm index 73c4d76b8..f20019651 100644 --- a/evmcc/test/ext/calldatacopy1.evm +++ b/evmcc/test/ext/calldatacopy1.evm @@ -1 +1 @@ -60146000600a37600053600a6014f2 +60326000600a37600053600a6014f2 diff --git a/evmcc/test/ext/calldatacopy1.lll b/evmcc/test/ext/calldatacopy1.lll index da3666c71..3d2ae0a78 100644 --- a/evmcc/test/ext/calldatacopy1.lll +++ b/evmcc/test/ext/calldatacopy1.lll @@ -1,5 +1,5 @@ (asm -20 ;; byte count +50 ;; byte count 0 ;; source index in calldata array 10 ;; dest index in memory CALLDATACOPY diff --git a/evmcc/test/ext/codecopy1.evm b/evmcc/test/ext/codecopy1.evm new file mode 100644 index 000000000..d286f9232 --- /dev/null +++ b/evmcc/test/ext/codecopy1.evm @@ -0,0 +1 @@ +60146000600a39600053600a6014f2 diff --git a/evmcc/test/ext/codecopy1.lll b/evmcc/test/ext/codecopy1.lll new file mode 100644 index 000000000..85a02b5d7 --- /dev/null +++ b/evmcc/test/ext/codecopy1.lll @@ -0,0 +1,13 @@ +(asm +20 ;; byte count +0 ;; source index in code array +10 ;; dest index in memory +CODECOPY + +0 +MLOAD ;; to dump memory + +10 +20 +RETURN +) \ No newline at end of file diff --git a/evmcc/test/ext/codecopy2.evm b/evmcc/test/ext/codecopy2.evm new file mode 100644 index 000000000..71cd92525 --- /dev/null +++ b/evmcc/test/ext/codecopy2.evm @@ -0,0 +1 @@ +606464e8d4a510006000396000536000600af2 diff --git a/evmcc/test/ext/codecopy2.lll b/evmcc/test/ext/codecopy2.lll new file mode 100644 index 000000000..dcbbcaa46 --- /dev/null +++ b/evmcc/test/ext/codecopy2.lll @@ -0,0 +1,13 @@ +(asm +100 ;; byte count +1000000000000 ;; source index in code array +0 ;; dest index in memory +CODECOPY + +0 +MLOAD ;; to dump memory + +0 +10 +RETURN +) \ No newline at end of file diff --git a/evmcc/test/ext/codecopy3.evm b/evmcc/test/ext/codecopy3.evm new file mode 100644 index 000000000..e4b6a9253 --- /dev/null +++ b/evmcc/test/ext/codecopy3.evm @@ -0,0 +1 @@ +3860006000396000536000600af2 diff --git a/evmcc/test/ext/codecopy3.lll b/evmcc/test/ext/codecopy3.lll new file mode 100644 index 000000000..80d9982c6 --- /dev/null +++ b/evmcc/test/ext/codecopy3.lll @@ -0,0 +1,13 @@ +(asm +CODESIZE ;; byte count +0 ;; source index in code array +0 ;; dest index in memory +CODECOPY + +0 +MLOAD ;; to dump memory + +0 +10 +RETURN +) \ No newline at end of file From 01b95883f2b959244fd5621c88ad220a9e8fb639 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 14 Oct 2014 18:22:30 +0200 Subject: [PATCH 117/641] Count gas cost for SSTORE instruction [#79942174] --- evmcc/Compiler.cpp | 1 + evmcc/GasMeter.cpp | 25 ++++++++++++++++++++++++- evmcc/GasMeter.h | 3 +++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 0fc72fd0d..3d43e5e54 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -609,6 +609,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) { auto index = stack.pop(); auto value = stack.pop(); + gasMeter.countSStore(ext, index, value); ext.setStore(index, value); break; } diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index 99b5e549d..cd7f9eb33 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -9,6 +9,7 @@ #include "Type.h" #include "Utils.h" +#include "Ext.h" namespace evmcc { @@ -100,12 +101,34 @@ void GasMeter::count(Instruction _inst) m_checkCall = m_builder.CreateCall(m_gasCheckFunc, llvm::UndefValue::get(Type::i256)); } - m_blockCost += getStepCost(_inst); + if (_inst != Instruction::SSTORE) // Handle cost of SSTORE separately in countSStore() + m_blockCost += getStepCost(_inst); if (isCostBlockEnd(_inst)) commitCostBlock(); } +void GasMeter::countSStore(Ext& _ext, llvm::Value* _index, llvm::Value* _newValue) +{ + assert(!m_checkCall); // Everything should've been commited before + + static const auto sstoreCost = static_cast(c_sstoreGas); + + // [ADD] if oldValue == 0 and newValue != 0 => 2*cost + // [DEL] if oldValue != 0 and newValue == 0 => 0 + + auto oldValue = _ext.store(_index); + auto oldValueIsZero = m_builder.CreateICmpEQ(oldValue, Constant::get(0), "oldValueIsZero"); + auto newValueIsZero = m_builder.CreateICmpEQ(_newValue, Constant::get(0), "newValueIsZero"); + auto oldValueIsntZero = m_builder.CreateICmpNE(oldValue, Constant::get(0), "oldValueIsntZero"); + auto newValueIsntZero = m_builder.CreateICmpNE(_newValue, Constant::get(0), "newValueIsntZero"); + auto isAdd = m_builder.CreateAnd(oldValueIsZero, newValueIsntZero, "isAdd"); + auto isDel = m_builder.CreateAnd(oldValueIsntZero, newValueIsZero, "isDel"); + auto cost = m_builder.CreateSelect(isAdd, Constant::get(2 * sstoreCost), Constant::get(sstoreCost), "cost"); + cost = m_builder.CreateSelect(isDel, Constant::get(0), cost, "cost"); + m_builder.CreateCall(m_gasCheckFunc, cost); +} + void GasMeter::giveBack(llvm::Value* _gas) { llvm::Value* gasCounter = m_builder.CreateLoad(m_gas, "gas"); diff --git a/evmcc/GasMeter.h b/evmcc/GasMeter.h index 95e8eaf8d..a47bb2244 100644 --- a/evmcc/GasMeter.h +++ b/evmcc/GasMeter.h @@ -19,6 +19,9 @@ public: /// Count step cost of instruction void count(dev::eth::Instruction _inst); + /// Calculate & count gas cost for SSTORE instruction + void countSStore(class Ext& _ext, llvm::Value* _index, llvm::Value* _newValue); + /// Finalize cost-block by checking gas needed for the block before the block /// @param _additionalCost adds additional cost to cost-block before commit void commitCostBlock(llvm::Value* _additionalCost = nullptr); From 31a07cb1b878c92db8d9d4908fa9dcb89232018a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 14 Oct 2014 18:26:47 +0200 Subject: [PATCH 118/641] Change a bit the implementation of GAS instruction [Delivers #79942174] --- evmcc/Compiler.cpp | 3 +-- evmcc/GasMeter.cpp | 4 ++-- evmcc/GasMeter.h | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 3d43e5e54..00ea5c12e 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -690,8 +690,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) case Instruction::GAS: { - auto value = builder.CreateLoad(gasMeter.getLLVMGasVar()); - stack.push(value); + stack.push(gasMeter.getGas()); break; } diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index cd7f9eb33..ab38bd85c 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -167,9 +167,9 @@ void GasMeter::checkMemory(llvm::Value* _additionalMemoryInWords, llvm::IRBuilde _builder.CreateCall(m_gasCheckFunc, cost); } -llvm::GlobalVariable* GasMeter::getLLVMGasVar() +llvm::Value* GasMeter::getGas() { - return m_gas; + m_builder.CreateLoad(m_gas, "gas"); } } diff --git a/evmcc/GasMeter.h b/evmcc/GasMeter.h index a47bb2244..60a1136b9 100644 --- a/evmcc/GasMeter.h +++ b/evmcc/GasMeter.h @@ -32,7 +32,7 @@ public: /// Generate code that checks the cost of additional memory used by program void checkMemory(llvm::Value* _additionalMemoryInWords, llvm::IRBuilder<>& _builder); - llvm::GlobalVariable* getLLVMGasVar(); + llvm::Value* getGas(); private: /// Cumulative gas cost of a block of instructions From 631330074602106ee034bc220b4b0991a25bc5ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 14 Oct 2014 19:03:04 +0200 Subject: [PATCH 119/641] Change a bit the implementation of GAS instruction (fix) [Delivers #79942174] --- evmcc/GasMeter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index ab38bd85c..11244c028 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -169,7 +169,7 @@ void GasMeter::checkMemory(llvm::Value* _additionalMemoryInWords, llvm::IRBuilde llvm::Value* GasMeter::getGas() { - m_builder.CreateLoad(m_gas, "gas"); + return m_builder.CreateLoad(m_gas, "gas"); } } From 1ffdda670516c10cad7bcf4e5a612c092278932f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 14 Oct 2014 19:17:54 +0200 Subject: [PATCH 120/641] Some LLVM function attribute fun --- evmcc/Memory.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index 1838afa4b..e40d61f3b 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -40,6 +40,10 @@ Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module, GasMeter& _ga m_returnDataSize->setUnnamedAddr(true); // Address is not important m_resize = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, Type::WordPtr, false), llvm::Function::ExternalLinkage, "mem_resize", _module); + llvm::AttrBuilder attrBuilder; + attrBuilder.addAttribute(llvm::Attribute::NoAlias).addAttribute(llvm::Attribute::NoCapture).addAttribute(llvm::Attribute::NonNull).addAttribute(llvm::Attribute::ReadOnly); + m_resize->setAttributes(llvm::AttributeSet::get(m_resize->getContext(), 1, attrBuilder)); + m_require = createRequireFunc(_module, _gasMeter); m_loadWord = createFunc(false, Type::i256, _module, _gasMeter); m_storeWord = createFunc(true, Type::i256, _module, _gasMeter); From 70ad81dad25f509b409c989ab407238a2522db7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 14 Oct 2014 20:15:43 +0200 Subject: [PATCH 121/641] Try to throw an OutOfGas exception when out of gas. The exception cannot be handled. [#80660432] --- evmcc/ExecutionEngine.cpp | 23 +++++++++++++++++------ evmcc/GasMeter.cpp | 20 ++++++++++++++++++-- evmcc/GasMeter.h | 1 + evmcc/Runtime.cpp | 17 ++++++++++++++++- evmcc/Type.h | 1 + 5 files changed, 53 insertions(+), 9 deletions(-) diff --git a/evmcc/ExecutionEngine.cpp b/evmcc/ExecutionEngine.cpp index 0e6df0b24..5cb94ddf0 100644 --- a/evmcc/ExecutionEngine.cpp +++ b/evmcc/ExecutionEngine.cpp @@ -13,6 +13,8 @@ #include #include +#include + #include "Runtime.h" #include "Memory.h" #include "Type.h" @@ -87,7 +89,7 @@ int ExecutionEngine::run(std::unique_ptr _module) ext->data = calldata; // Init runtime - uint64_t gas = 1000000; + uint64_t gas = 100; Runtime runtime(gas, std::move(ext)); auto entryFunc = module->getFunction("main"); @@ -97,9 +99,20 @@ int ExecutionEngine::run(std::unique_ptr _module) exit(1); } - auto result = exec->runFunction(entryFunc, {}); + + ReturnCode returnCode; + try + { + auto result = exec->runFunction(entryFunc, {}); + returnCode = static_cast(result.IntVal.getZExtValue()); + } + catch (const dev::eth::OutOfGas&) + { + returnCode = ReturnCode::OutOfGas; + } + gas = static_cast(Runtime::getGas()); - auto returnCode = static_cast(result.IntVal.getZExtValue()); + if (returnCode == ReturnCode::Return) { auto&& returnData = Memory::getReturnData(); // TODO: It might be better to place is in Runtime interface @@ -108,10 +121,8 @@ int ExecutionEngine::run(std::unique_ptr _module) for (auto it = returnData.begin(), end = returnData.end(); it != end; ++it) std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)*it << " "; std::cout << "]\n"; - - return 10; } - return 0; + return static_cast(returnCode); } } \ No newline at end of file diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index 11244c028..10a8fca98 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -83,11 +83,27 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module): m_gas = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "gas"); m_gas->setUnnamedAddr(true); // Address is not important + m_rtExit = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::MainReturn, false), llvm::Function::ExternalLinkage, "rt_exit", _module); + m_gasCheckFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "gas.check", _module); InsertPointGuard guard(m_builder); - m_builder.SetInsertPoint(llvm::BasicBlock::Create(_builder.getContext(), {}, m_gasCheckFunc)); + + auto checkBB = llvm::BasicBlock::Create(_builder.getContext(), "check", m_gasCheckFunc); + auto outOfGasBB = llvm::BasicBlock::Create(_builder.getContext(), "outOfGas", m_gasCheckFunc); + auto updateBB = llvm::BasicBlock::Create(_builder.getContext(), "update", m_gasCheckFunc); + + m_builder.SetInsertPoint(checkBB); llvm::Value* cost = m_gasCheckFunc->arg_begin(); - llvm::Value* gas = m_builder.CreateLoad(m_gas); + cost->setName("cost"); + llvm::Value* gas = m_builder.CreateLoad(m_gas, "gas"); + auto isOutOfGas = m_builder.CreateICmpUGT(cost, gas, "isOutOfGas"); + m_builder.CreateCondBr(isOutOfGas, outOfGasBB, updateBB); + + m_builder.SetInsertPoint(outOfGasBB); + m_builder.CreateCall(m_rtExit, Constant::get(ReturnCode::OutOfGas)); + m_builder.CreateRetVoid(); + + m_builder.SetInsertPoint(updateBB); gas = m_builder.CreateSub(gas, cost); m_builder.CreateStore(gas, m_gas); m_builder.CreateRetVoid(); diff --git a/evmcc/GasMeter.h b/evmcc/GasMeter.h index 60a1136b9..8738b49c0 100644 --- a/evmcc/GasMeter.h +++ b/evmcc/GasMeter.h @@ -41,6 +41,7 @@ private: llvm::IRBuilder<>& m_builder; llvm::CallInst* m_checkCall = nullptr; llvm::GlobalVariable* m_gas; + llvm::Function* m_rtExit; llvm::Function* m_gasCheckFunc; }; diff --git a/evmcc/Runtime.cpp b/evmcc/Runtime.cpp index a373d9501..834a8bbff 100644 --- a/evmcc/Runtime.cpp +++ b/evmcc/Runtime.cpp @@ -1,12 +1,27 @@ #include "Runtime.h" +#include + +#include "Type.h" + namespace evmcc { static Runtime* g_runtime; -extern "C" { EXPORT i256 gas; } +extern "C" +{ +EXPORT i256 gas; + +EXPORT void rt_exit(int32_t _returnCode) +{ + auto returnCode = static_cast(_returnCode); + if (returnCode == ReturnCode::OutOfGas) + BOOST_THROW_EXCEPTION(dev::eth::OutOfGas()); +} + +} Runtime::Runtime(dev::u256 _gas, std::unique_ptr _ext): m_ext(std::move(_ext)) diff --git a/evmcc/Type.h b/evmcc/Type.h index a8501d897..727183266 100644 --- a/evmcc/Type.h +++ b/evmcc/Type.h @@ -34,6 +34,7 @@ enum class ReturnCode Suicide = 2, BadJumpDestination = 101, + OutOfGas = 102, }; struct Constant From 471586cc824595ca3b883760b573d831deb08410 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 14 Oct 2014 20:49:48 +0200 Subject: [PATCH 122/641] Use longjmp to return OutOfGas code from main function (WIP) [#80660432] --- evmcc/Compiler.cpp | 15 ++++++++++++--- evmcc/Compiler.h | 2 ++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 00ea5c12e..7b1f6de18 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -6,7 +6,7 @@ #include #include #include -//#include +#include #include @@ -159,6 +159,7 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode) m_finalBlock = std::make_unique("FinalBlock", m_mainFunc); m_badJumpBlock = std::make_unique("BadJumpBlock", m_mainFunc); m_jumpTableBlock = std::make_unique("JumpTableBlock", m_mainFunc); + m_outOfGasBlock = std::make_unique("OutOfGas", m_mainFunc); for (auto it = directJumpTargets.cbegin(); it != directJumpTargets.cend(); ++it) { @@ -195,6 +196,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) // Create the basic blocks. auto entryBlock = llvm::BasicBlock::Create(context, "entry", m_mainFunc); builder.SetInsertPoint(entryBlock); + createBasicBlocks(bytecode); // Init runtime structures. @@ -203,7 +205,12 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) Ext ext(builder, module.get()); // Jump to first instruction - builder.CreateBr(basicBlocks.begin()->second); + auto setjmpFunc = llvm::Intrinsic::getDeclaration(module.get(), llvm::Intrinsic::eh_sjlj_setjmp); + auto jmpBufTy = llvm::ArrayType::get(builder.getInt64Ty(), 5); + auto jmpBuf = new llvm::GlobalVariable(*module, jmpBufTy, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(jmpBufTy), "jmpBuf"); + auto setjmpRet = builder.CreateCall(setjmpFunc, builder.CreateBitCast(jmpBuf, Type::BytePtr)); + auto isNormalFlow = builder.CreateICmpEQ(setjmpRet, builder.getInt32(0)); + builder.CreateCondBr(isNormalFlow, basicBlocks.begin()->second, m_outOfGasBlock->llvm()); for (auto basicBlockPairIt = basicBlocks.begin(); basicBlockPairIt != basicBlocks.end(); ++basicBlockPairIt) { @@ -921,10 +928,12 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) builder.SetInsertPoint(m_finalBlock->llvm()); builder.CreateRet(Constant::get(ReturnCode::Stop)); - // TODO: throw an exception or something builder.SetInsertPoint(m_badJumpBlock->llvm()); builder.CreateRet(Constant::get(ReturnCode::BadJumpDestination)); + builder.SetInsertPoint(m_outOfGasBlock->llvm()); + builder.CreateRet(Constant::get(ReturnCode::OutOfGas)); + builder.SetInsertPoint(m_jumpTableBlock->llvm()); if (m_indirectJumpTargets.size() > 0) { diff --git a/evmcc/Compiler.h b/evmcc/Compiler.h index 7d0cb4ab6..509cf77df 100644 --- a/evmcc/Compiler.h +++ b/evmcc/Compiler.h @@ -59,6 +59,8 @@ private: */ std::unique_ptr m_badJumpBlock; + std::unique_ptr m_outOfGasBlock; + /// Main program function llvm::Function* m_mainFunc = nullptr; }; From 8498ab5695221acbb43d3141610cade3b88b08f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 15 Oct 2014 11:11:07 +0200 Subject: [PATCH 123/641] Trying to implement "exceptions" with longjmp (does not work on Windows 64bit at least) --- evmcc/Compiler.cpp | 14 +++++++++----- evmcc/ExecutionEngine.cpp | 4 +++- evmcc/GasMeter.cpp | 15 +++++++++------ evmcc/GasMeter.h | 2 +- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 7b1f6de18..11e7569db 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -199,16 +199,20 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) createBasicBlocks(bytecode); + // Prepare jump buffer + auto jmpBufStorageTy = llvm::ArrayType::get(Type::Byte, 2048); + auto jmpBufStorage = new llvm::GlobalVariable(*module, jmpBufStorageTy, false, llvm::GlobalVariable::PrivateLinkage, llvm::ConstantAggregateZero::get(jmpBufStorageTy), "jmpBuf"); + jmpBufStorage->setAlignment(16); + auto jmpBuf = builder.CreateConstInBoundsGEP2_32(jmpBufStorage, 0, 0); + // Init runtime structures. - GasMeter gasMeter(builder, module.get()); + GasMeter gasMeter(builder, module.get(), jmpBuf); Memory memory(builder, module.get(), gasMeter); Ext ext(builder, module.get()); - // Jump to first instruction + // Create exception landing with setjmp and jump to first instruction auto setjmpFunc = llvm::Intrinsic::getDeclaration(module.get(), llvm::Intrinsic::eh_sjlj_setjmp); - auto jmpBufTy = llvm::ArrayType::get(builder.getInt64Ty(), 5); - auto jmpBuf = new llvm::GlobalVariable(*module, jmpBufTy, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(jmpBufTy), "jmpBuf"); - auto setjmpRet = builder.CreateCall(setjmpFunc, builder.CreateBitCast(jmpBuf, Type::BytePtr)); + auto setjmpRet = builder.CreateCall(setjmpFunc, jmpBuf); auto isNormalFlow = builder.CreateICmpEQ(setjmpRet, builder.getInt32(0)); builder.CreateCondBr(isNormalFlow, basicBlocks.begin()->second, m_outOfGasBlock->llvm()); diff --git a/evmcc/ExecutionEngine.cpp b/evmcc/ExecutionEngine.cpp index 5cb94ddf0..95c90ec19 100644 --- a/evmcc/ExecutionEngine.cpp +++ b/evmcc/ExecutionEngine.cpp @@ -121,7 +121,9 @@ int ExecutionEngine::run(std::unique_ptr _module) for (auto it = returnData.begin(), end = returnData.end(); it != end; ++it) std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)*it << " "; std::cout << "]\n"; - } + } + + std::cout << "RETURN CODE: " << (int)returnCode << std::endl; return static_cast(returnCode); } diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index 10a8fca98..0d0927563 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -77,7 +78,7 @@ bool isCostBlockEnd(Instruction _inst) } -GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module): +GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module, llvm::Value* _jmpBuf) : m_builder(_builder) { m_gas = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "gas"); @@ -88,9 +89,9 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module): m_gasCheckFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "gas.check", _module); InsertPointGuard guard(m_builder); - auto checkBB = llvm::BasicBlock::Create(_builder.getContext(), "check", m_gasCheckFunc); - auto outOfGasBB = llvm::BasicBlock::Create(_builder.getContext(), "outOfGas", m_gasCheckFunc); - auto updateBB = llvm::BasicBlock::Create(_builder.getContext(), "update", m_gasCheckFunc); + auto checkBB = llvm::BasicBlock::Create(_builder.getContext(), "Check", m_gasCheckFunc); + auto outOfGasBB = llvm::BasicBlock::Create(_builder.getContext(), "OutOfGas", m_gasCheckFunc); + auto updateBB = llvm::BasicBlock::Create(_builder.getContext(), "Update", m_gasCheckFunc); m_builder.SetInsertPoint(checkBB); llvm::Value* cost = m_gasCheckFunc->arg_begin(); @@ -100,8 +101,10 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module): m_builder.CreateCondBr(isOutOfGas, outOfGasBB, updateBB); m_builder.SetInsertPoint(outOfGasBB); - m_builder.CreateCall(m_rtExit, Constant::get(ReturnCode::OutOfGas)); - m_builder.CreateRetVoid(); + + auto longjmpFunc = llvm::Intrinsic::getDeclaration(_module, llvm::Intrinsic::eh_sjlj_longjmp); + m_builder.CreateCall(longjmpFunc, _jmpBuf); + m_builder.CreateUnreachable(); m_builder.SetInsertPoint(updateBB); gas = m_builder.CreateSub(gas, cost); diff --git a/evmcc/GasMeter.h b/evmcc/GasMeter.h index 8738b49c0..5af117900 100644 --- a/evmcc/GasMeter.h +++ b/evmcc/GasMeter.h @@ -11,7 +11,7 @@ namespace evmcc class GasMeter { public: - GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* module); + GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module, llvm::Value* _jmpBuf); GasMeter(const GasMeter&) = delete; void operator=(GasMeter) = delete; From 8e93171d3d92e7e090ff5dde9a6a8d383e584a36 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Wed, 15 Oct 2014 10:32:37 +0100 Subject: [PATCH 124/641] Codegen for EXTCODESIZE & EXTCODECOPY [Delivers #80644732] --- evmcc/Compiler.cpp | 50 ++++++++++++++++++++++++++++++---------------- evmcc/Ext.cpp | 42 +++++++++++++++++++++++++++++++++++++- evmcc/Ext.h | 4 ++++ evmcc/Memory.cpp | 24 ++++++++++++++++++++++ evmcc/Memory.h | 2 ++ 5 files changed, 104 insertions(+), 18 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 80a01cc55..6b4320543 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -744,35 +744,51 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } - case Instruction::CALLDATACOPY: - case Instruction::CODECOPY: + case Instruction::EXTCODESIZE: { - auto zero256 = ConstantInt::get(Type::i256, 0); + auto addr = stack.pop(); + auto value = ext.codesizeAt(addr); + stack.push(value); + break; + } + case Instruction::CALLDATACOPY: + { auto destMemIdx = stack.pop(); auto srcIdx = stack.pop(); auto reqBytes = stack.pop(); - auto reqMemSize = builder.CreateAdd(destMemIdx, reqBytes, "req_mem_size"); - memory.require(reqMemSize); + auto srcPtr = ext.calldata(); + auto srcSize = ext.calldatasize(); + + memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); + break; + } - auto memPtr = memory.getData(); - auto destPtr = builder.CreateGEP(memPtr, destMemIdx, "dest_mem_ptr"); + case Instruction::CODECOPY: + { + auto destMemIdx = stack.pop(); + auto srcIdx = stack.pop(); + auto reqBytes = stack.pop(); - auto srcBasePtr = inst == Instruction::CALLDATACOPY ? ext.calldata() : ext.code(); - auto srcPtr = builder.CreateGEP(srcBasePtr, srcIdx, "src_idx"); + auto srcPtr = ext.code(); + auto srcSize = ext.codesize(); - auto srcSize = inst == Instruction::CALLDATACOPY ? ext.calldatasize() : ext.codesize(); - // remaining data bytes: - auto remSrcSize = builder.CreateSub(srcSize, srcIdx); - auto remSizeNegative = builder.CreateICmpSLT(remSrcSize, zero256); - auto remSrcBytes = builder.CreateSelect(remSizeNegative, zero256, remSrcSize, "rem_src_bytes"); + memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); + break; + } - auto tooLittleDataBytes = builder.CreateICmpULT(remSrcBytes, reqBytes); - auto bytesToCopy = builder.CreateSelect(tooLittleDataBytes, remSrcBytes, reqBytes, "bytes_to_copy"); + case Instruction::EXTCODECOPY: + { + auto extAddr = stack.pop(); + auto destMemIdx = stack.pop(); + auto srcIdx = stack.pop(); + auto reqBytes = stack.pop(); - builder.CreateMemCpy(destPtr, srcPtr, bytesToCopy, 0); + auto srcPtr = ext.codeAt(extAddr); + auto srcSize = ext.codesizeAt(extAddr); + memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); break; } diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index 9f72bd0ca..2b3313b87 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -14,6 +14,7 @@ using llvm::types::i; using Linkage = llvm::GlobalValue::LinkageTypes; using dev::h256; using dev::u256; + namespace evmcc { @@ -94,6 +95,8 @@ Ext::Ext(llvm::IRBuilder<>& _builder, llvm::Module* module) m_bswap = Intrinsic::getDeclaration(module, Intrinsic::bswap, i256Ty); m_sha3 = Function::Create(TypeBuilder*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_sha3", module); m_exp = Function::Create(TypeBuilder*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_exp", module); + m_codeAt = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_codeAt", module); + m_codesizeAt = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_codesizeAt", module); m_builder.CreateCall(m_init, m_data); } @@ -209,9 +212,32 @@ llvm::Value* Ext::exp(llvm::Value* _left, llvm::Value* _right) return m_builder.CreateLoad(m_args[1]); } +llvm::Value* Ext::codeAt(llvm::Value* _addr) +{ + auto addr = bswap(_addr); + m_builder.CreateStore(addr, m_args[0]); + llvm::Value* args[] = {m_args[0], m_args[1]}; + m_builder.CreateCall(m_codeAt, args); + return m_builder.CreateLoad(m_args[1]); +} + +llvm::Value* Ext::codesizeAt(llvm::Value* _addr) +{ + auto addr = bswap(_addr); + m_builder.CreateStore(addr, m_args[0]); + llvm::Value* args[] = {m_args[0], m_args[1]}; + m_builder.CreateCall(m_codesizeAt, args); + return m_builder.CreateLoad(m_args[1]); +} + +} + + extern "C" { +using namespace evmcc; + EXPORT void ext_init(ExtData* _extData) { auto&& ext = Runtime::getExt(); @@ -307,7 +333,7 @@ EXPORT void ext_call(i256* _gas, h256* _receiveAddress, i256* _value, i256* _inO auto&& inRef = dev::bytesConstRef(Runtime::getMemory().data() + inOff, inSize); auto&& outRef = dev::bytesConstRef(Runtime::getMemory().data() + outOff, outSize); dev::eth::OnOpFunc onOp{}; // TODO: Handle that thing - auto ret = ext.call(receiveAddress, value, inRef, &gas, outRef, onOp, {}, receiveAddress); + ret = ext.call(receiveAddress, value, inRef, &gas, outRef, onOp, {}, receiveAddress); } *_gas = eth2llvm(gas); @@ -331,6 +357,20 @@ EXPORT void ext_exp(i256* _left, i256* _right, i256* _ret) *_ret = eth2llvm(ret); } +EXPORT void ext_codeAt(h256* _addr256, i256* _ret) +{ + auto&& ext = Runtime::getExt(); + auto addr = dev::right160(*_addr256); + auto& code = ext.codeAt(addr); + *_ret = *reinterpret_cast(const_cast(&code[0])); +} + +EXPORT void ext_codesizeAt(h256* _addr256, i256* _ret) +{ + auto&& ext = Runtime::getExt(); + auto addr = dev::right160(*_addr256); + auto& code = ext.codeAt(addr); + *_ret = eth2llvm(u256(code.size())); } } diff --git a/evmcc/Ext.h b/evmcc/Ext.h index 873d941a0..03ff90ba8 100644 --- a/evmcc/Ext.h +++ b/evmcc/Ext.h @@ -43,6 +43,8 @@ public: llvm::Value* sha3(llvm::Value* _inOff, llvm::Value* _inSize); llvm::Value* exp(llvm::Value* _left, llvm::Value* _right); + llvm::Value* codeAt(llvm::Value* _addr); + llvm::Value* codesizeAt(llvm::Value* _addr); private: llvm::Value* getDataElem(unsigned _index, const llvm::Twine& _name = ""); @@ -71,6 +73,8 @@ private: llvm::Function* m_bswap; llvm::Function* m_sha3; llvm::Function* m_exp; + llvm::Function* m_codeAt; + llvm::Function* m_codesizeAt; }; diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index e40d61f3b..cf82e7a50 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -177,6 +177,30 @@ void Memory::registerReturnData(llvm::Value* _index, llvm::Value* _size) m_builder.CreateStore(_size, m_returnDataSize); } +void Memory::copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value* _srcIdx, + llvm::Value* _destMemIdx, llvm::Value* _reqBytes) +{ + auto zero256 = llvm::ConstantInt::get(Type::i256, 0); + + auto reqMemSize = m_builder.CreateAdd(_destMemIdx, _reqBytes, "req_mem_size"); + require(reqMemSize); + + auto srcPtr = m_builder.CreateGEP(_srcPtr, _srcIdx, "src_idx"); + + auto memPtr = getData(); + auto destPtr = m_builder.CreateGEP(memPtr, _destMemIdx, "dest_mem_ptr"); + + // remaining source bytes: + auto remSrcSize = m_builder.CreateSub(_srcSize, _srcIdx); + auto remSizeNegative = m_builder.CreateICmpSLT(remSrcSize, zero256); + auto remSrcBytes = m_builder.CreateSelect(remSizeNegative, zero256, remSrcSize, "rem_src_bytes"); + + auto tooFewSrcBytes = m_builder.CreateICmpULT(remSrcBytes, _reqBytes); + auto bytesToCopy = m_builder.CreateSelect(tooFewSrcBytes, remSrcBytes, _reqBytes, "bytes_to_copy"); + + m_builder.CreateMemCpy(destPtr, srcPtr, bytesToCopy, 0); +} + void Memory::dump(uint64_t _begin, uint64_t _end) { if (getenv("EVMCC_DEBUG_MEMORY") == nullptr) diff --git a/evmcc/Memory.h b/evmcc/Memory.h index fdf4a17f7..34b4c68a8 100644 --- a/evmcc/Memory.h +++ b/evmcc/Memory.h @@ -20,6 +20,8 @@ public: void storeByte(llvm::Value* _addr, llvm::Value* _byte); llvm::Value* getData(); llvm::Value* getSize(); + void copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value* _srcIndex, + llvm::Value* _destMemIdx, llvm::Value* _byteCount); /// Requires this amount of memory. And counts gas fee for that memory. void require(llvm::Value* _size); From fc9b9f32c94e379f322cad8b22444a801143beac Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Wed, 15 Oct 2014 13:40:04 +0100 Subject: [PATCH 125/641] * codegen for CODECALL * fixes for EXTCODECOPY --- evmcc/Compiler.cpp | 9 +++++++-- evmcc/ExecutionEngine.cpp | 1 - evmcc/Ext.cpp | 25 ++++++++++++++----------- evmcc/Ext.h | 3 ++- evmcc/test/ext/extcodecopy1.evm | 1 + evmcc/test/ext/extcodecopy1.lll | 11 +++++++++++ 6 files changed, 35 insertions(+), 15 deletions(-) create mode 100644 evmcc/test/ext/extcodecopy1.evm create mode 100644 evmcc/test/ext/extcodecopy1.lll diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index dd9b0b510..a113655f9 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -873,9 +873,10 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) } case Instruction::CALL: + case Instruction::CALLCODE: { auto gas = stack.pop(); - auto receiveAddress = stack.pop(); + auto codeAddress = stack.pop(); auto value = stack.pop(); auto inOff = stack.pop(); auto inSize = stack.pop(); @@ -891,7 +892,11 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto sizeReq = builder.CreateSelect(cmp, inSizeReq, outSizeReq, "sizeReq"); memory.require(sizeReq); - auto ret = ext.call(gas, receiveAddress, value, inOff, inSize, outOff, outSize); + auto receiveAddress = codeAddress; + if (inst == Instruction::CALLCODE) + receiveAddress = ext.address(); + + auto ret = ext.call(gas, receiveAddress, value, inOff, inSize, outOff, outSize, codeAddress); gasMeter.giveBack(gas); stack.push(ret); break; diff --git a/evmcc/ExecutionEngine.cpp b/evmcc/ExecutionEngine.cpp index aeb720903..103842daf 100644 --- a/evmcc/ExecutionEngine.cpp +++ b/evmcc/ExecutionEngine.cpp @@ -27,7 +27,6 @@ ExecutionEngine::ExecutionEngine() } - int ExecutionEngine::run(std::unique_ptr _module) { auto module = _module.get(); // Keep ownership of the module in _module diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index 2b3313b87..93c3616e0 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -60,6 +60,7 @@ Ext::Ext(llvm::IRBuilder<>& _builder, llvm::Module* module) m_arg5 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg5"); m_arg6 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg6"); m_arg7 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg7"); + m_arg7 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg8"); Type* elements[] = { i256Ty, // i256 address; @@ -90,12 +91,12 @@ Ext::Ext(llvm::IRBuilder<>& _builder, llvm::Module* module) m_balance = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_balance", module); m_suicide = Function::Create(TypeBuilder*), true>::get(ctx), Linkage::ExternalLinkage, "ext_suicide", module); m_create = Function::Create(TypeBuilder*, i<256>*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_create", module); - Type* args[] = {i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy}; + Type* args[] = {i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy}; m_call = Function::Create(FunctionType::get(m_builder.getVoidTy(), args, false), Linkage::ExternalLinkage, "ext_call", module); m_bswap = Intrinsic::getDeclaration(module, Intrinsic::bswap, i256Ty); m_sha3 = Function::Create(TypeBuilder*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_sha3", module); m_exp = Function::Create(TypeBuilder*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_exp", module); - m_codeAt = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_codeAt", module); + m_codeAt = Function::Create(TypeBuilder*(i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_codeAt", module); m_codesizeAt = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_codesizeAt", module); m_builder.CreateCall(m_init, m_data); @@ -176,7 +177,7 @@ Value* Ext::create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* return address; } -llvm::Value* Ext::call(llvm::Value*& _gas, llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize) +llvm::Value* Ext::call(llvm::Value*& _gas, llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize, llvm::Value* _codeAddress) { m_builder.CreateStore(_gas, m_args[0]); auto receiveAddress = bswap(_receiveAddress); // to BE @@ -186,7 +187,10 @@ llvm::Value* Ext::call(llvm::Value*& _gas, llvm::Value* _receiveAddress, llvm::V m_builder.CreateStore(_inSize, m_arg5); m_builder.CreateStore(_outOff, m_arg6); m_builder.CreateStore(_outSize, m_arg7); - llvm::Value* args[] = {m_args[0], m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_args[1]}; + auto codeAddress = bswap(_codeAddress); // toBE + m_builder.CreateStore(codeAddress, m_arg8); + + llvm::Value* args[] = {m_args[0], m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_args[1]}; m_builder.CreateCall(m_call, args); _gas = m_builder.CreateLoad(m_args[0]); // Return gas return m_builder.CreateLoad(m_args[1]); @@ -216,9 +220,7 @@ llvm::Value* Ext::codeAt(llvm::Value* _addr) { auto addr = bswap(_addr); m_builder.CreateStore(addr, m_args[0]); - llvm::Value* args[] = {m_args[0], m_args[1]}; - m_builder.CreateCall(m_codeAt, args); - return m_builder.CreateLoad(m_args[1]); + return m_builder.CreateCall(m_codeAt, m_args[0]); } llvm::Value* Ext::codesizeAt(llvm::Value* _addr) @@ -315,7 +317,7 @@ EXPORT void ext_create(i256* _endowment, i256* _initOff, i256* _initSize, h256* -EXPORT void ext_call(i256* _gas, h256* _receiveAddress, i256* _value, i256* _inOff, i256* _inSize, i256* _outOff, i256* _outSize, i256* _ret) +EXPORT void ext_call(i256* _gas, h256* _receiveAddress, i256* _value, i256* _inOff, i256* _inSize, i256* _outOff, i256* _outSize, h256* _codeAddress, i256* _ret) { auto&& ext = Runtime::getExt(); auto value = llvm2eth(*_value); @@ -333,7 +335,8 @@ EXPORT void ext_call(i256* _gas, h256* _receiveAddress, i256* _value, i256* _inO auto&& inRef = dev::bytesConstRef(Runtime::getMemory().data() + inOff, inSize); auto&& outRef = dev::bytesConstRef(Runtime::getMemory().data() + outOff, outSize); dev::eth::OnOpFunc onOp{}; // TODO: Handle that thing - ret = ext.call(receiveAddress, value, inRef, &gas, outRef, onOp, {}, receiveAddress); + auto codeAddress = dev::right160(*_codeAddress); + ret = ext.call(receiveAddress, value, inRef, &gas, outRef, onOp, {}, codeAddress); } *_gas = eth2llvm(gas); @@ -357,12 +360,12 @@ EXPORT void ext_exp(i256* _left, i256* _right, i256* _ret) *_ret = eth2llvm(ret); } -EXPORT void ext_codeAt(h256* _addr256, i256* _ret) +EXPORT unsigned char* ext_codeAt(h256* _addr256) { auto&& ext = Runtime::getExt(); auto addr = dev::right160(*_addr256); auto& code = ext.codeAt(addr); - *_ret = *reinterpret_cast(const_cast(&code[0])); + return const_cast(code.data()); } EXPORT void ext_codesizeAt(h256* _addr256, i256* _ret) diff --git a/evmcc/Ext.h b/evmcc/Ext.h index 03ff90ba8..daf12b100 100644 --- a/evmcc/Ext.h +++ b/evmcc/Ext.h @@ -39,7 +39,7 @@ public: void suicide(llvm::Value* _address); llvm::Value* calldataload(llvm::Value* _index); llvm::Value* create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize); - llvm::Value* call(llvm::Value*& _gas, llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize); + llvm::Value* call(llvm::Value*& _gas, llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize, llvm::Value* _codeAddress); llvm::Value* sha3(llvm::Value* _inOff, llvm::Value* _inSize); llvm::Value* exp(llvm::Value* _left, llvm::Value* _right); @@ -61,6 +61,7 @@ private: llvm::Value* m_arg5; llvm::Value* m_arg6; llvm::Value* m_arg7; + llvm::Value* m_arg8; llvm::Value* m_data; llvm::Function* m_init; llvm::Function* m_store; diff --git a/evmcc/test/ext/extcodecopy1.evm b/evmcc/test/ext/extcodecopy1.evm new file mode 100644 index 000000000..6132b52d8 --- /dev/null +++ b/evmcc/test/ext/extcodecopy1.evm @@ -0,0 +1 @@ +60c86000600a303c60005360006020f2 diff --git a/evmcc/test/ext/extcodecopy1.lll b/evmcc/test/ext/extcodecopy1.lll new file mode 100644 index 000000000..c37054574 --- /dev/null +++ b/evmcc/test/ext/extcodecopy1.lll @@ -0,0 +1,11 @@ +(asm +200 ;; byte count +0 ;; source index in code array +10 ;; dest index in memory +ADDRESS +EXTCODECOPY + +0 MLOAD ;; to dump memory + +0 32 RETURN +) \ No newline at end of file From 2909cac50e94cfbfdb855467dea457a937eb6168 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 15 Oct 2014 15:07:31 +0200 Subject: [PATCH 126/641] Working longjmp solution [#80660432] --- evmcc/Compiler.cpp | 14 ++------------ evmcc/ExecutionEngine.cpp | 16 ++++++++++------ evmcc/GasMeter.cpp | 9 ++++++--- evmcc/GasMeter.h | 2 +- 4 files changed, 19 insertions(+), 22 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 8c64c3fe2..5a84d32fc 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -199,22 +199,12 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) createBasicBlocks(bytecode); - // Prepare jump buffer - auto jmpBufStorageTy = llvm::ArrayType::get(Type::Byte, 2048); - auto jmpBufStorage = new llvm::GlobalVariable(*module, jmpBufStorageTy, false, llvm::GlobalVariable::PrivateLinkage, llvm::ConstantAggregateZero::get(jmpBufStorageTy), "jmpBuf"); - jmpBufStorage->setAlignment(16); - auto jmpBuf = builder.CreateConstInBoundsGEP2_32(jmpBufStorage, 0, 0); - // Init runtime structures. - GasMeter gasMeter(builder, module.get(), jmpBuf); + GasMeter gasMeter(builder, module.get()); Memory memory(builder, module.get(), gasMeter); Ext ext(builder, module.get()); - // Create exception landing with setjmp and jump to first instruction - auto setjmpFunc = llvm::Intrinsic::getDeclaration(module.get(), llvm::Intrinsic::eh_sjlj_setjmp); - auto setjmpRet = builder.CreateCall(setjmpFunc, jmpBuf); - auto isNormalFlow = builder.CreateICmpEQ(setjmpRet, builder.getInt32(0)); - builder.CreateCondBr(isNormalFlow, basicBlocks.begin()->second, m_outOfGasBlock->llvm()); + builder.CreateBr(basicBlocks.begin()->second); for (auto basicBlockPairIt = basicBlocks.begin(); basicBlockPairIt != basicBlocks.end(); ++basicBlockPairIt) { diff --git a/evmcc/ExecutionEngine.cpp b/evmcc/ExecutionEngine.cpp index aeb720903..a5ed3681a 100644 --- a/evmcc/ExecutionEngine.cpp +++ b/evmcc/ExecutionEngine.cpp @@ -1,6 +1,8 @@ #include "ExecutionEngine.h" +#include + #include #include #include @@ -27,6 +29,8 @@ ExecutionEngine::ExecutionEngine() } +extern "C" { EXPORT std::jmp_buf* rt_jmpBuf; } + int ExecutionEngine::run(std::unique_ptr _module) { @@ -101,17 +105,17 @@ int ExecutionEngine::run(std::unique_ptr _module) exit(1); } - ReturnCode returnCode; - try + std::jmp_buf buf; + auto r = setjmp(buf); + if (r == 0) { + rt_jmpBuf = &buf; auto result = exec->runFunction(entryFunc, {}); returnCode = static_cast(result.IntVal.getZExtValue()); } - catch (const dev::eth::OutOfGas&) - { - returnCode = ReturnCode::OutOfGas; - } + else + returnCode = static_cast(r); gas = static_cast(Runtime::getGas()); diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index 0d0927563..adf7f407a 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -78,7 +78,7 @@ bool isCostBlockEnd(Instruction _inst) } -GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module, llvm::Value* _jmpBuf) : +GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module) : m_builder(_builder) { m_gas = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "gas"); @@ -102,8 +102,11 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module, llvm::Val m_builder.SetInsertPoint(outOfGasBB); - auto longjmpFunc = llvm::Intrinsic::getDeclaration(_module, llvm::Intrinsic::eh_sjlj_longjmp); - m_builder.CreateCall(longjmpFunc, _jmpBuf); + //auto longjmpFunc = llvm::Intrinsic::getDeclaration(_module, llvm::Intrinsic::eh_sjlj_longjmp); + auto extJmpBuf = new llvm::GlobalVariable(*_module, Type::BytePtr, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "rt_jmpBuf"); + llvm::Type* args[] = {Type::BytePtr, m_builder.getInt32Ty()}; + auto longjmpNative = llvm::Function::Create(llvm::FunctionType::get(Type::Void, args, false), llvm::Function::ExternalLinkage, "longjmp", _module); + m_builder.CreateCall2(longjmpNative, m_builder.CreateLoad(extJmpBuf), Constant::get(ReturnCode::OutOfGas)); m_builder.CreateUnreachable(); m_builder.SetInsertPoint(updateBB); diff --git a/evmcc/GasMeter.h b/evmcc/GasMeter.h index 5af117900..099ce004e 100644 --- a/evmcc/GasMeter.h +++ b/evmcc/GasMeter.h @@ -11,7 +11,7 @@ namespace evmcc class GasMeter { public: - GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module, llvm::Value* _jmpBuf); + GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module); GasMeter(const GasMeter&) = delete; void operator=(GasMeter) = delete; From 5a6d8b3d2f4cbd3deaab1c20c3f15d7f833de78e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 15 Oct 2014 15:12:24 +0200 Subject: [PATCH 127/641] Unused rt_exit() function removed [#80660432] --- evmcc/GasMeter.cpp | 2 -- evmcc/GasMeter.h | 1 - evmcc/Runtime.cpp | 8 -------- 3 files changed, 11 deletions(-) diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index adf7f407a..1e3b607b8 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -84,8 +84,6 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module) : m_gas = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "gas"); m_gas->setUnnamedAddr(true); // Address is not important - m_rtExit = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::MainReturn, false), llvm::Function::ExternalLinkage, "rt_exit", _module); - m_gasCheckFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "gas.check", _module); InsertPointGuard guard(m_builder); diff --git a/evmcc/GasMeter.h b/evmcc/GasMeter.h index 099ce004e..9774fbdaf 100644 --- a/evmcc/GasMeter.h +++ b/evmcc/GasMeter.h @@ -41,7 +41,6 @@ private: llvm::IRBuilder<>& m_builder; llvm::CallInst* m_checkCall = nullptr; llvm::GlobalVariable* m_gas; - llvm::Function* m_rtExit; llvm::Function* m_gasCheckFunc; }; diff --git a/evmcc/Runtime.cpp b/evmcc/Runtime.cpp index 834a8bbff..c37fa6702 100644 --- a/evmcc/Runtime.cpp +++ b/evmcc/Runtime.cpp @@ -13,14 +13,6 @@ static Runtime* g_runtime; extern "C" { EXPORT i256 gas; - -EXPORT void rt_exit(int32_t _returnCode) -{ - auto returnCode = static_cast(_returnCode); - if (returnCode == ReturnCode::OutOfGas) - BOOST_THROW_EXCEPTION(dev::eth::OutOfGas()); -} - } Runtime::Runtime(dev::u256 _gas, std::unique_ptr _ext): From c019b0394ae89146bffac8c032bb0ebab784c31e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 15 Oct 2014 15:35:26 +0200 Subject: [PATCH 128/641] Macros grouping PUSH, DUP and SWAP switch cases --- evmcc/Compiler.cpp | 102 +++------------------------------------------ evmcc/Utils.h | 67 +++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 96 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 45f21f29b..f71f4d2bf 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -14,6 +14,7 @@ #include "Memory.h" #include "Ext.h" #include "GasMeter.h" +#include "Utils.h" namespace evmcc { @@ -48,38 +49,8 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode) auto inst = static_cast(*curr); switch (inst) { - case Instruction::PUSH1: - case Instruction::PUSH2: - case Instruction::PUSH3: - case Instruction::PUSH4: - case Instruction::PUSH5: - case Instruction::PUSH6: - case Instruction::PUSH7: - case Instruction::PUSH8: - case Instruction::PUSH9: - case Instruction::PUSH10: - case Instruction::PUSH11: - case Instruction::PUSH12: - case Instruction::PUSH13: - case Instruction::PUSH14: - case Instruction::PUSH15: - case Instruction::PUSH16: - case Instruction::PUSH17: - case Instruction::PUSH18: - case Instruction::PUSH19: - case Instruction::PUSH20: - case Instruction::PUSH21: - case Instruction::PUSH22: - case Instruction::PUSH23: - case Instruction::PUSH24: - case Instruction::PUSH25: - case Instruction::PUSH26: - case Instruction::PUSH27: - case Instruction::PUSH28: - case Instruction::PUSH29: - case Instruction::PUSH30: - case Instruction::PUSH31: - case Instruction::PUSH32: + + case Instruction::ANY_PUSH: { auto numBytes = static_cast(inst) - static_cast(Instruction::PUSH1) + 1; auto next = curr + numBytes + 1; @@ -477,38 +448,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } - case Instruction::PUSH1: - case Instruction::PUSH2: - case Instruction::PUSH3: - case Instruction::PUSH4: - case Instruction::PUSH5: - case Instruction::PUSH6: - case Instruction::PUSH7: - case Instruction::PUSH8: - case Instruction::PUSH9: - case Instruction::PUSH10: - case Instruction::PUSH11: - case Instruction::PUSH12: - case Instruction::PUSH13: - case Instruction::PUSH14: - case Instruction::PUSH15: - case Instruction::PUSH16: - case Instruction::PUSH17: - case Instruction::PUSH18: - case Instruction::PUSH19: - case Instruction::PUSH20: - case Instruction::PUSH21: - case Instruction::PUSH22: - case Instruction::PUSH23: - case Instruction::PUSH24: - case Instruction::PUSH25: - case Instruction::PUSH26: - case Instruction::PUSH27: - case Instruction::PUSH28: - case Instruction::PUSH29: - case Instruction::PUSH30: - case Instruction::PUSH31: - case Instruction::PUSH32: + case Instruction::ANY_PUSH: { auto numBytes = static_cast(inst)-static_cast(Instruction::PUSH1) + 1; auto value = llvm::APInt(256, 0); @@ -523,44 +463,14 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } - case Instruction::DUP1: - case Instruction::DUP2: - case Instruction::DUP3: - case Instruction::DUP4: - case Instruction::DUP5: - case Instruction::DUP6: - case Instruction::DUP7: - case Instruction::DUP8: - case Instruction::DUP9: - case Instruction::DUP10: - case Instruction::DUP11: - case Instruction::DUP12: - case Instruction::DUP13: - case Instruction::DUP14: - case Instruction::DUP15: - case Instruction::DUP16: + case Instruction::ANY_DUP: { auto index = static_cast(inst)-static_cast(Instruction::DUP1); stack.dup(index); break; } - case Instruction::SWAP1: - case Instruction::SWAP2: - case Instruction::SWAP3: - case Instruction::SWAP4: - case Instruction::SWAP5: - case Instruction::SWAP6: - case Instruction::SWAP7: - case Instruction::SWAP8: - case Instruction::SWAP9: - case Instruction::SWAP10: - case Instruction::SWAP11: - case Instruction::SWAP12: - case Instruction::SWAP13: - case Instruction::SWAP14: - case Instruction::SWAP15: - case Instruction::SWAP16: + case Instruction::ANY_SWAP: { auto index = static_cast(inst)-static_cast(Instruction::SWAP1) + 1; stack.swap(index); diff --git a/evmcc/Utils.h b/evmcc/Utils.h index f0224831c..d5b136327 100644 --- a/evmcc/Utils.h +++ b/evmcc/Utils.h @@ -44,4 +44,71 @@ private: void operator=(InsertPointGuard) = delete; }; +#define ANY_PUSH PUSH1: \ + case Instruction::PUSH2: \ + case Instruction::PUSH3: \ + case Instruction::PUSH4: \ + case Instruction::PUSH5: \ + case Instruction::PUSH6: \ + case Instruction::PUSH7: \ + case Instruction::PUSH8: \ + case Instruction::PUSH9: \ + case Instruction::PUSH10: \ + case Instruction::PUSH11: \ + case Instruction::PUSH12: \ + case Instruction::PUSH13: \ + case Instruction::PUSH14: \ + case Instruction::PUSH15: \ + case Instruction::PUSH16: \ + case Instruction::PUSH17: \ + case Instruction::PUSH18: \ + case Instruction::PUSH19: \ + case Instruction::PUSH20: \ + case Instruction::PUSH21: \ + case Instruction::PUSH22: \ + case Instruction::PUSH23: \ + case Instruction::PUSH24: \ + case Instruction::PUSH25: \ + case Instruction::PUSH26: \ + case Instruction::PUSH27: \ + case Instruction::PUSH28: \ + case Instruction::PUSH29: \ + case Instruction::PUSH30: \ + case Instruction::PUSH31: \ + case Instruction::PUSH32 + +#define ANY_DUP DUP1: \ + case Instruction::DUP2: \ + case Instruction::DUP3: \ + case Instruction::DUP4: \ + case Instruction::DUP5: \ + case Instruction::DUP6: \ + case Instruction::DUP7: \ + case Instruction::DUP8: \ + case Instruction::DUP9: \ + case Instruction::DUP10: \ + case Instruction::DUP11: \ + case Instruction::DUP12: \ + case Instruction::DUP13: \ + case Instruction::DUP14: \ + case Instruction::DUP15: \ + case Instruction::DUP16 + +#define ANY_SWAP SWAP1: \ + case Instruction::SWAP2: \ + case Instruction::SWAP3: \ + case Instruction::SWAP4: \ + case Instruction::SWAP5: \ + case Instruction::SWAP6: \ + case Instruction::SWAP7: \ + case Instruction::SWAP8: \ + case Instruction::SWAP9: \ + case Instruction::SWAP10: \ + case Instruction::SWAP11: \ + case Instruction::SWAP12: \ + case Instruction::SWAP13: \ + case Instruction::SWAP14: \ + case Instruction::SWAP15: \ + case Instruction::SWAP16 + } \ No newline at end of file From e33be3bbdbc79b1f1e4a6e50889cb53e2db77833 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 15 Oct 2014 16:29:13 +0200 Subject: [PATCH 129/641] Change namespace from `evmcc` to `dev::eth::jit` [#80021262] --- evmcc/BasicBlock.cpp | 9 ++++++++- evmcc/BasicBlock.h | 9 ++++++++- evmcc/Compiler.cpp | 9 ++++++++- evmcc/Compiler.h | 8 +++++++- evmcc/ExecutionEngine.cpp | 12 +++++++++--- evmcc/ExecutionEngine.h | 10 ++++++++-- evmcc/Ext.cpp | 11 +++++++++-- evmcc/Ext.h | 11 ++++++++--- evmcc/GasMeter.cpp | 9 ++++++++- evmcc/GasMeter.h | 9 ++++++++- evmcc/Memory.cpp | 15 +++++++++++---- evmcc/Memory.h | 10 +++++++++- evmcc/Runtime.cpp | 10 ++++++++-- evmcc/Runtime.h | 10 ++++++++-- evmcc/Type.cpp | 9 ++++++++- evmcc/Type.h | 9 ++++++++- evmcc/Utils.cpp | 10 ++++++++-- evmcc/Utils.h | 10 ++++++++-- evmcc/evmcc.cpp | 10 +++++----- 19 files changed, 154 insertions(+), 36 deletions(-) diff --git a/evmcc/BasicBlock.cpp b/evmcc/BasicBlock.cpp index 3a2c1c548..02c85165d 100644 --- a/evmcc/BasicBlock.cpp +++ b/evmcc/BasicBlock.cpp @@ -6,7 +6,11 @@ #include "Type.h" -namespace evmcc +namespace dev +{ +namespace eth +{ +namespace jit { const char* BasicBlock::NamePrefix = "Instr."; @@ -69,3 +73,6 @@ void BasicBlock::Stack::swap(size_t _index) } } +} +} + diff --git a/evmcc/BasicBlock.h b/evmcc/BasicBlock.h index 598ab731c..71d8aa355 100644 --- a/evmcc/BasicBlock.h +++ b/evmcc/BasicBlock.h @@ -3,7 +3,11 @@ #include -namespace evmcc +namespace dev +{ +namespace eth +{ +namespace jit { using ProgramCounter = uint64_t; // TODO: Rename @@ -74,3 +78,6 @@ private: }; } +} +} + diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index f71f4d2bf..33e92b758 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -16,7 +16,11 @@ #include "GasMeter.h" #include "Utils.h" -namespace evmcc +namespace dev +{ +namespace eth +{ +namespace jit { using dev::eth::Instruction; @@ -945,3 +949,6 @@ void Compiler::linkBasicBlocks() } } +} +} + diff --git a/evmcc/Compiler.h b/evmcc/Compiler.h index 509cf77df..17bed3f78 100644 --- a/evmcc/Compiler.h +++ b/evmcc/Compiler.h @@ -7,7 +7,11 @@ #include "BasicBlock.h" -namespace evmcc +namespace dev +{ +namespace eth +{ +namespace jit { class Compiler @@ -66,3 +70,5 @@ private: }; } +} +} diff --git a/evmcc/ExecutionEngine.cpp b/evmcc/ExecutionEngine.cpp index a5ed3681a..df2ea74d6 100644 --- a/evmcc/ExecutionEngine.cpp +++ b/evmcc/ExecutionEngine.cpp @@ -21,7 +21,11 @@ #include "Memory.h" #include "Type.h" -namespace evmcc +namespace dev +{ +namespace eth +{ +namespace jit { ExecutionEngine::ExecutionEngine() @@ -91,7 +95,7 @@ int ExecutionEngine::run(std::unique_ptr _module) ext->currentBlock.gasLimit = 1008; std::string calldata = "Hello the Beautiful World of Ethereum!"; ext->data = calldata; - unsigned char fakecode[] = { 0x0d, 0x0e, 0x0a, 0x0d, 0x0b, 0x0e, 0xe, 0xf }; + unsigned char fakecode[] = {0x0d, 0x0e, 0x0a, 0x0d, 0x0b, 0x0e, 0xe, 0xf}; ext->code = decltype(ext->code)(fakecode, 8); // Init runtime @@ -118,7 +122,7 @@ int ExecutionEngine::run(std::unique_ptr _module) returnCode = static_cast(r); gas = static_cast(Runtime::getGas()); - + if (returnCode == ReturnCode::Return) { auto&& returnData = Memory::getReturnData(); // TODO: It might be better to place is in Runtime interface @@ -134,3 +138,5 @@ int ExecutionEngine::run(std::unique_ptr _module) } } +} +} diff --git a/evmcc/ExecutionEngine.h b/evmcc/ExecutionEngine.h index 1bdf8c564..158df0283 100644 --- a/evmcc/ExecutionEngine.h +++ b/evmcc/ExecutionEngine.h @@ -5,7 +5,11 @@ #include -namespace evmcc +namespace dev +{ +namespace eth +{ +namespace jit { class ExecutionEngine @@ -16,4 +20,6 @@ public: int run(std::unique_ptr module); }; -} \ No newline at end of file +} +} +} diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index 93c3616e0..0f5a18795 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -15,7 +15,11 @@ using Linkage = llvm::GlobalValue::LinkageTypes; using dev::h256; using dev::u256; -namespace evmcc +namespace dev +{ +namespace eth +{ +namespace jit { // TODO: Copy of dev::eth::fromAddress in VM.h @@ -238,7 +242,7 @@ llvm::Value* Ext::codesizeAt(llvm::Value* _addr) extern "C" { -using namespace evmcc; +using namespace dev::eth::jit; EXPORT void ext_init(ExtData* _extData) { @@ -377,3 +381,6 @@ EXPORT void ext_codesizeAt(h256* _addr256, i256* _ret) } } +} +} + diff --git a/evmcc/Ext.h b/evmcc/Ext.h index daf12b100..b8b93d61f 100644 --- a/evmcc/Ext.h +++ b/evmcc/Ext.h @@ -5,10 +5,12 @@ #include -namespace evmcc +namespace dev +{ +namespace eth +{ +namespace jit { - - class Ext { @@ -80,3 +82,6 @@ private: } +} +} + diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index 1e3b607b8..2d2774c74 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -12,7 +12,11 @@ #include "Utils.h" #include "Ext.h" -namespace evmcc +namespace dev +{ +namespace eth +{ +namespace jit { using namespace dev::eth; // We should move all the JIT code into dev::eth namespace @@ -193,3 +197,6 @@ llvm::Value* GasMeter::getGas() } } +} +} + diff --git a/evmcc/GasMeter.h b/evmcc/GasMeter.h index 9774fbdaf..c7c1a1bda 100644 --- a/evmcc/GasMeter.h +++ b/evmcc/GasMeter.h @@ -5,7 +5,11 @@ #include -namespace evmcc +namespace dev +{ +namespace eth +{ +namespace jit { class GasMeter @@ -45,3 +49,6 @@ private: }; } +} +} + diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index cf82e7a50..e9abad1c1 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -15,7 +15,11 @@ #include "Runtime.h" #include "GasMeter.h" -namespace evmcc +namespace dev +{ +namespace eth +{ +namespace jit { Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module, GasMeter& _gasMeter): @@ -213,11 +217,14 @@ void Memory::dump(uint64_t _begin, uint64_t _end) m_builder.CreateCall(m_memDump, llvm::ArrayRef(args)); } -} // namespace evmcc +} +} +} + extern "C" { - using namespace evmcc; + using namespace dev::eth::jit; EXPORT i256 mem_returnDataOffset; EXPORT i256 mem_returnDataSize; @@ -256,7 +263,7 @@ EXPORT void evmccrt_memory_dump(uint64_t _begin, uint64_t _end) } // extern "C" -dev::bytesConstRef evmcc::Memory::getReturnData() +dev::bytesConstRef dev::eth::jit::Memory::getReturnData() { // TODO: Handle large indexes auto offset = static_cast(llvm2eth(mem_returnDataOffset)); diff --git a/evmcc/Memory.h b/evmcc/Memory.h index 34b4c68a8..73dff7842 100644 --- a/evmcc/Memory.h +++ b/evmcc/Memory.h @@ -4,8 +4,13 @@ #include -namespace evmcc +namespace dev { +namespace eth +{ +namespace jit +{ + class GasMeter; class Memory @@ -58,3 +63,6 @@ private: }; } +} +} + diff --git a/evmcc/Runtime.cpp b/evmcc/Runtime.cpp index c37fa6702..a7cc0126e 100644 --- a/evmcc/Runtime.cpp +++ b/evmcc/Runtime.cpp @@ -5,7 +5,11 @@ #include "Type.h" -namespace evmcc +namespace dev +{ +namespace eth +{ +namespace jit { static Runtime* g_runtime; @@ -48,4 +52,6 @@ dev::u256 Runtime::getGas() return llvm2eth(gas); } -} \ No newline at end of file +} +} +} diff --git a/evmcc/Runtime.h b/evmcc/Runtime.h index 547e4bcf1..b9cfe2309 100644 --- a/evmcc/Runtime.h +++ b/evmcc/Runtime.h @@ -14,7 +14,11 @@ #define EXPORT #endif -namespace evmcc +namespace dev +{ +namespace eth +{ +namespace jit { using StackImpl = std::vector; @@ -40,4 +44,6 @@ private: std::unique_ptr m_ext; }; -} \ No newline at end of file +} +} +} diff --git a/evmcc/Type.cpp b/evmcc/Type.cpp index 4837829b4..4804f99b8 100644 --- a/evmcc/Type.cpp +++ b/evmcc/Type.cpp @@ -3,7 +3,11 @@ #include -namespace evmcc +namespace dev +{ +namespace eth +{ +namespace jit { llvm::IntegerType* Type::i256; @@ -36,3 +40,6 @@ llvm::Constant* Constant::get(ReturnCode _returnCode) } } +} +} + diff --git a/evmcc/Type.h b/evmcc/Type.h index 727183266..ac3196ed2 100644 --- a/evmcc/Type.h +++ b/evmcc/Type.h @@ -4,7 +4,11 @@ #include #include -namespace evmcc +namespace dev +{ +namespace eth +{ +namespace jit { struct Type @@ -46,3 +50,6 @@ struct Constant }; } +} +} + diff --git a/evmcc/Utils.cpp b/evmcc/Utils.cpp index cef08a283..7ad6ca283 100644 --- a/evmcc/Utils.cpp +++ b/evmcc/Utils.cpp @@ -1,7 +1,11 @@ #include "Utils.h" -namespace evmcc +namespace dev +{ +namespace eth +{ +namespace jit { dev::u256 llvm2eth(i256 _i) @@ -31,4 +35,6 @@ i256 eth2llvm(dev::u256 _u) return i; } -} \ No newline at end of file +} +} +} diff --git a/evmcc/Utils.h b/evmcc/Utils.h index d5b136327..74ad2a4d0 100644 --- a/evmcc/Utils.h +++ b/evmcc/Utils.h @@ -5,7 +5,11 @@ #include -namespace evmcc +namespace dev +{ +namespace eth +{ +namespace jit { /// Representation of 256-bit value binary compatible with LLVM i256 @@ -111,4 +115,6 @@ private: case Instruction::SWAP15: \ case Instruction::SWAP16 -} \ No newline at end of file +} +} +} diff --git a/evmcc/evmcc.cpp b/evmcc/evmcc.cpp index 222bcffb3..b49a2a372 100644 --- a/evmcc/evmcc.cpp +++ b/evmcc/evmcc.cpp @@ -15,8 +15,6 @@ #include "Compiler.h" #include "ExecutionEngine.h" -using namespace dev; - void show_usage() { @@ -74,6 +72,8 @@ int main(int argc, char** argv) boost::algorithm::trim(src); + using namespace dev; + bytes bytecode = fromHex(src); if (opt_show_bytes) @@ -89,15 +89,15 @@ int main(int argc, char** argv) if (opt_compile) { - auto module = evmcc::Compiler().compile(bytecode); + auto module = eth::jit::Compiler().compile(bytecode); llvm::raw_os_ostream out(std::cout); module->print(out, nullptr); } if (opt_interpret) { - auto engine = evmcc::ExecutionEngine(); - auto module = evmcc::Compiler().compile(bytecode); + auto engine = eth::jit::ExecutionEngine(); + auto module = eth::jit::Compiler().compile(bytecode); module->dump(); auto result = engine.run(std::move(module)); return result; From 91770a2e4d339c9e1b20989eb53a3c7bdf867916 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 15 Oct 2014 16:49:29 +0200 Subject: [PATCH 130/641] Eliminating some `using namespace` [#80021262] --- evmcc/Compiler.cpp | 22 ++++++++-------------- evmcc/Ext.cpp | 6 ++---- evmcc/GasMeter.cpp | 4 +--- evmcc/Memory.cpp | 3 ++- evmcc/Type.cpp | 6 +++--- evmcc/Type.h | 6 +++--- 6 files changed, 19 insertions(+), 28 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 33e92b758..1fbab5be8 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -23,10 +23,6 @@ namespace eth namespace jit { -using dev::eth::Instruction; -using namespace dev::eth; // We should move all the JIT code into dev::eth namespace - - Compiler::Compiler() : m_finalBlock(nullptr) , m_badJumpBlock(nullptr) @@ -159,14 +155,12 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode) std::unique_ptr Compiler::compile(const dev::bytes& bytecode) { - using namespace llvm; - - auto& context = getGlobalContext(); - auto module = std::make_unique("main", context); - IRBuilder<> builder(context); + auto& context = llvm::getGlobalContext(); + auto module = std::make_unique("main", context); + llvm::IRBuilder<> builder(context); // Create main function - m_mainFunc = Function::Create(FunctionType::get(Type::MainReturn, false), Function::ExternalLinkage, "main", module.get()); + m_mainFunc = llvm::Function::Create(llvm::FunctionType::get(Type::MainReturn, false), llvm::Function::ExternalLinkage, "main", module.get()); // Create the basic blocks. auto entryBlock = llvm::BasicBlock::Create(context, "entry", m_mainFunc); @@ -286,7 +280,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) case Instruction::NEG: { auto top = stack.pop(); - auto zero = ConstantInt::get(Type::i256, 0); + auto zero = Constant::get(0); auto res = builder.CreateSub(zero, top); stack.push(res); break; @@ -345,7 +339,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) case Instruction::NOT: { auto top = stack.pop(); - auto zero = ConstantInt::get(Type::i256, 0); + auto zero = Constant::get(0); auto iszero = builder.CreateICmpEQ(top, zero, "iszero"); auto result = builder.CreateZExt(iszero, Type::i256); stack.push(result); @@ -566,7 +560,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) { stack.swap(1); auto val = stack.pop(); - auto zero = ConstantInt::get(Type::i256, 0); + auto zero = Constant::get(0); auto cond = builder.CreateICmpNE(val, zero, "nonzero"); // Assume the basic blocks are properly ordered: @@ -876,7 +870,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) for (auto it = m_indirectJumpTargets.cbegin(); it != m_indirectJumpTargets.cend(); ++it) { auto& bb = *it; - auto dest = ConstantInt::get(Type::i256, bb->begin()); + auto dest = Constant::get(bb->begin()); switchInstr->addCase(dest, bb->llvm()); } } diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index 0f5a18795..e9618dcab 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -10,10 +10,6 @@ #include "Runtime.h" using namespace llvm; -using llvm::types::i; -using Linkage = llvm::GlobalValue::LinkageTypes; -using dev::h256; -using dev::u256; namespace dev { @@ -88,6 +84,8 @@ Ext::Ext(llvm::IRBuilder<>& _builder, llvm::Module* module) m_data = m_builder.CreateAlloca(extDataTy, nullptr, "ext.data"); + using llvm::types::i; + using Linkage = llvm::GlobalValue::LinkageTypes; m_init = Function::Create(FunctionType::get(m_builder.getVoidTy(), extDataTy->getPointerTo(), false), Linkage::ExternalLinkage, "ext_init", module); m_store = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_store", module); m_setStore = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_setStore", module); diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index 2d2774c74..bfd688c61 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -19,12 +19,10 @@ namespace eth namespace jit { -using namespace dev::eth; // We should move all the JIT code into dev::eth namespace - namespace // Helper functions { -uint64_t getStepCost(dev::eth::Instruction inst) // TODO: Add this function to FeeSructure +uint64_t getStepCost(dev::eth::Instruction inst) // TODO: Add this function to FeeSructure (pull request submitted) { switch (inst) { diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index e9abad1c1..7c742eb81 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -224,7 +224,8 @@ void Memory::dump(uint64_t _begin, uint64_t _end) extern "C" { - using namespace dev::eth::jit; + +using namespace dev::eth::jit; EXPORT i256 mem_returnDataOffset; EXPORT i256 mem_returnDataSize; diff --git a/evmcc/Type.cpp b/evmcc/Type.cpp index 4804f99b8..3ef339a1b 100644 --- a/evmcc/Type.cpp +++ b/evmcc/Type.cpp @@ -16,7 +16,7 @@ llvm::IntegerType* Type::lowPrecision; llvm::IntegerType* Type::Byte; llvm::PointerType* Type::BytePtr; llvm::Type* Type::Void; -llvm::Type* Type::MainReturn; +llvm::IntegerType* Type::MainReturn; void Type::init(llvm::LLVMContext& _context) { @@ -29,12 +29,12 @@ void Type::init(llvm::LLVMContext& _context) MainReturn = llvm::Type::getInt32Ty(_context); } -llvm::Constant* Constant::get(uint64_t _n) +llvm::ConstantInt* Constant::get(uint64_t _n) { return llvm::ConstantInt::get(Type::i256, _n); } -llvm::Constant* Constant::get(ReturnCode _returnCode) +llvm::ConstantInt* Constant::get(ReturnCode _returnCode) { return llvm::ConstantInt::get(Type::MainReturn, static_cast(_returnCode)); } diff --git a/evmcc/Type.h b/evmcc/Type.h index ac3196ed2..06907b7df 100644 --- a/evmcc/Type.h +++ b/evmcc/Type.h @@ -26,7 +26,7 @@ struct Type static llvm::Type* Void; /// Main function return type - static llvm::Type* MainReturn; + static llvm::IntegerType* MainReturn; static void init(llvm::LLVMContext& _context); }; @@ -44,9 +44,9 @@ enum class ReturnCode struct Constant { /// Returns word-size constant - static llvm::Constant* get(uint64_t _n); + static llvm::ConstantInt* get(uint64_t _n); - static llvm::Constant* get(ReturnCode _returnCode); + static llvm::ConstantInt* get(ReturnCode _returnCode); }; } From 2c44470e87918810b0cff39b8b79d109168a79d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 15 Oct 2014 16:58:15 +0200 Subject: [PATCH 131/641] Removing unnecessary `dev` name prefixes [#80021262] --- evmcc/Compiler.cpp | 8 +++----- evmcc/Compiler.h | 4 ++-- evmcc/ExecutionEngine.cpp | 12 ++++++------ evmcc/Ext.cpp | 38 +++++++++++++++++++------------------- evmcc/Ext.h | 2 +- evmcc/GasMeter.cpp | 2 +- evmcc/GasMeter.h | 2 +- evmcc/Memory.h | 2 +- evmcc/Runtime.cpp | 6 +++--- evmcc/Runtime.h | 10 +++++----- evmcc/Utils.cpp | 8 ++++---- evmcc/Utils.h | 4 ++-- evmcc/evmcc.cpp | 2 +- 13 files changed, 49 insertions(+), 51 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 1fbab5be8..5d474a0a8 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -30,7 +30,7 @@ Compiler::Compiler() Type::init(llvm::getGlobalContext()); } -void Compiler::createBasicBlocks(const dev::bytes& bytecode) +void Compiler::createBasicBlocks(const bytes& bytecode) { std::set splitPoints; // Sorted collections of instruction indices where basic blocks start/end splitPoints.insert(0); // First basic block @@ -41,8 +41,6 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode) for (auto curr = bytecode.cbegin(); curr != bytecode.cend(); ++curr) { - using dev::eth::Instruction; - ProgramCounter currentPC = curr - bytecode.cbegin(); validJumpTargets[currentPC] = 1; @@ -62,7 +60,7 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode) if (nextInst == Instruction::JUMP || nextInst == Instruction::JUMPI) { // Compute target PC of the jump. - dev::u256 val = 0; + u256 val = 0; for (auto iter = curr + 1; iter < next; ++iter) { val <<= 8; @@ -153,7 +151,7 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode) } } -std::unique_ptr Compiler::compile(const dev::bytes& bytecode) +std::unique_ptr Compiler::compile(const bytes& bytecode) { auto& context = llvm::getGlobalContext(); auto module = std::make_unique("main", context); diff --git a/evmcc/Compiler.h b/evmcc/Compiler.h index 17bed3f78..62337d2de 100644 --- a/evmcc/Compiler.h +++ b/evmcc/Compiler.h @@ -22,11 +22,11 @@ public: Compiler(); - std::unique_ptr compile(const dev::bytes& bytecode); + std::unique_ptr compile(const bytes& bytecode); private: - void createBasicBlocks(const dev::bytes& bytecode); + void createBasicBlocks(const bytes& bytecode); void linkBasicBlocks(); diff --git a/evmcc/ExecutionEngine.cpp b/evmcc/ExecutionEngine.cpp index df2ea74d6..6a494f42a 100644 --- a/evmcc/ExecutionEngine.cpp +++ b/evmcc/ExecutionEngine.cpp @@ -81,14 +81,14 @@ int ExecutionEngine::run(std::unique_ptr _module) exec->finalizeObject(); // Create fake ExtVM interface - auto ext = std::make_unique(); - ext->myAddress = dev::Address(1122334455667788); - ext->caller = dev::Address(0xfacefacefaceface); - ext->origin = dev::Address(101010101010101010); + auto ext = std::make_unique(); + ext->myAddress = Address(1122334455667788); + ext->caller = Address(0xfacefacefaceface); + ext->origin = Address(101010101010101010); ext->value = 0xabcd; ext->gasPrice = 1002; - ext->previousBlock.hash = dev::u256(1003); - ext->currentBlock.coinbaseAddress = dev::Address(1004); + ext->previousBlock.hash = u256(1003); + ext->currentBlock.coinbaseAddress = Address(1004); ext->currentBlock.timestamp = 1005; ext->currentBlock.number = 1006; ext->currentBlock.difficulty = 1007; diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index e9618dcab..a300b586c 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -18,10 +18,10 @@ namespace eth namespace jit { -// TODO: Copy of dev::eth::fromAddress in VM.h -inline dev::u256 fromAddress(dev::Address _a) +// TODO: Copy of fromAddress in VM.h +inline u256 fromAddress(Address _a) { - return (dev::u160)_a; + return (u160)_a; } struct ExtData @@ -288,13 +288,13 @@ EXPORT void ext_calldataload(i256* _index, i256* _value) EXPORT void ext_balance(h256* _address, i256* _value) { - auto u = Runtime::getExt().balance(dev::right160(*_address)); + auto u = Runtime::getExt().balance(right160(*_address)); *_value = eth2llvm(u); } EXPORT void ext_suicide(h256* _address) { - Runtime::getExt().suicide(dev::right160(*_address)); + Runtime::getExt().suicide(right160(*_address)); } EXPORT void ext_create(i256* _endowment, i256* _initOff, i256* _initSize, h256* _address) @@ -308,8 +308,8 @@ EXPORT void ext_create(i256* _endowment, i256* _initOff, i256* _initSize, h256* u256 gas; // TODO: Handle gas auto initOff = static_cast(llvm2eth(*_initOff)); auto initSize = static_cast(llvm2eth(*_initSize)); - auto&& initRef = dev::bytesConstRef(Runtime::getMemory().data() + initOff, initSize); - auto&& onOp = dev::bytesConstRef(); // TODO: Handle that thing + auto&& initRef = bytesConstRef(Runtime::getMemory().data() + initOff, initSize); + auto&& onOp = bytesConstRef(); // TODO: Handle that thing h256 address = ext.create(endowment, &gas, initRef, onOp); *_address = address; } @@ -329,15 +329,15 @@ EXPORT void ext_call(i256* _gas, h256* _receiveAddress, i256* _value, i256* _inO if (ext.balance(ext.myAddress) >= value) { ext.subBalance(value); - auto receiveAddress = dev::right160(*_receiveAddress); + auto receiveAddress = right160(*_receiveAddress); auto inOff = static_cast(llvm2eth(*_inOff)); auto inSize = static_cast(llvm2eth(*_inSize)); auto outOff = static_cast(llvm2eth(*_outOff)); auto outSize = static_cast(llvm2eth(*_outSize)); - auto&& inRef = dev::bytesConstRef(Runtime::getMemory().data() + inOff, inSize); - auto&& outRef = dev::bytesConstRef(Runtime::getMemory().data() + outOff, outSize); - dev::eth::OnOpFunc onOp{}; // TODO: Handle that thing - auto codeAddress = dev::right160(*_codeAddress); + auto&& inRef = bytesConstRef(Runtime::getMemory().data() + inOff, inSize); + auto&& outRef = bytesConstRef(Runtime::getMemory().data() + outOff, outSize); + OnOpFunc onOp{}; // TODO: Handle that thing + auto codeAddress = right160(*_codeAddress); ret = ext.call(receiveAddress, value, inRef, &gas, outRef, onOp, {}, codeAddress); } @@ -349,23 +349,23 @@ EXPORT void ext_sha3(i256* _inOff, i256* _inSize, i256* _ret) { auto inOff = static_cast(llvm2eth(*_inOff)); auto inSize = static_cast(llvm2eth(*_inSize)); - auto dataRef = dev::bytesConstRef(Runtime::getMemory().data() + inOff, inSize); - auto hash = dev::eth::sha3(dataRef); + auto dataRef = bytesConstRef(Runtime::getMemory().data() + inOff, inSize); + auto hash = sha3(dataRef); *_ret = *reinterpret_cast(&hash); } EXPORT void ext_exp(i256* _left, i256* _right, i256* _ret) { - dev::bigint left = llvm2eth(*_left); - dev::bigint right = llvm2eth(*_right); - auto ret = static_cast(boost::multiprecision::powm(left, right, dev::bigint(2) << 256)); + bigint left = llvm2eth(*_left); + bigint right = llvm2eth(*_right); + auto ret = static_cast(boost::multiprecision::powm(left, right, bigint(2) << 256)); *_ret = eth2llvm(ret); } EXPORT unsigned char* ext_codeAt(h256* _addr256) { auto&& ext = Runtime::getExt(); - auto addr = dev::right160(*_addr256); + auto addr = right160(*_addr256); auto& code = ext.codeAt(addr); return const_cast(code.data()); } @@ -373,7 +373,7 @@ EXPORT unsigned char* ext_codeAt(h256* _addr256) EXPORT void ext_codesizeAt(h256* _addr256, i256* _ret) { auto&& ext = Runtime::getExt(); - auto addr = dev::right160(*_addr256); + auto addr = right160(*_addr256); auto& code = ext.codeAt(addr); *_ret = eth2llvm(u256(code.size())); } diff --git a/evmcc/Ext.h b/evmcc/Ext.h index b8b93d61f..227632291 100644 --- a/evmcc/Ext.h +++ b/evmcc/Ext.h @@ -16,7 +16,7 @@ class Ext { public: Ext(llvm::IRBuilder<>& _builder, llvm::Module* module); - static void init(std::unique_ptr _ext); + static void init(std::unique_ptr _ext); llvm::Value* store(llvm::Value* _index); void setStore(llvm::Value* _index, llvm::Value* _value); diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index bfd688c61..f57f2b2c8 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -22,7 +22,7 @@ namespace jit namespace // Helper functions { -uint64_t getStepCost(dev::eth::Instruction inst) // TODO: Add this function to FeeSructure (pull request submitted) +uint64_t getStepCost(Instruction inst) // TODO: Add this function to FeeSructure (pull request submitted) { switch (inst) { diff --git a/evmcc/GasMeter.h b/evmcc/GasMeter.h index c7c1a1bda..88c952acd 100644 --- a/evmcc/GasMeter.h +++ b/evmcc/GasMeter.h @@ -21,7 +21,7 @@ public: void operator=(GasMeter) = delete; /// Count step cost of instruction - void count(dev::eth::Instruction _inst); + void count(Instruction _inst); /// Calculate & count gas cost for SSTORE instruction void countSStore(class Ext& _ext, llvm::Value* _index, llvm::Value* _newValue); diff --git a/evmcc/Memory.h b/evmcc/Memory.h index 73dff7842..24ed81a0c 100644 --- a/evmcc/Memory.h +++ b/evmcc/Memory.h @@ -35,7 +35,7 @@ public: void require(llvm::Value* _offset, llvm::Value* _size); void registerReturnData(llvm::Value* _index, llvm::Value* _size); - static dev::bytesConstRef getReturnData(); + static bytesConstRef getReturnData(); void dump(uint64_t _begin, uint64_t _end = 0); diff --git a/evmcc/Runtime.cpp b/evmcc/Runtime.cpp index a7cc0126e..d85f484b3 100644 --- a/evmcc/Runtime.cpp +++ b/evmcc/Runtime.cpp @@ -19,7 +19,7 @@ extern "C" EXPORT i256 gas; } -Runtime::Runtime(dev::u256 _gas, std::unique_ptr _ext): +Runtime::Runtime(u256 _gas, std::unique_ptr _ext): m_ext(std::move(_ext)) { assert(!g_runtime); @@ -42,12 +42,12 @@ MemoryImpl& Runtime::getMemory() return g_runtime->m_memory; } -dev::eth::ExtVMFace& Runtime::getExt() +ExtVMFace& Runtime::getExt() { return *g_runtime->m_ext; } -dev::u256 Runtime::getGas() +u256 Runtime::getGas() { return llvm2eth(gas); } diff --git a/evmcc/Runtime.h b/evmcc/Runtime.h index b9cfe2309..0312e305b 100644 --- a/evmcc/Runtime.h +++ b/evmcc/Runtime.h @@ -22,12 +22,12 @@ namespace jit { using StackImpl = std::vector; -using MemoryImpl = dev::bytes; +using MemoryImpl = bytes; class Runtime { public: - Runtime(dev::u256 _gas, std::unique_ptr _ext); + Runtime(u256 _gas, std::unique_ptr _ext); ~Runtime(); Runtime(const Runtime&) = delete; @@ -35,13 +35,13 @@ public: static StackImpl& getStack(); static MemoryImpl& getMemory(); - static dev::eth::ExtVMFace& getExt(); - static dev::u256 getGas(); + static ExtVMFace& getExt(); + static u256 getGas(); private: StackImpl m_stack; MemoryImpl m_memory; - std::unique_ptr m_ext; + std::unique_ptr m_ext; }; } diff --git a/evmcc/Utils.cpp b/evmcc/Utils.cpp index 7ad6ca283..0fd9c0e41 100644 --- a/evmcc/Utils.cpp +++ b/evmcc/Utils.cpp @@ -8,9 +8,9 @@ namespace eth namespace jit { -dev::u256 llvm2eth(i256 _i) +u256 llvm2eth(i256 _i) { - dev::u256 u = 0; + u256 u = 0; u |= _i.d; u <<= 64; u |= _i.c; @@ -21,10 +21,10 @@ dev::u256 llvm2eth(i256 _i) return u; } -i256 eth2llvm(dev::u256 _u) +i256 eth2llvm(u256 _u) { i256 i; - dev::u256 mask = 0xFFFFFFFFFFFFFFFF; + u256 mask = 0xFFFFFFFFFFFFFFFF; i.a = static_cast(_u & mask); _u >>= 64; i.b = static_cast(_u & mask); diff --git a/evmcc/Utils.h b/evmcc/Utils.h index 74ad2a4d0..27189d5d0 100644 --- a/evmcc/Utils.h +++ b/evmcc/Utils.h @@ -23,8 +23,8 @@ struct i256 }; static_assert(sizeof(i256) == 32, "Wrong i265 size"); -dev::u256 llvm2eth(i256); -i256 eth2llvm(dev::u256); +u256 llvm2eth(i256); +i256 eth2llvm(u256); struct InsertPointGuard { diff --git a/evmcc/evmcc.cpp b/evmcc/evmcc.cpp index b49a2a372..d8bf9438b 100644 --- a/evmcc/evmcc.cpp +++ b/evmcc/evmcc.cpp @@ -78,7 +78,7 @@ int main(int argc, char** argv) if (opt_show_bytes) { - std::cout << dev::memDump(bytecode) << std::endl; + std::cout << memDump(bytecode) << std::endl; } if (opt_dissassemble) From 3beeb4226e075b4f2a83619f41e1cf6ea552a417 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 15 Oct 2014 17:31:36 +0200 Subject: [PATCH 132/641] Some changes about final/stop block --- evmcc/Compiler.cpp | 15 +++++---------- evmcc/Compiler.h | 13 +++---------- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 5d474a0a8..cc2add6a5 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -24,8 +24,7 @@ namespace jit { Compiler::Compiler() - : m_finalBlock(nullptr) - , m_badJumpBlock(nullptr) + : m_badJumpBlock(nullptr) { Type::init(llvm::getGlobalContext()); } @@ -125,10 +124,9 @@ void Compiler::createBasicBlocks(const bytes& bytecode) basicBlocks.emplace(std::piecewise_construct, std::forward_as_tuple(beginInstIdx), std::forward_as_tuple(beginInstIdx, endInstIdx, m_mainFunc)); } - m_finalBlock = std::make_unique("FinalBlock", m_mainFunc); + m_stopBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Stop", m_mainFunc); m_badJumpBlock = std::make_unique("BadJumpBlock", m_mainFunc); m_jumpTableBlock = std::make_unique("JumpTableBlock", m_mainFunc); - m_outOfGasBlock = std::make_unique("OutOfGas", m_mainFunc); for (auto it = directJumpTargets.cbegin(); it != directJumpTargets.cend(); ++it) { @@ -830,8 +828,8 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) { if (basicBlock.end() == bytecode.size()) { - // Branch from the last regular block to the final block. - builder.CreateBr(m_finalBlock->llvm()); + // Return STOP code + builder.CreateRet(Constant::get(ReturnCode::Stop)); } else { @@ -848,15 +846,12 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) // TODO: move to separate function. // Note: Right now the codegen for special blocks depends only on createBasicBlock(), // not on the codegen for 'regular' blocks. But it has to be done before linkBasicBlocks(). - builder.SetInsertPoint(m_finalBlock->llvm()); + builder.SetInsertPoint(m_stopBB); builder.CreateRet(Constant::get(ReturnCode::Stop)); builder.SetInsertPoint(m_badJumpBlock->llvm()); builder.CreateRet(Constant::get(ReturnCode::BadJumpDestination)); - builder.SetInsertPoint(m_outOfGasBlock->llvm()); - builder.CreateRet(Constant::get(ReturnCode::OutOfGas)); - builder.SetInsertPoint(m_jumpTableBlock->llvm()); if (m_indirectJumpTargets.size() > 0) { diff --git a/evmcc/Compiler.h b/evmcc/Compiler.h index 62337d2de..44eeebae4 100644 --- a/evmcc/Compiler.h +++ b/evmcc/Compiler.h @@ -31,7 +31,7 @@ private: void linkBasicBlocks(); /** - * Maps a program counter pc to a basic block which starts at pc (if any). + * Maps a program counter pc to a basic block that starts at pc (if any). */ std::map basicBlocks; @@ -45,13 +45,8 @@ private: */ std::vector m_indirectJumpTargets; - /// Collection of basic blocks in program - //std::vector m_basicBlocks; - - /** - * Final block for normal (non-exceptional) execution. - */ - std::unique_ptr m_finalBlock; + /// Stop basic block - terminates execution with STOP code (0) + llvm::BasicBlock* m_stopBB = nullptr; /** * Block with a jump table. @@ -63,8 +58,6 @@ private: */ std::unique_ptr m_badJumpBlock; - std::unique_ptr m_outOfGasBlock; - /// Main program function llvm::Function* m_mainFunc = nullptr; }; From 08c7dcc3d294139cda461fd361d3f430521222b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 15 Oct 2014 19:06:35 +0200 Subject: [PATCH 133/641] Placing IRBuilder in Compiler class (for future refactoring) --- evmcc/Compiler.cpp | 177 ++++++++++++++++++++++----------------------- evmcc/Compiler.h | 4 +- 2 files changed, 90 insertions(+), 91 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index cc2add6a5..71ad61493 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -3,7 +3,7 @@ #include -#include +#include #include #include #include @@ -23,10 +23,10 @@ namespace eth namespace jit { -Compiler::Compiler() - : m_badJumpBlock(nullptr) +Compiler::Compiler(): + m_builder(llvm::getGlobalContext()) { - Type::init(llvm::getGlobalContext()); + Type::init(m_builder.getContext()); } void Compiler::createBasicBlocks(const bytes& bytecode) @@ -151,31 +151,29 @@ void Compiler::createBasicBlocks(const bytes& bytecode) std::unique_ptr Compiler::compile(const bytes& bytecode) { - auto& context = llvm::getGlobalContext(); - auto module = std::make_unique("main", context); - llvm::IRBuilder<> builder(context); + auto module = std::make_unique("main", m_builder.getContext()); // Create main function m_mainFunc = llvm::Function::Create(llvm::FunctionType::get(Type::MainReturn, false), llvm::Function::ExternalLinkage, "main", module.get()); // Create the basic blocks. - auto entryBlock = llvm::BasicBlock::Create(context, "entry", m_mainFunc); - builder.SetInsertPoint(entryBlock); + auto entryBlock = llvm::BasicBlock::Create(m_builder.getContext(), "entry", m_mainFunc); + m_builder.SetInsertPoint(entryBlock); createBasicBlocks(bytecode); // Init runtime structures. - GasMeter gasMeter(builder, module.get()); - Memory memory(builder, module.get(), gasMeter); - Ext ext(builder, module.get()); + GasMeter gasMeter(m_builder, module.get()); + Memory memory(m_builder, module.get(), gasMeter); + Ext ext(m_builder, module.get()); - builder.CreateBr(basicBlocks.begin()->second); + m_builder.CreateBr(basicBlocks.begin()->second); for (auto basicBlockPairIt = basicBlocks.begin(); basicBlockPairIt != basicBlocks.end(); ++basicBlockPairIt) { auto& basicBlock = basicBlockPairIt->second; auto& stack = basicBlock.getStack(); - builder.SetInsertPoint(basicBlock); + m_builder.SetInsertPoint(basicBlock); for (auto currentPC = basicBlock.begin(); currentPC != basicBlock.end(); ++currentPC) { @@ -190,7 +188,7 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) { auto lhs = stack.pop(); auto rhs = stack.pop(); - auto result = builder.CreateAdd(lhs, rhs); + auto result = m_builder.CreateAdd(lhs, rhs); stack.push(result); break; } @@ -199,7 +197,7 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) { auto lhs = stack.pop(); auto rhs = stack.pop(); - auto result = builder.CreateSub(lhs, rhs); + auto result = m_builder.CreateSub(lhs, rhs); stack.push(result); break; } @@ -208,10 +206,10 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) { auto lhs256 = stack.pop(); auto rhs256 = stack.pop(); - auto lhs128 = builder.CreateTrunc(lhs256, Type::lowPrecision); - auto rhs128 = builder.CreateTrunc(rhs256, Type::lowPrecision); - auto res128 = builder.CreateMul(lhs128, rhs128); - auto res256 = builder.CreateZExt(res128, Type::i256); + auto lhs128 = m_builder.CreateTrunc(lhs256, Type::lowPrecision); + auto rhs128 = m_builder.CreateTrunc(rhs256, Type::lowPrecision); + auto res128 = m_builder.CreateMul(lhs128, rhs128); + auto res256 = m_builder.CreateZExt(res128, Type::i256); stack.push(res256); break; } @@ -220,10 +218,10 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) { auto lhs256 = stack.pop(); auto rhs256 = stack.pop(); - auto lhs128 = builder.CreateTrunc(lhs256, Type::lowPrecision); - auto rhs128 = builder.CreateTrunc(rhs256, Type::lowPrecision); - auto res128 = builder.CreateUDiv(lhs128, rhs128); - auto res256 = builder.CreateZExt(res128, Type::i256); + auto lhs128 = m_builder.CreateTrunc(lhs256, Type::lowPrecision); + auto rhs128 = m_builder.CreateTrunc(rhs256, Type::lowPrecision); + auto res128 = m_builder.CreateUDiv(lhs128, rhs128); + auto res256 = m_builder.CreateZExt(res128, Type::i256); stack.push(res256); break; } @@ -232,10 +230,10 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) { auto lhs256 = stack.pop(); auto rhs256 = stack.pop(); - auto lhs128 = builder.CreateTrunc(lhs256, Type::lowPrecision); - auto rhs128 = builder.CreateTrunc(rhs256, Type::lowPrecision); - auto res128 = builder.CreateSDiv(lhs128, rhs128); - auto res256 = builder.CreateSExt(res128, Type::i256); + auto lhs128 = m_builder.CreateTrunc(lhs256, Type::lowPrecision); + auto rhs128 = m_builder.CreateTrunc(rhs256, Type::lowPrecision); + auto res128 = m_builder.CreateSDiv(lhs128, rhs128); + auto res256 = m_builder.CreateSExt(res128, Type::i256); stack.push(res256); break; } @@ -244,10 +242,10 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) { auto lhs256 = stack.pop(); auto rhs256 = stack.pop(); - auto lhs128 = builder.CreateTrunc(lhs256, Type::lowPrecision); - auto rhs128 = builder.CreateTrunc(rhs256, Type::lowPrecision); - auto res128 = builder.CreateURem(lhs128, rhs128); - auto res256 = builder.CreateZExt(res128, Type::i256); + auto lhs128 = m_builder.CreateTrunc(lhs256, Type::lowPrecision); + auto rhs128 = m_builder.CreateTrunc(rhs256, Type::lowPrecision); + auto res128 = m_builder.CreateURem(lhs128, rhs128); + auto res256 = m_builder.CreateZExt(res128, Type::i256); stack.push(res256); break; } @@ -256,10 +254,10 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) { auto lhs256 = stack.pop(); auto rhs256 = stack.pop(); - auto lhs128 = builder.CreateTrunc(lhs256, Type::lowPrecision); - auto rhs128 = builder.CreateTrunc(rhs256, Type::lowPrecision); - auto res128 = builder.CreateSRem(lhs128, rhs128); - auto res256 = builder.CreateSExt(res128, Type::i256); + auto lhs128 = m_builder.CreateTrunc(lhs256, Type::lowPrecision); + auto rhs128 = m_builder.CreateTrunc(rhs256, Type::lowPrecision); + auto res128 = m_builder.CreateSRem(lhs128, rhs128); + auto res256 = m_builder.CreateSExt(res128, Type::i256); stack.push(res256); break; } @@ -277,7 +275,7 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) { auto top = stack.pop(); auto zero = Constant::get(0); - auto res = builder.CreateSub(zero, top); + auto res = m_builder.CreateSub(zero, top); stack.push(res); break; } @@ -286,8 +284,8 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) { auto lhs = stack.pop(); auto rhs = stack.pop(); - auto res1 = builder.CreateICmpULT(lhs, rhs); - auto res256 = builder.CreateZExt(res1, Type::i256); + auto res1 = m_builder.CreateICmpULT(lhs, rhs); + auto res256 = m_builder.CreateZExt(res1, Type::i256); stack.push(res256); break; } @@ -296,8 +294,8 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) { auto lhs = stack.pop(); auto rhs = stack.pop(); - auto res1 = builder.CreateICmpUGT(lhs, rhs); - auto res256 = builder.CreateZExt(res1, Type::i256); + auto res1 = m_builder.CreateICmpUGT(lhs, rhs); + auto res256 = m_builder.CreateZExt(res1, Type::i256); stack.push(res256); break; } @@ -306,8 +304,8 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) { auto lhs = stack.pop(); auto rhs = stack.pop(); - auto res1 = builder.CreateICmpSLT(lhs, rhs); - auto res256 = builder.CreateZExt(res1, Type::i256); + auto res1 = m_builder.CreateICmpSLT(lhs, rhs); + auto res256 = m_builder.CreateZExt(res1, Type::i256); stack.push(res256); break; } @@ -316,8 +314,8 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) { auto lhs = stack.pop(); auto rhs = stack.pop(); - auto res1 = builder.CreateICmpSGT(lhs, rhs); - auto res256 = builder.CreateZExt(res1, Type::i256); + auto res1 = m_builder.CreateICmpSGT(lhs, rhs); + auto res256 = m_builder.CreateZExt(res1, Type::i256); stack.push(res256); break; } @@ -326,8 +324,8 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) { auto lhs = stack.pop(); auto rhs = stack.pop(); - auto res1 = builder.CreateICmpEQ(lhs, rhs); - auto res256 = builder.CreateZExt(res1, Type::i256); + auto res1 = m_builder.CreateICmpEQ(lhs, rhs); + auto res256 = m_builder.CreateZExt(res1, Type::i256); stack.push(res256); break; } @@ -335,9 +333,8 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) case Instruction::NOT: { auto top = stack.pop(); - auto zero = Constant::get(0); - auto iszero = builder.CreateICmpEQ(top, zero, "iszero"); - auto result = builder.CreateZExt(iszero, Type::i256); + auto iszero = m_builder.CreateICmpEQ(top, Constant::get(0), "iszero"); + auto result = m_builder.CreateZExt(iszero, Type::i256); stack.push(result); break; } @@ -346,7 +343,7 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) { auto lhs = stack.pop(); auto rhs = stack.pop(); - auto res = builder.CreateAnd(lhs, rhs); + auto res = m_builder.CreateAnd(lhs, rhs); stack.push(res); break; } @@ -355,7 +352,7 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) { auto lhs = stack.pop(); auto rhs = stack.pop(); - auto res = builder.CreateOr(lhs, rhs); + auto res = m_builder.CreateOr(lhs, rhs); stack.push(res); break; } @@ -364,7 +361,7 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) { auto lhs = stack.pop(); auto rhs = stack.pop(); - auto res = builder.CreateXor(lhs, rhs); + auto res = m_builder.CreateXor(lhs, rhs); stack.push(res); break; } @@ -386,12 +383,12 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) // TODO: Shifting by 0 gives wrong results as of this bug http://llvm.org/bugs/show_bug.cgi?id=16439 - auto shbits = builder.CreateShl(byteNum, Constant::get(3)); - value = builder.CreateShl(value, shbits); - value = builder.CreateLShr(value, Constant::get(31 * 8)); + auto shbits = m_builder.CreateShl(byteNum, Constant::get(3)); + value = m_builder.CreateShl(value, shbits); + value = m_builder.CreateLShr(value, Constant::get(31 * 8)); - auto byteNumValid = builder.CreateICmpULT(byteNum, Constant::get(32)); - value = builder.CreateSelect(byteNumValid, value, Constant::get(0)); + auto byteNumValid = m_builder.CreateICmpULT(byteNum, Constant::get(32)); + value = m_builder.CreateSelect(byteNumValid, value, Constant::get(0)); stack.push(value); break; @@ -401,13 +398,13 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) { auto val1 = stack.pop(); auto val2 = stack.pop(); - auto sum = builder.CreateAdd(val1, val2); + auto sum = m_builder.CreateAdd(val1, val2); auto mod = stack.pop(); - auto sum128 = builder.CreateTrunc(sum, Type::lowPrecision); - auto mod128 = builder.CreateTrunc(mod, Type::lowPrecision); - auto res128 = builder.CreateURem(sum128, mod128); - auto res256 = builder.CreateZExt(res128, Type::i256); + auto sum128 = m_builder.CreateTrunc(sum, Type::lowPrecision); + auto mod128 = m_builder.CreateTrunc(mod, Type::lowPrecision); + auto res128 = m_builder.CreateURem(sum128, mod128); + auto res256 = m_builder.CreateZExt(res128, Type::i256); stack.push(res256); break; } @@ -416,13 +413,13 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) { auto val1 = stack.pop(); auto val2 = stack.pop(); - auto prod = builder.CreateMul(val1, val2); + auto prod = m_builder.CreateMul(val1, val2); auto mod = stack.pop(); - auto prod128 = builder.CreateTrunc(prod, Type::lowPrecision); - auto mod128 = builder.CreateTrunc(mod, Type::lowPrecision); - auto res128 = builder.CreateURem(prod128, mod128); - auto res256 = builder.CreateZExt(res128, Type::i256); + auto prod128 = m_builder.CreateTrunc(prod, Type::lowPrecision); + auto mod128 = m_builder.CreateTrunc(mod, Type::lowPrecision); + auto res128 = m_builder.CreateURem(prod128, mod128); + auto res256 = m_builder.CreateZExt(res128, Type::i256); stack.push(res256); break; } @@ -452,7 +449,7 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) value <<= 8; value |= bytecode[currentPC]; } - auto c = builder.getInt(value); + auto c = m_builder.getInt(value); stack.push(c); break; } @@ -543,13 +540,13 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) // The target address is computed at compile time, // just pop it without looking... stack.pop(); - builder.CreateBr(targetBlock->llvm()); + m_builder.CreateBr(targetBlock->llvm()); } else { // FIXME: this get(0) is a temporary workaround to get some of the jump tests running. stack.get(0); - builder.CreateBr(m_jumpTableBlock->llvm()); + m_builder.CreateBr(m_jumpTableBlock->llvm()); } } else // JUMPI @@ -557,7 +554,7 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) stack.swap(1); auto val = stack.pop(); auto zero = Constant::get(0); - auto cond = builder.CreateICmpNE(val, zero, "nonzero"); + auto cond = m_builder.CreateICmpNE(val, zero, "nonzero"); // Assume the basic blocks are properly ordered: auto nextBBIter = basicBlockPairIt; @@ -568,11 +565,11 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) if (targetBlock) { stack.pop(); - builder.CreateCondBr(cond, targetBlock->llvm(), followBlock.llvm()); + m_builder.CreateCondBr(cond, targetBlock->llvm(), followBlock.llvm()); } else { - builder.CreateCondBr(cond, m_jumpTableBlock->llvm(), followBlock.llvm()); + m_builder.CreateCondBr(cond, m_jumpTableBlock->llvm(), followBlock.llvm()); } } @@ -780,10 +777,10 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) gasMeter.commitCostBlock(gas); // Require memory for the max of in and out buffers - auto inSizeReq = builder.CreateAdd(inOff, inSize, "inSizeReq"); - auto outSizeReq = builder.CreateAdd(outOff, outSize, "outSizeReq"); - auto cmp = builder.CreateICmpUGT(inSizeReq, outSizeReq); - auto sizeReq = builder.CreateSelect(cmp, inSizeReq, outSizeReq, "sizeReq"); + auto inSizeReq = m_builder.CreateAdd(inOff, inSize, "inSizeReq"); + auto outSizeReq = m_builder.CreateAdd(outOff, outSize, "outSizeReq"); + auto cmp = m_builder.CreateICmpUGT(inSizeReq, outSizeReq); + auto sizeReq = m_builder.CreateSelect(cmp, inSizeReq, outSizeReq, "sizeReq"); memory.require(sizeReq); auto receiveAddress = codeAddress; @@ -803,7 +800,7 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) memory.registerReturnData(index, size); - builder.CreateRet(Constant::get(ReturnCode::Return)); + m_builder.CreateRet(Constant::get(ReturnCode::Return)); break; } @@ -815,7 +812,7 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) } case Instruction::STOP: { - builder.CreateRet(Constant::get(ReturnCode::Stop)); + m_builder.CreateRet(Constant::get(ReturnCode::Stop)); break; } @@ -824,12 +821,12 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) gasMeter.commitCostBlock(); - if (!builder.GetInsertBlock()->getTerminator()) // If block not terminated + if (!m_builder.GetInsertBlock()->getTerminator()) // If block not terminated { if (basicBlock.end() == bytecode.size()) { // Return STOP code - builder.CreateRet(Constant::get(ReturnCode::Stop)); + m_builder.CreateRet(Constant::get(ReturnCode::Stop)); } else { @@ -837,7 +834,7 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) auto iterCopy = basicBlockPairIt; ++iterCopy; auto& next = iterCopy->second; - builder.CreateBr(next); + m_builder.CreateBr(next); } } } @@ -846,19 +843,19 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) // TODO: move to separate function. // Note: Right now the codegen for special blocks depends only on createBasicBlock(), // not on the codegen for 'regular' blocks. But it has to be done before linkBasicBlocks(). - builder.SetInsertPoint(m_stopBB); - builder.CreateRet(Constant::get(ReturnCode::Stop)); + m_builder.SetInsertPoint(m_stopBB); + m_builder.CreateRet(Constant::get(ReturnCode::Stop)); - builder.SetInsertPoint(m_badJumpBlock->llvm()); - builder.CreateRet(Constant::get(ReturnCode::BadJumpDestination)); + m_builder.SetInsertPoint(m_badJumpBlock->llvm()); + m_builder.CreateRet(Constant::get(ReturnCode::BadJumpDestination)); - builder.SetInsertPoint(m_jumpTableBlock->llvm()); + m_builder.SetInsertPoint(m_jumpTableBlock->llvm()); if (m_indirectJumpTargets.size() > 0) { auto& stack = m_jumpTableBlock->getStack(); auto dest = stack.pop(); - auto switchInstr = builder.CreateSwitch(dest, m_badJumpBlock->llvm(), + auto switchInstr = m_builder.CreateSwitch(dest, m_badJumpBlock->llvm(), m_indirectJumpTargets.size()); for (auto it = m_indirectJumpTargets.cbegin(); it != m_indirectJumpTargets.cend(); ++it) { @@ -869,7 +866,7 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) } else { - builder.CreateBr(m_badJumpBlock->llvm()); + m_builder.CreateBr(m_badJumpBlock->llvm()); } linkBasicBlocks(); diff --git a/evmcc/Compiler.h b/evmcc/Compiler.h index 44eeebae4..1aa54fa18 100644 --- a/evmcc/Compiler.h +++ b/evmcc/Compiler.h @@ -1,7 +1,7 @@ #pragma once -#include +#include #include @@ -30,6 +30,8 @@ private: void linkBasicBlocks(); + llvm::IRBuilder<> m_builder; + /** * Maps a program counter pc to a basic block that starts at pc (if any). */ From 1367f89b84090361faca05768d2257e7a5072e41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 15 Oct 2014 19:27:42 +0200 Subject: [PATCH 134/641] Basic block compilation in separated function --- evmcc/Compiler.cpp | 1200 ++++++++++++++++++++++---------------------- evmcc/Compiler.h | 2 + 2 files changed, 604 insertions(+), 598 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 71ad61493..d5d4e6816 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -172,706 +172,710 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) for (auto basicBlockPairIt = basicBlocks.begin(); basicBlockPairIt != basicBlocks.end(); ++basicBlockPairIt) { auto& basicBlock = basicBlockPairIt->second; - auto& stack = basicBlock.getStack(); - m_builder.SetInsertPoint(basicBlock); + auto iterCopy = basicBlockPairIt; + ++iterCopy; + auto nextBasicBlock = (iterCopy != basicBlocks.end()) ? iterCopy->second.llvm() : nullptr; + compileBasicBlock(basicBlock, bytecode, memory, ext, gasMeter, nextBasicBlock); + } + + // Code for special blocks: + // TODO: move to separate function. + // Note: Right now the codegen for special blocks depends only on createBasicBlock(), + // not on the codegen for 'regular' blocks. But it has to be done before linkBasicBlocks(). + m_builder.SetInsertPoint(m_stopBB); + m_builder.CreateRet(Constant::get(ReturnCode::Stop)); - for (auto currentPC = basicBlock.begin(); currentPC != basicBlock.end(); ++currentPC) + m_builder.SetInsertPoint(m_badJumpBlock->llvm()); + m_builder.CreateRet(Constant::get(ReturnCode::BadJumpDestination)); + + m_builder.SetInsertPoint(m_jumpTableBlock->llvm()); + if (m_indirectJumpTargets.size() > 0) + { + auto& stack = m_jumpTableBlock->getStack(); + + auto dest = stack.pop(); + auto switchInstr = m_builder.CreateSwitch(dest, m_badJumpBlock->llvm(), + m_indirectJumpTargets.size()); + for (auto it = m_indirectJumpTargets.cbegin(); it != m_indirectJumpTargets.cend(); ++it) { - auto inst = static_cast(bytecode[currentPC]); + auto& bb = *it; + auto dest = Constant::get(bb->begin()); + switchInstr->addCase(dest, bb->llvm()); + } + } + else + { + m_builder.CreateBr(m_badJumpBlock->llvm()); + } - gasMeter.count(inst); + linkBasicBlocks(); - switch (inst) - { + return module; +} - case Instruction::ADD: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto result = m_builder.CreateAdd(lhs, rhs); - stack.push(result); - break; - } - case Instruction::SUB: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto result = m_builder.CreateSub(lhs, rhs); - stack.push(result); - break; - } +void Compiler::compileBasicBlock(BasicBlock& basicBlock, const bytes& bytecode, Memory& memory, Ext& ext, GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock) +{ + auto& stack = basicBlock.getStack(); + m_builder.SetInsertPoint(basicBlock.llvm()); - case Instruction::MUL: - { - auto lhs256 = stack.pop(); - auto rhs256 = stack.pop(); - auto lhs128 = m_builder.CreateTrunc(lhs256, Type::lowPrecision); - auto rhs128 = m_builder.CreateTrunc(rhs256, Type::lowPrecision); - auto res128 = m_builder.CreateMul(lhs128, rhs128); - auto res256 = m_builder.CreateZExt(res128, Type::i256); - stack.push(res256); - break; - } + for (auto currentPC = basicBlock.begin(); currentPC != basicBlock.end(); ++currentPC) + { + auto inst = static_cast(bytecode[currentPC]); - case Instruction::DIV: - { - auto lhs256 = stack.pop(); - auto rhs256 = stack.pop(); - auto lhs128 = m_builder.CreateTrunc(lhs256, Type::lowPrecision); - auto rhs128 = m_builder.CreateTrunc(rhs256, Type::lowPrecision); - auto res128 = m_builder.CreateUDiv(lhs128, rhs128); - auto res256 = m_builder.CreateZExt(res128, Type::i256); - stack.push(res256); - break; - } + gasMeter.count(inst); - case Instruction::SDIV: - { - auto lhs256 = stack.pop(); - auto rhs256 = stack.pop(); - auto lhs128 = m_builder.CreateTrunc(lhs256, Type::lowPrecision); - auto rhs128 = m_builder.CreateTrunc(rhs256, Type::lowPrecision); - auto res128 = m_builder.CreateSDiv(lhs128, rhs128); - auto res256 = m_builder.CreateSExt(res128, Type::i256); - stack.push(res256); - break; - } + switch (inst) + { - case Instruction::MOD: - { - auto lhs256 = stack.pop(); - auto rhs256 = stack.pop(); - auto lhs128 = m_builder.CreateTrunc(lhs256, Type::lowPrecision); - auto rhs128 = m_builder.CreateTrunc(rhs256, Type::lowPrecision); - auto res128 = m_builder.CreateURem(lhs128, rhs128); - auto res256 = m_builder.CreateZExt(res128, Type::i256); - stack.push(res256); - break; - } + case Instruction::ADD: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto result = m_builder.CreateAdd(lhs, rhs); + stack.push(result); + break; + } - case Instruction::SMOD: - { - auto lhs256 = stack.pop(); - auto rhs256 = stack.pop(); - auto lhs128 = m_builder.CreateTrunc(lhs256, Type::lowPrecision); - auto rhs128 = m_builder.CreateTrunc(rhs256, Type::lowPrecision); - auto res128 = m_builder.CreateSRem(lhs128, rhs128); - auto res256 = m_builder.CreateSExt(res128, Type::i256); - stack.push(res256); - break; - } + case Instruction::SUB: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto result = m_builder.CreateSub(lhs, rhs); + stack.push(result); + break; + } - case Instruction::EXP: - { - auto left = stack.pop(); - auto right = stack.pop(); - auto ret = ext.exp(left, right); - stack.push(ret); - break; - } + case Instruction::MUL: + { + auto lhs256 = stack.pop(); + auto rhs256 = stack.pop(); + auto lhs128 = m_builder.CreateTrunc(lhs256, Type::lowPrecision); + auto rhs128 = m_builder.CreateTrunc(rhs256, Type::lowPrecision); + auto res128 = m_builder.CreateMul(lhs128, rhs128); + auto res256 = m_builder.CreateZExt(res128, Type::i256); + stack.push(res256); + break; + } - case Instruction::NEG: - { - auto top = stack.pop(); - auto zero = Constant::get(0); - auto res = m_builder.CreateSub(zero, top); - stack.push(res); - break; - } + case Instruction::DIV: + { + auto lhs256 = stack.pop(); + auto rhs256 = stack.pop(); + auto lhs128 = m_builder.CreateTrunc(lhs256, Type::lowPrecision); + auto rhs128 = m_builder.CreateTrunc(rhs256, Type::lowPrecision); + auto res128 = m_builder.CreateUDiv(lhs128, rhs128); + auto res256 = m_builder.CreateZExt(res128, Type::i256); + stack.push(res256); + break; + } - case Instruction::LT: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res1 = m_builder.CreateICmpULT(lhs, rhs); - auto res256 = m_builder.CreateZExt(res1, Type::i256); - stack.push(res256); - break; - } + case Instruction::SDIV: + { + auto lhs256 = stack.pop(); + auto rhs256 = stack.pop(); + auto lhs128 = m_builder.CreateTrunc(lhs256, Type::lowPrecision); + auto rhs128 = m_builder.CreateTrunc(rhs256, Type::lowPrecision); + auto res128 = m_builder.CreateSDiv(lhs128, rhs128); + auto res256 = m_builder.CreateSExt(res128, Type::i256); + stack.push(res256); + break; + } - case Instruction::GT: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res1 = m_builder.CreateICmpUGT(lhs, rhs); - auto res256 = m_builder.CreateZExt(res1, Type::i256); - stack.push(res256); - break; - } + case Instruction::MOD: + { + auto lhs256 = stack.pop(); + auto rhs256 = stack.pop(); + auto lhs128 = m_builder.CreateTrunc(lhs256, Type::lowPrecision); + auto rhs128 = m_builder.CreateTrunc(rhs256, Type::lowPrecision); + auto res128 = m_builder.CreateURem(lhs128, rhs128); + auto res256 = m_builder.CreateZExt(res128, Type::i256); + stack.push(res256); + break; + } - case Instruction::SLT: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res1 = m_builder.CreateICmpSLT(lhs, rhs); - auto res256 = m_builder.CreateZExt(res1, Type::i256); - stack.push(res256); - break; - } + case Instruction::SMOD: + { + auto lhs256 = stack.pop(); + auto rhs256 = stack.pop(); + auto lhs128 = m_builder.CreateTrunc(lhs256, Type::lowPrecision); + auto rhs128 = m_builder.CreateTrunc(rhs256, Type::lowPrecision); + auto res128 = m_builder.CreateSRem(lhs128, rhs128); + auto res256 = m_builder.CreateSExt(res128, Type::i256); + stack.push(res256); + break; + } - case Instruction::SGT: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res1 = m_builder.CreateICmpSGT(lhs, rhs); - auto res256 = m_builder.CreateZExt(res1, Type::i256); - stack.push(res256); - break; - } + case Instruction::EXP: + { + auto left = stack.pop(); + auto right = stack.pop(); + auto ret = ext.exp(left, right); + stack.push(ret); + break; + } - case Instruction::EQ: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res1 = m_builder.CreateICmpEQ(lhs, rhs); - auto res256 = m_builder.CreateZExt(res1, Type::i256); - stack.push(res256); - break; - } + case Instruction::NEG: + { + auto top = stack.pop(); + auto zero = Constant::get(0); + auto res = m_builder.CreateSub(zero, top); + stack.push(res); + break; + } - case Instruction::NOT: - { - auto top = stack.pop(); - auto iszero = m_builder.CreateICmpEQ(top, Constant::get(0), "iszero"); - auto result = m_builder.CreateZExt(iszero, Type::i256); - stack.push(result); - break; - } + case Instruction::LT: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res1 = m_builder.CreateICmpULT(lhs, rhs); + auto res256 = m_builder.CreateZExt(res1, Type::i256); + stack.push(res256); + break; + } - case Instruction::AND: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = m_builder.CreateAnd(lhs, rhs); - stack.push(res); - break; - } + case Instruction::GT: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res1 = m_builder.CreateICmpUGT(lhs, rhs); + auto res256 = m_builder.CreateZExt(res1, Type::i256); + stack.push(res256); + break; + } - case Instruction::OR: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = m_builder.CreateOr(lhs, rhs); - stack.push(res); - break; - } + case Instruction::SLT: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res1 = m_builder.CreateICmpSLT(lhs, rhs); + auto res256 = m_builder.CreateZExt(res1, Type::i256); + stack.push(res256); + break; + } - case Instruction::XOR: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = m_builder.CreateXor(lhs, rhs); - stack.push(res); - break; - } + case Instruction::SGT: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res1 = m_builder.CreateICmpSGT(lhs, rhs); + auto res256 = m_builder.CreateZExt(res1, Type::i256); + stack.push(res256); + break; + } - case Instruction::BYTE: - { - const auto byteNum = stack.pop(); - auto value = stack.pop(); + case Instruction::EQ: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res1 = m_builder.CreateICmpEQ(lhs, rhs); + auto res256 = m_builder.CreateZExt(res1, Type::i256); + stack.push(res256); + break; + } - /* - if (byteNum < 32) - use select - { - value <<= byteNum*8 - value >>= 31*8 - push value - } - else push 0 - */ + case Instruction::NOT: + { + auto top = stack.pop(); + auto iszero = m_builder.CreateICmpEQ(top, Constant::get(0), "iszero"); + auto result = m_builder.CreateZExt(iszero, Type::i256); + stack.push(result); + break; + } - // TODO: Shifting by 0 gives wrong results as of this bug http://llvm.org/bugs/show_bug.cgi?id=16439 + case Instruction::AND: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = m_builder.CreateAnd(lhs, rhs); + stack.push(res); + break; + } - auto shbits = m_builder.CreateShl(byteNum, Constant::get(3)); - value = m_builder.CreateShl(value, shbits); - value = m_builder.CreateLShr(value, Constant::get(31 * 8)); + case Instruction::OR: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = m_builder.CreateOr(lhs, rhs); + stack.push(res); + break; + } - auto byteNumValid = m_builder.CreateICmpULT(byteNum, Constant::get(32)); - value = m_builder.CreateSelect(byteNumValid, value, Constant::get(0)); - stack.push(value); + case Instruction::XOR: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = m_builder.CreateXor(lhs, rhs); + stack.push(res); + break; + } - break; - } + case Instruction::BYTE: + { + const auto byteNum = stack.pop(); + auto value = stack.pop(); - case Instruction::ADDMOD: + /* + if (byteNum < 32) - use select { - auto val1 = stack.pop(); - auto val2 = stack.pop(); - auto sum = m_builder.CreateAdd(val1, val2); - auto mod = stack.pop(); - - auto sum128 = m_builder.CreateTrunc(sum, Type::lowPrecision); - auto mod128 = m_builder.CreateTrunc(mod, Type::lowPrecision); - auto res128 = m_builder.CreateURem(sum128, mod128); - auto res256 = m_builder.CreateZExt(res128, Type::i256); - stack.push(res256); - break; + value <<= byteNum*8 + value >>= 31*8 + push value } + else push 0 + */ - case Instruction::MULMOD: - { - auto val1 = stack.pop(); - auto val2 = stack.pop(); - auto prod = m_builder.CreateMul(val1, val2); - auto mod = stack.pop(); - - auto prod128 = m_builder.CreateTrunc(prod, Type::lowPrecision); - auto mod128 = m_builder.CreateTrunc(mod, Type::lowPrecision); - auto res128 = m_builder.CreateURem(prod128, mod128); - auto res256 = m_builder.CreateZExt(res128, Type::i256); - stack.push(res256); - break; - } + // TODO: Shifting by 0 gives wrong results as of this bug http://llvm.org/bugs/show_bug.cgi?id=16439 - case Instruction::SHA3: - { - auto inOff = stack.pop(); - auto inSize = stack.pop(); - memory.require(inOff, inSize); - auto hash = ext.sha3(inOff, inSize); - stack.push(hash); - } + auto shbits = m_builder.CreateShl(byteNum, Constant::get(3)); + value = m_builder.CreateShl(value, shbits); + value = m_builder.CreateLShr(value, Constant::get(31 * 8)); - case Instruction::POP: - { - stack.pop(); - break; - } + auto byteNumValid = m_builder.CreateICmpULT(byteNum, Constant::get(32)); + value = m_builder.CreateSelect(byteNumValid, value, Constant::get(0)); + stack.push(value); - case Instruction::ANY_PUSH: - { - auto numBytes = static_cast(inst)-static_cast(Instruction::PUSH1) + 1; - auto value = llvm::APInt(256, 0); - for (decltype(numBytes) i = 0; i < numBytes; ++i) // TODO: Use pc as iterator - { - ++currentPC; - value <<= 8; - value |= bytecode[currentPC]; - } - auto c = m_builder.getInt(value); - stack.push(c); - break; - } + break; + } - case Instruction::ANY_DUP: - { - auto index = static_cast(inst)-static_cast(Instruction::DUP1); - stack.dup(index); - break; - } + case Instruction::ADDMOD: + { + auto val1 = stack.pop(); + auto val2 = stack.pop(); + auto sum = m_builder.CreateAdd(val1, val2); + auto mod = stack.pop(); + + auto sum128 = m_builder.CreateTrunc(sum, Type::lowPrecision); + auto mod128 = m_builder.CreateTrunc(mod, Type::lowPrecision); + auto res128 = m_builder.CreateURem(sum128, mod128); + auto res256 = m_builder.CreateZExt(res128, Type::i256); + stack.push(res256); + break; + } - case Instruction::ANY_SWAP: - { - auto index = static_cast(inst)-static_cast(Instruction::SWAP1) + 1; - stack.swap(index); - break; - } + case Instruction::MULMOD: + { + auto val1 = stack.pop(); + auto val2 = stack.pop(); + auto prod = m_builder.CreateMul(val1, val2); + auto mod = stack.pop(); + + auto prod128 = m_builder.CreateTrunc(prod, Type::lowPrecision); + auto mod128 = m_builder.CreateTrunc(mod, Type::lowPrecision); + auto res128 = m_builder.CreateURem(prod128, mod128); + auto res256 = m_builder.CreateZExt(res128, Type::i256); + stack.push(res256); + break; + } - case Instruction::MLOAD: - { - auto addr = stack.pop(); - auto word = memory.loadWord(addr); - stack.push(word); - break; - } + case Instruction::SHA3: + { + auto inOff = stack.pop(); + auto inSize = stack.pop(); + memory.require(inOff, inSize); + auto hash = ext.sha3(inOff, inSize); + stack.push(hash); + } - case Instruction::MSTORE: - { - auto addr = stack.pop(); - auto word = stack.pop(); - memory.storeWord(addr, word); - break; - } + case Instruction::POP: + { + stack.pop(); + break; + } - case Instruction::MSTORE8: + case Instruction::ANY_PUSH: + { + auto numBytes = static_cast(inst)-static_cast(Instruction::PUSH1) + 1; + auto value = llvm::APInt(256, 0); + for (decltype(numBytes) i = 0; i < numBytes; ++i) // TODO: Use pc as iterator { - auto addr = stack.pop(); - auto word = stack.pop(); - memory.storeByte(addr, word); - break; + ++currentPC; + value <<= 8; + value |= bytecode[currentPC]; } + auto c = m_builder.getInt(value); + stack.push(c); + break; + } - case Instruction::MSIZE: - { - auto word = memory.getSize(); - stack.push(word); - break; - } + case Instruction::ANY_DUP: + { + auto index = static_cast(inst)-static_cast(Instruction::DUP1); + stack.dup(index); + break; + } - case Instruction::SLOAD: - { - auto index = stack.pop(); - auto value = ext.store(index); - stack.push(value); - break; - } + case Instruction::ANY_SWAP: + { + auto index = static_cast(inst)-static_cast(Instruction::SWAP1) + 1; + stack.swap(index); + break; + } - case Instruction::SSTORE: - { - auto index = stack.pop(); - auto value = stack.pop(); - gasMeter.countSStore(ext, index, value); - ext.setStore(index, value); - break; - } + case Instruction::MLOAD: + { + auto addr = stack.pop(); + auto word = memory.loadWord(addr); + stack.push(word); + break; + } - case Instruction::JUMP: - case Instruction::JUMPI: - { - // Generate direct jump iff: - // 1. this is not the first instruction in the block - // 2. m_directJumpTargets[currentPC] is defined (meaning that the previous instruction is a PUSH) - // Otherwise generate a indirect jump (a switch). - BasicBlock* targetBlock = nullptr; - if (currentPC != basicBlock.begin()) - { - auto pairIter = m_directJumpTargets.find(currentPC); - if (pairIter != m_directJumpTargets.end()) - { - targetBlock = pairIter->second; - } - } + case Instruction::MSTORE: + { + auto addr = stack.pop(); + auto word = stack.pop(); + memory.storeWord(addr, word); + break; + } - if (inst == Instruction::JUMP) - { - if (targetBlock) - { - // The target address is computed at compile time, - // just pop it without looking... - stack.pop(); - m_builder.CreateBr(targetBlock->llvm()); - } - else - { - // FIXME: this get(0) is a temporary workaround to get some of the jump tests running. - stack.get(0); - m_builder.CreateBr(m_jumpTableBlock->llvm()); - } - } - else // JUMPI - { - stack.swap(1); - auto val = stack.pop(); - auto zero = Constant::get(0); - auto cond = m_builder.CreateICmpNE(val, zero, "nonzero"); - - // Assume the basic blocks are properly ordered: - auto nextBBIter = basicBlockPairIt; - ++nextBBIter; - assert (nextBBIter != basicBlocks.end()); - auto& followBlock = nextBBIter->second; - - if (targetBlock) - { - stack.pop(); - m_builder.CreateCondBr(cond, targetBlock->llvm(), followBlock.llvm()); - } - else - { - m_builder.CreateCondBr(cond, m_jumpTableBlock->llvm(), followBlock.llvm()); - } - } + case Instruction::MSTORE8: + { + auto addr = stack.pop(); + auto word = stack.pop(); + memory.storeByte(addr, word); + break; + } - break; - } + case Instruction::MSIZE: + { + auto word = memory.getSize(); + stack.push(word); + break; + } - case Instruction::JUMPDEST: - { - // Extra asserts just in case. - assert(currentPC == basicBlock.begin()); - break; - } + case Instruction::SLOAD: + { + auto index = stack.pop(); + auto value = ext.store(index); + stack.push(value); + break; + } - case Instruction::PC: - { - auto value = Constant::get(currentPC); - stack.push(value); - break; - } + case Instruction::SSTORE: + { + auto index = stack.pop(); + auto value = stack.pop(); + gasMeter.countSStore(ext, index, value); + ext.setStore(index, value); + break; + } - case Instruction::GAS: - { - stack.push(gasMeter.getGas()); - break; + case Instruction::JUMP: + case Instruction::JUMPI: + { + // Generate direct jump iff: + // 1. this is not the first instruction in the block + // 2. m_directJumpTargets[currentPC] is defined (meaning that the previous instruction is a PUSH) + // Otherwise generate a indirect jump (a switch). + BasicBlock* targetBlock = nullptr; + if (currentPC != basicBlock.begin()) + { + auto pairIter = m_directJumpTargets.find(currentPC); + if (pairIter != m_directJumpTargets.end()) + { + targetBlock = pairIter->second; + } } - case Instruction::ADDRESS: + if (inst == Instruction::JUMP) { - auto value = ext.address(); - stack.push(value); - break; + if (targetBlock) + { + // The target address is computed at compile time, + // just pop it without looking... + stack.pop(); + m_builder.CreateBr(targetBlock->llvm()); + } + else + { + // FIXME: this get(0) is a temporary workaround to get some of the jump tests running. + stack.get(0); + m_builder.CreateBr(m_jumpTableBlock->llvm()); + } } - - case Instruction::BALANCE: + else // JUMPI { - auto address = stack.pop(); - auto value = ext.balance(address); - stack.push(value); - break; - } + stack.swap(1); + auto val = stack.pop(); + auto zero = Constant::get(0); + auto cond = m_builder.CreateICmpNE(val, zero, "nonzero"); - case Instruction::CALLER: - { - auto value = ext.caller(); - stack.push(value); - break; - } + // Assume the basic blocks are properly ordered: + assert(nextBasicBlock); // FIXME: JUMPI can be last instruction - case Instruction::ORIGIN: - { - auto value = ext.origin(); - stack.push(value); - break; + if (targetBlock) + { + stack.pop(); + m_builder.CreateCondBr(cond, targetBlock->llvm(), nextBasicBlock); + } + else + { + m_builder.CreateCondBr(cond, m_jumpTableBlock->llvm(), nextBasicBlock); + } } - case Instruction::CALLVALUE: - { - auto value = ext.callvalue(); - stack.push(value); - break; - } + break; + } - case Instruction::CALLDATASIZE: - { - auto value = ext.calldatasize(); - stack.push(value); - break; - } + case Instruction::JUMPDEST: + { + // Extra asserts just in case. + assert(currentPC == basicBlock.begin()); + break; + } - case Instruction::CODESIZE: - { - auto value = ext.codesize(); - stack.push(value); - break; - } + case Instruction::PC: + { + auto value = Constant::get(currentPC); + stack.push(value); + break; + } - case Instruction::EXTCODESIZE: - { - auto addr = stack.pop(); - auto value = ext.codesizeAt(addr); - stack.push(value); - break; - } + case Instruction::GAS: + { + stack.push(gasMeter.getGas()); + break; + } - case Instruction::CALLDATACOPY: - { - auto destMemIdx = stack.pop(); - auto srcIdx = stack.pop(); - auto reqBytes = stack.pop(); + case Instruction::ADDRESS: + { + auto value = ext.address(); + stack.push(value); + break; + } - auto srcPtr = ext.calldata(); - auto srcSize = ext.calldatasize(); + case Instruction::BALANCE: + { + auto address = stack.pop(); + auto value = ext.balance(address); + stack.push(value); + break; + } - memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); - break; - } + case Instruction::CALLER: + { + auto value = ext.caller(); + stack.push(value); + break; + } - case Instruction::CODECOPY: - { - auto destMemIdx = stack.pop(); - auto srcIdx = stack.pop(); - auto reqBytes = stack.pop(); + case Instruction::ORIGIN: + { + auto value = ext.origin(); + stack.push(value); + break; + } - auto srcPtr = ext.code(); - auto srcSize = ext.codesize(); + case Instruction::CALLVALUE: + { + auto value = ext.callvalue(); + stack.push(value); + break; + } - memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); - break; - } + case Instruction::CALLDATASIZE: + { + auto value = ext.calldatasize(); + stack.push(value); + break; + } - case Instruction::EXTCODECOPY: - { - auto extAddr = stack.pop(); - auto destMemIdx = stack.pop(); - auto srcIdx = stack.pop(); - auto reqBytes = stack.pop(); + case Instruction::CODESIZE: + { + auto value = ext.codesize(); + stack.push(value); + break; + } - auto srcPtr = ext.codeAt(extAddr); - auto srcSize = ext.codesizeAt(extAddr); + case Instruction::EXTCODESIZE: + { + auto addr = stack.pop(); + auto value = ext.codesizeAt(addr); + stack.push(value); + break; + } - memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); - break; - } + case Instruction::CALLDATACOPY: + { + auto destMemIdx = stack.pop(); + auto srcIdx = stack.pop(); + auto reqBytes = stack.pop(); - case Instruction::CALLDATALOAD: - { - auto index = stack.pop(); - auto value = ext.calldataload(index); - stack.push(value); - break; - } + auto srcPtr = ext.calldata(); + auto srcSize = ext.calldatasize(); - case Instruction::GASPRICE: - { - auto value = ext.gasprice(); - stack.push(value); - break; - } + memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); + break; + } - case Instruction::PREVHASH: - { - auto value = ext.prevhash(); - stack.push(value); - break; - } + case Instruction::CODECOPY: + { + auto destMemIdx = stack.pop(); + auto srcIdx = stack.pop(); + auto reqBytes = stack.pop(); - case Instruction::COINBASE: - { - auto value = ext.coinbase(); - stack.push(value); - break; - } + auto srcPtr = ext.code(); + auto srcSize = ext.codesize(); - case Instruction::TIMESTAMP: - { - auto value = ext.timestamp(); - stack.push(value); - break; - } + memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); + break; + } - case Instruction::NUMBER: - { - auto value = ext.number(); - stack.push(value); - break; - } + case Instruction::EXTCODECOPY: + { + auto extAddr = stack.pop(); + auto destMemIdx = stack.pop(); + auto srcIdx = stack.pop(); + auto reqBytes = stack.pop(); - case Instruction::DIFFICULTY: - { - auto value = ext.difficulty(); - stack.push(value); - break; - } + auto srcPtr = ext.codeAt(extAddr); + auto srcSize = ext.codesizeAt(extAddr); - case Instruction::GASLIMIT: - { - auto value = ext.gaslimit(); - stack.push(value); - break; - } + memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); + break; + } - case Instruction::CREATE: - { - auto endowment = stack.pop(); - auto initOff = stack.pop(); - auto initSize = stack.pop(); - memory.require(initOff, initSize); + case Instruction::CALLDATALOAD: + { + auto index = stack.pop(); + auto value = ext.calldataload(index); + stack.push(value); + break; + } - auto address = ext.create(endowment, initOff, initSize); - stack.push(address); - break; - } + case Instruction::GASPRICE: + { + auto value = ext.gasprice(); + stack.push(value); + break; + } - case Instruction::CALL: - case Instruction::CALLCODE: - { - auto gas = stack.pop(); - auto codeAddress = stack.pop(); - auto value = stack.pop(); - auto inOff = stack.pop(); - auto inSize = stack.pop(); - auto outOff = stack.pop(); - auto outSize = stack.pop(); - - gasMeter.commitCostBlock(gas); - - // Require memory for the max of in and out buffers - auto inSizeReq = m_builder.CreateAdd(inOff, inSize, "inSizeReq"); - auto outSizeReq = m_builder.CreateAdd(outOff, outSize, "outSizeReq"); - auto cmp = m_builder.CreateICmpUGT(inSizeReq, outSizeReq); - auto sizeReq = m_builder.CreateSelect(cmp, inSizeReq, outSizeReq, "sizeReq"); - memory.require(sizeReq); - - auto receiveAddress = codeAddress; - if (inst == Instruction::CALLCODE) - receiveAddress = ext.address(); - - auto ret = ext.call(gas, receiveAddress, value, inOff, inSize, outOff, outSize, codeAddress); - gasMeter.giveBack(gas); - stack.push(ret); - break; - } + case Instruction::PREVHASH: + { + auto value = ext.prevhash(); + stack.push(value); + break; + } - case Instruction::RETURN: - { - auto index = stack.pop(); - auto size = stack.pop(); + case Instruction::COINBASE: + { + auto value = ext.coinbase(); + stack.push(value); + break; + } - memory.registerReturnData(index, size); + case Instruction::TIMESTAMP: + { + auto value = ext.timestamp(); + stack.push(value); + break; + } - m_builder.CreateRet(Constant::get(ReturnCode::Return)); - break; - } + case Instruction::NUMBER: + { + auto value = ext.number(); + stack.push(value); + break; + } - case Instruction::SUICIDE: - { - auto address = stack.pop(); - ext.suicide(address); - // Fall through - } - case Instruction::STOP: - { - m_builder.CreateRet(Constant::get(ReturnCode::Stop)); - break; - } + case Instruction::DIFFICULTY: + { + auto value = ext.difficulty(); + stack.push(value); + break; + } - } + case Instruction::GASLIMIT: + { + auto value = ext.gaslimit(); + stack.push(value); + break; } - gasMeter.commitCostBlock(); + case Instruction::CREATE: + { + auto endowment = stack.pop(); + auto initOff = stack.pop(); + auto initSize = stack.pop(); + memory.require(initOff, initSize); + + auto address = ext.create(endowment, initOff, initSize); + stack.push(address); + break; + } - if (!m_builder.GetInsertBlock()->getTerminator()) // If block not terminated + case Instruction::CALL: + case Instruction::CALLCODE: { - if (basicBlock.end() == bytecode.size()) - { - // Return STOP code - m_builder.CreateRet(Constant::get(ReturnCode::Stop)); - } - else - { - // Branch to the next block. - auto iterCopy = basicBlockPairIt; - ++iterCopy; - auto& next = iterCopy->second; - m_builder.CreateBr(next); - } + auto gas = stack.pop(); + auto codeAddress = stack.pop(); + auto value = stack.pop(); + auto inOff = stack.pop(); + auto inSize = stack.pop(); + auto outOff = stack.pop(); + auto outSize = stack.pop(); + + gasMeter.commitCostBlock(gas); + + // Require memory for the max of in and out buffers + auto inSizeReq = m_builder.CreateAdd(inOff, inSize, "inSizeReq"); + auto outSizeReq = m_builder.CreateAdd(outOff, outSize, "outSizeReq"); + auto cmp = m_builder.CreateICmpUGT(inSizeReq, outSizeReq); + auto sizeReq = m_builder.CreateSelect(cmp, inSizeReq, outSizeReq, "sizeReq"); + memory.require(sizeReq); + + auto receiveAddress = codeAddress; + if (inst == Instruction::CALLCODE) + receiveAddress = ext.address(); + + auto ret = ext.call(gas, receiveAddress, value, inOff, inSize, outOff, outSize, codeAddress); + gasMeter.giveBack(gas); + stack.push(ret); + break; } - } - // Code for special blocks: - // TODO: move to separate function. - // Note: Right now the codegen for special blocks depends only on createBasicBlock(), - // not on the codegen for 'regular' blocks. But it has to be done before linkBasicBlocks(). - m_builder.SetInsertPoint(m_stopBB); - m_builder.CreateRet(Constant::get(ReturnCode::Stop)); + case Instruction::RETURN: + { + auto index = stack.pop(); + auto size = stack.pop(); - m_builder.SetInsertPoint(m_badJumpBlock->llvm()); - m_builder.CreateRet(Constant::get(ReturnCode::BadJumpDestination)); + memory.registerReturnData(index, size); - m_builder.SetInsertPoint(m_jumpTableBlock->llvm()); - if (m_indirectJumpTargets.size() > 0) - { - auto& stack = m_jumpTableBlock->getStack(); + m_builder.CreateRet(Constant::get(ReturnCode::Return)); + break; + } - auto dest = stack.pop(); - auto switchInstr = m_builder.CreateSwitch(dest, m_badJumpBlock->llvm(), - m_indirectJumpTargets.size()); - for (auto it = m_indirectJumpTargets.cbegin(); it != m_indirectJumpTargets.cend(); ++it) + case Instruction::SUICIDE: { - auto& bb = *it; - auto dest = Constant::get(bb->begin()); - switchInstr->addCase(dest, bb->llvm()); + auto address = stack.pop(); + ext.suicide(address); + // Fall through + } + case Instruction::STOP: + { + m_builder.CreateRet(Constant::get(ReturnCode::Stop)); + break; + } + } - } - else - { - m_builder.CreateBr(m_badJumpBlock->llvm()); } - linkBasicBlocks(); + gasMeter.commitCostBlock(); - return module; + if (!m_builder.GetInsertBlock()->getTerminator()) // If block not terminated + { + if (basicBlock.end() == bytecode.size()) + { + // Return STOP code + m_builder.CreateRet(Constant::get(ReturnCode::Stop)); + } + else + { + // Branch to the next block. + assert(nextBasicBlock); + m_builder.CreateBr(nextBasicBlock); + } + } } diff --git a/evmcc/Compiler.h b/evmcc/Compiler.h index 1aa54fa18..1a0e61ca1 100644 --- a/evmcc/Compiler.h +++ b/evmcc/Compiler.h @@ -28,6 +28,8 @@ private: void createBasicBlocks(const bytes& bytecode); + void compileBasicBlock(BasicBlock& basicBlock, const bytes& bytecode, class Memory& memory, class Ext& ext, class GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock); + void linkBasicBlocks(); llvm::IRBuilder<> m_builder; From 837f17cea46f338ccafad43ada409e8586795db8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 15 Oct 2014 19:34:55 +0200 Subject: [PATCH 135/641] Cleanup block terminator generation --- evmcc/Compiler.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index d5d4e6816..77db366cf 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -862,19 +862,12 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, const bytes& bytecode, gasMeter.commitCostBlock(); - if (!m_builder.GetInsertBlock()->getTerminator()) // If block not terminated + if (!basicBlock.llvm()->getTerminator()) // If block not terminated { - if (basicBlock.end() == bytecode.size()) - { - // Return STOP code - m_builder.CreateRet(Constant::get(ReturnCode::Stop)); - } + if (nextBasicBlock) + m_builder.CreateBr(nextBasicBlock); // Branch to the next block else - { - // Branch to the next block. - assert(nextBasicBlock); - m_builder.CreateBr(nextBasicBlock); - } + m_builder.CreateRet(Constant::get(ReturnCode::Stop)); // Return STOP code } } From 83642fe9ded7d389b8e10607d0f3fa69423d8a83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 16 Oct 2014 13:05:51 +0200 Subject: [PATCH 136/641] Introducing CompilerHelper - a base class for... compiler helper classes like Memory, GasMeter, etc. --- evmcc/Compiler.cpp | 2 +- evmcc/CompilerHelper.cpp | 13 +++++++++++++ evmcc/CompilerHelper.h | 34 ++++++++++++++++++++++++++++++++++ evmcc/Ext.cpp | 4 ++-- evmcc/Ext.h | 9 +++------ evmcc/GasMeter.cpp | 2 +- evmcc/GasMeter.h | 11 ++++------- evmcc/Memory.cpp | 2 +- evmcc/Memory.h | 14 ++++---------- windows/evmcc.vcxproj | 6 +++++- windows/evmcc.vcxproj.filters | 2 ++ 11 files changed, 70 insertions(+), 29 deletions(-) create mode 100644 evmcc/CompilerHelper.cpp create mode 100644 evmcc/CompilerHelper.h diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 77db366cf..f48534959 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -714,7 +714,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, const bytes& bytecode, auto srcIdx = stack.pop(); auto reqBytes = stack.pop(); - auto srcPtr = ext.code(); + auto srcPtr = ext.code(); // TODO: Code & its size are constants, feature #80814234 auto srcSize = ext.codesize(); memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); diff --git a/evmcc/CompilerHelper.cpp b/evmcc/CompilerHelper.cpp new file mode 100644 index 000000000..a657a443a --- /dev/null +++ b/evmcc/CompilerHelper.cpp @@ -0,0 +1,13 @@ + +#include "CompilerHelper.h" + +namespace dev +{ +namespace eth +{ +namespace jit +{ + +} +} +} diff --git a/evmcc/CompilerHelper.h b/evmcc/CompilerHelper.h new file mode 100644 index 000000000..39cbc7c0d --- /dev/null +++ b/evmcc/CompilerHelper.h @@ -0,0 +1,34 @@ + +#pragma once + +#include + + +namespace dev +{ +namespace eth +{ +namespace jit +{ + +class CompilerHelper +{ +protected: + CompilerHelper(llvm::IRBuilder<>& _builder, llvm::Module* _module): + m_builder(_builder), + m_module(_module) + {} + + CompilerHelper(const CompilerHelper&) = delete; + void operator=(CompilerHelper) = delete; + + /// Reference to parent compiler IR builder + llvm::IRBuilder<>& m_builder; + + /// Reference to the IR module being compiled + llvm::Module* m_module; +}; + +} +} +} diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index a300b586c..43b5e9186 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -43,8 +43,8 @@ struct ExtData const byte* code; }; -Ext::Ext(llvm::IRBuilder<>& _builder, llvm::Module* module) - : m_builder(_builder) +Ext::Ext(llvm::IRBuilder<>& _builder, llvm::Module* module): + CompilerHelper(_builder, module) { auto&& ctx = _builder.getContext(); diff --git a/evmcc/Ext.h b/evmcc/Ext.h index 227632291..755c8bd16 100644 --- a/evmcc/Ext.h +++ b/evmcc/Ext.h @@ -1,10 +1,10 @@ #pragma once -#include - #include +#include "CompilerHelper.h" + namespace dev { namespace eth @@ -12,11 +12,10 @@ namespace eth namespace jit { -class Ext +class Ext : public CompilerHelper { public: Ext(llvm::IRBuilder<>& _builder, llvm::Module* module); - static void init(std::unique_ptr _ext); llvm::Value* store(llvm::Value* _index); void setStore(llvm::Value* _index, llvm::Value* _value); @@ -54,8 +53,6 @@ private: llvm::Value* bswap(llvm::Value*); private: - llvm::IRBuilder<>& m_builder; - llvm::Value* m_args[2]; llvm::Value* m_arg2; llvm::Value* m_arg3; diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index f57f2b2c8..ef3665bb4 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -81,7 +81,7 @@ bool isCostBlockEnd(Instruction _inst) } GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module) : - m_builder(_builder) + CompilerHelper(_builder, _module) { m_gas = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "gas"); m_gas->setUnnamedAddr(true); // Address is not important diff --git a/evmcc/GasMeter.h b/evmcc/GasMeter.h index 88c952acd..cea4a2b44 100644 --- a/evmcc/GasMeter.h +++ b/evmcc/GasMeter.h @@ -1,10 +1,10 @@ #pragma once -#include - #include +#include "CompilerHelper.h" + namespace dev { namespace eth @@ -12,14 +12,11 @@ namespace eth namespace jit { -class GasMeter +class GasMeter : public CompilerHelper { public: GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module); - GasMeter(const GasMeter&) = delete; - void operator=(GasMeter) = delete; - /// Count step cost of instruction void count(Instruction _inst); @@ -42,7 +39,7 @@ private: /// Cumulative gas cost of a block of instructions /// @TODO Handle overflow uint64_t m_blockCost = 0; - llvm::IRBuilder<>& m_builder; + llvm::CallInst* m_checkCall = nullptr; llvm::GlobalVariable* m_gas; llvm::Function* m_gasCheckFunc; diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index 7c742eb81..a000816e7 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -23,7 +23,7 @@ namespace jit { Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module, GasMeter& _gasMeter): - m_builder(_builder) + CompilerHelper(_builder, _module) { auto i64Ty = m_builder.getInt64Ty(); llvm::Type* argTypes[] = {i64Ty, i64Ty}; diff --git a/evmcc/Memory.h b/evmcc/Memory.h index 24ed81a0c..3d2db56ee 100644 --- a/evmcc/Memory.h +++ b/evmcc/Memory.h @@ -1,9 +1,9 @@ #pragma once -#include - #include +#include "CompilerHelper.h" + namespace dev { namespace eth @@ -11,14 +11,10 @@ namespace eth namespace jit { -class GasMeter; - -class Memory +class Memory : public CompilerHelper { public: - Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module, GasMeter& _gasMeter); - Memory(const Memory&) = delete; - void operator=(Memory) = delete; + Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module, class GasMeter& _gasMeter); llvm::Value* loadWord(llvm::Value* _addr); void storeWord(llvm::Value* _addr, llvm::Value* _word); @@ -44,8 +40,6 @@ private: llvm::Function* createRequireFunc(llvm::Module* _module, GasMeter& _gasMeter); private: - llvm::IRBuilder<>& m_builder; - llvm::GlobalVariable* m_data; llvm::GlobalVariable* m_size; diff --git a/windows/evmcc.vcxproj b/windows/evmcc.vcxproj index dbd9d1b57..efa7a6f20 100644 --- a/windows/evmcc.vcxproj +++ b/windows/evmcc.vcxproj @@ -21,6 +21,7 @@ + @@ -33,6 +34,7 @@ + @@ -123,8 +125,9 @@ Disabled WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) true - ../ + ../../llvm-3.5.0/include;../../builds/llvm3.5/include;%(AdditionalIncludeDirectories) false + false Console @@ -144,6 +147,7 @@ ../../llvm-3.5.0/include;../../builds/llvm3.5/include;%(AdditionalIncludeDirectories) 4068;4244;4267;4800 false + false Console diff --git a/windows/evmcc.vcxproj.filters b/windows/evmcc.vcxproj.filters index f84ec6ca3..adfcfaf60 100644 --- a/windows/evmcc.vcxproj.filters +++ b/windows/evmcc.vcxproj.filters @@ -11,6 +11,7 @@ + @@ -22,5 +23,6 @@ + \ No newline at end of file From cbab6546789823ab552d9fb0eaa7970dc447b827 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 16 Oct 2014 13:16:18 +0200 Subject: [PATCH 137/641] Get IR module from IR builder --- evmcc/Compiler.cpp | 6 +++--- evmcc/CompilerHelper.cpp | 7 +++++++ evmcc/CompilerHelper.h | 5 +---- evmcc/Ext.cpp | 5 +++-- evmcc/Ext.h | 2 +- evmcc/GasMeter.cpp | 12 ++++++------ evmcc/GasMeter.h | 2 +- evmcc/Memory.cpp | 24 ++++++++++++------------ evmcc/Memory.h | 2 +- 9 files changed, 35 insertions(+), 30 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index f48534959..bbd5cf90b 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -163,9 +163,9 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) createBasicBlocks(bytecode); // Init runtime structures. - GasMeter gasMeter(m_builder, module.get()); - Memory memory(m_builder, module.get(), gasMeter); - Ext ext(m_builder, module.get()); + GasMeter gasMeter(m_builder); + Memory memory(m_builder, gasMeter); + Ext ext(m_builder); m_builder.CreateBr(basicBlocks.begin()->second); diff --git a/evmcc/CompilerHelper.cpp b/evmcc/CompilerHelper.cpp index a657a443a..7b29690b7 100644 --- a/evmcc/CompilerHelper.cpp +++ b/evmcc/CompilerHelper.cpp @@ -1,6 +1,8 @@ #include "CompilerHelper.h" +#include + namespace dev { namespace eth @@ -8,6 +10,11 @@ namespace eth namespace jit { +CompilerHelper::CompilerHelper(llvm::IRBuilder<>& _builder) : + m_builder(_builder), + m_module(_builder.GetInsertBlock()->getParent()->getParent()) +{} + } } } diff --git a/evmcc/CompilerHelper.h b/evmcc/CompilerHelper.h index 39cbc7c0d..e10937277 100644 --- a/evmcc/CompilerHelper.h +++ b/evmcc/CompilerHelper.h @@ -14,10 +14,7 @@ namespace jit class CompilerHelper { protected: - CompilerHelper(llvm::IRBuilder<>& _builder, llvm::Module* _module): - m_builder(_builder), - m_module(_module) - {} + CompilerHelper(llvm::IRBuilder<>& _builder); CompilerHelper(const CompilerHelper&) = delete; void operator=(CompilerHelper) = delete; diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index 43b5e9186..f3f7699cd 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -43,10 +43,11 @@ struct ExtData const byte* code; }; -Ext::Ext(llvm::IRBuilder<>& _builder, llvm::Module* module): - CompilerHelper(_builder, module) +Ext::Ext(llvm::IRBuilder<>& _builder): + CompilerHelper(_builder) { auto&& ctx = _builder.getContext(); + auto module = m_module; auto i256Ty = m_builder.getIntNTy(256); auto i256PtrTy = i256Ty->getPointerTo(); diff --git a/evmcc/Ext.h b/evmcc/Ext.h index 755c8bd16..04c17fdac 100644 --- a/evmcc/Ext.h +++ b/evmcc/Ext.h @@ -15,7 +15,7 @@ namespace jit class Ext : public CompilerHelper { public: - Ext(llvm::IRBuilder<>& _builder, llvm::Module* module); + Ext(llvm::IRBuilder<>& _builder); llvm::Value* store(llvm::Value* _index); void setStore(llvm::Value* _index, llvm::Value* _value); diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index ef3665bb4..206e5c805 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -80,13 +80,13 @@ bool isCostBlockEnd(Instruction _inst) } -GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module) : - CompilerHelper(_builder, _module) +GasMeter::GasMeter(llvm::IRBuilder<>& _builder) : + CompilerHelper(_builder) { - m_gas = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "gas"); + m_gas = new llvm::GlobalVariable(*m_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "gas"); m_gas->setUnnamedAddr(true); // Address is not important - m_gasCheckFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "gas.check", _module); + m_gasCheckFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "gas.check", m_module); InsertPointGuard guard(m_builder); auto checkBB = llvm::BasicBlock::Create(_builder.getContext(), "Check", m_gasCheckFunc); @@ -103,9 +103,9 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module) : m_builder.SetInsertPoint(outOfGasBB); //auto longjmpFunc = llvm::Intrinsic::getDeclaration(_module, llvm::Intrinsic::eh_sjlj_longjmp); - auto extJmpBuf = new llvm::GlobalVariable(*_module, Type::BytePtr, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "rt_jmpBuf"); + auto extJmpBuf = new llvm::GlobalVariable(*m_module, Type::BytePtr, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "rt_jmpBuf"); llvm::Type* args[] = {Type::BytePtr, m_builder.getInt32Ty()}; - auto longjmpNative = llvm::Function::Create(llvm::FunctionType::get(Type::Void, args, false), llvm::Function::ExternalLinkage, "longjmp", _module); + auto longjmpNative = llvm::Function::Create(llvm::FunctionType::get(Type::Void, args, false), llvm::Function::ExternalLinkage, "longjmp", m_module); m_builder.CreateCall2(longjmpNative, m_builder.CreateLoad(extJmpBuf), Constant::get(ReturnCode::OutOfGas)); m_builder.CreateUnreachable(); diff --git a/evmcc/GasMeter.h b/evmcc/GasMeter.h index cea4a2b44..521e7080a 100644 --- a/evmcc/GasMeter.h +++ b/evmcc/GasMeter.h @@ -15,7 +15,7 @@ namespace jit class GasMeter : public CompilerHelper { public: - GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module); + GasMeter(llvm::IRBuilder<>& _builder); /// Count step cost of instruction void count(Instruction _inst); diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index a000816e7..7fde48949 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -22,36 +22,36 @@ namespace eth namespace jit { -Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module, GasMeter& _gasMeter): - CompilerHelper(_builder, _module) +Memory::Memory(llvm::IRBuilder<>& _builder, GasMeter& _gasMeter): + CompilerHelper(_builder) { auto i64Ty = m_builder.getInt64Ty(); llvm::Type* argTypes[] = {i64Ty, i64Ty}; auto dumpTy = llvm::FunctionType::get(m_builder.getVoidTy(), llvm::ArrayRef(argTypes), false); m_memDump = llvm::Function::Create(dumpTy, llvm::GlobalValue::LinkageTypes::ExternalLinkage, - "evmccrt_memory_dump", _module); + "evmccrt_memory_dump", m_module); - m_data = new llvm::GlobalVariable(*_module, Type::BytePtr, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::BytePtr), "mem.data"); + m_data = new llvm::GlobalVariable(*m_module, Type::BytePtr, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::BytePtr), "mem.data"); m_data->setUnnamedAddr(true); // Address is not important - m_size = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::PrivateLinkage, Constant::get(0), "mem.size"); + m_size = new llvm::GlobalVariable(*m_module, Type::i256, false, llvm::GlobalVariable::PrivateLinkage, Constant::get(0), "mem.size"); m_size->setUnnamedAddr(true); // Address is not important - m_returnDataOffset = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "mem_returnDataOffset"); + m_returnDataOffset = new llvm::GlobalVariable(*m_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "mem_returnDataOffset"); m_returnDataOffset->setUnnamedAddr(true); // Address is not important - m_returnDataSize = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "mem_returnDataSize"); + m_returnDataSize = new llvm::GlobalVariable(*m_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "mem_returnDataSize"); m_returnDataSize->setUnnamedAddr(true); // Address is not important - m_resize = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, Type::WordPtr, false), llvm::Function::ExternalLinkage, "mem_resize", _module); + m_resize = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, Type::WordPtr, false), llvm::Function::ExternalLinkage, "mem_resize", m_module); llvm::AttrBuilder attrBuilder; attrBuilder.addAttribute(llvm::Attribute::NoAlias).addAttribute(llvm::Attribute::NoCapture).addAttribute(llvm::Attribute::NonNull).addAttribute(llvm::Attribute::ReadOnly); m_resize->setAttributes(llvm::AttributeSet::get(m_resize->getContext(), 1, attrBuilder)); - m_require = createRequireFunc(_module, _gasMeter); - m_loadWord = createFunc(false, Type::i256, _module, _gasMeter); - m_storeWord = createFunc(true, Type::i256, _module, _gasMeter); - m_storeByte = createFunc(true, Type::Byte, _module, _gasMeter); + m_require = createRequireFunc(m_module, _gasMeter); + m_loadWord = createFunc(false, Type::i256, m_module, _gasMeter); + m_storeWord = createFunc(true, Type::i256, m_module, _gasMeter); + m_storeByte = createFunc(true, Type::Byte, m_module, _gasMeter); } llvm::Function* Memory::createRequireFunc(llvm::Module* _module, GasMeter& _gasMeter) diff --git a/evmcc/Memory.h b/evmcc/Memory.h index 3d2db56ee..489c37439 100644 --- a/evmcc/Memory.h +++ b/evmcc/Memory.h @@ -14,7 +14,7 @@ namespace jit class Memory : public CompilerHelper { public: - Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module, class GasMeter& _gasMeter); + Memory(llvm::IRBuilder<>& _builder, class GasMeter& _gasMeter); llvm::Value* loadWord(llvm::Value* _addr); void storeWord(llvm::Value* _addr, llvm::Value* _word); From cc2809c9b6fb628a26226d1947b8a489b6b8bdc1 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Thu, 16 Oct 2014 12:22:54 +0100 Subject: [PATCH 138/641] Added dumping of CFG to a .dot file [Delivers #80816506] --- evmcc/Compiler.cpp | 52 ++++++++++++++++++++++++++++++++++++++++++++++ evmcc/Compiler.h | 4 ++++ evmcc/evmcc.cpp | 18 ++++++++++++++-- 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 77db366cf..a7e8ba483 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -929,6 +929,58 @@ void Compiler::linkBasicBlocks() } } +void Compiler::dumpBasicBlockGraph(std::ostream& out) +{ + out << "digraph BB {\n" + << " node [shape=record];\n" + << " entry [share=record, label=\"entry block\"];\n"; + + // std::map blocksByName; + std::vector blocks; + for (auto& pair : this->basicBlocks) + { + blocks.push_back(&pair.second); + } + blocks.push_back(m_jumpTableBlock.get()); + blocks.push_back(m_badJumpBlock.get()); + + // Output nodes + for (auto bb : blocks) + { + std::string blockName = bb->llvm()->getName(); + // blocksByName.insert(std::pair(blockName, bb)); + + int numOfPhiNodes = 0; + auto firstNonPhiPtr = bb->llvm()->getFirstNonPHI(); + for (auto instrIter = bb->llvm()->begin(); &*instrIter != firstNonPhiPtr; ++instrIter, ++numOfPhiNodes); + + auto endStackSize = bb->getStack().size(); + + out << " \"" << blockName << "\" [shape=record, label=\"" + << std::to_string(numOfPhiNodes) << "|" + << blockName << "|" + << std::to_string(endStackSize) + << "\"];\n"; + } + + out << " entry -> \"Instr.0\";\n"; + + // Output edges + for (auto bb : blocks) + { + std::string blockName = bb->llvm()->getName(); + + auto end = llvm::succ_end(bb->llvm()); + for (llvm::succ_iterator it = llvm::succ_begin(bb->llvm()); it != end; ++it) + { + std::string succName = it->getName(); + out << " \"" << blockName << "\" -> \"" << succName << "\";\n"; + } + } + + out << "}\n"; +} + } } } diff --git a/evmcc/Compiler.h b/evmcc/Compiler.h index 1a0e61ca1..bda154689 100644 --- a/evmcc/Compiler.h +++ b/evmcc/Compiler.h @@ -24,6 +24,9 @@ public: std::unique_ptr compile(const bytes& bytecode); + void dumpBasicBlockGraph(std::ostream& out); + + private: void createBasicBlocks(const bytes& bytecode); @@ -32,6 +35,7 @@ private: void linkBasicBlocks(); + llvm::IRBuilder<> m_builder; /** diff --git a/evmcc/evmcc.cpp b/evmcc/evmcc.cpp index d8bf9438b..22ba1db50 100644 --- a/evmcc/evmcc.cpp +++ b/evmcc/evmcc.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include @@ -22,6 +23,7 @@ void show_usage() std::cerr << "usage: evmcc (-b|-c|-d)+ \n"; } + int main(int argc, char** argv) { @@ -30,7 +32,8 @@ int main(int argc, char** argv) bool opt_show_bytes = false; bool opt_compile = false; bool opt_interpret = false; - bool opt_unknown = false; + bool opt_dump_graph = false; + bool opt_unknown = false; for (int i = 1; i < argc; i++) { @@ -43,6 +46,8 @@ int main(int argc, char** argv) opt_dissassemble = true; else if (option == "-i") opt_interpret = true; + else if (option == "-g") + opt_dump_graph = true; else if (option[0] != '-' && input_file.empty()) input_file = option; else @@ -89,9 +94,18 @@ int main(int argc, char** argv) if (opt_compile) { - auto module = eth::jit::Compiler().compile(bytecode); + auto compiler = eth::jit::Compiler(); + auto module = compiler.compile(bytecode); llvm::raw_os_ostream out(std::cout); module->print(out, nullptr); + + if (opt_dump_graph) + { + std::ofstream ofs("blocks.dot"); + compiler.dumpBasicBlockGraph(ofs); + ofs.close(); + std::cout << "Basic blocks graph written to block.dot\n"; + } } if (opt_interpret) From 960380b8e552290f4c7ec6678c60c77669a7108a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 16 Oct 2014 13:27:28 +0200 Subject: [PATCH 139/641] Get IR module from IR builder on demand --- evmcc/CompilerHelper.cpp | 10 ++++++++-- evmcc/CompilerHelper.h | 6 +++--- evmcc/Ext.cpp | 2 +- evmcc/GasMeter.cpp | 9 +++++---- evmcc/Memory.cpp | 29 +++++++++++++++-------------- evmcc/Memory.h | 4 ++-- 6 files changed, 34 insertions(+), 26 deletions(-) diff --git a/evmcc/CompilerHelper.cpp b/evmcc/CompilerHelper.cpp index 7b29690b7..3bdf38641 100644 --- a/evmcc/CompilerHelper.cpp +++ b/evmcc/CompilerHelper.cpp @@ -11,10 +11,16 @@ namespace jit { CompilerHelper::CompilerHelper(llvm::IRBuilder<>& _builder) : - m_builder(_builder), - m_module(_builder.GetInsertBlock()->getParent()->getParent()) + m_builder(_builder) {} +llvm::Module* CompilerHelper::getModule() +{ + assert(m_builder.GetInsertBlock()); + assert(m_builder.GetInsertBlock()->getParent()); // BB must be in a function + return m_builder.GetInsertBlock()->getParent()->getParent(); +} + } } } diff --git a/evmcc/CompilerHelper.h b/evmcc/CompilerHelper.h index e10937277..7cf2653e5 100644 --- a/evmcc/CompilerHelper.h +++ b/evmcc/CompilerHelper.h @@ -19,11 +19,11 @@ protected: CompilerHelper(const CompilerHelper&) = delete; void operator=(CompilerHelper) = delete; + /// Reference to the IR module being compiled + llvm::Module* getModule(); + /// Reference to parent compiler IR builder llvm::IRBuilder<>& m_builder; - - /// Reference to the IR module being compiled - llvm::Module* m_module; }; } diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index f3f7699cd..5307bc191 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -47,7 +47,7 @@ Ext::Ext(llvm::IRBuilder<>& _builder): CompilerHelper(_builder) { auto&& ctx = _builder.getContext(); - auto module = m_module; + auto module = getModule(); auto i256Ty = m_builder.getIntNTy(256); auto i256PtrTy = i256Ty->getPointerTo(); diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index 206e5c805..f5e4a224b 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -83,10 +83,11 @@ bool isCostBlockEnd(Instruction _inst) GasMeter::GasMeter(llvm::IRBuilder<>& _builder) : CompilerHelper(_builder) { - m_gas = new llvm::GlobalVariable(*m_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "gas"); + auto module = getModule(); + m_gas = new llvm::GlobalVariable(*module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "gas"); m_gas->setUnnamedAddr(true); // Address is not important - m_gasCheckFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "gas.check", m_module); + m_gasCheckFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "gas.check", module); InsertPointGuard guard(m_builder); auto checkBB = llvm::BasicBlock::Create(_builder.getContext(), "Check", m_gasCheckFunc); @@ -103,9 +104,9 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder) : m_builder.SetInsertPoint(outOfGasBB); //auto longjmpFunc = llvm::Intrinsic::getDeclaration(_module, llvm::Intrinsic::eh_sjlj_longjmp); - auto extJmpBuf = new llvm::GlobalVariable(*m_module, Type::BytePtr, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "rt_jmpBuf"); + auto extJmpBuf = new llvm::GlobalVariable(*module, Type::BytePtr, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "rt_jmpBuf"); llvm::Type* args[] = {Type::BytePtr, m_builder.getInt32Ty()}; - auto longjmpNative = llvm::Function::Create(llvm::FunctionType::get(Type::Void, args, false), llvm::Function::ExternalLinkage, "longjmp", m_module); + auto longjmpNative = llvm::Function::Create(llvm::FunctionType::get(Type::Void, args, false), llvm::Function::ExternalLinkage, "longjmp", module); m_builder.CreateCall2(longjmpNative, m_builder.CreateLoad(extJmpBuf), Constant::get(ReturnCode::OutOfGas)); m_builder.CreateUnreachable(); diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index 7fde48949..d370a7f72 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -25,38 +25,39 @@ namespace jit Memory::Memory(llvm::IRBuilder<>& _builder, GasMeter& _gasMeter): CompilerHelper(_builder) { + auto module = getModule(); auto i64Ty = m_builder.getInt64Ty(); llvm::Type* argTypes[] = {i64Ty, i64Ty}; auto dumpTy = llvm::FunctionType::get(m_builder.getVoidTy(), llvm::ArrayRef(argTypes), false); m_memDump = llvm::Function::Create(dumpTy, llvm::GlobalValue::LinkageTypes::ExternalLinkage, - "evmccrt_memory_dump", m_module); + "evmccrt_memory_dump", module); - m_data = new llvm::GlobalVariable(*m_module, Type::BytePtr, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::BytePtr), "mem.data"); + m_data = new llvm::GlobalVariable(*module, Type::BytePtr, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::BytePtr), "mem.data"); m_data->setUnnamedAddr(true); // Address is not important - m_size = new llvm::GlobalVariable(*m_module, Type::i256, false, llvm::GlobalVariable::PrivateLinkage, Constant::get(0), "mem.size"); + m_size = new llvm::GlobalVariable(*module, Type::i256, false, llvm::GlobalVariable::PrivateLinkage, Constant::get(0), "mem.size"); m_size->setUnnamedAddr(true); // Address is not important - m_returnDataOffset = new llvm::GlobalVariable(*m_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "mem_returnDataOffset"); + m_returnDataOffset = new llvm::GlobalVariable(*module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "mem_returnDataOffset"); m_returnDataOffset->setUnnamedAddr(true); // Address is not important - m_returnDataSize = new llvm::GlobalVariable(*m_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "mem_returnDataSize"); + m_returnDataSize = new llvm::GlobalVariable(*module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "mem_returnDataSize"); m_returnDataSize->setUnnamedAddr(true); // Address is not important - m_resize = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, Type::WordPtr, false), llvm::Function::ExternalLinkage, "mem_resize", m_module); + m_resize = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, Type::WordPtr, false), llvm::Function::ExternalLinkage, "mem_resize", module); llvm::AttrBuilder attrBuilder; attrBuilder.addAttribute(llvm::Attribute::NoAlias).addAttribute(llvm::Attribute::NoCapture).addAttribute(llvm::Attribute::NonNull).addAttribute(llvm::Attribute::ReadOnly); m_resize->setAttributes(llvm::AttributeSet::get(m_resize->getContext(), 1, attrBuilder)); - m_require = createRequireFunc(m_module, _gasMeter); - m_loadWord = createFunc(false, Type::i256, m_module, _gasMeter); - m_storeWord = createFunc(true, Type::i256, m_module, _gasMeter); - m_storeByte = createFunc(true, Type::Byte, m_module, _gasMeter); + m_require = createRequireFunc(_gasMeter); + m_loadWord = createFunc(false, Type::i256, _gasMeter); + m_storeWord = createFunc(true, Type::i256, _gasMeter); + m_storeByte = createFunc(true, Type::Byte, _gasMeter); } -llvm::Function* Memory::createRequireFunc(llvm::Module* _module, GasMeter& _gasMeter) +llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter) { - auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "mem.require", _module); + auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "mem.require", getModule()); auto checkBB = llvm::BasicBlock::Create(func->getContext(), "check", func); auto resizeBB = llvm::BasicBlock::Create(func->getContext(), "resize", func); @@ -91,14 +92,14 @@ llvm::Function* Memory::createRequireFunc(llvm::Module* _module, GasMeter& _gasM return func; } -llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, llvm::Module* _module, GasMeter& _gasMeter) +llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, GasMeter& _gasMeter) { auto isWord = _valueType == Type::i256; llvm::Type* storeArgs[] = {Type::i256, _valueType}; auto name = _isStore ? isWord ? "mstore" : "mstore8" : "mload"; auto funcType = _isStore ? llvm::FunctionType::get(Type::Void, storeArgs, false) : llvm::FunctionType::get(Type::i256, Type::i256, false); - auto func = llvm::Function::Create(funcType, llvm::Function::PrivateLinkage, name, _module); + auto func = llvm::Function::Create(funcType, llvm::Function::PrivateLinkage, name, getModule()); InsertPointGuard guard(m_builder); // Restores insert point at function exit diff --git a/evmcc/Memory.h b/evmcc/Memory.h index 489c37439..2ab09c127 100644 --- a/evmcc/Memory.h +++ b/evmcc/Memory.h @@ -36,8 +36,8 @@ public: void dump(uint64_t _begin, uint64_t _end = 0); private: - llvm::Function* createFunc(bool _isStore, llvm::Type* _type, llvm::Module* _module, GasMeter& _gasMeter); - llvm::Function* createRequireFunc(llvm::Module* _module, GasMeter& _gasMeter); + llvm::Function* createFunc(bool _isStore, llvm::Type* _type, GasMeter& _gasMeter); + llvm::Function* createRequireFunc(GasMeter& _gasMeter); private: llvm::GlobalVariable* m_data; From 64205161576ad41a484b205ffbf58f12f9a9d0f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 16 Oct 2014 13:34:02 +0200 Subject: [PATCH 140/641] InsertPointGuard definition moved to CompilerHelper.h --- evmcc/CompilerHelper.h | 25 +++++++++++++++++++++++++ evmcc/GasMeter.cpp | 1 - evmcc/Utils.h | 22 ---------------------- 3 files changed, 25 insertions(+), 23 deletions(-) diff --git a/evmcc/CompilerHelper.h b/evmcc/CompilerHelper.h index 7cf2653e5..e284398a3 100644 --- a/evmcc/CompilerHelper.h +++ b/evmcc/CompilerHelper.h @@ -11,6 +11,7 @@ namespace eth namespace jit { +/// Base class for compiler helpers like Memory, GasMeter, etc. class CompilerHelper { protected: @@ -26,6 +27,30 @@ protected: llvm::IRBuilder<>& m_builder; }; + +/// Saves the insert point of the IR builder and restores it when destructed +struct InsertPointGuard +{ + InsertPointGuard(llvm::IRBuilder<>& _builder) : + m_builder(_builder), + m_insertBB(m_builder.GetInsertBlock()), + m_insertPt(m_builder.GetInsertPoint()) + {} + + InsertPointGuard(const InsertPointGuard&) = delete; + void operator=(InsertPointGuard) = delete; + + ~InsertPointGuard() + { + m_builder.SetInsertPoint(m_insertBB, m_insertPt); + } + +private: + llvm::IRBuilder<>& m_builder; + llvm::BasicBlock* m_insertBB; + llvm::BasicBlock::iterator m_insertPt; +}; + } } } diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index f5e4a224b..9c83ba8db 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -9,7 +9,6 @@ #include #include "Type.h" -#include "Utils.h" #include "Ext.h" namespace dev diff --git a/evmcc/Utils.h b/evmcc/Utils.h index 27189d5d0..1b146b3d2 100644 --- a/evmcc/Utils.h +++ b/evmcc/Utils.h @@ -26,28 +26,6 @@ static_assert(sizeof(i256) == 32, "Wrong i265 size"); u256 llvm2eth(i256); i256 eth2llvm(u256); -struct InsertPointGuard -{ - InsertPointGuard(llvm::IRBuilder<>& _builder) : - m_builder(_builder), - m_insertBB(m_builder.GetInsertBlock()), - m_insertPt(m_builder.GetInsertPoint()) - {} - - ~InsertPointGuard() - { - m_builder.SetInsertPoint(m_insertBB, m_insertPt); - } - -private: - llvm::IRBuilder<>& m_builder; - llvm::BasicBlock* m_insertBB; - llvm::BasicBlock::iterator m_insertPt; - - InsertPointGuard(const InsertPointGuard&) = delete; - void operator=(InsertPointGuard) = delete; -}; - #define ANY_PUSH PUSH1: \ case Instruction::PUSH2: \ case Instruction::PUSH3: \ From 92cf0b9ab0a64f85b602cc40d5569e860d24540e Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Thu, 16 Oct 2014 12:35:51 +0100 Subject: [PATCH 141/641] Dumping CFG to .dot: showing indirect jumps with dashed lines --- evmcc/Compiler.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index a7e8ba483..8acfa7d05 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -935,7 +935,6 @@ void Compiler::dumpBasicBlockGraph(std::ostream& out) << " node [shape=record];\n" << " entry [share=record, label=\"entry block\"];\n"; - // std::map blocksByName; std::vector blocks; for (auto& pair : this->basicBlocks) { @@ -948,7 +947,6 @@ void Compiler::dumpBasicBlockGraph(std::ostream& out) for (auto bb : blocks) { std::string blockName = bb->llvm()->getName(); - // blocksByName.insert(std::pair(blockName, bb)); int numOfPhiNodes = 0; auto firstNonPhiPtr = bb->llvm()->getFirstNonPHI(); @@ -957,10 +955,8 @@ void Compiler::dumpBasicBlockGraph(std::ostream& out) auto endStackSize = bb->getStack().size(); out << " \"" << blockName << "\" [shape=record, label=\"" - << std::to_string(numOfPhiNodes) << "|" - << blockName << "|" - << std::to_string(endStackSize) - << "\"];\n"; + << numOfPhiNodes << "|" << blockName << "|" << endStackSize + << "\"];\n"; } out << " entry -> \"Instr.0\";\n"; @@ -974,7 +970,8 @@ void Compiler::dumpBasicBlockGraph(std::ostream& out) for (llvm::succ_iterator it = llvm::succ_begin(bb->llvm()); it != end; ++it) { std::string succName = it->getName(); - out << " \"" << blockName << "\" -> \"" << succName << "\";\n"; + out << " \"" << blockName << "\" -> \"" << succName << "\"" + << ((bb == m_jumpTableBlock.get()) ? " [style = dashed];\n" : "\n"); } } From a6c58c38d89c1da68e4306be0b72087886722450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 16 Oct 2014 15:16:16 +0200 Subject: [PATCH 142/641] Move JIT compiler project to library --- evmcc/evmcc.cpp | 5 +- {evmcc => libevmjit}/BasicBlock.cpp | 0 {evmcc => libevmjit}/BasicBlock.h | 0 {evmcc => libevmjit}/Compiler.cpp | 0 {evmcc => libevmjit}/Compiler.h | 0 {evmcc => libevmjit}/CompilerHelper.cpp | 0 {evmcc => libevmjit}/CompilerHelper.h | 0 {evmcc => libevmjit}/ExecutionEngine.cpp | 0 {evmcc => libevmjit}/ExecutionEngine.h | 0 {evmcc => libevmjit}/Ext.cpp | 0 {evmcc => libevmjit}/Ext.h | 0 {evmcc => libevmjit}/GasMeter.cpp | 0 {evmcc => libevmjit}/GasMeter.h | 0 {evmcc => libevmjit}/Memory.cpp | 0 {evmcc => libevmjit}/Memory.h | 0 {evmcc => libevmjit}/Runtime.cpp | 0 {evmcc => libevmjit}/Runtime.h | 0 {evmcc => libevmjit}/Type.cpp | 0 {evmcc => libevmjit}/Type.h | 0 {evmcc => libevmjit}/Utils.cpp | 0 {evmcc => libevmjit}/Utils.h | 0 windows/Ethereum.sln | 87 ++++++++++++- windows/LLVM.props | 23 ++++ windows/LibEvmJit.vcxproj | 152 +++++++++++++++++++++++ windows/LibEvmJit.vcxproj.filters | 72 +++++++++++ windows/evmcc.vcxproj | 38 ++---- windows/evmcc.vcxproj.filters | 22 ---- 27 files changed, 341 insertions(+), 58 deletions(-) rename {evmcc => libevmjit}/BasicBlock.cpp (100%) rename {evmcc => libevmjit}/BasicBlock.h (100%) rename {evmcc => libevmjit}/Compiler.cpp (100%) rename {evmcc => libevmjit}/Compiler.h (100%) rename {evmcc => libevmjit}/CompilerHelper.cpp (100%) rename {evmcc => libevmjit}/CompilerHelper.h (100%) rename {evmcc => libevmjit}/ExecutionEngine.cpp (100%) rename {evmcc => libevmjit}/ExecutionEngine.h (100%) rename {evmcc => libevmjit}/Ext.cpp (100%) rename {evmcc => libevmjit}/Ext.h (100%) rename {evmcc => libevmjit}/GasMeter.cpp (100%) rename {evmcc => libevmjit}/GasMeter.h (100%) rename {evmcc => libevmjit}/Memory.cpp (100%) rename {evmcc => libevmjit}/Memory.h (100%) rename {evmcc => libevmjit}/Runtime.cpp (100%) rename {evmcc => libevmjit}/Runtime.h (100%) rename {evmcc => libevmjit}/Type.cpp (100%) rename {evmcc => libevmjit}/Type.h (100%) rename {evmcc => libevmjit}/Utils.cpp (100%) rename {evmcc => libevmjit}/Utils.h (100%) create mode 100644 windows/LLVM.props create mode 100644 windows/LibEvmJit.vcxproj create mode 100644 windows/LibEvmJit.vcxproj.filters diff --git a/evmcc/evmcc.cpp b/evmcc/evmcc.cpp index 22ba1db50..8a7ac5384 100644 --- a/evmcc/evmcc.cpp +++ b/evmcc/evmcc.cpp @@ -12,9 +12,8 @@ #include #include #include - -#include "Compiler.h" -#include "ExecutionEngine.h" +#include +#include void show_usage() diff --git a/evmcc/BasicBlock.cpp b/libevmjit/BasicBlock.cpp similarity index 100% rename from evmcc/BasicBlock.cpp rename to libevmjit/BasicBlock.cpp diff --git a/evmcc/BasicBlock.h b/libevmjit/BasicBlock.h similarity index 100% rename from evmcc/BasicBlock.h rename to libevmjit/BasicBlock.h diff --git a/evmcc/Compiler.cpp b/libevmjit/Compiler.cpp similarity index 100% rename from evmcc/Compiler.cpp rename to libevmjit/Compiler.cpp diff --git a/evmcc/Compiler.h b/libevmjit/Compiler.h similarity index 100% rename from evmcc/Compiler.h rename to libevmjit/Compiler.h diff --git a/evmcc/CompilerHelper.cpp b/libevmjit/CompilerHelper.cpp similarity index 100% rename from evmcc/CompilerHelper.cpp rename to libevmjit/CompilerHelper.cpp diff --git a/evmcc/CompilerHelper.h b/libevmjit/CompilerHelper.h similarity index 100% rename from evmcc/CompilerHelper.h rename to libevmjit/CompilerHelper.h diff --git a/evmcc/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp similarity index 100% rename from evmcc/ExecutionEngine.cpp rename to libevmjit/ExecutionEngine.cpp diff --git a/evmcc/ExecutionEngine.h b/libevmjit/ExecutionEngine.h similarity index 100% rename from evmcc/ExecutionEngine.h rename to libevmjit/ExecutionEngine.h diff --git a/evmcc/Ext.cpp b/libevmjit/Ext.cpp similarity index 100% rename from evmcc/Ext.cpp rename to libevmjit/Ext.cpp diff --git a/evmcc/Ext.h b/libevmjit/Ext.h similarity index 100% rename from evmcc/Ext.h rename to libevmjit/Ext.h diff --git a/evmcc/GasMeter.cpp b/libevmjit/GasMeter.cpp similarity index 100% rename from evmcc/GasMeter.cpp rename to libevmjit/GasMeter.cpp diff --git a/evmcc/GasMeter.h b/libevmjit/GasMeter.h similarity index 100% rename from evmcc/GasMeter.h rename to libevmjit/GasMeter.h diff --git a/evmcc/Memory.cpp b/libevmjit/Memory.cpp similarity index 100% rename from evmcc/Memory.cpp rename to libevmjit/Memory.cpp diff --git a/evmcc/Memory.h b/libevmjit/Memory.h similarity index 100% rename from evmcc/Memory.h rename to libevmjit/Memory.h diff --git a/evmcc/Runtime.cpp b/libevmjit/Runtime.cpp similarity index 100% rename from evmcc/Runtime.cpp rename to libevmjit/Runtime.cpp diff --git a/evmcc/Runtime.h b/libevmjit/Runtime.h similarity index 100% rename from evmcc/Runtime.h rename to libevmjit/Runtime.h diff --git a/evmcc/Type.cpp b/libevmjit/Type.cpp similarity index 100% rename from evmcc/Type.cpp rename to libevmjit/Type.cpp diff --git a/evmcc/Type.h b/libevmjit/Type.h similarity index 100% rename from evmcc/Type.h rename to libevmjit/Type.h diff --git a/evmcc/Utils.cpp b/libevmjit/Utils.cpp similarity index 100% rename from evmcc/Utils.cpp rename to libevmjit/Utils.cpp diff --git a/evmcc/Utils.h b/libevmjit/Utils.h similarity index 100% rename from evmcc/Utils.h rename to libevmjit/Utils.h diff --git a/windows/Ethereum.sln b/windows/Ethereum.sln index c894b8a79..11ced4384 100644 --- a/windows/Ethereum.sln +++ b/windows/Ethereum.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Express 2013 for Windows Desktop -VisualStudioVersion = 12.0.21005.1 +VisualStudioVersion = 12.0.30723.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libs", "Libs", "{988F2383-FA1D-408B-BCF6-C0EE7AB0A560}" EndProject @@ -38,141 +38,221 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lllc", "Lllc.vcxproj", "{255BDC68-B8DB-465F-8220-981E77684189}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "evmcc", "evmcc.vcxproj", "{D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}" + ProjectSection(ProjectDependencies) = postProject + {9C816740-5C11-4377-A3A7-46BE12F35FA0} = {9C816740-5C11-4377-A3A7-46BE12F35FA0} + {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F} = {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibEvmJit", "LibEvmJit.vcxproj", "{9C816740-5C11-4377-A3A7-46BE12F35FA0}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Mixed Platforms = Debug|Mixed Platforms Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 + Release|Mixed Platforms = Release|Mixed Platforms Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|Win32.ActiveCfg = Debug|Win32 {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|Win32.Build.0 = Debug|Win32 {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|x64.ActiveCfg = Debug|x64 {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|x64.Build.0 = Debug|x64 + {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|Mixed Platforms.Build.0 = Release|Win32 {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|Win32.ActiveCfg = Release|Win32 {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|Win32.Build.0 = Release|Win32 {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|x64.ActiveCfg = Release|x64 {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|x64.Build.0 = Release|x64 + {27014763-955D-486B-9BA7-69872192E6F4}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {27014763-955D-486B-9BA7-69872192E6F4}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {27014763-955D-486B-9BA7-69872192E6F4}.Debug|Win32.ActiveCfg = Debug|Win32 {27014763-955D-486B-9BA7-69872192E6F4}.Debug|Win32.Build.0 = Debug|Win32 {27014763-955D-486B-9BA7-69872192E6F4}.Debug|x64.ActiveCfg = Debug|x64 {27014763-955D-486B-9BA7-69872192E6F4}.Debug|x64.Build.0 = Debug|x64 + {27014763-955D-486B-9BA7-69872192E6F4}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {27014763-955D-486B-9BA7-69872192E6F4}.Release|Mixed Platforms.Build.0 = Release|Win32 {27014763-955D-486B-9BA7-69872192E6F4}.Release|Win32.ActiveCfg = Release|Win32 {27014763-955D-486B-9BA7-69872192E6F4}.Release|Win32.Build.0 = Release|Win32 {27014763-955D-486B-9BA7-69872192E6F4}.Release|x64.ActiveCfg = Release|x64 {27014763-955D-486B-9BA7-69872192E6F4}.Release|x64.Build.0 = Release|x64 + {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|Win32.ActiveCfg = Debug|Win32 {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|Win32.Build.0 = Debug|Win32 {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|x64.ActiveCfg = Debug|x64 {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|x64.Build.0 = Debug|x64 + {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|Mixed Platforms.Build.0 = Release|Win32 {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|Win32.ActiveCfg = Release|Win32 {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|Win32.Build.0 = Release|Win32 {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|x64.ActiveCfg = Release|x64 {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|x64.Build.0 = Release|x64 + {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|Win32.ActiveCfg = Debug|Win32 {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|Win32.Build.0 = Debug|Win32 {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|x64.ActiveCfg = Debug|x64 {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|x64.Build.0 = Debug|x64 + {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|Mixed Platforms.Build.0 = Release|Win32 {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|Win32.ActiveCfg = Release|Win32 {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|Win32.Build.0 = Release|Win32 {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|x64.ActiveCfg = Release|x64 {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|x64.Build.0 = Release|x64 + {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|Win32.ActiveCfg = Debug|Win32 {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|Win32.Build.0 = Debug|Win32 {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|x64.ActiveCfg = Debug|x64 {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|x64.Build.0 = Debug|x64 + {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|Mixed Platforms.Build.0 = Release|Win32 {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|Win32.ActiveCfg = Release|Win32 {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|Win32.Build.0 = Release|Win32 {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|x64.ActiveCfg = Release|x64 {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|x64.Build.0 = Release|x64 + {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|Win32.ActiveCfg = Debug|Win32 {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|Win32.Build.0 = Debug|Win32 {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|x64.ActiveCfg = Debug|x64 {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|x64.Build.0 = Debug|x64 + {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|Mixed Platforms.Build.0 = Release|Win32 {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|Win32.ActiveCfg = Release|Win32 {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|Win32.Build.0 = Release|Win32 {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|x64.ActiveCfg = Release|x64 {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|x64.Build.0 = Release|x64 + {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|Win32.ActiveCfg = Debug|Win32 {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|Win32.Build.0 = Debug|Win32 {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|x64.ActiveCfg = Debug|x64 {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|x64.Build.0 = Debug|x64 + {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|Mixed Platforms.Build.0 = Release|Win32 {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|Win32.ActiveCfg = Release|Win32 {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|Win32.Build.0 = Release|Win32 {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|x64.ActiveCfg = Release|x64 {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|x64.Build.0 = Release|x64 + {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Debug|Win32.ActiveCfg = Debug|Win32 {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Debug|Win32.Build.0 = Debug|Win32 {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Debug|x64.ActiveCfg = Debug|x64 {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Debug|x64.Build.0 = Debug|x64 + {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Release|Win32.ActiveCfg = Release|Win32 {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Release|Win32.Build.0 = Release|Win32 {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Release|x64.ActiveCfg = Release|x64 {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Release|x64.Build.0 = Release|x64 + {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Debug|Win32.ActiveCfg = Debug|Win32 {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Debug|Win32.Build.0 = Debug|Win32 {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Debug|x64.ActiveCfg = Debug|x64 {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Debug|x64.Build.0 = Debug|x64 + {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Release|Win32.ActiveCfg = Release|Win32 {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Release|Win32.Build.0 = Release|Win32 {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Release|x64.ActiveCfg = Release|x64 {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Release|x64.Build.0 = Release|x64 + {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|Win32.ActiveCfg = Debug|Win32 {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|Win32.Build.0 = Debug|Win32 {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|x64.ActiveCfg = Debug|x64 {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|x64.Build.0 = Debug|x64 + {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|Mixed Platforms.Build.0 = Release|Win32 {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|Win32.ActiveCfg = Release|Win32 {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|Win32.Build.0 = Release|Win32 {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|x64.ActiveCfg = Release|x64 {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|x64.Build.0 = Release|x64 + {90C70663-7181-4E99-9079-54188CEB8954}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {90C70663-7181-4E99-9079-54188CEB8954}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {90C70663-7181-4E99-9079-54188CEB8954}.Debug|Win32.ActiveCfg = Debug|Win32 {90C70663-7181-4E99-9079-54188CEB8954}.Debug|Win32.Build.0 = Debug|Win32 {90C70663-7181-4E99-9079-54188CEB8954}.Debug|x64.ActiveCfg = Debug|x64 {90C70663-7181-4E99-9079-54188CEB8954}.Debug|x64.Build.0 = Debug|x64 + {90C70663-7181-4E99-9079-54188CEB8954}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {90C70663-7181-4E99-9079-54188CEB8954}.Release|Mixed Platforms.Build.0 = Release|Win32 {90C70663-7181-4E99-9079-54188CEB8954}.Release|Win32.ActiveCfg = Release|Win32 {90C70663-7181-4E99-9079-54188CEB8954}.Release|Win32.Build.0 = Release|Win32 {90C70663-7181-4E99-9079-54188CEB8954}.Release|x64.ActiveCfg = Release|x64 {90C70663-7181-4E99-9079-54188CEB8954}.Release|x64.Build.0 = Release|x64 + {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|Win32.ActiveCfg = Debug|Win32 {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|Win32.Build.0 = Debug|Win32 {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|x64.ActiveCfg = Debug|x64 {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|x64.Build.0 = Debug|x64 + {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|Mixed Platforms.Build.0 = Release|Win32 {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|Win32.ActiveCfg = Release|Win32 {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|Win32.Build.0 = Release|Win32 {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|x64.ActiveCfg = Release|x64 {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|x64.Build.0 = Release|x64 + {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|Win32.ActiveCfg = Debug|Win32 {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|Win32.Build.0 = Debug|Win32 {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|x64.ActiveCfg = Debug|x64 {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|x64.Build.0 = Debug|x64 + {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|Mixed Platforms.Build.0 = Release|Win32 {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|Win32.ActiveCfg = Release|Win32 {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|Win32.Build.0 = Release|Win32 {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|x64.ActiveCfg = Release|x64 {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|x64.Build.0 = Release|x64 + {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|Win32.ActiveCfg = Debug|Win32 {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|Win32.Build.0 = Debug|Win32 {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|x64.ActiveCfg = Debug|x64 {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|x64.Build.0 = Debug|x64 + {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|Mixed Platforms.Build.0 = Release|Win32 {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|Win32.ActiveCfg = Release|Win32 {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|Win32.Build.0 = Release|Win32 {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|x64.ActiveCfg = Release|x64 {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|x64.Build.0 = Release|x64 + {255BDC68-B8DB-465F-8220-981E77684189}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {255BDC68-B8DB-465F-8220-981E77684189}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {255BDC68-B8DB-465F-8220-981E77684189}.Debug|Win32.ActiveCfg = Debug|Win32 {255BDC68-B8DB-465F-8220-981E77684189}.Debug|Win32.Build.0 = Debug|Win32 {255BDC68-B8DB-465F-8220-981E77684189}.Debug|x64.ActiveCfg = Debug|x64 {255BDC68-B8DB-465F-8220-981E77684189}.Debug|x64.Build.0 = Debug|x64 + {255BDC68-B8DB-465F-8220-981E77684189}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {255BDC68-B8DB-465F-8220-981E77684189}.Release|Mixed Platforms.Build.0 = Release|Win32 {255BDC68-B8DB-465F-8220-981E77684189}.Release|Win32.ActiveCfg = Release|Win32 {255BDC68-B8DB-465F-8220-981E77684189}.Release|Win32.Build.0 = Release|Win32 {255BDC68-B8DB-465F-8220-981E77684189}.Release|x64.ActiveCfg = Release|x64 {255BDC68-B8DB-465F-8220-981E77684189}.Release|x64.Build.0 = Release|x64 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|Win32.ActiveCfg = Debug|Win32 {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|Win32.Build.0 = Debug|Win32 {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|x64.ActiveCfg = Debug|x64 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|Mixed Platforms.Build.0 = Release|Win32 {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|Win32.ActiveCfg = Release|Win32 {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|Win32.Build.0 = Release|Win32 {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|x64.ActiveCfg = Release|x64 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|Win32.ActiveCfg = Debug|Win32 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|Win32.Build.0 = Debug|Win32 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|x64.ActiveCfg = Debug|x64 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|x64.Build.0 = Debug|x64 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|Mixed Platforms.Build.0 = Release|Win32 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|Win32.ActiveCfg = Release|Win32 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|Win32.Build.0 = Release|Win32 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|x64.ActiveCfg = Release|x64 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -181,11 +261,12 @@ Global {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F} = {988F2383-FA1D-408B-BCF6-C0EE7AB0A560} {27014763-955D-486B-9BA7-69872192E6F4} = {988F2383-FA1D-408B-BCF6-C0EE7AB0A560} {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA} = {988F2383-FA1D-408B-BCF6-C0EE7AB0A560} + {3BF049F8-AF7E-4E1C-9627-3E94C887AF24} = {6838FA95-01BF-4FF7-914C-FC209B81406E} + {3F3E389B-88DE-41D5-A73B-4F6036E18B36} = {6838FA95-01BF-4FF7-914C-FC209B81406E} {1CC213A4-3482-4211-B47B-172E90DAC7DE} = {988F2383-FA1D-408B-BCF6-C0EE7AB0A560} {1B1CA20E-39C3-4D9B-AC37-3783048E6672} = {988F2383-FA1D-408B-BCF6-C0EE7AB0A560} {DF3C5B07-A1A2-4F16-B37F-A27333622CDD} = {988F2383-FA1D-408B-BCF6-C0EE7AB0A560} {F174E81A-2A66-4693-B917-11BB42D3658C} = {988F2383-FA1D-408B-BCF6-C0EE7AB0A560} - {3BF049F8-AF7E-4E1C-9627-3E94C887AF24} = {6838FA95-01BF-4FF7-914C-FC209B81406E} - {3F3E389B-88DE-41D5-A73B-4F6036E18B36} = {6838FA95-01BF-4FF7-914C-FC209B81406E} + {9C816740-5C11-4377-A3A7-46BE12F35FA0} = {988F2383-FA1D-408B-BCF6-C0EE7AB0A560} EndGlobalSection EndGlobal diff --git a/windows/LLVM.props b/windows/LLVM.props new file mode 100644 index 000000000..708ff3085 --- /dev/null +++ b/windows/LLVM.props @@ -0,0 +1,23 @@ + + + + + ..\..\builds\llvm3.5 + ..\..\llvm-3.5.0\include;$(LLVMBuildDir)\include + + + + + $(LLVMIncludeDir);%(AdditionalIncludeDirectories) + 4800;%(DisableSpecificWarnings) + + + + + $(LLVMBuildDir) + + + $(LLVMIncludeDir) + + + \ No newline at end of file diff --git a/windows/LibEvmJit.vcxproj b/windows/LibEvmJit.vcxproj new file mode 100644 index 000000000..17832d871 --- /dev/null +++ b/windows/LibEvmJit.vcxproj @@ -0,0 +1,152 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {9C816740-5C11-4377-A3A7-46BE12F35FA0} + LibEvmJit + + + + StaticLibrary + true + v120 + + + StaticLibrary + true + v120 + + + StaticLibrary + false + v120 + true + + + StaticLibrary + false + v120 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + + + true + + + + + Level3 + Disabled + true + + + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/windows/LibEvmJit.vcxproj.filters b/windows/LibEvmJit.vcxproj.filters new file mode 100644 index 000000000..e24e4379e --- /dev/null +++ b/windows/LibEvmJit.vcxproj.filters @@ -0,0 +1,72 @@ + + + + + {9bb7d84d-6d6c-48af-a954-60049208b2f1} + + + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + \ No newline at end of file diff --git a/windows/evmcc.vcxproj b/windows/evmcc.vcxproj index efa7a6f20..6c1b72143 100644 --- a/windows/evmcc.vcxproj +++ b/windows/evmcc.vcxproj @@ -19,29 +19,7 @@ - - - - - - - - - - - - - - - - - - - - - - {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D} @@ -132,8 +110,8 @@ Console true - ../../builds/llvm3.5/Debug/lib;../../_build/LibEthereum/x64_Debug;%(AdditionalLibraryDirectories) - LibEthereum.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) + ../../builds/llvm3.5/Debug/lib;../../_build/LibEvmJit/x64_Debug;../../_build/LibEthereum/x64_Debug;%(AdditionalLibraryDirectories) + LibEthereum.lib;LibEvmJit.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) @@ -152,8 +130,8 @@ Console true - ../../builds/llvm3.5/Debug/lib;../../_build/LibEthereum/x64_Debug;../../_build/LibSecp256k1/x64_Debug;../../_build/LibCryptoPP/x64_Debug;%(AdditionalLibraryDirectories) - LibEthereum.lib;LibSecp256k1.lib;LibCryptoPP.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) + ../../builds/llvm3.5/Debug/lib;../../_build/LibEvmJit/x64_Debug;../../_build/LibEthereum/x64_Debug;../../_build/LibSecp256k1/x64_Debug;../../_build/LibCryptoPP/x64_Debug;%(AdditionalLibraryDirectories) + LibEthereum.lib;LibEvmJit.lib;LibSecp256k1.lib;LibCryptoPP.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) @@ -173,8 +151,8 @@ true true true - ../../builds/llvm3.5/Debug/lib;../../_build/LibEthereum/x64_Debug;%(AdditionalLibraryDirectories) - LibEthereum.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) + ../../builds/llvm3.5/Debug/lib;../../_build/LibEvmJit/x64_Debug;../../_build/LibEthereum/x64_Debug;%(AdditionalLibraryDirectories) + LibEthereum.lib;LibEvmJit.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) @@ -196,8 +174,8 @@ true true true - ../../builds/llvm3.5/Debug/lib;../../_build/LibEthereum/x64_Debug;%(AdditionalLibraryDirectories) - LibEthereum.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) + ../../builds/llvm3.5/Debug/lib;../../_build/LibEvmJit/x64_Debug;../../_build/LibEthereum/x64_Debug;%(AdditionalLibraryDirectories) + LibEthereum.lib;LibEvmJit.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) diff --git a/windows/evmcc.vcxproj.filters b/windows/evmcc.vcxproj.filters index adfcfaf60..6be5386a1 100644 --- a/windows/evmcc.vcxproj.filters +++ b/windows/evmcc.vcxproj.filters @@ -2,27 +2,5 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From 9552394cd1112e5b29563428316d3ae91db55614 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 16 Oct 2014 18:03:14 +0200 Subject: [PATCH 143/641] VM execution wrapper with similar interface as libevm/VM --- evmcc/evmcc.cpp | 4 ++-- libevmjit/Compiler.cpp | 16 ++++++------- libevmjit/Compiler.h | 6 ++--- libevmjit/ExecutionEngine.cpp | 2 +- libevmjit/ExecutionEngine.h | 2 ++ libevmjit/VM.cpp | 37 +++++++++++++++++++++++++++++++ libevmjit/VM.h | 32 ++++++++++++++++++++++++++ windows/LibEvmJit.vcxproj | 2 ++ windows/LibEvmJit.vcxproj.filters | 6 +++++ 9 files changed, 93 insertions(+), 14 deletions(-) create mode 100644 libevmjit/VM.cpp create mode 100644 libevmjit/VM.h diff --git a/evmcc/evmcc.cpp b/evmcc/evmcc.cpp index 8a7ac5384..600980d44 100644 --- a/evmcc/evmcc.cpp +++ b/evmcc/evmcc.cpp @@ -94,7 +94,7 @@ int main(int argc, char** argv) if (opt_compile) { auto compiler = eth::jit::Compiler(); - auto module = compiler.compile(bytecode); + auto module = compiler.compile({bytecode.data(), bytecode.size()}); llvm::raw_os_ostream out(std::cout); module->print(out, nullptr); @@ -110,7 +110,7 @@ int main(int argc, char** argv) if (opt_interpret) { auto engine = eth::jit::ExecutionEngine(); - auto module = eth::jit::Compiler().compile(bytecode); + auto module = eth::jit::Compiler().compile({bytecode.data(), bytecode.size()}); module->dump(); auto result = engine.run(std::move(module)); return result; diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 035abf287..cbb6118f4 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -29,7 +29,7 @@ Compiler::Compiler(): Type::init(m_builder.getContext()); } -void Compiler::createBasicBlocks(const bytes& bytecode) +void Compiler::createBasicBlocks(bytesConstRef bytecode) { std::set splitPoints; // Sorted collections of instruction indices where basic blocks start/end splitPoints.insert(0); // First basic block @@ -38,9 +38,9 @@ void Compiler::createBasicBlocks(const bytes& bytecode) std::vector indirectJumpTargets; boost::dynamic_bitset<> validJumpTargets(bytecode.size()); - for (auto curr = bytecode.cbegin(); curr != bytecode.cend(); ++curr) + for (auto curr = bytecode.begin(); curr != bytecode.end(); ++curr) { - ProgramCounter currentPC = curr - bytecode.cbegin(); + ProgramCounter currentPC = curr - bytecode.begin(); validJumpTargets[currentPC] = 1; auto inst = static_cast(*curr); @@ -51,7 +51,7 @@ void Compiler::createBasicBlocks(const bytes& bytecode) { auto numBytes = static_cast(inst) - static_cast(Instruction::PUSH1) + 1; auto next = curr + numBytes + 1; - if (next >= bytecode.cend()) + if (next >= bytecode.end()) break; auto nextInst = static_cast(*next); @@ -72,7 +72,7 @@ void Compiler::createBasicBlocks(const bytes& bytecode) targetPC = bytecode.size(); splitPoints.insert(targetPC); - ProgramCounter jumpPC = (next - bytecode.cbegin()); + ProgramCounter jumpPC = (next - bytecode.begin()); directJumpTargets[jumpPC] = targetPC; } @@ -95,7 +95,7 @@ void Compiler::createBasicBlocks(const bytes& bytecode) case Instruction::SUICIDE: { // Create a basic block starting at the following instruction. - if (curr + 1 < bytecode.cend()) + if (curr + 1 < bytecode.end()) { splitPoints.insert(currentPC + 1); } @@ -149,7 +149,7 @@ void Compiler::createBasicBlocks(const bytes& bytecode) } } -std::unique_ptr Compiler::compile(const bytes& bytecode) +std::unique_ptr Compiler::compile(bytesConstRef bytecode) { auto module = std::make_unique("main", m_builder.getContext()); @@ -214,7 +214,7 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) } -void Compiler::compileBasicBlock(BasicBlock& basicBlock, const bytes& bytecode, Memory& memory, Ext& ext, GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock) +void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, Memory& memory, Ext& ext, GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock) { auto& stack = basicBlock.getStack(); m_builder.SetInsertPoint(basicBlock.llvm()); diff --git a/libevmjit/Compiler.h b/libevmjit/Compiler.h index bda154689..f708898d6 100644 --- a/libevmjit/Compiler.h +++ b/libevmjit/Compiler.h @@ -22,16 +22,16 @@ public: Compiler(); - std::unique_ptr compile(const bytes& bytecode); + std::unique_ptr compile(bytesConstRef bytecode); void dumpBasicBlockGraph(std::ostream& out); private: - void createBasicBlocks(const bytes& bytecode); + void createBasicBlocks(bytesConstRef bytecode); - void compileBasicBlock(BasicBlock& basicBlock, const bytes& bytecode, class Memory& memory, class Ext& ext, class GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock); + void compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, class Memory& memory, class Ext& ext, class GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock); void linkBasicBlocks(); diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp index 6a494f42a..bac15a478 100644 --- a/libevmjit/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -125,7 +125,7 @@ int ExecutionEngine::run(std::unique_ptr _module) if (returnCode == ReturnCode::Return) { - auto&& returnData = Memory::getReturnData(); // TODO: It might be better to place is in Runtime interface + returnData = Memory::getReturnData().toVector(); // TODO: It might be better to place is in Runtime interface std::cout << "RETURN [ "; for (auto it = returnData.begin(), end = returnData.end(); it != end; ++it) diff --git a/libevmjit/ExecutionEngine.h b/libevmjit/ExecutionEngine.h index 158df0283..f6fb49276 100644 --- a/libevmjit/ExecutionEngine.h +++ b/libevmjit/ExecutionEngine.h @@ -18,6 +18,8 @@ public: ExecutionEngine(); int run(std::unique_ptr module); + + bytes returnData; }; } diff --git a/libevmjit/VM.cpp b/libevmjit/VM.cpp new file mode 100644 index 000000000..51cd7c5a3 --- /dev/null +++ b/libevmjit/VM.cpp @@ -0,0 +1,37 @@ + +#include "VM.h" + +#include + +#include "ExecutionEngine.h" +#include "Compiler.h" + +namespace dev +{ +namespace eth +{ +namespace jit +{ + +bytes VM::go(ExtVMFace& _ext) +{ + auto module = Compiler().compile(_ext.code); + module->dump(); + + ExecutionEngine engine; + auto exitCode = engine.run(std::move(module)); + + switch (exitCode) + { + case 101: + BOOST_THROW_EXCEPTION(BadJumpDestination()); + case 102: + BOOST_THROW_EXCEPTION(OutOfGas()); + } + + return std::move(engine.returnData); +} + +} +} +} diff --git a/libevmjit/VM.h b/libevmjit/VM.h new file mode 100644 index 000000000..3e7884b10 --- /dev/null +++ b/libevmjit/VM.h @@ -0,0 +1,32 @@ + +#pragma once + +#include +#include + +namespace dev +{ +namespace eth +{ +namespace jit +{ + +class VM +{ +public: + /// Construct VM object. + explicit VM(u256 _gas = 0): m_gas(_gas) {} + + void reset(u256 _gas = 0) { m_gas = _gas; } + + bytes go(ExtVMFace& _ext); + + u256 gas() const { return m_gas; } + +private: + u256 m_gas = 0; +}; + +} +} +} diff --git a/windows/LibEvmJit.vcxproj b/windows/LibEvmJit.vcxproj index 17832d871..1c71bb082 100644 --- a/windows/LibEvmJit.vcxproj +++ b/windows/LibEvmJit.vcxproj @@ -133,6 +133,7 @@ + @@ -145,6 +146,7 @@ + diff --git a/windows/LibEvmJit.vcxproj.filters b/windows/LibEvmJit.vcxproj.filters index e24e4379e..a2008f971 100644 --- a/windows/LibEvmJit.vcxproj.filters +++ b/windows/LibEvmJit.vcxproj.filters @@ -36,6 +36,9 @@ libevmjit + + libevmjit + @@ -68,5 +71,8 @@ libevmjit + + libevmjit + \ No newline at end of file From 5dbc877b294bf536dc988aa358deeb55a330e38b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 16 Oct 2014 18:19:58 +0200 Subject: [PATCH 144/641] test/rlp bugfix: expectedText can be empty --- test/rlp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rlp.cpp b/test/rlp.cpp index 95d40ada7..69360ad66 100644 --- a/test/rlp.cpp +++ b/test/rlp.cpp @@ -79,7 +79,7 @@ namespace dev if ( v.type() == js::str_type ) { const std::string& expectedText = v.get_str(); - if ( expectedText.front() == '#' ) + if ( !expectedText.empty() && expectedText.front() == '#' ) { // Deal with bigint instead of a raw string std::string bigIntStr = expectedText.substr(1,expectedText.length()-1); From 1a18343612a9378591cacce0f76e8270a1ba73d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 16 Oct 2014 18:20:49 +0200 Subject: [PATCH 145/641] Prepare VM test engine for running JIT-ed tests --- test/vm.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/test/vm.cpp b/test/vm.cpp index cc87866df..d77906731 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -493,7 +493,6 @@ void doTests(json_spirit::mValue& v, bool _fillin) BOOST_REQUIRE(o.count("pre") > 0); BOOST_REQUIRE(o.count("exec") > 0); - VM vm; dev::test::FakeExtVM fev; fev.importEnv(o["env"].get_obj()); fev.importState(o["pre"].get_obj()); @@ -508,11 +507,13 @@ void doTests(json_spirit::mValue& v, bool _fillin) fev.code = &fev.thisTxCode; } - vm.reset(fev.gas); bytes output; + u256 gas; try { - output = vm.go(fev).toBytes(); + VM vm(fev.gas); + output = vm.go(fev).toVector(); + gas = vm.gas(); // Get the remaining gas } catch (Exception const& _e) { @@ -549,7 +550,7 @@ void doTests(json_spirit::mValue& v, bool _fillin) o["post"] = mValue(fev.exportState()); o["callcreates"] = fev.exportCallCreates(); o["out"] = "0x" + toHex(output); - fev.push(o, "gas", vm.gas()); + fev.push(o, "gas", gas); } else { @@ -573,7 +574,7 @@ void doTests(json_spirit::mValue& v, bool _fillin) else BOOST_CHECK(output == fromHex(o["out"].get_str())); - BOOST_CHECK(test.toInt(o["gas"]) == vm.gas()); + BOOST_CHECK(test.toInt(o["gas"]) == gas); BOOST_CHECK(test.addresses == fev.addresses); BOOST_CHECK(test.callcreates == fev.callcreates); } From f8e7689d17acbd19005da8b4ea05961e1e9c2384 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 17 Oct 2014 10:51:58 +0200 Subject: [PATCH 146/641] Fix GasMeter not nulling cost call --- libevmjit/GasMeter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libevmjit/GasMeter.cpp b/libevmjit/GasMeter.cpp index 13c27118f..53c1e30e5 100644 --- a/libevmjit/GasMeter.cpp +++ b/libevmjit/GasMeter.cpp @@ -168,6 +168,7 @@ void GasMeter::commitCostBlock(llvm::Value* _additionalCost) if (m_blockCost == 0 && !_additionalCost) // Do not check 0 { m_checkCall->eraseFromParent(); // Remove the gas check call + m_checkCall = nullptr; return; } From 05964dccf7917f415197e7e3a4103512573a3357 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 17 Oct 2014 10:52:35 +0200 Subject: [PATCH 147/641] Fix not allocated arg8 for CALL --- libevmjit/Ext.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 5307bc191..5c4bb7c59 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -61,7 +61,7 @@ Ext::Ext(llvm::IRBuilder<>& _builder): m_arg5 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg5"); m_arg6 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg6"); m_arg7 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg7"); - m_arg7 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg8"); + m_arg8 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg8"); Type* elements[] = { i256Ty, // i256 address; From 0e56f2609d9cc1759928b657440b6397435670d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 17 Oct 2014 10:58:10 +0200 Subject: [PATCH 148/641] Running vm_tests with JIT --- test/vm.cpp | 17 ++++++++++++++--- windows/Ethereum.sln | 3 +++ windows/TestEthereum.vcxproj | 3 +++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/test/vm.cpp b/test/vm.cpp index d77906731..a7b785240 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -22,6 +22,7 @@ #include "vm.h" #include +#include #define FILL_TESTS @@ -511,9 +512,19 @@ void doTests(json_spirit::mValue& v, bool _fillin) u256 gas; try { - VM vm(fev.gas); - output = vm.go(fev).toVector(); - gas = vm.gas(); // Get the remaining gas + auto useJit = true; + if (useJit) + { + jit::VM vm(fev.gas); + output = vm.go(fev); + gas = vm.gas(); + } + else + { + VM vm(fev.gas); + output = vm.go(fev).toVector(); + gas = vm.gas(); // Get the remaining gas + } } catch (Exception const& _e) { diff --git a/windows/Ethereum.sln b/windows/Ethereum.sln index 11ced4384..33167a23b 100644 --- a/windows/Ethereum.sln +++ b/windows/Ethereum.sln @@ -16,6 +16,9 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestSecp256k1", "TestSecp256k1.vcxproj", "{3BF049F8-AF7E-4E1C-9627-3E94C887AF24}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestEthereum", "TestEthereum.vcxproj", "{3F3E389B-88DE-41D5-A73B-4F6036E18B36}" + ProjectSection(ProjectDependencies) = postProject + {9C816740-5C11-4377-A3A7-46BE12F35FA0} = {9C816740-5C11-4377-A3A7-46BE12F35FA0} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibCryptoPP", "LibCryptoPP.vcxproj", "{1CC213A4-3482-4211-B47B-172E90DAC7DE}" EndProject diff --git a/windows/TestEthereum.vcxproj b/windows/TestEthereum.vcxproj index 172e6be86..b07124581 100644 --- a/windows/TestEthereum.vcxproj +++ b/windows/TestEthereum.vcxproj @@ -55,6 +55,7 @@ + @@ -107,6 +108,8 @@ Console true + LibEthereum.lib;LibEvmJit.lib;LibSecp256k1.lib;LibCryptoPP.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) + ../../builds/llvm3.5/Debug/lib;../../_build/LibEvmJit/x64_Debug;../../_build/LibEthereum/x64_Debug;../../_build/LibSecp256k1/x64_Debug;../../_build/LibCryptoPP/x64_Debug;%(AdditionalLibraryDirectories) From 138ef80577bce0790654bcfc367ecefcdf91fb18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 17 Oct 2014 11:28:16 +0200 Subject: [PATCH 149/641] Tests moved to test/ folder --- evmcc/bytecode/if1.evm | 1 - evmcc/lll/if1.asm | 21 ------------------- evmcc/lll/if1.lll | 5 ----- .../arith/arith1.evm} | 0 .../arith/arith1.lll} | 0 evmcc/{bytecode => test/arith}/fib1.evm | 0 evmcc/{lll => test/arith}/fib1.lll | 0 evmcc/{bytecode => test/ext}/ext_test.evm | 0 evmcc/{lll => test/ext}/ext_test.lll | 0 evmcc/{bytecode => test/ext}/store_test.evm | 0 evmcc/{lll => test/ext}/store_test.lll | 0 evmcc/{bytecode => test/jump}/for1.evm | 0 evmcc/{lll => test/jump}/for1.lll | 0 evmcc/{bytecode => test/jump}/for2.evm | 0 evmcc/{lll => test/jump}/for2.lll | 0 evmcc/{lll => test/jump}/when1.asm | 0 evmcc/{bytecode => test/jump}/when1.evm | 0 evmcc/{lll => test/jump}/when1.lll | 0 evmcc/{bytecode => test}/kv.evm | 0 evmcc/{lll => test}/kv.lll | 0 evmcc/{bytecode => test/mem}/byte.evm | 0 evmcc/{lll => test/mem}/byte.lll | 0 evmcc/{bytecode => test/mem}/mem2.evm | 0 evmcc/{lll => test/mem}/mem2.lll | 0 evmcc/{bytecode => test/mem}/memtest1.evm | 0 evmcc/{lll => test/mem}/memtest1.lll | 0 evmcc/{bytecode => test/ret}/return1.evm | 0 evmcc/{lll => test/ret}/return1.lll | 0 evmcc/{bytecode => test/ret}/return2.evm | 0 evmcc/{lll => test/ret}/return2.lll | 0 evmcc/{bytecode => test/ret}/return_test.evm | 0 evmcc/{lll => test/ret}/return_test.lll | 0 evmcc/{bytecode => test/stack}/push_test.evm | 0 evmcc/{lll => test/stack}/push_test.lll | 0 evmcc/{bytecode => test/stack}/stack_test.evm | 0 evmcc/{lll => test/stack}/stack_test.lll | 0 evmcc/{bytecode => test/stack}/stackjump.evm | 0 evmcc/{lll => test/stack}/stackjump.lll | 0 38 files changed, 27 deletions(-) delete mode 100644 evmcc/bytecode/if1.evm delete mode 100644 evmcc/lll/if1.asm delete mode 100644 evmcc/lll/if1.lll rename evmcc/{bytecode/arithmetic_test.evm => test/arith/arith1.evm} (100%) rename evmcc/{lll/arithmetic_test.lll => test/arith/arith1.lll} (100%) rename evmcc/{bytecode => test/arith}/fib1.evm (100%) rename evmcc/{lll => test/arith}/fib1.lll (100%) rename evmcc/{bytecode => test/ext}/ext_test.evm (100%) rename evmcc/{lll => test/ext}/ext_test.lll (100%) rename evmcc/{bytecode => test/ext}/store_test.evm (100%) rename evmcc/{lll => test/ext}/store_test.lll (100%) rename evmcc/{bytecode => test/jump}/for1.evm (100%) rename evmcc/{lll => test/jump}/for1.lll (100%) rename evmcc/{bytecode => test/jump}/for2.evm (100%) rename evmcc/{lll => test/jump}/for2.lll (100%) rename evmcc/{lll => test/jump}/when1.asm (100%) rename evmcc/{bytecode => test/jump}/when1.evm (100%) rename evmcc/{lll => test/jump}/when1.lll (100%) rename evmcc/{bytecode => test}/kv.evm (100%) rename evmcc/{lll => test}/kv.lll (100%) rename evmcc/{bytecode => test/mem}/byte.evm (100%) rename evmcc/{lll => test/mem}/byte.lll (100%) rename evmcc/{bytecode => test/mem}/mem2.evm (100%) rename evmcc/{lll => test/mem}/mem2.lll (100%) rename evmcc/{bytecode => test/mem}/memtest1.evm (100%) rename evmcc/{lll => test/mem}/memtest1.lll (100%) rename evmcc/{bytecode => test/ret}/return1.evm (100%) rename evmcc/{lll => test/ret}/return1.lll (100%) rename evmcc/{bytecode => test/ret}/return2.evm (100%) rename evmcc/{lll => test/ret}/return2.lll (100%) rename evmcc/{bytecode => test/ret}/return_test.evm (100%) rename evmcc/{lll => test/ret}/return_test.lll (100%) rename evmcc/{bytecode => test/stack}/push_test.evm (100%) rename evmcc/{lll => test/stack}/push_test.lll (100%) rename evmcc/{bytecode => test/stack}/stack_test.evm (100%) rename evmcc/{lll => test/stack}/stack_test.lll (100%) rename evmcc/{bytecode => test/stack}/stackjump.evm (100%) rename evmcc/{lll => test/stack}/stackjump.lll (100%) diff --git a/evmcc/bytecode/if1.evm b/evmcc/bytecode/if1.evm deleted file mode 100644 index ee9009294..000000000 --- a/evmcc/bytecode/if1.evm +++ /dev/null @@ -1 +0,0 @@ -600160805460006080530b6016596003608054601b586002608054 diff --git a/evmcc/lll/if1.asm b/evmcc/lll/if1.asm deleted file mode 100644 index 4a938adce..000000000 --- a/evmcc/lll/if1.asm +++ /dev/null @@ -1,21 +0,0 @@ -.code: - PUSH 1 - PUSH 128 - MSTORE - PUSH 0 - PUSH 128 - MLOAD - GT - PUSH [tag0] - JUMPI - PUSH 3 - PUSH 128 - MSTORE - PUSH [tag1] - JUMP -tag0: - PUSH 2 - PUSH 128 - MSTORE -tag1: - diff --git a/evmcc/lll/if1.lll b/evmcc/lll/if1.lll deleted file mode 100644 index 7984807c1..000000000 --- a/evmcc/lll/if1.lll +++ /dev/null @@ -1,5 +0,0 @@ -{ - [i] 1 - - ( if (> @i 0) [i] 2 [i] 3 ) -} diff --git a/evmcc/bytecode/arithmetic_test.evm b/evmcc/test/arith/arith1.evm similarity index 100% rename from evmcc/bytecode/arithmetic_test.evm rename to evmcc/test/arith/arith1.evm diff --git a/evmcc/lll/arithmetic_test.lll b/evmcc/test/arith/arith1.lll similarity index 100% rename from evmcc/lll/arithmetic_test.lll rename to evmcc/test/arith/arith1.lll diff --git a/evmcc/bytecode/fib1.evm b/evmcc/test/arith/fib1.evm similarity index 100% rename from evmcc/bytecode/fib1.evm rename to evmcc/test/arith/fib1.evm diff --git a/evmcc/lll/fib1.lll b/evmcc/test/arith/fib1.lll similarity index 100% rename from evmcc/lll/fib1.lll rename to evmcc/test/arith/fib1.lll diff --git a/evmcc/bytecode/ext_test.evm b/evmcc/test/ext/ext_test.evm similarity index 100% rename from evmcc/bytecode/ext_test.evm rename to evmcc/test/ext/ext_test.evm diff --git a/evmcc/lll/ext_test.lll b/evmcc/test/ext/ext_test.lll similarity index 100% rename from evmcc/lll/ext_test.lll rename to evmcc/test/ext/ext_test.lll diff --git a/evmcc/bytecode/store_test.evm b/evmcc/test/ext/store_test.evm similarity index 100% rename from evmcc/bytecode/store_test.evm rename to evmcc/test/ext/store_test.evm diff --git a/evmcc/lll/store_test.lll b/evmcc/test/ext/store_test.lll similarity index 100% rename from evmcc/lll/store_test.lll rename to evmcc/test/ext/store_test.lll diff --git a/evmcc/bytecode/for1.evm b/evmcc/test/jump/for1.evm similarity index 100% rename from evmcc/bytecode/for1.evm rename to evmcc/test/jump/for1.evm diff --git a/evmcc/lll/for1.lll b/evmcc/test/jump/for1.lll similarity index 100% rename from evmcc/lll/for1.lll rename to evmcc/test/jump/for1.lll diff --git a/evmcc/bytecode/for2.evm b/evmcc/test/jump/for2.evm similarity index 100% rename from evmcc/bytecode/for2.evm rename to evmcc/test/jump/for2.evm diff --git a/evmcc/lll/for2.lll b/evmcc/test/jump/for2.lll similarity index 100% rename from evmcc/lll/for2.lll rename to evmcc/test/jump/for2.lll diff --git a/evmcc/lll/when1.asm b/evmcc/test/jump/when1.asm similarity index 100% rename from evmcc/lll/when1.asm rename to evmcc/test/jump/when1.asm diff --git a/evmcc/bytecode/when1.evm b/evmcc/test/jump/when1.evm similarity index 100% rename from evmcc/bytecode/when1.evm rename to evmcc/test/jump/when1.evm diff --git a/evmcc/lll/when1.lll b/evmcc/test/jump/when1.lll similarity index 100% rename from evmcc/lll/when1.lll rename to evmcc/test/jump/when1.lll diff --git a/evmcc/bytecode/kv.evm b/evmcc/test/kv.evm similarity index 100% rename from evmcc/bytecode/kv.evm rename to evmcc/test/kv.evm diff --git a/evmcc/lll/kv.lll b/evmcc/test/kv.lll similarity index 100% rename from evmcc/lll/kv.lll rename to evmcc/test/kv.lll diff --git a/evmcc/bytecode/byte.evm b/evmcc/test/mem/byte.evm similarity index 100% rename from evmcc/bytecode/byte.evm rename to evmcc/test/mem/byte.evm diff --git a/evmcc/lll/byte.lll b/evmcc/test/mem/byte.lll similarity index 100% rename from evmcc/lll/byte.lll rename to evmcc/test/mem/byte.lll diff --git a/evmcc/bytecode/mem2.evm b/evmcc/test/mem/mem2.evm similarity index 100% rename from evmcc/bytecode/mem2.evm rename to evmcc/test/mem/mem2.evm diff --git a/evmcc/lll/mem2.lll b/evmcc/test/mem/mem2.lll similarity index 100% rename from evmcc/lll/mem2.lll rename to evmcc/test/mem/mem2.lll diff --git a/evmcc/bytecode/memtest1.evm b/evmcc/test/mem/memtest1.evm similarity index 100% rename from evmcc/bytecode/memtest1.evm rename to evmcc/test/mem/memtest1.evm diff --git a/evmcc/lll/memtest1.lll b/evmcc/test/mem/memtest1.lll similarity index 100% rename from evmcc/lll/memtest1.lll rename to evmcc/test/mem/memtest1.lll diff --git a/evmcc/bytecode/return1.evm b/evmcc/test/ret/return1.evm similarity index 100% rename from evmcc/bytecode/return1.evm rename to evmcc/test/ret/return1.evm diff --git a/evmcc/lll/return1.lll b/evmcc/test/ret/return1.lll similarity index 100% rename from evmcc/lll/return1.lll rename to evmcc/test/ret/return1.lll diff --git a/evmcc/bytecode/return2.evm b/evmcc/test/ret/return2.evm similarity index 100% rename from evmcc/bytecode/return2.evm rename to evmcc/test/ret/return2.evm diff --git a/evmcc/lll/return2.lll b/evmcc/test/ret/return2.lll similarity index 100% rename from evmcc/lll/return2.lll rename to evmcc/test/ret/return2.lll diff --git a/evmcc/bytecode/return_test.evm b/evmcc/test/ret/return_test.evm similarity index 100% rename from evmcc/bytecode/return_test.evm rename to evmcc/test/ret/return_test.evm diff --git a/evmcc/lll/return_test.lll b/evmcc/test/ret/return_test.lll similarity index 100% rename from evmcc/lll/return_test.lll rename to evmcc/test/ret/return_test.lll diff --git a/evmcc/bytecode/push_test.evm b/evmcc/test/stack/push_test.evm similarity index 100% rename from evmcc/bytecode/push_test.evm rename to evmcc/test/stack/push_test.evm diff --git a/evmcc/lll/push_test.lll b/evmcc/test/stack/push_test.lll similarity index 100% rename from evmcc/lll/push_test.lll rename to evmcc/test/stack/push_test.lll diff --git a/evmcc/bytecode/stack_test.evm b/evmcc/test/stack/stack_test.evm similarity index 100% rename from evmcc/bytecode/stack_test.evm rename to evmcc/test/stack/stack_test.evm diff --git a/evmcc/lll/stack_test.lll b/evmcc/test/stack/stack_test.lll similarity index 100% rename from evmcc/lll/stack_test.lll rename to evmcc/test/stack/stack_test.lll diff --git a/evmcc/bytecode/stackjump.evm b/evmcc/test/stack/stackjump.evm similarity index 100% rename from evmcc/bytecode/stackjump.evm rename to evmcc/test/stack/stackjump.evm diff --git a/evmcc/lll/stackjump.lll b/evmcc/test/stack/stackjump.lll similarity index 100% rename from evmcc/lll/stackjump.lll rename to evmcc/test/stack/stackjump.lll From 23c54b6ee463049d5fc6e7c2ad672f21b20598bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 17 Oct 2014 11:29:20 +0200 Subject: [PATCH 150/641] Using ExtVM provided by test engine --- libevmjit/ExecutionEngine.cpp | 39 +++++++++++++++++++---------------- libevmjit/ExecutionEngine.h | 3 ++- libevmjit/Runtime.cpp | 6 +++--- libevmjit/Runtime.h | 4 ++-- libevmjit/VM.cpp | 2 +- 5 files changed, 29 insertions(+), 25 deletions(-) diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp index bac15a478..252cf7aff 100644 --- a/libevmjit/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -36,7 +36,7 @@ ExecutionEngine::ExecutionEngine() extern "C" { EXPORT std::jmp_buf* rt_jmpBuf; } -int ExecutionEngine::run(std::unique_ptr _module) +int ExecutionEngine::run(std::unique_ptr _module, ExtVMFace* _ext) { auto module = _module.get(); // Keep ownership of the module in _module @@ -81,26 +81,29 @@ int ExecutionEngine::run(std::unique_ptr _module) exec->finalizeObject(); // Create fake ExtVM interface - auto ext = std::make_unique(); - ext->myAddress = Address(1122334455667788); - ext->caller = Address(0xfacefacefaceface); - ext->origin = Address(101010101010101010); - ext->value = 0xabcd; - ext->gasPrice = 1002; - ext->previousBlock.hash = u256(1003); - ext->currentBlock.coinbaseAddress = Address(1004); - ext->currentBlock.timestamp = 1005; - ext->currentBlock.number = 1006; - ext->currentBlock.difficulty = 1007; - ext->currentBlock.gasLimit = 1008; - std::string calldata = "Hello the Beautiful World of Ethereum!"; - ext->data = calldata; - unsigned char fakecode[] = {0x0d, 0x0e, 0x0a, 0x0d, 0x0b, 0x0e, 0xe, 0xf}; - ext->code = decltype(ext->code)(fakecode, 8); + if (!_ext) + { + auto _ext = new ExtVMFace; + _ext->myAddress = Address(1122334455667788); + _ext->caller = Address(0xfacefacefaceface); + _ext->origin = Address(101010101010101010); + _ext->value = 0xabcd; + _ext->gasPrice = 1002; + _ext->previousBlock.hash = u256(1003); + _ext->currentBlock.coinbaseAddress = Address(1004); + _ext->currentBlock.timestamp = 1005; + _ext->currentBlock.number = 1006; + _ext->currentBlock.difficulty = 1007; + _ext->currentBlock.gasLimit = 1008; + std::string calldata = "Hello the Beautiful World of Ethereum!"; + _ext->data = calldata; + unsigned char fakecode[] = {0x0d, 0x0e, 0x0a, 0x0d, 0x0b, 0x0e, 0xe, 0xf}; + _ext->code = decltype(_ext->code)(fakecode, 8); + } // Init runtime uint64_t gas = 100; - Runtime runtime(gas, std::move(ext)); + Runtime runtime(gas, *_ext); auto entryFunc = module->getFunction("main"); if (!entryFunc) diff --git a/libevmjit/ExecutionEngine.h b/libevmjit/ExecutionEngine.h index f6fb49276..12ca66302 100644 --- a/libevmjit/ExecutionEngine.h +++ b/libevmjit/ExecutionEngine.h @@ -4,6 +4,7 @@ #include #include +#include namespace dev { @@ -17,7 +18,7 @@ class ExecutionEngine public: ExecutionEngine(); - int run(std::unique_ptr module); + int run(std::unique_ptr module, ExtVMFace* _ext = nullptr); bytes returnData; }; diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index d85f484b3..448d25f92 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -19,8 +19,8 @@ extern "C" EXPORT i256 gas; } -Runtime::Runtime(u256 _gas, std::unique_ptr _ext): - m_ext(std::move(_ext)) +Runtime::Runtime(u256 _gas, ExtVMFace& _ext): + m_ext(_ext) { assert(!g_runtime); g_runtime = this; @@ -44,7 +44,7 @@ MemoryImpl& Runtime::getMemory() ExtVMFace& Runtime::getExt() { - return *g_runtime->m_ext; + return g_runtime->m_ext; } u256 Runtime::getGas() diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index 0312e305b..165f47e06 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -27,7 +27,7 @@ using MemoryImpl = bytes; class Runtime { public: - Runtime(u256 _gas, std::unique_ptr _ext); + Runtime(u256 _gas, ExtVMFace& _ext); ~Runtime(); Runtime(const Runtime&) = delete; @@ -41,7 +41,7 @@ public: private: StackImpl m_stack; MemoryImpl m_memory; - std::unique_ptr m_ext; + ExtVMFace& m_ext; }; } diff --git a/libevmjit/VM.cpp b/libevmjit/VM.cpp index 51cd7c5a3..b4139f8bf 100644 --- a/libevmjit/VM.cpp +++ b/libevmjit/VM.cpp @@ -19,7 +19,7 @@ bytes VM::go(ExtVMFace& _ext) module->dump(); ExecutionEngine engine; - auto exitCode = engine.run(std::move(module)); + auto exitCode = engine.run(std::move(module), &_ext); switch (exitCode) { From 9a3a62cccdb2c88e99b78b2b8e799bff4a0254d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 17 Oct 2014 11:59:12 +0200 Subject: [PATCH 151/641] Using gas provided by test engine and fix for creating fake ExtVMFace. --- evmcc/evmcc.cpp | 3 ++- libevmjit/ExecutionEngine.cpp | 9 ++++----- libevmjit/ExecutionEngine.h | 2 +- libevmjit/VM.cpp | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/evmcc/evmcc.cpp b/evmcc/evmcc.cpp index 600980d44..9cf731419 100644 --- a/evmcc/evmcc.cpp +++ b/evmcc/evmcc.cpp @@ -112,7 +112,8 @@ int main(int argc, char** argv) auto engine = eth::jit::ExecutionEngine(); auto module = eth::jit::Compiler().compile({bytecode.data(), bytecode.size()}); module->dump(); - auto result = engine.run(std::move(module)); + u256 gas = 10000; + auto result = engine.run(std::move(module), gas); return result; } diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp index 252cf7aff..5390d82dd 100644 --- a/libevmjit/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -36,7 +36,7 @@ ExecutionEngine::ExecutionEngine() extern "C" { EXPORT std::jmp_buf* rt_jmpBuf; } -int ExecutionEngine::run(std::unique_ptr _module, ExtVMFace* _ext) +int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, ExtVMFace* _ext) { auto module = _module.get(); // Keep ownership of the module in _module @@ -83,7 +83,7 @@ int ExecutionEngine::run(std::unique_ptr _module, ExtVMFace* _ext) // Create fake ExtVM interface if (!_ext) { - auto _ext = new ExtVMFace; + _ext = new ExtVMFace; _ext->myAddress = Address(1122334455667788); _ext->caller = Address(0xfacefacefaceface); _ext->origin = Address(101010101010101010); @@ -102,8 +102,7 @@ int ExecutionEngine::run(std::unique_ptr _module, ExtVMFace* _ext) } // Init runtime - uint64_t gas = 100; - Runtime runtime(gas, *_ext); + Runtime runtime(_gas, *_ext); auto entryFunc = module->getFunction("main"); if (!entryFunc) @@ -124,7 +123,7 @@ int ExecutionEngine::run(std::unique_ptr _module, ExtVMFace* _ext) else returnCode = static_cast(r); - gas = static_cast(Runtime::getGas()); + _gas = Runtime::getGas(); if (returnCode == ReturnCode::Return) { diff --git a/libevmjit/ExecutionEngine.h b/libevmjit/ExecutionEngine.h index 12ca66302..15a4e6ef7 100644 --- a/libevmjit/ExecutionEngine.h +++ b/libevmjit/ExecutionEngine.h @@ -18,7 +18,7 @@ class ExecutionEngine public: ExecutionEngine(); - int run(std::unique_ptr module, ExtVMFace* _ext = nullptr); + int run(std::unique_ptr module, u256& _gas, ExtVMFace* _ext = nullptr); bytes returnData; }; diff --git a/libevmjit/VM.cpp b/libevmjit/VM.cpp index b4139f8bf..9e06fb6d0 100644 --- a/libevmjit/VM.cpp +++ b/libevmjit/VM.cpp @@ -19,7 +19,7 @@ bytes VM::go(ExtVMFace& _ext) module->dump(); ExecutionEngine engine; - auto exitCode = engine.run(std::move(module), &_ext); + auto exitCode = engine.run(std::move(module), m_gas, &_ext); switch (exitCode) { From ac276eaccee8b86df169d9af545e71a63ed18ddf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 17 Oct 2014 12:30:42 +0200 Subject: [PATCH 152/641] Do not try to add additional cost (call instruction) to cost-block --- libevmjit/GasMeter.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/libevmjit/GasMeter.cpp b/libevmjit/GasMeter.cpp index 53c1e30e5..ac7f47d19 100644 --- a/libevmjit/GasMeter.cpp +++ b/libevmjit/GasMeter.cpp @@ -165,20 +165,21 @@ void GasMeter::commitCostBlock(llvm::Value* _additionalCost) // If any uncommited block if (m_checkCall) { - if (m_blockCost == 0 && !_additionalCost) // Do not check 0 + if (m_blockCost == 0) // Do not check 0 { m_checkCall->eraseFromParent(); // Remove the gas check call m_checkCall = nullptr; return; } - llvm::Value* cost = Constant::get(m_blockCost); - if (_additionalCost) - cost = m_builder.CreateAdd(cost, _additionalCost); - - m_checkCall->setArgOperand(0, cost); // Update block cost in gas check call + m_checkCall->setArgOperand(0, Constant::get(m_blockCost)); // Update block cost in gas check call m_checkCall = nullptr; // End cost-block m_blockCost = 0; + + if (_additionalCost) + { + m_builder.CreateCall(m_gasCheckFunc, _additionalCost); + } } assert(m_blockCost == 0); } From a13a660315342f9db821bfc70c387f23ebd72d37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 17 Oct 2014 13:12:36 +0200 Subject: [PATCH 153/641] Fix for invalid jump table basic block --- libevmjit/Compiler.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index cbb6118f4..1e76e2fb7 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -927,6 +927,13 @@ void Compiler::linkBasicBlocks() completePhiNodes(*it); } } + + // Remove jump table block if not predecessors + if (llvm::pred_begin(m_jumpTableBlock->llvm()) == llvm::pred_end(m_jumpTableBlock->llvm())) + { + m_jumpTableBlock->llvm()->eraseFromParent(); + m_jumpTableBlock.reset(); + } } void Compiler::dumpBasicBlockGraph(std::ostream& out) From 008953a37c24e01f98a2c8296b09d662d9eaa0da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 17 Oct 2014 13:26:53 +0200 Subject: [PATCH 154/641] Limit debug output --- libevmjit/Compiler.cpp | 3 ++- libevmjit/VM.cpp | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 1e76e2fb7..3d5d7b275 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -923,7 +923,8 @@ void Compiler::linkBasicBlocks() for (auto it = llvm::po_ext_begin(bb.second.llvm(), visitSet), end = llvm::po_ext_end(bb.second.llvm(), visitSet); it != end; ++it) { - std::cerr << it->getName().str() << std::endl; + // TODO: Use logger + //std::cerr << it->getName().str() << std::endl; completePhiNodes(*it); } } diff --git a/libevmjit/VM.cpp b/libevmjit/VM.cpp index 9e06fb6d0..6b8b3e38b 100644 --- a/libevmjit/VM.cpp +++ b/libevmjit/VM.cpp @@ -16,7 +16,6 @@ namespace jit bytes VM::go(ExtVMFace& _ext) { auto module = Compiler().compile(_ext.code); - module->dump(); ExecutionEngine engine; auto exitCode = engine.run(std::move(module), m_gas, &_ext); From bcc6cd7056faf6b49ecbd9baca2f687dbb206780 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 17 Oct 2014 13:58:45 +0200 Subject: [PATCH 155/641] Turn on JIT testing with "--jit" command line parameter --- test/vm.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/vm.cpp b/test/vm.cpp index a7b785240..637ee77e9 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -512,7 +512,10 @@ void doTests(json_spirit::mValue& v, bool _fillin) u256 gas; try { - auto useJit = true; + auto argc = boost::unit_test::framework::master_test_suite().argc; + auto argv = boost::unit_test::framework::master_test_suite().argv; + + auto useJit = argc >= 2 && std::string(argv[1]) == "--jit"; if (useJit) { jit::VM vm(fev.gas); From 03f4a451aa00d7445b1577f87cd17c4a3c9a1e2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 17 Oct 2014 15:58:20 +0200 Subject: [PATCH 156/641] Add support for direct jump outside the code - terminates with STOP --- libevmjit/Compiler.cpp | 21 +++++++++++++-------- libevmjit/Compiler.h | 2 +- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 3d5d7b275..63ba83a77 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -67,9 +67,7 @@ void Compiler::createBasicBlocks(bytesConstRef bytecode) } // Create a block for the JUMP target. - ProgramCounter targetPC = val.convert_to(); - if (targetPC > bytecode.size()) - targetPC = bytecode.size(); + ProgramCounter targetPC = val < bytecode.size() ? val.convert_to() : bytecode.size(); splitPoints.insert(targetPC); ProgramCounter jumpPC = (next - bytecode.begin()); @@ -130,16 +128,23 @@ void Compiler::createBasicBlocks(bytesConstRef bytecode) for (auto it = directJumpTargets.cbegin(); it != directJumpTargets.cend(); ++it) { + if (it->second >= bytecode.size()) + { + // Jumping out of code means STOP + m_directJumpTargets[it->first] = m_stopBB; + continue; + } + auto blockIter = basicBlocks.find(it->second); if (blockIter != basicBlocks.end()) { - m_directJumpTargets[it->first] = &(blockIter->second); + m_directJumpTargets[it->first] = blockIter->second.llvm(); } else { std::cerr << "Bad JUMP at PC " << it->first << ": " << it->second << " is not a valid PC\n"; - m_directJumpTargets[it->first] = m_badJumpBlock.get(); + m_directJumpTargets[it->first] = m_badJumpBlock->llvm(); } } @@ -567,7 +572,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, // 1. this is not the first instruction in the block // 2. m_directJumpTargets[currentPC] is defined (meaning that the previous instruction is a PUSH) // Otherwise generate a indirect jump (a switch). - BasicBlock* targetBlock = nullptr; + llvm::BasicBlock* targetBlock = nullptr; if (currentPC != basicBlock.begin()) { auto pairIter = m_directJumpTargets.find(currentPC); @@ -584,7 +589,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, // The target address is computed at compile time, // just pop it without looking... stack.pop(); - m_builder.CreateBr(targetBlock->llvm()); + m_builder.CreateBr(targetBlock); } else { @@ -606,7 +611,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, if (targetBlock) { stack.pop(); - m_builder.CreateCondBr(cond, targetBlock->llvm(), nextBasicBlock); + m_builder.CreateCondBr(cond, targetBlock, nextBasicBlock); } else { diff --git a/libevmjit/Compiler.h b/libevmjit/Compiler.h index f708898d6..8972322ec 100644 --- a/libevmjit/Compiler.h +++ b/libevmjit/Compiler.h @@ -46,7 +46,7 @@ private: /** * Maps a pc at which there is a JUMP or JUMPI to the target block of the jump. */ - std::map m_directJumpTargets; + std::map m_directJumpTargets; /** * A list of possible blocks to which there may be indirect jumps. From a177ff9b126e2a9b8f7e738a16a77beb0b55d439 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 17 Oct 2014 16:07:53 +0200 Subject: [PATCH 157/641] Disable test filling --- test/vm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/vm.cpp b/test/vm.cpp index 637ee77e9..d65b5d3d5 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -24,7 +24,7 @@ #include #include -#define FILL_TESTS +//#define FILL_TESTS using namespace std; using namespace json_spirit; From b8e60e3f42356fb38c381298938e0a54171461d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 20 Oct 2014 16:08:15 +0200 Subject: [PATCH 158/641] Check if pushed item is a word --- libevmjit/BasicBlock.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libevmjit/BasicBlock.cpp b/libevmjit/BasicBlock.cpp index 02c85165d..736e0a572 100644 --- a/libevmjit/BasicBlock.cpp +++ b/libevmjit/BasicBlock.cpp @@ -32,6 +32,7 @@ BasicBlock::BasicBlock(std::string _name, llvm::Function* _mainFunc) : void BasicBlock::Stack::push(llvm::Value* _value) { + assert(_value->getType() == Type::i256); m_backend.push_back(_value); } From 86c42ce1fad36327dfa7cfc5ccf9daac46b9776d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 20 Oct 2014 16:08:59 +0200 Subject: [PATCH 159/641] Endianness handler --- libevmjit/Endianness.cpp | 24 ++++++++++++++++++++++++ libevmjit/Endianness.h | 22 ++++++++++++++++++++++ windows/LibEvmJit.vcxproj | 2 ++ windows/LibEvmJit.vcxproj.filters | 6 ++++++ 4 files changed, 54 insertions(+) create mode 100644 libevmjit/Endianness.cpp create mode 100644 libevmjit/Endianness.h diff --git a/libevmjit/Endianness.cpp b/libevmjit/Endianness.cpp new file mode 100644 index 000000000..7de7b9514 --- /dev/null +++ b/libevmjit/Endianness.cpp @@ -0,0 +1,24 @@ + +#include "Endianness.h" + +#include + +#include "Type.h" + +namespace dev +{ +namespace eth +{ +namespace jit +{ + +llvm::Value* Endianness::toBE(llvm::IRBuilder<>& _builder, llvm::Value* _word) +{ + // TODO: Native is Little Endian + auto bswap = llvm::Intrinsic::getDeclaration(_builder.GetInsertBlock()->getParent()->getParent(), llvm::Intrinsic::bswap, Type::i256); + return _builder.CreateCall(bswap, _word); +} + +} +} +} diff --git a/libevmjit/Endianness.h b/libevmjit/Endianness.h new file mode 100644 index 000000000..7b449b4d8 --- /dev/null +++ b/libevmjit/Endianness.h @@ -0,0 +1,22 @@ + +#pragma once + +#include + +namespace dev +{ +namespace eth +{ +namespace jit +{ + +class Endianness +{ +public: + + static llvm::Value* toBE(llvm::IRBuilder<>& _builder, llvm::Value* _word); +}; + +} +} +} diff --git a/windows/LibEvmJit.vcxproj b/windows/LibEvmJit.vcxproj index 1c71bb082..f516edf4f 100644 --- a/windows/LibEvmJit.vcxproj +++ b/windows/LibEvmJit.vcxproj @@ -126,6 +126,7 @@ + @@ -139,6 +140,7 @@ + diff --git a/windows/LibEvmJit.vcxproj.filters b/windows/LibEvmJit.vcxproj.filters index a2008f971..593ce8195 100644 --- a/windows/LibEvmJit.vcxproj.filters +++ b/windows/LibEvmJit.vcxproj.filters @@ -39,6 +39,9 @@ libevmjit + + libevmjit + @@ -74,5 +77,8 @@ libevmjit + + libevmjit + \ No newline at end of file From e34d69aeb0340bf827434138acf4357ab69f24de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 20 Oct 2014 16:14:11 +0200 Subject: [PATCH 160/641] BYTE reimplementation [Delivers #80911670] --- libevmjit/Compiler.cpp | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 63ba83a77..76daca792 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -15,6 +15,7 @@ #include "Ext.h" #include "GasMeter.h" #include "Utils.h" +#include "Endianness.h" namespace dev { @@ -420,21 +421,11 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, const auto byteNum = stack.pop(); auto value = stack.pop(); - /* - if (byteNum < 32) - use select - { - value <<= byteNum*8 - value >>= 31*8 - push value - } - else push 0 - */ - - // TODO: Shifting by 0 gives wrong results as of this bug http://llvm.org/bugs/show_bug.cgi?id=16439 - - auto shbits = m_builder.CreateShl(byteNum, Constant::get(3)); - value = m_builder.CreateShl(value, shbits); - value = m_builder.CreateLShr(value, Constant::get(31 * 8)); + // + 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"); + value = m_builder.CreateZExt(byte, Type::i256); auto byteNumValid = m_builder.CreateICmpULT(byteNum, Constant::get(32)); value = m_builder.CreateSelect(byteNumValid, value, Constant::get(0)); From c2669fe3a87b370cf23f64ccb12f1508984c5152 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 20 Oct 2014 16:15:27 +0200 Subject: [PATCH 161/641] Make ExtVMFace polymorphic to give JIT hope for working --- libevm/ExtVMFace.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h index 1b0f9eaf5..eeae720f3 100644 --- a/libevm/ExtVMFace.h +++ b/libevm/ExtVMFace.h @@ -57,37 +57,37 @@ public: ExtVMFace(Address _myAddress, Address _caller, Address _origin, u256 _value, u256 _gasPrice, bytesConstRef _data, bytesConstRef _code, BlockInfo const& _previousBlock, BlockInfo const& _currentBlock, unsigned _depth); /// Get the code at the given location in code ROM. - byte getCode(u256 _n) const { return _n < code.size() ? code[(unsigned)_n] : 0; } + virtual byte getCode(u256 _n) const { return _n < code.size() ? code[(unsigned)_n] : 0; } /// Read storage location. - u256 store(u256) { return 0; } + virtual u256 store(u256) { return 0; } /// Write a value in storage. - void setStore(u256, u256) {} + virtual void setStore(u256, u256) {} /// Read address's balance. - u256 balance(Address) { return 0; } + virtual u256 balance(Address) { return 0; } /// Read address's code. - bytes const& codeAt(Address) { return NullBytes; } + virtual bytes const& codeAt(Address) { return NullBytes; } /// Subtract amount from account's balance. - void subBalance(u256) {} + virtual void subBalance(u256) {} /// Determine account's TX count. - u256 txCount(Address) { return 0; } + virtual u256 txCount(Address) { return 0; } /// Suicide the associated contract and give proceeds to the given address. - void suicide(Address) { suicides.insert(myAddress); } + virtual void suicide(Address) { suicides.insert(myAddress); } /// Create a new (contract) account. - h160 create(u256, u256*, bytesConstRef, bytesConstRef) { return h160(); } + virtual h160 create(u256, u256*, bytesConstRef, bytesConstRef) { return h160(); } /// Make a new message call. - bool call(Address, u256, bytesConstRef, u256*, bytesRef, OnOpFunc const&, Address, Address) { return false; } + virtual bool call(Address, u256, bytesConstRef, u256*, bytesRef, OnOpFunc const&, Address, Address) { return false; } /// Revert any changes made (by any of the other calls). - void revert() {} + virtual void revert() {} Address myAddress; ///< Address associated with executing code (a contract, or contract-to-be). Address caller; ///< Address which sent the message (either equal to origin or a contract). From 40f23fceb364c0578f3fbd5550298ac2b26d8b28 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Mon, 20 Oct 2014 16:07:29 +0100 Subject: [PATCH 162/641] Defined dev::eth::FeeStructure::c_memoryGas and two other declared in FeeStructure. --- libevm/VM.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libevm/VM.cpp b/libevm/VM.cpp index e47237d5a..b2f7fea22 100644 --- a/libevm/VM.cpp +++ b/libevm/VM.cpp @@ -25,6 +25,10 @@ using namespace std; using namespace dev; using namespace dev::eth; +uint32_t const dev::eth::FeeStructure::c_memoryGas; +uint32_t const dev::eth::FeeStructure::c_txDataGas; +uint32_t const dev::eth::FeeStructure::c_txGas; + void VM::reset(u256 _gas) { m_gas = _gas; From 0abe8ab42e8ea8c9b0a2e9164352b7786887f40a Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Mon, 20 Oct 2014 16:12:00 +0100 Subject: [PATCH 163/641] Updated cmake files after moving the jit compiler to a lib. --- CMakeLists.txt | 1 + evmcc/CMakeLists.txt | 1 + test/CMakeLists.txt | 4 ++++ 3 files changed, 6 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3d055587c..150fb865c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -157,6 +157,7 @@ if (NOT LANGUAGES) endif() if (EVMCC) + add_subdirectory(libevmjit) add_subdirectory(evmcc) endif() diff --git a/evmcc/CMakeLists.txt b/evmcc/CMakeLists.txt index f09c327b8..ae9162162 100644 --- a/evmcc/CMakeLists.txt +++ b/evmcc/CMakeLists.txt @@ -12,6 +12,7 @@ target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} evm) target_link_libraries(${EXECUTABLE} evmface) +target_link_libraries(${EXECUTABLE} evmjit) if ("${TARGET_PLATFORM}" STREQUAL "w64") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 2e5366079..7dc226fb5 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -5,6 +5,8 @@ aux_source_directory(. SRC_LIST) include_directories(..) link_directories(../libethcore) link_directories(../libethereum) +link_directories(../libevm) +link_directories(../libevmjit) file(GLOB HEADERS "*.h") add_executable(testeth ${SRC_LIST} ${HEADERS}) @@ -14,6 +16,8 @@ target_link_libraries(testeth ethcore) target_link_libraries(testeth secp256k1) target_link_libraries(testeth gmp) target_link_libraries(testeth ${CRYPTOPP_LS}) +target_link_libraries(testeth evm) +target_link_libraries(testeth evmjit) if ("${TARGET_PLATFORM}" STREQUAL "w64") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") From d173447b97787046edef5ced44400cae08b8e5c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 20 Oct 2014 17:36:26 +0200 Subject: [PATCH 164/641] Another round of fixing ExtVM interface --- libevm/ExtVMFace.h | 2 +- test/vm.cpp | 19 +++++++++++++++---- test/vm.h | 18 +++++++++--------- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h index eeae720f3..481b11eff 100644 --- a/libevm/ExtVMFace.h +++ b/libevm/ExtVMFace.h @@ -81,7 +81,7 @@ public: virtual void suicide(Address) { suicides.insert(myAddress); } /// Create a new (contract) account. - virtual h160 create(u256, u256*, bytesConstRef, bytesConstRef) { return h160(); } + virtual h160 create(u256, u256*, bytesConstRef, OnOpFunc const&) { return h160(); } /// Make a new message call. virtual bool call(Address, u256, bytesConstRef, u256*, bytesRef, OnOpFunc const&, Address, Address) { return false; } diff --git a/test/vm.cpp b/test/vm.cpp index d65b5d3d5..80185f659 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -35,7 +35,7 @@ using namespace dev::test; FakeExtVM::FakeExtVM(eth::BlockInfo const& _previousBlock, eth::BlockInfo const& _currentBlock, unsigned _depth): /// TODO: XXX: remove the default argument & fix. ExtVMFace(Address(), Address(), Address(), 0, 1, bytesConstRef(), bytesConstRef(), _previousBlock, _currentBlock, _depth) {} -h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFunc) +h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFunc const&) { Transaction t; t.value = _endowment; @@ -45,7 +45,7 @@ h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFun m_s.noteSending(myAddress); m_ms.internal.resize(m_ms.internal.size() + 1); - auto ret = m_s.create(myAddress, _endowment, gasPrice, _gas, _init, origin, &suicides, &m_ms ? &(m_ms.internal.back()) : nullptr, OnOpFunc(), 1); + auto ret = m_s.create(myAddress, _endowment, gasPrice, _gas, _init, origin, &suicides, &m_ms ? &(m_ms.internal.back()) : nullptr, {}, 1); if (!m_ms.internal.back().from) m_ms.internal.pop_back(); @@ -61,7 +61,7 @@ h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFun return ret; } -bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, OnOpFunc, Address _myAddressOverride = Address(), Address _codeAddressOverride = Address()) +bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, OnOpFunc const&, Address _myAddressOverride = Address(), Address _codeAddressOverride = Address()) { u256 contractgas = 0xffff; @@ -91,7 +91,7 @@ bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, if (!m_s.addresses().count(myAddress)) { m_ms.internal.resize(m_ms.internal.size() + 1); - auto na = m_s.createNewAddress(myAddress, myAddress, balance(myAddress), gasPrice, &contractgas, init, origin, &suicides, &m_ms ? &(m_ms.internal.back()) : nullptr, OnOpFunc(), 1); + auto na = m_s.createNewAddress(myAddress, myAddress, balance(myAddress), gasPrice, &contractgas, init, origin, &suicides, &m_ms ? &(m_ms.internal.back()) : nullptr, {}, 1); if (!m_ms.internal.back().from) m_ms.internal.pop_back(); if (na != myAddress) @@ -588,6 +588,17 @@ void doTests(json_spirit::mValue& v, bool _fillin) else BOOST_CHECK(output == fromHex(o["out"].get_str())); + //auto a = fev.addresses.at(fev.myAddress); + //auto b = test.addresses.at(fev.myAddress); + + //auto t = a == b; + //auto t0 = get<0>(a) == get<0>(b); + //auto t1 = get<1>(a) == get<1>(b); + //auto t2 = get<2>(a) == get<2>(b); + //auto t3 = get<3>(a) == get<3>(b); + + //BOOST_CHECK_EQUAL(get<0>(a), get<0>(b)); + BOOST_CHECK(test.toInt(o["gas"]) == gas); BOOST_CHECK(test.addresses == fev.addresses); BOOST_CHECK(test.callcreates == fev.callcreates); diff --git a/test/vm.h b/test/vm.h index 34e0e855a..a9897bee3 100644 --- a/test/vm.h +++ b/test/vm.h @@ -53,15 +53,15 @@ public: FakeExtVM() {} FakeExtVM(eth::BlockInfo const& _previousBlock, eth::BlockInfo const& _currentBlock, unsigned _depth = 0); - u256 store(u256 _n) { return std::get<2>(addresses[myAddress])[_n]; } - void setStore(u256 _n, u256 _v) { std::get<2>(addresses[myAddress])[_n] = _v; } - u256 balance(Address _a) { return std::get<0>(addresses[_a]); } - void subBalance(u256 _a) { std::get<0>(addresses[myAddress]) -= _a; } - u256 txCount(Address _a) { return std::get<1>(addresses[_a]); } - void suicide(Address _a) { std::get<0>(addresses[_a]) += std::get<0>(addresses[myAddress]); addresses.erase(myAddress); } - bytes const& codeAt(Address _a) { return std::get<3>(addresses[_a]); } - h160 create(u256 _endowment, u256* _gas, bytesConstRef _init, eth::OnOpFunc); - bool call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, eth::OnOpFunc, Address, Address); + u256 store(u256 _n) override { return std::get<2>(addresses[myAddress])[_n]; } + void setStore(u256 _n, u256 _v) override { std::get<2>(addresses[myAddress])[_n] = _v; } + u256 balance(Address _a) override { return std::get<0>(addresses[_a]); } + void subBalance(u256 _a) override { std::get<0>(addresses[myAddress]) -= _a; } + u256 txCount(Address _a) override { return std::get<1>(addresses[_a]); } + void suicide(Address _a) override { std::get<0>(addresses[_a]) += std::get<0>(addresses[myAddress]); addresses.erase(myAddress); } + bytes const& codeAt(Address _a) override { return std::get<3>(addresses[_a]); } + h160 create(u256 _endowment, u256* _gas, bytesConstRef _init, eth::OnOpFunc const&) override; + bool call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, eth::OnOpFunc const&, Address, Address) override; void setTransaction(Address _caller, u256 _value, u256 _gasPrice, bytes const& _data); void setContract(Address _myAddress, u256 _myBalance, u256 _myNonce, std::map const& _storage, bytes const& _code); void set(Address _a, u256 _myBalance, u256 _myNonce, std::map const& _storage, bytes const& _code); From e193d2d0817e600924c1508b6ce356717e781ca9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 20 Oct 2014 17:37:42 +0200 Subject: [PATCH 165/641] Another round of fixing ExtVM interface --- libevmjit/Ext.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 5c4bb7c59..26ed962b2 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -310,7 +310,7 @@ EXPORT void ext_create(i256* _endowment, i256* _initOff, i256* _initSize, h256* auto initOff = static_cast(llvm2eth(*_initOff)); auto initSize = static_cast(llvm2eth(*_initSize)); auto&& initRef = bytesConstRef(Runtime::getMemory().data() + initOff, initSize); - auto&& onOp = bytesConstRef(); // TODO: Handle that thing + OnOpFunc onOp{}; // TODO: Handle that thing h256 address = ext.create(endowment, &gas, initRef, onOp); *_address = address; } From 448e3141f67c4931a5c2246ca21f7fc11c4b21b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 20 Oct 2014 17:49:09 +0200 Subject: [PATCH 166/641] Fixing Visual Studio compilation - these FeeStructure constants are weird --- libevm/FeeStructure.cpp | 6 ++++++ libevm/VM.cpp | 4 ---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/libevm/FeeStructure.cpp b/libevm/FeeStructure.cpp index aeeb19e27..b04dc113b 100644 --- a/libevm/FeeStructure.cpp +++ b/libevm/FeeStructure.cpp @@ -31,6 +31,12 @@ namespace dev namespace eth { +#ifndef _MSC_VER +uint32_t const FeeStructure::c_memoryGas; +uint32_t const FeeStructure::c_txDataGas; +uint32_t const FeeStructure::c_txGas; +#endif + uint32_t FeeStructure::getInstructionFee(Instruction _inst) { switch (_inst) diff --git a/libevm/VM.cpp b/libevm/VM.cpp index b2f7fea22..e47237d5a 100644 --- a/libevm/VM.cpp +++ b/libevm/VM.cpp @@ -25,10 +25,6 @@ using namespace std; using namespace dev; using namespace dev::eth; -uint32_t const dev::eth::FeeStructure::c_memoryGas; -uint32_t const dev::eth::FeeStructure::c_txDataGas; -uint32_t const dev::eth::FeeStructure::c_txGas; - void VM::reset(u256 _gas) { m_gas = _gas; From 340a84fbf451716a348dd8131252dbe9abe2077f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 20 Oct 2014 18:38:39 +0200 Subject: [PATCH 167/641] Throw exception if EVM program is not jitable instead of terminating to make tests going --- libevmjit/Compiler.cpp | 5 +---- libevmjit/ExecutionEngine.cpp | 13 ++----------- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 34970c602..65f75c20f 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -901,10 +901,7 @@ void Compiler::linkBasicBlocks() // TODO: In case entry block is reached - report error auto predBB = findBasicBlock(*predIt); if (!predBB) - { - std::cerr << "Stack too small in " << _llbb->getName().str() << std::endl; - std::exit(1); - } + BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Unsupported dynamic stack")); auto value = predBB->getStack().get(valueIdx); phi->addIncoming(value, predBB->llvm()); } diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp index 5390d82dd..9ff4bed99 100644 --- a/libevmjit/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -70,13 +70,7 @@ int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, ExtV auto exec = std::unique_ptr(builder.create()); if (!exec) - { - if (!errorMsg.empty()) - std::cerr << "error creating EE: " << errorMsg << std::endl; - else - std::cerr << "unknown error creating llvm::ExecutionEngine" << std::endl; - exit(1); - } + BOOST_THROW_EXCEPTION(Exception() << errinfo_comment(errorMsg)); _module.release(); // Successfully created llvm::ExecutionEngine takes ownership of the module exec->finalizeObject(); @@ -106,10 +100,7 @@ int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, ExtV auto entryFunc = module->getFunction("main"); if (!entryFunc) - { - std::cerr << "main function not found\n"; - exit(1); - } + BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("main function not found")); ReturnCode returnCode; std::jmp_buf buf; From 79f93faa7de7f1e20a1730ae30d987430d06185e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 20 Oct 2014 18:57:06 +0200 Subject: [PATCH 168/641] Fix compiling empty bytecode --- libevmjit/Compiler.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 65f75c20f..19c90e244 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -33,16 +33,18 @@ Compiler::Compiler(): void Compiler::createBasicBlocks(bytesConstRef bytecode) { std::set splitPoints; // Sorted collections of instruction indices where basic blocks start/end - splitPoints.insert(0); // First basic block std::map directJumpTargets; std::vector indirectJumpTargets; - boost::dynamic_bitset<> validJumpTargets(bytecode.size()); + boost::dynamic_bitset<> validJumpTargets(std::max(bytecode.size(), size_t(1))); + + splitPoints.insert(0); // First basic block + validJumpTargets[0] = true; for (auto curr = bytecode.begin(); curr != bytecode.end(); ++curr) { ProgramCounter currentPC = curr - bytecode.begin(); - validJumpTargets[currentPC] = 1; + validJumpTargets[currentPC] = true; auto inst = static_cast(*curr); switch (inst) From 399ba5a855ecfa0547627f24b967e10d7f0a551a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 21 Oct 2014 00:41:34 +0200 Subject: [PATCH 169/641] Updating Visual Studio project files --- windows/Ethereum.sln | 1 - windows/LLVM.props | 12 ++++++++++-- windows/LibEvmJit.vcxproj | 5 +++++ windows/TestEthereum.vcxproj | 11 +++++------ windows/evmcc.vcxproj | 15 ++++++++++----- 5 files changed, 30 insertions(+), 14 deletions(-) diff --git a/windows/Ethereum.sln b/windows/Ethereum.sln index 33167a23b..c4ac205a7 100644 --- a/windows/Ethereum.sln +++ b/windows/Ethereum.sln @@ -43,7 +43,6 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "evmcc", "evmcc.vcxproj", "{D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}" ProjectSection(ProjectDependencies) = postProject {9C816740-5C11-4377-A3A7-46BE12F35FA0} = {9C816740-5C11-4377-A3A7-46BE12F35FA0} - {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F} = {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibEvmJit", "LibEvmJit.vcxproj", "{9C816740-5C11-4377-A3A7-46BE12F35FA0}" diff --git a/windows/LLVM.props b/windows/LLVM.props index 708ff3085..3290a4f64 100644 --- a/windows/LLVM.props +++ b/windows/LLVM.props @@ -2,8 +2,9 @@ - ..\..\builds\llvm3.5 - ..\..\llvm-3.5.0\include;$(LLVMBuildDir)\include + ..\..\_build\llvm\$(Platform) + ..\..\llvm\include;$(LLVMBuildDir)\include + $(LLVMBuildDir)\$(Configuration)\lib @@ -11,6 +12,10 @@ $(LLVMIncludeDir);%(AdditionalIncludeDirectories) 4800;%(DisableSpecificWarnings) + + $(LLVMLibDir);%(AdditionalLibraryDirectories) + LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) + @@ -19,5 +24,8 @@ $(LLVMIncludeDir) + + $(LLVMLibDir) + \ No newline at end of file diff --git a/windows/LibEvmJit.vcxproj b/windows/LibEvmJit.vcxproj index f516edf4f..3a62813c0 100644 --- a/windows/LibEvmJit.vcxproj +++ b/windows/LibEvmJit.vcxproj @@ -150,6 +150,11 @@ + + + {826e68cb-d3ee-4a8a-b540-59a8c3f38d4f} + + diff --git a/windows/TestEthereum.vcxproj b/windows/TestEthereum.vcxproj index b07124581..be475a949 100644 --- a/windows/TestEthereum.vcxproj +++ b/windows/TestEthereum.vcxproj @@ -108,7 +108,6 @@ Console true - LibEthereum.lib;LibEvmJit.lib;LibSecp256k1.lib;LibCryptoPP.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) ../../builds/llvm3.5/Debug/lib;../../_build/LibEvmJit/x64_Debug;../../_build/LibEthereum/x64_Debug;../../_build/LibSecp256k1/x64_Debug;../../_build/LibCryptoPP/x64_Debug;%(AdditionalLibraryDirectories) @@ -155,11 +154,6 @@ true - - - {826e68cb-d3ee-4a8a-b540-59a8c3f38d4f} - - @@ -191,6 +185,11 @@ + + + {9c816740-5c11-4377-a3a7-46be12f35fa0} + + diff --git a/windows/evmcc.vcxproj b/windows/evmcc.vcxproj index 6c1b72143..a93635e6b 100644 --- a/windows/evmcc.vcxproj +++ b/windows/evmcc.vcxproj @@ -21,6 +21,11 @@ + + + {9c816740-5c11-4377-a3a7-46be12f35fa0} + + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D} Win32Proj @@ -58,21 +63,25 @@ + + + + @@ -110,7 +119,6 @@ Console true - ../../builds/llvm3.5/Debug/lib;../../_build/LibEvmJit/x64_Debug;../../_build/LibEthereum/x64_Debug;%(AdditionalLibraryDirectories) LibEthereum.lib;LibEvmJit.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) @@ -130,8 +138,7 @@ Console true - ../../builds/llvm3.5/Debug/lib;../../_build/LibEvmJit/x64_Debug;../../_build/LibEthereum/x64_Debug;../../_build/LibSecp256k1/x64_Debug;../../_build/LibCryptoPP/x64_Debug;%(AdditionalLibraryDirectories) - LibEthereum.lib;LibEvmJit.lib;LibSecp256k1.lib;LibCryptoPP.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) + %(AdditionalDependencies) @@ -151,7 +158,6 @@ true true true - ../../builds/llvm3.5/Debug/lib;../../_build/LibEvmJit/x64_Debug;../../_build/LibEthereum/x64_Debug;%(AdditionalLibraryDirectories) LibEthereum.lib;LibEvmJit.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) @@ -174,7 +180,6 @@ true true true - ../../builds/llvm3.5/Debug/lib;../../_build/LibEvmJit/x64_Debug;../../_build/LibEthereum/x64_Debug;%(AdditionalLibraryDirectories) LibEthereum.lib;LibEvmJit.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) From 9e8e9af60381c0e4e21d68b47686fe25c4c52280 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 21 Oct 2014 11:51:45 +0200 Subject: [PATCH 170/641] Remove dead code --- test/vm.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/test/vm.cpp b/test/vm.cpp index 80185f659..5cb2a7b7f 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -588,17 +588,6 @@ void doTests(json_spirit::mValue& v, bool _fillin) else BOOST_CHECK(output == fromHex(o["out"].get_str())); - //auto a = fev.addresses.at(fev.myAddress); - //auto b = test.addresses.at(fev.myAddress); - - //auto t = a == b; - //auto t0 = get<0>(a) == get<0>(b); - //auto t1 = get<1>(a) == get<1>(b); - //auto t2 = get<2>(a) == get<2>(b); - //auto t3 = get<3>(a) == get<3>(b); - - //BOOST_CHECK_EQUAL(get<0>(a), get<0>(b)); - BOOST_CHECK(test.toInt(o["gas"]) == gas); BOOST_CHECK(test.addresses == fev.addresses); BOOST_CHECK(test.callcreates == fev.callcreates); From 270cddef8b6b3490959d9a7428f6b1567abad3db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 21 Oct 2014 11:54:54 +0200 Subject: [PATCH 171/641] Enhance VM tests reports --- test/vm.cpp | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/test/vm.cpp b/test/vm.cpp index 5cb2a7b7f..91bb17c0c 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -588,8 +588,44 @@ void doTests(json_spirit::mValue& v, bool _fillin) else BOOST_CHECK(output == fromHex(o["out"].get_str())); - BOOST_CHECK(test.toInt(o["gas"]) == gas); - BOOST_CHECK(test.addresses == fev.addresses); + BOOST_CHECK_EQUAL(test.toInt(o["gas"]), gas); + + auto& expectedAddrs = test.addresses; + auto& resultAddrs = fev.addresses; + for (auto&& expectedPair : expectedAddrs) + { + auto& expectedAddr = expectedPair.first; + auto resultAddrIt = resultAddrs.find(expectedAddr); + if (resultAddrIt == resultAddrs.end()) + BOOST_ERROR("Missing expected address " << expectedAddr); + else + { + auto& expectedState = expectedPair.second; + auto& resultState = resultAddrIt->second; + BOOST_CHECK_MESSAGE(std::get<0>(expectedState) == std::get<0>(resultState), expectedAddr << ": incorrect balance " << std::get<0>(resultState) << ", expected " << std::get<0>(expectedState)); + BOOST_CHECK_MESSAGE(std::get<1>(expectedState) == std::get<1>(resultState), expectedAddr << ": incorrect txCount " << std::get<1>(resultState) << ", expected " << std::get<1>(expectedState)); + BOOST_CHECK_MESSAGE(std::get<3>(expectedState) == std::get<3>(resultState), expectedAddr << ": incorrect code"); + + auto&& expectedStore = std::get<2>(expectedState); + auto&& resultStore = std::get<2>(resultState); + + for (auto&& expectedStorePair : expectedStore) + { + auto& expectedStoreKey = expectedStorePair.first; + auto resultStoreIt = resultStore.find(expectedStoreKey); + if (resultStoreIt == resultStore.end()) + BOOST_ERROR(expectedAddr << ": missing store key " << expectedStoreKey); + else + { + auto& expectedStoreValue = expectedStorePair.second; + auto& resultStoreValue = resultStoreIt->second; + BOOST_CHECK_MESSAGE(expectedStoreValue == resultStoreValue, expectedAddr << ": store[" << expectedStoreKey << "] = " << resultStoreValue << ", expected " << expectedStoreValue); + } + } + } + } + + BOOST_CHECK(test.addresses == fev.addresses); // Just to make sure nothing missed BOOST_CHECK(test.callcreates == fev.callcreates); } } From 0a84ed39d8ab3c8fb9c107885f6e271d5a846ac8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 21 Oct 2014 12:52:46 +0200 Subject: [PATCH 172/641] Handle endianness of MSTORE & MLOAD [#79877740] --- evmcc/test/mem/mstore1.evm | 1 + evmcc/test/mem/mstore1.lll | 6 ++++++ libevmjit/Endianness.cpp | 3 ++- libevmjit/Endianness.h | 7 ++++++- libevmjit/Memory.cpp | 6 +++++- 5 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 evmcc/test/mem/mstore1.evm create mode 100644 evmcc/test/mem/mstore1.lll diff --git a/evmcc/test/mem/mstore1.evm b/evmcc/test/mem/mstore1.evm new file mode 100644 index 000000000..ba6141ab1 --- /dev/null +++ b/evmcc/test/mem/mstore1.evm @@ -0,0 +1 @@ +6001600054 diff --git a/evmcc/test/mem/mstore1.lll b/evmcc/test/mem/mstore1.lll new file mode 100644 index 000000000..2d2ca32b5 --- /dev/null +++ b/evmcc/test/mem/mstore1.lll @@ -0,0 +1,6 @@ + +(asm ;; [] +1 +0 +MSTORE ;; [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1] +) \ No newline at end of file diff --git a/libevmjit/Endianness.cpp b/libevmjit/Endianness.cpp index 7de7b9514..f0da5f9d4 100644 --- a/libevmjit/Endianness.cpp +++ b/libevmjit/Endianness.cpp @@ -12,9 +12,10 @@ namespace eth namespace jit { -llvm::Value* Endianness::toBE(llvm::IRBuilder<>& _builder, llvm::Value* _word) +llvm::Value* Endianness::bswap(llvm::IRBuilder<>& _builder, llvm::Value* _word) { // TODO: Native is Little Endian + assert(_word->getType() == Type::i256); auto bswap = llvm::Intrinsic::getDeclaration(_builder.GetInsertBlock()->getParent()->getParent(), llvm::Intrinsic::bswap, Type::i256); return _builder.CreateCall(bswap, _word); } diff --git a/libevmjit/Endianness.h b/libevmjit/Endianness.h index 7b449b4d8..9234961c1 100644 --- a/libevmjit/Endianness.h +++ b/libevmjit/Endianness.h @@ -14,7 +14,12 @@ class Endianness { public: - static llvm::Value* toBE(llvm::IRBuilder<>& _builder, llvm::Value* _word); + static llvm::Value* toBE(llvm::IRBuilder<>& _builder, llvm::Value* _word) { return bswap(_builder, _word); } + + static llvm::Value* toNative(llvm::IRBuilder<>& _builder, llvm::Value* _word) { return bswap(_builder, _word); } + +private: + static llvm::Value* bswap(llvm::IRBuilder<>& _builder, llvm::Value* _word); }; } diff --git a/libevmjit/Memory.cpp b/libevmjit/Memory.cpp index d370a7f72..23d027ba4 100644 --- a/libevmjit/Memory.cpp +++ b/libevmjit/Memory.cpp @@ -14,6 +14,7 @@ #include "Type.h" #include "Runtime.h" #include "GasMeter.h" +#include "Endianness.h" namespace dev { @@ -117,12 +118,15 @@ llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, GasMet { llvm::Value* value = ++func->arg_begin(); value->setName("value"); + if (isWord) + value = Endianness::toBE(m_builder, value); m_builder.CreateStore(value, ptr); m_builder.CreateRetVoid(); } else { - auto ret = m_builder.CreateLoad(ptr); + llvm::Value* ret = m_builder.CreateLoad(ptr); + ret = Endianness::toNative(m_builder, ret); m_builder.CreateRet(ret); } From b283a07f76913e9eb0d6a29fd303fa15e2ace966 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 21 Oct 2014 14:23:19 +0200 Subject: [PATCH 173/641] Fix SHA3 instruction :) --- libevmjit/Compiler.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 19c90e244..ab98b27d0 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -473,6 +473,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, memory.require(inOff, inSize); auto hash = ext.sha3(inOff, inSize); stack.push(hash); + break; } case Instruction::POP: From 71ccd3f353bdc12a3b528c6fd6e917f76f9290e4 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Tue, 21 Oct 2014 14:29:27 +0100 Subject: [PATCH 174/641] Propagation of values between basic blocks (and the stack): initial implementation (probably buggy, but simple cases work). [#80895676] --- libevmjit/BasicBlock.cpp | 11 ++-- libevmjit/BasicBlock.h | 22 ++++--- libevmjit/Compiler.cpp | 134 +++++++++++++++++++++++++++------------ libevmjit/Compiler.h | 2 +- libevmjit/Stack.cpp | 69 ++++++++++++++++++++ libevmjit/Stack.h | 35 ++++++++++ 6 files changed, 218 insertions(+), 55 deletions(-) create mode 100644 libevmjit/Stack.cpp create mode 100644 libevmjit/Stack.h diff --git a/libevmjit/BasicBlock.cpp b/libevmjit/BasicBlock.cpp index 736e0a572..927f1180b 100644 --- a/libevmjit/BasicBlock.cpp +++ b/libevmjit/BasicBlock.cpp @@ -30,20 +30,20 @@ BasicBlock::BasicBlock(std::string _name, llvm::Function* _mainFunc) : {} -void BasicBlock::Stack::push(llvm::Value* _value) +void BasicBlock::LocalStack::push(llvm::Value* _value) { assert(_value->getType() == Type::i256); m_backend.push_back(_value); } -llvm::Value* BasicBlock::Stack::pop() +llvm::Value* BasicBlock::LocalStack::pop() { auto top = get(0); m_backend.pop_back(); return top; } -llvm::Value* BasicBlock::Stack::get(size_t _index) +llvm::Value* BasicBlock::LocalStack::get(size_t _index) { if (_index >= m_backend.size()) { @@ -55,18 +55,19 @@ llvm::Value* BasicBlock::Stack::get(size_t _index) m_backend[i] = m_llvmBB->empty() ? llvm::PHINode::Create(Type::i256, 0, {}, m_llvmBB) : llvm::PHINode::Create(Type::i256, 0, {}, m_llvmBB->getFirstNonPHI()); + m_numRequiredStackItems += 1; } } return *(m_backend.rbegin() + _index); } -void BasicBlock::Stack::dup(size_t _index) +void BasicBlock::LocalStack::dup(size_t _index) { m_backend.push_back(get(_index)); } -void BasicBlock::Stack::swap(size_t _index) +void BasicBlock::LocalStack::swap(size_t _index) { assert(_index != 0); get(_index); // Create PHI nodes diff --git a/libevmjit/BasicBlock.h b/libevmjit/BasicBlock.h index 71d8aa355..51a48c6e0 100644 --- a/libevmjit/BasicBlock.h +++ b/libevmjit/BasicBlock.h @@ -15,7 +15,7 @@ using ProgramCounter = uint64_t; // TODO: Rename class BasicBlock { public: - class Stack + class LocalStack { public: /// Pushes value on stack @@ -37,17 +37,23 @@ public: /// Size of the stack size_t size() const { return m_backend.size(); } + size_t initialSize() const { return m_numRequiredStackItems; } + private: - Stack(llvm::BasicBlock* _llvmBB) : m_llvmBB(_llvmBB) {} - Stack(const Stack&) = delete; - void operator=(const Stack&) = delete; + // LocalStack(llvm::BasicBlock* _llvmBB) : m_llvmBB(_llvmBB) {} + LocalStack(llvm::BasicBlock* _llvmBB) : m_llvmBB(_llvmBB), m_numRequiredStackItems(0) {} + LocalStack(LocalStack const&) = delete; + void operator=(LocalStack const&) = delete; friend BasicBlock; private: std::vector m_backend; - /// LLVM Basic Block where phi nodes are inserted - llvm::BasicBlock* const m_llvmBB; + /** Basic block into which phi nodes are inserted */ + llvm::BasicBlock* m_llvmBB; + + /** Number of items required on the EVM stack at the beginning of the block */ + size_t m_numRequiredStackItems; }; /// Basic block name prefix. The rest is beging instruction index. @@ -62,7 +68,7 @@ public: operator llvm::BasicBlock*() { return m_llvmBB; } llvm::BasicBlock* llvm() { return m_llvmBB; } - Stack& getStack() { return m_stack; } + LocalStack& getStack() { return m_stack; } ProgramCounter begin() { return m_beginInstIdx; } ProgramCounter end() { return m_endInstIdx; } @@ -74,7 +80,7 @@ private: /// Basic black state vector (stack) - current/end values and their positions on stack /// @internal Must be AFTER m_llvmBB - Stack m_stack; + LocalStack m_stack; }; } diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 34970c602..35e88f045 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -12,6 +12,7 @@ #include "Type.h" #include "Memory.h" +#include "Stack.h" #include "Ext.h" #include "GasMeter.h" #include "Utils.h" @@ -172,6 +173,7 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) GasMeter gasMeter(m_builder); Memory memory(m_builder, gasMeter); Ext ext(m_builder); + Stack stack(m_builder); m_builder.CreateBr(basicBlocks.begin()->second); @@ -214,7 +216,7 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) m_builder.CreateBr(m_badJumpBlock->llvm()); } - linkBasicBlocks(); + linkBasicBlocks(stack); return module; } @@ -868,61 +870,111 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, } -void Compiler::linkBasicBlocks() +void Compiler::linkBasicBlocks(Stack& stack) { - /// Helper function that finds basic block given LLVM basic block pointer - auto findBasicBlock = [this](llvm::BasicBlock* _llbb) -> BasicBlock* + struct BBInfo { - // TODO: Fix for finding jumpTableBlock - if (_llbb == this->m_jumpTableBlock->llvm()) - return this->m_jumpTableBlock.get(); - - for (auto&& bb : this->basicBlocks) - if (_llbb == bb.second.llvm()) - return &bb.second; - return nullptr; - - // Name is used to get basic block index (index of first instruction) - // TODO: If basicBlocs are still a map - multikey map can be used - //auto&& idxStr = _llbb->getName().substr(sizeof(BasicBlock::NamePrefix) - 2); - //auto idx = std::stoul(idxStr); - //return basicBlocks.find(idx)->second; + BasicBlock& bblock; + std::vector predecessors; + size_t inputItems; + size_t outputItems; + + BBInfo(BasicBlock& _bblock) + : bblock(_bblock), + predecessors(), + inputItems(_bblock.getStack().initialSize()), + outputItems(_bblock.getStack().size()) + {} }; - auto completePhiNodes = [findBasicBlock](llvm::BasicBlock* _llbb) -> void + std::map cfg; + + // Create nodes in cfg + for (auto& pair : this->basicBlocks) + { + auto& bb = pair.second; + cfg.emplace(std::piecewise_construct, + std::forward_as_tuple(bb.llvm()), + std::forward_as_tuple(bb)); + } + + auto& entryBlock = m_mainFunc->getEntryBlock(); + + // Create edges in cfg + for (auto& pair : cfg) + { + auto bbPtr = pair.first; + auto& bbInfo = pair.second; + + for (auto predIt = llvm::pred_begin(bbPtr); predIt != llvm::pred_end(bbPtr); ++predIt) + { + if (*predIt != &entryBlock) + bbInfo.predecessors.push_back(&cfg.find(*predIt)->second); + } + } + + // Iteratively compute inputs and outputs of each block, until reaching fixpoint. + bool valuesChanged = true; + while (valuesChanged) { - size_t valueIdx = 0; - auto firstNonPhi = _llbb->getFirstNonPHI(); - for (auto instIt = _llbb->begin(); &*instIt != firstNonPhi; ++instIt, ++valueIdx) + valuesChanged = false; + for (auto& pair : cfg) { - auto phi = llvm::cast(instIt); - for (auto predIt = llvm::pred_begin(_llbb); predIt != llvm::pred_end(_llbb); ++predIt) + auto& bbInfo = pair.second; + + for (auto predInfo : bbInfo.predecessors) { - // TODO: In case entry block is reached - report error - auto predBB = findBasicBlock(*predIt); - if (!predBB) + if (predInfo->outputItems < bbInfo.inputItems) + { + bbInfo.inputItems = predInfo->outputItems; + valuesChanged = true; + } + else if (predInfo->outputItems > bbInfo.inputItems) { - std::cerr << "Stack too small in " << _llbb->getName().str() << std::endl; - std::exit(1); + predInfo->outputItems = bbInfo.inputItems; + valuesChanged = true; } - auto value = predBB->getStack().get(valueIdx); - phi->addIncoming(value, predBB->llvm()); } } - }; + } - - // TODO: It is crappy visiting of basic blocks. - llvm::SmallPtrSet visitSet; - for (auto&& bb : basicBlocks) // TODO: External loop is to visit unreable blocks that can also have phi nodes + // Propagate values between blocks. + for (auto& pair : cfg) { - for (auto it = llvm::po_ext_begin(bb.second.llvm(), visitSet), - end = llvm::po_ext_end(bb.second.llvm(), visitSet); it != end; ++it) + auto llbb = pair.first; + auto& bbInfo = pair.second; + auto& bblock = bbInfo.bblock; + + // Complete phi nodes for the top bbInfo.inputItems placeholder values + auto instrIter = llbb->begin(); + for (size_t valueIdx = 0; valueIdx < bbInfo.inputItems; ++instrIter, ++valueIdx) { - // TODO: Use logger - //std::cerr << it->getName().str() << std::endl; - completePhiNodes(*it); + auto phi = llvm::cast(instrIter); + for (auto predIt : bbInfo.predecessors) + { + assert(valueIdx < predIt->bblock.getStack().size()); + auto value = predIt->bblock.getStack().get(valueIdx); + phi->addIncoming(value, predIt->bblock.llvm()); + } + } + + // Turn the remaining phi nodes into stack.pop's. + m_builder.SetInsertPoint(llbb, llvm::BasicBlock::iterator(llbb->getFirstNonPHI())); + for (; llvm::isa(*instrIter); ) + { + auto phi = llvm::cast(instrIter); + auto value = stack.popWord(); + phi->replaceAllUsesWith(value); + ++ instrIter; + phi->eraseFromParent(); } + + // Emit stack push's at the end of the block, just before the terminator; + m_builder.SetInsertPoint(llbb, -- llbb->end()); + auto localStackSize = bblock.getStack().size(); + assert(localStackSize >= bbInfo.outputItems); + for (size_t i = 0; i < localStackSize - bbInfo.outputItems; ++i) + stack.pushWord(bblock.getStack().get(localStackSize - 1 - i)); } // Remove jump table block if not predecessors diff --git a/libevmjit/Compiler.h b/libevmjit/Compiler.h index 8972322ec..ac6277e7b 100644 --- a/libevmjit/Compiler.h +++ b/libevmjit/Compiler.h @@ -33,7 +33,7 @@ private: void compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, class Memory& memory, class Ext& ext, class GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock); - void linkBasicBlocks(); + void linkBasicBlocks(class Stack& stack); llvm::IRBuilder<> m_builder; diff --git a/libevmjit/Stack.cpp b/libevmjit/Stack.cpp new file mode 100644 index 000000000..772e6255b --- /dev/null +++ b/libevmjit/Stack.cpp @@ -0,0 +1,69 @@ +#include "Stack.h" +#include "Runtime.h" + +#include +#include + +namespace dev +{ +namespace eth +{ +namespace jit +{ + +Stack::Stack(llvm::IRBuilder<>& _builder) + : CompilerHelper(_builder) +{ + auto i256Ty = m_builder.getIntNTy(256); + auto i256PtrTy = i256Ty->getPointerTo(); + + m_arg = m_builder.CreateAlloca(i256Ty, nullptr, "stack.retVal"); + + using namespace llvm; + using Linkage = GlobalValue::LinkageTypes; + + auto module = getModule(); + m_push = Function::Create(FunctionType::get(m_builder.getVoidTy(), i256PtrTy, false), Linkage::ExternalLinkage, "stack_push", module); + m_pop = Function::Create(FunctionType::get(m_builder.getVoidTy(), i256PtrTy, false), Linkage::ExternalLinkage, "stack_pop", module); +} + +Stack::~Stack() +{} + +llvm::Instruction* Stack::popWord() +{ + m_builder.CreateCall(m_pop, m_arg); + return m_builder.CreateLoad(m_arg); +} + +void Stack::pushWord(llvm::Value* _word) +{ + m_builder.CreateStore(_word, m_arg); + m_builder.CreateCall(m_push, m_arg); +} + +} +} +} + +extern "C" +{ + +using namespace dev::eth::jit; + +EXPORT void stack_pop(i256* _ret) +{ + auto& stack = Runtime::getStack(); + assert(stack.size() > 0); + *_ret = stack.back(); + stack.pop_back(); +} + +EXPORT void stack_push(i256* _word) +{ + auto& stack = Runtime::getStack(); + stack.push_back(*_word); +} + +} // extern "C" + diff --git a/libevmjit/Stack.h b/libevmjit/Stack.h new file mode 100644 index 000000000..5e1ac0f39 --- /dev/null +++ b/libevmjit/Stack.h @@ -0,0 +1,35 @@ +#pragma once + +#include "CompilerHelper.h" + +#include + +namespace dev +{ +namespace eth +{ +namespace jit +{ + +class Stack : public CompilerHelper +{ +public: + Stack(llvm::IRBuilder<>& builder); + virtual ~Stack(); + + void pushWord(llvm::Value* _word); + llvm::Instruction* popWord(); + +private: + llvm::Function* m_push; + llvm::Function* m_pop; + + llvm::Value* m_arg; +}; + + +} +} +} + + From ceb6d86fa35bcdbaa64b33aa5685bfe63c48e244 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Tue, 21 Oct 2014 14:52:43 +0100 Subject: [PATCH 175/641] added missing CMakeLists.txt --- libevmjit/CMakeLists.txt | 60 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 libevmjit/CMakeLists.txt diff --git a/libevmjit/CMakeLists.txt b/libevmjit/CMakeLists.txt new file mode 100644 index 000000000..f461c16cf --- /dev/null +++ b/libevmjit/CMakeLists.txt @@ -0,0 +1,60 @@ +cmake_policy(SET CMP0015 NEW) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") + +aux_source_directory(. SRC_LIST) + +set(EXECUTABLE evmjit) + +file(GLOB HEADERS "*.h") +if (EVMJIT_STATIC) + add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) +else() + add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) +endif() + +include_directories(..) + +target_link_libraries(${EXECUTABLE} devcore) +target_link_libraries(${EXECUTABLE} ethcore) +target_link_libraries(${EXECUTABLE} evm) +target_link_libraries(${EXECUTABLE} evmface) + +if ("${TARGET_PLATFORM}" STREQUAL "w64") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") + target_link_libraries(${EXECUTABLE} gcc) + target_link_libraries(${EXECUTABLE} gdi32) + target_link_libraries(${EXECUTABLE} ws2_32) + target_link_libraries(${EXECUTABLE} mswsock) + target_link_libraries(${EXECUTABLE} shlwapi) + target_link_libraries(${EXECUTABLE} iphlpapi) + target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) + set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) +elseif (UNIX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") +else () + find_package(Threads REQUIRED) + target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) +endif () + +# LLVM specific commands + +find_package(LLVM REQUIRED CONFIG) + +message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") +message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + +include_directories(${LLVM_INCLUDE_DIRS}) +add_definitions(${LLVM_DEFINITIONS}) + +llvm_map_components_to_libnames(llvm_libs core support mcjit x86asmparser x86codegen) +target_link_libraries(evmjit ${llvm_libs}) + +# end of LLVM specific commands + + + +install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) +install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) + +cmake_policy(SET CMP0015 NEW) From ca016033888ce10df246ce6a8ec6235913210416 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 21 Oct 2014 15:55:29 +0200 Subject: [PATCH 176/641] Remove unreachable basic blocks before "linking" --- libevmjit/Compiler.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index ab98b27d0..fe720b811 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -911,7 +911,26 @@ void Compiler::linkBasicBlocks() } }; - + // Remove dead basic blocks + auto sthErased = false; + do + { + sthErased = false; + for (auto it = basicBlocks.begin(); it != basicBlocks.end();) + { + auto llvmBB = it->second.llvm(); + if (llvm::pred_begin(llvmBB) == llvm::pred_end(llvmBB)) + { + llvmBB->eraseFromParent(); + basicBlocks.erase(it++); + sthErased = true; + } + else + ++it; + } + } + while (sthErased); + // TODO: It is crappy visiting of basic blocks. llvm::SmallPtrSet visitSet; for (auto&& bb : basicBlocks) // TODO: External loop is to visit unreable blocks that can also have phi nodes From 6c702a178d7eb2b3bb12983d266ed687a203d74f Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Tue, 21 Oct 2014 15:00:09 +0100 Subject: [PATCH 177/641] cmake: added dependency on libevmjit to target createRandomTest --- test/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 962d82ca5..bb3dd9ead 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -25,6 +25,7 @@ target_link_libraries(createRandomTest ethereum) target_link_libraries(createRandomTest ethcore) target_link_libraries(createRandomTest boost_chrono) target_link_libraries(createRandomTest boost_unit_test_framework) +target_link_libraries(createRandomTest evmjit) if ("${TARGET_PLATFORM}" STREQUAL "w64") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") From 9a257917d322b59e8ef93e00eff3517f6057af36 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Tue, 21 Oct 2014 15:00:43 +0100 Subject: [PATCH 178/641] minor changes in the compiler driver --- evmcc/evmcc.cpp | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/evmcc/evmcc.cpp b/evmcc/evmcc.cpp index 9cf731419..3cd06d5a8 100644 --- a/evmcc/evmcc.cpp +++ b/evmcc/evmcc.cpp @@ -91,12 +91,12 @@ int main(int argc, char** argv) std::cout << assembly << std::endl; } - if (opt_compile) + if (opt_compile || opt_interpret) { auto compiler = eth::jit::Compiler(); auto module = compiler.compile({bytecode.data(), bytecode.size()}); - llvm::raw_os_ostream out(std::cout); - module->print(out, nullptr); + + module->dump(); if (opt_dump_graph) { @@ -105,17 +105,15 @@ int main(int argc, char** argv) ofs.close(); std::cout << "Basic blocks graph written to block.dot\n"; } - } - if (opt_interpret) - { - auto engine = eth::jit::ExecutionEngine(); - auto module = eth::jit::Compiler().compile({bytecode.data(), bytecode.size()}); - module->dump(); - u256 gas = 10000; - auto result = engine.run(std::move(module), gas); - return result; - } + if (opt_interpret) + { + auto engine = eth::jit::ExecutionEngine(); + u256 gas = 10000; + auto result = engine.run(std::move(module), gas); + return result; + } + } return 0; } From 5eeb082ae0918b1e2c52607058c95818fe27e7b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 21 Oct 2014 16:06:30 +0200 Subject: [PATCH 179/641] Remove unreachable basic blocks before "linking" --- libevmjit/Compiler.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index a88797413..ef8eb2f2d 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -875,6 +875,25 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, void Compiler::linkBasicBlocks(Stack& stack) { + // Remove dead basic blocks + auto sthErased = false; + do + { + sthErased = false; + for (auto it = basicBlocks.begin(); it != basicBlocks.end();) + { + auto llvmBB = it->second.llvm(); + if (llvm::pred_begin(llvmBB) == llvm::pred_end(llvmBB)) + { + llvmBB->eraseFromParent(); + basicBlocks.erase(it++); + sthErased = true; + } + else + ++it; + } + } while (sthErased); + struct BBInfo { BasicBlock& bblock; From baf935b31c644c663c0d7b1701d1e44d5bca3620 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Tue, 21 Oct 2014 15:53:51 +0100 Subject: [PATCH 180/641] Handling pop() from the empty EVM stack. [#80895676] --- libevmjit/Compiler.cpp | 11 +++++++---- libevmjit/Stack.cpp | 8 ++++++++ libevmjit/Type.h | 1 + libevmjit/VM.cpp | 2 ++ 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index a88797413..640561ad9 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -925,6 +925,9 @@ void Compiler::linkBasicBlocks(Stack& stack) { auto& bbInfo = pair.second; + if (bbInfo.predecessors.empty()) + bbInfo.inputItems = 0; // no consequences for other blocks, so leave valuesChanged false + for (auto predInfo : bbInfo.predecessors) { if (predInfo->outputItems < bbInfo.inputItems) @@ -996,11 +999,11 @@ void Compiler::dumpBasicBlockGraph(std::ostream& out) std::vector blocks; for (auto& pair : this->basicBlocks) - { blocks.push_back(&pair.second); - } - blocks.push_back(m_jumpTableBlock.get()); - blocks.push_back(m_badJumpBlock.get()); + if (m_jumpTableBlock.get()) + blocks.push_back(m_jumpTableBlock.get()); + if (m_badJumpBlock.get()) + blocks.push_back(m_badJumpBlock.get()); // Output nodes for (auto bb : blocks) diff --git a/libevmjit/Stack.cpp b/libevmjit/Stack.cpp index 772e6255b..ce7d09471 100644 --- a/libevmjit/Stack.cpp +++ b/libevmjit/Stack.cpp @@ -1,5 +1,8 @@ #include "Stack.h" #include "Runtime.h" +#include "Type.h" + +#include #include #include @@ -51,9 +54,14 @@ extern "C" using namespace dev::eth::jit; +extern std::jmp_buf* rt_jmpBuf; + EXPORT void stack_pop(i256* _ret) { auto& stack = Runtime::getStack(); + if (stack.size() == 0) + longjmp(*rt_jmpBuf, static_cast(ReturnCode::StackTooSmall)); + assert(stack.size() > 0); *_ret = stack.back(); stack.pop_back(); diff --git a/libevmjit/Type.h b/libevmjit/Type.h index 06907b7df..a03bfac38 100644 --- a/libevmjit/Type.h +++ b/libevmjit/Type.h @@ -39,6 +39,7 @@ enum class ReturnCode BadJumpDestination = 101, OutOfGas = 102, + StackTooSmall = 103 }; struct Constant diff --git a/libevmjit/VM.cpp b/libevmjit/VM.cpp index 6b8b3e38b..16011241e 100644 --- a/libevmjit/VM.cpp +++ b/libevmjit/VM.cpp @@ -26,6 +26,8 @@ bytes VM::go(ExtVMFace& _ext) BOOST_THROW_EXCEPTION(BadJumpDestination()); case 102: BOOST_THROW_EXCEPTION(OutOfGas()); + case 103: + BOOST_THROW_EXCEPTION(StackTooSmall(1,0)); } return std::move(engine.returnData); From 12ccd5d44ff094b1baf3e4d50193dfd3c03d1038 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Tue, 21 Oct 2014 16:24:53 +0100 Subject: [PATCH 181/641] added assert in linkBasicBlocks() --- libevmjit/Compiler.cpp | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index f6093b374..bf77901cd 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -892,7 +892,16 @@ void Compiler::linkBasicBlocks(Stack& stack) else ++it; } - } while (sthErased); + } + while (sthErased); + + // Remove jump table block if no predecessors + if (llvm::pred_begin(m_jumpTableBlock->llvm()) == llvm::pred_end(m_jumpTableBlock->llvm())) + { + m_jumpTableBlock->llvm()->eraseFromParent(); + m_jumpTableBlock.reset(); + } + struct BBInfo { @@ -931,7 +940,11 @@ void Compiler::linkBasicBlocks(Stack& stack) for (auto predIt = llvm::pred_begin(bbPtr); predIt != llvm::pred_end(bbPtr); ++predIt) { if (*predIt != &entryBlock) - bbInfo.predecessors.push_back(&cfg.find(*predIt)->second); + { + auto predInfoEntry = cfg.find(*predIt); + assert(predInfoEntry != cfg.end()); + bbInfo.predecessors.push_back(&predInfoEntry->second); + } } } @@ -1001,13 +1014,6 @@ void Compiler::linkBasicBlocks(Stack& stack) for (size_t i = 0; i < localStackSize - bbInfo.outputItems; ++i) stack.pushWord(bblock.getStack().get(localStackSize - 1 - i)); } - - // Remove jump table block if not predecessors - if (llvm::pred_begin(m_jumpTableBlock->llvm()) == llvm::pred_end(m_jumpTableBlock->llvm())) - { - m_jumpTableBlock->llvm()->eraseFromParent(); - m_jumpTableBlock.reset(); - } } void Compiler::dumpBasicBlockGraph(std::ostream& out) From 52bc5c6ca92338cdbac0652c75a2d97fde4a277a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 21 Oct 2014 17:35:18 +0200 Subject: [PATCH 182/641] Handle endianness for CALLDATALOAD correctly [#79877740] --- libevmjit/Ext.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 26ed962b2..ca0a83307 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -8,6 +8,7 @@ #include #include "Runtime.h" +#include "Endianness.h" using namespace llvm; @@ -145,7 +146,8 @@ Value* Ext::calldataload(Value* _index) { m_builder.CreateStore(_index, m_args[0]); m_builder.CreateCall(m_calldataload, m_args); - return m_builder.CreateLoad(m_args[1]); + auto ret = m_builder.CreateLoad(m_args[1]); + return Endianness::toNative(m_builder, ret); } Value* Ext::bswap(Value* _value) @@ -282,8 +284,8 @@ EXPORT void ext_calldataload(i256* _index, i256* _value) auto index = static_cast(llvm2eth(*_index)); assert(index + 31 > index); // TODO: Handle large index auto b = reinterpret_cast(_value); - for (size_t i = index, j = 31; i <= index + 31; ++i, --j) - b[j] = i < Runtime::getExt().data.size() ? Runtime::getExt().data[i] : 0; + for (size_t i = index, j = 0; i <= index + 31; ++i, ++j) + b[j] = i < Runtime::getExt().data.size() ? Runtime::getExt().data[i] : 0; // Keep Big Endian // TODO: It all can be done by adding padding to data or by using min() algorithm without branch } From f778b4eba710d133692963d3b8378bc59820837c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 21 Oct 2014 17:44:48 +0200 Subject: [PATCH 183/641] Comment: storage uses native endianness [#79877740] --- libevmjit/Ext.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index ca0a83307..98cb791e0 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -109,7 +109,7 @@ Ext::Ext(llvm::IRBuilder<>& _builder): llvm::Value* Ext::store(llvm::Value* _index) { m_builder.CreateStore(_index, m_args[0]); - m_builder.CreateCall(m_store, m_args); + m_builder.CreateCall(m_store, m_args); // Uses native endianness return m_builder.CreateLoad(m_args[1]); } @@ -117,7 +117,7 @@ void Ext::setStore(llvm::Value* _index, llvm::Value* _value) { m_builder.CreateStore(_index, m_args[0]); m_builder.CreateStore(_value, m_args[1]); - m_builder.CreateCall(m_setStore, m_args); + m_builder.CreateCall(m_setStore, m_args); // Uses native endianness } Value* Ext::getDataElem(unsigned _index, const Twine& _name) @@ -268,7 +268,7 @@ EXPORT void ext_init(ExtData* _extData) EXPORT void ext_store(i256* _index, i256* _value) { auto index = llvm2eth(*_index); - auto value = Runtime::getExt().store(index); + auto value = Runtime::getExt().store(index); // Interface uses native endianness *_value = eth2llvm(value); } @@ -276,7 +276,7 @@ EXPORT void ext_setStore(i256* _index, i256* _value) { auto index = llvm2eth(*_index); auto value = llvm2eth(*_value); - Runtime::getExt().setStore(index, value); + Runtime::getExt().setStore(index, value); // Interface uses native endianness } EXPORT void ext_calldataload(i256* _index, i256* _value) From 847d5f98645e031b377fbba398712d45dbb99cab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 21 Oct 2014 17:50:34 +0200 Subject: [PATCH 184/641] Use Endianness in Ext [#79877740] --- libevmjit/Ext.cpp | 21 ++++++++------------- libevmjit/Ext.h | 2 -- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 98cb791e0..045d25b62 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -150,14 +150,9 @@ Value* Ext::calldataload(Value* _index) return Endianness::toNative(m_builder, ret); } -Value* Ext::bswap(Value* _value) -{ - return m_builder.CreateCall(m_bswap, _value); -} - Value* Ext::balance(Value* _address) { - auto address = bswap(_address); // to BE + auto address = Endianness::toBE(m_builder, _address); m_builder.CreateStore(address, m_args[0]); m_builder.CreateCall(m_balance, m_args); return m_builder.CreateLoad(m_args[1]); @@ -165,7 +160,7 @@ Value* Ext::balance(Value* _address) void Ext::suicide(Value* _address) { - auto address = bswap(_address); // to BE + auto address = Endianness::toBE(m_builder, _address); m_builder.CreateStore(address, m_args[0]); m_builder.CreateCall(m_suicide, m_args[0]); } @@ -178,21 +173,21 @@ Value* Ext::create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* Value* args[] = {m_args[0], m_arg2, m_arg3, m_args[1]}; m_builder.CreateCall(m_create, args); Value* address = m_builder.CreateLoad(m_args[1]); - address = bswap(address); // to LE + address = Endianness::toNative(m_builder, address); return address; } llvm::Value* Ext::call(llvm::Value*& _gas, llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize, llvm::Value* _codeAddress) { m_builder.CreateStore(_gas, m_args[0]); - auto receiveAddress = bswap(_receiveAddress); // to BE + auto receiveAddress = Endianness::toBE(m_builder, _receiveAddress); m_builder.CreateStore(receiveAddress, m_arg2); m_builder.CreateStore(_value, m_arg3); m_builder.CreateStore(_inOff, m_arg4); m_builder.CreateStore(_inSize, m_arg5); m_builder.CreateStore(_outOff, m_arg6); m_builder.CreateStore(_outSize, m_arg7); - auto codeAddress = bswap(_codeAddress); // toBE + auto codeAddress = Endianness::toBE(m_builder, _codeAddress); m_builder.CreateStore(codeAddress, m_arg8); llvm::Value* args[] = {m_args[0], m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_args[1]}; @@ -208,7 +203,7 @@ llvm::Value* Ext::sha3(llvm::Value* _inOff, llvm::Value* _inSize) llvm::Value* args[] = {m_args[0], m_arg2, m_args[1]}; m_builder.CreateCall(m_sha3, args); Value* hash = m_builder.CreateLoad(m_args[1]); - hash = bswap(hash); // to LE + hash = Endianness::toNative(m_builder, hash); return hash; } @@ -223,14 +218,14 @@ llvm::Value* Ext::exp(llvm::Value* _left, llvm::Value* _right) llvm::Value* Ext::codeAt(llvm::Value* _addr) { - auto addr = bswap(_addr); + auto addr = Endianness::toBE(m_builder, _addr); m_builder.CreateStore(addr, m_args[0]); return m_builder.CreateCall(m_codeAt, m_args[0]); } llvm::Value* Ext::codesizeAt(llvm::Value* _addr) { - auto addr = bswap(_addr); + auto addr = Endianness::toBE(m_builder, _addr); m_builder.CreateStore(addr, m_args[0]); llvm::Value* args[] = {m_args[0], m_args[1]}; m_builder.CreateCall(m_codesizeAt, args); diff --git a/libevmjit/Ext.h b/libevmjit/Ext.h index 04c17fdac..361b6e47e 100644 --- a/libevmjit/Ext.h +++ b/libevmjit/Ext.h @@ -50,8 +50,6 @@ public: private: llvm::Value* getDataElem(unsigned _index, const llvm::Twine& _name = ""); - llvm::Value* bswap(llvm::Value*); - private: llvm::Value* m_args[2]; llvm::Value* m_arg2; From 17a3006633c16aad1ef3751f999f36463a3d5f92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 21 Oct 2014 18:16:57 +0200 Subject: [PATCH 185/641] Add support for Big Endian architectures [Delivers #79877740] --- libevmjit/Endianness.h | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/libevmjit/Endianness.h b/libevmjit/Endianness.h index 9234961c1..951904358 100644 --- a/libevmjit/Endianness.h +++ b/libevmjit/Endianness.h @@ -1,6 +1,8 @@ #pragma once +#include + #include namespace dev @@ -10,14 +12,19 @@ namespace eth namespace jit { -class Endianness +struct Endianness { -public: +#if defined(BOOST_LITTLE_ENDIAN) static llvm::Value* toBE(llvm::IRBuilder<>& _builder, llvm::Value* _word) { return bswap(_builder, _word); } - static llvm::Value* toNative(llvm::IRBuilder<>& _builder, llvm::Value* _word) { return bswap(_builder, _word); } +#elif defined(BOOST_BIG_ENDIAN) + static llvm::Value* toBE(llvm::IRBuilder<>&, llvm::Value* _word) { return _word; } + static llvm::Value* toNative(llvm::IRBuilder<>&, llvm::Value* _word) { return _word; } + +#endif // Add support for PDP endianness if needed + private: static llvm::Value* bswap(llvm::IRBuilder<>& _builder, llvm::Value* _word); }; From 57a8935d876253e7f7866818c987042ce8fb8371 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 21 Oct 2014 19:42:24 +0200 Subject: [PATCH 186/641] Fix remaining gas testing [#81118624] --- test/vm.cpp | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/test/vm.cpp b/test/vm.cpp index 784515c1a..cd40a5ee3 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -512,37 +512,35 @@ void doTests(json_spirit::mValue& v, bool _fillin) fev.code = &fev.thisTxCode; } + + auto argc = boost::unit_test::framework::master_test_suite().argc; + auto argv = boost::unit_test::framework::master_test_suite().argv; + auto useJit = argc >= 2 && std::string(argv[1]) == "--jit"; + + jit::VM jit(fev.gas); + VM interpreter(fev.gas); bytes output; - u256 gas; + auto outOfGas = false; try { - auto argc = boost::unit_test::framework::master_test_suite().argc; - auto argv = boost::unit_test::framework::master_test_suite().argv; - - auto useJit = argc >= 2 && std::string(argv[1]) == "--jit"; if (useJit) - { - jit::VM vm(fev.gas); - output = vm.go(fev); - gas = vm.gas(); - } + output = jit.go(fev); else - { - VM vm(fev.gas); - output = vm.go(fev).toVector(); - gas = vm.gas(); // Get the remaining gas + output = interpreter.go(fev).toVector(); } + catch (OutOfGas const&) + { + outOfGas = true; } catch (Exception const& _e) { cnote << "VM did throw an exception: " << diagnostic_information(_e); - //BOOST_ERROR("Failed VM Test with Exception: " << e.what()); } catch (std::exception const& _e) { cnote << "VM did throw an exception: " << _e.what(); - //BOOST_ERROR("Failed VM Test with Exception: " << e.what()); } + auto gas = useJit ? jit.gas() : interpreter.gas(); // delete null entries in storage for the sake of comparison @@ -593,6 +591,9 @@ void doTests(json_spirit::mValue& v, bool _fillin) BOOST_CHECK(output == fromHex(o["out"].get_str())); BOOST_CHECK_EQUAL(test.toInt(o["gas"]), gas); + + if (outOfGas) + BOOST_CHECK_MESSAGE(gas == 0, "Remaining gas not 0 in out-of-gas state"); auto& expectedAddrs = test.addresses; auto& resultAddrs = fev.addresses; From daf7d16670ef670ae6cbf4514e518bbe9bdee5ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 21 Oct 2014 19:52:08 +0200 Subject: [PATCH 187/641] Null gas in case of out-of-gas exception [Delivers #81118624] --- libevmjit/ExecutionEngine.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp index 9ff4bed99..4bcaf2c50 100644 --- a/libevmjit/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -114,7 +114,8 @@ int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, ExtV else returnCode = static_cast(r); - _gas = Runtime::getGas(); + // Return remaining gas + _gas = returnCode == ReturnCode::OutOfGas ? 0 : Runtime::getGas(); if (returnCode == ReturnCode::Return) { From 15499e68b87c3caa8f9e7bf480f97d0da5fb25c3 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Tue, 21 Oct 2014 21:52:18 +0100 Subject: [PATCH 188/641] Fixed bug in phi node rewriting [#80895676] --- libevmjit/Compiler.cpp | 47 +++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index bf77901cd..71661bde9 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -924,11 +924,13 @@ void Compiler::linkBasicBlocks(Stack& stack) for (auto& pair : this->basicBlocks) { auto& bb = pair.second; - cfg.emplace(std::piecewise_construct, - std::forward_as_tuple(bb.llvm()), - std::forward_as_tuple(bb)); + cfg.emplace(bb.llvm(), bb); } + // Insert jump table block into cfg + if (m_jumpTableBlock) + cfg.emplace(m_jumpTableBlock->llvm(), *m_jumpTableBlock); + auto& entryBlock = m_mainFunc->getEntryBlock(); // Create edges in cfg @@ -976,6 +978,8 @@ void Compiler::linkBasicBlocks(Stack& stack) } } + std::map phiReplacements; + // Propagate values between blocks. for (auto& pair : cfg) { @@ -998,13 +1002,12 @@ void Compiler::linkBasicBlocks(Stack& stack) // Turn the remaining phi nodes into stack.pop's. m_builder.SetInsertPoint(llbb, llvm::BasicBlock::iterator(llbb->getFirstNonPHI())); - for (; llvm::isa(*instrIter); ) + for (; llvm::isa(*instrIter); ++instrIter) { auto phi = llvm::cast(instrIter); auto value = stack.popWord(); - phi->replaceAllUsesWith(value); - ++ instrIter; - phi->eraseFromParent(); + // Don't delete the phi node yet. It may still be stored in a local stack of some block. + phiReplacements[phi] = value; } // Emit stack push's at the end of the block, just before the terminator; @@ -1014,6 +1017,12 @@ void Compiler::linkBasicBlocks(Stack& stack) for (size_t i = 0; i < localStackSize - bbInfo.outputItems; ++i) stack.pushWord(bblock.getStack().get(localStackSize - 1 - i)); } + + for (auto& entry : phiReplacements) + { + entry.first->replaceAllUsesWith(entry.second); + entry.first->eraseFromParent(); + } } void Compiler::dumpBasicBlockGraph(std::ostream& out) @@ -1025,11 +1034,13 @@ void Compiler::dumpBasicBlockGraph(std::ostream& out) std::vector blocks; for (auto& pair : this->basicBlocks) blocks.push_back(&pair.second); - if (m_jumpTableBlock.get()) + if (m_jumpTableBlock) blocks.push_back(m_jumpTableBlock.get()); - if (m_badJumpBlock.get()) + if (m_badJumpBlock) blocks.push_back(m_badJumpBlock.get()); + std::map phiNodesPerBlock; + // Output nodes for (auto bb : blocks) { @@ -1038,27 +1049,29 @@ void Compiler::dumpBasicBlockGraph(std::ostream& out) int numOfPhiNodes = 0; auto firstNonPhiPtr = bb->llvm()->getFirstNonPHI(); for (auto instrIter = bb->llvm()->begin(); &*instrIter != firstNonPhiPtr; ++instrIter, ++numOfPhiNodes); + phiNodesPerBlock[bb] = numOfPhiNodes; + auto initStackSize = bb->getStack().initialSize(); auto endStackSize = bb->getStack().size(); out << " \"" << blockName << "\" [shape=record, label=\"" - << numOfPhiNodes << "|" << blockName << "|" << endStackSize + << initStackSize << "|" << blockName << "|" << endStackSize << "\"];\n"; } - out << " entry -> \"Instr.0\";\n"; - // Output edges for (auto bb : blocks) { std::string blockName = bb->llvm()->getName(); - auto end = llvm::succ_end(bb->llvm()); - for (llvm::succ_iterator it = llvm::succ_begin(bb->llvm()); it != end; ++it) + auto end = llvm::pred_end(bb->llvm()); + for (llvm::pred_iterator it = llvm::pred_begin(bb->llvm()); it != end; ++it) { - std::string succName = it->getName(); - out << " \"" << blockName << "\" -> \"" << succName << "\"" - << ((bb == m_jumpTableBlock.get()) ? " [style = dashed];\n" : "\n"); + out << " \"" << (*it)->getName().str() << "\" -> \"" << blockName << "\" [" + << ((m_jumpTableBlock.get() && *it == m_jumpTableBlock.get()->llvm()) ? "style = dashed, " : "") + << "label = \"" + << phiNodesPerBlock[bb] + << "\"];\n"; } } From 472f9c749fb87eefbb45811d1c1d9a30b1493aab Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Wed, 22 Oct 2014 10:01:56 +0100 Subject: [PATCH 189/641] Fixed the order in which phi nodes are created (was incorrect) [#80895676] --- evmcc/test/jump/fib1.ethel | 3 ++- evmcc/test/jump/fib1.evm | 2 +- evmcc/test/jump/rec1.ethel | 4 ++++ evmcc/test/jump/rec1.evm | 1 + libevmjit/BasicBlock.cpp | 2 +- 5 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 evmcc/test/jump/rec1.ethel create mode 100644 evmcc/test/jump/rec1.evm diff --git a/evmcc/test/jump/fib1.ethel b/evmcc/test/jump/fib1.ethel index 6efd4ed2d..81b869f41 100644 --- a/evmcc/test/jump/fib1.ethel +++ b/evmcc/test/jump/fib1.ethel @@ -2,4 +2,5 @@ let fib n = if n < 3 then 1 else fib (n-1) + fib (n-2) -return fib 5 +return fib 10 + diff --git a/evmcc/test/jump/fib1.evm b/evmcc/test/jump/fib1.evm index b5b5bf9c6..5042a192f 100644 --- a/evmcc/test/jump/fib1.evm +++ b/evmcc/test/jump/fib1.evm @@ -1 +1 @@ -630000000d60056300000016585d60005460206000f28060030a630000004759630000002f816001036300000016585d630000003f836002036300000016585d0163000000495860019350505058 \ No newline at end of file +6007600a6010585d60005460206000f26003810a602f596020600282036010585d602a600183036010585d01603158600190509058 \ No newline at end of file diff --git a/evmcc/test/jump/rec1.ethel b/evmcc/test/jump/rec1.ethel new file mode 100644 index 000000000..f83c8e81e --- /dev/null +++ b/evmcc/test/jump/rec1.ethel @@ -0,0 +1,4 @@ +let f n = + if n == 0 then 2 else f (n-1) + +return f 10 diff --git a/evmcc/test/jump/rec1.evm b/evmcc/test/jump/rec1.evm new file mode 100644 index 000000000..2ae62aff6 --- /dev/null +++ b/evmcc/test/jump/rec1.evm @@ -0,0 +1 @@ +6007600a6010585d60005460206000f26000810e6024596020600182036010585d602658600290509058 \ No newline at end of file diff --git a/libevmjit/BasicBlock.cpp b/libevmjit/BasicBlock.cpp index 927f1180b..2c5ea7285 100644 --- a/libevmjit/BasicBlock.cpp +++ b/libevmjit/BasicBlock.cpp @@ -52,7 +52,7 @@ llvm::Value* BasicBlock::LocalStack::get(size_t _index) m_backend.insert(m_backend.begin(), nMissingVals, nullptr); for (decltype(nMissingVals) i = 0; i < nMissingVals; ++i) { - m_backend[i] = m_llvmBB->empty() ? + m_backend[nMissingVals - 1 - i] = m_llvmBB->empty() ? llvm::PHINode::Create(Type::i256, 0, {}, m_llvmBB) : llvm::PHINode::Create(Type::i256, 0, {}, m_llvmBB->getFirstNonPHI()); m_numRequiredStackItems += 1; From 71426520a1fb387cfc8bdd6c63d9b1fa3123c1bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 22 Oct 2014 15:12:27 +0200 Subject: [PATCH 190/641] Add LLVMEnable user macro in LLVM.props (VS property sheet) to allow easily disabling LLVM dependency --- windows/Eth.vcxproj | 4 ++++ windows/LLVM.props | 17 +++++++++++++++-- windows/TestEthereum.vcxproj | 3 +++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/windows/Eth.vcxproj b/windows/Eth.vcxproj index 9b2d47727..3af0a0bce 100644 --- a/windows/Eth.vcxproj +++ b/windows/Eth.vcxproj @@ -52,21 +52,25 @@ + + + + diff --git a/windows/LLVM.props b/windows/LLVM.props index 3290a4f64..42be9a170 100644 --- a/windows/LLVM.props +++ b/windows/LLVM.props @@ -2,22 +2,32 @@ + 1 + ..\..\llvm ..\..\_build\llvm\$(Platform) - ..\..\llvm\include;$(LLVMBuildDir)\include + $(LLVMSrcDir)\include;$(LLVMBuildDir)\include $(LLVMBuildDir)\$(Configuration)\lib + LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib $(LLVMIncludeDir);%(AdditionalIncludeDirectories) 4800;%(DisableSpecificWarnings) + ETH_JIT=$(LLVMEnabled);%(PreprocessorDefinitions) $(LLVMLibDir);%(AdditionalLibraryDirectories) - LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) + $(LLVMLibs);%(AdditionalDependencies) + + $(LLVMEnabled) + + + $(LLVMSrcDir) + $(LLVMBuildDir) @@ -27,5 +37,8 @@ $(LLVMLibDir) + + $(LLVMLibs) + \ No newline at end of file diff --git a/windows/TestEthereum.vcxproj b/windows/TestEthereum.vcxproj index be475a949..277a38a3d 100644 --- a/windows/TestEthereum.vcxproj +++ b/windows/TestEthereum.vcxproj @@ -51,6 +51,7 @@ + @@ -60,10 +61,12 @@ + + From 4f69964b2a5ceee327d3f1c18a7f5d18ba87c8d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 22 Oct 2014 16:23:25 +0200 Subject: [PATCH 191/641] Extract interface of VM into new VMFace class --- libevm/VM.cpp | 12 ++++- libevm/VM.h | 38 +++------------ libevm/VMFace.cpp | 19 ++++++++ libevm/VMFace.h | 75 +++++++++++++++++++++++++++++ windows/LibEthereum.vcxproj | 2 + windows/LibEthereum.vcxproj.filters | 6 +++ 6 files changed, 120 insertions(+), 32 deletions(-) create mode 100644 libevm/VMFace.cpp create mode 100644 libevm/VMFace.h diff --git a/libevm/VM.cpp b/libevm/VM.cpp index e47237d5a..4afd75659 100644 --- a/libevm/VM.cpp +++ b/libevm/VM.cpp @@ -20,13 +20,21 @@ */ #include "VM.h" +#include -using namespace std; using namespace dev; using namespace dev::eth; void VM::reset(u256 _gas) { - m_gas = _gas; + VMFace::reset(_gas); m_curPC = 0; } + +bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps) +{ + if (auto defaultExt = dynamic_cast(&_ext)) + return go(*defaultExt, _onOp, _steps); + else + return go(_ext, _onOp, _steps); +} diff --git a/libevm/VM.h b/libevm/VM.h index e092bdfed..9f47afe4a 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -27,6 +27,7 @@ #include #include #include +#include "VMFace.h" #include "FeeStructure.h" #include "ExtVMFace.h" @@ -35,52 +36,29 @@ namespace dev namespace eth { -struct VMException: virtual Exception {}; -struct StepsDone: virtual VMException {}; -struct BreakPointHit: virtual VMException {}; -struct BadInstruction: virtual VMException {}; -struct BadJumpDestination: virtual VMException {}; -struct OutOfGas: virtual VMException {}; -class StackTooSmall: virtual public VMException { public: StackTooSmall(u256 _req, u256 _got): req(_req), got(_got) {} u256 req; u256 got; }; - -// Convert from a 256-bit integer stack/memory entry into a 160-bit Address hash. -// Currently we just pull out the right (low-order in BE) 160-bits. -inline Address asAddress(u256 _item) -{ - return right160(h256(_item)); -} - -inline u256 fromAddress(Address _a) -{ - return (u160)_a; -// h256 ret; -// memcpy(&ret, &_a, sizeof(_a)); -// return ret; -} - /** */ -class VM +class VM : public VMFace { public: /// Construct VM object. - explicit VM(u256 _gas = 0) { reset(_gas); } + explicit VM(u256 _gas = 0): VMFace(_gas) {} - void reset(u256 _gas = 0); + virtual void reset(u256 _gas = 0) override final; - template - bytesConstRef go(Ext& _ext, OnOpFunc const& _onOp = OnOpFunc(), uint64_t _steps = (uint64_t)-1); + virtual bytesConstRef go(ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) override final; void require(u256 _n) { if (m_stack.size() < _n) BOOST_THROW_EXCEPTION(StackTooSmall(_n, m_stack.size())); } void requireMem(unsigned _n) { if (m_temp.size() < _n) { m_temp.resize(_n); } } - u256 gas() const { return m_gas; } u256 curPC() const { return m_curPC; } bytes const& memory() const { return m_temp; } u256s const& stack() const { return m_stack; } private: - u256 m_gas = 0; + template + bytesConstRef go(Ext& _ext, OnOpFunc const& _onOp, uint64_t _steps); + u256 m_curPC = 0; bytes m_temp; u256s m_stack; diff --git a/libevm/VMFace.cpp b/libevm/VMFace.cpp new file mode 100644 index 000000000..22f13d5a6 --- /dev/null +++ b/libevm/VMFace.cpp @@ -0,0 +1,19 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ + +#include "VM.h" + diff --git a/libevm/VMFace.h b/libevm/VMFace.h new file mode 100644 index 000000000..f10068700 --- /dev/null +++ b/libevm/VMFace.h @@ -0,0 +1,75 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ + +#pragma once + +#include +#include "ExtVMFace.h" + +namespace dev +{ +namespace eth +{ + +struct VMException: virtual Exception {}; +struct StepsDone: virtual VMException {}; +struct BreakPointHit: virtual VMException {}; +struct BadInstruction: virtual VMException {}; +struct BadJumpDestination: virtual VMException {}; +struct OutOfGas: virtual VMException {}; +class StackTooSmall: virtual public VMException { public: StackTooSmall(u256 _req, u256 _got): req(_req), got(_got) {} u256 req; u256 got; }; + +// Convert from a 256-bit integer stack/memory entry into a 160-bit Address hash. +// Currently we just pull out the right (low-order in BE) 160-bits. +inline Address asAddress(u256 _item) +{ + return right160(h256(_item)); +} + +inline u256 fromAddress(Address _a) +{ + return (u160)_a; + // h256 ret; + // memcpy(&ret, &_a, sizeof(_a)); + // return ret; +} + +/** + */ +class VMFace +{ +public: + /// Construct VM object. + explicit VMFace(u256 _gas = 0): m_gas(_gas) {} + + virtual ~VMFace() = default; + + VMFace(VMFace const&) = delete; + void operator=(VMFace const&) = delete; + + virtual void reset(u256 _gas = 0) { m_gas = _gas; } + + virtual bytesConstRef go(ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) = 0; + + u256 gas() const { return m_gas; } + +protected: + u256 m_gas = 0; +}; + +} +} diff --git a/windows/LibEthereum.vcxproj b/windows/LibEthereum.vcxproj index 8c08091ec..b5305c322 100644 --- a/windows/LibEthereum.vcxproj +++ b/windows/LibEthereum.vcxproj @@ -141,6 +141,7 @@ true true + @@ -360,6 +361,7 @@ true true + diff --git a/windows/LibEthereum.vcxproj.filters b/windows/LibEthereum.vcxproj.filters index 7d743d82d..e86c30c00 100644 --- a/windows/LibEthereum.vcxproj.filters +++ b/windows/LibEthereum.vcxproj.filters @@ -193,6 +193,9 @@ libethcore + + libevm + @@ -417,6 +420,9 @@ libwebthree + + libevm + From dfb283097ca5e1bccc07c33d8a997612afe084f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 22 Oct 2014 16:40:05 +0200 Subject: [PATCH 192/641] Implement VMFace with jit::VM --- libevmjit/VM.cpp | 7 ++++--- libevmjit/VM.h | 14 +++++--------- test/vm.cpp | 2 +- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/libevmjit/VM.cpp b/libevmjit/VM.cpp index 16011241e..c6364eadb 100644 --- a/libevmjit/VM.cpp +++ b/libevmjit/VM.cpp @@ -1,7 +1,7 @@ #include "VM.h" -#include +#include #include "ExecutionEngine.h" #include "Compiler.h" @@ -13,7 +13,7 @@ namespace eth namespace jit { -bytes VM::go(ExtVMFace& _ext) +bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps) { auto module = Compiler().compile(_ext.code); @@ -30,7 +30,8 @@ bytes VM::go(ExtVMFace& _ext) BOOST_THROW_EXCEPTION(StackTooSmall(1,0)); } - return std::move(engine.returnData); + m_output = std::move(engine.returnData); + return {m_output.data(), m_output.size()}; // TODO: This all bytesConstRef stuff sucks } } diff --git a/libevmjit/VM.h b/libevmjit/VM.h index 3e7884b10..934e16ed0 100644 --- a/libevmjit/VM.h +++ b/libevmjit/VM.h @@ -2,6 +2,7 @@ #pragma once #include +#include #include namespace dev @@ -11,20 +12,15 @@ namespace eth namespace jit { -class VM +class VM: public VMFace { public: - /// Construct VM object. - explicit VM(u256 _gas = 0): m_gas(_gas) {} + explicit VM(u256 _gas = 0): VMFace(_gas) {} - void reset(u256 _gas = 0) { m_gas = _gas; } - - bytes go(ExtVMFace& _ext); - - u256 gas() const { return m_gas; } + virtual bytesConstRef go(ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) final; private: - u256 m_gas = 0; + bytes m_output; }; } diff --git a/test/vm.cpp b/test/vm.cpp index cd40a5ee3..179a47b91 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -524,7 +524,7 @@ void doTests(json_spirit::mValue& v, bool _fillin) try { if (useJit) - output = jit.go(fev); + output = jit.go(fev).toVector(); else output = interpreter.go(fev).toVector(); } From f49612f10c522622d67f212df71250c3d0bbb441 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 22 Oct 2014 16:52:47 +0200 Subject: [PATCH 193/641] Update VM test engine to use VMFace interface --- test/vm.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/test/vm.cpp b/test/vm.cpp index 179a47b91..4671a92b6 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -517,16 +517,13 @@ void doTests(json_spirit::mValue& v, bool _fillin) auto argv = boost::unit_test::framework::master_test_suite().argv; auto useJit = argc >= 2 && std::string(argv[1]) == "--jit"; - jit::VM jit(fev.gas); - VM interpreter(fev.gas); + auto vm = useJit ? std::unique_ptr(new jit::VM) : std::unique_ptr(new VM); + vm->reset(fev.gas); bytes output; auto outOfGas = false; try { - if (useJit) - output = jit.go(fev).toVector(); - else - output = interpreter.go(fev).toVector(); + output = vm->go(fev).toVector(); } catch (OutOfGas const&) { @@ -540,7 +537,7 @@ void doTests(json_spirit::mValue& v, bool _fillin) { cnote << "VM did throw an exception: " << _e.what(); } - auto gas = useJit ? jit.gas() : interpreter.gas(); + auto gas = vm->gas(); // delete null entries in storage for the sake of comparison From 08cae3947ead23e5cde92bc0ec6c1b1f48d63487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 22 Oct 2014 17:27:27 +0200 Subject: [PATCH 194/641] Try not to use JIT in any interactive mode --- libevmjit/VM.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libevmjit/VM.cpp b/libevmjit/VM.cpp index c6364eadb..f1c1ad0a7 100644 --- a/libevmjit/VM.cpp +++ b/libevmjit/VM.cpp @@ -15,6 +15,9 @@ namespace jit bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps) { + assert(_onOp == nullptr); // Parameter ignored + assert(_steps == (uint64_t)-1); // Parameter ignored + auto module = Compiler().compile(_ext.code); ExecutionEngine engine; From a7dabc897e42318b9f1be7c40036058b4183f906 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 22 Oct 2014 17:30:02 +0200 Subject: [PATCH 195/641] Use VMFace in some places in Executive --- libethereum/Executive.cpp | 2 +- libethereum/Executive.h | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index fe5b21761..c46b8c39b 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -147,7 +147,7 @@ OnOpFunc Executive::simpleTrace() return [](uint64_t steps, Instruction inst, bigint newMemSize, bigint gasCost, void* voidVM, void const* voidExt) { ExtVM const& ext = *(ExtVM const*)voidExt; - VM& vm = *(VM*)voidVM; + VM& vm = *(VM*)voidVM; // TODO: Ok for now, because only interpeter/VM supports OnOp callback, but safer solution would be nice ostringstream o; o << endl << " STACK" << endl; diff --git a/libethereum/Executive.h b/libethereum/Executive.h index 82b7df7e9..f7c056252 100644 --- a/libethereum/Executive.h +++ b/libethereum/Executive.h @@ -25,7 +25,6 @@ #include #include #include -#include #include "Transaction.h" #include "Manifest.h" @@ -34,7 +33,7 @@ namespace dev namespace eth { -class VM; +class VMFace; class ExtVM; class State; @@ -62,14 +61,14 @@ public: bytesConstRef out() const { return m_out; } h160 newAddress() const { return m_newAddress; } - VM const& vm() const { return *m_vm; } + VMFace const& vm() const { return *m_vm; } State const& state() const { return m_s; } ExtVM const& ext() const { return *m_ext; } private: State& m_s; ExtVM* m_ext = nullptr; // TODO: make safe. - VM* m_vm = nullptr; + VMFace* m_vm = nullptr; Manifest* m_ms = nullptr; bytesConstRef m_out; Address m_newAddress; From 6ca44a9ada482608221237c571533a5590de9dad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 22 Oct 2014 17:35:33 +0200 Subject: [PATCH 196/641] Better assert condition --- libevmjit/VM.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libevmjit/VM.cpp b/libevmjit/VM.cpp index f1c1ad0a7..9a76c5bcb 100644 --- a/libevmjit/VM.cpp +++ b/libevmjit/VM.cpp @@ -15,7 +15,7 @@ namespace jit bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps) { - assert(_onOp == nullptr); // Parameter ignored + assert(!_onOp); // Parameter ignored assert(_steps == (uint64_t)-1); // Parameter ignored auto module = Compiler().compile(_ext.code); From 900fd04f1edab3f86e789d629c7350d17a6a0f68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 22 Oct 2014 18:48:14 +0200 Subject: [PATCH 197/641] Change the way VMs are created (mostly for tracking where are created) --- libethereum/Executive.cpp | 4 ++-- libethereum/State.cpp | 6 ++++-- libevm/VM.h | 8 ++++---- libevm/VMFace.cpp | 11 +++++++++++ libevm/VMFace.h | 7 ++++++- libevmjit/VM.h | 8 ++++---- test/vm.cpp | 7 ++++--- windows/Eth.vcxproj | 3 +++ 8 files changed, 38 insertions(+), 16 deletions(-) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index c46b8c39b..30986928e 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -118,7 +118,7 @@ bool Executive::call(Address _receiveAddress, Address _senderAddress, u256 _valu if (m_s.addressHasCode(_receiveAddress)) { - m_vm = new VM(_gas); + m_vm = VMFace::create(VMFace::Interpreter, _gas).release(); bytes const& c = m_s.code(_receiveAddress); m_ext = new ExtVM(m_s, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &c, m_ms); } @@ -137,7 +137,7 @@ bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _g m_s.m_cache[m_newAddress] = AddressState(0, m_s.balance(m_newAddress) + _endowment, h256(), h256()); // Execute _init. - m_vm = new VM(_gas); + m_vm = VMFace::create(VMFace::JIT, _gas).release(); m_ext = new ExtVM(m_s, m_newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _init, m_ms); return _init.empty(); } diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 931ee2cf6..b51224e32 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -1146,7 +1146,8 @@ bool State::call(Address _receiveAddress, Address _codeAddress, Address _senderA } else if (addressHasCode(_codeAddress)) { - VM vm(*_gas); + auto vmObj = VMFace::create(VMFace::Interpreter, *_gas); + VMFace& vm = *vmObj; ExtVM evm(*this, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &code(_codeAddress), o_ms, _level); bool revert = false; @@ -1208,7 +1209,8 @@ h160 State::create(Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas, m_cache[newAddress] = AddressState(0, balance(newAddress) + _endowment, h256(), h256()); // Execute init code. - VM vm(*_gas); + auto vmObj = VMFace::create(VMFace::Interpreter, *_gas); + VMFace& vm = *vmObj; ExtVM evm(*this, newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _code, o_ms, _level); bool revert = false; bytesConstRef out; diff --git a/libevm/VM.h b/libevm/VM.h index 9f47afe4a..2ddf16bb6 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -41,10 +41,7 @@ namespace eth class VM : public VMFace { public: - /// Construct VM object. - explicit VM(u256 _gas = 0): VMFace(_gas) {} - - virtual void reset(u256 _gas = 0) override final; + virtual void reset(u256 _gas = 0) noexcept override final; virtual bytesConstRef go(ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) override final; @@ -56,6 +53,9 @@ public: u256s const& stack() const { return m_stack; } private: + friend VMFace; + explicit VM(u256 _gas = 0): VMFace(_gas) {} + template bytesConstRef go(Ext& _ext, OnOpFunc const& _onOp, uint64_t _steps); diff --git a/libevm/VMFace.cpp b/libevm/VMFace.cpp index 22f13d5a6..2553f3004 100644 --- a/libevm/VMFace.cpp +++ b/libevm/VMFace.cpp @@ -15,5 +15,16 @@ along with cpp-ethereum. If not, see . */ +#include "VMFace.h" #include "VM.h" +#include +using namespace dev; +using namespace dev::eth; + +std::unique_ptr VMFace::create(VMFace::Kind _kind, u256 _gas) +{ + std::unique_ptr vm(_kind == Kind::JIT ? static_cast(new jit::VM) : new VM); + vm->reset(_gas); + return vm; +} diff --git a/libevm/VMFace.h b/libevm/VMFace.h index f10068700..508a39bc0 100644 --- a/libevm/VMFace.h +++ b/libevm/VMFace.h @@ -17,6 +17,7 @@ #pragma once +#include #include #include "ExtVMFace.h" @@ -61,12 +62,16 @@ public: VMFace(VMFace const&) = delete; void operator=(VMFace const&) = delete; - virtual void reset(u256 _gas = 0) { m_gas = _gas; } + virtual void reset(u256 _gas = 0) noexcept { m_gas = _gas; } virtual bytesConstRef go(ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) = 0; u256 gas() const { return m_gas; } + enum Kind: bool { Interpreter, JIT }; + + static std::unique_ptr create(Kind, u256 _gas = 0); + protected: u256 m_gas = 0; }; diff --git a/libevmjit/VM.h b/libevmjit/VM.h index 934e16ed0..93b359cd7 100644 --- a/libevmjit/VM.h +++ b/libevmjit/VM.h @@ -14,12 +14,12 @@ namespace jit class VM: public VMFace { -public: - explicit VM(u256 _gas = 0): VMFace(_gas) {} - - virtual bytesConstRef go(ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) final; + virtual bytesConstRef go(ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) override final; private: + friend VMFace; + explicit VM(u256 _gas = 0): VMFace(_gas) {} + bytes m_output; }; diff --git a/test/vm.cpp b/test/vm.cpp index 4671a92b6..d62329af4 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -436,7 +436,8 @@ h160 FakeState::createNewAddress(Address _newAddress, Address _sender, u256 _end m_cache[_newAddress] = AddressState(0, balance(_newAddress) + _endowment, h256(), h256()); // Execute init code. - VM vm(*_gas); + auto vmObj = VMFace::create(VMFace::Interpreter, *_gas); + VMFace& vm = *vmObj; ExtVM evm(*this, _newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _code, o_ms, _level); bool revert = false; bytesConstRef out; @@ -517,8 +518,8 @@ void doTests(json_spirit::mValue& v, bool _fillin) auto argv = boost::unit_test::framework::master_test_suite().argv; auto useJit = argc >= 2 && std::string(argv[1]) == "--jit"; - auto vm = useJit ? std::unique_ptr(new jit::VM) : std::unique_ptr(new VM); - vm->reset(fev.gas); + auto vmKind = useJit ? VMFace::JIT : VMFace::Interpreter; + auto vm = VMFace::create(vmKind, fev.gas); bytes output; auto outOfGas = false; try diff --git a/windows/Eth.vcxproj b/windows/Eth.vcxproj index 3af0a0bce..d67d964f8 100644 --- a/windows/Eth.vcxproj +++ b/windows/Eth.vcxproj @@ -155,6 +155,9 @@ {826e68cb-d3ee-4a8a-b540-59a8c3f38d4f} + + {9c816740-5c11-4377-a3a7-46be12f35fa0} + From 0ff7da1c9d84f80990b3e7c540227b6be35768ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 22 Oct 2014 19:27:10 +0200 Subject: [PATCH 198/641] Do not skip evmcc build in Visual Studio solution --- windows/Ethereum.sln | 280 ++++++++++++++++++++++--------------------- 1 file changed, 141 insertions(+), 139 deletions(-) diff --git a/windows/Ethereum.sln b/windows/Ethereum.sln index c4ac205a7..df5916e63 100644 --- a/windows/Ethereum.sln +++ b/windows/Ethereum.sln @@ -57,88 +57,88 @@ Global Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|Win32.ActiveCfg = Debug|Win32 - {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|Win32.Build.0 = Debug|Win32 - {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|x64.ActiveCfg = Debug|x64 - {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|x64.Build.0 = Debug|x64 - {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|Mixed Platforms.Build.0 = Release|Win32 - {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|Win32.ActiveCfg = Release|Win32 - {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|Win32.Build.0 = Release|Win32 + {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|Mixed Platforms.ActiveCfg = Release|x64 + {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|Mixed Platforms.Build.0 = Release|x64 + {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|Win32.ActiveCfg = Release|x64 + {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|Win32.Build.0 = Release|x64 + {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|x64.ActiveCfg = Release|x64 + {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|x64.Build.0 = Release|x64 + {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|Mixed Platforms.ActiveCfg = Release|x64 + {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|Mixed Platforms.Build.0 = Release|x64 + {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|Win32.ActiveCfg = Release|x64 + {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|Win32.Build.0 = Release|x64 {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|x64.ActiveCfg = Release|x64 {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|x64.Build.0 = Release|x64 - {27014763-955D-486B-9BA7-69872192E6F4}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {27014763-955D-486B-9BA7-69872192E6F4}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {27014763-955D-486B-9BA7-69872192E6F4}.Debug|Win32.ActiveCfg = Debug|Win32 - {27014763-955D-486B-9BA7-69872192E6F4}.Debug|Win32.Build.0 = Debug|Win32 - {27014763-955D-486B-9BA7-69872192E6F4}.Debug|x64.ActiveCfg = Debug|x64 - {27014763-955D-486B-9BA7-69872192E6F4}.Debug|x64.Build.0 = Debug|x64 - {27014763-955D-486B-9BA7-69872192E6F4}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {27014763-955D-486B-9BA7-69872192E6F4}.Release|Mixed Platforms.Build.0 = Release|Win32 - {27014763-955D-486B-9BA7-69872192E6F4}.Release|Win32.ActiveCfg = Release|Win32 - {27014763-955D-486B-9BA7-69872192E6F4}.Release|Win32.Build.0 = Release|Win32 + {27014763-955D-486B-9BA7-69872192E6F4}.Debug|Mixed Platforms.ActiveCfg = Release|x64 + {27014763-955D-486B-9BA7-69872192E6F4}.Debug|Mixed Platforms.Build.0 = Release|x64 + {27014763-955D-486B-9BA7-69872192E6F4}.Debug|Win32.ActiveCfg = Release|x64 + {27014763-955D-486B-9BA7-69872192E6F4}.Debug|Win32.Build.0 = Release|x64 + {27014763-955D-486B-9BA7-69872192E6F4}.Debug|x64.ActiveCfg = Release|x64 + {27014763-955D-486B-9BA7-69872192E6F4}.Debug|x64.Build.0 = Release|x64 + {27014763-955D-486B-9BA7-69872192E6F4}.Release|Mixed Platforms.ActiveCfg = Release|x64 + {27014763-955D-486B-9BA7-69872192E6F4}.Release|Mixed Platforms.Build.0 = Release|x64 + {27014763-955D-486B-9BA7-69872192E6F4}.Release|Win32.ActiveCfg = Release|x64 + {27014763-955D-486B-9BA7-69872192E6F4}.Release|Win32.Build.0 = Release|x64 {27014763-955D-486B-9BA7-69872192E6F4}.Release|x64.ActiveCfg = Release|x64 {27014763-955D-486B-9BA7-69872192E6F4}.Release|x64.Build.0 = Release|x64 - {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|Win32.ActiveCfg = Debug|Win32 - {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|Win32.Build.0 = Debug|Win32 - {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|x64.ActiveCfg = Debug|x64 - {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|x64.Build.0 = Debug|x64 - {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|Mixed Platforms.Build.0 = Release|Win32 - {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|Win32.ActiveCfg = Release|Win32 - {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|Win32.Build.0 = Release|Win32 + {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|Mixed Platforms.ActiveCfg = Release|x64 + {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|Mixed Platforms.Build.0 = Release|x64 + {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|Win32.ActiveCfg = Release|x64 + {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|Win32.Build.0 = Release|x64 + {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|x64.ActiveCfg = Release|x64 + {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|x64.Build.0 = Release|x64 + {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|Mixed Platforms.ActiveCfg = Release|x64 + {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|Mixed Platforms.Build.0 = Release|x64 + {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|Win32.ActiveCfg = Release|x64 + {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|Win32.Build.0 = Release|x64 {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|x64.ActiveCfg = Release|x64 {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|x64.Build.0 = Release|x64 - {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|Win32.ActiveCfg = Debug|Win32 - {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|Win32.Build.0 = Debug|Win32 - {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|x64.ActiveCfg = Debug|x64 - {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|x64.Build.0 = Debug|x64 - {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|Mixed Platforms.Build.0 = Release|Win32 - {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|Win32.ActiveCfg = Release|Win32 - {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|Win32.Build.0 = Release|Win32 + {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|Mixed Platforms.ActiveCfg = Release|x64 + {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|Mixed Platforms.Build.0 = Release|x64 + {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|Win32.ActiveCfg = Release|x64 + {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|Win32.Build.0 = Release|x64 + {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|x64.ActiveCfg = Release|x64 + {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|x64.Build.0 = Release|x64 + {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|Mixed Platforms.ActiveCfg = Release|x64 + {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|Mixed Platforms.Build.0 = Release|x64 + {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|Win32.ActiveCfg = Release|x64 + {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|Win32.Build.0 = Release|x64 {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|x64.ActiveCfg = Release|x64 {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|x64.Build.0 = Release|x64 - {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|Win32.ActiveCfg = Debug|Win32 - {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|Win32.Build.0 = Debug|Win32 - {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|x64.ActiveCfg = Debug|x64 - {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|x64.Build.0 = Debug|x64 - {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|Mixed Platforms.Build.0 = Release|Win32 - {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|Win32.ActiveCfg = Release|Win32 - {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|Win32.Build.0 = Release|Win32 + {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|Mixed Platforms.ActiveCfg = Release|x64 + {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|Mixed Platforms.Build.0 = Release|x64 + {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|Win32.ActiveCfg = Release|x64 + {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|Win32.Build.0 = Release|x64 + {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|x64.ActiveCfg = Release|x64 + {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|x64.Build.0 = Release|x64 + {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|Mixed Platforms.ActiveCfg = Release|x64 + {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|Mixed Platforms.Build.0 = Release|x64 + {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|Win32.ActiveCfg = Release|x64 + {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|Win32.Build.0 = Release|x64 {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|x64.ActiveCfg = Release|x64 {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|x64.Build.0 = Release|x64 - {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|Win32.ActiveCfg = Debug|Win32 - {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|Win32.Build.0 = Debug|Win32 - {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|x64.ActiveCfg = Debug|x64 - {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|x64.Build.0 = Debug|x64 - {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|Mixed Platforms.Build.0 = Release|Win32 - {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|Win32.ActiveCfg = Release|Win32 - {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|Win32.Build.0 = Release|Win32 + {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|Mixed Platforms.ActiveCfg = Release|x64 + {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|Mixed Platforms.Build.0 = Release|x64 + {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|Win32.ActiveCfg = Release|x64 + {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|Win32.Build.0 = Release|x64 + {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|x64.ActiveCfg = Release|x64 + {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|x64.Build.0 = Release|x64 + {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|Mixed Platforms.ActiveCfg = Release|x64 + {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|Mixed Platforms.Build.0 = Release|x64 + {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|Win32.ActiveCfg = Release|x64 + {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|Win32.Build.0 = Release|x64 {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|x64.ActiveCfg = Release|x64 {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|x64.Build.0 = Release|x64 - {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|Win32.ActiveCfg = Debug|Win32 - {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|Win32.Build.0 = Debug|Win32 - {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|x64.ActiveCfg = Debug|x64 - {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|x64.Build.0 = Debug|x64 - {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|Mixed Platforms.Build.0 = Release|Win32 - {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|Win32.ActiveCfg = Release|Win32 - {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|Win32.Build.0 = Release|Win32 + {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|Mixed Platforms.ActiveCfg = Release|x64 + {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|Mixed Platforms.Build.0 = Release|x64 + {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|Win32.ActiveCfg = Release|x64 + {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|Win32.Build.0 = Release|x64 + {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|x64.ActiveCfg = Release|x64 + {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|x64.Build.0 = Release|x64 + {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|Mixed Platforms.ActiveCfg = Release|x64 + {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|Mixed Platforms.Build.0 = Release|x64 + {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|Win32.ActiveCfg = Release|x64 + {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|Win32.Build.0 = Release|x64 {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|x64.ActiveCfg = Release|x64 {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|x64.Build.0 = Release|x64 {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 @@ -161,16 +161,16 @@ Global {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Release|Win32.Build.0 = Release|Win32 {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Release|x64.ActiveCfg = Release|x64 {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Release|x64.Build.0 = Release|x64 - {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|Win32.ActiveCfg = Debug|Win32 - {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|Win32.Build.0 = Debug|Win32 - {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|x64.ActiveCfg = Debug|x64 - {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|x64.Build.0 = Debug|x64 - {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|Mixed Platforms.Build.0 = Release|Win32 - {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|Win32.ActiveCfg = Release|Win32 - {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|Win32.Build.0 = Release|Win32 + {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|Mixed Platforms.ActiveCfg = Release|x64 + {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|Mixed Platforms.Build.0 = Release|x64 + {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|Win32.ActiveCfg = Release|x64 + {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|Win32.Build.0 = Release|x64 + {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|x64.ActiveCfg = Release|x64 + {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|x64.Build.0 = Release|x64 + {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|Mixed Platforms.ActiveCfg = Release|x64 + {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|Mixed Platforms.Build.0 = Release|x64 + {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|Win32.ActiveCfg = Release|x64 + {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|Win32.Build.0 = Release|x64 {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|x64.ActiveCfg = Release|x64 {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|x64.Build.0 = Release|x64 {90C70663-7181-4E99-9079-54188CEB8954}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 @@ -185,74 +185,76 @@ Global {90C70663-7181-4E99-9079-54188CEB8954}.Release|Win32.Build.0 = Release|Win32 {90C70663-7181-4E99-9079-54188CEB8954}.Release|x64.ActiveCfg = Release|x64 {90C70663-7181-4E99-9079-54188CEB8954}.Release|x64.Build.0 = Release|x64 - {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|Win32.ActiveCfg = Debug|Win32 - {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|Win32.Build.0 = Debug|Win32 - {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|x64.ActiveCfg = Debug|x64 - {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|x64.Build.0 = Debug|x64 - {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|Mixed Platforms.Build.0 = Release|Win32 - {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|Win32.ActiveCfg = Release|Win32 - {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|Win32.Build.0 = Release|Win32 + {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|Mixed Platforms.ActiveCfg = Release|x64 + {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|Mixed Platforms.Build.0 = Release|x64 + {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|Win32.ActiveCfg = Release|x64 + {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|Win32.Build.0 = Release|x64 + {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|x64.ActiveCfg = Release|x64 + {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|x64.Build.0 = Release|x64 + {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|Mixed Platforms.ActiveCfg = Release|x64 + {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|Mixed Platforms.Build.0 = Release|x64 + {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|Win32.ActiveCfg = Release|x64 + {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|Win32.Build.0 = Release|x64 {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|x64.ActiveCfg = Release|x64 {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|x64.Build.0 = Release|x64 - {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|Win32.ActiveCfg = Debug|Win32 - {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|Win32.Build.0 = Debug|Win32 - {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|x64.ActiveCfg = Debug|x64 - {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|x64.Build.0 = Debug|x64 - {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|Mixed Platforms.Build.0 = Release|Win32 - {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|Win32.ActiveCfg = Release|Win32 - {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|Win32.Build.0 = Release|Win32 + {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|Mixed Platforms.ActiveCfg = Release|x64 + {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|Mixed Platforms.Build.0 = Release|x64 + {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|Win32.ActiveCfg = Release|x64 + {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|Win32.Build.0 = Release|x64 + {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|x64.ActiveCfg = Release|x64 + {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|x64.Build.0 = Release|x64 + {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|Mixed Platforms.ActiveCfg = Release|x64 + {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|Mixed Platforms.Build.0 = Release|x64 + {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|Win32.ActiveCfg = Release|x64 + {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|Win32.Build.0 = Release|x64 {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|x64.ActiveCfg = Release|x64 {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|x64.Build.0 = Release|x64 - {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|Win32.ActiveCfg = Debug|Win32 - {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|Win32.Build.0 = Debug|Win32 - {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|x64.ActiveCfg = Debug|x64 - {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|x64.Build.0 = Debug|x64 - {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|Mixed Platforms.Build.0 = Release|Win32 - {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|Win32.ActiveCfg = Release|Win32 - {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|Win32.Build.0 = Release|Win32 + {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|Mixed Platforms.ActiveCfg = Release|x64 + {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|Mixed Platforms.Build.0 = Release|x64 + {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|Win32.ActiveCfg = Release|x64 + {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|Win32.Build.0 = Release|x64 + {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|x64.ActiveCfg = Release|x64 + {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|x64.Build.0 = Release|x64 + {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|Mixed Platforms.ActiveCfg = Release|x64 + {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|Mixed Platforms.Build.0 = Release|x64 + {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|Win32.ActiveCfg = Release|x64 + {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|Win32.Build.0 = Release|x64 {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|x64.ActiveCfg = Release|x64 {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|x64.Build.0 = Release|x64 - {255BDC68-B8DB-465F-8220-981E77684189}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {255BDC68-B8DB-465F-8220-981E77684189}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {255BDC68-B8DB-465F-8220-981E77684189}.Debug|Win32.ActiveCfg = Debug|Win32 - {255BDC68-B8DB-465F-8220-981E77684189}.Debug|Win32.Build.0 = Debug|Win32 - {255BDC68-B8DB-465F-8220-981E77684189}.Debug|x64.ActiveCfg = Debug|x64 - {255BDC68-B8DB-465F-8220-981E77684189}.Debug|x64.Build.0 = Debug|x64 - {255BDC68-B8DB-465F-8220-981E77684189}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {255BDC68-B8DB-465F-8220-981E77684189}.Release|Mixed Platforms.Build.0 = Release|Win32 - {255BDC68-B8DB-465F-8220-981E77684189}.Release|Win32.ActiveCfg = Release|Win32 - {255BDC68-B8DB-465F-8220-981E77684189}.Release|Win32.Build.0 = Release|Win32 + {255BDC68-B8DB-465F-8220-981E77684189}.Debug|Mixed Platforms.ActiveCfg = Release|x64 + {255BDC68-B8DB-465F-8220-981E77684189}.Debug|Mixed Platforms.Build.0 = Release|x64 + {255BDC68-B8DB-465F-8220-981E77684189}.Debug|Win32.ActiveCfg = Release|x64 + {255BDC68-B8DB-465F-8220-981E77684189}.Debug|Win32.Build.0 = Release|x64 + {255BDC68-B8DB-465F-8220-981E77684189}.Debug|x64.ActiveCfg = Release|x64 + {255BDC68-B8DB-465F-8220-981E77684189}.Debug|x64.Build.0 = Release|x64 + {255BDC68-B8DB-465F-8220-981E77684189}.Release|Mixed Platforms.ActiveCfg = Release|x64 + {255BDC68-B8DB-465F-8220-981E77684189}.Release|Mixed Platforms.Build.0 = Release|x64 + {255BDC68-B8DB-465F-8220-981E77684189}.Release|Win32.ActiveCfg = Release|x64 + {255BDC68-B8DB-465F-8220-981E77684189}.Release|Win32.Build.0 = Release|x64 {255BDC68-B8DB-465F-8220-981E77684189}.Release|x64.ActiveCfg = Release|x64 {255BDC68-B8DB-465F-8220-981E77684189}.Release|x64.Build.0 = Release|x64 - {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|Win32.ActiveCfg = Debug|Win32 - {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|Win32.Build.0 = Debug|Win32 - {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|x64.ActiveCfg = Debug|x64 - {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|Mixed Platforms.Build.0 = Release|Win32 - {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|Win32.ActiveCfg = Release|Win32 - {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|Win32.Build.0 = Release|Win32 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|Mixed Platforms.ActiveCfg = Release|x64 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|Mixed Platforms.Build.0 = Release|x64 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|Win32.ActiveCfg = Release|x64 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|Win32.Build.0 = Release|x64 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|x64.ActiveCfg = Release|x64 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|x64.Build.0 = Release|x64 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|Mixed Platforms.ActiveCfg = Release|x64 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|Mixed Platforms.Build.0 = Release|x64 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|Win32.ActiveCfg = Release|x64 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|Win32.Build.0 = Release|x64 {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|x64.ActiveCfg = Release|x64 - {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|Win32.ActiveCfg = Debug|Win32 - {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|Win32.Build.0 = Debug|Win32 - {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|x64.ActiveCfg = Debug|x64 - {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|x64.Build.0 = Debug|x64 - {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|Mixed Platforms.Build.0 = Release|Win32 - {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|Win32.ActiveCfg = Release|Win32 - {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|Win32.Build.0 = Release|Win32 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|x64.Build.0 = Release|x64 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|Mixed Platforms.ActiveCfg = Release|x64 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|Mixed Platforms.Build.0 = Release|x64 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|Win32.ActiveCfg = Release|x64 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|Win32.Build.0 = Release|x64 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|x64.ActiveCfg = Release|x64 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|x64.Build.0 = Release|x64 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|Mixed Platforms.ActiveCfg = Release|x64 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|Mixed Platforms.Build.0 = Release|x64 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|Win32.ActiveCfg = Release|x64 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|Win32.Build.0 = Release|x64 {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|x64.ActiveCfg = Release|x64 {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|x64.Build.0 = Release|x64 EndGlobalSection From fa494bc6a9005363f09249e5e83a654283836bca Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Wed, 22 Oct 2014 23:17:04 +0100 Subject: [PATCH 199/641] update some CMakeLists.txt --- eth/CMakeLists.txt | 5 +++++ exp/CMakeLists.txt | 4 ++++ neth/CMakeLists.txt | 4 ++++ 3 files changed, 13 insertions(+) diff --git a/eth/CMakeLists.txt b/eth/CMakeLists.txt index 087c5314a..274700ee7 100644 --- a/eth/CMakeLists.txt +++ b/eth/CMakeLists.txt @@ -14,6 +14,11 @@ add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) target_link_libraries(${EXECUTABLE} webthree) target_link_libraries(${EXECUTABLE} secp256k1) target_link_libraries(${EXECUTABLE} gmp) + +if(EVMCC) + target_link_libraries(${EXECUTABLE} evmjit) +endif() + if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() diff --git a/exp/CMakeLists.txt b/exp/CMakeLists.txt index da6775798..c671f240f 100644 --- a/exp/CMakeLists.txt +++ b/exp/CMakeLists.txt @@ -17,6 +17,10 @@ target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) +if(EVMCC) + target_link_libraries(${EXECUTABLE} evmjit) +endif() + if ("${TARGET_PLATFORM}" STREQUAL "w64") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") target_link_libraries(${EXECUTABLE} gcc) diff --git a/neth/CMakeLists.txt b/neth/CMakeLists.txt index 2b3f92947..184fc7104 100644 --- a/neth/CMakeLists.txt +++ b/neth/CMakeLists.txt @@ -24,6 +24,10 @@ if(JSONRPC_LS) target_link_libraries(${EXECUTABLE} ${JSONRPC_LS}) endif() +if(EVMCC) + target_link_libraries(${EXECUTABLE} evmjit) +endif() + if ("${TARGET_PLATFORM}" STREQUAL "w64") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") target_link_libraries(${EXECUTABLE} gcc) From 69b36f01f6ab2f8e0a4adb7994d8c3870d4a43f6 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Wed, 22 Oct 2014 23:17:48 +0100 Subject: [PATCH 200/641] added option to set initial gas --- evmcc/evmcc.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/evmcc/evmcc.cpp b/evmcc/evmcc.cpp index 3cd06d5a8..abaf3e511 100644 --- a/evmcc/evmcc.cpp +++ b/evmcc/evmcc.cpp @@ -25,7 +25,6 @@ void show_usage() int main(int argc, char** argv) { - std::string input_file; bool opt_dissassemble = false; bool opt_show_bytes = false; @@ -33,6 +32,7 @@ int main(int argc, char** argv) bool opt_interpret = false; bool opt_dump_graph = false; bool opt_unknown = false; + size_t initialGas = 10000; for (int i = 1; i < argc; i++) { @@ -47,6 +47,12 @@ int main(int argc, char** argv) opt_interpret = true; else if (option == "-g") opt_dump_graph = true; + else if (option == "-G" && i + 1 < argc) + { + std::string gasValue = argv[++i]; + initialGas = boost::lexical_cast(gasValue); + std::cerr << "Initial gas set to " << initialGas << "\n"; + } else if (option[0] != '-' && input_file.empty()) input_file = option; else @@ -109,7 +115,7 @@ int main(int argc, char** argv) if (opt_interpret) { auto engine = eth::jit::ExecutionEngine(); - u256 gas = 10000; + u256 gas = initialGas; auto result = engine.run(std::move(module), gas); return result; } From 77e18420db7dab4b85e4a42af36541726c83b9f4 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Wed, 22 Oct 2014 23:24:02 +0100 Subject: [PATCH 201/641] fixes for compiling libevm/VM.cpp with gcc --- libevm/VM.cpp | 2 +- libevm/VM.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libevm/VM.cpp b/libevm/VM.cpp index 4afd75659..4504fa302 100644 --- a/libevm/VM.cpp +++ b/libevm/VM.cpp @@ -25,7 +25,7 @@ using namespace dev; using namespace dev::eth; -void VM::reset(u256 _gas) +void VM::reset(u256 _gas) noexcept { VMFace::reset(_gas); m_curPC = 0; diff --git a/libevm/VM.h b/libevm/VM.h index 2ddf16bb6..344764d87 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -52,10 +52,11 @@ public: bytes const& memory() const { return m_temp; } u256s const& stack() const { return m_stack; } -private: friend VMFace; explicit VM(u256 _gas = 0): VMFace(_gas) {} +private: + template bytesConstRef go(Ext& _ext, OnOpFunc const& _onOp, uint64_t _steps); From 055097bc1f56f9f8f29fde0933c58727df2cef58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 23 Oct 2014 10:33:11 +0200 Subject: [PATCH 202/641] Add createRandomTest.cpp to TestEhereum Visual Studio project --- windows/TestEthereum.vcxproj | 1 + windows/TestEthereum.vcxproj.filters | 1 + 2 files changed, 2 insertions(+) diff --git a/windows/TestEthereum.vcxproj b/windows/TestEthereum.vcxproj index 277a38a3d..1ef821380 100644 --- a/windows/TestEthereum.vcxproj +++ b/windows/TestEthereum.vcxproj @@ -159,6 +159,7 @@ + diff --git a/windows/TestEthereum.vcxproj.filters b/windows/TestEthereum.vcxproj.filters index 4be707aec..f86265ab8 100644 --- a/windows/TestEthereum.vcxproj.filters +++ b/windows/TestEthereum.vcxproj.filters @@ -20,6 +20,7 @@ + From c4de0745e2eed27ef7c358a8eb8eff54c17a366d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 23 Oct 2014 12:37:48 +0200 Subject: [PATCH 203/641] Fix Visual Studio solution bad build configuration --- windows/Ethereum.sln | 168 +++++++++++++++++++++---------------------- 1 file changed, 84 insertions(+), 84 deletions(-) diff --git a/windows/Ethereum.sln b/windows/Ethereum.sln index df5916e63..4d2c7a3b4 100644 --- a/windows/Ethereum.sln +++ b/windows/Ethereum.sln @@ -59,86 +59,86 @@ Global GlobalSection(ProjectConfigurationPlatforms) = postSolution {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|Mixed Platforms.ActiveCfg = Release|x64 {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|Mixed Platforms.Build.0 = Release|x64 - {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|Win32.ActiveCfg = Release|x64 - {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|Win32.Build.0 = Release|x64 - {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|x64.ActiveCfg = Release|x64 - {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|x64.Build.0 = Release|x64 + {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|Win32.ActiveCfg = Debug|Win32 + {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|Win32.Build.0 = Debug|Win32 + {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|x64.ActiveCfg = Debug|x64 + {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|x64.Build.0 = Debug|x64 {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|Mixed Platforms.ActiveCfg = Release|x64 {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|Mixed Platforms.Build.0 = Release|x64 - {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|Win32.ActiveCfg = Release|x64 - {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|Win32.Build.0 = Release|x64 + {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|Win32.ActiveCfg = Release|Win32 + {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|Win32.Build.0 = Release|Win32 {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|x64.ActiveCfg = Release|x64 {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|x64.Build.0 = Release|x64 {27014763-955D-486B-9BA7-69872192E6F4}.Debug|Mixed Platforms.ActiveCfg = Release|x64 {27014763-955D-486B-9BA7-69872192E6F4}.Debug|Mixed Platforms.Build.0 = Release|x64 - {27014763-955D-486B-9BA7-69872192E6F4}.Debug|Win32.ActiveCfg = Release|x64 - {27014763-955D-486B-9BA7-69872192E6F4}.Debug|Win32.Build.0 = Release|x64 - {27014763-955D-486B-9BA7-69872192E6F4}.Debug|x64.ActiveCfg = Release|x64 - {27014763-955D-486B-9BA7-69872192E6F4}.Debug|x64.Build.0 = Release|x64 + {27014763-955D-486B-9BA7-69872192E6F4}.Debug|Win32.ActiveCfg = Debug|Win32 + {27014763-955D-486B-9BA7-69872192E6F4}.Debug|Win32.Build.0 = Debug|Win32 + {27014763-955D-486B-9BA7-69872192E6F4}.Debug|x64.ActiveCfg = Debug|x64 + {27014763-955D-486B-9BA7-69872192E6F4}.Debug|x64.Build.0 = Debug|x64 {27014763-955D-486B-9BA7-69872192E6F4}.Release|Mixed Platforms.ActiveCfg = Release|x64 {27014763-955D-486B-9BA7-69872192E6F4}.Release|Mixed Platforms.Build.0 = Release|x64 - {27014763-955D-486B-9BA7-69872192E6F4}.Release|Win32.ActiveCfg = Release|x64 - {27014763-955D-486B-9BA7-69872192E6F4}.Release|Win32.Build.0 = Release|x64 + {27014763-955D-486B-9BA7-69872192E6F4}.Release|Win32.ActiveCfg = Release|Win32 + {27014763-955D-486B-9BA7-69872192E6F4}.Release|Win32.Build.0 = Release|Win32 {27014763-955D-486B-9BA7-69872192E6F4}.Release|x64.ActiveCfg = Release|x64 {27014763-955D-486B-9BA7-69872192E6F4}.Release|x64.Build.0 = Release|x64 {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|Mixed Platforms.ActiveCfg = Release|x64 {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|Mixed Platforms.Build.0 = Release|x64 - {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|Win32.ActiveCfg = Release|x64 - {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|Win32.Build.0 = Release|x64 - {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|x64.ActiveCfg = Release|x64 - {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|x64.Build.0 = Release|x64 + {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|Win32.ActiveCfg = Debug|Win32 + {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|Win32.Build.0 = Debug|Win32 + {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|x64.ActiveCfg = Debug|x64 + {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|x64.Build.0 = Debug|x64 {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|Mixed Platforms.ActiveCfg = Release|x64 {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|Mixed Platforms.Build.0 = Release|x64 - {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|Win32.ActiveCfg = Release|x64 - {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|Win32.Build.0 = Release|x64 + {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|Win32.ActiveCfg = Release|Win32 + {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|Win32.Build.0 = Release|Win32 {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|x64.ActiveCfg = Release|x64 {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|x64.Build.0 = Release|x64 {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|Mixed Platforms.ActiveCfg = Release|x64 {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|Mixed Platforms.Build.0 = Release|x64 - {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|Win32.ActiveCfg = Release|x64 - {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|Win32.Build.0 = Release|x64 - {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|x64.ActiveCfg = Release|x64 - {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|x64.Build.0 = Release|x64 + {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|Win32.ActiveCfg = Debug|Win32 + {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|Win32.Build.0 = Debug|Win32 + {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|x64.ActiveCfg = Debug|x64 + {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|x64.Build.0 = Debug|x64 {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|Mixed Platforms.ActiveCfg = Release|x64 {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|Mixed Platforms.Build.0 = Release|x64 - {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|Win32.ActiveCfg = Release|x64 - {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|Win32.Build.0 = Release|x64 + {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|Win32.ActiveCfg = Release|Win32 + {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|Win32.Build.0 = Release|Win32 {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|x64.ActiveCfg = Release|x64 {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|x64.Build.0 = Release|x64 {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|Mixed Platforms.ActiveCfg = Release|x64 {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|Mixed Platforms.Build.0 = Release|x64 - {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|Win32.ActiveCfg = Release|x64 - {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|Win32.Build.0 = Release|x64 - {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|x64.ActiveCfg = Release|x64 - {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|x64.Build.0 = Release|x64 + {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|Win32.ActiveCfg = Debug|Win32 + {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|Win32.Build.0 = Debug|Win32 + {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|x64.ActiveCfg = Debug|x64 + {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|x64.Build.0 = Debug|x64 {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|Mixed Platforms.ActiveCfg = Release|x64 {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|Mixed Platforms.Build.0 = Release|x64 - {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|Win32.ActiveCfg = Release|x64 - {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|Win32.Build.0 = Release|x64 + {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|Win32.ActiveCfg = Release|Win32 + {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|Win32.Build.0 = Release|Win32 {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|x64.ActiveCfg = Release|x64 {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|x64.Build.0 = Release|x64 {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|Mixed Platforms.ActiveCfg = Release|x64 {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|Mixed Platforms.Build.0 = Release|x64 - {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|Win32.ActiveCfg = Release|x64 - {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|Win32.Build.0 = Release|x64 - {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|x64.ActiveCfg = Release|x64 - {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|x64.Build.0 = Release|x64 + {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|Win32.ActiveCfg = Debug|Win32 + {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|Win32.Build.0 = Debug|Win32 + {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|x64.ActiveCfg = Debug|x64 + {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|x64.Build.0 = Debug|x64 {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|Mixed Platforms.ActiveCfg = Release|x64 {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|Mixed Platforms.Build.0 = Release|x64 - {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|Win32.ActiveCfg = Release|x64 - {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|Win32.Build.0 = Release|x64 + {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|Win32.ActiveCfg = Release|Win32 + {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|Win32.Build.0 = Release|Win32 {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|x64.ActiveCfg = Release|x64 {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|x64.Build.0 = Release|x64 {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|Mixed Platforms.ActiveCfg = Release|x64 {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|Mixed Platforms.Build.0 = Release|x64 - {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|Win32.ActiveCfg = Release|x64 - {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|Win32.Build.0 = Release|x64 - {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|x64.ActiveCfg = Release|x64 - {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|x64.Build.0 = Release|x64 + {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|Win32.ActiveCfg = Debug|Win32 + {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|Win32.Build.0 = Debug|Win32 + {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|x64.ActiveCfg = Debug|x64 + {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|x64.Build.0 = Debug|x64 {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|Mixed Platforms.ActiveCfg = Release|x64 {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|Mixed Platforms.Build.0 = Release|x64 - {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|Win32.ActiveCfg = Release|x64 - {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|Win32.Build.0 = Release|x64 + {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|Win32.ActiveCfg = Release|Win32 + {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|Win32.Build.0 = Release|Win32 {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|x64.ActiveCfg = Release|x64 {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|x64.Build.0 = Release|x64 {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 @@ -163,14 +163,14 @@ Global {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Release|x64.Build.0 = Release|x64 {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|Mixed Platforms.ActiveCfg = Release|x64 {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|Mixed Platforms.Build.0 = Release|x64 - {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|Win32.ActiveCfg = Release|x64 - {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|Win32.Build.0 = Release|x64 - {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|x64.ActiveCfg = Release|x64 - {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|x64.Build.0 = Release|x64 + {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|Win32.ActiveCfg = Debug|Win32 + {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|Win32.Build.0 = Debug|Win32 + {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|x64.ActiveCfg = Debug|x64 + {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|x64.Build.0 = Debug|x64 {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|Mixed Platforms.ActiveCfg = Release|x64 {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|Mixed Platforms.Build.0 = Release|x64 - {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|Win32.ActiveCfg = Release|x64 - {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|Win32.Build.0 = Release|x64 + {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|Win32.ActiveCfg = Release|Win32 + {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|Win32.Build.0 = Release|Win32 {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|x64.ActiveCfg = Release|x64 {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|x64.Build.0 = Release|x64 {90C70663-7181-4E99-9079-54188CEB8954}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 @@ -187,74 +187,74 @@ Global {90C70663-7181-4E99-9079-54188CEB8954}.Release|x64.Build.0 = Release|x64 {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|Mixed Platforms.ActiveCfg = Release|x64 {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|Mixed Platforms.Build.0 = Release|x64 - {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|Win32.ActiveCfg = Release|x64 - {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|Win32.Build.0 = Release|x64 - {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|x64.ActiveCfg = Release|x64 - {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|x64.Build.0 = Release|x64 + {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|Win32.ActiveCfg = Debug|Win32 + {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|Win32.Build.0 = Debug|Win32 + {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|x64.ActiveCfg = Debug|x64 + {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|x64.Build.0 = Debug|x64 {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|Mixed Platforms.ActiveCfg = Release|x64 {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|Mixed Platforms.Build.0 = Release|x64 - {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|Win32.ActiveCfg = Release|x64 - {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|Win32.Build.0 = Release|x64 + {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|Win32.ActiveCfg = Release|Win32 + {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|Win32.Build.0 = Release|Win32 {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|x64.ActiveCfg = Release|x64 {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|x64.Build.0 = Release|x64 {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|Mixed Platforms.ActiveCfg = Release|x64 {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|Mixed Platforms.Build.0 = Release|x64 - {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|Win32.ActiveCfg = Release|x64 - {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|Win32.Build.0 = Release|x64 - {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|x64.ActiveCfg = Release|x64 - {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|x64.Build.0 = Release|x64 + {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|Win32.ActiveCfg = Debug|Win32 + {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|Win32.Build.0 = Debug|Win32 + {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|x64.ActiveCfg = Debug|x64 + {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|x64.Build.0 = Debug|x64 {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|Mixed Platforms.ActiveCfg = Release|x64 {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|Mixed Platforms.Build.0 = Release|x64 - {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|Win32.ActiveCfg = Release|x64 - {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|Win32.Build.0 = Release|x64 + {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|Win32.ActiveCfg = Release|Win32 + {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|Win32.Build.0 = Release|Win32 {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|x64.ActiveCfg = Release|x64 {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|x64.Build.0 = Release|x64 {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|Mixed Platforms.ActiveCfg = Release|x64 {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|Mixed Platforms.Build.0 = Release|x64 - {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|Win32.ActiveCfg = Release|x64 - {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|Win32.Build.0 = Release|x64 - {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|x64.ActiveCfg = Release|x64 - {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|x64.Build.0 = Release|x64 + {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|Win32.ActiveCfg = Debug|Win32 + {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|Win32.Build.0 = Debug|Win32 + {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|x64.ActiveCfg = Debug|x64 + {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|x64.Build.0 = Debug|x64 {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|Mixed Platforms.ActiveCfg = Release|x64 {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|Mixed Platforms.Build.0 = Release|x64 - {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|Win32.ActiveCfg = Release|x64 - {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|Win32.Build.0 = Release|x64 + {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|Win32.ActiveCfg = Release|Win32 + {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|Win32.Build.0 = Release|Win32 {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|x64.ActiveCfg = Release|x64 {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|x64.Build.0 = Release|x64 {255BDC68-B8DB-465F-8220-981E77684189}.Debug|Mixed Platforms.ActiveCfg = Release|x64 {255BDC68-B8DB-465F-8220-981E77684189}.Debug|Mixed Platforms.Build.0 = Release|x64 - {255BDC68-B8DB-465F-8220-981E77684189}.Debug|Win32.ActiveCfg = Release|x64 - {255BDC68-B8DB-465F-8220-981E77684189}.Debug|Win32.Build.0 = Release|x64 - {255BDC68-B8DB-465F-8220-981E77684189}.Debug|x64.ActiveCfg = Release|x64 - {255BDC68-B8DB-465F-8220-981E77684189}.Debug|x64.Build.0 = Release|x64 + {255BDC68-B8DB-465F-8220-981E77684189}.Debug|Win32.ActiveCfg = Debug|Win32 + {255BDC68-B8DB-465F-8220-981E77684189}.Debug|Win32.Build.0 = Debug|Win32 + {255BDC68-B8DB-465F-8220-981E77684189}.Debug|x64.ActiveCfg = Debug|x64 + {255BDC68-B8DB-465F-8220-981E77684189}.Debug|x64.Build.0 = Debug|x64 {255BDC68-B8DB-465F-8220-981E77684189}.Release|Mixed Platforms.ActiveCfg = Release|x64 {255BDC68-B8DB-465F-8220-981E77684189}.Release|Mixed Platforms.Build.0 = Release|x64 - {255BDC68-B8DB-465F-8220-981E77684189}.Release|Win32.ActiveCfg = Release|x64 - {255BDC68-B8DB-465F-8220-981E77684189}.Release|Win32.Build.0 = Release|x64 + {255BDC68-B8DB-465F-8220-981E77684189}.Release|Win32.ActiveCfg = Release|Win32 + {255BDC68-B8DB-465F-8220-981E77684189}.Release|Win32.Build.0 = Release|Win32 {255BDC68-B8DB-465F-8220-981E77684189}.Release|x64.ActiveCfg = Release|x64 {255BDC68-B8DB-465F-8220-981E77684189}.Release|x64.Build.0 = Release|x64 {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|Mixed Platforms.ActiveCfg = Release|x64 {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|Mixed Platforms.Build.0 = Release|x64 - {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|Win32.ActiveCfg = Release|x64 - {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|Win32.Build.0 = Release|x64 - {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|x64.ActiveCfg = Release|x64 - {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|x64.Build.0 = Release|x64 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|Win32.ActiveCfg = Debug|Win32 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|Win32.Build.0 = Debug|Win32 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|x64.ActiveCfg = Debug|x64 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|x64.Build.0 = Debug|x64 {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|Mixed Platforms.ActiveCfg = Release|x64 {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|Mixed Platforms.Build.0 = Release|x64 - {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|Win32.ActiveCfg = Release|x64 - {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|Win32.Build.0 = Release|x64 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|Win32.ActiveCfg = Release|Win32 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|Win32.Build.0 = Release|Win32 {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|x64.ActiveCfg = Release|x64 {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|x64.Build.0 = Release|x64 {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|Mixed Platforms.ActiveCfg = Release|x64 {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|Mixed Platforms.Build.0 = Release|x64 - {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|Win32.ActiveCfg = Release|x64 - {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|Win32.Build.0 = Release|x64 - {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|x64.ActiveCfg = Release|x64 - {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|x64.Build.0 = Release|x64 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|Win32.ActiveCfg = Debug|Win32 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|Win32.Build.0 = Debug|Win32 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|x64.ActiveCfg = Debug|x64 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|x64.Build.0 = Debug|x64 {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|Mixed Platforms.ActiveCfg = Release|x64 {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|Mixed Platforms.Build.0 = Release|x64 - {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|Win32.ActiveCfg = Release|x64 - {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|Win32.Build.0 = Release|x64 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|Win32.ActiveCfg = Release|Win32 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|Win32.Build.0 = Release|Win32 {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|x64.ActiveCfg = Release|x64 {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|x64.Build.0 = Release|x64 EndGlobalSection From eb347cb24c5e9151758bc157e7638cdd13117789 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 23 Oct 2014 12:38:45 +0200 Subject: [PATCH 204/641] Update createRandomTest.cpp to use new VM construction method --- libevm/VM.h | 3 +-- test/createRandomTest.cpp | 4 +++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libevm/VM.h b/libevm/VM.h index 344764d87..2ddf16bb6 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -52,11 +52,10 @@ public: bytes const& memory() const { return m_temp; } u256s const& stack() const { return m_stack; } +private: friend VMFace; explicit VM(u256 _gas = 0): VMFace(_gas) {} -private: - template bytesConstRef go(Ext& _ext, OnOpFunc const& _onOp, uint64_t _steps); diff --git a/test/createRandomTest.cpp b/test/createRandomTest.cpp index 874869a5c..dbe50851a 100644 --- a/test/createRandomTest.cpp +++ b/test/createRandomTest.cpp @@ -97,7 +97,9 @@ void doMyTests(json_spirit::mValue& v) assert(o.count("pre") > 0); assert(o.count("exec") > 0); - eth::VM vm; + + auto vmObj = eth::VMFace::create(eth::VMFace::Interpreter); + auto& vm = *vmObj; test::FakeExtVM fev; fev.importEnv(o["env"].get_obj()); fev.importState(o["pre"].get_obj()); From 0a14243ca1f38cc8558457296b6bcea6daea1355 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 23 Oct 2014 12:39:20 +0200 Subject: [PATCH 205/641] Change directory separator in LLVM.props (Visual Studio) --- windows/LLVM.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/windows/LLVM.props b/windows/LLVM.props index 42be9a170..a5c6c4dc5 100644 --- a/windows/LLVM.props +++ b/windows/LLVM.props @@ -3,8 +3,8 @@ 1 - ..\..\llvm - ..\..\_build\llvm\$(Platform) + ../../llvm + ../../_build/llvm/$(Platform) $(LLVMSrcDir)\include;$(LLVMBuildDir)\include $(LLVMBuildDir)\$(Configuration)\lib LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib From 4d601dc9554f75c45a0a335edf920abcda31e954 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 23 Oct 2014 12:40:18 +0200 Subject: [PATCH 206/641] Remove createRandomTest.cpp from TestEthereum project (Visual Studio) --- windows/TestEthereum.vcxproj | 2 -- windows/TestEthereum.vcxproj.filters | 1 - 2 files changed, 3 deletions(-) diff --git a/windows/TestEthereum.vcxproj b/windows/TestEthereum.vcxproj index 1ef821380..557a899b3 100644 --- a/windows/TestEthereum.vcxproj +++ b/windows/TestEthereum.vcxproj @@ -111,7 +111,6 @@ Console true - ../../builds/llvm3.5/Debug/lib;../../_build/LibEvmJit/x64_Debug;../../_build/LibEthereum/x64_Debug;../../_build/LibSecp256k1/x64_Debug;../../_build/LibCryptoPP/x64_Debug;%(AdditionalLibraryDirectories) @@ -159,7 +158,6 @@ - diff --git a/windows/TestEthereum.vcxproj.filters b/windows/TestEthereum.vcxproj.filters index f86265ab8..4be707aec 100644 --- a/windows/TestEthereum.vcxproj.filters +++ b/windows/TestEthereum.vcxproj.filters @@ -20,7 +20,6 @@ - From b2f0fddeadeab9f0dcdcc6de858cfe56ac91b5d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 23 Oct 2014 14:37:01 +0200 Subject: [PATCH 207/641] Add vm.h file to TestEthereum project (Visual Studio) --- windows/TestEthereum.vcxproj | 1 + windows/TestEthereum.vcxproj.filters | 1 + 2 files changed, 2 insertions(+) diff --git a/windows/TestEthereum.vcxproj b/windows/TestEthereum.vcxproj index 557a899b3..94667fa16 100644 --- a/windows/TestEthereum.vcxproj +++ b/windows/TestEthereum.vcxproj @@ -185,6 +185,7 @@ + diff --git a/windows/TestEthereum.vcxproj.filters b/windows/TestEthereum.vcxproj.filters index 4be707aec..bd2253c5e 100644 --- a/windows/TestEthereum.vcxproj.filters +++ b/windows/TestEthereum.vcxproj.filters @@ -34,5 +34,6 @@ + \ No newline at end of file From 7aa2b25220dc2fa7c56bcf41310759344eafe5fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 23 Oct 2014 15:27:18 +0200 Subject: [PATCH 208/641] Add option to set VM kind in State. Interpreter by default. --- libethereum/State.cpp | 12 +++++++----- libethereum/State.h | 9 +++++++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/libethereum/State.cpp b/libethereum/State.cpp index b51224e32..3099530b2 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -166,7 +166,8 @@ State::State(State const& _s): m_previousBlock(_s.m_previousBlock), m_currentBlock(_s.m_currentBlock), m_ourAddress(_s.m_ourAddress), - m_blockReward(_s.m_blockReward) + m_blockReward(_s.m_blockReward), + m_vmKind(_s.m_vmKind) { paranoia("after state cloning (copy cons).", true); } @@ -199,6 +200,7 @@ State& State::operator=(State const& _s) m_ourAddress = _s.m_ourAddress; m_blockReward = _s.m_blockReward; m_lastTx = _s.m_lastTx; + m_vmKind = _s.m_vmKind; paranoia("after state cloning (assignment op)", true); return *this; } @@ -1146,8 +1148,8 @@ bool State::call(Address _receiveAddress, Address _codeAddress, Address _senderA } else if (addressHasCode(_codeAddress)) { - auto vmObj = VMFace::create(VMFace::Interpreter, *_gas); - VMFace& vm = *vmObj; + auto vmObj = VMFace::create(getVMKind(), *_gas); + auto& vm = *vmObj; ExtVM evm(*this, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &code(_codeAddress), o_ms, _level); bool revert = false; @@ -1209,8 +1211,8 @@ h160 State::create(Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas, m_cache[newAddress] = AddressState(0, balance(newAddress) + _endowment, h256(), h256()); // Execute init code. - auto vmObj = VMFace::create(VMFace::Interpreter, *_gas); - VMFace& vm = *vmObj; + auto vmObj = VMFace::create(getVMKind(), *_gas); + auto& vm = *vmObj; ExtVM evm(*this, newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _code, o_ms, _level); bool revert = false; bytesConstRef out; diff --git a/libethereum/State.h b/libethereum/State.h index dd6043c73..a3641a3cb 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -32,6 +32,7 @@ #include #include #include +#include #include "TransactionQueue.h" #include "AddressState.h" #include "Transaction.h" @@ -264,6 +265,12 @@ public: /// the block since all state changes are ultimately reversed. void cleanup(bool _fullCommit); + /// Sets VM kind to be used by the state + void setVMKind(VMFace::Kind _kind) { m_vmKind = _kind; } + + /// Get the kind of VM used by the state + VMFace::Kind getVMKind() const { return m_vmKind; } + private: /// Undo the changes to the state for committing to mine. void uncommitToMine(); @@ -330,6 +337,8 @@ private: u256 m_blockReward; + VMFace::Kind m_vmKind = VMFace::Interpreter; ///< The kind of VM used by the state + static std::string c_defaultPath; static const std::map c_precompiled; From 2d0557e2ee236b73546d6dd9f3ed7d19ec852a0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 23 Oct 2014 15:28:08 +0200 Subject: [PATCH 209/641] Expose VM kind setting of State in FakeExtVM --- test/vm.cpp | 19 ++++++++++--------- test/vm.h | 2 ++ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/test/vm.cpp b/test/vm.cpp index d62329af4..d68a30c6b 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -436,8 +436,8 @@ h160 FakeState::createNewAddress(Address _newAddress, Address _sender, u256 _end m_cache[_newAddress] = AddressState(0, balance(_newAddress) + _endowment, h256(), h256()); // Execute init code. - auto vmObj = VMFace::create(VMFace::Interpreter, *_gas); - VMFace& vm = *vmObj; + auto vmObj = VMFace::create(getVMKind(), *_gas); + auto& vm = *vmObj; ExtVM evm(*this, _newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _code, o_ms, _level); bool revert = false; bytesConstRef out; @@ -499,7 +499,14 @@ void doTests(json_spirit::mValue& v, bool _fillin) BOOST_REQUIRE(o.count("pre") > 0); BOOST_REQUIRE(o.count("exec") > 0); + auto argc = boost::unit_test::framework::master_test_suite().argc; + auto argv = boost::unit_test::framework::master_test_suite().argv; + auto useJit = argc >= 2 && std::string(argv[1]) == "--jit"; + auto vmKind = useJit ? VMFace::JIT : VMFace::Interpreter; + dev::test::FakeExtVM fev; + fev.setVMKind(vmKind); + fev.importEnv(o["env"].get_obj()); fev.importState(o["pre"].get_obj()); @@ -512,14 +519,8 @@ void doTests(json_spirit::mValue& v, bool _fillin) fev.thisTxCode = get<3>(fev.addresses.at(fev.myAddress)); fev.code = &fev.thisTxCode; } - - - auto argc = boost::unit_test::framework::master_test_suite().argc; - auto argv = boost::unit_test::framework::master_test_suite().argv; - auto useJit = argc >= 2 && std::string(argv[1]) == "--jit"; - auto vmKind = useJit ? VMFace::JIT : VMFace::Interpreter; - auto vm = VMFace::create(vmKind, fev.gas); + auto vm = VMFace::create(fev.getVMKind(), fev.gas); bytes output; auto outOfGas = false; try diff --git a/test/vm.h b/test/vm.h index a9897bee3..2069cad3d 100644 --- a/test/vm.h +++ b/test/vm.h @@ -79,6 +79,8 @@ public: void importExec(json_spirit::mObject& _o); json_spirit::mArray exportCallCreates(); void importCallCreates(json_spirit::mArray& _callcreates); + void setVMKind(eth::VMFace::Kind _kind) { m_s.setVMKind(_kind); } + eth::VMFace::Kind getVMKind() const { return m_s.getVMKind(); } std::map, bytes>> addresses; eth::Transactions callcreates; From 6ad065bb3e30b5e67283f70e84ac55368e843e6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 23 Oct 2014 15:49:12 +0200 Subject: [PATCH 210/641] Revert "Expose VM kind setting of State in FakeExtVM" This reverts commit 2d0557e2ee236b73546d6dd9f3ed7d19ec852a0f. --- test/vm.cpp | 19 +++++++++---------- test/vm.h | 2 -- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/test/vm.cpp b/test/vm.cpp index d68a30c6b..d62329af4 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -436,8 +436,8 @@ h160 FakeState::createNewAddress(Address _newAddress, Address _sender, u256 _end m_cache[_newAddress] = AddressState(0, balance(_newAddress) + _endowment, h256(), h256()); // Execute init code. - auto vmObj = VMFace::create(getVMKind(), *_gas); - auto& vm = *vmObj; + auto vmObj = VMFace::create(VMFace::Interpreter, *_gas); + VMFace& vm = *vmObj; ExtVM evm(*this, _newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _code, o_ms, _level); bool revert = false; bytesConstRef out; @@ -499,14 +499,7 @@ void doTests(json_spirit::mValue& v, bool _fillin) BOOST_REQUIRE(o.count("pre") > 0); BOOST_REQUIRE(o.count("exec") > 0); - auto argc = boost::unit_test::framework::master_test_suite().argc; - auto argv = boost::unit_test::framework::master_test_suite().argv; - auto useJit = argc >= 2 && std::string(argv[1]) == "--jit"; - auto vmKind = useJit ? VMFace::JIT : VMFace::Interpreter; - dev::test::FakeExtVM fev; - fev.setVMKind(vmKind); - fev.importEnv(o["env"].get_obj()); fev.importState(o["pre"].get_obj()); @@ -519,8 +512,14 @@ void doTests(json_spirit::mValue& v, bool _fillin) fev.thisTxCode = get<3>(fev.addresses.at(fev.myAddress)); fev.code = &fev.thisTxCode; } + + + auto argc = boost::unit_test::framework::master_test_suite().argc; + auto argv = boost::unit_test::framework::master_test_suite().argv; + auto useJit = argc >= 2 && std::string(argv[1]) == "--jit"; - auto vm = VMFace::create(fev.getVMKind(), fev.gas); + auto vmKind = useJit ? VMFace::JIT : VMFace::Interpreter; + auto vm = VMFace::create(vmKind, fev.gas); bytes output; auto outOfGas = false; try diff --git a/test/vm.h b/test/vm.h index 2069cad3d..a9897bee3 100644 --- a/test/vm.h +++ b/test/vm.h @@ -79,8 +79,6 @@ public: void importExec(json_spirit::mObject& _o); json_spirit::mArray exportCallCreates(); void importCallCreates(json_spirit::mArray& _callcreates); - void setVMKind(eth::VMFace::Kind _kind) { m_s.setVMKind(_kind); } - eth::VMFace::Kind getVMKind() const { return m_s.getVMKind(); } std::map, bytes>> addresses; eth::Transactions callcreates; From cdb49404ddb7237f7b705d4c3ccf16a646e6eae6 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Thu, 23 Oct 2014 23:56:56 +0100 Subject: [PATCH 211/641] Refactored local stack [#81180320] --- libevmjit/BasicBlock.cpp | 201 +++++++++++++++++++++++++++++----- libevmjit/BasicBlock.h | 70 ++++++++---- libevmjit/Compiler.cpp | 66 +++++++---- libevmjit/Compiler.h | 2 +- libevmjit/ExecutionEngine.cpp | 5 +- libevmjit/Stack.cpp | 65 ++++++++--- libevmjit/Stack.h | 12 +- libevmjit/Type.cpp | 3 + libevmjit/Type.h | 2 + 9 files changed, 342 insertions(+), 84 deletions(-) diff --git a/libevmjit/BasicBlock.cpp b/libevmjit/BasicBlock.cpp index 2c5ea7285..13d66140f 100644 --- a/libevmjit/BasicBlock.cpp +++ b/libevmjit/BasicBlock.cpp @@ -1,8 +1,11 @@ #include "BasicBlock.h" +#include + #include #include +#include #include "Type.h" @@ -15,65 +18,211 @@ namespace jit const char* BasicBlock::NamePrefix = "Instr."; -BasicBlock::BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx, llvm::Function* _mainFunc) : +BasicBlock::BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder) : m_beginInstIdx(_beginInstIdx), m_endInstIdx(_endInstIdx), m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {NamePrefix, std::to_string(_beginInstIdx)}, _mainFunc)), - m_stack(m_llvmBB) + m_stack(_builder) {} -BasicBlock::BasicBlock(std::string _name, llvm::Function* _mainFunc) : +BasicBlock::BasicBlock(std::string _name, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder) : m_beginInstIdx(0), m_endInstIdx(0), m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), _name, _mainFunc)), - m_stack(m_llvmBB) + m_stack(_builder) {} +BasicBlock::LocalStack::LocalStack(llvm::IRBuilder<>& _builder) : + m_builder(_builder), + m_initialStack(), + m_currentStack(), + m_tosOffset(0) +{} void BasicBlock::LocalStack::push(llvm::Value* _value) { - assert(_value->getType() == Type::i256); - m_backend.push_back(_value); + m_currentStack.push_back(_value); + m_tosOffset += 1; } llvm::Value* BasicBlock::LocalStack::pop() { - auto top = get(0); - m_backend.pop_back(); - return top; + auto result = get(0); + + if (m_currentStack.size() > 0) + m_currentStack.pop_back(); + + m_tosOffset -= 1; + return result; +} + +/** + * Pushes a copy of _index-th element (tos is 0-th elem). + */ +void BasicBlock::LocalStack::dup(size_t _index) +{ + auto val = get(_index); + push(val); +} + +/** + * Swaps tos with _index-th element (tos is 0-th elem). + * _index must be > 0. + */ +void BasicBlock::LocalStack::swap(size_t _index) +{ + assert(_index > 0); + auto val = get(_index); + auto tos = get(0); + set(_index, tos); + set(0, val); +} + +void BasicBlock::LocalStack::synchronize(Stack& _evmStack) +{ + auto blockTerminator = m_builder.GetInsertBlock()->getTerminator(); + assert(blockTerminator != nullptr); + m_builder.SetInsertPoint(blockTerminator); + + auto currIter = m_currentStack.begin(); + auto endIter = m_currentStack.end(); + + // Update (emit set()) changed values + for (int idx = m_currentStack.size() - 1 - m_tosOffset; + currIter < endIter && idx >= 0; + ++currIter, --idx) + { + assert(static_cast(idx) < m_initialStack.size()); + if (*currIter != m_initialStack[idx]) // value needs update + _evmStack.set(static_cast(idx), *currIter); + } + + if (m_tosOffset < 0) + { + // Pop values + _evmStack.pop(static_cast(-m_tosOffset)); + } + + // Push new values + for ( ; currIter < endIter; ++currIter) + { + assert(*currIter != nullptr); + _evmStack.push(*currIter); + } + + // Emit get() for all (used) values from the initial stack + for (size_t idx = 0; idx < m_initialStack.size(); ++idx) + { + auto val = m_initialStack[idx]; + 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); + } + phi->eraseFromParent(); + } + + // Reset the stack + m_initialStack.erase(m_initialStack.begin(), m_initialStack.end()); + m_currentStack.erase(m_currentStack.begin(), m_currentStack.end()); + m_tosOffset = 0; +} + +std::vector::iterator BasicBlock::LocalStack::getItemIterator(size_t _index) +{ + if (_index < m_currentStack.size()) + return m_currentStack.end() - _index - 1; + + // Need to map more elements from the EVM stack + auto nNewItems = 1 + _index - m_currentStack.size(); + m_currentStack.insert(m_currentStack.begin(), nNewItems, nullptr); + + return m_currentStack.end() - _index - 1; } llvm::Value* BasicBlock::LocalStack::get(size_t _index) -{ - if (_index >= m_backend.size()) +{ + auto itemIter = getItemIterator(_index); + + if (*itemIter == nullptr) { - // Create PHI node for missing values - auto nMissingVals = _index - m_backend.size() + 1; - m_backend.insert(m_backend.begin(), nMissingVals, nullptr); - for (decltype(nMissingVals) i = 0; i < nMissingVals; ++i) + // Need to fetch a new item from the EVM stack + assert(static_cast(_index) >= m_tosOffset); + size_t initialIdx = _index - m_tosOffset; + if (initialIdx >= m_initialStack.size()) { - m_backend[nMissingVals - 1 - i] = m_llvmBB->empty() ? - llvm::PHINode::Create(Type::i256, 0, {}, m_llvmBB) : - llvm::PHINode::Create(Type::i256, 0, {}, m_llvmBB->getFirstNonPHI()); - m_numRequiredStackItems += 1; + auto nNewItems = 1 + initialIdx - m_initialStack.size(); + m_initialStack.insert(m_initialStack.end(), nNewItems, nullptr); } + + assert(m_initialStack[initialIdx] == nullptr); + // Create a dummy value. + std::string name = "get_" + boost::lexical_cast(_index); + m_initialStack[initialIdx] = m_builder.CreatePHI(Type::i256, 0, name); + *itemIter = m_initialStack[initialIdx]; } - return *(m_backend.rbegin() + _index); + return *itemIter; } -void BasicBlock::LocalStack::dup(size_t _index) +void BasicBlock::LocalStack::set(size_t _index, llvm::Value* _word) { - m_backend.push_back(get(_index)); + auto itemIter = getItemIterator(_index); + *itemIter = _word; } -void BasicBlock::LocalStack::swap(size_t _index) + +void BasicBlock::dump() { - assert(_index != 0); - get(_index); // Create PHI nodes - std::swap(*m_backend.rbegin(), *(m_backend.rbegin() + _index)); + std::cerr << "Initial stack:\n"; + for (auto val : m_stack.m_initialStack) + { + if (val == nullptr) + std::cerr << " ?\n"; + else if (llvm::isa(val)) + val->dump(); + else + { + std::cerr << " "; + val->dump(); + } + } + std::cerr << " ...\n"; + + std::cerr << "Instructions:\n"; + for (auto ins = m_llvmBB->begin(); ins != m_llvmBB->end(); ++ins) + ins->dump(); + + std::cerr << "Current stack (offset = " + << m_stack.m_tosOffset << "):\n"; + + for (auto val = m_stack.m_currentStack.rbegin(); val != m_stack.m_currentStack.rend(); ++val) + { + if (*val == nullptr) + std::cerr << " ?\n"; + else if (llvm::isa(*val)) + (*val)->dump(); + else + { + std::cerr << " "; + (*val)->dump(); + } + + } + std::cerr << " ...\n----------------------------------------\n"; } + + + } } } diff --git a/libevmjit/BasicBlock.h b/libevmjit/BasicBlock.h index 51a48c6e0..2723cf919 100644 --- a/libevmjit/BasicBlock.h +++ b/libevmjit/BasicBlock.h @@ -1,8 +1,11 @@ +#pragma once #include #include +#include "Stack.h" + namespace dev { namespace eth @@ -18,49 +21,72 @@ public: class LocalStack { public: + /// Pushes value on stack void push(llvm::Value* _value); /// Pops and returns top value llvm::Value* pop(); - /// Gets _index'th value from top (counting from 0) - llvm::Value* get(size_t _index); - - /// Duplicates _index'th value on stack. + /// Duplicates _index'th value on stack void dup(size_t _index); /// Swaps _index'th value on stack with a value on stack top. - /// @param _index Index of value to be swaped. Cannot be 0. + /// @param _index Index of value to be swaped. Must be > 0. void swap(size_t _index); - /// Size of the stack - size_t size() const { return m_backend.size(); } - - size_t initialSize() const { return m_numRequiredStackItems; } + /// Synchronize current local stack with the EVM stack. + void synchronize(Stack& _evmStack); private: - // LocalStack(llvm::BasicBlock* _llvmBB) : m_llvmBB(_llvmBB) {} - LocalStack(llvm::BasicBlock* _llvmBB) : m_llvmBB(_llvmBB), m_numRequiredStackItems(0) {} + + LocalStack(llvm::IRBuilder<>& _builder); LocalStack(LocalStack const&) = delete; void operator=(LocalStack const&) = delete; friend BasicBlock; + /// Gets _index'th value from top (counting from 0) + llvm::Value* get(size_t _index); + + /// Sets _index'th value from top (counting from 0) + void set(size_t _index, llvm::Value* _value); + + std::vector::iterator getItemIterator(size_t _index); + private: - std::vector m_backend; - /** Basic block into which phi nodes are inserted */ - llvm::BasicBlock* m_llvmBB; + llvm::IRBuilder<>& m_builder; + + /** + * This stack contains LLVM values that correspond to items found at + * the EVM stack when the current basic block starts executing. + * Location 0 corresponds to the top of the EVM stack, location 1 is + * the item below the top and so on. The stack grows as the code + * accesses more items on the EVM stack but once a value is put on + * the stack, it will never be replaced. + */ + std::vector m_initialStack; + + /** + * This stack tracks the contents of the EVM stack as the current basic + * block executes. It may grow on both sides, as the code pushes items on + * top of the stack or changes existing items. + */ + std::vector m_currentStack; + + /** + * How many items higher is the current stack than the initial one. + * May be negative. + */ + int m_tosOffset; - /** Number of items required on the EVM stack at the beginning of the block */ - size_t m_numRequiredStackItems; }; /// Basic block name prefix. The rest is beging instruction index. static const char* NamePrefix; - explicit BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx, llvm::Function* _mainFunc); - explicit BasicBlock(std::string _name, llvm::Function* _mainFunc); + explicit BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder); + explicit BasicBlock(std::string _name, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder); BasicBlock(const BasicBlock&) = delete; void operator=(const BasicBlock&) = delete; @@ -68,11 +94,15 @@ public: operator llvm::BasicBlock*() { return m_llvmBB; } llvm::BasicBlock* llvm() { return m_llvmBB; } - LocalStack& getStack() { return m_stack; } - ProgramCounter begin() { return m_beginInstIdx; } ProgramCounter end() { return m_endInstIdx; } + LocalStack& localStack() { return m_stack; } + + /// Prints local stack and block instructions to stderr. + /// Useful for calling in a debugger session. + void dump(); + private: ProgramCounter const m_beginInstIdx; ProgramCounter const m_endInstIdx; diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 71661bde9..1b408d6fe 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -123,12 +123,12 @@ void Compiler::createBasicBlocks(bytesConstRef bytecode) auto beginInstIdx = *it; ++it; auto endInstIdx = it != splitPoints.cend() ? *it : bytecode.size(); - basicBlocks.emplace(std::piecewise_construct, std::forward_as_tuple(beginInstIdx), std::forward_as_tuple(beginInstIdx, endInstIdx, m_mainFunc)); + basicBlocks.emplace(std::piecewise_construct, std::forward_as_tuple(beginInstIdx), std::forward_as_tuple(beginInstIdx, endInstIdx, m_mainFunc, m_builder)); } m_stopBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Stop", m_mainFunc); - m_badJumpBlock = std::make_unique("BadJumpBlock", m_mainFunc); - m_jumpTableBlock = std::make_unique("JumpTableBlock", m_mainFunc); + m_badJumpBlock = std::make_unique("BadJumpBlock", m_mainFunc, m_builder); + m_jumpTableBlock = std::make_unique("JumpTableBlock", m_mainFunc, m_builder); for (auto it = directJumpTargets.cbegin(); it != directJumpTargets.cend(); ++it) { @@ -186,6 +186,9 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) ++iterCopy; auto nextBasicBlock = (iterCopy != basicBlocks.end()) ? iterCopy->second.llvm() : nullptr; compileBasicBlock(basicBlock, bytecode, memory, ext, gasMeter, nextBasicBlock); + if (getenv("EVMCC_DEBUG_BLOCKS")) + basicBlock.dump(); + basicBlock.localStack().synchronize(stack); } // Code for special blocks: @@ -201,9 +204,9 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) m_builder.SetInsertPoint(m_jumpTableBlock->llvm()); if (m_indirectJumpTargets.size() > 0) { - auto& stack = m_jumpTableBlock->getStack(); + // auto& stack = m_jumpTableBlock->getStack(); - auto dest = stack.pop(); + auto dest = m_jumpTableBlock->localStack().pop(); //m_jumpTableBlock->localGet(0); // stack.pop(); auto switchInstr = m_builder.CreateSwitch(dest, m_badJumpBlock->llvm(), m_indirectJumpTargets.size()); for (auto it = m_indirectJumpTargets.cbegin(); it != m_indirectJumpTargets.cend(); ++it) @@ -218,7 +221,8 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) m_builder.CreateBr(m_badJumpBlock->llvm()); } - linkBasicBlocks(stack); + m_jumpTableBlock->localStack().synchronize(stack); + linkBasicBlocks(); return module; } @@ -226,8 +230,8 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, Memory& memory, Ext& ext, GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock) { - auto& stack = basicBlock.getStack(); m_builder.SetInsertPoint(basicBlock.llvm()); + auto& stack = basicBlock.localStack(); for (auto currentPC = basicBlock.begin(); currentPC != basicBlock.end(); ++currentPC) { @@ -589,8 +593,6 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, } else { - // FIXME: this get(0) is a temporary workaround to get some of the jump tests running. - stack.get(0); m_builder.CreateBr(m_jumpTableBlock->llvm()); } } @@ -873,7 +875,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, } -void Compiler::linkBasicBlocks(Stack& stack) +void Compiler::linkBasicBlocks() // Stack& stack) { // Remove dead basic blocks auto sthErased = false; @@ -902,13 +904,14 @@ void Compiler::linkBasicBlocks(Stack& stack) m_jumpTableBlock.reset(); } - +/* struct BBInfo { BasicBlock& bblock; std::vector predecessors; size_t inputItems; size_t outputItems; + std::vector phisToRewrite; BBInfo(BasicBlock& _bblock) : bblock(_bblock), @@ -978,7 +981,8 @@ void Compiler::linkBasicBlocks(Stack& stack) } } - std::map phiReplacements; + // std::map phiReplacements; + // std::vector phiNodesToRewrite; // Propagate values between blocks. for (auto& pair : cfg) @@ -1001,13 +1005,14 @@ void Compiler::linkBasicBlocks(Stack& stack) } // Turn the remaining phi nodes into stack.pop's. - m_builder.SetInsertPoint(llbb, llvm::BasicBlock::iterator(llbb->getFirstNonPHI())); + // m_builder.SetInsertPoint(llbb, llvm::BasicBlock::iterator(llbb->getFirstNonPHI())); for (; llvm::isa(*instrIter); ++instrIter) { auto phi = llvm::cast(instrIter); - auto value = stack.popWord(); + // auto value = stack.popWord(); // Don't delete the phi node yet. It may still be stored in a local stack of some block. - phiReplacements[phi] = value; + // phiReplacements[phi] = value; + bbInfo.phisToRewrite.push_back(phi); } // Emit stack push's at the end of the block, just before the terminator; @@ -1018,11 +1023,33 @@ void Compiler::linkBasicBlocks(Stack& stack) stack.pushWord(bblock.getStack().get(localStackSize - 1 - i)); } - for (auto& entry : phiReplacements) + for (auto& entry : cfg) { - entry.first->replaceAllUsesWith(entry.second); - entry.first->eraseFromParent(); + // Where was the last stack.pop() inserted + auto lastPopIt = entry.first->begin(); + + for (auto phi : entry.second.phisToRewrite) + { + // Insert stack.pop() before the first use of phi, + // then replace all uses of phi with the popped val. + + if (phi->use_begin() == phi->use_end()) + { + // For a phi with no uses, insert pop just after the previous one + } + std::cout << "*** PHI node " << phi->getName().str() << " has no uses!\n"; + } + else + { + assert(llvm::isa(phi->use_begin()->getUser())); + + m_builder.SetInsertPoint(*phi->use_begin()); + auto popVal = stack.popWord(); + phi->replaceAllUsesWith(popVal); + phi->eraseFromParent(); + } } + */ } void Compiler::dumpBasicBlockGraph(std::ostream& out) @@ -1030,7 +1057,7 @@ void Compiler::dumpBasicBlockGraph(std::ostream& out) out << "digraph BB {\n" << " node [shape=record];\n" << " entry [share=record, label=\"entry block\"];\n"; - +/* std::vector blocks; for (auto& pair : this->basicBlocks) blocks.push_back(&pair.second); @@ -1076,6 +1103,7 @@ void Compiler::dumpBasicBlockGraph(std::ostream& out) } out << "}\n"; + */ } } diff --git a/libevmjit/Compiler.h b/libevmjit/Compiler.h index ac6277e7b..9d7b37fbc 100644 --- a/libevmjit/Compiler.h +++ b/libevmjit/Compiler.h @@ -33,7 +33,7 @@ private: void compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, class Memory& memory, class Ext& ext, class GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock); - void linkBasicBlocks(class Stack& stack); + void linkBasicBlocks(); //class Stack& stack); llvm::IRBuilder<> m_builder; diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp index 4bcaf2c50..af5f96ac7 100644 --- a/libevmjit/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -19,6 +19,7 @@ #include "Runtime.h" #include "Memory.h" +#include "Stack.h" #include "Type.h" namespace dev @@ -35,7 +36,6 @@ ExecutionEngine::ExecutionEngine() extern "C" { EXPORT std::jmp_buf* rt_jmpBuf; } - int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, ExtVMFace* _ext) { auto module = _module.get(); // Keep ownership of the module in _module @@ -117,6 +117,8 @@ int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, ExtV // Return remaining gas _gas = returnCode == ReturnCode::OutOfGas ? 0 : Runtime::getGas(); + std::cout << "Max stack size: " << Stack::maxStackSize << std::endl; + if (returnCode == ReturnCode::Return) { returnData = Memory::getReturnData().toVector(); // TODO: It might be better to place is in Runtime interface @@ -128,6 +130,7 @@ int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, ExtV } std::cout << "RETURN CODE: " << (int)returnCode << std::endl; + return static_cast(returnCode); } diff --git a/libevmjit/Stack.cpp b/libevmjit/Stack.cpp index ce7d09471..89044bea8 100644 --- a/libevmjit/Stack.cpp +++ b/libevmjit/Stack.cpp @@ -17,34 +17,48 @@ namespace jit Stack::Stack(llvm::IRBuilder<>& _builder) : CompilerHelper(_builder) { - auto i256Ty = m_builder.getIntNTy(256); - auto i256PtrTy = i256Ty->getPointerTo(); - - m_arg = m_builder.CreateAlloca(i256Ty, nullptr, "stack.retVal"); + m_arg = m_builder.CreateAlloca(Type::i256, nullptr, "stack.arg"); using namespace llvm; using Linkage = GlobalValue::LinkageTypes; auto module = getModule(); - m_push = Function::Create(FunctionType::get(m_builder.getVoidTy(), i256PtrTy, false), Linkage::ExternalLinkage, "stack_push", module); - m_pop = Function::Create(FunctionType::get(m_builder.getVoidTy(), i256PtrTy, false), Linkage::ExternalLinkage, "stack_pop", module); + m_push = Function::Create(FunctionType::get(m_builder.getVoidTy(), Type::WordPtr, false), Linkage::ExternalLinkage, "stack_push", module); + m_pop = Function::Create(FunctionType::get(m_builder.getVoidTy(), Type::Size, false), Linkage::ExternalLinkage, "stack_pop", module); + llvm::Type* getSetArgTypes[] = {Type::Size, Type::WordPtr}; + m_get = Function::Create(FunctionType::get(m_builder.getVoidTy(), ArrayRef(getSetArgTypes), false), Linkage::ExternalLinkage, "stack_get", module); + m_set = Function::Create(FunctionType::get(m_builder.getVoidTy(), ArrayRef(getSetArgTypes), false), Linkage::ExternalLinkage, "stack_set", module); } Stack::~Stack() {} -llvm::Instruction* Stack::popWord() +llvm::Value* Stack::get(size_t _index) { - m_builder.CreateCall(m_pop, m_arg); + m_builder.CreateCall2(m_get, llvm::ConstantInt::get(Type::Size, _index, false), m_arg); return m_builder.CreateLoad(m_arg); } -void Stack::pushWord(llvm::Value* _word) +void Stack::set(size_t _index, llvm::Value* _value) +{ + m_builder.CreateStore(_value, m_arg); + m_builder.CreateCall2(m_set, llvm::ConstantInt::get(Type::Size, _index, false), m_arg); +} + +void Stack::pop(size_t _count) { - m_builder.CreateStore(_word, m_arg); + m_builder.CreateCall(m_pop, llvm::ConstantInt::get(Type::Size, _count, false)); +} + +void Stack::push(llvm::Value* _value) +{ + m_builder.CreateStore(_value, m_arg); m_builder.CreateCall(m_push, m_arg); } + +size_t Stack::maxStackSize = 0; + } } } @@ -56,21 +70,42 @@ using namespace dev::eth::jit; extern std::jmp_buf* rt_jmpBuf; -EXPORT void stack_pop(i256* _ret) +EXPORT void stack_pop(uint64_t _count) { auto& stack = Runtime::getStack(); - if (stack.size() == 0) + if (stack.size() < _count) longjmp(*rt_jmpBuf, static_cast(ReturnCode::StackTooSmall)); - assert(stack.size() > 0); - *_ret = stack.back(); - stack.pop_back(); + stack.erase(stack.end() - _count, stack.end()); } EXPORT void stack_push(i256* _word) { auto& stack = Runtime::getStack(); stack.push_back(*_word); + + if (stack.size() > Stack::maxStackSize) + Stack::maxStackSize = stack.size(); +} + +EXPORT void stack_get(uint64_t _index, i256* _ret) +{ + auto& stack = Runtime::getStack(); + // TODO: encode _index and stack size in the return code + if (stack.size() <= _index) + longjmp(*rt_jmpBuf, static_cast(ReturnCode::StackTooSmall)); + + *_ret = *(stack.rbegin() + _index); +} + +EXPORT void stack_set(uint64_t _index, i256* _word) +{ + auto& stack = Runtime::getStack(); + // TODO: encode _index and stack size in the return code + if (stack.size() <= _index) + longjmp(*rt_jmpBuf, static_cast(ReturnCode::StackTooSmall)); + + *(stack.rbegin() + _index) = *_word; } } // extern "C" diff --git a/libevmjit/Stack.h b/libevmjit/Stack.h index 5e1ac0f39..2380b2a15 100644 --- a/libevmjit/Stack.h +++ b/libevmjit/Stack.h @@ -14,15 +14,23 @@ namespace jit class Stack : public CompilerHelper { public: + Stack(llvm::IRBuilder<>& builder); virtual ~Stack(); - void pushWord(llvm::Value* _word); - llvm::Instruction* popWord(); + llvm::Value* get(size_t _index); + void set(size_t _index, llvm::Value* _value); + void pop(size_t _count); + void push(llvm::Value* _value); + + static size_t maxStackSize; private: + llvm::Function* m_push; llvm::Function* m_pop; + llvm::Function* m_get; + llvm::Function* m_set; llvm::Value* m_arg; }; diff --git a/libevmjit/Type.cpp b/libevmjit/Type.cpp index 3ef339a1b..baf458dbd 100644 --- a/libevmjit/Type.cpp +++ b/libevmjit/Type.cpp @@ -13,6 +13,7 @@ namespace jit llvm::IntegerType* Type::i256; llvm::PointerType* Type::WordPtr; llvm::IntegerType* Type::lowPrecision; +llvm::IntegerType* Type::Size; llvm::IntegerType* Type::Byte; llvm::PointerType* Type::BytePtr; llvm::Type* Type::Void; @@ -23,6 +24,8 @@ void Type::init(llvm::LLVMContext& _context) i256 = llvm::Type::getIntNTy(_context, 256); WordPtr = i256->getPointerTo(); lowPrecision = llvm::Type::getInt64Ty(_context); + // TODO: Size should be architecture-dependent + Size = llvm::Type::getInt64Ty(_context); Byte = llvm::Type::getInt8Ty(_context); BytePtr = Byte->getPointerTo(); Void = llvm::Type::getVoidTy(_context); diff --git a/libevmjit/Type.h b/libevmjit/Type.h index a03bfac38..16a13c373 100644 --- a/libevmjit/Type.h +++ b/libevmjit/Type.h @@ -20,6 +20,8 @@ struct Type /// @TODO: Use 64-bit for now. In 128-bit compiler-rt library functions are required static llvm::IntegerType* lowPrecision; + static llvm::IntegerType* Size; + static llvm::IntegerType* Byte; static llvm::PointerType* BytePtr; From 9ec5ffd7d7f79c005c081e2ce186ca5d07cb40ac Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Fri, 24 Oct 2014 00:00:25 +0100 Subject: [PATCH 212/641] new test cases --- evmcc/test/jump/ackermann.ethel | 7 +++++++ evmcc/test/jump/ackermann.evm | 1 + evmcc/test/jump/fac.ethel | 5 +++++ evmcc/test/jump/fac.evm | 1 + evmcc/test/jump/fac_tail.ethel | 5 +++++ evmcc/test/jump/fac_tail.evm | 1 + evmcc/test/stack/oos.evm | 1 + evmcc/test/stack/oos.lll | 11 +++++++++++ evmcc/test/stack/swap.evm | 1 + evmcc/test/stack/swap.lll | 25 +++++++++++++++++++++++++ evmcc/test/stack/swapswap.evm | 1 + evmcc/test/stack/swapswap.lll | 26 ++++++++++++++++++++++++++ evmcc/test/stack/test.evm | 1 + 13 files changed, 86 insertions(+) create mode 100644 evmcc/test/jump/ackermann.ethel create mode 100644 evmcc/test/jump/ackermann.evm create mode 100644 evmcc/test/jump/fac.ethel create mode 100644 evmcc/test/jump/fac.evm create mode 100644 evmcc/test/jump/fac_tail.ethel create mode 100644 evmcc/test/jump/fac_tail.evm create mode 100644 evmcc/test/stack/oos.evm create mode 100644 evmcc/test/stack/oos.lll create mode 100644 evmcc/test/stack/swap.evm create mode 100644 evmcc/test/stack/swap.lll create mode 100644 evmcc/test/stack/swapswap.evm create mode 100644 evmcc/test/stack/swapswap.lll create mode 100644 evmcc/test/stack/test.evm diff --git a/evmcc/test/jump/ackermann.ethel b/evmcc/test/jump/ackermann.ethel new file mode 100644 index 000000000..971fd2b8d --- /dev/null +++ b/evmcc/test/jump/ackermann.ethel @@ -0,0 +1,7 @@ +let A m n = + if m == 0 then n+1 + else if n == 0 then A (m-1) 1 + else A (m-1) (A (m) (n-1)) + +return A 3 8 + diff --git a/evmcc/test/jump/ackermann.evm b/evmcc/test/jump/ackermann.evm new file mode 100644 index 000000000..964844045 --- /dev/null +++ b/evmcc/test/jump/ackermann.evm @@ -0,0 +1 @@ +6009600360086012585d60005460206000f26000820e6047596000810e603859603460018303603084600185036012585d6012585d60445860436001830360016012585d604b5860018101905090509058 \ No newline at end of file diff --git a/evmcc/test/jump/fac.ethel b/evmcc/test/jump/fac.ethel new file mode 100644 index 000000000..8bfe94dd6 --- /dev/null +++ b/evmcc/test/jump/fac.ethel @@ -0,0 +1,5 @@ +let fac n = + if n == 0 then 1 + else n * fac (n-1) + +return fac 60 \ No newline at end of file diff --git a/evmcc/test/jump/fac.evm b/evmcc/test/jump/fac.evm new file mode 100644 index 000000000..04cd3e4f4 --- /dev/null +++ b/evmcc/test/jump/fac.evm @@ -0,0 +1 @@ +6007603c6010585d60005460206000f26000810e6026596020600182036010585d8102602858600190509058 \ No newline at end of file diff --git a/evmcc/test/jump/fac_tail.ethel b/evmcc/test/jump/fac_tail.ethel new file mode 100644 index 000000000..9ce5ecac7 --- /dev/null +++ b/evmcc/test/jump/fac_tail.ethel @@ -0,0 +1,5 @@ +let fac a n = + if n == 0 then a + else fac (a*n) (n-1) + +return fac 1 60 \ No newline at end of file diff --git a/evmcc/test/jump/fac_tail.evm b/evmcc/test/jump/fac_tail.evm new file mode 100644 index 000000000..8384d94e4 --- /dev/null +++ b/evmcc/test/jump/fac_tail.evm @@ -0,0 +1 @@ +60096001603c6012585d60005460206000f26000810e6029596025818302600183036012585d602a5881905090509058 \ No newline at end of file diff --git a/evmcc/test/stack/oos.evm b/evmcc/test/stack/oos.evm new file mode 100644 index 000000000..ea2f1c890 --- /dev/null +++ b/evmcc/test/stack/oos.evm @@ -0,0 +1 @@ +60018194505050509150 diff --git a/evmcc/test/stack/oos.lll b/evmcc/test/stack/oos.lll new file mode 100644 index 000000000..5394b06ba --- /dev/null +++ b/evmcc/test/stack/oos.lll @@ -0,0 +1,11 @@ +(asm ;; x . v y z +1 ;; 1 x . v y z +DUP2 ;; x 1 x . v y z +SWAP5 ;; y 1 x . v x z +POP ;; 1 x . v x z +POP ;; x . v x z +POP ;; . v x z +POP ;; v x z +SWAP2 ;; z x v +POP ;; x v +) diff --git a/evmcc/test/stack/swap.evm b/evmcc/test/stack/swap.evm new file mode 100644 index 000000000..27914aa55 --- /dev/null +++ b/evmcc/test/stack/swap.evm @@ -0,0 +1 @@ +600160026001600a590090600160115900016000546001601ff2 diff --git a/evmcc/test/stack/swap.lll b/evmcc/test/stack/swap.lll new file mode 100644 index 000000000..e9ac214bd --- /dev/null +++ b/evmcc/test/stack/swap.lll @@ -0,0 +1,25 @@ +(asm +1 ;; 0 +2 ;; 2 +1 ;; 4 +10 ;; 6 +JUMPI ;; 8 +STOP ;; 9 + +;; stack = 2,1 +SWAP1 ;; 10 +1 ;; 11 +17 ;; 13 +JUMPI ;; 15 +STOP ;; 16 + +;; stack = 1,2 +ADD ;; 17 +0 +MSTORE +1 +31 +RETURN ;; returns 03 +) + + diff --git a/evmcc/test/stack/swapswap.evm b/evmcc/test/stack/swapswap.evm new file mode 100644 index 000000000..f0081f238 --- /dev/null +++ b/evmcc/test/stack/swapswap.evm @@ -0,0 +1 @@ +600160026001600a59009090600160125900016000546001601ff2 diff --git a/evmcc/test/stack/swapswap.lll b/evmcc/test/stack/swapswap.lll new file mode 100644 index 000000000..67fe75941 --- /dev/null +++ b/evmcc/test/stack/swapswap.lll @@ -0,0 +1,26 @@ +(asm +1 ;; 0 +2 ;; 2 +1 ;; 4 +10 ;; 6 +JUMPI ;; 8 +STOP ;; 9 + +;; stack = 2,1 +SWAP1 ;; 10 +SWAP1 ;; 11 +1 ;; 12 +18 ;; 14 +JUMPI ;; 16 +STOP ;; 17 + +;; stack = 2,1 +ADD ;; 18 +0 +MSTORE +1 +31 +RETURN ;; returns 03 +) + + diff --git a/evmcc/test/stack/test.evm b/evmcc/test/stack/test.evm new file mode 100644 index 000000000..ea2f1c890 --- /dev/null +++ b/evmcc/test/stack/test.evm @@ -0,0 +1 @@ +60018194505050509150 From 9fa2958d3951d989adfa772819ba0a58bec76782 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 24 Oct 2014 11:48:18 +0200 Subject: [PATCH 213/641] Visual Studio build fix --- libevmjit/BasicBlock.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libevmjit/BasicBlock.cpp b/libevmjit/BasicBlock.cpp index 13d66140f..cc0efc11a 100644 --- a/libevmjit/BasicBlock.cpp +++ b/libevmjit/BasicBlock.cpp @@ -1,6 +1,8 @@ #include "BasicBlock.h" +#include + #include #include From 8b4709452948607b8e087f1fee95ce942ee79628 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 24 Oct 2014 15:19:32 +0200 Subject: [PATCH 214/641] Introducing RuntimeData struct - a data that will be provided to running program --- libevmjit/Compiler.cpp | 5 ++++- libevmjit/ExecutionEngine.cpp | 2 +- libevmjit/Runtime.cpp | 9 +++++++++ libevmjit/Runtime.h | 12 ++++++++++++ 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 1b408d6fe..0128c76d5 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -17,6 +17,7 @@ #include "GasMeter.h" #include "Utils.h" #include "Endianness.h" +#include "Runtime.h" namespace dev { @@ -163,7 +164,9 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) auto module = std::make_unique("main", m_builder.getContext()); // Create main function - m_mainFunc = llvm::Function::Create(llvm::FunctionType::get(Type::MainReturn, false), llvm::Function::ExternalLinkage, "main", module.get()); + llvm::Type* mainFuncArgTypes[] = {m_builder.getInt32Ty(), RuntimeData::getType()->getPointerTo()}; // There must be int in first place because LLVM does not support other signatures + auto mainFuncType = llvm::FunctionType::get(Type::MainReturn, mainFuncArgTypes, false); + m_mainFunc = llvm::Function::Create(mainFuncType, llvm::Function::ExternalLinkage, "main", module.get()); // Create the basic blocks. auto entryBlock = llvm::BasicBlock::Create(m_builder.getContext(), "entry", m_mainFunc); diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp index af5f96ac7..e537d0517 100644 --- a/libevmjit/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -108,7 +108,7 @@ int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, ExtV if (r == 0) { rt_jmpBuf = &buf; - auto result = exec->runFunction(entryFunc, {}); + auto result = exec->runFunction(entryFunc, {{}, llvm::GenericValue(runtime.getDataPtr())}); returnCode = static_cast(result.IntVal.getZExtValue()); } else diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 448d25f92..900b109fa 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -12,6 +12,15 @@ namespace eth namespace jit { +llvm::StructType* RuntimeData::getType() +{ + llvm::Type* elems[] = + { + Type::i256, + }; + return llvm::StructType::create(elems, "RuntimeData"); +} + static Runtime* g_runtime; extern "C" diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index 165f47e06..8cee63fa1 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -21,6 +21,13 @@ namespace eth namespace jit { +struct RuntimeData +{ + static llvm::StructType* getType(); + + i256 gas; +}; + using StackImpl = std::vector; using MemoryImpl = bytes; @@ -33,12 +40,17 @@ public: Runtime(const Runtime&) = delete; void operator=(const Runtime&) = delete; + RuntimeData* getDataPtr() { return &m_data; } + static StackImpl& getStack(); static MemoryImpl& getMemory(); static ExtVMFace& getExt(); static u256 getGas(); private: + + /// @internal Must be the first element to asure Runtime* === RuntimeData* + RuntimeData m_data; StackImpl m_stack; MemoryImpl m_memory; ExtVMFace& m_ext; From 3fbe03a45670c9ba29178e97a39e9166878cb5f2 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Fri, 24 Oct 2014 15:08:33 +0100 Subject: [PATCH 215/641] Propagation of values between basic blocks' local stacks [#80895676] --- evmcc/test/stack/swap.evm | 2 +- evmcc/test/stack/swap.lll | 24 ++-- evmcc/test/stack/swapswap.evm | 2 +- evmcc/test/stack/swapswap.lll | 28 ++-- libevmjit/BasicBlock.cpp | 197 +++++++++++++++++++++++---- libevmjit/BasicBlock.h | 9 +- libevmjit/Compiler.cpp | 246 ++++++++++------------------------ libevmjit/Compiler.h | 4 +- 8 files changed, 288 insertions(+), 224 deletions(-) diff --git a/evmcc/test/stack/swap.evm b/evmcc/test/stack/swap.evm index 27914aa55..d17f0ee09 100644 --- a/evmcc/test/stack/swap.evm +++ b/evmcc/test/stack/swap.evm @@ -1 +1 @@ -600160026001600a590090600160115900016000546001601ff2 +600560026001600c59505000906001601559505000036000546001601ff2 diff --git a/evmcc/test/stack/swap.lll b/evmcc/test/stack/swap.lll index e9ac214bd..90dee585d 100644 --- a/evmcc/test/stack/swap.lll +++ b/evmcc/test/stack/swap.lll @@ -1,20 +1,26 @@ (asm -1 ;; 0 +5 ;; 0 2 ;; 2 1 ;; 4 -10 ;; 6 +12 ;; 6 JUMPI ;; 8 -STOP ;; 9 + +POP ;; 9 +POP ;; 10 +STOP ;; 11 ;; stack = 2,1 -SWAP1 ;; 10 -1 ;; 11 -17 ;; 13 -JUMPI ;; 15 -STOP ;; 16 +SWAP1 ;; 12 +1 ;; 13 +21 ;; 15 +JUMPI ;; 17 + +POP ;; 18 +POP ;; 19 +STOP ;; 20 ;; stack = 1,2 -ADD ;; 17 +SUB ;; 21 0 MSTORE 1 diff --git a/evmcc/test/stack/swapswap.evm b/evmcc/test/stack/swapswap.evm index f0081f238..fb4f1bf75 100644 --- a/evmcc/test/stack/swapswap.evm +++ b/evmcc/test/stack/swapswap.evm @@ -1 +1 @@ -600160026001600a59009090600160125900016000546001601ff2 +600260056001600c5950500090906001601659505000036000546001601ff2 diff --git a/evmcc/test/stack/swapswap.lll b/evmcc/test/stack/swapswap.lll index 67fe75941..1fedf726e 100644 --- a/evmcc/test/stack/swapswap.lll +++ b/evmcc/test/stack/swapswap.lll @@ -1,21 +1,27 @@ (asm -1 ;; 0 -2 ;; 2 +2 ;; 0 +5 ;; 2 1 ;; 4 -10 ;; 6 +12 ;; 6 JUMPI ;; 8 -STOP ;; 9 + +POP ;; 9 +POP ;; 10 +STOP ;; 11 ;; stack = 2,1 -SWAP1 ;; 10 -SWAP1 ;; 11 -1 ;; 12 -18 ;; 14 -JUMPI ;; 16 -STOP ;; 17 +SWAP1 ;; 12 +SWAP1 ;; 13 +1 ;; 14 +22 ;; 16 +JUMPI ;; 18 + +POP ;; 19 +POP ;; 20 +STOP ;; 21 ;; stack = 2,1 -ADD ;; 18 +SUB ;; 22 0 MSTORE 1 diff --git a/libevmjit/BasicBlock.cpp b/libevmjit/BasicBlock.cpp index 13d66140f..3fffb2148 100644 --- a/libevmjit/BasicBlock.cpp +++ b/libevmjit/BasicBlock.cpp @@ -3,9 +3,11 @@ #include +#include #include #include #include +#include #include "Type.h" @@ -22,17 +24,18 @@ BasicBlock::BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx, m_beginInstIdx(_beginInstIdx), m_endInstIdx(_endInstIdx), m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {NamePrefix, std::to_string(_beginInstIdx)}, _mainFunc)), - m_stack(_builder) + m_stack(_builder, m_llvmBB) {} BasicBlock::BasicBlock(std::string _name, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder) : m_beginInstIdx(0), m_endInstIdx(0), m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), _name, _mainFunc)), - m_stack(_builder) + m_stack(_builder, m_llvmBB) {} -BasicBlock::LocalStack::LocalStack(llvm::IRBuilder<>& _builder) : +BasicBlock::LocalStack::LocalStack(llvm::IRBuilder<>& _builder, llvm::BasicBlock* _llvmBB) : + m_llvmBB(_llvmBB), m_builder(_builder), m_initialStack(), m_currentStack(), @@ -80,7 +83,7 @@ void BasicBlock::LocalStack::swap(size_t _index) void BasicBlock::LocalStack::synchronize(Stack& _evmStack) { - auto blockTerminator = m_builder.GetInsertBlock()->getTerminator(); + auto blockTerminator = m_llvmBB->getTerminator(); assert(blockTerminator != nullptr); m_builder.SetInsertPoint(blockTerminator); @@ -180,44 +183,190 @@ void BasicBlock::LocalStack::set(size_t _index, llvm::Value* _word) } + +void BasicBlock::linkLocalStacks(std::vector basicBlocks, llvm::IRBuilder<>& _builder) +{ + struct BBInfo + { + BasicBlock& bblock; + std::vector predecessors; + size_t inputItems; + size_t outputItems; + std::vector phisToRewrite; + + BBInfo(BasicBlock& _bblock) : + bblock(_bblock), + predecessors(), + inputItems(0), + outputItems(0) + { + auto& initialStack = bblock.localStack().m_initialStack; + for (auto it = initialStack.begin(); + it != initialStack.end() && *it != nullptr; + ++it, ++inputItems); + + //if (bblock.localStack().m_tosOffset > 0) + // outputItems = bblock.localStack().m_tosOffset; + auto& exitStack = bblock.localStack().m_currentStack; + for (auto it = exitStack.rbegin(); + it != exitStack.rend() && *it != nullptr; + ++it, ++outputItems); + } + }; + + std::map cfg; + + // Create nodes in cfg + for (auto bb : basicBlocks) + cfg.emplace(bb->llvm(), *bb); + + // Create edges in cfg: for each bb info fill the list + // of predecessor infos. + for (auto& pair : cfg) + { + auto bb = pair.first; + auto& info = pair.second; + + for (auto predIt = llvm::pred_begin(bb); predIt != llvm::pred_end(bb); ++predIt) + { + auto predInfoEntry = cfg.find(*predIt); + if (predInfoEntry != cfg.end()) + info.predecessors.push_back(&predInfoEntry->second); + } + } + + // Iteratively compute inputs and outputs of each block, until reaching fixpoint. + bool valuesChanged = true; + while (valuesChanged) + { + if (getenv("EVMCC_DEBUG_BLOCKS")) + { + for (auto& pair: cfg) + std::cerr << pair.second.bblock.llvm()->getName().str() + << ": in " << pair.second.inputItems + << ", out " << pair.second.outputItems + << "\n"; + } + + valuesChanged = false; + for (auto& pair : cfg) + { + auto& info = pair.second; + + if (info.predecessors.empty()) + info.inputItems = 0; // no consequences for other blocks, so leave valuesChanged false + + for (auto predInfo : info.predecessors) + { + if (predInfo->outputItems < info.inputItems) + { + info.inputItems = predInfo->outputItems; + valuesChanged = true; + } + else if (predInfo->outputItems > info.inputItems) + { + predInfo->outputItems = info.inputItems; + valuesChanged = true; + } + } + } + } + + // Propagate values between blocks. + for (auto& entry : cfg) + { + auto& info = entry.second; + auto& bblock = info.bblock; + + llvm::BasicBlock::iterator fstNonPhi(bblock.llvm()->getFirstNonPHI()); + auto phiIter = bblock.localStack().m_initialStack.begin(); + for (size_t index = 0; index < info.inputItems; ++index, ++phiIter) + { + assert(llvm::isa(*phiIter)); + auto phi = llvm::cast(*phiIter); + + for (auto predIt : info.predecessors) + { + auto& predExitStack = predIt->bblock.localStack().m_currentStack; + auto value = *(predExitStack.end() - 1 - index); + phi->addIncoming(value, predIt->bblock.llvm()); + } + + // Move phi to the front + if (llvm::BasicBlock::iterator(phi) != bblock.llvm()->begin()) + { + phi->removeFromParent(); + _builder.SetInsertPoint(bblock.llvm(), bblock.llvm()->begin()); + _builder.Insert(phi); + } + } + + // The items pulled directly from predecessors block must be removed + // from the list of items that has to be popped from the initial stack. + auto& initialStack = bblock.localStack().m_initialStack; + initialStack.erase(initialStack.begin(), initialStack.begin() + info.inputItems); + // Initial stack shrinks, so the size difference grows: + bblock.localStack().m_tosOffset += info.inputItems; + } + + // We must account for the items that were pushed directly to successor + // blocks and thus should not be on the list of items to be pushed onto + // to EVM stack + for (auto& entry : cfg) + { + auto& info = entry.second; + auto& bblock = info.bblock; + + auto& exitStack = bblock.localStack().m_currentStack; + exitStack.erase(exitStack.end() - info.outputItems, exitStack.end()); + bblock.localStack().m_tosOffset -= info.outputItems; + } +} + void BasicBlock::dump() { - std::cerr << "Initial stack:\n"; + dump(std::cerr, false); +} + +void BasicBlock::dump(std::ostream& _out, bool _dotOutput) +{ + llvm::raw_os_ostream out(_out); + + out << (_dotOutput ? "" : "Initial stack:\n"); for (auto val : m_stack.m_initialStack) { if (val == nullptr) - std::cerr << " ?\n"; + out << " ?"; else if (llvm::isa(val)) - val->dump(); + out << *val; else - { - std::cerr << " "; - val->dump(); - } + out << " " << *val; + + out << (_dotOutput ? "\\l" : "\n"); } - std::cerr << " ...\n"; - std::cerr << "Instructions:\n"; + out << (_dotOutput ? "| " : "Instructions:\n"); for (auto ins = m_llvmBB->begin(); ins != m_llvmBB->end(); ++ins) - ins->dump(); + out << *ins << (_dotOutput ? "\\l" : "\n"); - std::cerr << "Current stack (offset = " - << m_stack.m_tosOffset << "):\n"; + if (! _dotOutput) + out << "Current stack (offset = " << m_stack.m_tosOffset << "):\n"; + else + out << "|"; for (auto val = m_stack.m_currentStack.rbegin(); val != m_stack.m_currentStack.rend(); ++val) { if (*val == nullptr) - std::cerr << " ?\n"; + out << " ?"; else if (llvm::isa(*val)) - (*val)->dump(); + out << **val; else - { - std::cerr << " "; - (*val)->dump(); - } - + out << " " << **val; + out << (_dotOutput ? "\\l" : "\n"); } - std::cerr << " ...\n----------------------------------------\n"; + + if (! _dotOutput) + out << " ...\n----------------------------------------\n"; } diff --git a/libevmjit/BasicBlock.h b/libevmjit/BasicBlock.h index 2723cf919..65044eb2a 100644 --- a/libevmjit/BasicBlock.h +++ b/libevmjit/BasicBlock.h @@ -40,7 +40,7 @@ public: private: - LocalStack(llvm::IRBuilder<>& _builder); + LocalStack(llvm::IRBuilder<>& _builder, llvm::BasicBlock* _llvmBB); LocalStack(LocalStack const&) = delete; void operator=(LocalStack const&) = delete; friend BasicBlock; @@ -55,6 +55,8 @@ public: private: + llvm::BasicBlock* m_llvmBB; + llvm::IRBuilder<>& m_builder; /** @@ -99,9 +101,14 @@ public: LocalStack& localStack() { return m_stack; } + /// Optimization: propagates values between local stacks in basic blocks + /// to avoid excessive pushing/popping on the EVM stack. + static void linkLocalStacks(std::vector _basicBlocks, llvm::IRBuilder<>& _builder); + /// Prints local stack and block instructions to stderr. /// Useful for calling in a debugger session. void dump(); + void dump(std::ostream& os, bool _dotOutput = false); private: ProgramCounter const m_beginInstIdx; diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 1b408d6fe..9632f5194 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -1,11 +1,13 @@ #include "Compiler.h" +#include + #include -#include -#include #include +#include +#include #include #include @@ -186,9 +188,6 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) ++iterCopy; auto nextBasicBlock = (iterCopy != basicBlocks.end()) ? iterCopy->second.llvm() : nullptr; compileBasicBlock(basicBlock, bytecode, memory, ext, gasMeter, nextBasicBlock); - if (getenv("EVMCC_DEBUG_BLOCKS")) - basicBlock.dump(); - basicBlock.localStack().synchronize(stack); } // Code for special blocks: @@ -204,9 +203,7 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) m_builder.SetInsertPoint(m_jumpTableBlock->llvm()); if (m_indirectJumpTargets.size() > 0) { - // auto& stack = m_jumpTableBlock->getStack(); - - auto dest = m_jumpTableBlock->localStack().pop(); //m_jumpTableBlock->localGet(0); // stack.pop(); + auto dest = m_jumpTableBlock->localStack().pop(); auto switchInstr = m_builder.CreateSwitch(dest, m_badJumpBlock->llvm(), m_indirectJumpTargets.size()); for (auto it = m_indirectJumpTargets.cbegin(); it != m_indirectJumpTargets.cend(); ++it) @@ -221,8 +218,51 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) m_builder.CreateBr(m_badJumpBlock->llvm()); } - m_jumpTableBlock->localStack().synchronize(stack); - linkBasicBlocks(); + removeDeadBlocks(); + + if (getenv("EVMCC_DEBUG_BLOCKS")) + { + std::ofstream ofs("blocks-init.dot"); + dumpBasicBlockGraph(ofs); + ofs.close(); + std::cerr << "\n\nAfter dead block elimination \n\n"; + dump(); + } + + if (getenv("EVMCC_OPTIMIZE_STACK")) + { + std::vector blockList; + for (auto& entry : basicBlocks) + blockList.push_back(&entry.second); + + if (m_jumpTableBlock != nullptr) + blockList.push_back(m_jumpTableBlock.get()); + + BasicBlock::linkLocalStacks(blockList, m_builder); + + if (getenv("EVMCC_DEBUG_BLOCKS")) + { + std::ofstream ofs("blocks-opt.dot"); + dumpBasicBlockGraph(ofs); + ofs.close(); + std::cerr << "\n\nAfter stack optimization \n\n"; + dump(); + } + } + + for (auto& entry : basicBlocks) + entry.second.localStack().synchronize(stack); + if (m_jumpTableBlock != nullptr) + m_jumpTableBlock->localStack().synchronize(stack); + + if (getenv("EVMCC_DEBUG_BLOCKS")) + { + std::ofstream ofs("blocks-sync.dot"); + dumpBasicBlockGraph(ofs); + ofs.close(); + std::cerr << "\n\nAfter stack synchronization \n\n"; + dump(); + } return module; } @@ -875,7 +915,8 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, } -void Compiler::linkBasicBlocks() // Stack& stack) + +void Compiler::removeDeadBlocks() { // Remove dead basic blocks auto sthErased = false; @@ -903,187 +944,33 @@ void Compiler::linkBasicBlocks() // Stack& stack) m_jumpTableBlock->llvm()->eraseFromParent(); m_jumpTableBlock.reset(); } - -/* - struct BBInfo - { - BasicBlock& bblock; - std::vector predecessors; - size_t inputItems; - size_t outputItems; - std::vector phisToRewrite; - - BBInfo(BasicBlock& _bblock) - : bblock(_bblock), - predecessors(), - inputItems(_bblock.getStack().initialSize()), - outputItems(_bblock.getStack().size()) - {} - }; - - std::map cfg; - - // Create nodes in cfg - for (auto& pair : this->basicBlocks) - { - auto& bb = pair.second; - cfg.emplace(bb.llvm(), bb); - } - - // Insert jump table block into cfg - if (m_jumpTableBlock) - cfg.emplace(m_jumpTableBlock->llvm(), *m_jumpTableBlock); - - auto& entryBlock = m_mainFunc->getEntryBlock(); - - // Create edges in cfg - for (auto& pair : cfg) - { - auto bbPtr = pair.first; - auto& bbInfo = pair.second; - - for (auto predIt = llvm::pred_begin(bbPtr); predIt != llvm::pred_end(bbPtr); ++predIt) - { - if (*predIt != &entryBlock) - { - auto predInfoEntry = cfg.find(*predIt); - assert(predInfoEntry != cfg.end()); - bbInfo.predecessors.push_back(&predInfoEntry->second); - } - } - } - - // Iteratively compute inputs and outputs of each block, until reaching fixpoint. - bool valuesChanged = true; - while (valuesChanged) - { - valuesChanged = false; - for (auto& pair : cfg) - { - auto& bbInfo = pair.second; - - if (bbInfo.predecessors.empty()) - bbInfo.inputItems = 0; // no consequences for other blocks, so leave valuesChanged false - - for (auto predInfo : bbInfo.predecessors) - { - if (predInfo->outputItems < bbInfo.inputItems) - { - bbInfo.inputItems = predInfo->outputItems; - valuesChanged = true; - } - else if (predInfo->outputItems > bbInfo.inputItems) - { - predInfo->outputItems = bbInfo.inputItems; - valuesChanged = true; - } - } - } - } - - // std::map phiReplacements; - // std::vector phiNodesToRewrite; - - // Propagate values between blocks. - for (auto& pair : cfg) - { - auto llbb = pair.first; - auto& bbInfo = pair.second; - auto& bblock = bbInfo.bblock; - - // Complete phi nodes for the top bbInfo.inputItems placeholder values - auto instrIter = llbb->begin(); - for (size_t valueIdx = 0; valueIdx < bbInfo.inputItems; ++instrIter, ++valueIdx) - { - auto phi = llvm::cast(instrIter); - for (auto predIt : bbInfo.predecessors) - { - assert(valueIdx < predIt->bblock.getStack().size()); - auto value = predIt->bblock.getStack().get(valueIdx); - phi->addIncoming(value, predIt->bblock.llvm()); - } - } - - // Turn the remaining phi nodes into stack.pop's. - // m_builder.SetInsertPoint(llbb, llvm::BasicBlock::iterator(llbb->getFirstNonPHI())); - for (; llvm::isa(*instrIter); ++instrIter) - { - auto phi = llvm::cast(instrIter); - // auto value = stack.popWord(); - // Don't delete the phi node yet. It may still be stored in a local stack of some block. - // phiReplacements[phi] = value; - bbInfo.phisToRewrite.push_back(phi); - } - - // Emit stack push's at the end of the block, just before the terminator; - m_builder.SetInsertPoint(llbb, -- llbb->end()); - auto localStackSize = bblock.getStack().size(); - assert(localStackSize >= bbInfo.outputItems); - for (size_t i = 0; i < localStackSize - bbInfo.outputItems; ++i) - stack.pushWord(bblock.getStack().get(localStackSize - 1 - i)); - } - - for (auto& entry : cfg) - { - // Where was the last stack.pop() inserted - auto lastPopIt = entry.first->begin(); - - for (auto phi : entry.second.phisToRewrite) - { - // Insert stack.pop() before the first use of phi, - // then replace all uses of phi with the popped val. - - if (phi->use_begin() == phi->use_end()) - { - // For a phi with no uses, insert pop just after the previous one - } - std::cout << "*** PHI node " << phi->getName().str() << " has no uses!\n"; - } - else - { - assert(llvm::isa(phi->use_begin()->getUser())); - - m_builder.SetInsertPoint(*phi->use_begin()); - auto popVal = stack.popWord(); - phi->replaceAllUsesWith(popVal); - phi->eraseFromParent(); - } - } - */ } void Compiler::dumpBasicBlockGraph(std::ostream& out) { out << "digraph BB {\n" - << " node [shape=record];\n" + << " node [shape=record, fontname=Courier, fontsize=10];\n" << " entry [share=record, label=\"entry block\"];\n"; -/* + std::vector blocks; - for (auto& pair : this->basicBlocks) + for (auto& pair : basicBlocks) blocks.push_back(&pair.second); if (m_jumpTableBlock) blocks.push_back(m_jumpTableBlock.get()); if (m_badJumpBlock) blocks.push_back(m_badJumpBlock.get()); - std::map phiNodesPerBlock; + // std::map phiNodesPerBlock; // Output nodes for (auto bb : blocks) { std::string blockName = bb->llvm()->getName(); - int numOfPhiNodes = 0; - auto firstNonPhiPtr = bb->llvm()->getFirstNonPHI(); - for (auto instrIter = bb->llvm()->begin(); &*instrIter != firstNonPhiPtr; ++instrIter, ++numOfPhiNodes); - phiNodesPerBlock[bb] = numOfPhiNodes; - - auto initStackSize = bb->getStack().initialSize(); - auto endStackSize = bb->getStack().size(); + std::ostringstream oss; + bb->dump(oss, true); - out << " \"" << blockName << "\" [shape=record, label=\"" - << initStackSize << "|" << blockName << "|" << endStackSize - << "\"];\n"; + out << " \"" << blockName << "\" [shape=record, label=\" { " << blockName << "|" << oss.str() << "} \"];\n"; } // Output edges @@ -1096,14 +983,21 @@ void Compiler::dumpBasicBlockGraph(std::ostream& out) { out << " \"" << (*it)->getName().str() << "\" -> \"" << blockName << "\" [" << ((m_jumpTableBlock.get() && *it == m_jumpTableBlock.get()->llvm()) ? "style = dashed, " : "") - << "label = \"" - << phiNodesPerBlock[bb] - << "\"];\n"; + //<< "label = \"" + //<< phiNodesPerBlock[bb] + << "];\n"; } } out << "}\n"; - */ +} + +void Compiler::dump() +{ + for (auto& entry : basicBlocks) + entry.second.dump(); + if (m_jumpTableBlock != nullptr) + m_jumpTableBlock->dump(); } } diff --git a/libevmjit/Compiler.h b/libevmjit/Compiler.h index 9d7b37fbc..afd5aef72 100644 --- a/libevmjit/Compiler.h +++ b/libevmjit/Compiler.h @@ -33,8 +33,10 @@ private: void compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, class Memory& memory, class Ext& ext, class GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock); - void linkBasicBlocks(); //class Stack& stack); + void removeDeadBlocks(); + /// Dump all basic blocks to stderr. Useful in a debugging session. + void dump(); llvm::IRBuilder<> m_builder; From c87717aa781f9fd05258dea49876afd8e14229d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 24 Oct 2014 16:20:29 +0200 Subject: [PATCH 216/641] Export runtime data to global variable in main function --- libevmjit/Compiler.cpp | 1 + libevmjit/CompilerHelper.cpp | 8 ++++++++ libevmjit/CompilerHelper.h | 3 +++ libevmjit/Runtime.cpp | 28 ++++++++++++++++++++++++---- libevmjit/Runtime.h | 12 ++++++++++++ 5 files changed, 48 insertions(+), 4 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 0128c76d5..14952163f 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -175,6 +175,7 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) createBasicBlocks(bytecode); // Init runtime structures. + RuntimeManager runtimeManager(m_builder); GasMeter gasMeter(m_builder); Memory memory(m_builder, gasMeter); Ext ext(m_builder); diff --git a/libevmjit/CompilerHelper.cpp b/libevmjit/CompilerHelper.cpp index 3bdf38641..b919043f2 100644 --- a/libevmjit/CompilerHelper.cpp +++ b/libevmjit/CompilerHelper.cpp @@ -21,6 +21,14 @@ llvm::Module* CompilerHelper::getModule() return m_builder.GetInsertBlock()->getParent()->getParent(); } +llvm::Function* CompilerHelper::getMainFunction() +{ + assert(m_builder.GetInsertBlock()); + auto mainFunc = m_builder.GetInsertBlock()->getParent(); + assert(mainFunc && mainFunc->getName() == "main"); + return mainFunc; +} + } } } diff --git a/libevmjit/CompilerHelper.h b/libevmjit/CompilerHelper.h index e284398a3..23bbcbd11 100644 --- a/libevmjit/CompilerHelper.h +++ b/libevmjit/CompilerHelper.h @@ -23,6 +23,9 @@ protected: /// Reference to the IR module being compiled llvm::Module* getModule(); + /// Reference to the main module function + llvm::Function* getMainFunction(); + /// Reference to parent compiler IR builder llvm::IRBuilder<>& m_builder; }; diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 900b109fa..4d800535c 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -1,6 +1,9 @@ #include "Runtime.h" +#include +#include + #include #include "Type.h" @@ -14,11 +17,16 @@ namespace jit llvm::StructType* RuntimeData::getType() { - llvm::Type* elems[] = + static llvm::StructType* type = nullptr; + if (!type) { - Type::i256, - }; - return llvm::StructType::create(elems, "RuntimeData"); + llvm::Type* elems[] = + { + Type::i256, + }; + type = llvm::StructType::create(elems, "RuntimeData"); + } + return type; } static Runtime* g_runtime; @@ -61,6 +69,18 @@ u256 Runtime::getGas() return llvm2eth(gas); } + +RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder): CompilerHelper(_builder) +{ + auto dataPtrType = RuntimeData::getType()->getPointerTo(); + m_dataPtr = new llvm::GlobalVariable(*getModule(), dataPtrType, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(dataPtrType), "rt"); + + // Export data + auto mainFunc = getMainFunction(); + llvm::Value* dataPtr = &mainFunc->getArgumentList().back(); + m_builder.CreateStore(dataPtr, m_dataPtr); +} + } } } diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index 8cee63fa1..d9984966e 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -5,6 +5,7 @@ #include +#include "CompilerHelper.h" #include "Utils.h" @@ -56,6 +57,17 @@ private: ExtVMFace& m_ext; }; +class RuntimeManager: public CompilerHelper +{ +public: + RuntimeManager(llvm::IRBuilder<>& _builder); + + llvm::Value* getGas(); + +private: + llvm::GlobalVariable* m_dataPtr; +}; + } } } From fcf5400c3ab76f427dd04f1a2807bdd8d3efd1ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 10:35:44 +0100 Subject: [PATCH 217/641] Place current gas counter value in RuntimeData --- libevmjit/Compiler.cpp | 8 ++++---- libevmjit/Compiler.h | 2 +- libevmjit/ExecutionEngine.cpp | 2 +- libevmjit/GasMeter.cpp | 21 +++++++-------------- libevmjit/GasMeter.h | 8 ++++---- libevmjit/Runtime.cpp | 25 ++++++++++++++++++------- libevmjit/Runtime.h | 3 ++- 7 files changed, 37 insertions(+), 32 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 339f73959..ddfe2497e 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -178,7 +178,7 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) // Init runtime structures. RuntimeManager runtimeManager(m_builder); - GasMeter gasMeter(m_builder); + GasMeter gasMeter(m_builder, runtimeManager); Memory memory(m_builder, gasMeter); Ext ext(m_builder); Stack stack(m_builder); @@ -191,7 +191,7 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) auto iterCopy = basicBlockPairIt; ++iterCopy; auto nextBasicBlock = (iterCopy != basicBlocks.end()) ? iterCopy->second.llvm() : nullptr; - compileBasicBlock(basicBlock, bytecode, memory, ext, gasMeter, nextBasicBlock); + compileBasicBlock(basicBlock, bytecode, runtimeManager, memory, ext, gasMeter, nextBasicBlock); } // Code for special blocks: @@ -272,7 +272,7 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) } -void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, Memory& memory, Ext& ext, GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock) +void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, RuntimeManager& _runtimeManager, Memory& memory, Ext& ext, GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock) { m_builder.SetInsertPoint(basicBlock.llvm()); auto& stack = basicBlock.localStack(); @@ -680,7 +680,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, case Instruction::GAS: { - stack.push(gasMeter.getGas()); + stack.push(_runtimeManager.getGas()); break; } diff --git a/libevmjit/Compiler.h b/libevmjit/Compiler.h index afd5aef72..d543b9b1d 100644 --- a/libevmjit/Compiler.h +++ b/libevmjit/Compiler.h @@ -31,7 +31,7 @@ private: void createBasicBlocks(bytesConstRef bytecode); - void compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, class Memory& memory, class Ext& ext, class GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock); + void compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, class RuntimeManager& _runtimeManager, class Memory& memory, class Ext& ext, class GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock); void removeDeadBlocks(); diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp index e537d0517..5d5af553e 100644 --- a/libevmjit/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -115,7 +115,7 @@ int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, ExtV returnCode = static_cast(r); // Return remaining gas - _gas = returnCode == ReturnCode::OutOfGas ? 0 : Runtime::getGas(); + _gas = returnCode == ReturnCode::OutOfGas ? 0 : runtime.getGas(); std::cout << "Max stack size: " << Stack::maxStackSize << std::endl; diff --git a/libevmjit/GasMeter.cpp b/libevmjit/GasMeter.cpp index 6eb8eb6eb..317b204fc 100644 --- a/libevmjit/GasMeter.cpp +++ b/libevmjit/GasMeter.cpp @@ -10,6 +10,7 @@ #include "Type.h" #include "Ext.h" +#include "Runtime.h" namespace dev { @@ -79,12 +80,11 @@ bool isCostBlockEnd(Instruction _inst) } -GasMeter::GasMeter(llvm::IRBuilder<>& _builder) : - CompilerHelper(_builder) +GasMeter::GasMeter(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager) : + CompilerHelper(_builder), + m_runtimeManager(_runtimeManager) { auto module = getModule(); - m_gas = new llvm::GlobalVariable(*module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "gas"); - m_gas->setUnnamedAddr(true); // Address is not important m_gasCheckFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "gas.check", module); InsertPointGuard guard(m_builder); @@ -96,7 +96,7 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder) : m_builder.SetInsertPoint(checkBB); llvm::Value* cost = m_gasCheckFunc->arg_begin(); cost->setName("cost"); - llvm::Value* gas = m_builder.CreateLoad(m_gas, "gas"); + auto gas = m_runtimeManager.getGas(); auto isOutOfGas = m_builder.CreateICmpUGT(cost, gas, "isOutOfGas"); m_builder.CreateCondBr(isOutOfGas, outOfGasBB, updateBB); @@ -111,7 +111,7 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder) : m_builder.SetInsertPoint(updateBB); gas = m_builder.CreateSub(gas, cost); - m_builder.CreateStore(gas, m_gas); + m_runtimeManager.setGas(gas); m_builder.CreateRetVoid(); } @@ -153,9 +153,7 @@ void GasMeter::countSStore(Ext& _ext, llvm::Value* _index, llvm::Value* _newValu void GasMeter::giveBack(llvm::Value* _gas) { - llvm::Value* gasCounter = m_builder.CreateLoad(m_gas, "gas"); - gasCounter = m_builder.CreateAdd(gasCounter, _gas); - m_builder.CreateStore(gasCounter, m_gas); + m_runtimeManager.setGas(m_builder.CreateAdd(m_runtimeManager.getGas(), _gas)); } void GasMeter::commitCostBlock(llvm::Value* _additionalCost) @@ -191,11 +189,6 @@ void GasMeter::checkMemory(llvm::Value* _additionalMemoryInWords, llvm::IRBuilde _builder.CreateCall(m_gasCheckFunc, cost); } -llvm::Value* GasMeter::getGas() -{ - return m_builder.CreateLoad(m_gas, "gas"); -} - } } } diff --git a/libevmjit/GasMeter.h b/libevmjit/GasMeter.h index 521e7080a..82007fc00 100644 --- a/libevmjit/GasMeter.h +++ b/libevmjit/GasMeter.h @@ -11,11 +11,12 @@ namespace eth { namespace jit { +class RuntimeManager; class GasMeter : public CompilerHelper { public: - GasMeter(llvm::IRBuilder<>& _builder); + GasMeter(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager); /// Count step cost of instruction void count(Instruction _inst); @@ -33,16 +34,15 @@ public: /// Generate code that checks the cost of additional memory used by program void checkMemory(llvm::Value* _additionalMemoryInWords, llvm::IRBuilder<>& _builder); - llvm::Value* getGas(); - private: /// Cumulative gas cost of a block of instructions /// @TODO Handle overflow uint64_t m_blockCost = 0; llvm::CallInst* m_checkCall = nullptr; - llvm::GlobalVariable* m_gas; llvm::Function* m_gasCheckFunc; + + RuntimeManager& m_runtimeManager; }; } diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 4d800535c..e37729e5b 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -31,17 +31,12 @@ llvm::StructType* RuntimeData::getType() static Runtime* g_runtime; -extern "C" -{ -EXPORT i256 gas; -} - Runtime::Runtime(u256 _gas, ExtVMFace& _ext): m_ext(_ext) { assert(!g_runtime); g_runtime = this; - gas = eth2llvm(_gas); + m_data.gas = eth2llvm(_gas); } Runtime::~Runtime() @@ -66,7 +61,7 @@ ExtVMFace& Runtime::getExt() u256 Runtime::getGas() { - return llvm2eth(gas); + return llvm2eth(m_data.gas); } @@ -81,6 +76,22 @@ RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder): CompilerHelper(_bui m_builder.CreateStore(dataPtr, m_dataPtr); } +llvm::Value* RuntimeManager::getGas() +{ + //auto gasPtr = m_builder.CreateConstGEP2_64(m_dataPtr, 0, 0); + auto rt = m_builder.CreateLoad(m_dataPtr); + auto gasPtr = m_builder.CreateStructGEP(rt, 0); + return m_builder.CreateLoad(gasPtr, "gas"); +} + +void RuntimeManager::setGas(llvm::Value* _gas) +{ + //auto gasPtr = m_builder.CreateStructGEP(m_dataPtr, 0); + auto rt = m_builder.CreateLoad(m_dataPtr); + auto gasPtr = m_builder.CreateStructGEP(rt, 0); + m_builder.CreateStore(_gas, gasPtr); +} + } } } diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index d9984966e..418555c04 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -46,7 +46,7 @@ public: static StackImpl& getStack(); static MemoryImpl& getMemory(); static ExtVMFace& getExt(); - static u256 getGas(); + u256 getGas(); private: @@ -63,6 +63,7 @@ public: RuntimeManager(llvm::IRBuilder<>& _builder); llvm::Value* getGas(); + void setGas(llvm::Value* _gas); private: llvm::GlobalVariable* m_dataPtr; From 9ec1ea526ac13e24853fedb2b969e473ddaa06f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 11:45:07 +0100 Subject: [PATCH 218/641] Access memory structure through runtime structure [#81470252] --- libevmjit/Compiler.cpp | 2 +- libevmjit/ExecutionEngine.cpp | 2 +- libevmjit/Ext.cpp | 9 ++--- libevmjit/Memory.cpp | 68 +++++++++++++++-------------------- libevmjit/Memory.h | 7 ++-- libevmjit/Runtime.cpp | 34 +++++++++++------- libevmjit/Runtime.h | 5 ++- 7 files changed, 66 insertions(+), 61 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index ddfe2497e..c3c09384b 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -179,7 +179,7 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) // Init runtime structures. RuntimeManager runtimeManager(m_builder); GasMeter gasMeter(m_builder, runtimeManager); - Memory memory(m_builder, gasMeter); + Memory memory(m_builder, gasMeter, runtimeManager); Ext ext(m_builder); Stack stack(m_builder); diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp index 5d5af553e..f7f30614c 100644 --- a/libevmjit/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -121,7 +121,7 @@ int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, ExtV if (returnCode == ReturnCode::Return) { - returnData = Memory::getReturnData().toVector(); // TODO: It might be better to place is in Runtime interface + returnData = runtime.getReturnData().toVector(); // TODO: It might be better to place is in Runtime interface std::cout << "RETURN [ "; for (auto it = returnData.begin(), end = returnData.end(); it != end; ++it) diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 045d25b62..07023c674 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -306,7 +306,8 @@ EXPORT void ext_create(i256* _endowment, i256* _initOff, i256* _initSize, h256* u256 gas; // TODO: Handle gas auto initOff = static_cast(llvm2eth(*_initOff)); auto initSize = static_cast(llvm2eth(*_initSize)); - auto&& initRef = bytesConstRef(Runtime::getMemory().data() + initOff, initSize); + //auto&& initRef = bytesConstRef(Runtime::getMemory().data() + initOff, initSize); + bytesConstRef initRef; OnOpFunc onOp{}; // TODO: Handle that thing h256 address = ext.create(endowment, &gas, initRef, onOp); *_address = address; @@ -332,8 +333,8 @@ EXPORT void ext_call(i256* _gas, h256* _receiveAddress, i256* _value, i256* _inO auto inSize = static_cast(llvm2eth(*_inSize)); auto outOff = static_cast(llvm2eth(*_outOff)); auto outSize = static_cast(llvm2eth(*_outSize)); - auto&& inRef = bytesConstRef(Runtime::getMemory().data() + inOff, inSize); - auto&& outRef = bytesConstRef(Runtime::getMemory().data() + outOff, outSize); + auto&& inRef = bytesConstRef(); //Runtime::getMemory().data() + inOff, inSize); + auto&& outRef = bytesConstRef(); // Runtime::getMemory().data() + outOff, outSize); OnOpFunc onOp{}; // TODO: Handle that thing auto codeAddress = right160(*_codeAddress); ret = ext.call(receiveAddress, value, inRef, &gas, outRef, onOp, {}, codeAddress); @@ -347,7 +348,7 @@ EXPORT void ext_sha3(i256* _inOff, i256* _inSize, i256* _ret) { auto inOff = static_cast(llvm2eth(*_inOff)); auto inSize = static_cast(llvm2eth(*_inSize)); - auto dataRef = bytesConstRef(Runtime::getMemory().data() + inOff, inSize); + auto dataRef = bytesConstRef(); // Runtime::getMemory().data() + inOff, inSize); auto hash = sha3(dataRef); *_ret = *reinterpret_cast(&hash); } diff --git a/libevmjit/Memory.cpp b/libevmjit/Memory.cpp index 23d027ba4..8d7674885 100644 --- a/libevmjit/Memory.cpp +++ b/libevmjit/Memory.cpp @@ -15,6 +15,7 @@ #include "Runtime.h" #include "GasMeter.h" #include "Endianness.h" +#include "Runtime.h" namespace dev { @@ -23,7 +24,7 @@ namespace eth namespace jit { -Memory::Memory(llvm::IRBuilder<>& _builder, GasMeter& _gasMeter): +Memory::Memory(llvm::IRBuilder<>& _builder, GasMeter& _gasMeter, RuntimeManager& _runtimeManager): CompilerHelper(_builder) { auto module = getModule(); @@ -45,18 +46,19 @@ Memory::Memory(llvm::IRBuilder<>& _builder, GasMeter& _gasMeter): m_returnDataSize = new llvm::GlobalVariable(*module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "mem_returnDataSize"); m_returnDataSize->setUnnamedAddr(true); // Address is not important - m_resize = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, Type::WordPtr, false), llvm::Function::ExternalLinkage, "mem_resize", module); + llvm::Type* resizeArgs[] = {RuntimeData::getType()->getPointerTo(), Type::WordPtr}; + m_resize = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, resizeArgs, false), llvm::Function::ExternalLinkage, "mem_resize", module); llvm::AttrBuilder attrBuilder; attrBuilder.addAttribute(llvm::Attribute::NoAlias).addAttribute(llvm::Attribute::NoCapture).addAttribute(llvm::Attribute::NonNull).addAttribute(llvm::Attribute::ReadOnly); m_resize->setAttributes(llvm::AttributeSet::get(m_resize->getContext(), 1, attrBuilder)); - m_require = createRequireFunc(_gasMeter); + m_require = createRequireFunc(_gasMeter, _runtimeManager); m_loadWord = createFunc(false, Type::i256, _gasMeter); m_storeWord = createFunc(true, Type::i256, _gasMeter); m_storeByte = createFunc(true, Type::Byte, _gasMeter); } -llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter) +llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _runtimeManager) { auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "mem.require", getModule()); @@ -83,7 +85,7 @@ llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter) _gasMeter.checkMemory(newWords, m_builder); // Resize m_builder.CreateStore(sizeRequired, m_size); - auto newData = m_builder.CreateCall(m_resize, m_size, "newData"); + auto newData = m_builder.CreateCall2(m_resize, _runtimeManager.getRuntimePtr(), m_size, "newData"); m_builder.CreateStore(newData, m_data); m_builder.CreateBr(returnBB); @@ -232,48 +234,36 @@ extern "C" using namespace dev::eth::jit; -EXPORT i256 mem_returnDataOffset; -EXPORT i256 mem_returnDataSize; - -EXPORT uint8_t* mem_resize(i256* _size) +EXPORT uint8_t* mem_resize(Runtime* _rt, i256* _size) { auto size = _size->a; // Trunc to 64-bit - auto& memory = Runtime::getMemory(); + auto& memory = _rt->getMemory(); memory.resize(size); return memory.data(); } EXPORT void evmccrt_memory_dump(uint64_t _begin, uint64_t _end) { - if (_end == 0) - _end = Runtime::getMemory().size(); - - std::cerr << "MEMORY: active size: " << std::dec - << Runtime::getMemory().size() / 32 << " words\n"; - std::cerr << "MEMORY: dump from " << std::dec - << _begin << " to " << _end << ":"; - if (_end <= _begin) - return; - - _begin = _begin / 16 * 16; - for (size_t i = _begin; i < _end; i++) - { - if ((i - _begin) % 16 == 0) - std::cerr << '\n' << std::dec << i << ": "; - - auto b = Runtime::getMemory()[i]; - std::cerr << std::hex << std::setw(2) << static_cast(b) << ' '; - } - std::cerr << std::endl; + //if (_end == 0) + // _end = Runtime::getMemory().size(); + + //std::cerr << "MEMORY: active size: " << std::dec + // << Runtime::getMemory().size() / 32 << " words\n"; + //std::cerr << "MEMORY: dump from " << std::dec + // << _begin << " to " << _end << ":"; + //if (_end <= _begin) + // return; + + //_begin = _begin / 16 * 16; + //for (size_t i = _begin; i < _end; i++) + //{ + // if ((i - _begin) % 16 == 0) + // std::cerr << '\n' << std::dec << i << ": "; + + // auto b = Runtime::getMemory()[i]; + // std::cerr << std::hex << std::setw(2) << static_cast(b) << ' '; + //} + //std::cerr << std::endl; } } // extern "C" - -dev::bytesConstRef dev::eth::jit::Memory::getReturnData() -{ - // TODO: Handle large indexes - auto offset = static_cast(llvm2eth(mem_returnDataOffset)); - auto size = static_cast(llvm2eth(mem_returnDataSize)); - auto& memory = Runtime::getMemory(); - return {memory.data() + offset, size}; -} diff --git a/libevmjit/Memory.h b/libevmjit/Memory.h index 2ab09c127..d92538247 100644 --- a/libevmjit/Memory.h +++ b/libevmjit/Memory.h @@ -10,11 +10,12 @@ namespace eth { namespace jit { +class RuntimeManager; class Memory : public CompilerHelper { public: - Memory(llvm::IRBuilder<>& _builder, class GasMeter& _gasMeter); + Memory(llvm::IRBuilder<>& _builder, class GasMeter& _gasMeter, RuntimeManager& _runtimeManager); llvm::Value* loadWord(llvm::Value* _addr); void storeWord(llvm::Value* _addr, llvm::Value* _word); @@ -31,13 +32,13 @@ public: void require(llvm::Value* _offset, llvm::Value* _size); void registerReturnData(llvm::Value* _index, llvm::Value* _size); - static bytesConstRef getReturnData(); + bytesConstRef getReturnData(); void dump(uint64_t _begin, uint64_t _end = 0); private: llvm::Function* createFunc(bool _isStore, llvm::Type* _type, GasMeter& _gasMeter); - llvm::Function* createRequireFunc(GasMeter& _gasMeter); + llvm::Function* createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _runtimeManager); private: llvm::GlobalVariable* m_data; diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index e37729e5b..37e414b17 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -29,7 +29,7 @@ llvm::StructType* RuntimeData::getType() return type; } -static Runtime* g_runtime; +static Runtime* g_runtime; // FIXME: Remove Runtime::Runtime(u256 _gas, ExtVMFace& _ext): m_ext(_ext) @@ -49,11 +49,6 @@ StackImpl& Runtime::getStack() return g_runtime->m_stack; } -MemoryImpl& Runtime::getMemory() -{ - return g_runtime->m_memory; -} - ExtVMFace& Runtime::getExt() { return g_runtime->m_ext; @@ -64,6 +59,19 @@ u256 Runtime::getGas() return llvm2eth(m_data.gas); } +extern "C" { + EXPORT i256 mem_returnDataOffset; // FIXME: Dis-globalize + EXPORT i256 mem_returnDataSize; +} + +bytesConstRef Runtime::getReturnData() +{ + // TODO: Handle large indexes + auto offset = static_cast(llvm2eth(mem_returnDataOffset)); + auto size = static_cast(llvm2eth(mem_returnDataSize)); + return{getMemory().data() + offset, size}; +} + RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder): CompilerHelper(_builder) { @@ -76,19 +84,21 @@ RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder): CompilerHelper(_bui m_builder.CreateStore(dataPtr, m_dataPtr); } +llvm::Value* RuntimeManager::getRuntimePtr() +{ + // TODO: If in main function - get it from param + return m_builder.CreateLoad(m_dataPtr); +} + llvm::Value* RuntimeManager::getGas() { - //auto gasPtr = m_builder.CreateConstGEP2_64(m_dataPtr, 0, 0); - auto rt = m_builder.CreateLoad(m_dataPtr); - auto gasPtr = m_builder.CreateStructGEP(rt, 0); + auto gasPtr = m_builder.CreateStructGEP(getRuntimePtr(), 0); return m_builder.CreateLoad(gasPtr, "gas"); } void RuntimeManager::setGas(llvm::Value* _gas) { - //auto gasPtr = m_builder.CreateStructGEP(m_dataPtr, 0); - auto rt = m_builder.CreateLoad(m_dataPtr); - auto gasPtr = m_builder.CreateStructGEP(rt, 0); + auto gasPtr = m_builder.CreateStructGEP(getRuntimePtr(), 0); m_builder.CreateStore(_gas, gasPtr); } diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index 418555c04..87f43f786 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -44,9 +44,10 @@ public: RuntimeData* getDataPtr() { return &m_data; } static StackImpl& getStack(); - static MemoryImpl& getMemory(); + MemoryImpl& getMemory() { return m_memory; } static ExtVMFace& getExt(); u256 getGas(); + bytesConstRef getReturnData(); private: @@ -62,6 +63,8 @@ class RuntimeManager: public CompilerHelper public: RuntimeManager(llvm::IRBuilder<>& _builder); + llvm::Value* getRuntimePtr(); + llvm::Value* getGas(); void setGas(llvm::Value* _gas); From f81971bae852f5aea0b3dfda60a9357b96a9622d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 12:16:33 +0100 Subject: [PATCH 219/641] Add Type::RuntimePtr predefined LLVM type --- libevmjit/Type.cpp | 4 ++++ libevmjit/Type.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/libevmjit/Type.cpp b/libevmjit/Type.cpp index baf458dbd..5021473ff 100644 --- a/libevmjit/Type.cpp +++ b/libevmjit/Type.cpp @@ -3,6 +3,8 @@ #include +#include "Runtime.h" + namespace dev { namespace eth @@ -18,6 +20,7 @@ llvm::IntegerType* Type::Byte; llvm::PointerType* Type::BytePtr; llvm::Type* Type::Void; llvm::IntegerType* Type::MainReturn; +llvm::PointerType* Type::RuntimePtr; void Type::init(llvm::LLVMContext& _context) { @@ -30,6 +33,7 @@ void Type::init(llvm::LLVMContext& _context) BytePtr = Byte->getPointerTo(); Void = llvm::Type::getVoidTy(_context); MainReturn = llvm::Type::getInt32Ty(_context); + RuntimePtr = RuntimeData::getType()->getPointerTo(); } llvm::ConstantInt* Constant::get(uint64_t _n) diff --git a/libevmjit/Type.h b/libevmjit/Type.h index 16a13c373..86915cd9e 100644 --- a/libevmjit/Type.h +++ b/libevmjit/Type.h @@ -30,6 +30,8 @@ struct Type /// Main function return type static llvm::IntegerType* MainReturn; + static llvm::PointerType* RuntimePtr; + static void init(llvm::LLVMContext& _context); }; From 0d4ca779ff7f4ad455d08fc0820d4a2552cf0dcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 12:17:04 +0100 Subject: [PATCH 220/641] Access stack structure through runtime structure [#81470252] --- libevmjit/Compiler.cpp | 2 +- libevmjit/Runtime.cpp | 4 ---- libevmjit/Runtime.h | 2 +- libevmjit/Stack.cpp | 44 ++++++++++++++++++++++++------------------ libevmjit/Stack.h | 4 +++- 5 files changed, 30 insertions(+), 26 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index c3c09384b..b20d5ae9c 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -181,7 +181,7 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) GasMeter gasMeter(m_builder, runtimeManager); Memory memory(m_builder, gasMeter, runtimeManager); Ext ext(m_builder); - Stack stack(m_builder); + Stack stack(m_builder, runtimeManager); m_builder.CreateBr(basicBlocks.begin()->second); diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 37e414b17..a41d5e296 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -44,10 +44,6 @@ Runtime::~Runtime() g_runtime = nullptr; } -StackImpl& Runtime::getStack() -{ - return g_runtime->m_stack; -} ExtVMFace& Runtime::getExt() { diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index 87f43f786..dc617b777 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -43,7 +43,7 @@ public: RuntimeData* getDataPtr() { return &m_data; } - static StackImpl& getStack(); + StackImpl& getStack() { return m_stack; } MemoryImpl& getMemory() { return m_memory; } static ExtVMFace& getExt(); u256 getGas(); diff --git a/libevmjit/Stack.cpp b/libevmjit/Stack.cpp index 89044bea8..6c287dc6a 100644 --- a/libevmjit/Stack.cpp +++ b/libevmjit/Stack.cpp @@ -14,8 +14,9 @@ namespace eth namespace jit { -Stack::Stack(llvm::IRBuilder<>& _builder) - : CompilerHelper(_builder) +Stack::Stack(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager) + : CompilerHelper(_builder), + m_runtimeManager(_runtimeManager) { m_arg = m_builder.CreateAlloca(Type::i256, nullptr, "stack.arg"); @@ -23,11 +24,16 @@ Stack::Stack(llvm::IRBuilder<>& _builder) using Linkage = GlobalValue::LinkageTypes; auto module = getModule(); - m_push = Function::Create(FunctionType::get(m_builder.getVoidTy(), Type::WordPtr, false), Linkage::ExternalLinkage, "stack_push", module); - m_pop = Function::Create(FunctionType::get(m_builder.getVoidTy(), Type::Size, false), Linkage::ExternalLinkage, "stack_pop", module); - llvm::Type* getSetArgTypes[] = {Type::Size, Type::WordPtr}; - m_get = Function::Create(FunctionType::get(m_builder.getVoidTy(), ArrayRef(getSetArgTypes), false), Linkage::ExternalLinkage, "stack_get", module); - m_set = Function::Create(FunctionType::get(m_builder.getVoidTy(), ArrayRef(getSetArgTypes), false), Linkage::ExternalLinkage, "stack_set", module); + + llvm::Type* pushArgTypes[] = {Type::RuntimePtr, Type::WordPtr}; + m_push = Function::Create(FunctionType::get(Type::Void, pushArgTypes, false), Linkage::ExternalLinkage, "stack_push", module); + + llvm::Type* popArgTypes[] = {Type::RuntimePtr, Type::Size}; + m_pop = Function::Create(FunctionType::get(Type::Void, popArgTypes, false), Linkage::ExternalLinkage, "stack_pop", module); + + llvm::Type* getSetArgTypes[] = {Type::RuntimePtr, Type::Size, Type::WordPtr}; + m_get = Function::Create(FunctionType::get(Type::Void, getSetArgTypes, false), Linkage::ExternalLinkage, "stack_get", module); + m_set = Function::Create(FunctionType::get(Type::Void, getSetArgTypes, false), Linkage::ExternalLinkage, "stack_set", module); } Stack::~Stack() @@ -35,25 +41,25 @@ Stack::~Stack() llvm::Value* Stack::get(size_t _index) { - m_builder.CreateCall2(m_get, llvm::ConstantInt::get(Type::Size, _index, false), m_arg); + m_builder.CreateCall3(m_get, m_runtimeManager.getRuntimePtr(), llvm::ConstantInt::get(Type::Size, _index, false), m_arg); return m_builder.CreateLoad(m_arg); } void Stack::set(size_t _index, llvm::Value* _value) { m_builder.CreateStore(_value, m_arg); - m_builder.CreateCall2(m_set, llvm::ConstantInt::get(Type::Size, _index, false), m_arg); + m_builder.CreateCall3(m_set, m_runtimeManager.getRuntimePtr(), llvm::ConstantInt::get(Type::Size, _index, false), m_arg); } void Stack::pop(size_t _count) { - m_builder.CreateCall(m_pop, llvm::ConstantInt::get(Type::Size, _count, false)); + m_builder.CreateCall2(m_pop, m_runtimeManager.getRuntimePtr(), llvm::ConstantInt::get(Type::Size, _count, false)); } void Stack::push(llvm::Value* _value) { m_builder.CreateStore(_value, m_arg); - m_builder.CreateCall(m_push, m_arg); + m_builder.CreateCall2(m_push, m_runtimeManager.getRuntimePtr(), m_arg); } @@ -70,27 +76,27 @@ using namespace dev::eth::jit; extern std::jmp_buf* rt_jmpBuf; -EXPORT void stack_pop(uint64_t _count) +EXPORT void stack_pop(Runtime* _rt, uint64_t _count) { - auto& stack = Runtime::getStack(); + auto& stack = _rt->getStack(); if (stack.size() < _count) longjmp(*rt_jmpBuf, static_cast(ReturnCode::StackTooSmall)); stack.erase(stack.end() - _count, stack.end()); } -EXPORT void stack_push(i256* _word) +EXPORT void stack_push(Runtime* _rt, i256* _word) { - auto& stack = Runtime::getStack(); + auto& stack = _rt->getStack(); stack.push_back(*_word); if (stack.size() > Stack::maxStackSize) Stack::maxStackSize = stack.size(); } -EXPORT void stack_get(uint64_t _index, i256* _ret) +EXPORT void stack_get(Runtime* _rt, uint64_t _index, i256* _ret) { - auto& stack = Runtime::getStack(); + auto& stack = _rt->getStack(); // TODO: encode _index and stack size in the return code if (stack.size() <= _index) longjmp(*rt_jmpBuf, static_cast(ReturnCode::StackTooSmall)); @@ -98,9 +104,9 @@ EXPORT void stack_get(uint64_t _index, i256* _ret) *_ret = *(stack.rbegin() + _index); } -EXPORT void stack_set(uint64_t _index, i256* _word) +EXPORT void stack_set(Runtime* _rt, uint64_t _index, i256* _word) { - auto& stack = Runtime::getStack(); + auto& stack = _rt->getStack(); // TODO: encode _index and stack size in the return code if (stack.size() <= _index) longjmp(*rt_jmpBuf, static_cast(ReturnCode::StackTooSmall)); diff --git a/libevmjit/Stack.h b/libevmjit/Stack.h index 2380b2a15..db9032ec4 100644 --- a/libevmjit/Stack.h +++ b/libevmjit/Stack.h @@ -10,12 +10,13 @@ namespace eth { namespace jit { +class RuntimeManager; class Stack : public CompilerHelper { public: - Stack(llvm::IRBuilder<>& builder); + Stack(llvm::IRBuilder<>& builder, RuntimeManager& runtimeManager); virtual ~Stack(); llvm::Value* get(size_t _index); @@ -26,6 +27,7 @@ public: static size_t maxStackSize; private: + RuntimeManager& m_runtimeManager; llvm::Function* m_push; llvm::Function* m_pop; From 5d3afa175606067fae4c37e441b80a295386a99d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 12:19:02 +0100 Subject: [PATCH 221/641] Use Type::RuntimePtr instead of RuntimeData::getType->getPointerTo() --- libevmjit/Compiler.cpp | 2 +- libevmjit/Memory.cpp | 2 +- libevmjit/Runtime.cpp | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index b20d5ae9c..5061dabb0 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -166,7 +166,7 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) auto module = std::make_unique("main", m_builder.getContext()); // Create main function - llvm::Type* mainFuncArgTypes[] = {m_builder.getInt32Ty(), RuntimeData::getType()->getPointerTo()}; // There must be int in first place because LLVM does not support other signatures + llvm::Type* mainFuncArgTypes[] = {m_builder.getInt32Ty(), Type::RuntimePtr}; // There must be int in first place because LLVM does not support other signatures auto mainFuncType = llvm::FunctionType::get(Type::MainReturn, mainFuncArgTypes, false); m_mainFunc = llvm::Function::Create(mainFuncType, llvm::Function::ExternalLinkage, "main", module.get()); diff --git a/libevmjit/Memory.cpp b/libevmjit/Memory.cpp index 8d7674885..fa5a2b0dd 100644 --- a/libevmjit/Memory.cpp +++ b/libevmjit/Memory.cpp @@ -46,7 +46,7 @@ Memory::Memory(llvm::IRBuilder<>& _builder, GasMeter& _gasMeter, RuntimeManager& m_returnDataSize = new llvm::GlobalVariable(*module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "mem_returnDataSize"); m_returnDataSize->setUnnamedAddr(true); // Address is not important - llvm::Type* resizeArgs[] = {RuntimeData::getType()->getPointerTo(), Type::WordPtr}; + llvm::Type* resizeArgs[] = {Type::RuntimePtr, Type::WordPtr}; m_resize = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, resizeArgs, false), llvm::Function::ExternalLinkage, "mem_resize", module); llvm::AttrBuilder attrBuilder; attrBuilder.addAttribute(llvm::Attribute::NoAlias).addAttribute(llvm::Attribute::NoCapture).addAttribute(llvm::Attribute::NonNull).addAttribute(llvm::Attribute::ReadOnly); diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index a41d5e296..e09db52c9 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -71,8 +71,7 @@ bytesConstRef Runtime::getReturnData() RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder): CompilerHelper(_builder) { - auto dataPtrType = RuntimeData::getType()->getPointerTo(); - m_dataPtr = new llvm::GlobalVariable(*getModule(), dataPtrType, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(dataPtrType), "rt"); + m_dataPtr = new llvm::GlobalVariable(*getModule(), Type::RuntimePtr, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::RuntimePtr), "rt"); // Export data auto mainFunc = getMainFunction(); From 7ec7977fc457952f9a8ec8b4f50542ca7619f154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 12:42:32 +0100 Subject: [PATCH 222/641] Introducing RuntimeHelper - a compiler helper that depends on runtime data [#81470252] --- libevmjit/CompilerHelper.cpp | 8 ++++++++ libevmjit/CompilerHelper.h | 17 +++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/libevmjit/CompilerHelper.cpp b/libevmjit/CompilerHelper.cpp index b919043f2..c2d612c66 100644 --- a/libevmjit/CompilerHelper.cpp +++ b/libevmjit/CompilerHelper.cpp @@ -3,6 +3,8 @@ #include +#include "Runtime.h" + namespace dev { namespace eth @@ -29,6 +31,12 @@ llvm::Function* CompilerHelper::getMainFunction() return mainFunc; } + +RuntimeHelper::RuntimeHelper(RuntimeManager& _runtimeManager): + CompilerHelper(_runtimeManager.getBuilder()), + m_runtimeManager(_runtimeManager) +{} + } } } diff --git a/libevmjit/CompilerHelper.h b/libevmjit/CompilerHelper.h index 23bbcbd11..cf83d70cd 100644 --- a/libevmjit/CompilerHelper.h +++ b/libevmjit/CompilerHelper.h @@ -10,6 +10,7 @@ namespace eth { namespace jit { +class RuntimeManager; /// Base class for compiler helpers like Memory, GasMeter, etc. class CompilerHelper @@ -28,6 +29,22 @@ protected: /// Reference to parent compiler IR builder llvm::IRBuilder<>& m_builder; + llvm::IRBuilder<>& getBuilder() { return m_builder; } + + friend class RuntimeHelper; +}; + + +/// Compiler helper that depends on runtime data +class RuntimeHelper : public CompilerHelper +{ +protected: + RuntimeHelper(RuntimeManager& _runtimeManager); + + RuntimeManager& getRuntimeManager() { return m_runtimeManager; } + +private: + RuntimeManager& m_runtimeManager; }; From c7ccf546fcc75360d30b710f4c5f2bce66fd5bb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 14:18:39 +0100 Subject: [PATCH 223/641] Moving ADDRESS data from Ext to Runtime [#81470252] --- libevmjit/Compiler.cpp | 6 +++--- libevmjit/Ext.cpp | 8 +++----- libevmjit/Ext.h | 5 ++--- libevmjit/Runtime.cpp | 33 +++++++++++++++++++++++---------- libevmjit/Runtime.h | 19 +++++++++++++++---- 5 files changed, 46 insertions(+), 25 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 5061dabb0..26d5c6f19 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -180,7 +180,7 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) RuntimeManager runtimeManager(m_builder); GasMeter gasMeter(m_builder, runtimeManager); Memory memory(m_builder, gasMeter, runtimeManager); - Ext ext(m_builder); + Ext ext(runtimeManager); Stack stack(m_builder, runtimeManager); m_builder.CreateBr(basicBlocks.begin()->second); @@ -686,7 +686,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, case Instruction::ADDRESS: { - auto value = ext.address(); + auto value = _runtimeManager.get(RuntimeData::Address); stack.push(value); break; } @@ -873,7 +873,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto receiveAddress = codeAddress; if (inst == Instruction::CALLCODE) - receiveAddress = ext.address(); + receiveAddress = _runtimeManager.get(RuntimeData::Address); auto ret = ext.call(gas, receiveAddress, value, inOff, inSize, outOff, outSize, codeAddress); gasMeter.giveBack(gas); diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 07023c674..2e38aef27 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -44,10 +44,10 @@ struct ExtData const byte* code; }; -Ext::Ext(llvm::IRBuilder<>& _builder): - CompilerHelper(_builder) +Ext::Ext(RuntimeManager& _runtimeManager): + RuntimeHelper(_runtimeManager) { - auto&& ctx = _builder.getContext(); + auto&& ctx = m_builder.getContext(); auto module = getModule(); auto i256Ty = m_builder.getIntNTy(256); @@ -126,7 +126,6 @@ Value* Ext::getDataElem(unsigned _index, const Twine& _name) return m_builder.CreateLoad(valuePtr); } -Value* Ext::address() { return getDataElem(0, "address"); } Value* Ext::caller() { return getDataElem(1, "caller"); } Value* Ext::origin() { return getDataElem(2, "origin"); } Value* Ext::callvalue() { return getDataElem(3, "callvalue"); } @@ -243,7 +242,6 @@ using namespace dev::eth::jit; EXPORT void ext_init(ExtData* _extData) { auto&& ext = Runtime::getExt(); - _extData->address = eth2llvm(fromAddress(ext.myAddress)); _extData->caller = eth2llvm(fromAddress(ext.caller)); _extData->origin = eth2llvm(fromAddress(ext.origin)); _extData->callvalue = eth2llvm(ext.value); diff --git a/libevmjit/Ext.h b/libevmjit/Ext.h index 361b6e47e..6d8501d29 100644 --- a/libevmjit/Ext.h +++ b/libevmjit/Ext.h @@ -12,15 +12,14 @@ namespace eth namespace jit { -class Ext : public CompilerHelper +class Ext : public RuntimeHelper { public: - Ext(llvm::IRBuilder<>& _builder); + Ext(RuntimeManager& _runtimeManager); llvm::Value* store(llvm::Value* _index); void setStore(llvm::Value* _index, llvm::Value* _value); - llvm::Value* address(); llvm::Value* caller(); llvm::Value* origin(); llvm::Value* callvalue(); diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index e09db52c9..bf231cc10 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -22,7 +22,7 @@ llvm::StructType* RuntimeData::getType() { llvm::Type* elems[] = { - Type::i256, + llvm::ArrayType::get(Type::i256, _size) }; type = llvm::StructType::create(elems, "RuntimeData"); } @@ -36,7 +36,8 @@ Runtime::Runtime(u256 _gas, ExtVMFace& _ext): { assert(!g_runtime); g_runtime = this; - m_data.gas = eth2llvm(_gas); + set(RuntimeData::Gas, _gas); + set(RuntimeData::Address, fromAddress(_ext.myAddress)); } Runtime::~Runtime() @@ -44,15 +45,20 @@ Runtime::~Runtime() g_runtime = nullptr; } +void Runtime::set(RuntimeData::Index _index, u256 _value) +{ + m_data.elems[_index] = eth2llvm(_value); +} + ExtVMFace& Runtime::getExt() { return g_runtime->m_ext; } -u256 Runtime::getGas() +u256 Runtime::getGas() const { - return llvm2eth(m_data.gas); + return llvm2eth(m_data.elems[RuntimeData::Gas]); } extern "C" { @@ -60,12 +66,12 @@ extern "C" { EXPORT i256 mem_returnDataSize; } -bytesConstRef Runtime::getReturnData() +bytesConstRef Runtime::getReturnData() const { // TODO: Handle large indexes auto offset = static_cast(llvm2eth(mem_returnDataOffset)); auto size = static_cast(llvm2eth(mem_returnDataSize)); - return{getMemory().data() + offset, size}; + return {m_memory.data() + offset, size}; } @@ -85,16 +91,23 @@ llvm::Value* RuntimeManager::getRuntimePtr() return m_builder.CreateLoad(m_dataPtr); } +llvm::Value* RuntimeManager::get(RuntimeData::Index _index) +{ + llvm::Value* idxList[] = {m_builder.getInt32(0), m_builder.getInt32(0), m_builder.getInt32(_index)}; + auto ptr = m_builder.CreateInBoundsGEP(getRuntimePtr(), idxList, "dataElemPtr"); + return m_builder.CreateLoad(ptr); +} + llvm::Value* RuntimeManager::getGas() { - auto gasPtr = m_builder.CreateStructGEP(getRuntimePtr(), 0); - return m_builder.CreateLoad(gasPtr, "gas"); + return get(RuntimeData::Gas); } void RuntimeManager::setGas(llvm::Value* _gas) { - auto gasPtr = m_builder.CreateStructGEP(getRuntimePtr(), 0); - m_builder.CreateStore(_gas, gasPtr); + llvm::Value* idxList[] = {m_builder.getInt32(0), m_builder.getInt32(0), m_builder.getInt32(RuntimeData::Gas)}; + auto ptr = m_builder.CreateInBoundsGEP(getRuntimePtr(), idxList, "gasPtr"); + m_builder.CreateStore(_gas, ptr); } } diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index dc617b777..8b2efe8ed 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -24,9 +24,17 @@ namespace jit struct RuntimeData { - static llvm::StructType* getType(); + enum Index: unsigned + { + Gas, + Address, + + _size + }; + + i256 elems[_size]; - i256 gas; + static llvm::StructType* getType(); }; using StackImpl = std::vector; @@ -46,10 +54,12 @@ public: StackImpl& getStack() { return m_stack; } MemoryImpl& getMemory() { return m_memory; } static ExtVMFace& getExt(); - u256 getGas(); - bytesConstRef getReturnData(); + + u256 getGas() const; + bytesConstRef getReturnData() const; private: + void set(RuntimeData::Index _index, u256 _value); /// @internal Must be the first element to asure Runtime* === RuntimeData* RuntimeData m_data; @@ -65,6 +75,7 @@ public: llvm::Value* getRuntimePtr(); + llvm::Value* get(RuntimeData::Index _index); llvm::Value* getGas(); void setGas(llvm::Value* _gas); From 669612cdcf3b6e5e833564a473b60468b65d71a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 14:30:36 +0100 Subject: [PATCH 224/641] Add name to data indices [#81470252] --- libevmjit/Runtime.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index bf231cc10..779ffe8a9 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -29,6 +29,19 @@ llvm::StructType* RuntimeData::getType() return type; } +namespace +{ +llvm::Twine getName(RuntimeData::Index _index) +{ + switch (_index) + { + default: return "data"; + case RuntimeData::Gas: return "gas"; + case RuntimeData::Address: return "address"; + } +} +} + static Runtime* g_runtime; // FIXME: Remove Runtime::Runtime(u256 _gas, ExtVMFace& _ext): @@ -94,8 +107,8 @@ llvm::Value* RuntimeManager::getRuntimePtr() llvm::Value* RuntimeManager::get(RuntimeData::Index _index) { llvm::Value* idxList[] = {m_builder.getInt32(0), m_builder.getInt32(0), m_builder.getInt32(_index)}; - auto ptr = m_builder.CreateInBoundsGEP(getRuntimePtr(), idxList, "dataElemPtr"); - return m_builder.CreateLoad(ptr); + auto ptr = m_builder.CreateInBoundsGEP(getRuntimePtr(), idxList, getName(_index) + "Ptr"); + return m_builder.CreateLoad(ptr, getName(_index)); } llvm::Value* RuntimeManager::getGas() From ae89279c1af56ee01b7b76eff7691cc73ff4fc50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 14:42:47 +0100 Subject: [PATCH 225/641] Moving ORIGIN, CALLER & CALLVALUE data from Ext to Runtime [#81470252] --- libevmjit/Compiler.cpp | 6 +++--- libevmjit/Ext.cpp | 36 +++++++++++------------------------- libevmjit/Ext.h | 3 --- libevmjit/Runtime.cpp | 12 +++++++++--- libevmjit/Runtime.h | 3 +++ 5 files changed, 26 insertions(+), 34 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 26d5c6f19..ccdc21e39 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -701,21 +701,21 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, case Instruction::CALLER: { - auto value = ext.caller(); + auto value = _runtimeManager.get(RuntimeData::Caller); stack.push(value); break; } case Instruction::ORIGIN: { - auto value = ext.origin(); + auto value = _runtimeManager.get(RuntimeData::Origin); stack.push(value); break; } case Instruction::CALLVALUE: { - auto value = ext.callvalue(); + auto value = _runtimeManager.get(RuntimeData::CallValue); stack.push(value); break; } diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 2e38aef27..741bd9993 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -27,10 +27,6 @@ inline u256 fromAddress(Address _a) struct ExtData { - i256 address; - i256 caller; - i256 origin; - i256 callvalue; i256 calldatasize; i256 gasprice; i256 prevhash; @@ -65,10 +61,6 @@ Ext::Ext(RuntimeManager& _runtimeManager): m_arg8 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg8"); Type* elements[] = { - i256Ty, // i256 address; - i256Ty, // i256 caller; - i256Ty, // i256 origin; - i256Ty, // i256 callvalue; i256Ty, // i256 calldatasize; i256Ty, // i256 gasprice; i256Ty, // i256 prevhash; @@ -126,20 +118,17 @@ Value* Ext::getDataElem(unsigned _index, const Twine& _name) return m_builder.CreateLoad(valuePtr); } -Value* Ext::caller() { return getDataElem(1, "caller"); } -Value* Ext::origin() { return getDataElem(2, "origin"); } -Value* Ext::callvalue() { return getDataElem(3, "callvalue"); } -Value* Ext::calldatasize() { return getDataElem(4, "calldatasize"); } -Value* Ext::gasprice() { return getDataElem(5, "gasprice"); } -Value* Ext::prevhash() { return getDataElem(6, "prevhash"); } -Value* Ext::coinbase() { return getDataElem(7, "coinbase"); } -Value* Ext::timestamp() { return getDataElem(8, "timestamp"); } -Value* Ext::number() { return getDataElem(9, "number"); } -Value* Ext::difficulty() { return getDataElem(10, "difficulty"); } -Value* Ext::gaslimit() { return getDataElem(11, "gaslimit"); } -Value* Ext::codesize() { return getDataElem(12, "codesize"); } -Value* Ext::calldata() { return getDataElem(13, "calldata"); } -Value* Ext::code() { return getDataElem(14, "code"); } +Value* Ext::calldatasize() { return getDataElem(0, "calldatasize"); } +Value* Ext::gasprice() { return getDataElem(1, "gasprice"); } +Value* Ext::prevhash() { return getDataElem(2, "prevhash"); } +Value* Ext::coinbase() { return getDataElem(3, "coinbase"); } +Value* Ext::timestamp() { return getDataElem(4, "timestamp"); } +Value* Ext::number() { return getDataElem(5, "number"); } +Value* Ext::difficulty() { return getDataElem(6, "difficulty"); } +Value* Ext::gaslimit() { return getDataElem(7, "gaslimit"); } +Value* Ext::codesize() { return getDataElem(8, "codesize"); } +Value* Ext::calldata() { return getDataElem(9, "calldata"); } +Value* Ext::code() { return getDataElem(10, "code"); } Value* Ext::calldataload(Value* _index) { @@ -242,9 +231,6 @@ using namespace dev::eth::jit; EXPORT void ext_init(ExtData* _extData) { auto&& ext = Runtime::getExt(); - _extData->caller = eth2llvm(fromAddress(ext.caller)); - _extData->origin = eth2llvm(fromAddress(ext.origin)); - _extData->callvalue = eth2llvm(ext.value); _extData->gasprice = eth2llvm(ext.gasPrice); _extData->calldatasize = eth2llvm(ext.data.size()); _extData->prevhash = eth2llvm(ext.previousBlock.hash); diff --git a/libevmjit/Ext.h b/libevmjit/Ext.h index 6d8501d29..5585f9d05 100644 --- a/libevmjit/Ext.h +++ b/libevmjit/Ext.h @@ -20,9 +20,6 @@ public: llvm::Value* store(llvm::Value* _index); void setStore(llvm::Value* _index, llvm::Value* _value); - llvm::Value* caller(); - llvm::Value* origin(); - llvm::Value* callvalue(); llvm::Value* calldatasize(); llvm::Value* gasprice(); llvm::Value* prevhash(); diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 779ffe8a9..374398b69 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -35,9 +35,12 @@ llvm::Twine getName(RuntimeData::Index _index) { switch (_index) { - default: return "data"; - case RuntimeData::Gas: return "gas"; - case RuntimeData::Address: return "address"; + default: return "data"; + case RuntimeData::Gas: return "gas"; + case RuntimeData::Address: return "address"; + case RuntimeData::Caller: return "caller"; + case RuntimeData::Origin: return "origin"; + case RuntimeData::CallValue: return "callvalue"; } } } @@ -51,6 +54,9 @@ Runtime::Runtime(u256 _gas, ExtVMFace& _ext): g_runtime = this; set(RuntimeData::Gas, _gas); set(RuntimeData::Address, fromAddress(_ext.myAddress)); + set(RuntimeData::Caller, fromAddress(_ext.caller)); + set(RuntimeData::Origin, fromAddress(_ext.origin)); + set(RuntimeData::CallValue, _ext.value); } Runtime::~Runtime() diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index 8b2efe8ed..3300b4106 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -28,6 +28,9 @@ struct RuntimeData { Gas, Address, + Caller, + Origin, + CallValue, _size }; From 6facdd0df6ba67c0ee0b48ec2905a06ce644aac5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 15:05:21 +0100 Subject: [PATCH 226/641] Moving the rest word-size data from Ext to Runtime [#81470252] --- libevmjit/Compiler.cpp | 24 ++++++++++++------------ libevmjit/Ext.cpp | 40 ++-------------------------------------- libevmjit/Ext.h | 9 --------- libevmjit/Runtime.cpp | 18 ++++++++++++++++++ libevmjit/Runtime.h | 9 +++++++++ 5 files changed, 41 insertions(+), 59 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index ccdc21e39..e711fe706 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -722,14 +722,14 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, case Instruction::CALLDATASIZE: { - auto value = ext.calldatasize(); + auto value = _runtimeManager.get(RuntimeData::CallDataSize); stack.push(value); break; } case Instruction::CODESIZE: { - auto value = ext.codesize(); + auto value = _runtimeManager.get(RuntimeData::CodeSize); stack.push(value); break; } @@ -749,7 +749,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto reqBytes = stack.pop(); auto srcPtr = ext.calldata(); - auto srcSize = ext.calldatasize(); + auto srcSize = _runtimeManager.get(RuntimeData::CallDataSize); memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); break; @@ -762,7 +762,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto reqBytes = stack.pop(); auto srcPtr = ext.code(); // TODO: Code & its size are constants, feature #80814234 - auto srcSize = ext.codesize(); + auto srcSize = _runtimeManager.get(RuntimeData::CodeSize); memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); break; @@ -791,50 +791,50 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, } case Instruction::GASPRICE: - { - auto value = ext.gasprice(); + { + auto value = _runtimeManager.get(RuntimeData::GasPrice); stack.push(value); break; } case Instruction::PREVHASH: { - auto value = ext.prevhash(); + auto value = _runtimeManager.get(RuntimeData::PrevHash); stack.push(value); break; } case Instruction::COINBASE: { - auto value = ext.coinbase(); + auto value = _runtimeManager.get(RuntimeData::CoinBase); stack.push(value); break; } case Instruction::TIMESTAMP: { - auto value = ext.timestamp(); + auto value = _runtimeManager.get(RuntimeData::TimeStamp); stack.push(value); break; } case Instruction::NUMBER: { - auto value = ext.number(); + auto value = _runtimeManager.get(RuntimeData::Number); stack.push(value); break; } case Instruction::DIFFICULTY: { - auto value = ext.difficulty(); + auto value = _runtimeManager.get(RuntimeData::Difficulty); stack.push(value); break; } case Instruction::GASLIMIT: { - auto value = ext.gaslimit(); + auto value = _runtimeManager.get(RuntimeData::GasLimit); stack.push(value); break; } diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 741bd9993..1adaf741c 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -27,15 +27,6 @@ inline u256 fromAddress(Address _a) struct ExtData { - i256 calldatasize; - i256 gasprice; - i256 prevhash; - i256 coinbase; - i256 timestamp; - i256 number; - i256 difficulty; - i256 gaslimit; - i256 codesize; const byte* calldata; const byte* code; }; @@ -61,15 +52,6 @@ Ext::Ext(RuntimeManager& _runtimeManager): m_arg8 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg8"); Type* elements[] = { - i256Ty, // i256 calldatasize; - i256Ty, // i256 gasprice; - i256Ty, // i256 prevhash; - i256Ty, // i256 coinbase; - i256Ty, // i256 timestamp; - i256Ty, // i256 number; - i256Ty, // i256 difficulty; - i256Ty, // i256 gaslimit; - i256Ty, // i256 codesize i8PtrTy, // byte* calldata i8PtrTy, // byte* code @@ -118,17 +100,8 @@ Value* Ext::getDataElem(unsigned _index, const Twine& _name) return m_builder.CreateLoad(valuePtr); } -Value* Ext::calldatasize() { return getDataElem(0, "calldatasize"); } -Value* Ext::gasprice() { return getDataElem(1, "gasprice"); } -Value* Ext::prevhash() { return getDataElem(2, "prevhash"); } -Value* Ext::coinbase() { return getDataElem(3, "coinbase"); } -Value* Ext::timestamp() { return getDataElem(4, "timestamp"); } -Value* Ext::number() { return getDataElem(5, "number"); } -Value* Ext::difficulty() { return getDataElem(6, "difficulty"); } -Value* Ext::gaslimit() { return getDataElem(7, "gaslimit"); } -Value* Ext::codesize() { return getDataElem(8, "codesize"); } -Value* Ext::calldata() { return getDataElem(9, "calldata"); } -Value* Ext::code() { return getDataElem(10, "code"); } +Value* Ext::calldata() { return getDataElem(0, "calldata"); } +Value* Ext::code() { return getDataElem(1, "code"); } Value* Ext::calldataload(Value* _index) { @@ -231,15 +204,6 @@ using namespace dev::eth::jit; EXPORT void ext_init(ExtData* _extData) { auto&& ext = Runtime::getExt(); - _extData->gasprice = eth2llvm(ext.gasPrice); - _extData->calldatasize = eth2llvm(ext.data.size()); - _extData->prevhash = eth2llvm(ext.previousBlock.hash); - _extData->coinbase = eth2llvm(fromAddress(ext.currentBlock.coinbaseAddress)); - _extData->timestamp = eth2llvm(ext.currentBlock.timestamp); - _extData->number = eth2llvm(ext.currentBlock.number); - _extData->difficulty = eth2llvm(ext.currentBlock.difficulty); - _extData->gaslimit = eth2llvm(ext.currentBlock.gasLimit); - _extData->codesize = eth2llvm(ext.code.size()); _extData->calldata = ext.data.data(); _extData->code = ext.code.data(); } diff --git a/libevmjit/Ext.h b/libevmjit/Ext.h index 5585f9d05..62938f3cb 100644 --- a/libevmjit/Ext.h +++ b/libevmjit/Ext.h @@ -20,15 +20,6 @@ public: llvm::Value* store(llvm::Value* _index); void setStore(llvm::Value* _index, llvm::Value* _value); - llvm::Value* calldatasize(); - llvm::Value* gasprice(); - llvm::Value* prevhash(); - llvm::Value* coinbase(); - llvm::Value* timestamp(); - llvm::Value* number(); - llvm::Value* difficulty(); - llvm::Value* gaslimit(); - llvm::Value* codesize(); llvm::Value* calldata(); llvm::Value* code(); diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 374398b69..42d2fe52f 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -41,6 +41,15 @@ llvm::Twine getName(RuntimeData::Index _index) case RuntimeData::Caller: return "caller"; case RuntimeData::Origin: return "origin"; case RuntimeData::CallValue: return "callvalue"; + case RuntimeData::CallDataSize: return "calldatasize"; + case RuntimeData::GasPrice: return "gasprice"; + case RuntimeData::PrevHash: return "prevhash"; + case RuntimeData::CoinBase: return "coinbase"; + case RuntimeData::TimeStamp: return "timestamp"; + case RuntimeData::Number: return "number"; + case RuntimeData::Difficulty: return "difficulty"; + case RuntimeData::GasLimit: return "gaslimit"; + case RuntimeData::CodeSize: return "codesize"; } } } @@ -57,6 +66,15 @@ Runtime::Runtime(u256 _gas, ExtVMFace& _ext): set(RuntimeData::Caller, fromAddress(_ext.caller)); set(RuntimeData::Origin, fromAddress(_ext.origin)); set(RuntimeData::CallValue, _ext.value); + set(RuntimeData::CallDataSize, _ext.data.size()); + set(RuntimeData::GasPrice, _ext.gasPrice); + set(RuntimeData::PrevHash, _ext.previousBlock.hash); + set(RuntimeData::CoinBase, fromAddress(_ext.currentBlock.coinbaseAddress)); + set(RuntimeData::TimeStamp, _ext.currentBlock.timestamp); + set(RuntimeData::Number, _ext.currentBlock.number); + set(RuntimeData::Difficulty, _ext.currentBlock.difficulty); + set(RuntimeData::GasLimit, _ext.currentBlock.gasLimit); + set(RuntimeData::CodeSize, _ext.code.size()); // TODO: Use constant } Runtime::~Runtime() diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index 3300b4106..478c212b1 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -31,6 +31,15 @@ struct RuntimeData Caller, Origin, CallValue, + CallDataSize, + GasPrice, + PrevHash, + CoinBase, + TimeStamp, + Number, + Difficulty, + GasLimit, + CodeSize, _size }; From 356f6609d58cdd52fe6ac04fcbb1603c7169016c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 15:21:47 +0100 Subject: [PATCH 227/641] Group instructions that access runtime data [#81470252] --- libevmjit/Compiler.cpp | 103 ++++++----------------------------------- libevmjit/Runtime.cpp | 22 +++++++++ libevmjit/Runtime.h | 1 + 3 files changed, 36 insertions(+), 90 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index e711fe706..7f6aba051 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -679,57 +679,29 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, } case Instruction::GAS: - { - stack.push(_runtimeManager.getGas()); - break; - } - case Instruction::ADDRESS: - { - auto value = _runtimeManager.get(RuntimeData::Address); - stack.push(value); - break; - } - - case Instruction::BALANCE: - { - auto address = stack.pop(); - auto value = ext.balance(address); - stack.push(value); - break; - } - case Instruction::CALLER: - { - auto value = _runtimeManager.get(RuntimeData::Caller); - stack.push(value); - break; - } - case Instruction::ORIGIN: - { - auto value = _runtimeManager.get(RuntimeData::Origin); - stack.push(value); - break; - } - case Instruction::CALLVALUE: - { - auto value = _runtimeManager.get(RuntimeData::CallValue); - stack.push(value); - break; - } - case Instruction::CALLDATASIZE: + case Instruction::CODESIZE: + case Instruction::GASPRICE: + case Instruction::PREVHASH: + case Instruction::COINBASE: + case Instruction::TIMESTAMP: + case Instruction::NUMBER: + case Instruction::DIFFICULTY: + case Instruction::GASLIMIT: { - auto value = _runtimeManager.get(RuntimeData::CallDataSize); - stack.push(value); + // Pushes an element of runtime data on stack + stack.push(_runtimeManager.get(inst)); break; } - case Instruction::CODESIZE: + case Instruction::BALANCE: { - auto value = _runtimeManager.get(RuntimeData::CodeSize); + auto address = stack.pop(); + auto value = ext.balance(address); stack.push(value); break; } @@ -790,55 +762,6 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, break; } - case Instruction::GASPRICE: - { - auto value = _runtimeManager.get(RuntimeData::GasPrice); - stack.push(value); - break; - } - - case Instruction::PREVHASH: - { - auto value = _runtimeManager.get(RuntimeData::PrevHash); - stack.push(value); - break; - } - - case Instruction::COINBASE: - { - auto value = _runtimeManager.get(RuntimeData::CoinBase); - stack.push(value); - break; - } - - case Instruction::TIMESTAMP: - { - auto value = _runtimeManager.get(RuntimeData::TimeStamp); - stack.push(value); - break; - } - - case Instruction::NUMBER: - { - auto value = _runtimeManager.get(RuntimeData::Number); - stack.push(value); - break; - } - - case Instruction::DIFFICULTY: - { - auto value = _runtimeManager.get(RuntimeData::Difficulty); - stack.push(value); - break; - } - - case Instruction::GASLIMIT: - { - auto value = _runtimeManager.get(RuntimeData::GasLimit); - stack.push(value); - break; - } - case Instruction::CREATE: { auto endowment = stack.pop(); diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 42d2fe52f..21fcfaddb 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -135,6 +135,28 @@ llvm::Value* RuntimeManager::get(RuntimeData::Index _index) return m_builder.CreateLoad(ptr, getName(_index)); } +llvm::Value* RuntimeManager::get(Instruction _inst) +{ + switch (_inst) + { + default: assert(false); return nullptr; + case Instruction::GAS: return get(RuntimeData::Gas); + case Instruction::ADDRESS: return get(RuntimeData::Address); + case Instruction::CALLER: return get(RuntimeData::Caller); + case Instruction::ORIGIN: return get(RuntimeData::Origin); + case Instruction::CALLVALUE: return get(RuntimeData::CallValue); + case Instruction::CALLDATASIZE: return get(RuntimeData::CallDataSize); + case Instruction::GASPRICE: return get(RuntimeData::GasPrice); + case Instruction::PREVHASH: return get(RuntimeData::PrevHash); + case Instruction::COINBASE: return get(RuntimeData::CoinBase); + case Instruction::TIMESTAMP: return get(RuntimeData::TimeStamp); + case Instruction::NUMBER: return get(RuntimeData::Number); + case Instruction::DIFFICULTY: return get(RuntimeData::Difficulty); + case Instruction::GASLIMIT: return get(RuntimeData::GasLimit); + case Instruction::CODESIZE: return get(RuntimeData::CodeSize); + } +} + llvm::Value* RuntimeManager::getGas() { return get(RuntimeData::Gas); diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index 478c212b1..a4bb89427 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -88,6 +88,7 @@ public: llvm::Value* getRuntimePtr(); llvm::Value* get(RuntimeData::Index _index); + llvm::Value* get(Instruction _inst); llvm::Value* getGas(); void setGas(llvm::Value* _gas); From f12620d6d8d0a3e9d91432267dc23e88f1c052df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 16:00:41 +0100 Subject: [PATCH 228/641] Moving CALLDATA data from Ext to Runtime [#81470252] --- libevmjit/Compiler.cpp | 2 +- libevmjit/Ext.cpp | 4 +--- libevmjit/Ext.h | 1 - libevmjit/Runtime.cpp | 10 +++++++++- libevmjit/Runtime.h | 4 +++- 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 7f6aba051..a872a0097 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -720,7 +720,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto srcIdx = stack.pop(); auto reqBytes = stack.pop(); - auto srcPtr = ext.calldata(); + auto srcPtr = _runtimeManager.getCallData(); auto srcSize = _runtimeManager.get(RuntimeData::CallDataSize); memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 1adaf741c..b75cd3195 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -52,7 +52,6 @@ Ext::Ext(RuntimeManager& _runtimeManager): m_arg8 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg8"); Type* elements[] = { - i8PtrTy, // byte* calldata i8PtrTy, // byte* code }; @@ -100,8 +99,7 @@ Value* Ext::getDataElem(unsigned _index, const Twine& _name) return m_builder.CreateLoad(valuePtr); } -Value* Ext::calldata() { return getDataElem(0, "calldata"); } -Value* Ext::code() { return getDataElem(1, "code"); } +Value* Ext::code() { return getDataElem(0, "code"); } Value* Ext::calldataload(Value* _index) { diff --git a/libevmjit/Ext.h b/libevmjit/Ext.h index 62938f3cb..f798ec549 100644 --- a/libevmjit/Ext.h +++ b/libevmjit/Ext.h @@ -20,7 +20,6 @@ public: llvm::Value* store(llvm::Value* _index); void setStore(llvm::Value* _index, llvm::Value* _value); - llvm::Value* calldata(); llvm::Value* code(); llvm::Value* balance(llvm::Value* _address); diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 21fcfaddb..523d5ea90 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -22,7 +22,8 @@ llvm::StructType* RuntimeData::getType() { llvm::Type* elems[] = { - llvm::ArrayType::get(Type::i256, _size) + llvm::ArrayType::get(Type::i256, _size), + Type::BytePtr }; type = llvm::StructType::create(elems, "RuntimeData"); } @@ -75,6 +76,7 @@ Runtime::Runtime(u256 _gas, ExtVMFace& _ext): set(RuntimeData::Difficulty, _ext.currentBlock.difficulty); set(RuntimeData::GasLimit, _ext.currentBlock.gasLimit); set(RuntimeData::CodeSize, _ext.code.size()); // TODO: Use constant + m_data.callData = _ext.data.data(); } Runtime::~Runtime() @@ -157,6 +159,12 @@ llvm::Value* RuntimeManager::get(Instruction _inst) } } +llvm::Value* RuntimeManager::getCallData() +{ + auto ptr = getBuilder().CreateStructGEP(getRuntimePtr(), 1, "calldataPtr"); + return getBuilder().CreateLoad(ptr, "calldata"); +} + llvm::Value* RuntimeManager::getGas() { return get(RuntimeData::Gas); diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index a4bb89427..d8f1a2624 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -45,6 +45,7 @@ struct RuntimeData }; i256 elems[_size]; + byte const* callData; static llvm::StructType* getType(); }; @@ -89,7 +90,8 @@ public: llvm::Value* get(RuntimeData::Index _index); llvm::Value* get(Instruction _inst); - llvm::Value* getGas(); + llvm::Value* getGas(); // TODO: Remove + llvm::Value* getCallData(); void setGas(llvm::Value* _gas); private: From 13fb431c54a1790a7f0ceef2f35a0734aa1eec02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 16:13:38 +0100 Subject: [PATCH 229/641] Moving CODE data from Ext to Runtime [#81470252] --- libevmjit/Compiler.cpp | 2 +- libevmjit/Ext.cpp | 19 ------------------- libevmjit/Ext.h | 5 ----- libevmjit/Runtime.cpp | 8 ++++++++ libevmjit/Runtime.h | 2 ++ 5 files changed, 11 insertions(+), 25 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index a872a0097..600551c29 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -733,7 +733,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto srcIdx = stack.pop(); auto reqBytes = stack.pop(); - auto srcPtr = ext.code(); // TODO: Code & its size are constants, feature #80814234 + auto srcPtr = _runtimeManager.getCode(); // TODO: Code & its size are constants, feature #80814234 auto srcSize = _runtimeManager.get(RuntimeData::CodeSize); memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index b75cd3195..6659425ea 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -51,17 +51,8 @@ Ext::Ext(RuntimeManager& _runtimeManager): m_arg7 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg7"); m_arg8 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg8"); - Type* elements[] = { - i8PtrTy, // byte* code - - }; - auto extDataTy = StructType::create(elements, "ext.Data"); - - m_data = m_builder.CreateAlloca(extDataTy, nullptr, "ext.data"); - using llvm::types::i; using Linkage = llvm::GlobalValue::LinkageTypes; - m_init = Function::Create(FunctionType::get(m_builder.getVoidTy(), extDataTy->getPointerTo(), false), Linkage::ExternalLinkage, "ext_init", module); m_store = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_store", module); m_setStore = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_setStore", module); m_calldataload = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_calldataload", module); @@ -75,8 +66,6 @@ Ext::Ext(RuntimeManager& _runtimeManager): m_exp = Function::Create(TypeBuilder*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_exp", module); m_codeAt = Function::Create(TypeBuilder*(i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_codeAt", module); m_codesizeAt = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_codesizeAt", module); - - m_builder.CreateCall(m_init, m_data); } llvm::Value* Ext::store(llvm::Value* _index) @@ -93,14 +82,6 @@ void Ext::setStore(llvm::Value* _index, llvm::Value* _value) m_builder.CreateCall(m_setStore, m_args); // Uses native endianness } -Value* Ext::getDataElem(unsigned _index, const Twine& _name) -{ - auto valuePtr = m_builder.CreateStructGEP(m_data, _index, _name); - return m_builder.CreateLoad(valuePtr); -} - -Value* Ext::code() { return getDataElem(0, "code"); } - Value* Ext::calldataload(Value* _index) { m_builder.CreateStore(_index, m_args[0]); diff --git a/libevmjit/Ext.h b/libevmjit/Ext.h index f798ec549..e7200e95a 100644 --- a/libevmjit/Ext.h +++ b/libevmjit/Ext.h @@ -20,8 +20,6 @@ public: llvm::Value* store(llvm::Value* _index); void setStore(llvm::Value* _index, llvm::Value* _value); - llvm::Value* code(); - llvm::Value* balance(llvm::Value* _address); void suicide(llvm::Value* _address); llvm::Value* calldataload(llvm::Value* _index); @@ -33,8 +31,6 @@ public: llvm::Value* codeAt(llvm::Value* _addr); llvm::Value* codesizeAt(llvm::Value* _addr); -private: - llvm::Value* getDataElem(unsigned _index, const llvm::Twine& _name = ""); private: llvm::Value* m_args[2]; @@ -46,7 +42,6 @@ private: llvm::Value* m_arg7; llvm::Value* m_arg8; llvm::Value* m_data; - llvm::Function* m_init; llvm::Function* m_store; llvm::Function* m_setStore; llvm::Function* m_calldataload; diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 523d5ea90..489034a17 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -23,6 +23,7 @@ llvm::StructType* RuntimeData::getType() llvm::Type* elems[] = { llvm::ArrayType::get(Type::i256, _size), + Type::BytePtr, Type::BytePtr }; type = llvm::StructType::create(elems, "RuntimeData"); @@ -77,6 +78,7 @@ Runtime::Runtime(u256 _gas, ExtVMFace& _ext): set(RuntimeData::GasLimit, _ext.currentBlock.gasLimit); set(RuntimeData::CodeSize, _ext.code.size()); // TODO: Use constant m_data.callData = _ext.data.data(); + m_data.code = _ext.code.data(); } Runtime::~Runtime() @@ -165,6 +167,12 @@ llvm::Value* RuntimeManager::getCallData() return getBuilder().CreateLoad(ptr, "calldata"); } +llvm::Value* RuntimeManager::getCode() +{ + auto ptr = getBuilder().CreateStructGEP(getRuntimePtr(), 2, "codePtr"); + return getBuilder().CreateLoad(ptr, "code"); +} + llvm::Value* RuntimeManager::getGas() { return get(RuntimeData::Gas); diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index d8f1a2624..7eb7c2d38 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -46,6 +46,7 @@ struct RuntimeData i256 elems[_size]; byte const* callData; + byte const* code; static llvm::StructType* getType(); }; @@ -92,6 +93,7 @@ public: llvm::Value* get(Instruction _inst); llvm::Value* getGas(); // TODO: Remove llvm::Value* getCallData(); + llvm::Value* getCode(); void setGas(llvm::Value* _gas); private: From df144a7e2e911c3fe3fc53c18dcd88a4c1785992 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 16:16:02 +0100 Subject: [PATCH 230/641] Old bswap intrinsic removed --- libevmjit/Ext.cpp | 1 - libevmjit/Ext.h | 1 - 2 files changed, 2 deletions(-) diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 6659425ea..853b8cd94 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -61,7 +61,6 @@ Ext::Ext(RuntimeManager& _runtimeManager): m_create = Function::Create(TypeBuilder*, i<256>*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_create", module); Type* args[] = {i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy}; m_call = Function::Create(FunctionType::get(m_builder.getVoidTy(), args, false), Linkage::ExternalLinkage, "ext_call", module); - m_bswap = Intrinsic::getDeclaration(module, Intrinsic::bswap, i256Ty); m_sha3 = Function::Create(TypeBuilder*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_sha3", module); m_exp = Function::Create(TypeBuilder*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_exp", module); m_codeAt = Function::Create(TypeBuilder*(i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_codeAt", module); diff --git a/libevmjit/Ext.h b/libevmjit/Ext.h index e7200e95a..fe62f43c6 100644 --- a/libevmjit/Ext.h +++ b/libevmjit/Ext.h @@ -49,7 +49,6 @@ private: llvm::Function* m_suicide; llvm::Function* m_create; llvm::Function* m_call; - llvm::Function* m_bswap; llvm::Function* m_sha3; llvm::Function* m_exp; llvm::Function* m_codeAt; From 18ccc108a0a91bb8f920b5ea742f65814e0c4805 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 16:46:53 +0100 Subject: [PATCH 231/641] Using RuntimeData pointer in ext functions [#81470252] --- libevmjit/Ext.cpp | 111 ++++++++++++++++++++---------------------- libevmjit/Runtime.cpp | 6 --- libevmjit/Runtime.h | 2 +- 3 files changed, 53 insertions(+), 66 deletions(-) diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 853b8cd94..170086dae 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -8,10 +8,9 @@ #include #include "Runtime.h" +#include "Type.h" #include "Endianness.h" -using namespace llvm; - namespace dev { namespace eth @@ -51,26 +50,27 @@ Ext::Ext(RuntimeManager& _runtimeManager): m_arg7 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg7"); m_arg8 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg8"); - using llvm::types::i; using Linkage = llvm::GlobalValue::LinkageTypes; - m_store = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_store", module); - m_setStore = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_setStore", module); - m_calldataload = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_calldataload", module); - m_balance = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_balance", module); - m_suicide = Function::Create(TypeBuilder*), true>::get(ctx), Linkage::ExternalLinkage, "ext_suicide", module); - m_create = Function::Create(TypeBuilder*, i<256>*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_create", module); - Type* args[] = {i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy}; - m_call = Function::Create(FunctionType::get(m_builder.getVoidTy(), args, false), Linkage::ExternalLinkage, "ext_call", module); - m_sha3 = Function::Create(TypeBuilder*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_sha3", module); - m_exp = Function::Create(TypeBuilder*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_exp", module); - m_codeAt = Function::Create(TypeBuilder*(i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_codeAt", module); - m_codesizeAt = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_codesizeAt", module); + + llvm::Type* argsTypes[] = {Type::RuntimePtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr}; + + m_store = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 3}, false), Linkage::ExternalLinkage, "ext_store", module); + m_setStore = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 3}, false), Linkage::ExternalLinkage, "ext_setStore", module); + m_calldataload = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 3}, false), Linkage::ExternalLinkage, "ext_calldataload", module); + m_balance = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 3}, false), Linkage::ExternalLinkage, "ext_balance", module); + m_suicide = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 2}, false), Linkage::ExternalLinkage, "ext_suicide", module); + m_create = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 5}, false), Linkage::ExternalLinkage, "ext_create", module); + m_call = llvm::Function::Create(llvm::FunctionType::get(Type::Void, argsTypes, false), Linkage::ExternalLinkage, "ext_call", module); + m_sha3 = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 4}, false), Linkage::ExternalLinkage, "ext_sha3", module); + m_exp = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 4}, false), Linkage::ExternalLinkage, "ext_exp", module); + m_codeAt = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, Type::WordPtr, false), Linkage::ExternalLinkage, "ext_codeAt", module); + m_codesizeAt = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 3}, false), Linkage::ExternalLinkage, "ext_codesizeAt", module); } llvm::Value* Ext::store(llvm::Value* _index) { m_builder.CreateStore(_index, m_args[0]); - m_builder.CreateCall(m_store, m_args); // Uses native endianness + m_builder.CreateCall3(m_store, getRuntimeManager().getRuntimePtr(), m_args[0], m_args[1]); // Uses native endianness return m_builder.CreateLoad(m_args[1]); } @@ -78,40 +78,40 @@ void Ext::setStore(llvm::Value* _index, llvm::Value* _value) { m_builder.CreateStore(_index, m_args[0]); m_builder.CreateStore(_value, m_args[1]); - m_builder.CreateCall(m_setStore, m_args); // Uses native endianness + m_builder.CreateCall3(m_setStore, getRuntimeManager().getRuntimePtr(), m_args[0], m_args[1]); // Uses native endianness } -Value* Ext::calldataload(Value* _index) +llvm::Value* Ext::calldataload(llvm::Value* _index) { m_builder.CreateStore(_index, m_args[0]); - m_builder.CreateCall(m_calldataload, m_args); + m_builder.CreateCall3(m_calldataload, getRuntimeManager().getRuntimePtr(), m_args[0], m_args[1]); auto ret = m_builder.CreateLoad(m_args[1]); return Endianness::toNative(m_builder, ret); } -Value* Ext::balance(Value* _address) +llvm::Value* Ext::balance(llvm::Value* _address) { auto address = Endianness::toBE(m_builder, _address); m_builder.CreateStore(address, m_args[0]); - m_builder.CreateCall(m_balance, m_args); + m_builder.CreateCall3(m_balance, getRuntimeManager().getRuntimePtr(), m_args[0], m_args[1]); return m_builder.CreateLoad(m_args[1]); } -void Ext::suicide(Value* _address) +void Ext::suicide(llvm::Value* _address) { auto address = Endianness::toBE(m_builder, _address); m_builder.CreateStore(address, m_args[0]); - m_builder.CreateCall(m_suicide, m_args[0]); + m_builder.CreateCall2(m_suicide, getRuntimeManager().getRuntimePtr(), m_args[0]); } -Value* Ext::create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize) +llvm::Value* Ext::create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize) { m_builder.CreateStore(_endowment, m_args[0]); m_builder.CreateStore(_initOff, m_arg2); m_builder.CreateStore(_initSize, m_arg3); - Value* args[] = {m_args[0], m_arg2, m_arg3, m_args[1]}; + llvm::Value* args[] = {getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_arg3, m_args[1]}; m_builder.CreateCall(m_create, args); - Value* address = m_builder.CreateLoad(m_args[1]); + llvm::Value* address = m_builder.CreateLoad(m_args[1]); address = Endianness::toNative(m_builder, address); return address; } @@ -129,7 +129,7 @@ llvm::Value* Ext::call(llvm::Value*& _gas, llvm::Value* _receiveAddress, llvm::V auto codeAddress = Endianness::toBE(m_builder, _codeAddress); m_builder.CreateStore(codeAddress, m_arg8); - llvm::Value* args[] = {m_args[0], m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_args[1]}; + llvm::Value* args[] = {getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_args[1]}; m_builder.CreateCall(m_call, args); _gas = m_builder.CreateLoad(m_args[0]); // Return gas return m_builder.CreateLoad(m_args[1]); @@ -139,9 +139,9 @@ llvm::Value* Ext::sha3(llvm::Value* _inOff, llvm::Value* _inSize) { m_builder.CreateStore(_inOff, m_args[0]); m_builder.CreateStore(_inSize, m_arg2); - llvm::Value* args[] = {m_args[0], m_arg2, m_args[1]}; + llvm::Value* args[] = {getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_args[1]}; m_builder.CreateCall(m_sha3, args); - Value* hash = m_builder.CreateLoad(m_args[1]); + llvm::Value* hash = m_builder.CreateLoad(m_args[1]); hash = Endianness::toNative(m_builder, hash); return hash; } @@ -150,7 +150,7 @@ llvm::Value* Ext::exp(llvm::Value* _left, llvm::Value* _right) { m_builder.CreateStore(_left, m_args[0]); m_builder.CreateStore(_right, m_arg2); - llvm::Value* args[] = {m_args[0], m_arg2, m_args[1]}; + llvm::Value* args[] = {getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_args[1]}; m_builder.CreateCall(m_exp, args); return m_builder.CreateLoad(m_args[1]); } @@ -159,14 +159,14 @@ llvm::Value* Ext::codeAt(llvm::Value* _addr) { auto addr = Endianness::toBE(m_builder, _addr); m_builder.CreateStore(addr, m_args[0]); - return m_builder.CreateCall(m_codeAt, m_args[0]); + return m_builder.CreateCall2(m_codeAt, getRuntimeManager().getRuntimePtr(), m_args[0]); } llvm::Value* Ext::codesizeAt(llvm::Value* _addr) { auto addr = Endianness::toBE(m_builder, _addr); m_builder.CreateStore(addr, m_args[0]); - llvm::Value* args[] = {m_args[0], m_args[1]}; + llvm::Value* args[] = {getRuntimeManager().getRuntimePtr(), m_args[0], m_args[1]}; m_builder.CreateCall(m_codesizeAt, args); return m_builder.CreateLoad(m_args[1]); } @@ -179,51 +179,44 @@ extern "C" using namespace dev::eth::jit; -EXPORT void ext_init(ExtData* _extData) -{ - auto&& ext = Runtime::getExt(); - _extData->calldata = ext.data.data(); - _extData->code = ext.code.data(); -} - -EXPORT void ext_store(i256* _index, i256* _value) +EXPORT void ext_store(Runtime* _rt, i256* _index, i256* _value) { auto index = llvm2eth(*_index); - auto value = Runtime::getExt().store(index); // Interface uses native endianness + auto value = _rt->getExt().store(index); // Interface uses native endianness *_value = eth2llvm(value); } -EXPORT void ext_setStore(i256* _index, i256* _value) +EXPORT void ext_setStore(Runtime* _rt, i256* _index, i256* _value) { auto index = llvm2eth(*_index); auto value = llvm2eth(*_value); - Runtime::getExt().setStore(index, value); // Interface uses native endianness + _rt->getExt().setStore(index, value); // Interface uses native endianness } -EXPORT void ext_calldataload(i256* _index, i256* _value) +EXPORT void ext_calldataload(Runtime* _rt, i256* _index, i256* _value) { auto index = static_cast(llvm2eth(*_index)); assert(index + 31 > index); // TODO: Handle large index auto b = reinterpret_cast(_value); for (size_t i = index, j = 0; i <= index + 31; ++i, ++j) - b[j] = i < Runtime::getExt().data.size() ? Runtime::getExt().data[i] : 0; // Keep Big Endian + b[j] = i < _rt->getExt().data.size() ? _rt->getExt().data[i] : 0; // Keep Big Endian // TODO: It all can be done by adding padding to data or by using min() algorithm without branch } -EXPORT void ext_balance(h256* _address, i256* _value) +EXPORT void ext_balance(Runtime* _rt, h256* _address, i256* _value) { - auto u = Runtime::getExt().balance(right160(*_address)); + auto u = _rt->getExt().balance(right160(*_address)); *_value = eth2llvm(u); } -EXPORT void ext_suicide(h256* _address) +EXPORT void ext_suicide(Runtime* _rt, h256* _address) { - Runtime::getExt().suicide(right160(*_address)); + _rt->getExt().suicide(right160(*_address)); } -EXPORT void ext_create(i256* _endowment, i256* _initOff, i256* _initSize, h256* _address) +EXPORT void ext_create(Runtime* _rt, i256* _endowment, i256* _initOff, i256* _initSize, h256* _address) { - auto&& ext = Runtime::getExt(); + auto&& ext = _rt->getExt(); auto endowment = llvm2eth(*_endowment); if (ext.balance(ext.myAddress) >= endowment) @@ -244,9 +237,9 @@ EXPORT void ext_create(i256* _endowment, i256* _initOff, i256* _initSize, h256* -EXPORT void ext_call(i256* _gas, h256* _receiveAddress, i256* _value, i256* _inOff, i256* _inSize, i256* _outOff, i256* _outSize, h256* _codeAddress, i256* _ret) +EXPORT void ext_call(Runtime* _rt, i256* _gas, h256* _receiveAddress, i256* _value, i256* _inOff, i256* _inSize, i256* _outOff, i256* _outSize, h256* _codeAddress, i256* _ret) { - auto&& ext = Runtime::getExt(); + auto&& ext = _rt->getExt(); auto value = llvm2eth(*_value); auto ret = false; @@ -270,7 +263,7 @@ EXPORT void ext_call(i256* _gas, h256* _receiveAddress, i256* _value, i256* _inO _ret->a = ret ? 1 : 0; } -EXPORT void ext_sha3(i256* _inOff, i256* _inSize, i256* _ret) +EXPORT void ext_sha3(Runtime* _rt, i256* _inOff, i256* _inSize, i256* _ret) { auto inOff = static_cast(llvm2eth(*_inOff)); auto inSize = static_cast(llvm2eth(*_inSize)); @@ -279,7 +272,7 @@ EXPORT void ext_sha3(i256* _inOff, i256* _inSize, i256* _ret) *_ret = *reinterpret_cast(&hash); } -EXPORT void ext_exp(i256* _left, i256* _right, i256* _ret) +EXPORT void ext_exp(Runtime* _rt, i256* _left, i256* _right, i256* _ret) { bigint left = llvm2eth(*_left); bigint right = llvm2eth(*_right); @@ -287,17 +280,17 @@ EXPORT void ext_exp(i256* _left, i256* _right, i256* _ret) *_ret = eth2llvm(ret); } -EXPORT unsigned char* ext_codeAt(h256* _addr256) +EXPORT unsigned char* ext_codeAt(Runtime* _rt, h256* _addr256) //FIXME: Check endianess { - auto&& ext = Runtime::getExt(); + auto&& ext = _rt->getExt(); auto addr = right160(*_addr256); auto& code = ext.codeAt(addr); return const_cast(code.data()); } -EXPORT void ext_codesizeAt(h256* _addr256, i256* _ret) +EXPORT void ext_codesizeAt(Runtime* _rt, h256* _addr256, i256* _ret) //FIXME: Check endianess { - auto&& ext = Runtime::getExt(); + auto&& ext = _rt->getExt(); auto addr = right160(*_addr256); auto& code = ext.codeAt(addr); *_ret = eth2llvm(u256(code.size())); diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 489034a17..4b9464293 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -91,12 +91,6 @@ void Runtime::set(RuntimeData::Index _index, u256 _value) m_data.elems[_index] = eth2llvm(_value); } - -ExtVMFace& Runtime::getExt() -{ - return g_runtime->m_ext; -} - u256 Runtime::getGas() const { return llvm2eth(m_data.elems[RuntimeData::Gas]); diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index 7eb7c2d38..ec912849a 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -67,7 +67,7 @@ public: StackImpl& getStack() { return m_stack; } MemoryImpl& getMemory() { return m_memory; } - static ExtVMFace& getExt(); + ExtVMFace& getExt() { return m_ext; } u256 getGas() const; bytesConstRef getReturnData() const; From 2fec309a55e06f059d25393fb3c3ff842388f546 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Mon, 27 Oct 2014 21:35:58 +0000 Subject: [PATCH 232/641] Print compilation/execution times --- libevmjit/Compiler.cpp | 8 ++++++++ libevmjit/ExecutionEngine.cpp | 15 +++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 9632f5194..09314452f 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -10,6 +10,9 @@ #include #include +#include +#include + #include #include "Type.h" @@ -264,6 +267,11 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) dump(); } + llvm::FunctionPassManager fpManager(module.get()); + fpManager.add(llvm::createLowerSwitchPass()); + fpManager.doInitialization(); + fpManager.run(*m_mainFunc); + return module; } diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp index af5f96ac7..6363f6d72 100644 --- a/libevmjit/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -2,6 +2,7 @@ #include "ExecutionEngine.h" #include +#include #include #include @@ -72,7 +73,13 @@ int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, ExtV if (!exec) BOOST_THROW_EXCEPTION(Exception() << errinfo_comment(errorMsg)); _module.release(); // Successfully created llvm::ExecutionEngine takes ownership of the module + + auto finalizationStartTime = std::chrono::high_resolution_clock::now(); exec->finalizeObject(); + auto finalizationEndTime = std::chrono::high_resolution_clock::now(); + std::cerr << "*** Module finalization time: " + << std::chrono::duration_cast(finalizationEndTime - finalizationStartTime).count() + << std::endl; // Create fake ExtVM interface if (!_ext) @@ -107,9 +114,17 @@ int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, ExtV auto r = setjmp(buf); if (r == 0) { + auto executionStartTime = std::chrono::high_resolution_clock::now(); + rt_jmpBuf = &buf; auto result = exec->runFunction(entryFunc, {}); returnCode = static_cast(result.IntVal.getZExtValue()); + + auto executionEndTime = std::chrono::high_resolution_clock::now(); + std::cerr << "*** Execution time: " + << std::chrono::duration_cast(executionEndTime - executionStartTime).count() + << std::endl; + } else returnCode = static_cast(r); From 0b2c3c0e00ec3eeb662add094d03dcec59901462 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Mon, 27 Oct 2014 23:12:07 +0000 Subject: [PATCH 233/641] 256-bit arithmetic implemented via calls to boost::multiprecision library. [#79450108] --- evmcc/test/arith/div.evm | 1 + evmcc/test/arith/div.lll | 10 ++++ evmcc/test/arith/mul.evm | 1 + evmcc/test/arith/mul.lll | 13 +++++ libevmjit/Arith256.cpp | 118 +++++++++++++++++++++++++++++++++++++++ libevmjit/Arith256.h | 41 ++++++++++++++ 6 files changed, 184 insertions(+) create mode 100644 evmcc/test/arith/div.evm create mode 100644 evmcc/test/arith/div.lll create mode 100644 evmcc/test/arith/mul.evm create mode 100644 evmcc/test/arith/mul.lll create mode 100644 libevmjit/Arith256.cpp create mode 100644 libevmjit/Arith256.h diff --git a/evmcc/test/arith/div.evm b/evmcc/test/arith/div.evm new file mode 100644 index 000000000..b68d5d202 --- /dev/null +++ b/evmcc/test/arith/div.evm @@ -0,0 +1 @@ +60027ffedcba9876543210fedcba9876543210fedcba9876543210fedcba98765432100460005460206000f2 diff --git a/evmcc/test/arith/div.lll b/evmcc/test/arith/div.lll new file mode 100644 index 000000000..72c22bfdc --- /dev/null +++ b/evmcc/test/arith/div.lll @@ -0,0 +1,10 @@ +(asm +0x2 +0xfedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210 +DIV +0 +MSTORE +32 +0 +RETURN +) diff --git a/evmcc/test/arith/mul.evm b/evmcc/test/arith/mul.evm new file mode 100644 index 000000000..7e8afd268 --- /dev/null +++ b/evmcc/test/arith/mul.evm @@ -0,0 +1 @@ +7001234567890abcdef0fedcba09876543217001234567890abcdef0fedcba09876543217001234567890abcdef0fedcba0987654321020260005460206000f2 diff --git a/evmcc/test/arith/mul.lll b/evmcc/test/arith/mul.lll new file mode 100644 index 000000000..b0fa343bb --- /dev/null +++ b/evmcc/test/arith/mul.lll @@ -0,0 +1,13 @@ +(asm +0x1234567890abcdef0fedcba0987654321 +0x1234567890abcdef0fedcba0987654321 +0x1234567890abcdef0fedcba0987654321 +MUL +MUL +0 +MSTORE +32 +0 +RETURN +;; 47d0817e4167b1eb4f9fc722b133ef9d7d9a6fb4c2c1c442d000107a5e419561 +) diff --git a/libevmjit/Arith256.cpp b/libevmjit/Arith256.cpp new file mode 100644 index 000000000..094ad2ea5 --- /dev/null +++ b/libevmjit/Arith256.cpp @@ -0,0 +1,118 @@ +#include "Arith256.h" +#include "Runtime.h" +#include "Type.h" + +#include + +#include + +namespace dev +{ +namespace eth +{ +namespace jit +{ + +Arith256::Arith256(llvm::IRBuilder<>& _builder) : + CompilerHelper(_builder) +{ + using namespace llvm; + + m_result = m_builder.CreateAlloca(Type::i256, nullptr, "arith.result"); + m_arg1 = m_builder.CreateAlloca(Type::i256, nullptr, "arith.arg1"); + m_arg2 = m_builder.CreateAlloca(Type::i256, nullptr, "arith.arg2"); + + using Linkage = GlobalValue::LinkageTypes; + + llvm::Type* argTypes[] = {Type::WordPtr, Type::WordPtr, Type::WordPtr}; + m_mul = Function::Create(FunctionType::get(Type::Void, argTypes, false), Linkage::ExternalLinkage, "arith_mul", getModule()); + m_div = Function::Create(FunctionType::get(Type::Void, argTypes, false), Linkage::ExternalLinkage, "arith_div", getModule()); + m_mod = Function::Create(FunctionType::get(Type::Void, argTypes, false), Linkage::ExternalLinkage, "arith_mod", getModule()); + m_sdiv = Function::Create(FunctionType::get(Type::Void, argTypes, false), Linkage::ExternalLinkage, "arith_sdiv", getModule()); + m_smod = Function::Create(FunctionType::get(Type::Void, argTypes, false), Linkage::ExternalLinkage, "arith_smod", getModule()); +} + +Arith256::~Arith256() +{} + +llvm::Value* Arith256::binaryOp(llvm::Function* _op, llvm::Value* _arg1, llvm::Value* _arg2) +{ + m_builder.CreateStore(_arg1, m_arg1); + m_builder.CreateStore(_arg2, m_arg2); + m_builder.CreateCall3(_op, m_arg1, m_arg2, m_result); + return m_builder.CreateLoad(m_result); +} + +llvm::Value* Arith256::mul(llvm::Value* _arg1, llvm::Value* _arg2) +{ + return binaryOp(m_mul, _arg1, _arg2); +} + +llvm::Value* Arith256::div(llvm::Value* _arg1, llvm::Value* _arg2) +{ + return binaryOp(m_div, _arg1, _arg2); +} + +llvm::Value* Arith256::mod(llvm::Value* _arg1, llvm::Value* _arg2) +{ + return binaryOp(m_mod, _arg1, _arg2); +} + +llvm::Value* Arith256::sdiv(llvm::Value* _arg1, llvm::Value* _arg2) +{ + return binaryOp(m_sdiv, _arg1, _arg2); +} + +llvm::Value* Arith256::smod(llvm::Value* _arg1, llvm::Value* _arg2) +{ + return binaryOp(m_smod, _arg1, _arg2); +} + +} +} +} + + +extern "C" +{ + +using namespace dev::eth::jit; + +EXPORT void arith_mul(i256* _arg1, i256* _arg2, i256* _result) +{ + dev::u256 arg1 = llvm2eth(*_arg1); + dev::u256 arg2 = llvm2eth(*_arg2); + *_result = eth2llvm(arg1 * arg2); +} + +EXPORT void arith_div(i256* _arg1, i256* _arg2, i256* _result) +{ + dev::u256 arg1 = llvm2eth(*_arg1); + dev::u256 arg2 = llvm2eth(*_arg2); + *_result = eth2llvm(arg2 == 0 ? arg2 : arg1 / arg2); +} + +EXPORT void arith_mod(i256* _arg1, i256* _arg2, i256* _result) +{ + dev::u256 arg1 = llvm2eth(*_arg1); + dev::u256 arg2 = llvm2eth(*_arg2); + *_result = eth2llvm(arg2 == 0 ? arg2 : arg1 % arg2); +} + +EXPORT void arith_sdiv(i256* _arg1, i256* _arg2, i256* _result) +{ + dev::u256 arg1 = llvm2eth(*_arg1); + dev::u256 arg2 = llvm2eth(*_arg2); + *_result = eth2llvm(arg2 == 0 ? arg2 : dev::s2u(dev::u2s(arg1) / dev::u2s(arg2))); +} + +EXPORT void arith_smod(i256* _arg1, i256* _arg2, i256* _result) +{ + dev::u256 arg1 = llvm2eth(*_arg1); + dev::u256 arg2 = llvm2eth(*_arg2); + *_result = eth2llvm(arg2 == 0 ? arg2 : dev::s2u(dev::u2s(arg1) % dev::u2s(arg2))); +} + +} + + diff --git a/libevmjit/Arith256.h b/libevmjit/Arith256.h new file mode 100644 index 000000000..32afae8a7 --- /dev/null +++ b/libevmjit/Arith256.h @@ -0,0 +1,41 @@ +#pragma once + +#include "CompilerHelper.h" + +namespace dev +{ +namespace eth +{ +namespace jit +{ + +class Arith256 : public CompilerHelper +{ +public: + Arith256(llvm::IRBuilder<>& _builder); + virtual ~Arith256(); + + llvm::Value* mul(llvm::Value* _arg1, llvm::Value* _arg2); + llvm::Value* div(llvm::Value* _arg1, llvm::Value* _arg2); + llvm::Value* mod(llvm::Value* _arg1, llvm::Value* _arg2); + llvm::Value* sdiv(llvm::Value* _arg1, llvm::Value* _arg2); + llvm::Value* smod(llvm::Value* _arg1, llvm::Value* _arg2); + +private: + llvm::Value* binaryOp(llvm::Function* _op, llvm::Value* _arg1, llvm::Value* _arg2); + + llvm::Function* m_mul; + llvm::Function* m_div; + llvm::Function* m_mod; + llvm::Function* m_sdiv; + llvm::Function* m_smod; + + llvm::Value* m_arg1; + llvm::Value* m_arg2; + llvm::Value* m_result; +}; + + +} +} +} From 07a909188ad32c7a327bfc6b6a5f2fcbb5938dd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 09:23:28 +0100 Subject: [PATCH 234/641] Move jmpbuf to Runtime [#81470252] --- libevmjit/ExecutionEngine.cpp | 8 ++------ libevmjit/GasMeter.cpp | 3 +-- libevmjit/Runtime.cpp | 10 +++++++++- libevmjit/Runtime.h | 8 +++++++- libevmjit/Stack.cpp | 8 +++----- 5 files changed, 22 insertions(+), 15 deletions(-) diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp index 068237af6..efa039f2b 100644 --- a/libevmjit/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -35,8 +35,6 @@ ExecutionEngine::ExecutionEngine() } -extern "C" { EXPORT std::jmp_buf* rt_jmpBuf; } - int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, ExtVMFace* _ext) { auto module = _module.get(); // Keep ownership of the module in _module @@ -102,21 +100,19 @@ int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, ExtV _ext->code = decltype(_ext->code)(fakecode, 8); } - // Init runtime - Runtime runtime(_gas, *_ext); - auto entryFunc = module->getFunction("main"); if (!entryFunc) BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("main function not found")); ReturnCode returnCode; std::jmp_buf buf; + Runtime runtime(_gas, *_ext, buf); auto r = setjmp(buf); if (r == 0) { + auto executionStartTime = std::chrono::high_resolution_clock::now(); - rt_jmpBuf = &buf; auto result = exec->runFunction(entryFunc, {{}, llvm::GenericValue(runtime.getDataPtr())}); returnCode = static_cast(result.IntVal.getZExtValue()); diff --git a/libevmjit/GasMeter.cpp b/libevmjit/GasMeter.cpp index 317b204fc..897044cbe 100644 --- a/libevmjit/GasMeter.cpp +++ b/libevmjit/GasMeter.cpp @@ -103,10 +103,9 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager) m_builder.SetInsertPoint(outOfGasBB); //auto longjmpFunc = llvm::Intrinsic::getDeclaration(_module, llvm::Intrinsic::eh_sjlj_longjmp); - auto extJmpBuf = new llvm::GlobalVariable(*module, Type::BytePtr, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "rt_jmpBuf"); llvm::Type* args[] = {Type::BytePtr, m_builder.getInt32Ty()}; auto longjmpNative = llvm::Function::Create(llvm::FunctionType::get(Type::Void, args, false), llvm::Function::ExternalLinkage, "longjmp", module); - m_builder.CreateCall2(longjmpNative, m_builder.CreateLoad(extJmpBuf), Constant::get(ReturnCode::OutOfGas)); + m_builder.CreateCall2(longjmpNative, m_runtimeManager.getJmpBuf(), Constant::get(ReturnCode::OutOfGas)); m_builder.CreateUnreachable(); m_builder.SetInsertPoint(updateBB); diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 4b9464293..0be5a5b70 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -24,6 +24,7 @@ llvm::StructType* RuntimeData::getType() { llvm::ArrayType::get(Type::i256, _size), Type::BytePtr, + Type::BytePtr, Type::BytePtr }; type = llvm::StructType::create(elems, "RuntimeData"); @@ -58,7 +59,7 @@ llvm::Twine getName(RuntimeData::Index _index) static Runtime* g_runtime; // FIXME: Remove -Runtime::Runtime(u256 _gas, ExtVMFace& _ext): +Runtime::Runtime(u256 _gas, ExtVMFace& _ext, jmp_buf _jmpBuf): m_ext(_ext) { assert(!g_runtime); @@ -79,6 +80,7 @@ Runtime::Runtime(u256 _gas, ExtVMFace& _ext): set(RuntimeData::CodeSize, _ext.code.size()); // TODO: Use constant m_data.callData = _ext.data.data(); m_data.code = _ext.code.data(); + m_data.jmpBuf = _jmpBuf; } Runtime::~Runtime() @@ -167,6 +169,12 @@ llvm::Value* RuntimeManager::getCode() return getBuilder().CreateLoad(ptr, "code"); } +llvm::Value* RuntimeManager::getJmpBuf() +{ + auto ptr = getBuilder().CreateStructGEP(getRuntimePtr(), 3, "jmpbufPtr"); + return getBuilder().CreateLoad(ptr, "jmpbuf"); +} + llvm::Value* RuntimeManager::getGas() { return get(RuntimeData::Gas); diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index ec912849a..43fafb4d9 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -41,12 +41,16 @@ struct RuntimeData GasLimit, CodeSize, + ReturnDataOffset = CallValue, // Reuse 2 fields for return data reference + ReturnDataSize = CallDataSize, + _size }; i256 elems[_size]; byte const* callData; byte const* code; + decltype(&jmp_buf{}[0]) jmpBuf; static llvm::StructType* getType(); }; @@ -57,7 +61,7 @@ using MemoryImpl = bytes; class Runtime { public: - Runtime(u256 _gas, ExtVMFace& _ext); + Runtime(u256 _gas, ExtVMFace& _ext, jmp_buf _jmpBuf); ~Runtime(); Runtime(const Runtime&) = delete; @@ -71,6 +75,7 @@ public: u256 getGas() const; bytesConstRef getReturnData() const; + decltype(&jmp_buf{}[0]) getJmpBuf() { return m_data.jmpBuf; } private: void set(RuntimeData::Index _index, u256 _value); @@ -94,6 +99,7 @@ public: llvm::Value* getGas(); // TODO: Remove llvm::Value* getCallData(); llvm::Value* getCode(); + llvm::Value* getJmpBuf(); void setGas(llvm::Value* _gas); private: diff --git a/libevmjit/Stack.cpp b/libevmjit/Stack.cpp index 6c287dc6a..144cd5d54 100644 --- a/libevmjit/Stack.cpp +++ b/libevmjit/Stack.cpp @@ -74,13 +74,11 @@ extern "C" using namespace dev::eth::jit; -extern std::jmp_buf* rt_jmpBuf; - EXPORT void stack_pop(Runtime* _rt, uint64_t _count) { auto& stack = _rt->getStack(); if (stack.size() < _count) - longjmp(*rt_jmpBuf, static_cast(ReturnCode::StackTooSmall)); + longjmp(_rt->getJmpBuf(), static_cast(ReturnCode::StackTooSmall)); stack.erase(stack.end() - _count, stack.end()); } @@ -99,7 +97,7 @@ EXPORT void stack_get(Runtime* _rt, uint64_t _index, i256* _ret) auto& stack = _rt->getStack(); // TODO: encode _index and stack size in the return code if (stack.size() <= _index) - longjmp(*rt_jmpBuf, static_cast(ReturnCode::StackTooSmall)); + longjmp(_rt->getJmpBuf(), static_cast(ReturnCode::StackTooSmall)); *_ret = *(stack.rbegin() + _index); } @@ -109,7 +107,7 @@ EXPORT void stack_set(Runtime* _rt, uint64_t _index, i256* _word) auto& stack = _rt->getStack(); // TODO: encode _index and stack size in the return code if (stack.size() <= _index) - longjmp(*rt_jmpBuf, static_cast(ReturnCode::StackTooSmall)); + longjmp(_rt->getJmpBuf(), static_cast(ReturnCode::StackTooSmall)); *(stack.rbegin() + _index) = *_word; } From d86d6c689b17212a05d5c7a4e589c14ab074ba9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 10:21:50 +0100 Subject: [PATCH 235/641] Fix ReturnData::Index::_size --- libevmjit/Runtime.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index 43fafb4d9..c2b21e4ca 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -41,10 +41,10 @@ struct RuntimeData GasLimit, CodeSize, - ReturnDataOffset = CallValue, // Reuse 2 fields for return data reference - ReturnDataSize = CallDataSize, + _size, - _size + ReturnDataOffset = CallValue, // Reuse 2 fields for return data reference + ReturnDataSize = CallDataSize }; i256 elems[_size]; From 33246126f22a0d65837f5aedecef2dbcdbe0f937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 10:27:41 +0100 Subject: [PATCH 236/641] Move return data reference to Runtime [#81470252] --- libevmjit/Compiler.cpp | 5 +++-- libevmjit/Memory.cpp | 18 ++---------------- libevmjit/Memory.h | 12 ++---------- libevmjit/Runtime.cpp | 33 +++++++++++++++++++++++---------- libevmjit/Runtime.h | 5 +++++ 5 files changed, 35 insertions(+), 38 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index dd73ff1e5..3aac68cd8 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -182,7 +182,7 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) // Init runtime structures. RuntimeManager runtimeManager(m_builder); GasMeter gasMeter(m_builder, runtimeManager); - Memory memory(m_builder, gasMeter, runtimeManager); + Memory memory(runtimeManager, gasMeter); Ext ext(runtimeManager); Stack stack(m_builder, runtimeManager); @@ -817,7 +817,8 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto index = stack.pop(); auto size = stack.pop(); - memory.registerReturnData(index, size); + memory.require(index, size); + _runtimeManager.registerReturnData(index, size); m_builder.CreateRet(Constant::get(ReturnCode::Return)); break; diff --git a/libevmjit/Memory.cpp b/libevmjit/Memory.cpp index fa5a2b0dd..b7b3d8497 100644 --- a/libevmjit/Memory.cpp +++ b/libevmjit/Memory.cpp @@ -24,8 +24,8 @@ namespace eth namespace jit { -Memory::Memory(llvm::IRBuilder<>& _builder, GasMeter& _gasMeter, RuntimeManager& _runtimeManager): - CompilerHelper(_builder) +Memory::Memory(RuntimeManager& _runtimeManager, GasMeter& _gasMeter): + RuntimeHelper(_runtimeManager) { auto module = getModule(); auto i64Ty = m_builder.getInt64Ty(); @@ -40,12 +40,6 @@ Memory::Memory(llvm::IRBuilder<>& _builder, GasMeter& _gasMeter, RuntimeManager& m_size = new llvm::GlobalVariable(*module, Type::i256, false, llvm::GlobalVariable::PrivateLinkage, Constant::get(0), "mem.size"); m_size->setUnnamedAddr(true); // Address is not important - m_returnDataOffset = new llvm::GlobalVariable(*module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "mem_returnDataOffset"); - m_returnDataOffset->setUnnamedAddr(true); // Address is not important - - m_returnDataSize = new llvm::GlobalVariable(*module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "mem_returnDataSize"); - m_returnDataSize->setUnnamedAddr(true); // Address is not important - llvm::Type* resizeArgs[] = {Type::RuntimePtr, Type::WordPtr}; m_resize = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, resizeArgs, false), llvm::Function::ExternalLinkage, "mem_resize", module); llvm::AttrBuilder attrBuilder; @@ -180,14 +174,6 @@ void Memory::require(llvm::Value* _offset, llvm::Value* _size) require(sizeRequired); } -void Memory::registerReturnData(llvm::Value* _index, llvm::Value* _size) -{ - require(_index, _size); // Make sure that memory is allocated and count gas - - m_builder.CreateStore(_index, m_returnDataOffset); - m_builder.CreateStore(_size, m_returnDataSize); -} - void Memory::copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value* _srcIdx, llvm::Value* _destMemIdx, llvm::Value* _reqBytes) { diff --git a/libevmjit/Memory.h b/libevmjit/Memory.h index d92538247..d8c1e4b72 100644 --- a/libevmjit/Memory.h +++ b/libevmjit/Memory.h @@ -10,12 +10,11 @@ namespace eth { namespace jit { -class RuntimeManager; -class Memory : public CompilerHelper +class Memory : public RuntimeHelper { public: - Memory(llvm::IRBuilder<>& _builder, class GasMeter& _gasMeter, RuntimeManager& _runtimeManager); + Memory(RuntimeManager& _runtimeManager, class GasMeter& _gasMeter); llvm::Value* loadWord(llvm::Value* _addr); void storeWord(llvm::Value* _addr, llvm::Value* _word); @@ -31,9 +30,6 @@ public: /// Requires the amount of memory to for data defined by offset and size. And counts gas fee for that memory. void require(llvm::Value* _offset, llvm::Value* _size); - void registerReturnData(llvm::Value* _index, llvm::Value* _size); - bytesConstRef getReturnData(); - void dump(uint64_t _begin, uint64_t _end = 0); private: @@ -44,10 +40,6 @@ private: llvm::GlobalVariable* m_data; llvm::GlobalVariable* m_size; - /// @TODO: m_data and m_size could be used - llvm::GlobalVariable* m_returnDataOffset; - llvm::GlobalVariable* m_returnDataSize; - llvm::Function* m_resize; llvm::Function* m_require; llvm::Function* m_loadWord; diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 0be5a5b70..b9dd63ea2 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -98,16 +98,14 @@ u256 Runtime::getGas() const return llvm2eth(m_data.elems[RuntimeData::Gas]); } -extern "C" { - EXPORT i256 mem_returnDataOffset; // FIXME: Dis-globalize - EXPORT i256 mem_returnDataSize; -} - bytesConstRef Runtime::getReturnData() const { // TODO: Handle large indexes - auto offset = static_cast(llvm2eth(mem_returnDataOffset)); - auto size = static_cast(llvm2eth(mem_returnDataSize)); + auto offset = static_cast(llvm2eth(m_data.elems[RuntimeData::ReturnDataOffset])); + auto size = static_cast(llvm2eth(m_data.elems[RuntimeData::ReturnDataSize])); + + assert(offset + size <= m_memory.size()); + // TODO: Handle invalid data access by returning empty ref return {m_memory.data() + offset, size}; } @@ -128,11 +126,26 @@ llvm::Value* RuntimeManager::getRuntimePtr() return m_builder.CreateLoad(m_dataPtr); } -llvm::Value* RuntimeManager::get(RuntimeData::Index _index) +llvm::Value* RuntimeManager::getPtr(RuntimeData::Index _index) { llvm::Value* idxList[] = {m_builder.getInt32(0), m_builder.getInt32(0), m_builder.getInt32(_index)}; - auto ptr = m_builder.CreateInBoundsGEP(getRuntimePtr(), idxList, getName(_index) + "Ptr"); - return m_builder.CreateLoad(ptr, getName(_index)); + return m_builder.CreateInBoundsGEP(getRuntimePtr(), idxList, getName(_index) + "Ptr"); +} + +llvm::Value* RuntimeManager::get(RuntimeData::Index _index) +{ + return m_builder.CreateLoad(getPtr(_index), getName(_index)); +} + +void RuntimeManager::set(RuntimeData::Index _index, llvm::Value* _value) +{ + m_builder.CreateStore(_value, getPtr(_index)); +} + +void RuntimeManager::registerReturnData(llvm::Value* _offset, llvm::Value* _size) +{ + set(RuntimeData::ReturnDataOffset, _offset); + set(RuntimeData::ReturnDataSize, _size); } llvm::Value* RuntimeManager::get(Instruction _inst) diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index c2b21e4ca..f516912eb 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -102,7 +102,12 @@ public: llvm::Value* getJmpBuf(); void setGas(llvm::Value* _gas); + void registerReturnData(llvm::Value* _index, llvm::Value* _size); + private: + llvm::Value* getPtr(RuntimeData::Index _index); + void set(RuntimeData::Index _index, llvm::Value* _value); + llvm::GlobalVariable* m_dataPtr; }; From 66a7834e95337f12834f90635a77cff357c4b30f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 10:32:10 +0100 Subject: [PATCH 237/641] Change some runtime names --- libevmjit/Compiler.cpp | 1 + libevmjit/Runtime.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 3aac68cd8..cfa9349c6 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -172,6 +172,7 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) llvm::Type* mainFuncArgTypes[] = {m_builder.getInt32Ty(), Type::RuntimePtr}; // There must be int in first place because LLVM does not support other signatures auto mainFuncType = llvm::FunctionType::get(Type::MainReturn, mainFuncArgTypes, false); m_mainFunc = llvm::Function::Create(mainFuncType, llvm::Function::ExternalLinkage, "main", module.get()); + m_mainFunc->arg_begin()->getNextNode()->setName("rt"); // Create the basic blocks. auto entryBlock = llvm::BasicBlock::Create(m_builder.getContext(), "entry", m_mainFunc); diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index b9dd63ea2..233ce2a39 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -27,7 +27,7 @@ llvm::StructType* RuntimeData::getType() Type::BytePtr, Type::BytePtr }; - type = llvm::StructType::create(elems, "RuntimeData"); + type = llvm::StructType::create(elems, "Runtime"); } return type; } From bb67c7587dadf78f3e694c4a0f6cd6f9a4f4faa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 10:43:18 +0100 Subject: [PATCH 238/641] Get Runtime pointer from main function argument if available --- libevmjit/CompilerHelper.cpp | 6 ++++-- libevmjit/Runtime.cpp | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/libevmjit/CompilerHelper.cpp b/libevmjit/CompilerHelper.cpp index c2d612c66..c4835c32e 100644 --- a/libevmjit/CompilerHelper.cpp +++ b/libevmjit/CompilerHelper.cpp @@ -27,8 +27,10 @@ llvm::Function* CompilerHelper::getMainFunction() { assert(m_builder.GetInsertBlock()); auto mainFunc = m_builder.GetInsertBlock()->getParent(); - assert(mainFunc && mainFunc->getName() == "main"); - return mainFunc; + assert(mainFunc); + if (mainFunc->getName() == "main") + return mainFunc; + return nullptr; } diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 233ce2a39..86966e2b1 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -122,8 +122,9 @@ RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder): CompilerHelper(_bui llvm::Value* RuntimeManager::getRuntimePtr() { - // TODO: If in main function - get it from param - return m_builder.CreateLoad(m_dataPtr); + if (auto mainFunc = getMainFunction()) + return mainFunc->arg_begin()->getNextNode(); // Runtime is the second parameter of main function + return m_builder.CreateLoad(m_dataPtr, "rt"); } llvm::Value* RuntimeManager::getPtr(RuntimeData::Index _index) From 2eedd8dfdbaed08d8274bb429374413c60e9084b Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Tue, 28 Oct 2014 09:50:42 +0000 Subject: [PATCH 239/641] Added missing changes [#79450108] --- libevmjit/Compiler.cpp | 89 ++++++++++++++++-------------------------- libevmjit/Compiler.h | 2 +- 2 files changed, 35 insertions(+), 56 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index dd73ff1e5..a03543d91 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -22,6 +22,7 @@ #include "GasMeter.h" #include "Utils.h" #include "Endianness.h" +#include "Arith256.h" #include "Runtime.h" namespace dev @@ -185,6 +186,7 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) Memory memory(m_builder, gasMeter, runtimeManager); Ext ext(runtimeManager); Stack stack(m_builder, runtimeManager); + Arith256 arith(m_builder); m_builder.CreateBr(basicBlocks.begin()->second); @@ -194,7 +196,7 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) auto iterCopy = basicBlockPairIt; ++iterCopy; auto nextBasicBlock = (iterCopy != basicBlocks.end()) ? iterCopy->second.llvm() : nullptr; - compileBasicBlock(basicBlock, bytecode, runtimeManager, memory, ext, gasMeter, nextBasicBlock); + compileBasicBlock(basicBlock, bytecode, runtimeManager, arith, memory, ext, gasMeter, nextBasicBlock); } // Code for special blocks: @@ -280,7 +282,7 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) } -void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, RuntimeManager& _runtimeManager, Memory& memory, Ext& ext, GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock) +void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, RuntimeManager& _runtimeManager, Arith256& arith, Memory& memory, Ext& ext, GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock) { m_builder.SetInsertPoint(basicBlock.llvm()); auto& stack = basicBlock.localStack(); @@ -314,61 +316,46 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, case Instruction::MUL: { - auto lhs256 = stack.pop(); - auto rhs256 = stack.pop(); - auto lhs128 = m_builder.CreateTrunc(lhs256, Type::lowPrecision); - auto rhs128 = m_builder.CreateTrunc(rhs256, Type::lowPrecision); - auto res128 = m_builder.CreateMul(lhs128, rhs128); - auto res256 = m_builder.CreateZExt(res128, Type::i256); - stack.push(res256); + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = arith.mul(lhs, rhs); + stack.push(res); break; } case Instruction::DIV: { - auto lhs256 = stack.pop(); - auto rhs256 = stack.pop(); - auto lhs128 = m_builder.CreateTrunc(lhs256, Type::lowPrecision); - auto rhs128 = m_builder.CreateTrunc(rhs256, Type::lowPrecision); - auto res128 = m_builder.CreateUDiv(lhs128, rhs128); - auto res256 = m_builder.CreateZExt(res128, Type::i256); - stack.push(res256); + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = arith.div(lhs, rhs); + stack.push(res); break; } case Instruction::SDIV: { - auto lhs256 = stack.pop(); - auto rhs256 = stack.pop(); - auto lhs128 = m_builder.CreateTrunc(lhs256, Type::lowPrecision); - auto rhs128 = m_builder.CreateTrunc(rhs256, Type::lowPrecision); - auto res128 = m_builder.CreateSDiv(lhs128, rhs128); - auto res256 = m_builder.CreateSExt(res128, Type::i256); - stack.push(res256); + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = arith.sdiv(lhs, rhs); + stack.push(res); break; } case Instruction::MOD: { - auto lhs256 = stack.pop(); - auto rhs256 = stack.pop(); - auto lhs128 = m_builder.CreateTrunc(lhs256, Type::lowPrecision); - auto rhs128 = m_builder.CreateTrunc(rhs256, Type::lowPrecision); - auto res128 = m_builder.CreateURem(lhs128, rhs128); - auto res256 = m_builder.CreateZExt(res128, Type::i256); - stack.push(res256); + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = arith.mod(lhs, rhs); + stack.push(res); break; } case Instruction::SMOD: { - auto lhs256 = stack.pop(); - auto rhs256 = stack.pop(); - auto lhs128 = m_builder.CreateTrunc(lhs256, Type::lowPrecision); - auto rhs128 = m_builder.CreateTrunc(rhs256, Type::lowPrecision); - auto res128 = m_builder.CreateSRem(lhs128, rhs128); - auto res256 = m_builder.CreateSExt(res128, Type::i256); - stack.push(res256); + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = arith.smod(lhs, rhs); + stack.push(res); break; } @@ -496,31 +483,23 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, case Instruction::ADDMOD: { - auto val1 = stack.pop(); - auto val2 = stack.pop(); - auto sum = m_builder.CreateAdd(val1, val2); + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto sum = m_builder.CreateAdd(lhs, rhs); auto mod = stack.pop(); - - auto sum128 = m_builder.CreateTrunc(sum, Type::lowPrecision); - auto mod128 = m_builder.CreateTrunc(mod, Type::lowPrecision); - auto res128 = m_builder.CreateURem(sum128, mod128); - auto res256 = m_builder.CreateZExt(res128, Type::i256); - stack.push(res256); + auto res = arith.mod(sum, mod); + stack.push(res); break; } case Instruction::MULMOD: { - auto val1 = stack.pop(); - auto val2 = stack.pop(); - auto prod = m_builder.CreateMul(val1, val2); + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto prod = m_builder.CreateMul(lhs, rhs); auto mod = stack.pop(); - - auto prod128 = m_builder.CreateTrunc(prod, Type::lowPrecision); - auto mod128 = m_builder.CreateTrunc(mod, Type::lowPrecision); - auto res128 = m_builder.CreateURem(prod128, mod128); - auto res256 = m_builder.CreateZExt(res128, Type::i256); - stack.push(res256); + auto res = arith.mod(prod, mod); + stack.push(res); break; } diff --git a/libevmjit/Compiler.h b/libevmjit/Compiler.h index d543b9b1d..d58745a06 100644 --- a/libevmjit/Compiler.h +++ b/libevmjit/Compiler.h @@ -31,7 +31,7 @@ private: void createBasicBlocks(bytesConstRef bytecode); - void compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, class RuntimeManager& _runtimeManager, class Memory& memory, class Ext& ext, class GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock); + void compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, class RuntimeManager& _runtimeManager, class Arith256& arith, class Memory& memory, class Ext& ext, class GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock); void removeDeadBlocks(); From 686e894b26de378e82484e7670439adb122fdd05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 11:17:00 +0100 Subject: [PATCH 240/641] Add Arith256.* files to Visual Studio project --- windows/LibEvmJit.vcxproj | 2 ++ windows/LibEvmJit.vcxproj.filters | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/windows/LibEvmJit.vcxproj b/windows/LibEvmJit.vcxproj index 1fdc62392..a9288a212 100644 --- a/windows/LibEvmJit.vcxproj +++ b/windows/LibEvmJit.vcxproj @@ -123,6 +123,7 @@ + @@ -138,6 +139,7 @@ + diff --git a/windows/LibEvmJit.vcxproj.filters b/windows/LibEvmJit.vcxproj.filters index b8e592036..ae89fe550 100644 --- a/windows/LibEvmJit.vcxproj.filters +++ b/windows/LibEvmJit.vcxproj.filters @@ -45,6 +45,9 @@ libevmjit + + libevmjit + @@ -86,5 +89,8 @@ libevmjit + + libevmjit + \ No newline at end of file From d74ce85d4a9ee03157d3624764a9e8f60586313e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 11:24:50 +0100 Subject: [PATCH 241/641] Restore correct memory access in Ext functions --- libevmjit/Ext.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 170086dae..bf7947408 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -225,8 +225,7 @@ EXPORT void ext_create(Runtime* _rt, i256* _endowment, i256* _initOff, i256* _in u256 gas; // TODO: Handle gas auto initOff = static_cast(llvm2eth(*_initOff)); auto initSize = static_cast(llvm2eth(*_initSize)); - //auto&& initRef = bytesConstRef(Runtime::getMemory().data() + initOff, initSize); - bytesConstRef initRef; + auto&& initRef = bytesConstRef(_rt->getMemory().data() + initOff, initSize); OnOpFunc onOp{}; // TODO: Handle that thing h256 address = ext.create(endowment, &gas, initRef, onOp); *_address = address; @@ -252,8 +251,8 @@ EXPORT void ext_call(Runtime* _rt, i256* _gas, h256* _receiveAddress, i256* _val auto inSize = static_cast(llvm2eth(*_inSize)); auto outOff = static_cast(llvm2eth(*_outOff)); auto outSize = static_cast(llvm2eth(*_outSize)); - auto&& inRef = bytesConstRef(); //Runtime::getMemory().data() + inOff, inSize); - auto&& outRef = bytesConstRef(); // Runtime::getMemory().data() + outOff, outSize); + auto&& inRef = bytesConstRef(_rt->getMemory().data() + inOff, inSize); + auto&& outRef = bytesConstRef(_rt->getMemory().data() + outOff, outSize); OnOpFunc onOp{}; // TODO: Handle that thing auto codeAddress = right160(*_codeAddress); ret = ext.call(receiveAddress, value, inRef, &gas, outRef, onOp, {}, codeAddress); @@ -267,7 +266,7 @@ EXPORT void ext_sha3(Runtime* _rt, i256* _inOff, i256* _inSize, i256* _ret) { auto inOff = static_cast(llvm2eth(*_inOff)); auto inSize = static_cast(llvm2eth(*_inSize)); - auto dataRef = bytesConstRef(); // Runtime::getMemory().data() + inOff, inSize); + auto dataRef = bytesConstRef(_rt->getMemory().data() + inOff, inSize); auto hash = sha3(dataRef); *_ret = *reinterpret_cast(&hash); } From a0204f8e50178e463a76e25e21d58872a0586877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 11:37:15 +0100 Subject: [PATCH 242/641] Fix EXTCODECOPY --- libevmjit/Ext.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index bf7947408..003b0ae08 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -63,7 +63,7 @@ Ext::Ext(RuntimeManager& _runtimeManager): m_call = llvm::Function::Create(llvm::FunctionType::get(Type::Void, argsTypes, false), Linkage::ExternalLinkage, "ext_call", module); m_sha3 = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 4}, false), Linkage::ExternalLinkage, "ext_sha3", module); m_exp = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 4}, false), Linkage::ExternalLinkage, "ext_exp", module); - m_codeAt = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, Type::WordPtr, false), Linkage::ExternalLinkage, "ext_codeAt", module); + m_codeAt = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, {argsTypes, 2}, false), Linkage::ExternalLinkage, "ext_codeAt", module); m_codesizeAt = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 3}, false), Linkage::ExternalLinkage, "ext_codesizeAt", module); } From df4267e6f8251e3998a68356e86dcba8ef1ef6af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 12:28:23 +0100 Subject: [PATCH 243/641] Ignore opOp callback silently --- libevmjit/VM.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libevmjit/VM.cpp b/libevmjit/VM.cpp index 9a76c5bcb..56121941e 100644 --- a/libevmjit/VM.cpp +++ b/libevmjit/VM.cpp @@ -13,9 +13,8 @@ namespace eth namespace jit { -bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps) +bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const&, uint64_t) { - assert(!_onOp); // Parameter ignored assert(_steps == (uint64_t)-1); // Parameter ignored auto module = Compiler().compile(_ext.code); From f1451174e30583c3ae02dc95b4b03bd8f70b9417 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 12:30:05 +0100 Subject: [PATCH 244/641] Ignore opOp callback silently --- libevmjit/VM.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libevmjit/VM.cpp b/libevmjit/VM.cpp index 56121941e..dd54dd0e5 100644 --- a/libevmjit/VM.cpp +++ b/libevmjit/VM.cpp @@ -15,8 +15,6 @@ namespace jit bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const&, uint64_t) { - assert(_steps == (uint64_t)-1); // Parameter ignored - auto module = Compiler().compile(_ext.code); ExecutionEngine engine; From 23440c642a533b291000383ad218734648073f97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 14:28:23 +0100 Subject: [PATCH 245/641] Return jit::VM only if ETH_JIT macro is on --- libevm/VMFace.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libevm/VMFace.cpp b/libevm/VMFace.cpp index 2553f3004..03f228ad0 100644 --- a/libevm/VMFace.cpp +++ b/libevm/VMFace.cpp @@ -24,7 +24,12 @@ using namespace dev::eth; std::unique_ptr VMFace::create(VMFace::Kind _kind, u256 _gas) { - std::unique_ptr vm(_kind == Kind::JIT ? static_cast(new jit::VM) : new VM); + std::unique_ptr vm; +#if ETH_JIT + vm.reset(_kind == Kind::JIT ? static_cast(new jit::VM) : new VM); +#else + vm.reset(new VM); +#endif vm->reset(_gas); return vm; } From 8cec0751fda1021e3ed55e1049670c9da23987b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 15:37:24 +0100 Subject: [PATCH 246/641] Add missing Visual Studio projects dependencies --- windows/LibEthereum.vcxproj | 4 ++++ windows/TestEthereum.vcxproj | 3 +++ 2 files changed, 7 insertions(+) diff --git a/windows/LibEthereum.vcxproj b/windows/LibEthereum.vcxproj index d19bbc175..956252979 100644 --- a/windows/LibEthereum.vcxproj +++ b/windows/LibEthereum.vcxproj @@ -479,21 +479,25 @@ + + + + diff --git a/windows/TestEthereum.vcxproj b/windows/TestEthereum.vcxproj index 94667fa16..d81fe613a 100644 --- a/windows/TestEthereum.vcxproj +++ b/windows/TestEthereum.vcxproj @@ -189,6 +189,9 @@ + + {826e68cb-d3ee-4a8a-b540-59a8c3f38d4f} + {9c816740-5c11-4377-a3a7-46be12f35fa0} From 5707ac924ab3428832f5713689a0d105f2fc1e8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 16:08:19 +0100 Subject: [PATCH 247/641] Disable LLVM dependency --- windows/Eth.vcxproj | 3 --- windows/LLVM.props | 2 +- windows/TestEthereum.vcxproj | 3 --- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/windows/Eth.vcxproj b/windows/Eth.vcxproj index d67d964f8..3af0a0bce 100644 --- a/windows/Eth.vcxproj +++ b/windows/Eth.vcxproj @@ -155,9 +155,6 @@ {826e68cb-d3ee-4a8a-b540-59a8c3f38d4f} - - {9c816740-5c11-4377-a3a7-46be12f35fa0} - diff --git a/windows/LLVM.props b/windows/LLVM.props index a5c6c4dc5..72fd53a85 100644 --- a/windows/LLVM.props +++ b/windows/LLVM.props @@ -2,7 +2,7 @@ - 1 + 0 ../../llvm ../../_build/llvm/$(Platform) $(LLVMSrcDir)\include;$(LLVMBuildDir)\include diff --git a/windows/TestEthereum.vcxproj b/windows/TestEthereum.vcxproj index d81fe613a..57542f0b4 100644 --- a/windows/TestEthereum.vcxproj +++ b/windows/TestEthereum.vcxproj @@ -192,9 +192,6 @@ {826e68cb-d3ee-4a8a-b540-59a8c3f38d4f} - - {9c816740-5c11-4377-a3a7-46be12f35fa0} - From acc50285e7f6bd38b48e779bf0370e9b1bd2c292 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 17:41:38 +0100 Subject: [PATCH 248/641] Fix compile on Visual Studio --- libevm/VM.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libevm/VM.h b/libevm/VM.h index d5db792f5..6e9819ccd 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -427,12 +427,12 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con break; case Instruction::SIGNEXTEND: { - unsigned k = m_stack.back(); + unsigned k = m_stack.back().convert_to(); m_stack.pop_back(); auto& b = m_stack.back(); if (k <= 31) if ((b >> (k * 8)) & 0x80) - for (int i = 31; i > k; --i) + for (unsigned i = 31; i > k; --i) b |= (u256(0xff) << i); break; } From 6541b0db8a87e9102a2346d3caf8200ea54bdece Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 18:04:01 +0100 Subject: [PATCH 249/641] Add raiseException helper to RuntimeManager [#81563132] --- libevmjit/GasMeter.cpp | 6 +----- libevmjit/GasMeter.h | 2 +- libevmjit/Runtime.cpp | 7 +++++++ libevmjit/Runtime.h | 8 ++++++-- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/libevmjit/GasMeter.cpp b/libevmjit/GasMeter.cpp index b71fd8286..7294fa2f7 100644 --- a/libevmjit/GasMeter.cpp +++ b/libevmjit/GasMeter.cpp @@ -101,11 +101,7 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager) m_builder.CreateCondBr(isOutOfGas, outOfGasBB, updateBB); m_builder.SetInsertPoint(outOfGasBB); - - //auto longjmpFunc = llvm::Intrinsic::getDeclaration(_module, llvm::Intrinsic::eh_sjlj_longjmp); - llvm::Type* args[] = {Type::BytePtr, m_builder.getInt32Ty()}; - auto longjmpNative = llvm::Function::Create(llvm::FunctionType::get(Type::Void, args, false), llvm::Function::ExternalLinkage, "longjmp", module); - m_builder.CreateCall2(longjmpNative, m_runtimeManager.getJmpBuf(), Constant::get(ReturnCode::OutOfGas)); + _runtimeManager.raiseException(ReturnCode::OutOfGas); m_builder.CreateUnreachable(); m_builder.SetInsertPoint(updateBB); diff --git a/libevmjit/GasMeter.h b/libevmjit/GasMeter.h index 82007fc00..dcfde92a3 100644 --- a/libevmjit/GasMeter.h +++ b/libevmjit/GasMeter.h @@ -13,7 +13,7 @@ namespace jit { class RuntimeManager; -class GasMeter : public CompilerHelper +class GasMeter : public CompilerHelper // TODO: Use RuntimeHelper { public: GasMeter(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager); diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 86966e2b1..a93f191a9 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -113,6 +113,8 @@ bytesConstRef Runtime::getReturnData() const RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder): CompilerHelper(_builder) { m_dataPtr = new llvm::GlobalVariable(*getModule(), Type::RuntimePtr, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::RuntimePtr), "rt"); + llvm::Type* args[] = {Type::BytePtr, m_builder.getInt32Ty()}; + m_longjmp = llvm::Function::Create(llvm::FunctionType::get(Type::Void, args, false), llvm::Function::ExternalLinkage, "longjmp", getModule()); // Export data auto mainFunc = getMainFunction(); @@ -149,6 +151,11 @@ void RuntimeManager::registerReturnData(llvm::Value* _offset, llvm::Value* _size set(RuntimeData::ReturnDataSize, _size); } +void RuntimeManager::raiseException(ReturnCode _returnCode) +{ + m_builder.CreateCall2(m_longjmp, getJmpBuf(), Constant::get(_returnCode)); +} + llvm::Value* RuntimeManager::get(Instruction _inst) { switch (_inst) diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index f516912eb..ad2002674 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -7,6 +7,7 @@ #include "CompilerHelper.h" #include "Utils.h" +#include "Type.h" #ifdef _MSC_VER @@ -99,16 +100,19 @@ public: llvm::Value* getGas(); // TODO: Remove llvm::Value* getCallData(); llvm::Value* getCode(); - llvm::Value* getJmpBuf(); void setGas(llvm::Value* _gas); void registerReturnData(llvm::Value* _index, llvm::Value* _size); + void raiseException(ReturnCode _returnCode); + private: llvm::Value* getPtr(RuntimeData::Index _index); void set(RuntimeData::Index _index, llvm::Value* _value); + llvm::Value* getJmpBuf(); - llvm::GlobalVariable* m_dataPtr; + llvm::GlobalVariable* m_dataPtr = nullptr; + llvm::Function* m_longjmp = nullptr; }; } From 6ae263f9867cab8c1192d56d295fcbbb32c5fc16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 18:15:58 +0100 Subject: [PATCH 250/641] Handle bad instructions (BadInstruction exception) [#81563132] --- evmcc/test/except/badinst1.evm | 1 + libevmjit/Compiler.cpp | 5 +++++ libevmjit/Type.h | 3 ++- libevmjit/VM.cpp | 11 +++++++---- 4 files changed, 15 insertions(+), 5 deletions(-) create mode 100644 evmcc/test/except/badinst1.evm diff --git a/evmcc/test/except/badinst1.evm b/evmcc/test/except/badinst1.evm new file mode 100644 index 000000000..69aadac5e --- /dev/null +++ b/evmcc/test/except/badinst1.evm @@ -0,0 +1 @@ +4a diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 0b9fb5b7b..02c8db715 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -816,6 +816,11 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, break; } + default: // Invalid instruction - runtime exception + { + _runtimeManager.raiseException(ReturnCode::BadInstruction); + } + } } diff --git a/libevmjit/Type.h b/libevmjit/Type.h index 86915cd9e..b432f0813 100644 --- a/libevmjit/Type.h +++ b/libevmjit/Type.h @@ -43,7 +43,8 @@ enum class ReturnCode BadJumpDestination = 101, OutOfGas = 102, - StackTooSmall = 103 + StackTooSmall = 103, + BadInstruction = 104, }; struct Constant diff --git a/libevmjit/VM.cpp b/libevmjit/VM.cpp index dd54dd0e5..0907682d2 100644 --- a/libevmjit/VM.cpp +++ b/libevmjit/VM.cpp @@ -5,6 +5,7 @@ #include "ExecutionEngine.h" #include "Compiler.h" +#include "Type.h" namespace dev { @@ -20,14 +21,16 @@ bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const&, uint64_t) ExecutionEngine engine; auto exitCode = engine.run(std::move(module), m_gas, &_ext); - switch (exitCode) + switch (static_cast(exitCode)) { - case 101: + case ReturnCode::BadJumpDestination: BOOST_THROW_EXCEPTION(BadJumpDestination()); - case 102: + case ReturnCode::OutOfGas: BOOST_THROW_EXCEPTION(OutOfGas()); - case 103: + case ReturnCode::StackTooSmall: BOOST_THROW_EXCEPTION(StackTooSmall(1,0)); + case ReturnCode::BadInstruction: + BOOST_THROW_EXCEPTION(BadInstruction()); } m_output = std::move(engine.returnData); From 1b2e51432abad75a1a4ab9e111b5a9f4f8771725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 20:20:21 +0100 Subject: [PATCH 251/641] Call helper --- libevmjit/CompilerHelper.h | 7 +++++++ libevmjit/GasMeter.cpp | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/libevmjit/CompilerHelper.h b/libevmjit/CompilerHelper.h index cf83d70cd..c2257bf51 100644 --- a/libevmjit/CompilerHelper.h +++ b/libevmjit/CompilerHelper.h @@ -31,6 +31,13 @@ protected: llvm::IRBuilder<>& m_builder; llvm::IRBuilder<>& getBuilder() { return m_builder; } + template + llvm::CallInst* call(llvm::Function* _func, _Args*... _args) + { + llvm::Value* args[] = {_args...}; + return m_builder.CreateCall(_func, args); + } + friend class RuntimeHelper; }; diff --git a/libevmjit/GasMeter.cpp b/libevmjit/GasMeter.cpp index 7294fa2f7..20ee30e9a 100644 --- a/libevmjit/GasMeter.cpp +++ b/libevmjit/GasMeter.cpp @@ -143,7 +143,7 @@ void GasMeter::countSStore(Ext& _ext, llvm::Value* _index, llvm::Value* _newValu auto isDel = m_builder.CreateAnd(oldValueIsntZero, newValueIsZero, "isDel"); auto cost = m_builder.CreateSelect(isAdd, Constant::get(2 * sstoreCost), Constant::get(sstoreCost), "cost"); cost = m_builder.CreateSelect(isDel, Constant::get(0), cost, "cost"); - m_builder.CreateCall(m_gasCheckFunc, cost); + call(m_gasCheckFunc, cost); } void GasMeter::giveBack(llvm::Value* _gas) From 2ae0fa25d6f21f048729c210144fa5ad43789e44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 20:36:03 +0100 Subject: [PATCH 252/641] Using call helper --- libevmjit/CompilerHelper.h | 4 ++-- libevmjit/Ext.cpp | 17 ++++++----------- libevmjit/GasMeter.cpp | 2 +- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/libevmjit/CompilerHelper.h b/libevmjit/CompilerHelper.h index c2257bf51..19315fe4a 100644 --- a/libevmjit/CompilerHelper.h +++ b/libevmjit/CompilerHelper.h @@ -32,10 +32,10 @@ protected: llvm::IRBuilder<>& getBuilder() { return m_builder; } template - llvm::CallInst* call(llvm::Function* _func, _Args*... _args) + llvm::CallInst* createCall(llvm::Function* _func, _Args*... _args) { llvm::Value* args[] = {_args...}; - return m_builder.CreateCall(_func, args); + return getBuilder().CreateCall(_func, args); } friend class RuntimeHelper; diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 34c1ebf5e..0da9c8809 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -109,8 +109,7 @@ llvm::Value* Ext::create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::V m_builder.CreateStore(_endowment, m_args[0]); m_builder.CreateStore(_initOff, m_arg2); m_builder.CreateStore(_initSize, m_arg3); - llvm::Value* args[] = {getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_arg3, m_args[1]}; - m_builder.CreateCall(m_create, args); + createCall(m_create, getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_arg3, m_args[1]); llvm::Value* address = m_builder.CreateLoad(m_args[1]); address = Endianness::toNative(m_builder, address); return address; @@ -128,9 +127,7 @@ llvm::Value* Ext::call(llvm::Value*& _gas, llvm::Value* _receiveAddress, llvm::V m_builder.CreateStore(_outSize, m_arg7); auto codeAddress = Endianness::toBE(m_builder, _codeAddress); m_builder.CreateStore(codeAddress, m_arg8); - - llvm::Value* args[] = {getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_args[1]}; - m_builder.CreateCall(m_call, args); + createCall(m_call, getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_args[1]); _gas = m_builder.CreateLoad(m_args[0]); // Return gas return m_builder.CreateLoad(m_args[1]); } @@ -139,8 +136,7 @@ llvm::Value* Ext::sha3(llvm::Value* _inOff, llvm::Value* _inSize) { m_builder.CreateStore(_inOff, m_args[0]); m_builder.CreateStore(_inSize, m_arg2); - llvm::Value* args[] = {getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_args[1]}; - m_builder.CreateCall(m_sha3, args); + createCall(m_sha3, getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_args[1]); llvm::Value* hash = m_builder.CreateLoad(m_args[1]); hash = Endianness::toNative(m_builder, hash); return hash; @@ -148,10 +144,10 @@ llvm::Value* Ext::sha3(llvm::Value* _inOff, llvm::Value* _inSize) llvm::Value* Ext::exp(llvm::Value* _left, llvm::Value* _right) { + // TODO: Move ext to Arith256 m_builder.CreateStore(_left, m_args[0]); m_builder.CreateStore(_right, m_arg2); - llvm::Value* args[] = {getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_args[1]}; - m_builder.CreateCall(m_exp, args); + createCall(m_exp, getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_args[1]); return m_builder.CreateLoad(m_args[1]); } @@ -166,8 +162,7 @@ llvm::Value* Ext::codesizeAt(llvm::Value* _addr) { auto addr = Endianness::toBE(m_builder, _addr); m_builder.CreateStore(addr, m_args[0]); - llvm::Value* args[] = {getRuntimeManager().getRuntimePtr(), m_args[0], m_args[1]}; - m_builder.CreateCall(m_codesizeAt, args); + createCall(m_codesizeAt, getRuntimeManager().getRuntimePtr(), m_args[0], m_args[1]); return m_builder.CreateLoad(m_args[1]); } diff --git a/libevmjit/GasMeter.cpp b/libevmjit/GasMeter.cpp index 20ee30e9a..149944f28 100644 --- a/libevmjit/GasMeter.cpp +++ b/libevmjit/GasMeter.cpp @@ -143,7 +143,7 @@ void GasMeter::countSStore(Ext& _ext, llvm::Value* _index, llvm::Value* _newValu auto isDel = m_builder.CreateAnd(oldValueIsntZero, newValueIsZero, "isDel"); auto cost = m_builder.CreateSelect(isAdd, Constant::get(2 * sstoreCost), Constant::get(sstoreCost), "cost"); cost = m_builder.CreateSelect(isDel, Constant::get(0), cost, "cost"); - call(m_gasCheckFunc, cost); + createCall(m_gasCheckFunc, cost); } void GasMeter::giveBack(llvm::Value* _gas) From f4202d9144057642846a05501329cd4969301b3c Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Tue, 28 Oct 2014 22:25:08 +0000 Subject: [PATCH 253/641] 1. Indenting spaces converted to tabs 2. Options changed: -G --> -g --- evmcc/evmcc.cpp | 125 ++++++++++++++++++++++++++---------------------- 1 file changed, 69 insertions(+), 56 deletions(-) diff --git a/evmcc/evmcc.cpp b/evmcc/evmcc.cpp index abaf3e511..1e0b7e1cd 100644 --- a/evmcc/evmcc.cpp +++ b/evmcc/evmcc.cpp @@ -1,4 +1,5 @@ +#include #include #include #include @@ -18,92 +19,104 @@ void show_usage() { - // FIXME: Use arg[0] as program name? - std::cerr << "usage: evmcc (-b|-c|-d)+ \n"; + // FIXME: Use arg[0] as program name? + std::cerr << "usage: evmcc (-b|-c|-d)+ \n"; } int main(int argc, char** argv) { - std::string input_file; - bool opt_dissassemble = false; - bool opt_show_bytes = false; + std::string input_file; + bool opt_dissassemble = false; + bool opt_show_bytes = false; bool opt_compile = false; bool opt_interpret = false; bool opt_dump_graph = false; bool opt_unknown = false; + bool opt_verbose = false; size_t initialGas = 10000; - for (int i = 1; i < argc; i++) - { - std::string option = argv[i]; - if (option == "-b") - opt_show_bytes = true; - else if (option == "-c") - opt_compile = true; - else if (option == "-d") + for (int i = 1; i < argc; i++) + { + std::string option = argv[i]; + if (option == "-b") + opt_show_bytes = true; + else if (option == "-c") + opt_compile = true; + else if (option == "-d") opt_dissassemble = true; else if (option == "-i") opt_interpret = true; - else if (option == "-g") + else if (option == "--dump-cfg") opt_dump_graph = true; - else if (option == "-G" && i + 1 < argc) + else if (option == "-g" && i + 1 < argc) { std::string gasValue = argv[++i]; initialGas = boost::lexical_cast(gasValue); std::cerr << "Initial gas set to " << initialGas << "\n"; } + else if (option == "-v") + opt_verbose = true; else if (option[0] != '-' && input_file.empty()) input_file = option; - else - { - opt_unknown = true; - break; - } - } - - if (opt_unknown || - input_file.empty() || - (!opt_show_bytes && !opt_compile && !opt_dissassemble && !opt_interpret)) - { - show_usage(); - exit(1); - } - - std::ifstream ifs(input_file); - if (!ifs.is_open()) - { - std::cerr << "cannot open file " << input_file << std::endl; - exit(1); - } - - std::string src((std::istreambuf_iterator(ifs)), - (std::istreambuf_iterator())); - - boost::algorithm::trim(src); + else + { + opt_unknown = true; + break; + } + } + + if (opt_unknown || + input_file.empty() || + (!opt_show_bytes && !opt_compile && !opt_dissassemble && !opt_interpret)) + { + show_usage(); + exit(1); + } + + std::ifstream ifs(input_file); + if (!ifs.is_open()) + { + std::cerr << "cannot open file " << input_file << std::endl; + exit(1); + } + + std::string src((std::istreambuf_iterator(ifs)), + (std::istreambuf_iterator())); + + boost::algorithm::trim(src); using namespace dev; - bytes bytecode = fromHex(src); + bytes bytecode = fromHex(src); - if (opt_show_bytes) - { - std::cout << memDump(bytecode) << std::endl; - } + if (opt_show_bytes) + std::cout << memDump(bytecode) << std::endl; - if (opt_dissassemble) - { - std::string assembly = eth::disassemble(bytecode); - std::cout << assembly << std::endl; - } + if (opt_dissassemble) + { + std::string assembly = eth::disassemble(bytecode); + std::cout << assembly << std::endl; + } - if (opt_compile || opt_interpret) - { - auto compiler = eth::jit::Compiler(); + if (opt_compile || opt_interpret) + { + auto compilationStartTime = std::chrono::high_resolution_clock::now(); + + auto compiler = eth::jit::Compiler(); auto module = compiler.compile({bytecode.data(), bytecode.size()}); + auto compilationEndTime = std::chrono::high_resolution_clock::now(); + module->dump(); + if (opt_verbose) + { + std::cerr << "*** Compilation time: " + << std::chrono::duration_cast(compilationEndTime - compilationStartTime).count() + << std::endl; + } + if (opt_dump_graph) { std::ofstream ofs("blocks.dot"); @@ -119,7 +132,7 @@ int main(int argc, char** argv) auto result = engine.run(std::move(module), gas); return result; } - } + } - return 0; + return 0; } From 017bfd9d7a706ee750a88e1dc2a47e9bc81b1e31 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Tue, 28 Oct 2014 22:29:00 +0000 Subject: [PATCH 254/641] Changed semantics of JUMPDEST so that *the next* instruction is a jump destination --- libevmjit/Compiler.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index a03543d91..cd680d927 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -91,9 +91,12 @@ void Compiler::createBasicBlocks(bytesConstRef bytecode) case Instruction::JUMPDEST: { - // A basic block starts here. - splitPoints.insert(currentPC); - indirectJumpTargets.push_back(currentPC); + // A basic block starts at the next instruction. + if (currentPC + 1 < bytecode.size()) + { + splitPoints.insert(currentPC + 1); + indirectJumpTargets.push_back(currentPC + 1); + } break; } @@ -653,8 +656,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, case Instruction::JUMPDEST: { - // Extra asserts just in case. - assert(currentPC == basicBlock.begin()); + // Nothing to do break; } From f48c0d7e9603ae32f42ee5a28237ecb9e04e214f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 29 Oct 2014 10:21:59 +0100 Subject: [PATCH 255/641] Expose VM kind setting of State in FakeExtVM This reverts commit 6ad065bb3e30b5e67283f70e84ac55368e843e6a. --- test/vm.cpp | 19 ++++++++++--------- test/vm.h | 2 ++ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/test/vm.cpp b/test/vm.cpp index d03a4a278..a8e1ea727 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -441,8 +441,8 @@ h160 FakeState::createNewAddress(Address _newAddress, Address _sender, u256 _end m_cache[_newAddress] = AddressState(0, balance(_newAddress) + _endowment, h256(), h256()); // Execute init code. - auto vmObj = VMFace::create(VMFace::Interpreter, *_gas); - VMFace& vm = *vmObj; + auto vmObj = VMFace::create(getVMKind(), *_gas); + auto& vm = *vmObj; ExtVM evm(*this, _newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _code, o_ms, _level); bool revert = false; bytesConstRef out; @@ -500,7 +500,14 @@ void doTests(json_spirit::mValue& v, bool _fillin) BOOST_REQUIRE(o.count("pre") > 0); BOOST_REQUIRE(o.count("exec") > 0); + auto argc = boost::unit_test::framework::master_test_suite().argc; + auto argv = boost::unit_test::framework::master_test_suite().argv; + auto useJit = argc >= 2 && std::string(argv[1]) == "--jit"; + auto vmKind = useJit ? VMFace::JIT : VMFace::Interpreter; + dev::test::FakeExtVM fev; + fev.setVMKind(vmKind); + fev.importEnv(o["env"].get_obj()); fev.importState(o["pre"].get_obj()); @@ -513,14 +520,8 @@ void doTests(json_spirit::mValue& v, bool _fillin) fev.thisTxCode = get<3>(fev.addresses.at(fev.myAddress)); fev.code = &fev.thisTxCode; } - - - auto argc = boost::unit_test::framework::master_test_suite().argc; - auto argv = boost::unit_test::framework::master_test_suite().argv; - auto useJit = argc >= 2 && std::string(argv[1]) == "--jit"; - auto vmKind = useJit ? VMFace::JIT : VMFace::Interpreter; - auto vm = VMFace::create(vmKind, fev.gas); + auto vm = VMFace::create(fev.getVMKind(), fev.gas); bytes output; auto outOfGas = false; try diff --git a/test/vm.h b/test/vm.h index f3aae694a..e51fe3f89 100644 --- a/test/vm.h +++ b/test/vm.h @@ -80,6 +80,8 @@ public: void importExec(json_spirit::mObject& _o); json_spirit::mArray exportCallCreates(); void importCallCreates(json_spirit::mArray& _callcreates); + void setVMKind(eth::VMFace::Kind _kind) { m_s.setVMKind(_kind); } + eth::VMFace::Kind getVMKind() const { return m_s.getVMKind(); } template eth::OnOpFunc simpleTrace(); From 57fd3e14587a5639bed1b6b5d5b054611de25ba7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 29 Oct 2014 10:30:00 +0100 Subject: [PATCH 256/641] Remove global Runtime pointer --- libevmjit/Runtime.cpp | 9 --------- libevmjit/Runtime.h | 1 - 2 files changed, 10 deletions(-) diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index a93f191a9..3efd78a26 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -57,13 +57,9 @@ llvm::Twine getName(RuntimeData::Index _index) } } -static Runtime* g_runtime; // FIXME: Remove - Runtime::Runtime(u256 _gas, ExtVMFace& _ext, jmp_buf _jmpBuf): m_ext(_ext) { - assert(!g_runtime); - g_runtime = this; set(RuntimeData::Gas, _gas); set(RuntimeData::Address, fromAddress(_ext.myAddress)); set(RuntimeData::Caller, fromAddress(_ext.caller)); @@ -83,11 +79,6 @@ Runtime::Runtime(u256 _gas, ExtVMFace& _ext, jmp_buf _jmpBuf): m_data.jmpBuf = _jmpBuf; } -Runtime::~Runtime() -{ - g_runtime = nullptr; -} - void Runtime::set(RuntimeData::Index _index, u256 _value) { m_data.elems[_index] = eth2llvm(_value); diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index ad2002674..418652c40 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -63,7 +63,6 @@ class Runtime { public: Runtime(u256 _gas, ExtVMFace& _ext, jmp_buf _jmpBuf); - ~Runtime(); Runtime(const Runtime&) = delete; void operator=(const Runtime&) = delete; From 732c40b57a667f04c790e17d2fa31f56c4b42c2e Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Wed, 29 Oct 2014 10:29:34 +0000 Subject: [PATCH 257/641] MULMOD/ADDMOD implemented in separate functions [FIXES #80566276] --- libevmjit/Arith256.cpp | 53 +++++++++++++++++++++++++++++++++++++----- libevmjit/Arith256.h | 6 +++++ libevmjit/Compiler.cpp | 6 ++--- test/vm.cpp | 26 +++++++++++++++++++-- 4 files changed, 79 insertions(+), 12 deletions(-) diff --git a/libevmjit/Arith256.cpp b/libevmjit/Arith256.cpp index 094ad2ea5..caf7bf3d0 100644 --- a/libevmjit/Arith256.cpp +++ b/libevmjit/Arith256.cpp @@ -21,15 +21,20 @@ Arith256::Arith256(llvm::IRBuilder<>& _builder) : m_result = m_builder.CreateAlloca(Type::i256, nullptr, "arith.result"); m_arg1 = m_builder.CreateAlloca(Type::i256, nullptr, "arith.arg1"); m_arg2 = m_builder.CreateAlloca(Type::i256, nullptr, "arith.arg2"); + m_arg3 = m_builder.CreateAlloca(Type::i256, nullptr, "arith.arg3"); using Linkage = GlobalValue::LinkageTypes; - llvm::Type* argTypes[] = {Type::WordPtr, Type::WordPtr, Type::WordPtr}; - m_mul = Function::Create(FunctionType::get(Type::Void, argTypes, false), Linkage::ExternalLinkage, "arith_mul", getModule()); - m_div = Function::Create(FunctionType::get(Type::Void, argTypes, false), Linkage::ExternalLinkage, "arith_div", getModule()); - m_mod = Function::Create(FunctionType::get(Type::Void, argTypes, false), Linkage::ExternalLinkage, "arith_mod", getModule()); - m_sdiv = Function::Create(FunctionType::get(Type::Void, argTypes, false), Linkage::ExternalLinkage, "arith_sdiv", getModule()); - m_smod = Function::Create(FunctionType::get(Type::Void, argTypes, false), Linkage::ExternalLinkage, "arith_smod", getModule()); + llvm::Type* arg2Types[] = {Type::WordPtr, Type::WordPtr, Type::WordPtr}; + llvm::Type* arg3Types[] = {Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr}; + + m_mul = Function::Create(FunctionType::get(Type::Void, arg2Types, false), Linkage::ExternalLinkage, "arith_mul", getModule()); + m_div = Function::Create(FunctionType::get(Type::Void, arg2Types, false), Linkage::ExternalLinkage, "arith_div", getModule()); + m_mod = Function::Create(FunctionType::get(Type::Void, arg2Types, false), Linkage::ExternalLinkage, "arith_mod", getModule()); + m_sdiv = Function::Create(FunctionType::get(Type::Void, arg2Types, false), Linkage::ExternalLinkage, "arith_sdiv", getModule()); + m_smod = Function::Create(FunctionType::get(Type::Void, arg2Types, false), Linkage::ExternalLinkage, "arith_smod", getModule()); + m_addmod = Function::Create(FunctionType::get(Type::Void, arg3Types, false), Linkage::ExternalLinkage, "arith_addmod", getModule()); + m_mulmod = Function::Create(FunctionType::get(Type::Void, arg3Types, false), Linkage::ExternalLinkage, "arith_mulmod", getModule()); } Arith256::~Arith256() @@ -43,6 +48,15 @@ llvm::Value* Arith256::binaryOp(llvm::Function* _op, llvm::Value* _arg1, llvm::V return m_builder.CreateLoad(m_result); } +llvm::Value* Arith256::ternaryOp(llvm::Function* _op, llvm::Value* _arg1, llvm::Value* _arg2, llvm::Value* _arg3) +{ + m_builder.CreateStore(_arg1, m_arg1); + m_builder.CreateStore(_arg2, m_arg2); + m_builder.CreateStore(_arg3, m_arg3); + m_builder.CreateCall4(_op, m_arg1, m_arg2, m_arg3, m_result); + return m_builder.CreateLoad(m_result); +} + llvm::Value* Arith256::mul(llvm::Value* _arg1, llvm::Value* _arg2) { return binaryOp(m_mul, _arg1, _arg2); @@ -68,6 +82,17 @@ llvm::Value* Arith256::smod(llvm::Value* _arg1, llvm::Value* _arg2) return binaryOp(m_smod, _arg1, _arg2); } +llvm::Value* Arith256::addmod(llvm::Value* _arg1, llvm::Value* _arg2, llvm::Value* _arg3) +{ + return ternaryOp(m_addmod, _arg1, _arg2, _arg3); +} + +llvm::Value* Arith256::mulmod(llvm::Value* _arg1, llvm::Value* _arg2, llvm::Value* _arg3) +{ + return ternaryOp(m_mulmod, _arg1, _arg2, _arg3); +} + + } } } @@ -113,6 +138,22 @@ EXPORT void arith_smod(i256* _arg1, i256* _arg2, i256* _result) *_result = eth2llvm(arg2 == 0 ? arg2 : dev::s2u(dev::u2s(arg1) % dev::u2s(arg2))); } +EXPORT void arith_mulmod(i256* _arg1, i256* _arg2, i256* _arg3, i256* _result) +{ + dev::u256 arg1 = llvm2eth(*_arg1); + dev::u256 arg2 = llvm2eth(*_arg2); + dev::u256 arg3 = llvm2eth(*_arg3); + *_result = eth2llvm(dev::u256((dev::bigint(arg1) * dev::bigint(arg2)) % arg3)); +} + +EXPORT void arith_addmod(i256* _arg1, i256* _arg2, i256* _arg3, i256* _result) +{ + dev::u256 arg1 = llvm2eth(*_arg1); + dev::u256 arg2 = llvm2eth(*_arg2); + dev::u256 arg3 = llvm2eth(*_arg3); + *_result = eth2llvm(dev::u256((dev::bigint(arg1) + dev::bigint(arg2)) % arg3)); +} + } diff --git a/libevmjit/Arith256.h b/libevmjit/Arith256.h index 32afae8a7..2268d5076 100644 --- a/libevmjit/Arith256.h +++ b/libevmjit/Arith256.h @@ -20,18 +20,24 @@ public: llvm::Value* mod(llvm::Value* _arg1, llvm::Value* _arg2); llvm::Value* sdiv(llvm::Value* _arg1, llvm::Value* _arg2); llvm::Value* smod(llvm::Value* _arg1, llvm::Value* _arg2); + llvm::Value* mulmod(llvm::Value* _arg1, llvm::Value* _arg2, llvm::Value* _arg3); + llvm::Value* addmod(llvm::Value* _arg1, llvm::Value* _arg2, llvm::Value* _arg3); private: llvm::Value* binaryOp(llvm::Function* _op, llvm::Value* _arg1, llvm::Value* _arg2); + llvm::Value* ternaryOp(llvm::Function* _op, llvm::Value* _arg1, llvm::Value* _arg2, llvm::Value* _arg3); llvm::Function* m_mul; llvm::Function* m_div; llvm::Function* m_mod; llvm::Function* m_sdiv; llvm::Function* m_smod; + llvm::Function* m_mulmod; + llvm::Function* m_addmod; llvm::Value* m_arg1; llvm::Value* m_arg2; + llvm::Value* m_arg3; llvm::Value* m_result; }; diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index cd680d927..d36ee5009 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -488,9 +488,8 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, { auto lhs = stack.pop(); auto rhs = stack.pop(); - auto sum = m_builder.CreateAdd(lhs, rhs); auto mod = stack.pop(); - auto res = arith.mod(sum, mod); + auto res = arith.addmod(lhs, rhs, mod); stack.push(res); break; } @@ -499,9 +498,8 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, { auto lhs = stack.pop(); auto rhs = stack.pop(); - auto prod = m_builder.CreateMul(lhs, rhs); auto mod = stack.pop(); - auto res = arith.mod(prod, mod); + auto res = arith.mulmod(lhs, rhs, mod); stack.push(res); break; } diff --git a/test/vm.cpp b/test/vm.cpp index d62329af4..c056abf5b 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -24,7 +24,7 @@ #include #include #include - +#include //#define FILL_TESTS using namespace std; @@ -357,7 +357,7 @@ void FakeExtVM::importExec(mObject& _o) thisTxCode.clear(); code = &thisTxCode; if (_o["code"].type() == str_type) - if (_o["code"].get_str().find_first_of("0x") == 0) + if (_o["code"].get_str().find_first_of("0x") != 0) thisTxCode = compileLLL(_o["code"].get_str()); else thisTxCode = fromHex(_o["code"].get_str().substr(2)); @@ -518,10 +518,16 @@ void doTests(json_spirit::mValue& v, bool _fillin) auto argv = boost::unit_test::framework::master_test_suite().argv; auto useJit = argc >= 2 && std::string(argv[1]) == "--jit"; + auto showTimes = false; + for (auto i = 0; i < argc; ++i) + showTimes |= std::string(argv[i]) == "--show-times"; + auto vmKind = useJit ? VMFace::JIT : VMFace::Interpreter; auto vm = VMFace::create(vmKind, fev.gas); bytes output; auto outOfGas = false; + + auto startTime = std::chrono::high_resolution_clock::now(); try { output = vm->go(fev).toVector(); @@ -538,6 +544,16 @@ void doTests(json_spirit::mValue& v, bool _fillin) { cnote << "VM did throw an exception: " << _e.what(); } + + auto endTime = std::chrono::high_resolution_clock::now(); + if (showTimes) + { + auto testDuration = endTime - startTime; + cnote << "Execution time: " + << std::chrono::duration_cast(testDuration).count() + << " ms"; + } + auto gas = vm->gas(); // delete null entries in storage for the sake of comparison @@ -760,8 +776,14 @@ BOOST_AUTO_TEST_CASE(vmPushDupSwapTest) dev::test::executeTests("vmPushDupSwapTest"); } +BOOST_AUTO_TEST_CASE(vmPerformanceTest) +{ + dev::test::executeTests("vmPerformanceTest"); +} + BOOST_AUTO_TEST_CASE(vmSystemOperationsTest) { dev::test::executeTests("vmSystemOperationsTest"); } + From 4c7fddd3e81fe5ca7adc9643d5dec7fa038a721d Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Wed, 29 Oct 2014 11:03:41 +0000 Subject: [PATCH 258/641] added dependency on libethereum to evmcc --- evmcc/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/evmcc/CMakeLists.txt b/evmcc/CMakeLists.txt index ae9162162..52ce6ec38 100644 --- a/evmcc/CMakeLists.txt +++ b/evmcc/CMakeLists.txt @@ -10,6 +10,7 @@ add_executable(${EXECUTABLE} ${SRC_LIST}) target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} ethcore) +target_link_libraries(${EXECUTABLE} ethereum) target_link_libraries(${EXECUTABLE} evm) target_link_libraries(${EXECUTABLE} evmface) target_link_libraries(${EXECUTABLE} evmjit) From 0432706b2fa1391bf4bac7f3aeff0e6a93a52d90 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Wed, 29 Oct 2014 11:05:01 +0000 Subject: [PATCH 259/641] added inlcude of setjmp.h required for jmp_buf type --- libevmjit/Runtime.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index 418652c40..e71b646cf 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -1,6 +1,8 @@ #pragma once + +#include #include #include From a34259ec66d0bdb7a5707e8c592c8369cf83aab1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 29 Oct 2014 12:14:05 +0100 Subject: [PATCH 260/641] Fix bad .filters file --- windows/LibEthereum.vcxproj.filters | 1 + 1 file changed, 1 insertion(+) diff --git a/windows/LibEthereum.vcxproj.filters b/windows/LibEthereum.vcxproj.filters index d34e63e27..d96ee47a5 100644 --- a/windows/LibEthereum.vcxproj.filters +++ b/windows/LibEthereum.vcxproj.filters @@ -195,6 +195,7 @@ libevm + libdevcrypto From be6a02a446c7652751df4c8369261d46d4af7757 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 29 Oct 2014 12:14:24 +0100 Subject: [PATCH 261/641] Use clog for JIT logs --- libevmjit/Compiler.cpp | 4 ++-- libevmjit/ExecutionEngine.cpp | 23 +++++++++++------------ libevmjit/Utils.h | 3 +++ 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 02c8db715..2ee776387 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -153,8 +153,8 @@ void Compiler::createBasicBlocks(bytesConstRef bytecode) } else { - std::cerr << "Bad JUMP at PC " << it->first - << ": " << it->second << " is not a valid PC\n"; + clog(JIT) << "Bad JUMP at PC " << it->first + << ": " << it->second << " is not a valid PC"; m_directJumpTargets[it->first] = m_badJumpBlock->llvm(); } } diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp index efa039f2b..c6e623d0e 100644 --- a/libevmjit/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -75,9 +75,8 @@ int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, ExtV auto finalizationStartTime = std::chrono::high_resolution_clock::now(); exec->finalizeObject(); auto finalizationEndTime = std::chrono::high_resolution_clock::now(); - std::cerr << "*** Module finalization time: " - << std::chrono::duration_cast(finalizationEndTime - finalizationStartTime).count() - << std::endl; + clog(JIT) << "Module finalization time: " + << std::chrono::duration_cast(finalizationEndTime - finalizationStartTime).count(); // Create fake ExtVM interface if (!_ext) @@ -117,9 +116,8 @@ int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, ExtV returnCode = static_cast(result.IntVal.getZExtValue()); auto executionEndTime = std::chrono::high_resolution_clock::now(); - std::cerr << "*** Execution time: " - << std::chrono::duration_cast(executionEndTime - executionStartTime).count() - << std::endl; + clog(JIT) << "Execution time : " + << std::chrono::duration_cast(executionEndTime - executionStartTime).count(); } else @@ -128,19 +126,20 @@ int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, ExtV // Return remaining gas _gas = returnCode == ReturnCode::OutOfGas ? 0 : runtime.getGas(); - std::cout << "Max stack size: " << Stack::maxStackSize << std::endl; + clog(JIT) << "Max stack size: " << Stack::maxStackSize; if (returnCode == ReturnCode::Return) { returnData = runtime.getReturnData().toVector(); // TODO: It might be better to place is in Runtime interface - std::cout << "RETURN [ "; + auto&& log = clog(JIT); + log << "RETURN [ "; for (auto it = returnData.begin(), end = returnData.end(); it != end; ++it) - std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)*it << " "; - std::cout << "]\n"; + log << std::hex << std::setw(2) << std::setfill('0') << (int)*it << " "; + log << "]"; } - - std::cout << "RETURN CODE: " << (int)returnCode << std::endl; + else + cslog(JIT) << "RETURN " << (int)returnCode; return static_cast(returnCode); } diff --git a/libevmjit/Utils.h b/libevmjit/Utils.h index 1b146b3d2..7a3afda64 100644 --- a/libevmjit/Utils.h +++ b/libevmjit/Utils.h @@ -4,6 +4,7 @@ #include #include +#include namespace dev { @@ -12,6 +13,8 @@ namespace eth namespace jit { +struct JIT: public NoteChannel { static const char* name() { return "JIT"; } }; + /// Representation of 256-bit value binary compatible with LLVM i256 // TODO: Replace with h256 struct i256 From 9a82a78b889eb38395f60abf06a44134682fdfcc Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Wed, 29 Oct 2014 11:52:11 +0000 Subject: [PATCH 262/641] json test file for performance testing --- evmcc/test/vmtests/vmPerformanceTest.json | 169 ++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 evmcc/test/vmtests/vmPerformanceTest.json diff --git a/evmcc/test/vmtests/vmPerformanceTest.json b/evmcc/test/vmtests/vmPerformanceTest.json new file mode 100644 index 000000000..1bcc2ec15 --- /dev/null +++ b/evmcc/test/vmtests/vmPerformanceTest.json @@ -0,0 +1,169 @@ +{ + "for100000" : { + "callcreates" : [ ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "10000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "code" : "0x620186a06080545d60006080530b0f60295960a0536080530160a0546001608053036080546008585d", + "data" : "0x", + "gas" : "10000000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7799983", + "out" : "0x0", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x620186a06080545d60006080530b0f60295960a0536080530160a0546001608053036080546008585d", + "nonce" : "0", + "storage" : { + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x620186a06080545d60006080530b0f60295960a0536080530160a0546001608053036080546008585d", + "nonce" : "0", + "storage" : { } + } + } + }, + + "recloop" : { + "callcreates" : [ ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "10000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "code" : "0x600c6204000060006015585d60005460206000f25d6000820e602e59602a60018303600183016015585d6030585d805d905090509058", + "data" : "0x", + "gas" : "10000000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "4232808", + "out" : "0x0000000000000000000000000000000000000000000000000000000000040000", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600c6204000060006015585d60005460206000f25d6000820e602e59602a60018303600183016015585d6030585d805d905090509058", + "nonce" : "0", + "storage" : { + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600c6204000060006015585d60005460206000f25d6000820e602e59602a60018303600183016015585d6030585d805d905090509058", + "nonce" : "0", + "storage" : { } + } + } + }, + + "fib25" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "10000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "code" : "0x600860196011585d60005460206000f25d6003810a6031596022600282036011585d602c600183036011585d016034585d60015d90509058", + "data" : "0x", + "gas" : "10000000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7374139", + "out" : "0x0000000000000000000000000000000000000000000000000000000000012511", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600860196011585d60005460206000f25d6003810a6031596022600282036011585d602c600183036011585d016034585d60015d90509058", + "nonce" : "0", + "storage" : { + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600860196011585d60005460206000f25d6003810a6031596022600282036011585d602c600183036011585d016034585d60015d90509058", + "nonce" : "0", + "storage" : { + } + } + } + }, + + "ackermann36" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "10000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "code" : "0x600a600360066013585d60005460206000f25d6000820e604b596000810e603a59603660018303603284600185036013585d6013585d6047585d60466001830360016013585d5d6050585d600181015d905090509058", + "data" : "0x", + "gas" : "10000000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "5865402", + "out" : "0x00000000000000000000000000000000000000000000000000000000000001fd", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600a600360066013585d60005460206000f25d6000820e604b596000810e603a59603660018303603284600185036013585d6013585d6047585d60466001830360016013585d5d6050585d600181015d905090509058", + "nonce" : "0", + "storage" : { + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600a600360066013585d60005460206000f25d6000820e604b596000810e603a59603660018303603284600185036013585d6013585d6047585d60466001830360016013585d5d6050585d600181015d905090509058", + "nonce" : "0", + "storage" : { + } + } + } + }, +} From 865cfe4a72a497065ad0cb37f4c16e3224300986 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Wed, 29 Oct 2014 11:54:02 +0000 Subject: [PATCH 263/641] turned on stack optimization by default in jit compiler --- libevmjit/Compiler.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 99172fbe9..0ba31db95 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -242,8 +242,8 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) dump(); } - if (getenv("EVMCC_OPTIMIZE_STACK")) - { + //if (getenv("EVMCC_OPTIMIZE_STACK")) + //{ std::vector blockList; for (auto& entry : basicBlocks) blockList.push_back(&entry.second); @@ -261,7 +261,7 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) std::cerr << "\n\nAfter stack optimization \n\n"; dump(); } - } + //} for (auto& entry : basicBlocks) entry.second.localStack().synchronize(stack); From b009ad1b88688b427220891b9cec7db36fa4619b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 29 Oct 2014 14:29:21 +0100 Subject: [PATCH 264/641] Fix emcc Visual Studio project for Release configuration --- windows/evmcc.vcxproj | 2 -- 1 file changed, 2 deletions(-) diff --git a/windows/evmcc.vcxproj b/windows/evmcc.vcxproj index a93635e6b..1448bb5a8 100644 --- a/windows/evmcc.vcxproj +++ b/windows/evmcc.vcxproj @@ -171,7 +171,6 @@ true WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) true - ../../llvm-3.5.0/include;../../builds/llvm3.5/include;%(AdditionalIncludeDirectories) 4068;4244;4267;4800 false @@ -180,7 +179,6 @@ true true true - LibEthereum.lib;LibEvmJit.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) From 68829e87b946f969dc6bbdaa90aac0ef94b6b07c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 29 Oct 2014 14:53:09 +0100 Subject: [PATCH 265/641] Remove done FIXME tasks --- libevmjit/Ext.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 0da9c8809..f7b10cfa2 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -274,7 +274,7 @@ EXPORT void ext_exp(Runtime* _rt, i256* _left, i256* _right, i256* _ret) *_ret = eth2llvm(ret); } -EXPORT unsigned char* ext_codeAt(Runtime* _rt, h256* _addr256) //FIXME: Check endianess +EXPORT unsigned char* ext_codeAt(Runtime* _rt, h256* _addr256) { auto&& ext = _rt->getExt(); auto addr = right160(*_addr256); @@ -282,7 +282,7 @@ EXPORT unsigned char* ext_codeAt(Runtime* _rt, h256* _addr256) //FIXME: Check en return const_cast(code.data()); } -EXPORT void ext_codesizeAt(Runtime* _rt, h256* _addr256, i256* _ret) //FIXME: Check endianess +EXPORT void ext_codesizeAt(Runtime* _rt, h256* _addr256, i256* _ret) { auto&& ext = _rt->getExt(); auto addr = right160(*_addr256); From 16868c7222759e77989455c58345ab3702e659be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 29 Oct 2014 16:19:13 +0100 Subject: [PATCH 266/641] Improve Stack code formatting --- libevmjit/Stack.cpp | 86 +++++++++++++++++++++------------------------ libevmjit/Stack.h | 2 -- 2 files changed, 41 insertions(+), 47 deletions(-) diff --git a/libevmjit/Stack.cpp b/libevmjit/Stack.cpp index 144cd5d54..d6538a22d 100644 --- a/libevmjit/Stack.cpp +++ b/libevmjit/Stack.cpp @@ -14,8 +14,8 @@ namespace eth namespace jit { -Stack::Stack(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager) - : CompilerHelper(_builder), +Stack::Stack(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager): + CompilerHelper(_builder), m_runtimeManager(_runtimeManager) { m_arg = m_builder.CreateAlloca(Type::i256, nullptr, "stack.arg"); @@ -36,9 +36,6 @@ Stack::Stack(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager) m_set = Function::Create(FunctionType::get(Type::Void, getSetArgTypes, false), Linkage::ExternalLinkage, "stack_set", module); } -Stack::~Stack() -{} - llvm::Value* Stack::get(size_t _index) { m_builder.CreateCall3(m_get, m_runtimeManager.getRuntimePtr(), llvm::ConstantInt::get(Type::Size, _index, false), m_arg); @@ -71,46 +68,45 @@ size_t Stack::maxStackSize = 0; extern "C" { - -using namespace dev::eth::jit; - -EXPORT void stack_pop(Runtime* _rt, uint64_t _count) -{ - auto& stack = _rt->getStack(); - if (stack.size() < _count) - longjmp(_rt->getJmpBuf(), static_cast(ReturnCode::StackTooSmall)); - - stack.erase(stack.end() - _count, stack.end()); -} - -EXPORT void stack_push(Runtime* _rt, i256* _word) -{ - auto& stack = _rt->getStack(); - stack.push_back(*_word); - - if (stack.size() > Stack::maxStackSize) - Stack::maxStackSize = stack.size(); -} - -EXPORT void stack_get(Runtime* _rt, uint64_t _index, i256* _ret) -{ - auto& stack = _rt->getStack(); - // TODO: encode _index and stack size in the return code - if (stack.size() <= _index) - longjmp(_rt->getJmpBuf(), static_cast(ReturnCode::StackTooSmall)); - - *_ret = *(stack.rbegin() + _index); -} - -EXPORT void stack_set(Runtime* _rt, uint64_t _index, i256* _word) -{ - auto& stack = _rt->getStack(); - // TODO: encode _index and stack size in the return code - if (stack.size() <= _index) - longjmp(_rt->getJmpBuf(), static_cast(ReturnCode::StackTooSmall)); - - *(stack.rbegin() + _index) = *_word; -} + using namespace dev::eth::jit; + + EXPORT void stack_pop(Runtime* _rt, uint64_t _count) + { + auto& stack = _rt->getStack(); + if (stack.size() < _count) + longjmp(_rt->getJmpBuf(), static_cast(ReturnCode::StackTooSmall)); + + stack.erase(stack.end() - _count, stack.end()); + } + + EXPORT void stack_push(Runtime* _rt, i256* _word) + { + auto& stack = _rt->getStack(); + stack.push_back(*_word); + + if (stack.size() > Stack::maxStackSize) + Stack::maxStackSize = stack.size(); + } + + EXPORT void stack_get(Runtime* _rt, uint64_t _index, i256* _ret) + { + auto& stack = _rt->getStack(); + // TODO: encode _index and stack size in the return code + if (stack.size() <= _index) + longjmp(_rt->getJmpBuf(), static_cast(ReturnCode::StackTooSmall)); + + *_ret = *(stack.rbegin() + _index); + } + + EXPORT void stack_set(Runtime* _rt, uint64_t _index, i256* _word) + { + auto& stack = _rt->getStack(); + // TODO: encode _index and stack size in the return code + if (stack.size() <= _index) + longjmp(_rt->getJmpBuf(), static_cast(ReturnCode::StackTooSmall)); + + *(stack.rbegin() + _index) = *_word; + } } // extern "C" diff --git a/libevmjit/Stack.h b/libevmjit/Stack.h index db9032ec4..3e8881e4f 100644 --- a/libevmjit/Stack.h +++ b/libevmjit/Stack.h @@ -15,9 +15,7 @@ class RuntimeManager; class Stack : public CompilerHelper { public: - Stack(llvm::IRBuilder<>& builder, RuntimeManager& runtimeManager); - virtual ~Stack(); llvm::Value* get(size_t _index); void set(size_t _index, llvm::Value* _value); From de76284186a457e0b7baeb39cd164b3c0827e322 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 29 Oct 2014 16:19:32 +0100 Subject: [PATCH 267/641] Change #include setjmp --- libevmjit/Runtime.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index e71b646cf..8c784b394 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -1,9 +1,8 @@ #pragma once - -#include #include +#include #include From 57c6eb8ba3ea0a722d471136887b1781bde0048c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 29 Oct 2014 16:21:21 +0100 Subject: [PATCH 268/641] Improve Arith256 code formatting --- libevmjit/Arith256.cpp | 104 ++++++++++++++++++++--------------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/libevmjit/Arith256.cpp b/libevmjit/Arith256.cpp index caf7bf3d0..61b0ba35e 100644 --- a/libevmjit/Arith256.cpp +++ b/libevmjit/Arith256.cpp @@ -101,58 +101,58 @@ llvm::Value* Arith256::mulmod(llvm::Value* _arg1, llvm::Value* _arg2, llvm::Valu extern "C" { -using namespace dev::eth::jit; - -EXPORT void arith_mul(i256* _arg1, i256* _arg2, i256* _result) -{ - dev::u256 arg1 = llvm2eth(*_arg1); - dev::u256 arg2 = llvm2eth(*_arg2); - *_result = eth2llvm(arg1 * arg2); -} - -EXPORT void arith_div(i256* _arg1, i256* _arg2, i256* _result) -{ - dev::u256 arg1 = llvm2eth(*_arg1); - dev::u256 arg2 = llvm2eth(*_arg2); - *_result = eth2llvm(arg2 == 0 ? arg2 : arg1 / arg2); -} - -EXPORT void arith_mod(i256* _arg1, i256* _arg2, i256* _result) -{ - dev::u256 arg1 = llvm2eth(*_arg1); - dev::u256 arg2 = llvm2eth(*_arg2); - *_result = eth2llvm(arg2 == 0 ? arg2 : arg1 % arg2); -} - -EXPORT void arith_sdiv(i256* _arg1, i256* _arg2, i256* _result) -{ - dev::u256 arg1 = llvm2eth(*_arg1); - dev::u256 arg2 = llvm2eth(*_arg2); - *_result = eth2llvm(arg2 == 0 ? arg2 : dev::s2u(dev::u2s(arg1) / dev::u2s(arg2))); -} - -EXPORT void arith_smod(i256* _arg1, i256* _arg2, i256* _result) -{ - dev::u256 arg1 = llvm2eth(*_arg1); - dev::u256 arg2 = llvm2eth(*_arg2); - *_result = eth2llvm(arg2 == 0 ? arg2 : dev::s2u(dev::u2s(arg1) % dev::u2s(arg2))); -} - -EXPORT void arith_mulmod(i256* _arg1, i256* _arg2, i256* _arg3, i256* _result) -{ - dev::u256 arg1 = llvm2eth(*_arg1); - dev::u256 arg2 = llvm2eth(*_arg2); - dev::u256 arg3 = llvm2eth(*_arg3); - *_result = eth2llvm(dev::u256((dev::bigint(arg1) * dev::bigint(arg2)) % arg3)); -} - -EXPORT void arith_addmod(i256* _arg1, i256* _arg2, i256* _arg3, i256* _result) -{ - dev::u256 arg1 = llvm2eth(*_arg1); - dev::u256 arg2 = llvm2eth(*_arg2); - dev::u256 arg3 = llvm2eth(*_arg3); - *_result = eth2llvm(dev::u256((dev::bigint(arg1) + dev::bigint(arg2)) % arg3)); -} + using namespace dev::eth::jit; + + EXPORT void arith_mul(i256* _arg1, i256* _arg2, i256* _result) + { + dev::u256 arg1 = llvm2eth(*_arg1); + dev::u256 arg2 = llvm2eth(*_arg2); + *_result = eth2llvm(arg1 * arg2); + } + + EXPORT void arith_div(i256* _arg1, i256* _arg2, i256* _result) + { + dev::u256 arg1 = llvm2eth(*_arg1); + dev::u256 arg2 = llvm2eth(*_arg2); + *_result = eth2llvm(arg2 == 0 ? arg2 : arg1 / arg2); + } + + EXPORT void arith_mod(i256* _arg1, i256* _arg2, i256* _result) + { + dev::u256 arg1 = llvm2eth(*_arg1); + dev::u256 arg2 = llvm2eth(*_arg2); + *_result = eth2llvm(arg2 == 0 ? arg2 : arg1 % arg2); + } + + EXPORT void arith_sdiv(i256* _arg1, i256* _arg2, i256* _result) + { + dev::u256 arg1 = llvm2eth(*_arg1); + dev::u256 arg2 = llvm2eth(*_arg2); + *_result = eth2llvm(arg2 == 0 ? arg2 : dev::s2u(dev::u2s(arg1) / dev::u2s(arg2))); + } + + EXPORT void arith_smod(i256* _arg1, i256* _arg2, i256* _result) + { + dev::u256 arg1 = llvm2eth(*_arg1); + dev::u256 arg2 = llvm2eth(*_arg2); + *_result = eth2llvm(arg2 == 0 ? arg2 : dev::s2u(dev::u2s(arg1) % dev::u2s(arg2))); + } + + EXPORT void arith_mulmod(i256* _arg1, i256* _arg2, i256* _arg3, i256* _result) + { + dev::u256 arg1 = llvm2eth(*_arg1); + dev::u256 arg2 = llvm2eth(*_arg2); + dev::u256 arg3 = llvm2eth(*_arg3); + *_result = eth2llvm(dev::u256((dev::bigint(arg1) * dev::bigint(arg2)) % arg3)); + } + + EXPORT void arith_addmod(i256* _arg1, i256* _arg2, i256* _arg3, i256* _result) + { + dev::u256 arg1 = llvm2eth(*_arg1); + dev::u256 arg2 = llvm2eth(*_arg2); + dev::u256 arg3 = llvm2eth(*_arg3); + *_result = eth2llvm(dev::u256((dev::bigint(arg1) + dev::bigint(arg2)) % arg3)); + } } From 31ccf59bd086047893bfb1ded8e50253784dc74e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 29 Oct 2014 16:38:18 +0100 Subject: [PATCH 269/641] Improve code formatting --- libevmjit/BasicBlock.h | 2 +- libevmjit/Ext.h | 2 +- libevmjit/Memory.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libevmjit/BasicBlock.h b/libevmjit/BasicBlock.h index 65044eb2a..ffa9ca109 100644 --- a/libevmjit/BasicBlock.h +++ b/libevmjit/BasicBlock.h @@ -14,7 +14,7 @@ namespace jit { using ProgramCounter = uint64_t; // TODO: Rename - + class BasicBlock { public: diff --git a/libevmjit/Ext.h b/libevmjit/Ext.h index fe62f43c6..8e70af7d0 100644 --- a/libevmjit/Ext.h +++ b/libevmjit/Ext.h @@ -54,7 +54,7 @@ private: llvm::Function* m_codeAt; llvm::Function* m_codesizeAt; }; - + } } diff --git a/libevmjit/Memory.h b/libevmjit/Memory.h index d8c1e4b72..f315b9295 100644 --- a/libevmjit/Memory.h +++ b/libevmjit/Memory.h @@ -22,7 +22,7 @@ public: llvm::Value* getData(); llvm::Value* getSize(); void copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value* _srcIndex, - llvm::Value* _destMemIdx, llvm::Value* _byteCount); + llvm::Value* _destMemIdx, llvm::Value* _byteCount); /// Requires this amount of memory. And counts gas fee for that memory. void require(llvm::Value* _size); From 3216898b49cc6919f2ad98cf95a07372bfacbd0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 29 Oct 2014 16:39:28 +0100 Subject: [PATCH 270/641] Improve Memory code formatting --- libevmjit/Memory.cpp | 72 +++++++++++++++++++++---------------------- libevmjit/Runtime.cpp | 4 +-- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/libevmjit/Memory.cpp b/libevmjit/Memory.cpp index b7b3d8497..63e97efc6 100644 --- a/libevmjit/Memory.cpp +++ b/libevmjit/Memory.cpp @@ -31,8 +31,8 @@ Memory::Memory(RuntimeManager& _runtimeManager, GasMeter& _gasMeter): auto i64Ty = m_builder.getInt64Ty(); llvm::Type* argTypes[] = {i64Ty, i64Ty}; auto dumpTy = llvm::FunctionType::get(m_builder.getVoidTy(), llvm::ArrayRef(argTypes), false); - m_memDump = llvm::Function::Create(dumpTy, llvm::GlobalValue::LinkageTypes::ExternalLinkage, - "evmccrt_memory_dump", module); + m_memDump = llvm::Function::Create(dumpTy, llvm::GlobalValue::LinkageTypes::ExternalLinkage, + "evmccrt_memory_dump", module); m_data = new llvm::GlobalVariable(*module, Type::BytePtr, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::BytePtr), "mem.data"); m_data->setUnnamedAddr(true); // Address is not important @@ -103,7 +103,7 @@ llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, GasMet m_builder.SetInsertPoint(llvm::BasicBlock::Create(func->getContext(), {}, func)); llvm::Value* index = func->arg_begin(); index->setName("index"); - + auto valueSize = _valueType->getPrimitiveSizeInBits() / 8; this->require(index, Constant::get(valueSize)); auto data = m_builder.CreateLoad(m_data, "data"); @@ -175,7 +175,7 @@ void Memory::require(llvm::Value* _offset, llvm::Value* _size) } void Memory::copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value* _srcIdx, - llvm::Value* _destMemIdx, llvm::Value* _reqBytes) + llvm::Value* _destMemIdx, llvm::Value* _reqBytes) { auto zero256 = llvm::ConstantInt::get(Type::i256, 0); @@ -218,38 +218,38 @@ void Memory::dump(uint64_t _begin, uint64_t _end) extern "C" { -using namespace dev::eth::jit; - -EXPORT uint8_t* mem_resize(Runtime* _rt, i256* _size) -{ - auto size = _size->a; // Trunc to 64-bit - auto& memory = _rt->getMemory(); - memory.resize(size); - return memory.data(); -} - -EXPORT void evmccrt_memory_dump(uint64_t _begin, uint64_t _end) -{ - //if (_end == 0) - // _end = Runtime::getMemory().size(); - - //std::cerr << "MEMORY: active size: " << std::dec - // << Runtime::getMemory().size() / 32 << " words\n"; - //std::cerr << "MEMORY: dump from " << std::dec - // << _begin << " to " << _end << ":"; - //if (_end <= _begin) - // return; + using namespace dev::eth::jit; - //_begin = _begin / 16 * 16; - //for (size_t i = _begin; i < _end; i++) - //{ - // if ((i - _begin) % 16 == 0) - // std::cerr << '\n' << std::dec << i << ": "; + EXPORT uint8_t* mem_resize(Runtime* _rt, i256* _size) + { + auto size = _size->a; // Trunc to 64-bit + auto& memory = _rt->getMemory(); + memory.resize(size); + return memory.data(); + } - // auto b = Runtime::getMemory()[i]; - // std::cerr << std::hex << std::setw(2) << static_cast(b) << ' '; - //} - //std::cerr << std::endl; -} + EXPORT void evmccrt_memory_dump(uint64_t _begin, uint64_t _end) + { + //if (_end == 0) + // _end = Runtime::getMemory().size(); + + //std::cerr << "MEMORY: active size: " << std::dec + // << Runtime::getMemory().size() / 32 << " words\n"; + //std::cerr << "MEMORY: dump from " << std::dec + // << _begin << " to " << _end << ":"; + //if (_end <= _begin) + // return; + + //_begin = _begin / 16 * 16; + //for (size_t i = _begin; i < _end; i++) + //{ + // if ((i - _begin) % 16 == 0) + // std::cerr << '\n' << std::dec << i << ": "; + + // auto b = Runtime::getMemory()[i]; + // std::cerr << std::hex << std::setw(2) << static_cast(b) << ' '; + //} + //std::cerr << std::endl; + } -} // extern "C" +} // extern "C" diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 3efd78a26..361089ba1 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -73,7 +73,7 @@ Runtime::Runtime(u256 _gas, ExtVMFace& _ext, jmp_buf _jmpBuf): set(RuntimeData::Number, _ext.currentBlock.number); set(RuntimeData::Difficulty, _ext.currentBlock.difficulty); set(RuntimeData::GasLimit, _ext.currentBlock.gasLimit); - set(RuntimeData::CodeSize, _ext.code.size()); // TODO: Use constant + set(RuntimeData::CodeSize, _ext.code.size()); // TODO: Use constant m_data.callData = _ext.data.data(); m_data.code = _ext.code.data(); m_data.jmpBuf = _jmpBuf; @@ -116,7 +116,7 @@ RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder): CompilerHelper(_bui llvm::Value* RuntimeManager::getRuntimePtr() { if (auto mainFunc = getMainFunction()) - return mainFunc->arg_begin()->getNextNode(); // Runtime is the second parameter of main function + return mainFunc->arg_begin()->getNextNode(); // Runtime is the second parameter of main function return m_builder.CreateLoad(m_dataPtr, "rt"); } From 3e948d963b73686657841ea3c4a4f23e7a9555ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 29 Oct 2014 16:41:00 +0100 Subject: [PATCH 271/641] Improve BasicBlock code formatting --- libevmjit/BasicBlock.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libevmjit/BasicBlock.cpp b/libevmjit/BasicBlock.cpp index 1756971be..a35462cbe 100644 --- a/libevmjit/BasicBlock.cpp +++ b/libevmjit/BasicBlock.cpp @@ -109,7 +109,7 @@ void BasicBlock::LocalStack::synchronize(Stack& _evmStack) } // Push new values - for ( ; currIter < endIter; ++currIter) + for (; currIter < endIter; ++currIter) { assert(*currIter != nullptr); _evmStack.push(*currIter); @@ -243,11 +243,11 @@ void BasicBlock::linkLocalStacks(std::vector basicBlocks, llvm::IRB { if (getenv("EVMCC_DEBUG_BLOCKS")) { - for (auto& pair: cfg) + for (auto& pair : cfg) std::cerr << pair.second.bblock.llvm()->getName().str() << ": in " << pair.second.inputItems - << ", out " << pair.second.outputItems - << "\n"; + << ", out " << pair.second.outputItems + << "\n"; } valuesChanged = false; @@ -347,7 +347,7 @@ void BasicBlock::dump(std::ostream& _out, bool _dotOutput) out << (_dotOutput ? "\\l" : "\n"); } - out << (_dotOutput ? "| " : "Instructions:\n"); + out << (_dotOutput ? "| " : "Instructions:\n"); for (auto ins = m_llvmBB->begin(); ins != m_llvmBB->end(); ++ins) out << *ins << (_dotOutput ? "\\l" : "\n"); From 1f6d12a55c73fbacadc657d12a73b25e8e1cb6a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 29 Oct 2014 16:42:04 +0100 Subject: [PATCH 272/641] Improve ExecutionEngine code formatting --- libevmjit/ExecutionEngine.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp index c6e623d0e..c8ab85150 100644 --- a/libevmjit/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -64,19 +64,19 @@ int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, ExtV auto triple = llvm::Triple(llvm::sys::getProcessTriple()); if (triple.getOS() == llvm::Triple::OSType::Win32) - triple.setObjectFormat(llvm::Triple::ObjectFormatType::ELF); // MCJIT does not support COFF format + triple.setObjectFormat(llvm::Triple::ObjectFormatType::ELF); // MCJIT does not support COFF format module->setTargetTriple(triple.str()); auto exec = std::unique_ptr(builder.create()); if (!exec) BOOST_THROW_EXCEPTION(Exception() << errinfo_comment(errorMsg)); - _module.release(); // Successfully created llvm::ExecutionEngine takes ownership of the module + _module.release(); // Successfully created llvm::ExecutionEngine takes ownership of the module auto finalizationStartTime = std::chrono::high_resolution_clock::now(); exec->finalizeObject(); auto finalizationEndTime = std::chrono::high_resolution_clock::now(); clog(JIT) << "Module finalization time: " - << std::chrono::duration_cast(finalizationEndTime - finalizationStartTime).count(); + << std::chrono::duration_cast(finalizationEndTime - finalizationStartTime).count(); // Create fake ExtVM interface if (!_ext) @@ -117,7 +117,7 @@ int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, ExtV auto executionEndTime = std::chrono::high_resolution_clock::now(); clog(JIT) << "Execution time : " - << std::chrono::duration_cast(executionEndTime - executionStartTime).count(); + << std::chrono::duration_cast(executionEndTime - executionStartTime).count(); } else From 715c60000d48d2b0f74765002ab9bc43f342f66b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 29 Oct 2014 16:42:22 +0100 Subject: [PATCH 273/641] Improve GasMeter code formatting --- libevmjit/GasMeter.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libevmjit/GasMeter.cpp b/libevmjit/GasMeter.cpp index 149944f28..82b587dd8 100644 --- a/libevmjit/GasMeter.cpp +++ b/libevmjit/GasMeter.cpp @@ -31,7 +31,7 @@ uint64_t getStepCost(Instruction inst) // TODO: Add this function to FeeSructure return 0; case Instruction::SSTORE: - return static_cast(c_sstoreResetGas); // FIXME: Check store gas + return static_cast(c_sstoreResetGas); // FIXME: Check store gas case Instruction::SLOAD: return static_cast(c_sloadGas); @@ -87,7 +87,7 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager) auto module = getModule(); m_gasCheckFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "gas.check", module); - InsertPointGuard guard(m_builder); + InsertPointGuard guard(m_builder); auto checkBB = llvm::BasicBlock::Create(_builder.getContext(), "Check", m_gasCheckFunc); auto outOfGasBB = llvm::BasicBlock::Create(_builder.getContext(), "OutOfGas", m_gasCheckFunc); @@ -117,7 +117,7 @@ void GasMeter::count(Instruction _inst) // Create gas check call with mocked block cost at begining of current cost-block m_checkCall = m_builder.CreateCall(m_gasCheckFunc, llvm::UndefValue::get(Type::i256)); } - + if (_inst != Instruction::SSTORE) // Handle cost of SSTORE separately in countSStore() m_blockCost += getStepCost(_inst); @@ -129,7 +129,7 @@ void GasMeter::countSStore(Ext& _ext, llvm::Value* _index, llvm::Value* _newValu { assert(!m_checkCall); // Everything should've been commited before - static const auto sstoreCost = static_cast(c_sstoreResetGas); // FIXME: Check store gas + static const auto sstoreCost = static_cast(c_sstoreResetGas); // FIXME: Check store gas // [ADD] if oldValue == 0 and newValue != 0 => 2*cost // [DEL] if oldValue != 0 and newValue == 0 => 0 From d9ce724f55155c1be5b156b893c7f1d30a4e517d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 29 Oct 2014 16:43:02 +0100 Subject: [PATCH 274/641] Improve Ext code formatting --- libevmjit/Ext.cpp | 198 +++++++++++++++++++++++----------------------- 1 file changed, 99 insertions(+), 99 deletions(-) diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index f7b10cfa2..ef2681803 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -24,7 +24,7 @@ inline u256 fromAddress(Address _a) return (u160)_a; } -struct ExtData +struct ExtData { const byte* calldata; const byte* code; @@ -172,123 +172,123 @@ llvm::Value* Ext::codesizeAt(llvm::Value* _addr) extern "C" { -using namespace dev::eth::jit; + using namespace dev::eth::jit; -EXPORT void ext_store(Runtime* _rt, i256* _index, i256* _value) -{ - auto index = llvm2eth(*_index); - auto value = _rt->getExt().store(index); // Interface uses native endianness - *_value = eth2llvm(value); -} - -EXPORT void ext_setStore(Runtime* _rt, i256* _index, i256* _value) -{ - auto index = llvm2eth(*_index); - auto value = llvm2eth(*_value); - _rt->getExt().setStore(index, value); // Interface uses native endianness -} + EXPORT void ext_store(Runtime* _rt, i256* _index, i256* _value) + { + auto index = llvm2eth(*_index); + auto value = _rt->getExt().store(index); // Interface uses native endianness + *_value = eth2llvm(value); + } -EXPORT void ext_calldataload(Runtime* _rt, i256* _index, i256* _value) -{ - auto index = static_cast(llvm2eth(*_index)); - assert(index + 31 > index); // TODO: Handle large index - auto b = reinterpret_cast(_value); - for (size_t i = index, j = 0; i <= index + 31; ++i, ++j) - b[j] = i < _rt->getExt().data.size() ? _rt->getExt().data[i] : 0; // Keep Big Endian - // TODO: It all can be done by adding padding to data or by using min() algorithm without branch -} + EXPORT void ext_setStore(Runtime* _rt, i256* _index, i256* _value) + { + auto index = llvm2eth(*_index); + auto value = llvm2eth(*_value); + _rt->getExt().setStore(index, value); // Interface uses native endianness + } -EXPORT void ext_balance(Runtime* _rt, h256* _address, i256* _value) -{ - auto u = _rt->getExt().balance(right160(*_address)); - *_value = eth2llvm(u); -} + EXPORT void ext_calldataload(Runtime* _rt, i256* _index, i256* _value) + { + auto index = static_cast(llvm2eth(*_index)); + assert(index + 31 > index); // TODO: Handle large index + auto b = reinterpret_cast(_value); + for (size_t i = index, j = 0; i <= index + 31; ++i, ++j) + b[j] = i < _rt->getExt().data.size() ? _rt->getExt().data[i] : 0; // Keep Big Endian + // TODO: It all can be done by adding padding to data or by using min() algorithm without branch + } -EXPORT void ext_suicide(Runtime* _rt, h256* _address) -{ - _rt->getExt().suicide(right160(*_address)); -} + EXPORT void ext_balance(Runtime* _rt, h256* _address, i256* _value) + { + auto u = _rt->getExt().balance(right160(*_address)); + *_value = eth2llvm(u); + } -EXPORT void ext_create(Runtime* _rt, i256* _endowment, i256* _initOff, i256* _initSize, h256* _address) -{ - auto&& ext = _rt->getExt(); - auto endowment = llvm2eth(*_endowment); + EXPORT void ext_suicide(Runtime* _rt, h256* _address) + { + _rt->getExt().suicide(right160(*_address)); + } - if (ext.balance(ext.myAddress) >= endowment) + EXPORT void ext_create(Runtime* _rt, i256* _endowment, i256* _initOff, i256* _initSize, h256* _address) { - ext.subBalance(endowment); - u256 gas; // TODO: Handle gas - auto initOff = static_cast(llvm2eth(*_initOff)); - auto initSize = static_cast(llvm2eth(*_initSize)); - auto&& initRef = bytesConstRef(_rt->getMemory().data() + initOff, initSize); - OnOpFunc onOp{}; // TODO: Handle that thing - h256 address(ext.create(endowment, &gas, initRef, onOp), h256::AlignRight); - *_address = address; + auto&& ext = _rt->getExt(); + auto endowment = llvm2eth(*_endowment); + + if (ext.balance(ext.myAddress) >= endowment) + { + ext.subBalance(endowment); + u256 gas; // TODO: Handle gas + auto initOff = static_cast(llvm2eth(*_initOff)); + auto initSize = static_cast(llvm2eth(*_initSize)); + auto&& initRef = bytesConstRef(_rt->getMemory().data() + initOff, initSize); + OnOpFunc onOp {}; // TODO: Handle that thing + h256 address(ext.create(endowment, &gas, initRef, onOp), h256::AlignRight); + *_address = address; + } + else + *_address = {}; } - else - *_address = {}; -} -EXPORT void ext_call(Runtime* _rt, i256* _gas, h256* _receiveAddress, i256* _value, i256* _inOff, i256* _inSize, i256* _outOff, i256* _outSize, h256* _codeAddress, i256* _ret) -{ - auto&& ext = _rt->getExt(); - auto value = llvm2eth(*_value); + EXPORT void ext_call(Runtime* _rt, i256* _gas, h256* _receiveAddress, i256* _value, i256* _inOff, i256* _inSize, i256* _outOff, i256* _outSize, h256* _codeAddress, i256* _ret) + { + auto&& ext = _rt->getExt(); + auto value = llvm2eth(*_value); + + auto ret = false; + auto gas = llvm2eth(*_gas); + if (ext.balance(ext.myAddress) >= value) + { + ext.subBalance(value); + auto receiveAddress = right160(*_receiveAddress); + auto inOff = static_cast(llvm2eth(*_inOff)); + auto inSize = static_cast(llvm2eth(*_inSize)); + auto outOff = static_cast(llvm2eth(*_outOff)); + auto outSize = static_cast(llvm2eth(*_outSize)); + auto&& inRef = bytesConstRef(_rt->getMemory().data() + inOff, inSize); + auto&& outRef = bytesConstRef(_rt->getMemory().data() + outOff, outSize); + OnOpFunc onOp {}; // TODO: Handle that thing + auto codeAddress = right160(*_codeAddress); + ret = ext.call(receiveAddress, value, inRef, &gas, outRef, onOp, {}, codeAddress); + } + + *_gas = eth2llvm(gas); + _ret->a = ret ? 1 : 0; + } - auto ret = false; - auto gas = llvm2eth(*_gas); - if (ext.balance(ext.myAddress) >= value) + EXPORT void ext_sha3(Runtime* _rt, i256* _inOff, i256* _inSize, i256* _ret) { - ext.subBalance(value); - auto receiveAddress = right160(*_receiveAddress); auto inOff = static_cast(llvm2eth(*_inOff)); auto inSize = static_cast(llvm2eth(*_inSize)); - auto outOff = static_cast(llvm2eth(*_outOff)); - auto outSize = static_cast(llvm2eth(*_outSize)); - auto&& inRef = bytesConstRef(_rt->getMemory().data() + inOff, inSize); - auto&& outRef = bytesConstRef(_rt->getMemory().data() + outOff, outSize); - OnOpFunc onOp{}; // TODO: Handle that thing - auto codeAddress = right160(*_codeAddress); - ret = ext.call(receiveAddress, value, inRef, &gas, outRef, onOp, {}, codeAddress); + auto dataRef = bytesConstRef(_rt->getMemory().data() + inOff, inSize); + auto hash = sha3(dataRef); + *_ret = *reinterpret_cast(&hash); } - *_gas = eth2llvm(gas); - _ret->a = ret ? 1 : 0; -} - -EXPORT void ext_sha3(Runtime* _rt, i256* _inOff, i256* _inSize, i256* _ret) -{ - auto inOff = static_cast(llvm2eth(*_inOff)); - auto inSize = static_cast(llvm2eth(*_inSize)); - auto dataRef = bytesConstRef(_rt->getMemory().data() + inOff, inSize); - auto hash = sha3(dataRef); - *_ret = *reinterpret_cast(&hash); -} - -EXPORT void ext_exp(Runtime* _rt, i256* _left, i256* _right, i256* _ret) -{ - bigint left = llvm2eth(*_left); - bigint right = llvm2eth(*_right); - auto ret = static_cast(boost::multiprecision::powm(left, right, bigint(2) << 256)); - *_ret = eth2llvm(ret); -} + EXPORT void ext_exp(Runtime* _rt, i256* _left, i256* _right, i256* _ret) + { + bigint left = llvm2eth(*_left); + bigint right = llvm2eth(*_right); + auto ret = static_cast(boost::multiprecision::powm(left, right, bigint(2) << 256)); + *_ret = eth2llvm(ret); + } -EXPORT unsigned char* ext_codeAt(Runtime* _rt, h256* _addr256) -{ - auto&& ext = _rt->getExt(); - auto addr = right160(*_addr256); - auto& code = ext.codeAt(addr); - return const_cast(code.data()); -} + EXPORT unsigned char* ext_codeAt(Runtime* _rt, h256* _addr256) + { + auto&& ext = _rt->getExt(); + auto addr = right160(*_addr256); + auto& code = ext.codeAt(addr); + return const_cast(code.data()); + } -EXPORT void ext_codesizeAt(Runtime* _rt, h256* _addr256, i256* _ret) -{ - auto&& ext = _rt->getExt(); - auto addr = right160(*_addr256); - auto& code = ext.codeAt(addr); - *_ret = eth2llvm(u256(code.size())); -} + EXPORT void ext_codesizeAt(Runtime* _rt, h256* _addr256, i256* _ret) + { + auto&& ext = _rt->getExt(); + auto addr = right160(*_addr256); + auto& code = ext.codeAt(addr); + *_ret = eth2llvm(u256(code.size())); + } } } From fd351c84fbc3f95005fa135108e888f55fa0f287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 29 Oct 2014 16:43:38 +0100 Subject: [PATCH 275/641] Improve VM code formatting --- libevmjit/VM.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libevmjit/VM.cpp b/libevmjit/VM.cpp index 0907682d2..c0a8c8605 100644 --- a/libevmjit/VM.cpp +++ b/libevmjit/VM.cpp @@ -28,13 +28,13 @@ bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const&, uint64_t) case ReturnCode::OutOfGas: BOOST_THROW_EXCEPTION(OutOfGas()); case ReturnCode::StackTooSmall: - BOOST_THROW_EXCEPTION(StackTooSmall(1,0)); + BOOST_THROW_EXCEPTION(StackTooSmall(1, 0)); case ReturnCode::BadInstruction: BOOST_THROW_EXCEPTION(BadInstruction()); } m_output = std::move(engine.returnData); - return {m_output.data(), m_output.size()}; // TODO: This all bytesConstRef stuff sucks + return {m_output.data(), m_output.size()}; // TODO: This all bytesConstRef stuff sucks } } From 91dd7122c2b9fd4ddc04c3bf57f4acf966f793d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 29 Oct 2014 16:45:35 +0100 Subject: [PATCH 276/641] Improve Compiler code formatting --- libevmjit/Compiler.cpp | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index bed0aaaab..8dc19e84c 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -46,7 +46,7 @@ void Compiler::createBasicBlocks(bytesConstRef bytecode) std::vector indirectJumpTargets; boost::dynamic_bitset<> validJumpTargets(std::max(bytecode.size(), size_t(1))); - splitPoints.insert(0); // First basic block + splitPoints.insert(0); // First basic block validJumpTargets[0] = true; for (auto curr = bytecode.begin(); curr != bytecode.end(); ++curr) @@ -120,7 +120,7 @@ void Compiler::createBasicBlocks(bytesConstRef bytecode) } // Remove split points generated from jumps out of code or into data. - for (auto it = splitPoints.cbegin(); it != splitPoints.cend(); ) + for (auto it = splitPoints.cbegin(); it != splitPoints.cend();) { if (*it > bytecode.size() || !validJumpTargets[*it]) it = splitPoints.erase(it); @@ -128,7 +128,7 @@ void Compiler::createBasicBlocks(bytesConstRef bytecode) ++it; } - for (auto it = splitPoints.cbegin(); it != splitPoints.cend(); ) + for (auto it = splitPoints.cbegin(); it != splitPoints.cend();) { auto beginInstIdx = *it; ++it; @@ -173,7 +173,7 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) auto module = std::make_unique("main", m_builder.getContext()); // Create main function - llvm::Type* mainFuncArgTypes[] = {m_builder.getInt32Ty(), Type::RuntimePtr}; // There must be int in first place because LLVM does not support other signatures + llvm::Type* mainFuncArgTypes[] = {m_builder.getInt32Ty(), Type::RuntimePtr}; // There must be int in first place because LLVM does not support other signatures auto mainFuncType = llvm::FunctionType::get(Type::MainReturn, mainFuncArgTypes, false); m_mainFunc = llvm::Function::Create(mainFuncType, llvm::Function::ExternalLinkage, "main", module.get()); m_mainFunc->arg_begin()->getNextNode()->setName("rt"); @@ -217,8 +217,8 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) if (m_indirectJumpTargets.size() > 0) { auto dest = m_jumpTableBlock->localStack().pop(); - auto switchInstr = m_builder.CreateSwitch(dest, m_badJumpBlock->llvm(), - m_indirectJumpTargets.size()); + auto switchInstr = m_builder.CreateSwitch(dest, m_badJumpBlock->llvm(), + m_indirectJumpTargets.size()); for (auto it = m_indirectJumpTargets.cbegin(); it != m_indirectJumpTargets.cend(); ++it) { auto& bb = *it; @@ -523,9 +523,9 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, case Instruction::ANY_PUSH: { - auto numBytes = static_cast(inst)-static_cast(Instruction::PUSH1) + 1; + auto numBytes = static_cast(inst) - static_cast(Instruction::PUSH1) + 1; auto value = llvm::APInt(256, 0); - for (decltype(numBytes) i = 0; i < numBytes; ++i) // TODO: Use pc as iterator + for (decltype(numBytes) i = 0; i < numBytes; ++i) // TODO: Use pc as iterator { ++currentPC; value <<= 8; @@ -538,14 +538,14 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, case Instruction::ANY_DUP: { - auto index = static_cast(inst)-static_cast(Instruction::DUP1); + auto index = static_cast(inst) - static_cast(Instruction::DUP1); stack.dup(index); break; } case Instruction::ANY_SWAP: { - auto index = static_cast(inst)-static_cast(Instruction::SWAP1) + 1; + auto index = static_cast(inst) - static_cast(Instruction::SWAP1) + 1; stack.swap(index); break; } @@ -721,7 +721,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto srcIdx = stack.pop(); auto reqBytes = stack.pop(); - auto srcPtr = _runtimeManager.getCode(); // TODO: Code & its size are constants, feature #80814234 + auto srcPtr = _runtimeManager.getCode(); // TODO: Code & its size are constants, feature #80814234 auto srcSize = _runtimeManager.get(RuntimeData::CodeSize); memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); @@ -826,12 +826,12 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, gasMeter.commitCostBlock(); - if (!basicBlock.llvm()->getTerminator()) // If block not terminated + if (!basicBlock.llvm()->getTerminator()) // If block not terminated { if (nextBasicBlock) - m_builder.CreateBr(nextBasicBlock); // Branch to the next block + m_builder.CreateBr(nextBasicBlock); // Branch to the next block else - m_builder.CreateRet(Constant::get(ReturnCode::Stop)); // Return STOP code + m_builder.CreateRet(Constant::get(ReturnCode::Stop)); // Return STOP code } } @@ -870,8 +870,8 @@ void Compiler::removeDeadBlocks() void Compiler::dumpBasicBlockGraph(std::ostream& out) { out << "digraph BB {\n" - << " node [shape=record, fontname=Courier, fontsize=10];\n" - << " entry [share=record, label=\"entry block\"];\n"; + << " node [shape=record, fontname=Courier, fontsize=10];\n" + << " entry [share=record, label=\"entry block\"];\n"; std::vector blocks; for (auto& pair : basicBlocks) @@ -903,10 +903,10 @@ void Compiler::dumpBasicBlockGraph(std::ostream& out) for (llvm::pred_iterator it = llvm::pred_begin(bb->llvm()); it != end; ++it) { out << " \"" << (*it)->getName().str() << "\" -> \"" << blockName << "\" [" - << ((m_jumpTableBlock.get() && *it == m_jumpTableBlock.get()->llvm()) ? "style = dashed, " : "") - //<< "label = \"" - //<< phiNodesPerBlock[bb] - << "];\n"; + << ((m_jumpTableBlock.get() && *it == m_jumpTableBlock.get()->llvm()) ? "style = dashed, " : "") + //<< "label = \"" + //<< phiNodesPerBlock[bb] + << "];\n"; } } From 76719fb4f49a3a50f09c586990b189e988a67553 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 29 Oct 2014 20:03:32 +0100 Subject: [PATCH 277/641] Update astyle options: - "delete-empty-lines" removed as it removes single empty lines also - "keep-one-line-blocks" added to keep one-line inline methods implementations - "close-templates" added - places template angle bracket together --- astylerc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/astylerc b/astylerc index 0b407b9fe..d4e1188eb 100644 --- a/astylerc +++ b/astylerc @@ -6,6 +6,6 @@ min-conditional-indent=1 pad-oper pad-header unpad-paren -delete-empty-lines align-pointer=type - +keep-one-line-blocks +close-templates From decf4105159a29597a99e4e3d8cb7c08c9390448 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 29 Oct 2014 20:49:28 +0100 Subject: [PATCH 278/641] Update gas counting for SSTORE, no refunding yet [#81575908] --- libevmjit/GasMeter.cpp | 21 ++++++++------------- libevmjit/Type.h | 2 +- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/libevmjit/GasMeter.cpp b/libevmjit/GasMeter.cpp index 82b587dd8..d3f6c10f3 100644 --- a/libevmjit/GasMeter.cpp +++ b/libevmjit/GasMeter.cpp @@ -28,11 +28,9 @@ uint64_t getStepCost(Instruction inst) // TODO: Add this function to FeeSructure { case Instruction::STOP: case Instruction::SUICIDE: + case Instruction::SSTORE: // Handle cost of SSTORE separately in GasMeter::countSStore() return 0; - case Instruction::SSTORE: - return static_cast(c_sstoreResetGas); // FIXME: Check store gas - case Instruction::SLOAD: return static_cast(c_sloadGas); @@ -118,8 +116,7 @@ void GasMeter::count(Instruction _inst) m_checkCall = m_builder.CreateCall(m_gasCheckFunc, llvm::UndefValue::get(Type::i256)); } - if (_inst != Instruction::SSTORE) // Handle cost of SSTORE separately in countSStore() - m_blockCost += getStepCost(_inst); + m_blockCost += getStepCost(_inst); if (isCostBlockEnd(_inst)) commitCostBlock(); @@ -129,20 +126,18 @@ void GasMeter::countSStore(Ext& _ext, llvm::Value* _index, llvm::Value* _newValu { assert(!m_checkCall); // Everything should've been commited before - static const auto sstoreCost = static_cast(c_sstoreResetGas); // FIXME: Check store gas - - // [ADD] if oldValue == 0 and newValue != 0 => 2*cost - // [DEL] if oldValue != 0 and newValue == 0 => 0 + static const auto updateCost = static_cast(c_sstoreResetGas); // TODO: Discuss naming (DB names look better) + static const auto insertCost = static_cast(c_sstoreSetGas); auto oldValue = _ext.store(_index); auto oldValueIsZero = m_builder.CreateICmpEQ(oldValue, Constant::get(0), "oldValueIsZero"); auto newValueIsZero = m_builder.CreateICmpEQ(_newValue, Constant::get(0), "newValueIsZero"); auto oldValueIsntZero = m_builder.CreateICmpNE(oldValue, Constant::get(0), "oldValueIsntZero"); auto newValueIsntZero = m_builder.CreateICmpNE(_newValue, Constant::get(0), "newValueIsntZero"); - auto isAdd = m_builder.CreateAnd(oldValueIsZero, newValueIsntZero, "isAdd"); - auto isDel = m_builder.CreateAnd(oldValueIsntZero, newValueIsZero, "isDel"); - auto cost = m_builder.CreateSelect(isAdd, Constant::get(2 * sstoreCost), Constant::get(sstoreCost), "cost"); - cost = m_builder.CreateSelect(isDel, Constant::get(0), cost, "cost"); + auto isInsert = m_builder.CreateAnd(oldValueIsZero, newValueIsntZero, "isInsert"); + auto isDelete = m_builder.CreateAnd(oldValueIsntZero, newValueIsZero, "isDelete"); + auto cost = m_builder.CreateSelect(isInsert, Constant::get(insertCost), Constant::get(updateCost), "cost"); + cost = m_builder.CreateSelect(isDelete, Constant::get(0), cost, "cost"); createCall(m_gasCheckFunc, cost); } diff --git a/libevmjit/Type.h b/libevmjit/Type.h index b432f0813..21c41efc0 100644 --- a/libevmjit/Type.h +++ b/libevmjit/Type.h @@ -50,7 +50,7 @@ enum class ReturnCode struct Constant { /// Returns word-size constant - static llvm::ConstantInt* get(uint64_t _n); + static llvm::ConstantInt* get(uint64_t _n); // TODO: add overload with u256 static llvm::ConstantInt* get(ReturnCode _returnCode); }; From 56bd2c3411d5e94df0fd03e840cca38f8373b2ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 29 Oct 2014 21:23:16 +0100 Subject: [PATCH 279/641] Allow creating LLVM constants directly from u256 --- libevmjit/GasMeter.cpp | 5 +---- libevmjit/Type.cpp | 8 ++++++++ libevmjit/Type.h | 4 +++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/libevmjit/GasMeter.cpp b/libevmjit/GasMeter.cpp index d3f6c10f3..5f6f81e72 100644 --- a/libevmjit/GasMeter.cpp +++ b/libevmjit/GasMeter.cpp @@ -126,9 +126,6 @@ void GasMeter::countSStore(Ext& _ext, llvm::Value* _index, llvm::Value* _newValu { assert(!m_checkCall); // Everything should've been commited before - static const auto updateCost = static_cast(c_sstoreResetGas); // TODO: Discuss naming (DB names look better) - static const auto insertCost = static_cast(c_sstoreSetGas); - auto oldValue = _ext.store(_index); auto oldValueIsZero = m_builder.CreateICmpEQ(oldValue, Constant::get(0), "oldValueIsZero"); auto newValueIsZero = m_builder.CreateICmpEQ(_newValue, Constant::get(0), "newValueIsZero"); @@ -136,7 +133,7 @@ void GasMeter::countSStore(Ext& _ext, llvm::Value* _index, llvm::Value* _newValu auto newValueIsntZero = m_builder.CreateICmpNE(_newValue, Constant::get(0), "newValueIsntZero"); auto isInsert = m_builder.CreateAnd(oldValueIsZero, newValueIsntZero, "isInsert"); auto isDelete = m_builder.CreateAnd(oldValueIsntZero, newValueIsZero, "isDelete"); - auto cost = m_builder.CreateSelect(isInsert, Constant::get(insertCost), Constant::get(updateCost), "cost"); + auto cost = m_builder.CreateSelect(isInsert, Constant::get(c_sstoreSetGas), Constant::get(c_sstoreResetGas), "cost"); cost = m_builder.CreateSelect(isDelete, Constant::get(0), cost, "cost"); createCall(m_gasCheckFunc, cost); } diff --git a/libevmjit/Type.cpp b/libevmjit/Type.cpp index 5021473ff..33d571087 100644 --- a/libevmjit/Type.cpp +++ b/libevmjit/Type.cpp @@ -41,6 +41,14 @@ llvm::ConstantInt* Constant::get(uint64_t _n) return llvm::ConstantInt::get(Type::i256, _n); } +llvm::ConstantInt* Constant::get(u256 _n) +{ + auto limbs = _n.backend().limbs(); + auto words = reinterpret_cast(limbs); + llvm::APInt n(256, 4, words); + return static_cast(llvm::ConstantInt::get(Type::i256, n)); +} + llvm::ConstantInt* Constant::get(ReturnCode _returnCode) { return llvm::ConstantInt::get(Type::MainReturn, static_cast(_returnCode)); diff --git a/libevmjit/Type.h b/libevmjit/Type.h index 21c41efc0..c80e46777 100644 --- a/libevmjit/Type.h +++ b/libevmjit/Type.h @@ -3,6 +3,7 @@ #include #include +#include namespace dev { @@ -50,7 +51,8 @@ enum class ReturnCode struct Constant { /// Returns word-size constant - static llvm::ConstantInt* get(uint64_t _n); // TODO: add overload with u256 + static llvm::ConstantInt* get(uint64_t _n); + static llvm::ConstantInt* get(u256 _n); static llvm::ConstantInt* get(ReturnCode _returnCode); }; From 3f50913d95752663e5289672f6d6b06697b96bb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 29 Oct 2014 21:56:12 +0100 Subject: [PATCH 280/641] Fix u256 to APInt conversion --- libevmjit/Type.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libevmjit/Type.cpp b/libevmjit/Type.cpp index 33d571087..447da6a4b 100644 --- a/libevmjit/Type.cpp +++ b/libevmjit/Type.cpp @@ -43,9 +43,11 @@ llvm::ConstantInt* Constant::get(uint64_t _n) llvm::ConstantInt* Constant::get(u256 _n) { - auto limbs = _n.backend().limbs(); - auto words = reinterpret_cast(limbs); - llvm::APInt n(256, 4, words); + auto& backend = _n.backend(); + auto words = reinterpret_cast(backend.limbs()); + auto nWords = backend.limb_bits == 64 ? backend.size() : (backend.size() + 1) / 2; + llvm::APInt n(256, nWords, words); + assert(n.toString(10, false) == _n.str()); return static_cast(llvm::ConstantInt::get(Type::i256, n)); } From 236361044cadda0ecda7edd5445c386415b047a5 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Wed, 29 Oct 2014 22:13:25 +0000 Subject: [PATCH 281/641] Got rid of some gcc warnings --- libevmjit/Ext.cpp | 7 +++---- libevmjit/Memory.cpp | 26 +------------------------- libevmjit/VM.cpp | 2 ++ 3 files changed, 6 insertions(+), 29 deletions(-) diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index ef2681803..9484d9b26 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -31,14 +31,13 @@ struct ExtData }; Ext::Ext(RuntimeManager& _runtimeManager): - RuntimeHelper(_runtimeManager) + RuntimeHelper(_runtimeManager), + m_data() { auto&& ctx = m_builder.getContext(); auto module = getModule(); auto i256Ty = m_builder.getIntNTy(256); - auto i256PtrTy = i256Ty->getPointerTo(); - auto i8PtrTy = m_builder.getInt8PtrTy(); m_args[0] = m_builder.CreateAlloca(i256Ty, nullptr, "ext.index"); m_args[1] = m_builder.CreateAlloca(i256Ty, nullptr, "ext.value"); @@ -266,7 +265,7 @@ extern "C" *_ret = *reinterpret_cast(&hash); } - EXPORT void ext_exp(Runtime* _rt, i256* _left, i256* _right, i256* _ret) + EXPORT void ext_exp(Runtime*, i256* _left, i256* _right, i256* _ret) { bigint left = llvm2eth(*_left); bigint right = llvm2eth(*_right); diff --git a/libevmjit/Memory.cpp b/libevmjit/Memory.cpp index 63e97efc6..86c6e8e07 100644 --- a/libevmjit/Memory.cpp +++ b/libevmjit/Memory.cpp @@ -89,7 +89,7 @@ llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _ return func; } -llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, GasMeter& _gasMeter) +llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, GasMeter&) { auto isWord = _valueType == Type::i256; @@ -228,28 +228,4 @@ extern "C" return memory.data(); } - EXPORT void evmccrt_memory_dump(uint64_t _begin, uint64_t _end) - { - //if (_end == 0) - // _end = Runtime::getMemory().size(); - - //std::cerr << "MEMORY: active size: " << std::dec - // << Runtime::getMemory().size() / 32 << " words\n"; - //std::cerr << "MEMORY: dump from " << std::dec - // << _begin << " to " << _end << ":"; - //if (_end <= _begin) - // return; - - //_begin = _begin / 16 * 16; - //for (size_t i = _begin; i < _end; i++) - //{ - // if ((i - _begin) % 16 == 0) - // std::cerr << '\n' << std::dec << i << ": "; - - // auto b = Runtime::getMemory()[i]; - // std::cerr << std::hex << std::setw(2) << static_cast(b) << ' '; - //} - //std::cerr << std::endl; - } - } // extern "C" diff --git a/libevmjit/VM.cpp b/libevmjit/VM.cpp index c0a8c8605..b42b09499 100644 --- a/libevmjit/VM.cpp +++ b/libevmjit/VM.cpp @@ -31,6 +31,8 @@ bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const&, uint64_t) BOOST_THROW_EXCEPTION(StackTooSmall(1, 0)); case ReturnCode::BadInstruction: BOOST_THROW_EXCEPTION(BadInstruction()); + default: + break; } m_output = std::move(engine.returnData); From 4f5959ed641a1736c07b493f3a243ba63e5c598c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 30 Oct 2014 10:39:45 +0100 Subject: [PATCH 282/641] Remove old code --- libevmjit/Ext.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index ef2681803..bee65c564 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -24,12 +24,6 @@ inline u256 fromAddress(Address _a) return (u160)_a; } -struct ExtData -{ - const byte* calldata; - const byte* code; -}; - Ext::Ext(RuntimeManager& _runtimeManager): RuntimeHelper(_runtimeManager) { From e3ccbf8d49f358ec86e6b1c702d8810907ad08b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 30 Oct 2014 11:12:18 +0100 Subject: [PATCH 283/641] Increase refund counter if deleting a storage item [Delivers #81575908] --- evmcc/test/ext/store_delete.evm | 1 + evmcc/test/ext/store_delete.lll | 9 +++++++++ libevmjit/Ext.cpp | 8 +++++++- 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 evmcc/test/ext/store_delete.evm create mode 100644 evmcc/test/ext/store_delete.lll diff --git a/evmcc/test/ext/store_delete.evm b/evmcc/test/ext/store_delete.evm new file mode 100644 index 000000000..d6acae03d --- /dev/null +++ b/evmcc/test/ext/store_delete.evm @@ -0,0 +1 @@ +6104d26063576000606357 diff --git a/evmcc/test/ext/store_delete.lll b/evmcc/test/ext/store_delete.lll new file mode 100644 index 000000000..3d8f0f23a --- /dev/null +++ b/evmcc/test/ext/store_delete.lll @@ -0,0 +1,9 @@ + +(asm +1234 +99 +SSTORE +0 +99 +SSTORE +) \ No newline at end of file diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index bee65c564..09b350763 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -6,6 +6,7 @@ #include #include +#include #include "Runtime.h" #include "Type.h" @@ -179,7 +180,12 @@ extern "C" { auto index = llvm2eth(*_index); auto value = llvm2eth(*_value); - _rt->getExt().setStore(index, value); // Interface uses native endianness + auto& ext = _rt->getExt(); + + if (value == 0 && ext.store(index) != 0) // If delete + ext.sub.refunds += c_sstoreRefundGas; // Increase refund counter + + ext.setStore(index, value); // Interface uses native endianness } EXPORT void ext_calldataload(Runtime* _rt, i256* _index, i256* _value) From 8cfe2ee454334876926b30ca53b34c27e49cf056 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 30 Oct 2014 11:44:31 +0100 Subject: [PATCH 284/641] BNOT instruction [Delivers #81700198] --- evmcc/test/arith/arith_bnot.evm | 1 + evmcc/test/arith/arith_bnot.lll | 14 ++++++++++++++ libevmjit/Compiler.cpp | 11 ++++------- 3 files changed, 19 insertions(+), 7 deletions(-) create mode 100644 evmcc/test/arith/arith_bnot.evm create mode 100644 evmcc/test/arith/arith_bnot.lll diff --git a/evmcc/test/arith/arith_bnot.evm b/evmcc/test/arith/arith_bnot.evm new file mode 100644 index 000000000..4cfaf8f55 --- /dev/null +++ b/evmcc/test/arith/arith_bnot.evm @@ -0,0 +1 @@ +6201e2406000546000530960005460206000f2 diff --git a/evmcc/test/arith/arith_bnot.lll b/evmcc/test/arith/arith_bnot.lll new file mode 100644 index 000000000..a83b05a9a --- /dev/null +++ b/evmcc/test/arith/arith_bnot.lll @@ -0,0 +1,14 @@ + +(asm +123456 +0 +MSTORE +0 +MLOAD +BNOT +0 +MSTORE +32 +0 +RETURN +) \ No newline at end of file diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 8dc19e84c..6b8f094e3 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -372,14 +372,11 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, break; } - /*case Instruction::NEG: + case Instruction::BNOT: { - auto top = stack.pop(); - auto zero = Constant::get(0); - auto res = m_builder.CreateSub(zero, top); - stack.push(res); - break; - }*/ + auto value = stack.pop(); + auto ret = m_builder.CreateXor(value, llvm::APInt(256, -1, true), "bnot"); + } case Instruction::LT: { From 4c27c26af9ab1cdcb1009af9e27a59136a18b9cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 30 Oct 2014 12:22:59 +0100 Subject: [PATCH 285/641] Fix BNOT instruction [Delivers #81700198] --- libevmjit/Compiler.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 6b8f094e3..ab0f7efe7 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -376,6 +376,8 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, { auto value = stack.pop(); auto ret = m_builder.CreateXor(value, llvm::APInt(256, -1, true), "bnot"); + stack.push(ret); + break; } case Instruction::LT: From f8feca9dfc9dbd1966cf3d258c01f71a24590843 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Thu, 30 Oct 2014 12:56:52 +0000 Subject: [PATCH 286/641] SIGEXTEND: first try [#81700414] --- libevmjit/Compiler.cpp | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 8dc19e84c..ea74d1051 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -372,14 +372,14 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, break; } - /*case Instruction::NEG: + case Instruction::BNOT: { auto top = stack.pop(); - auto zero = Constant::get(0); - auto res = m_builder.CreateSub(zero, top); + auto allones = llvm::ConstantInt::get(Type::i256, llvm::APInt::getAllOnesValue(256)); + auto res = m_builder.CreateXor(top, allones); stack.push(res); break; - }*/ + } case Instruction::LT: { @@ -505,6 +505,35 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, break; } + case Instruction::SIGNEXTEND: + { + auto k = stack.pop(); + auto b = stack.pop(); + auto k32 = m_builder.CreateTrunc(k, m_builder.getIntNTy(5), "k_32"); + auto k32ext = m_builder.CreateZExt(k32, Type::i256); + auto k32x8 = m_builder.CreateMul(k32ext, Constant::get(8), "kx8"); + + // test for b >> (k * 8 + 7) + auto val = m_builder.CreateAdd(k32x8, llvm::ConstantInt::get(Type::i256, 7)); + auto tmp = m_builder.CreateAShr(b, val); + auto bitset = m_builder.CreateTrunc(tmp, m_builder.getInt1Ty()); + + // shift left by (31 - k) * 8 = (248 - k*8), then do arithmetic shr by the same amount. + auto shiftSize = m_builder.CreateSub(llvm::ConstantInt::get(Type::i256, 31 * 8), k32x8); + auto bshl = m_builder.CreateShl(b, shiftSize); + auto bshr = m_builder.CreateAShr(bshl, shiftSize); + + // bshr is our final value if 0 <= k <= 30 and bitset is true, + // otherwise we push back b unchanged + auto kInRange = m_builder.CreateICmpULE(k, llvm::ConstantInt::get(Type::i256, 30)); + auto cond = m_builder.CreateAnd(kInRange, bitset); + + auto result = m_builder.CreateSelect(cond, bshr, b); + stack.push(result); + + break; + } + case Instruction::SHA3: { auto inOff = stack.pop(); From c32e1e05b3e1c6a4535909650c8bc6a32388ba2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 30 Oct 2014 15:50:44 +0100 Subject: [PATCH 287/641] Fix case where JUMPI is the last instruction --- evmcc/test/jump/jumpi_at_the_end.evm | 1 + evmcc/test/jump/jumpi_at_the_end.lll | 1 + evmcc/test/vmtests/vm_jump.json | 41 ++++++++++++++++++++++++++++ libevmjit/Compiler.cpp | 11 ++------ 4 files changed, 46 insertions(+), 8 deletions(-) create mode 100644 evmcc/test/jump/jumpi_at_the_end.evm create mode 100644 evmcc/test/jump/jumpi_at_the_end.lll create mode 100644 evmcc/test/vmtests/vm_jump.json diff --git a/evmcc/test/jump/jumpi_at_the_end.evm b/evmcc/test/jump/jumpi_at_the_end.evm new file mode 100644 index 000000000..2d7411761 --- /dev/null +++ b/evmcc/test/jump/jumpi_at_the_end.evm @@ -0,0 +1 @@ +600a6000545d6000536001900380600054600659 diff --git a/evmcc/test/jump/jumpi_at_the_end.lll b/evmcc/test/jump/jumpi_at_the_end.lll new file mode 100644 index 000000000..263ada6a7 --- /dev/null +++ b/evmcc/test/jump/jumpi_at_the_end.lll @@ -0,0 +1 @@ +(asm 10 0 MSTORE JUMPDEST 0 MLOAD 1 SWAP1 SUB DUP1 0 MSTORE 6 JUMPI) \ No newline at end of file diff --git a/evmcc/test/vmtests/vm_jump.json b/evmcc/test/vmtests/vm_jump.json new file mode 100644 index 000000000..6b63edeae --- /dev/null +++ b/evmcc/test/vmtests/vm_jump.json @@ -0,0 +1,41 @@ +{ + "jumpi_at_the_end" : { + "callcreates" : [ ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "10000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "code" : "(asm 10 0 MSTORE JUMPDEST 0 MLOAD 1 SWAP1 SUB DUP1 0 MSTORE 6 JUMPI)", + "data" : "0x", + "gas" : "1000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "895", + "out" : "0x0", + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "(asm 10 0 MSTORE JUMPDEST 0 MLOAD 1 SWAP1 SUB DUP1 0 MSTORE 6 JUMPI)", + "nonce" : "0", + "storage" : {} + } + }, + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "(asm 10 0 MSTORE JUMPDEST 0 MLOAD 1 SWAP1 SUB DUP1 0 MSTORE 6 JUMPI)", + "nonce" : "0", + "storage" : {} + } + } + } +} diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index ab0f7efe7..593820b8c 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -609,9 +609,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, { auto pairIter = m_directJumpTargets.find(currentPC); if (pairIter != m_directJumpTargets.end()) - { targetBlock = pairIter->second; - } } if (inst == Instruction::JUMP) @@ -624,9 +622,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, m_builder.CreateBr(targetBlock); } else - { m_builder.CreateBr(m_jumpTableBlock->llvm()); - } } else // JUMPI { @@ -635,8 +631,9 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto zero = Constant::get(0); auto cond = m_builder.CreateICmpNE(val, zero, "nonzero"); - // Assume the basic blocks are properly ordered: - assert(nextBasicBlock); // FIXME: JUMPI can be last instruction + + if (!nextBasicBlock) // In case JUMPI is the last instruction + nextBasicBlock = m_stopBB; if (targetBlock) { @@ -644,9 +641,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, m_builder.CreateCondBr(cond, targetBlock, nextBasicBlock); } else - { m_builder.CreateCondBr(cond, m_jumpTableBlock->llvm(), nextBasicBlock); - } } break; From c11867553240f36245f88067dcaafc12063905bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 30 Oct 2014 16:29:14 +0100 Subject: [PATCH 288/641] Improve PUSH compilation --- libevmjit/Compiler.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 939c4a275..c104ec092 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -552,16 +552,15 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, case Instruction::ANY_PUSH: { - auto numBytes = static_cast(inst) - static_cast(Instruction::PUSH1) + 1; + const auto numBytes = static_cast(inst) - static_cast(Instruction::PUSH1) + 1; auto value = llvm::APInt(256, 0); - for (decltype(numBytes) i = 0; i < numBytes; ++i) // TODO: Use pc as iterator + for (auto lastPC = currentPC + numBytes; currentPC < lastPC;) { - ++currentPC; value <<= 8; - value |= bytecode[currentPC]; + value |= bytecode[++currentPC]; } - auto c = m_builder.getInt(value); - stack.push(c); + + stack.push(m_builder.getInt(value)); break; } From 1dc5bece058979a229cfccca3c45a3e468914897 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 30 Oct 2014 17:32:20 +0100 Subject: [PATCH 289/641] Fix MSIZE and memory resize step [Delivers #81777708] --- libevmjit/Memory.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libevmjit/Memory.cpp b/libevmjit/Memory.cpp index 86c6e8e07..84aa105fe 100644 --- a/libevmjit/Memory.cpp +++ b/libevmjit/Memory.cpp @@ -74,7 +74,8 @@ llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _ m_builder.SetInsertPoint(resizeBB); // Check gas first auto wordsRequired = m_builder.CreateUDiv(m_builder.CreateAdd(sizeRequired, Constant::get(31)), Constant::get(32), "wordsRequired"); - auto words = m_builder.CreateUDiv(m_builder.CreateAdd(size, Constant::get(31)), Constant::get(32), "words"); + sizeRequired = m_builder.CreateMul(wordsRequired, Constant::get(32), "roundedSizeRequired"); + auto words = m_builder.CreateUDiv(size, Constant::get(32), "words"); // size is always 32*k auto newWords = m_builder.CreateSub(wordsRequired, words, "addtionalWords"); _gasMeter.checkMemory(newWords, m_builder); // Resize From 250374180385fd36351d733c0363b073989be243 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Thu, 30 Oct 2014 16:42:44 +0000 Subject: [PATCH 290/641] CMakeLists updated, should now build without LLVM when EVMJIT is not enabled [#81588646] --- CMakeLists.txt | 17 +++++++++++++---- eth/CMakeLists.txt | 2 +- evmcc/CMakeLists.txt | 7 ++----- exp/CMakeLists.txt | 2 +- libevmjit/CMakeLists.txt | 7 +++---- neth/CMakeLists.txt | 2 +- test/CMakeLists.txt | 9 ++++++--- 7 files changed, 27 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 53fe2684b..4c1cf55c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,7 @@ function(createDefaultCacheConfig) set(LANGUAGES OFF CACHE BOOL "Limit build to Serpent/LLL tools") set(VMTRACE OFF CACHE BOOL "VM tracing and run-time checks (useful for cross-implementation VM debugging)") set(PARANOIA OFF CACHE BOOL "Additional run-time checks") + set(EVMJIT OFF CACHE BOOL "Build a just-in-time compiler for EVM code (requires LLVM)") endfunction() @@ -39,6 +40,14 @@ function(configureProject) message(FATAL_ERROR "VM tracing requires debug.") endif () endif () + + if (EVMJIT) + if (LANGUAGES) + message(FATAL_ERROR "Unset LANGUAGES to build EVMJIT") + else() + add_definitions(-DETH_EVMJIT) + endif() + endif() endfunction() @@ -75,7 +84,7 @@ cmake_policy(SET CMP0015 NEW) createDefaultCacheConfig() configureProject() -message("-- LANGUAGES: ${LANGUAGES}; VMTRACE: ${VMTRACE}; PARANOIA: ${PARANOIA}; HEADLESS: ${HEADLESS}") +message("-- LANGUAGES: ${LANGUAGES}; VMTRACE: ${VMTRACE}; PARANOIA: ${PARANOIA}; HEADLESS: ${HEADLESS}; EVMJIT: ${EVMJIT}") # Default TARGET_PLATFORM to "linux". @@ -158,9 +167,9 @@ if (NOT LANGUAGES) endif() endif() -if (EVMCC) - add_subdirectory(libevmjit) - add_subdirectory(evmcc) +if (EVMJIT) + add_subdirectory(libevmjit) + add_subdirectory(evmcc) endif() diff --git a/eth/CMakeLists.txt b/eth/CMakeLists.txt index 274700ee7..d04cac504 100644 --- a/eth/CMakeLists.txt +++ b/eth/CMakeLists.txt @@ -15,7 +15,7 @@ target_link_libraries(${EXECUTABLE} webthree) target_link_libraries(${EXECUTABLE} secp256k1) target_link_libraries(${EXECUTABLE} gmp) -if(EVMCC) +if(EVMJIT) target_link_libraries(${EXECUTABLE} evmjit) endif() diff --git a/evmcc/CMakeLists.txt b/evmcc/CMakeLists.txt index 52ce6ec38..230013aef 100644 --- a/evmcc/CMakeLists.txt +++ b/evmcc/CMakeLists.txt @@ -25,8 +25,6 @@ if ("${TARGET_PLATFORM}" STREQUAL "w64") target_link_libraries(${EXECUTABLE} iphlpapi) target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) -elseif (UNIX) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") else () find_package(Threads REQUIRED) target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) @@ -42,13 +40,12 @@ message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") include_directories(${LLVM_INCLUDE_DIRS}) add_definitions(${LLVM_DEFINITIONS}) -llvm_map_components_to_libnames(llvm_libs core support mcjit x86asmparser x86codegen) -target_link_libraries(evmcc ${llvm_libs}) +# llvm_map_components_to_libnames(llvm_libs core support mcjit x86asmparser x86codegen) +# target_link_libraries(evmcc ${llvm_libs}) # end of LLVM specific commands - install( TARGETS ${EXECUTABLE} DESTINATION bin ) cmake_policy(SET CMP0015 NEW) diff --git a/exp/CMakeLists.txt b/exp/CMakeLists.txt index c671f240f..fce739007 100644 --- a/exp/CMakeLists.txt +++ b/exp/CMakeLists.txt @@ -17,7 +17,7 @@ target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) -if(EVMCC) +if(EVMJIT) target_link_libraries(${EXECUTABLE} evmjit) endif() diff --git a/libevmjit/CMakeLists.txt b/libevmjit/CMakeLists.txt index f461c16cf..cc63e72db 100644 --- a/libevmjit/CMakeLists.txt +++ b/libevmjit/CMakeLists.txt @@ -20,6 +20,7 @@ target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} evm) target_link_libraries(${EXECUTABLE} evmface) + if ("${TARGET_PLATFORM}" STREQUAL "w64") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") target_link_libraries(${EXECUTABLE} gcc) @@ -30,14 +31,12 @@ if ("${TARGET_PLATFORM}" STREQUAL "w64") target_link_libraries(${EXECUTABLE} iphlpapi) target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) -elseif (UNIX) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") else () find_package(Threads REQUIRED) target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) endif () -# LLVM specific commands +# LLVM specific config find_package(LLVM REQUIRED CONFIG) @@ -50,7 +49,7 @@ add_definitions(${LLVM_DEFINITIONS}) llvm_map_components_to_libnames(llvm_libs core support mcjit x86asmparser x86codegen) target_link_libraries(evmjit ${llvm_libs}) -# end of LLVM specific commands +# end of LLVM specific config diff --git a/neth/CMakeLists.txt b/neth/CMakeLists.txt index 184fc7104..d1b3fb441 100644 --- a/neth/CMakeLists.txt +++ b/neth/CMakeLists.txt @@ -24,7 +24,7 @@ if(JSONRPC_LS) target_link_libraries(${EXECUTABLE} ${JSONRPC_LS}) endif() -if(EVMCC) +if(EVMJIT) target_link_libraries(${EXECUTABLE} evmjit) endif() diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 16eb0f40e..17dda74d2 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -7,7 +7,6 @@ include_directories(..) link_directories(../libethcore) link_directories(../libethereum) link_directories(../libevm) -link_directories(../libevmjit) file(GLOB HEADERS "*.h") add_executable(testeth ${SRC_LIST} ${HEADERS}) @@ -20,13 +19,17 @@ target_link_libraries(testeth gmp) target_link_libraries(testeth solidity) target_link_libraries(testeth ${CRYPTOPP_LS}) target_link_libraries(testeth evm) -target_link_libraries(testeth evmjit) +if (EVMJIT) + target_link_libraries(testeth evmjit) +endif() target_link_libraries(createRandomTest ethereum) target_link_libraries(createRandomTest ethcore) target_link_libraries(createRandomTest boost_chrono) target_link_libraries(createRandomTest boost_unit_test_framework) -target_link_libraries(createRandomTest evmjit) +if (EVMJIT) + target_link_libraries(createRandomTest evmjit) +endif() if ("${TARGET_PLATFORM}" STREQUAL "w64") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") From feaa976c884644f00c4b865b1e725ea657d0d2ed Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Thu, 30 Oct 2014 16:46:01 +0000 Subject: [PATCH 291/641] Cleaning up warnings and build dependencies [#81588646] --- evmcc/evmcc.cpp | 2 - libevm/VMFace.cpp | 3 +- libevmjit/Compiler.cpp | 12 +- libevmjit/Compiler.cpp.orig | 962 ++++++++++++++++++++++++++++++++++ libevmjit/ExecutionEngine.cpp | 7 +- windows/LLVM.props | 2 +- 6 files changed, 978 insertions(+), 10 deletions(-) create mode 100644 libevmjit/Compiler.cpp.orig diff --git a/evmcc/evmcc.cpp b/evmcc/evmcc.cpp index 1e0b7e1cd..047fdf252 100644 --- a/evmcc/evmcc.cpp +++ b/evmcc/evmcc.cpp @@ -8,8 +8,6 @@ #include -#include - #include #include #include diff --git a/libevm/VMFace.cpp b/libevm/VMFace.cpp index 03f228ad0..3313ee926 100644 --- a/libevm/VMFace.cpp +++ b/libevm/VMFace.cpp @@ -25,9 +25,10 @@ using namespace dev::eth; std::unique_ptr VMFace::create(VMFace::Kind _kind, u256 _gas) { std::unique_ptr vm; -#if ETH_JIT +#if ETH_EVMJIT vm.reset(_kind == Kind::JIT ? static_cast(new jit::VM) : new VM); #else + (void) _kind; // suppress unused var warning vm.reset(new VM); #endif vm->reset(_gas); diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index d7a87b508..befb843e2 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -33,7 +33,9 @@ namespace jit { Compiler::Compiler(): - m_builder(llvm::getGlobalContext()) + m_builder(llvm::getGlobalContext()), + m_jumpTableBlock(), + m_badJumpBlock() { Type::init(m_builder.getContext()); } @@ -137,8 +139,8 @@ void Compiler::createBasicBlocks(bytesConstRef bytecode) } m_stopBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Stop", m_mainFunc); - m_badJumpBlock = std::make_unique("BadJumpBlock", m_mainFunc, m_builder); - m_jumpTableBlock = std::make_unique("JumpTableBlock", m_mainFunc, m_builder); + m_badJumpBlock = std::unique_ptr(new BasicBlock("BadJumpBlock", m_mainFunc, m_builder)); + m_jumpTableBlock = std::unique_ptr(new BasicBlock("JumpTableBlock", m_mainFunc, m_builder)); for (auto it = directJumpTargets.cbegin(); it != directJumpTargets.cend(); ++it) { @@ -170,7 +172,7 @@ void Compiler::createBasicBlocks(bytesConstRef bytecode) std::unique_ptr Compiler::compile(bytesConstRef bytecode) { - auto module = std::make_unique("main", m_builder.getContext()); + auto module = std::unique_ptr(new llvm::Module("main", m_builder.getContext())); // Create main function llvm::Type* mainFuncArgTypes[] = {m_builder.getInt32Ty(), Type::RuntimePtr}; // There must be int in first place because LLVM does not support other signatures @@ -513,7 +515,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto k32 = m_builder.CreateZExt(k32_, Type::i256); auto k32x8 = m_builder.CreateMul(k32, Constant::get(8), "kx8"); - // test for b >> (k * 8 + 7) + // test for word >> (k * 8 + 7) auto bitpos = m_builder.CreateAdd(k32x8, Constant::get(7), "bitpos"); auto bitval = m_builder.CreateLShr(word, bitpos, "bitval"); auto bittest = m_builder.CreateTrunc(bitval, m_builder.getInt1Ty(), "bittest"); diff --git a/libevmjit/Compiler.cpp.orig b/libevmjit/Compiler.cpp.orig new file mode 100644 index 000000000..a7d2b116c --- /dev/null +++ b/libevmjit/Compiler.cpp.orig @@ -0,0 +1,962 @@ + +#include "Compiler.h" + +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#include "Type.h" +#include "Memory.h" +#include "Stack.h" +#include "Ext.h" +#include "GasMeter.h" +#include "Utils.h" +#include "Endianness.h" +#include "Arith256.h" +#include "Runtime.h" + +namespace dev +{ +namespace eth +{ +namespace jit +{ + +Compiler::Compiler(): + m_builder(llvm::getGlobalContext()) +{ + Type::init(m_builder.getContext()); +} + +void Compiler::createBasicBlocks(bytesConstRef bytecode) +{ + std::set splitPoints; // Sorted collections of instruction indices where basic blocks start/end + + std::map directJumpTargets; + std::vector indirectJumpTargets; + boost::dynamic_bitset<> validJumpTargets(std::max(bytecode.size(), size_t(1))); + + splitPoints.insert(0); // First basic block + validJumpTargets[0] = true; + + for (auto curr = bytecode.begin(); curr != bytecode.end(); ++curr) + { + ProgramCounter currentPC = curr - bytecode.begin(); + validJumpTargets[currentPC] = true; + + auto inst = static_cast(*curr); + switch (inst) + { + + case Instruction::ANY_PUSH: + { + auto numBytes = static_cast(inst) - static_cast(Instruction::PUSH1) + 1; + auto next = curr + numBytes + 1; + if (next >= bytecode.end()) + break; + + auto nextInst = static_cast(*next); + + if (nextInst == Instruction::JUMP || nextInst == Instruction::JUMPI) + { + // Compute target PC of the jump. + u256 val = 0; + for (auto iter = curr + 1; iter < next; ++iter) + { + val <<= 8; + val |= *iter; + } + + // Create a block for the JUMP target. + ProgramCounter targetPC = val < bytecode.size() ? val.convert_to() : bytecode.size(); + splitPoints.insert(targetPC); + + ProgramCounter jumpPC = (next - bytecode.begin()); + directJumpTargets[jumpPC] = targetPC; + } + + curr += numBytes; + break; + } + + case Instruction::JUMPDEST: + { + // A basic block starts at the next instruction. + if (currentPC + 1 < bytecode.size()) + { + splitPoints.insert(currentPC + 1); + indirectJumpTargets.push_back(currentPC + 1); + } + break; + } + + case Instruction::JUMP: + case Instruction::JUMPI: + case Instruction::RETURN: + case Instruction::STOP: + case Instruction::SUICIDE: + { + // Create a basic block starting at the following instruction. + if (curr + 1 < bytecode.end()) + { + splitPoints.insert(currentPC + 1); + } + break; + } + + default: + break; + } + } + + // Remove split points generated from jumps out of code or into data. + for (auto it = splitPoints.cbegin(); it != splitPoints.cend();) + { + if (*it > bytecode.size() || !validJumpTargets[*it]) + it = splitPoints.erase(it); + else + ++it; + } + + for (auto it = splitPoints.cbegin(); it != splitPoints.cend();) + { + auto beginInstIdx = *it; + ++it; + auto endInstIdx = it != splitPoints.cend() ? *it : bytecode.size(); + basicBlocks.emplace(std::piecewise_construct, std::forward_as_tuple(beginInstIdx), std::forward_as_tuple(beginInstIdx, endInstIdx, m_mainFunc, m_builder)); + } + + m_stopBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Stop", m_mainFunc); + m_badJumpBlock = std::make_unique("BadJumpBlock", m_mainFunc, m_builder); + m_jumpTableBlock = std::make_unique("JumpTableBlock", m_mainFunc, m_builder); + + for (auto it = directJumpTargets.cbegin(); it != directJumpTargets.cend(); ++it) + { + if (it->second >= bytecode.size()) + { + // Jumping out of code means STOP + m_directJumpTargets[it->first] = m_stopBB; + continue; + } + + auto blockIter = basicBlocks.find(it->second); + if (blockIter != basicBlocks.end()) + { + m_directJumpTargets[it->first] = blockIter->second.llvm(); + } + else + { + clog(JIT) << "Bad JUMP at PC " << it->first + << ": " << it->second << " is not a valid PC"; + m_directJumpTargets[it->first] = m_badJumpBlock->llvm(); + } + } + + for (auto it = indirectJumpTargets.cbegin(); it != indirectJumpTargets.cend(); ++it) + { + m_indirectJumpTargets.push_back(&basicBlocks.find(*it)->second); + } +} + +std::unique_ptr Compiler::compile(bytesConstRef bytecode) +{ + auto module = std::make_unique("main", m_builder.getContext()); + + // Create main function + llvm::Type* mainFuncArgTypes[] = {m_builder.getInt32Ty(), Type::RuntimePtr}; // There must be int in first place because LLVM does not support other signatures + auto mainFuncType = llvm::FunctionType::get(Type::MainReturn, mainFuncArgTypes, false); + m_mainFunc = llvm::Function::Create(mainFuncType, llvm::Function::ExternalLinkage, "main", module.get()); + m_mainFunc->arg_begin()->getNextNode()->setName("rt"); + + // Create the basic blocks. + auto entryBlock = llvm::BasicBlock::Create(m_builder.getContext(), "entry", m_mainFunc); + m_builder.SetInsertPoint(entryBlock); + + createBasicBlocks(bytecode); + + // Init runtime structures. + RuntimeManager runtimeManager(m_builder); + GasMeter gasMeter(m_builder, runtimeManager); + Memory memory(runtimeManager, gasMeter); + Ext ext(runtimeManager); + Stack stack(m_builder, runtimeManager); + Arith256 arith(m_builder); + + m_builder.CreateBr(basicBlocks.begin()->second); + + for (auto basicBlockPairIt = basicBlocks.begin(); basicBlockPairIt != basicBlocks.end(); ++basicBlockPairIt) + { + auto& basicBlock = basicBlockPairIt->second; + auto iterCopy = basicBlockPairIt; + ++iterCopy; + auto nextBasicBlock = (iterCopy != basicBlocks.end()) ? iterCopy->second.llvm() : nullptr; + compileBasicBlock(basicBlock, bytecode, runtimeManager, arith, memory, ext, gasMeter, nextBasicBlock); + } + + // Code for special blocks: + // TODO: move to separate function. + // Note: Right now the codegen for special blocks depends only on createBasicBlock(), + // not on the codegen for 'regular' blocks. But it has to be done before linkBasicBlocks(). + m_builder.SetInsertPoint(m_stopBB); + m_builder.CreateRet(Constant::get(ReturnCode::Stop)); + + m_builder.SetInsertPoint(m_badJumpBlock->llvm()); + m_builder.CreateRet(Constant::get(ReturnCode::BadJumpDestination)); + + m_builder.SetInsertPoint(m_jumpTableBlock->llvm()); + if (m_indirectJumpTargets.size() > 0) + { + auto dest = m_jumpTableBlock->localStack().pop(); + auto switchInstr = m_builder.CreateSwitch(dest, m_badJumpBlock->llvm(), + m_indirectJumpTargets.size()); + for (auto it = m_indirectJumpTargets.cbegin(); it != m_indirectJumpTargets.cend(); ++it) + { + auto& bb = *it; + auto dest = Constant::get(bb->begin()); + switchInstr->addCase(dest, bb->llvm()); + } + } + else + { + m_builder.CreateBr(m_badJumpBlock->llvm()); + } + + removeDeadBlocks(); + + if (getenv("EVMCC_DEBUG_BLOCKS")) + { + std::ofstream ofs("blocks-init.dot"); + dumpBasicBlockGraph(ofs); + ofs.close(); + std::cerr << "\n\nAfter dead block elimination \n\n"; + dump(); + } + + //if (getenv("EVMCC_OPTIMIZE_STACK")) + //{ + std::vector blockList; + for (auto& entry : basicBlocks) + blockList.push_back(&entry.second); + + if (m_jumpTableBlock != nullptr) + blockList.push_back(m_jumpTableBlock.get()); + + BasicBlock::linkLocalStacks(blockList, m_builder); + + if (getenv("EVMCC_DEBUG_BLOCKS")) + { + std::ofstream ofs("blocks-opt.dot"); + dumpBasicBlockGraph(ofs); + ofs.close(); + std::cerr << "\n\nAfter stack optimization \n\n"; + dump(); + } + //} + + for (auto& entry : basicBlocks) + entry.second.localStack().synchronize(stack); + if (m_jumpTableBlock != nullptr) + m_jumpTableBlock->localStack().synchronize(stack); + + if (getenv("EVMCC_DEBUG_BLOCKS")) + { + std::ofstream ofs("blocks-sync.dot"); + dumpBasicBlockGraph(ofs); + ofs.close(); + std::cerr << "\n\nAfter stack synchronization \n\n"; + dump(); + } + + llvm::FunctionPassManager fpManager(module.get()); + fpManager.add(llvm::createLowerSwitchPass()); + fpManager.doInitialization(); + fpManager.run(*m_mainFunc); + + return module; +} + + +void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, RuntimeManager& _runtimeManager, Arith256& arith, Memory& memory, Ext& ext, GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock) +{ + m_builder.SetInsertPoint(basicBlock.llvm()); + auto& stack = basicBlock.localStack(); + + for (auto currentPC = basicBlock.begin(); currentPC != basicBlock.end(); ++currentPC) + { + auto inst = static_cast(bytecode[currentPC]); + + gasMeter.count(inst); + + switch (inst) + { + + case Instruction::ADD: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto result = m_builder.CreateAdd(lhs, rhs); + stack.push(result); + break; + } + + case Instruction::SUB: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto result = m_builder.CreateSub(lhs, rhs); + stack.push(result); + break; + } + + case Instruction::MUL: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = arith.mul(lhs, rhs); + stack.push(res); + break; + } + + case Instruction::DIV: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = arith.div(lhs, rhs); + stack.push(res); + break; + } + + case Instruction::SDIV: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = arith.sdiv(lhs, rhs); + stack.push(res); + break; + } + + case Instruction::MOD: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = arith.mod(lhs, rhs); + stack.push(res); + break; + } + + case Instruction::SMOD: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = arith.smod(lhs, rhs); + stack.push(res); + break; + } + + case Instruction::EXP: + { + auto left = stack.pop(); + auto right = stack.pop(); + auto ret = ext.exp(left, right); + stack.push(ret); + break; + } + + case Instruction::BNOT: + { +<<<<<<< HEAD + auto top = stack.pop(); + auto allones = llvm::ConstantInt::get(Type::i256, llvm::APInt::getAllOnesValue(256)); + auto res = m_builder.CreateXor(top, allones); + stack.push(res); +======= + auto value = stack.pop(); + auto ret = m_builder.CreateXor(value, llvm::APInt(256, -1, true), "bnot"); + stack.push(ret); +>>>>>>> cd8727a1e4786caaccf7fbbffd178edcc7aa3c35 + break; + } + + case Instruction::LT: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res1 = m_builder.CreateICmpULT(lhs, rhs); + auto res256 = m_builder.CreateZExt(res1, Type::i256); + stack.push(res256); + break; + } + + case Instruction::GT: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res1 = m_builder.CreateICmpUGT(lhs, rhs); + auto res256 = m_builder.CreateZExt(res1, Type::i256); + stack.push(res256); + break; + } + + case Instruction::SLT: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res1 = m_builder.CreateICmpSLT(lhs, rhs); + auto res256 = m_builder.CreateZExt(res1, Type::i256); + stack.push(res256); + break; + } + + case Instruction::SGT: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res1 = m_builder.CreateICmpSGT(lhs, rhs); + auto res256 = m_builder.CreateZExt(res1, Type::i256); + stack.push(res256); + break; + } + + case Instruction::EQ: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res1 = m_builder.CreateICmpEQ(lhs, rhs); + auto res256 = m_builder.CreateZExt(res1, Type::i256); + stack.push(res256); + break; + } + + case Instruction::NOT: + { + auto top = stack.pop(); + auto iszero = m_builder.CreateICmpEQ(top, Constant::get(0), "iszero"); + auto result = m_builder.CreateZExt(iszero, Type::i256); + stack.push(result); + break; + } + + case Instruction::AND: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = m_builder.CreateAnd(lhs, rhs); + stack.push(res); + break; + } + + case Instruction::OR: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = m_builder.CreateOr(lhs, rhs); + stack.push(res); + break; + } + + case Instruction::XOR: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = m_builder.CreateXor(lhs, rhs); + stack.push(res); + break; + } + + case Instruction::BYTE: + { + const auto byteNum = stack.pop(); + auto value = stack.pop(); + + // + 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"); + value = m_builder.CreateZExt(byte, Type::i256); + + auto byteNumValid = m_builder.CreateICmpULT(byteNum, Constant::get(32)); + value = m_builder.CreateSelect(byteNumValid, value, Constant::get(0)); + stack.push(value); + + break; + } + + case Instruction::ADDMOD: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto mod = stack.pop(); + auto res = arith.addmod(lhs, rhs, mod); + stack.push(res); + break; + } + + case Instruction::MULMOD: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto mod = stack.pop(); + auto res = arith.mulmod(lhs, rhs, mod); + stack.push(res); + break; + } + + case Instruction::SIGNEXTEND: + { + auto k = stack.pop(); + auto b = stack.pop(); + auto k32 = m_builder.CreateTrunc(k, m_builder.getIntNTy(5), "k_32"); + auto k32ext = m_builder.CreateZExt(k32, Type::i256); + auto k32x8 = m_builder.CreateMul(k32ext, Constant::get(8), "kx8"); + + // test for b >> (k * 8 + 7) + auto val = m_builder.CreateAdd(k32x8, llvm::ConstantInt::get(Type::i256, 7)); + auto tmp = m_builder.CreateAShr(b, val); + auto bitset = m_builder.CreateTrunc(tmp, m_builder.getInt1Ty()); + + // shift left by (31 - k) * 8 = (248 - k*8), then do arithmetic shr by the same amount. + auto shiftSize = m_builder.CreateSub(llvm::ConstantInt::get(Type::i256, 31 * 8), k32x8); + auto bshl = m_builder.CreateShl(b, shiftSize); + auto bshr = m_builder.CreateAShr(bshl, shiftSize); + + // bshr is our final value if 0 <= k <= 30 and bitset is true, + // otherwise we push back b unchanged + auto kInRange = m_builder.CreateICmpULE(k, llvm::ConstantInt::get(Type::i256, 30)); + auto cond = m_builder.CreateAnd(kInRange, bitset); + + auto result = m_builder.CreateSelect(cond, bshr, b); + stack.push(result); + + break; + } + + case Instruction::SHA3: + { + auto inOff = stack.pop(); + auto inSize = stack.pop(); + memory.require(inOff, inSize); + auto hash = ext.sha3(inOff, inSize); + stack.push(hash); + break; + } + + case Instruction::POP: + { + stack.pop(); + break; + } + + case Instruction::ANY_PUSH: + { + auto numBytes = static_cast(inst) - static_cast(Instruction::PUSH1) + 1; + auto value = llvm::APInt(256, 0); + for (decltype(numBytes) i = 0; i < numBytes; ++i) // TODO: Use pc as iterator + { + ++currentPC; + value <<= 8; + value |= bytecode[currentPC]; + } + auto c = m_builder.getInt(value); + stack.push(c); + break; + } + + case Instruction::ANY_DUP: + { + auto index = static_cast(inst) - static_cast(Instruction::DUP1); + stack.dup(index); + break; + } + + case Instruction::ANY_SWAP: + { + auto index = static_cast(inst) - static_cast(Instruction::SWAP1) + 1; + stack.swap(index); + break; + } + + case Instruction::MLOAD: + { + auto addr = stack.pop(); + auto word = memory.loadWord(addr); + stack.push(word); + break; + } + + case Instruction::MSTORE: + { + auto addr = stack.pop(); + auto word = stack.pop(); + memory.storeWord(addr, word); + break; + } + + case Instruction::MSTORE8: + { + auto addr = stack.pop(); + auto word = stack.pop(); + memory.storeByte(addr, word); + break; + } + + case Instruction::MSIZE: + { + auto word = memory.getSize(); + stack.push(word); + break; + } + + case Instruction::SLOAD: + { + auto index = stack.pop(); + auto value = ext.store(index); + stack.push(value); + break; + } + + case Instruction::SSTORE: + { + auto index = stack.pop(); + auto value = stack.pop(); + gasMeter.countSStore(ext, index, value); + ext.setStore(index, value); + break; + } + + case Instruction::JUMP: + case Instruction::JUMPI: + { + // Generate direct jump iff: + // 1. this is not the first instruction in the block + // 2. m_directJumpTargets[currentPC] is defined (meaning that the previous instruction is a PUSH) + // Otherwise generate a indirect jump (a switch). + llvm::BasicBlock* targetBlock = nullptr; + if (currentPC != basicBlock.begin()) + { + auto pairIter = m_directJumpTargets.find(currentPC); + if (pairIter != m_directJumpTargets.end()) + { + targetBlock = pairIter->second; + } + } + + if (inst == Instruction::JUMP) + { + if (targetBlock) + { + // The target address is computed at compile time, + // just pop it without looking... + stack.pop(); + m_builder.CreateBr(targetBlock); + } + else + { + m_builder.CreateBr(m_jumpTableBlock->llvm()); + } + } + else // JUMPI + { + stack.swap(1); + auto val = stack.pop(); + auto zero = Constant::get(0); + auto cond = m_builder.CreateICmpNE(val, zero, "nonzero"); + + // Assume the basic blocks are properly ordered: + assert(nextBasicBlock); // FIXME: JUMPI can be last instruction + + if (targetBlock) + { + stack.pop(); + m_builder.CreateCondBr(cond, targetBlock, nextBasicBlock); + } + else + { + m_builder.CreateCondBr(cond, m_jumpTableBlock->llvm(), nextBasicBlock); + } + } + + break; + } + + case Instruction::JUMPDEST: + { + // Nothing to do + break; + } + + case Instruction::PC: + { + auto value = Constant::get(currentPC); + stack.push(value); + break; + } + + case Instruction::GAS: + case Instruction::ADDRESS: + case Instruction::CALLER: + case Instruction::ORIGIN: + case Instruction::CALLVALUE: + case Instruction::CALLDATASIZE: + case Instruction::CODESIZE: + case Instruction::GASPRICE: + case Instruction::PREVHASH: + case Instruction::COINBASE: + case Instruction::TIMESTAMP: + case Instruction::NUMBER: + case Instruction::DIFFICULTY: + case Instruction::GASLIMIT: + { + // Pushes an element of runtime data on stack + stack.push(_runtimeManager.get(inst)); + break; + } + + case Instruction::BALANCE: + { + auto address = stack.pop(); + auto value = ext.balance(address); + stack.push(value); + break; + } + + case Instruction::EXTCODESIZE: + { + auto addr = stack.pop(); + auto value = ext.codesizeAt(addr); + stack.push(value); + break; + } + + case Instruction::CALLDATACOPY: + { + auto destMemIdx = stack.pop(); + auto srcIdx = stack.pop(); + auto reqBytes = stack.pop(); + + auto srcPtr = _runtimeManager.getCallData(); + auto srcSize = _runtimeManager.get(RuntimeData::CallDataSize); + + memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); + break; + } + + case Instruction::CODECOPY: + { + auto destMemIdx = stack.pop(); + auto srcIdx = stack.pop(); + auto reqBytes = stack.pop(); + + auto srcPtr = _runtimeManager.getCode(); // TODO: Code & its size are constants, feature #80814234 + auto srcSize = _runtimeManager.get(RuntimeData::CodeSize); + + memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); + break; + } + + case Instruction::EXTCODECOPY: + { + auto extAddr = stack.pop(); + auto destMemIdx = stack.pop(); + auto srcIdx = stack.pop(); + auto reqBytes = stack.pop(); + + auto srcPtr = ext.codeAt(extAddr); + auto srcSize = ext.codesizeAt(extAddr); + + memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); + break; + } + + case Instruction::CALLDATALOAD: + { + auto index = stack.pop(); + auto value = ext.calldataload(index); + stack.push(value); + break; + } + + case Instruction::CREATE: + { + auto endowment = stack.pop(); + auto initOff = stack.pop(); + auto initSize = stack.pop(); + memory.require(initOff, initSize); + + auto address = ext.create(endowment, initOff, initSize); + stack.push(address); + break; + } + + case Instruction::CALL: + case Instruction::CALLCODE: + { + auto gas = stack.pop(); + auto codeAddress = stack.pop(); + auto value = stack.pop(); + auto inOff = stack.pop(); + auto inSize = stack.pop(); + auto outOff = stack.pop(); + auto outSize = stack.pop(); + + gasMeter.commitCostBlock(gas); + + // Require memory for the max of in and out buffers + auto inSizeReq = m_builder.CreateAdd(inOff, inSize, "inSizeReq"); + auto outSizeReq = m_builder.CreateAdd(outOff, outSize, "outSizeReq"); + auto cmp = m_builder.CreateICmpUGT(inSizeReq, outSizeReq); + auto sizeReq = m_builder.CreateSelect(cmp, inSizeReq, outSizeReq, "sizeReq"); + memory.require(sizeReq); + + auto receiveAddress = codeAddress; + if (inst == Instruction::CALLCODE) + receiveAddress = _runtimeManager.get(RuntimeData::Address); + + auto ret = ext.call(gas, receiveAddress, value, inOff, inSize, outOff, outSize, codeAddress); + gasMeter.giveBack(gas); + stack.push(ret); + break; + } + + case Instruction::RETURN: + { + auto index = stack.pop(); + auto size = stack.pop(); + + memory.require(index, size); + _runtimeManager.registerReturnData(index, size); + + m_builder.CreateRet(Constant::get(ReturnCode::Return)); + break; + } + + case Instruction::SUICIDE: + { + auto address = stack.pop(); + ext.suicide(address); + // Fall through + } + case Instruction::STOP: + { + m_builder.CreateRet(Constant::get(ReturnCode::Stop)); + break; + } + + default: // Invalid instruction - runtime exception + { + _runtimeManager.raiseException(ReturnCode::BadInstruction); + } + + } + } + + gasMeter.commitCostBlock(); + + if (!basicBlock.llvm()->getTerminator()) // If block not terminated + { + if (nextBasicBlock) + m_builder.CreateBr(nextBasicBlock); // Branch to the next block + else + m_builder.CreateRet(Constant::get(ReturnCode::Stop)); // Return STOP code + } +} + + + +void Compiler::removeDeadBlocks() +{ + // Remove dead basic blocks + auto sthErased = false; + do + { + sthErased = false; + for (auto it = basicBlocks.begin(); it != basicBlocks.end();) + { + auto llvmBB = it->second.llvm(); + if (llvm::pred_begin(llvmBB) == llvm::pred_end(llvmBB)) + { + llvmBB->eraseFromParent(); + basicBlocks.erase(it++); + sthErased = true; + } + else + ++it; + } + } + while (sthErased); + + // Remove jump table block if no predecessors + if (llvm::pred_begin(m_jumpTableBlock->llvm()) == llvm::pred_end(m_jumpTableBlock->llvm())) + { + m_jumpTableBlock->llvm()->eraseFromParent(); + m_jumpTableBlock.reset(); + } +} + +void Compiler::dumpBasicBlockGraph(std::ostream& out) +{ + out << "digraph BB {\n" + << " node [shape=record, fontname=Courier, fontsize=10];\n" + << " entry [share=record, label=\"entry block\"];\n"; + + std::vector blocks; + for (auto& pair : basicBlocks) + blocks.push_back(&pair.second); + if (m_jumpTableBlock) + blocks.push_back(m_jumpTableBlock.get()); + if (m_badJumpBlock) + blocks.push_back(m_badJumpBlock.get()); + + // std::map phiNodesPerBlock; + + // Output nodes + for (auto bb : blocks) + { + std::string blockName = bb->llvm()->getName(); + + std::ostringstream oss; + bb->dump(oss, true); + + out << " \"" << blockName << "\" [shape=record, label=\" { " << blockName << "|" << oss.str() << "} \"];\n"; + } + + // Output edges + for (auto bb : blocks) + { + std::string blockName = bb->llvm()->getName(); + + auto end = llvm::pred_end(bb->llvm()); + for (llvm::pred_iterator it = llvm::pred_begin(bb->llvm()); it != end; ++it) + { + out << " \"" << (*it)->getName().str() << "\" -> \"" << blockName << "\" [" + << ((m_jumpTableBlock.get() && *it == m_jumpTableBlock.get()->llvm()) ? "style = dashed, " : "") + //<< "label = \"" + //<< phiNodesPerBlock[bb] + << "];\n"; + } + } + + out << "}\n"; +} + +void Compiler::dump() +{ + for (auto& entry : basicBlocks) + entry.second.dump(); + if (m_jumpTableBlock != nullptr) + m_jumpTableBlock->dump(); +} + +} +} +} + diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp index c8ab85150..4c617d9ea 100644 --- a/libevmjit/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -1,9 +1,11 @@ - #include "ExecutionEngine.h" #include #include +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" + #include #include #include @@ -16,6 +18,9 @@ #include #include +#pragma GCC diagnostic pop + + #include #include "Runtime.h" diff --git a/windows/LLVM.props b/windows/LLVM.props index a5c6c4dc5..7a779144b 100644 --- a/windows/LLVM.props +++ b/windows/LLVM.props @@ -14,7 +14,7 @@ $(LLVMIncludeDir);%(AdditionalIncludeDirectories) 4800;%(DisableSpecificWarnings) - ETH_JIT=$(LLVMEnabled);%(PreprocessorDefinitions) + ETH_EVMJIT=$(LLVMEnabled);%(PreprocessorDefinitions) $(LLVMLibDir);%(AdditionalLibraryDirectories) From de7f0ac7b3e15418b34cc46163aa39b0219174fc Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Thu, 30 Oct 2014 16:47:43 +0000 Subject: [PATCH 292/641] New performance tests [Delivers #81578852] --- evmcc/test/vmtests/vmPerformanceTest.json | 90 ++++++++++++++++++++++- 1 file changed, 88 insertions(+), 2 deletions(-) diff --git a/evmcc/test/vmtests/vmPerformanceTest.json b/evmcc/test/vmtests/vmPerformanceTest.json index 1bcc2ec15..07baa6709 100644 --- a/evmcc/test/vmtests/vmPerformanceTest.json +++ b/evmcc/test/vmtests/vmPerformanceTest.json @@ -1,5 +1,47 @@ { - "for100000" : { + "mulmodloop" : { + "callcreates" : [ ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "code" : "0x60015d68010000000000000000908060010115600358", + "data" : "0x", + "gas" : "1000000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "0", + "out" : "0x0", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60015d68010000000000000000908060010115600358", + "nonce" : "0", + "storage" : { + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60015d68010000000000000000908060010115600358", + "nonce" : "0", + "storage" : { } + } + } + }, + + + "for-1e06" : { "callcreates" : [ ], "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", @@ -40,7 +82,7 @@ } }, - "recloop" : { + "recloop0x40000" : { "callcreates" : [ ], "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", @@ -166,4 +208,48 @@ } } }, + + "jumptable100" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "10000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "code" : "0x6127105d600190038060000e6104615961001b600160005458005d610026600260005458005d610031600360005458005d61003c600460005458005d610047600560005458005d610052600660005458005d61005d600760005458005d610068600860005458005d610073600960005458005d61007e600a60005458005d610089600b60005458005d610094600c60005458005d61009f600d60005458005d6100aa600e60005458005d6100b5600f60005458005d6100c0601060005458005d6100cb601160005458005d6100d6601260005458005d6100e1601360005458005d6100ec601460005458005d6100f7601560005458005d610102601660005458005d61010d601760005458005d610118601860005458005d610123601960005458005d61012e601a60005458005d610139601b60005458005d610144601c60005458005d61014f601d60005458005d61015a601e60005458005d610165601f60005458005d610170602060005458005d61017b602160005458005d610186602260005458005d610191602360005458005d61019c602460005458005d6101a7602560005458005d6101b2602660005458005d6101bd602760005458005d6101c8602860005458005d6101d3602960005458005d6101de602a60005458005d6101e9602b60005458005d6101f4602c60005458005d6101ff602d60005458005d61020a602e60005458005d610215602f60005458005d610220603060005458005d61022b603160005458005d610236603260005458005d610241603360005458005d61024c603460005458005d610257603560005458005d610262603660005458005d61026d603760005458005d610278603860005458005d610283603960005458005d61028e603a60005458005d610299603b60005458005d6102a4603c60005458005d6102af603d60005458005d6102ba603e60005458005d6102c5603f60005458005d6102d0604060005458005d6102db604160005458005d6102e6604260005458005d6102f1604360005458005d6102fc604460005458005d610307604560005458005d610312604660005458005d61031d604760005458005d610328604860005458005d610333604960005458005d61033e604a60005458005d610349604b60005458005d610354604c60005458005d61035f604d60005458005d61036a604e60005458005d610375604f60005458005d610380605060005458005d61038b605160005458005d610396605260005458005d6103a1605360005458005d6103ac605460005458005d6103b7605560005458005d6103c2605660005458005d6103cd605760005458005d6103d8605860005458005d6103e3605960005458005d6103ee605a60005458005d6103f9605b60005458005d610404605c60005458005d61040f605d60005458005d61041a605e60005458005d610425605f60005458005d610430606060005458005d61043b606160005458005d610446606260005458005d610451606360005458005d61045c606460005458005d610004585d60206000f2", + "data" : "0x", + "gas" : "10000000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "4900496", + "out" : "0x0000000000000000000000000000000000000000000000000000000000000064", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x6127105d600190038060000e6104615961001b600160005458005d610026600260005458005d610031600360005458005d61003c600460005458005d610047600560005458005d610052600660005458005d61005d600760005458005d610068600860005458005d610073600960005458005d61007e600a60005458005d610089600b60005458005d610094600c60005458005d61009f600d60005458005d6100aa600e60005458005d6100b5600f60005458005d6100c0601060005458005d6100cb601160005458005d6100d6601260005458005d6100e1601360005458005d6100ec601460005458005d6100f7601560005458005d610102601660005458005d61010d601760005458005d610118601860005458005d610123601960005458005d61012e601a60005458005d610139601b60005458005d610144601c60005458005d61014f601d60005458005d61015a601e60005458005d610165601f60005458005d610170602060005458005d61017b602160005458005d610186602260005458005d610191602360005458005d61019c602460005458005d6101a7602560005458005d6101b2602660005458005d6101bd602760005458005d6101c8602860005458005d6101d3602960005458005d6101de602a60005458005d6101e9602b60005458005d6101f4602c60005458005d6101ff602d60005458005d61020a602e60005458005d610215602f60005458005d610220603060005458005d61022b603160005458005d610236603260005458005d610241603360005458005d61024c603460005458005d610257603560005458005d610262603660005458005d61026d603760005458005d610278603860005458005d610283603960005458005d61028e603a60005458005d610299603b60005458005d6102a4603c60005458005d6102af603d60005458005d6102ba603e60005458005d6102c5603f60005458005d6102d0604060005458005d6102db604160005458005d6102e6604260005458005d6102f1604360005458005d6102fc604460005458005d610307604560005458005d610312604660005458005d61031d604760005458005d610328604860005458005d610333604960005458005d61033e604a60005458005d610349604b60005458005d610354604c60005458005d61035f604d60005458005d61036a604e60005458005d610375604f60005458005d610380605060005458005d61038b605160005458005d610396605260005458005d6103a1605360005458005d6103ac605460005458005d6103b7605560005458005d6103c2605660005458005d6103cd605760005458005d6103d8605860005458005d6103e3605960005458005d6103ee605a60005458005d6103f9605b60005458005d610404605c60005458005d61040f605d60005458005d61041a605e60005458005d610425605f60005458005d610430606060005458005d61043b606160005458005d610446606260005458005d610451606360005458005d61045c606460005458005d610004585d60206000f2", + "nonce" : "0", + "storage" : { + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x6127105d600190038060000e6104615961001b600160005458005d610026600260005458005d610031600360005458005d61003c600460005458005d610047600560005458005d610052600660005458005d61005d600760005458005d610068600860005458005d610073600960005458005d61007e600a60005458005d610089600b60005458005d610094600c60005458005d61009f600d60005458005d6100aa600e60005458005d6100b5600f60005458005d6100c0601060005458005d6100cb601160005458005d6100d6601260005458005d6100e1601360005458005d6100ec601460005458005d6100f7601560005458005d610102601660005458005d61010d601760005458005d610118601860005458005d610123601960005458005d61012e601a60005458005d610139601b60005458005d610144601c60005458005d61014f601d60005458005d61015a601e60005458005d610165601f60005458005d610170602060005458005d61017b602160005458005d610186602260005458005d610191602360005458005d61019c602460005458005d6101a7602560005458005d6101b2602660005458005d6101bd602760005458005d6101c8602860005458005d6101d3602960005458005d6101de602a60005458005d6101e9602b60005458005d6101f4602c60005458005d6101ff602d60005458005d61020a602e60005458005d610215602f60005458005d610220603060005458005d61022b603160005458005d610236603260005458005d610241603360005458005d61024c603460005458005d610257603560005458005d610262603660005458005d61026d603760005458005d610278603860005458005d610283603960005458005d61028e603a60005458005d610299603b60005458005d6102a4603c60005458005d6102af603d60005458005d6102ba603e60005458005d6102c5603f60005458005d6102d0604060005458005d6102db604160005458005d6102e6604260005458005d6102f1604360005458005d6102fc604460005458005d610307604560005458005d610312604660005458005d61031d604760005458005d610328604860005458005d610333604960005458005d61033e604a60005458005d610349604b60005458005d610354604c60005458005d61035f604d60005458005d61036a604e60005458005d610375604f60005458005d610380605060005458005d61038b605160005458005d610396605260005458005d6103a1605360005458005d6103ac605460005458005d6103b7605560005458005d6103c2605660005458005d6103cd605760005458005d6103d8605860005458005d6103e3605960005458005d6103ee605a60005458005d6103f9605b60005458005d610404605c60005458005d61040f605d60005458005d61041a605e60005458005d610425605f60005458005d610430606060005458005d61043b606160005458005d610446606260005458005d610451606360005458005d61045c606460005458005d610004585d60206000f2", + "nonce" : "0", + "storage" : { + } + } + } + }, + } From 46fc1a396ecddfe23f7082404b9bcb739b7e0868 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Thu, 30 Oct 2014 16:51:04 +0000 Subject: [PATCH 293/641] removed accidentally added *.orig file --- libevmjit/Compiler.cpp.orig | 962 ------------------------------------ 1 file changed, 962 deletions(-) delete mode 100644 libevmjit/Compiler.cpp.orig diff --git a/libevmjit/Compiler.cpp.orig b/libevmjit/Compiler.cpp.orig deleted file mode 100644 index a7d2b116c..000000000 --- a/libevmjit/Compiler.cpp.orig +++ /dev/null @@ -1,962 +0,0 @@ - -#include "Compiler.h" - -#include - -#include - -#include -#include -#include -#include - -#include -#include - -#include - -#include "Type.h" -#include "Memory.h" -#include "Stack.h" -#include "Ext.h" -#include "GasMeter.h" -#include "Utils.h" -#include "Endianness.h" -#include "Arith256.h" -#include "Runtime.h" - -namespace dev -{ -namespace eth -{ -namespace jit -{ - -Compiler::Compiler(): - m_builder(llvm::getGlobalContext()) -{ - Type::init(m_builder.getContext()); -} - -void Compiler::createBasicBlocks(bytesConstRef bytecode) -{ - std::set splitPoints; // Sorted collections of instruction indices where basic blocks start/end - - std::map directJumpTargets; - std::vector indirectJumpTargets; - boost::dynamic_bitset<> validJumpTargets(std::max(bytecode.size(), size_t(1))); - - splitPoints.insert(0); // First basic block - validJumpTargets[0] = true; - - for (auto curr = bytecode.begin(); curr != bytecode.end(); ++curr) - { - ProgramCounter currentPC = curr - bytecode.begin(); - validJumpTargets[currentPC] = true; - - auto inst = static_cast(*curr); - switch (inst) - { - - case Instruction::ANY_PUSH: - { - auto numBytes = static_cast(inst) - static_cast(Instruction::PUSH1) + 1; - auto next = curr + numBytes + 1; - if (next >= bytecode.end()) - break; - - auto nextInst = static_cast(*next); - - if (nextInst == Instruction::JUMP || nextInst == Instruction::JUMPI) - { - // Compute target PC of the jump. - u256 val = 0; - for (auto iter = curr + 1; iter < next; ++iter) - { - val <<= 8; - val |= *iter; - } - - // Create a block for the JUMP target. - ProgramCounter targetPC = val < bytecode.size() ? val.convert_to() : bytecode.size(); - splitPoints.insert(targetPC); - - ProgramCounter jumpPC = (next - bytecode.begin()); - directJumpTargets[jumpPC] = targetPC; - } - - curr += numBytes; - break; - } - - case Instruction::JUMPDEST: - { - // A basic block starts at the next instruction. - if (currentPC + 1 < bytecode.size()) - { - splitPoints.insert(currentPC + 1); - indirectJumpTargets.push_back(currentPC + 1); - } - break; - } - - case Instruction::JUMP: - case Instruction::JUMPI: - case Instruction::RETURN: - case Instruction::STOP: - case Instruction::SUICIDE: - { - // Create a basic block starting at the following instruction. - if (curr + 1 < bytecode.end()) - { - splitPoints.insert(currentPC + 1); - } - break; - } - - default: - break; - } - } - - // Remove split points generated from jumps out of code or into data. - for (auto it = splitPoints.cbegin(); it != splitPoints.cend();) - { - if (*it > bytecode.size() || !validJumpTargets[*it]) - it = splitPoints.erase(it); - else - ++it; - } - - for (auto it = splitPoints.cbegin(); it != splitPoints.cend();) - { - auto beginInstIdx = *it; - ++it; - auto endInstIdx = it != splitPoints.cend() ? *it : bytecode.size(); - basicBlocks.emplace(std::piecewise_construct, std::forward_as_tuple(beginInstIdx), std::forward_as_tuple(beginInstIdx, endInstIdx, m_mainFunc, m_builder)); - } - - m_stopBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Stop", m_mainFunc); - m_badJumpBlock = std::make_unique("BadJumpBlock", m_mainFunc, m_builder); - m_jumpTableBlock = std::make_unique("JumpTableBlock", m_mainFunc, m_builder); - - for (auto it = directJumpTargets.cbegin(); it != directJumpTargets.cend(); ++it) - { - if (it->second >= bytecode.size()) - { - // Jumping out of code means STOP - m_directJumpTargets[it->first] = m_stopBB; - continue; - } - - auto blockIter = basicBlocks.find(it->second); - if (blockIter != basicBlocks.end()) - { - m_directJumpTargets[it->first] = blockIter->second.llvm(); - } - else - { - clog(JIT) << "Bad JUMP at PC " << it->first - << ": " << it->second << " is not a valid PC"; - m_directJumpTargets[it->first] = m_badJumpBlock->llvm(); - } - } - - for (auto it = indirectJumpTargets.cbegin(); it != indirectJumpTargets.cend(); ++it) - { - m_indirectJumpTargets.push_back(&basicBlocks.find(*it)->second); - } -} - -std::unique_ptr Compiler::compile(bytesConstRef bytecode) -{ - auto module = std::make_unique("main", m_builder.getContext()); - - // Create main function - llvm::Type* mainFuncArgTypes[] = {m_builder.getInt32Ty(), Type::RuntimePtr}; // There must be int in first place because LLVM does not support other signatures - auto mainFuncType = llvm::FunctionType::get(Type::MainReturn, mainFuncArgTypes, false); - m_mainFunc = llvm::Function::Create(mainFuncType, llvm::Function::ExternalLinkage, "main", module.get()); - m_mainFunc->arg_begin()->getNextNode()->setName("rt"); - - // Create the basic blocks. - auto entryBlock = llvm::BasicBlock::Create(m_builder.getContext(), "entry", m_mainFunc); - m_builder.SetInsertPoint(entryBlock); - - createBasicBlocks(bytecode); - - // Init runtime structures. - RuntimeManager runtimeManager(m_builder); - GasMeter gasMeter(m_builder, runtimeManager); - Memory memory(runtimeManager, gasMeter); - Ext ext(runtimeManager); - Stack stack(m_builder, runtimeManager); - Arith256 arith(m_builder); - - m_builder.CreateBr(basicBlocks.begin()->second); - - for (auto basicBlockPairIt = basicBlocks.begin(); basicBlockPairIt != basicBlocks.end(); ++basicBlockPairIt) - { - auto& basicBlock = basicBlockPairIt->second; - auto iterCopy = basicBlockPairIt; - ++iterCopy; - auto nextBasicBlock = (iterCopy != basicBlocks.end()) ? iterCopy->second.llvm() : nullptr; - compileBasicBlock(basicBlock, bytecode, runtimeManager, arith, memory, ext, gasMeter, nextBasicBlock); - } - - // Code for special blocks: - // TODO: move to separate function. - // Note: Right now the codegen for special blocks depends only on createBasicBlock(), - // not on the codegen for 'regular' blocks. But it has to be done before linkBasicBlocks(). - m_builder.SetInsertPoint(m_stopBB); - m_builder.CreateRet(Constant::get(ReturnCode::Stop)); - - m_builder.SetInsertPoint(m_badJumpBlock->llvm()); - m_builder.CreateRet(Constant::get(ReturnCode::BadJumpDestination)); - - m_builder.SetInsertPoint(m_jumpTableBlock->llvm()); - if (m_indirectJumpTargets.size() > 0) - { - auto dest = m_jumpTableBlock->localStack().pop(); - auto switchInstr = m_builder.CreateSwitch(dest, m_badJumpBlock->llvm(), - m_indirectJumpTargets.size()); - for (auto it = m_indirectJumpTargets.cbegin(); it != m_indirectJumpTargets.cend(); ++it) - { - auto& bb = *it; - auto dest = Constant::get(bb->begin()); - switchInstr->addCase(dest, bb->llvm()); - } - } - else - { - m_builder.CreateBr(m_badJumpBlock->llvm()); - } - - removeDeadBlocks(); - - if (getenv("EVMCC_DEBUG_BLOCKS")) - { - std::ofstream ofs("blocks-init.dot"); - dumpBasicBlockGraph(ofs); - ofs.close(); - std::cerr << "\n\nAfter dead block elimination \n\n"; - dump(); - } - - //if (getenv("EVMCC_OPTIMIZE_STACK")) - //{ - std::vector blockList; - for (auto& entry : basicBlocks) - blockList.push_back(&entry.second); - - if (m_jumpTableBlock != nullptr) - blockList.push_back(m_jumpTableBlock.get()); - - BasicBlock::linkLocalStacks(blockList, m_builder); - - if (getenv("EVMCC_DEBUG_BLOCKS")) - { - std::ofstream ofs("blocks-opt.dot"); - dumpBasicBlockGraph(ofs); - ofs.close(); - std::cerr << "\n\nAfter stack optimization \n\n"; - dump(); - } - //} - - for (auto& entry : basicBlocks) - entry.second.localStack().synchronize(stack); - if (m_jumpTableBlock != nullptr) - m_jumpTableBlock->localStack().synchronize(stack); - - if (getenv("EVMCC_DEBUG_BLOCKS")) - { - std::ofstream ofs("blocks-sync.dot"); - dumpBasicBlockGraph(ofs); - ofs.close(); - std::cerr << "\n\nAfter stack synchronization \n\n"; - dump(); - } - - llvm::FunctionPassManager fpManager(module.get()); - fpManager.add(llvm::createLowerSwitchPass()); - fpManager.doInitialization(); - fpManager.run(*m_mainFunc); - - return module; -} - - -void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, RuntimeManager& _runtimeManager, Arith256& arith, Memory& memory, Ext& ext, GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock) -{ - m_builder.SetInsertPoint(basicBlock.llvm()); - auto& stack = basicBlock.localStack(); - - for (auto currentPC = basicBlock.begin(); currentPC != basicBlock.end(); ++currentPC) - { - auto inst = static_cast(bytecode[currentPC]); - - gasMeter.count(inst); - - switch (inst) - { - - case Instruction::ADD: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto result = m_builder.CreateAdd(lhs, rhs); - stack.push(result); - break; - } - - case Instruction::SUB: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto result = m_builder.CreateSub(lhs, rhs); - stack.push(result); - break; - } - - case Instruction::MUL: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = arith.mul(lhs, rhs); - stack.push(res); - break; - } - - case Instruction::DIV: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = arith.div(lhs, rhs); - stack.push(res); - break; - } - - case Instruction::SDIV: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = arith.sdiv(lhs, rhs); - stack.push(res); - break; - } - - case Instruction::MOD: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = arith.mod(lhs, rhs); - stack.push(res); - break; - } - - case Instruction::SMOD: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = arith.smod(lhs, rhs); - stack.push(res); - break; - } - - case Instruction::EXP: - { - auto left = stack.pop(); - auto right = stack.pop(); - auto ret = ext.exp(left, right); - stack.push(ret); - break; - } - - case Instruction::BNOT: - { -<<<<<<< HEAD - auto top = stack.pop(); - auto allones = llvm::ConstantInt::get(Type::i256, llvm::APInt::getAllOnesValue(256)); - auto res = m_builder.CreateXor(top, allones); - stack.push(res); -======= - auto value = stack.pop(); - auto ret = m_builder.CreateXor(value, llvm::APInt(256, -1, true), "bnot"); - stack.push(ret); ->>>>>>> cd8727a1e4786caaccf7fbbffd178edcc7aa3c35 - break; - } - - case Instruction::LT: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res1 = m_builder.CreateICmpULT(lhs, rhs); - auto res256 = m_builder.CreateZExt(res1, Type::i256); - stack.push(res256); - break; - } - - case Instruction::GT: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res1 = m_builder.CreateICmpUGT(lhs, rhs); - auto res256 = m_builder.CreateZExt(res1, Type::i256); - stack.push(res256); - break; - } - - case Instruction::SLT: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res1 = m_builder.CreateICmpSLT(lhs, rhs); - auto res256 = m_builder.CreateZExt(res1, Type::i256); - stack.push(res256); - break; - } - - case Instruction::SGT: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res1 = m_builder.CreateICmpSGT(lhs, rhs); - auto res256 = m_builder.CreateZExt(res1, Type::i256); - stack.push(res256); - break; - } - - case Instruction::EQ: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res1 = m_builder.CreateICmpEQ(lhs, rhs); - auto res256 = m_builder.CreateZExt(res1, Type::i256); - stack.push(res256); - break; - } - - case Instruction::NOT: - { - auto top = stack.pop(); - auto iszero = m_builder.CreateICmpEQ(top, Constant::get(0), "iszero"); - auto result = m_builder.CreateZExt(iszero, Type::i256); - stack.push(result); - break; - } - - case Instruction::AND: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = m_builder.CreateAnd(lhs, rhs); - stack.push(res); - break; - } - - case Instruction::OR: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = m_builder.CreateOr(lhs, rhs); - stack.push(res); - break; - } - - case Instruction::XOR: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = m_builder.CreateXor(lhs, rhs); - stack.push(res); - break; - } - - case Instruction::BYTE: - { - const auto byteNum = stack.pop(); - auto value = stack.pop(); - - // - 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"); - value = m_builder.CreateZExt(byte, Type::i256); - - auto byteNumValid = m_builder.CreateICmpULT(byteNum, Constant::get(32)); - value = m_builder.CreateSelect(byteNumValid, value, Constant::get(0)); - stack.push(value); - - break; - } - - case Instruction::ADDMOD: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto mod = stack.pop(); - auto res = arith.addmod(lhs, rhs, mod); - stack.push(res); - break; - } - - case Instruction::MULMOD: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto mod = stack.pop(); - auto res = arith.mulmod(lhs, rhs, mod); - stack.push(res); - break; - } - - case Instruction::SIGNEXTEND: - { - auto k = stack.pop(); - auto b = stack.pop(); - auto k32 = m_builder.CreateTrunc(k, m_builder.getIntNTy(5), "k_32"); - auto k32ext = m_builder.CreateZExt(k32, Type::i256); - auto k32x8 = m_builder.CreateMul(k32ext, Constant::get(8), "kx8"); - - // test for b >> (k * 8 + 7) - auto val = m_builder.CreateAdd(k32x8, llvm::ConstantInt::get(Type::i256, 7)); - auto tmp = m_builder.CreateAShr(b, val); - auto bitset = m_builder.CreateTrunc(tmp, m_builder.getInt1Ty()); - - // shift left by (31 - k) * 8 = (248 - k*8), then do arithmetic shr by the same amount. - auto shiftSize = m_builder.CreateSub(llvm::ConstantInt::get(Type::i256, 31 * 8), k32x8); - auto bshl = m_builder.CreateShl(b, shiftSize); - auto bshr = m_builder.CreateAShr(bshl, shiftSize); - - // bshr is our final value if 0 <= k <= 30 and bitset is true, - // otherwise we push back b unchanged - auto kInRange = m_builder.CreateICmpULE(k, llvm::ConstantInt::get(Type::i256, 30)); - auto cond = m_builder.CreateAnd(kInRange, bitset); - - auto result = m_builder.CreateSelect(cond, bshr, b); - stack.push(result); - - break; - } - - case Instruction::SHA3: - { - auto inOff = stack.pop(); - auto inSize = stack.pop(); - memory.require(inOff, inSize); - auto hash = ext.sha3(inOff, inSize); - stack.push(hash); - break; - } - - case Instruction::POP: - { - stack.pop(); - break; - } - - case Instruction::ANY_PUSH: - { - auto numBytes = static_cast(inst) - static_cast(Instruction::PUSH1) + 1; - auto value = llvm::APInt(256, 0); - for (decltype(numBytes) i = 0; i < numBytes; ++i) // TODO: Use pc as iterator - { - ++currentPC; - value <<= 8; - value |= bytecode[currentPC]; - } - auto c = m_builder.getInt(value); - stack.push(c); - break; - } - - case Instruction::ANY_DUP: - { - auto index = static_cast(inst) - static_cast(Instruction::DUP1); - stack.dup(index); - break; - } - - case Instruction::ANY_SWAP: - { - auto index = static_cast(inst) - static_cast(Instruction::SWAP1) + 1; - stack.swap(index); - break; - } - - case Instruction::MLOAD: - { - auto addr = stack.pop(); - auto word = memory.loadWord(addr); - stack.push(word); - break; - } - - case Instruction::MSTORE: - { - auto addr = stack.pop(); - auto word = stack.pop(); - memory.storeWord(addr, word); - break; - } - - case Instruction::MSTORE8: - { - auto addr = stack.pop(); - auto word = stack.pop(); - memory.storeByte(addr, word); - break; - } - - case Instruction::MSIZE: - { - auto word = memory.getSize(); - stack.push(word); - break; - } - - case Instruction::SLOAD: - { - auto index = stack.pop(); - auto value = ext.store(index); - stack.push(value); - break; - } - - case Instruction::SSTORE: - { - auto index = stack.pop(); - auto value = stack.pop(); - gasMeter.countSStore(ext, index, value); - ext.setStore(index, value); - break; - } - - case Instruction::JUMP: - case Instruction::JUMPI: - { - // Generate direct jump iff: - // 1. this is not the first instruction in the block - // 2. m_directJumpTargets[currentPC] is defined (meaning that the previous instruction is a PUSH) - // Otherwise generate a indirect jump (a switch). - llvm::BasicBlock* targetBlock = nullptr; - if (currentPC != basicBlock.begin()) - { - auto pairIter = m_directJumpTargets.find(currentPC); - if (pairIter != m_directJumpTargets.end()) - { - targetBlock = pairIter->second; - } - } - - if (inst == Instruction::JUMP) - { - if (targetBlock) - { - // The target address is computed at compile time, - // just pop it without looking... - stack.pop(); - m_builder.CreateBr(targetBlock); - } - else - { - m_builder.CreateBr(m_jumpTableBlock->llvm()); - } - } - else // JUMPI - { - stack.swap(1); - auto val = stack.pop(); - auto zero = Constant::get(0); - auto cond = m_builder.CreateICmpNE(val, zero, "nonzero"); - - // Assume the basic blocks are properly ordered: - assert(nextBasicBlock); // FIXME: JUMPI can be last instruction - - if (targetBlock) - { - stack.pop(); - m_builder.CreateCondBr(cond, targetBlock, nextBasicBlock); - } - else - { - m_builder.CreateCondBr(cond, m_jumpTableBlock->llvm(), nextBasicBlock); - } - } - - break; - } - - case Instruction::JUMPDEST: - { - // Nothing to do - break; - } - - case Instruction::PC: - { - auto value = Constant::get(currentPC); - stack.push(value); - break; - } - - case Instruction::GAS: - case Instruction::ADDRESS: - case Instruction::CALLER: - case Instruction::ORIGIN: - case Instruction::CALLVALUE: - case Instruction::CALLDATASIZE: - case Instruction::CODESIZE: - case Instruction::GASPRICE: - case Instruction::PREVHASH: - case Instruction::COINBASE: - case Instruction::TIMESTAMP: - case Instruction::NUMBER: - case Instruction::DIFFICULTY: - case Instruction::GASLIMIT: - { - // Pushes an element of runtime data on stack - stack.push(_runtimeManager.get(inst)); - break; - } - - case Instruction::BALANCE: - { - auto address = stack.pop(); - auto value = ext.balance(address); - stack.push(value); - break; - } - - case Instruction::EXTCODESIZE: - { - auto addr = stack.pop(); - auto value = ext.codesizeAt(addr); - stack.push(value); - break; - } - - case Instruction::CALLDATACOPY: - { - auto destMemIdx = stack.pop(); - auto srcIdx = stack.pop(); - auto reqBytes = stack.pop(); - - auto srcPtr = _runtimeManager.getCallData(); - auto srcSize = _runtimeManager.get(RuntimeData::CallDataSize); - - memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); - break; - } - - case Instruction::CODECOPY: - { - auto destMemIdx = stack.pop(); - auto srcIdx = stack.pop(); - auto reqBytes = stack.pop(); - - auto srcPtr = _runtimeManager.getCode(); // TODO: Code & its size are constants, feature #80814234 - auto srcSize = _runtimeManager.get(RuntimeData::CodeSize); - - memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); - break; - } - - case Instruction::EXTCODECOPY: - { - auto extAddr = stack.pop(); - auto destMemIdx = stack.pop(); - auto srcIdx = stack.pop(); - auto reqBytes = stack.pop(); - - auto srcPtr = ext.codeAt(extAddr); - auto srcSize = ext.codesizeAt(extAddr); - - memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); - break; - } - - case Instruction::CALLDATALOAD: - { - auto index = stack.pop(); - auto value = ext.calldataload(index); - stack.push(value); - break; - } - - case Instruction::CREATE: - { - auto endowment = stack.pop(); - auto initOff = stack.pop(); - auto initSize = stack.pop(); - memory.require(initOff, initSize); - - auto address = ext.create(endowment, initOff, initSize); - stack.push(address); - break; - } - - case Instruction::CALL: - case Instruction::CALLCODE: - { - auto gas = stack.pop(); - auto codeAddress = stack.pop(); - auto value = stack.pop(); - auto inOff = stack.pop(); - auto inSize = stack.pop(); - auto outOff = stack.pop(); - auto outSize = stack.pop(); - - gasMeter.commitCostBlock(gas); - - // Require memory for the max of in and out buffers - auto inSizeReq = m_builder.CreateAdd(inOff, inSize, "inSizeReq"); - auto outSizeReq = m_builder.CreateAdd(outOff, outSize, "outSizeReq"); - auto cmp = m_builder.CreateICmpUGT(inSizeReq, outSizeReq); - auto sizeReq = m_builder.CreateSelect(cmp, inSizeReq, outSizeReq, "sizeReq"); - memory.require(sizeReq); - - auto receiveAddress = codeAddress; - if (inst == Instruction::CALLCODE) - receiveAddress = _runtimeManager.get(RuntimeData::Address); - - auto ret = ext.call(gas, receiveAddress, value, inOff, inSize, outOff, outSize, codeAddress); - gasMeter.giveBack(gas); - stack.push(ret); - break; - } - - case Instruction::RETURN: - { - auto index = stack.pop(); - auto size = stack.pop(); - - memory.require(index, size); - _runtimeManager.registerReturnData(index, size); - - m_builder.CreateRet(Constant::get(ReturnCode::Return)); - break; - } - - case Instruction::SUICIDE: - { - auto address = stack.pop(); - ext.suicide(address); - // Fall through - } - case Instruction::STOP: - { - m_builder.CreateRet(Constant::get(ReturnCode::Stop)); - break; - } - - default: // Invalid instruction - runtime exception - { - _runtimeManager.raiseException(ReturnCode::BadInstruction); - } - - } - } - - gasMeter.commitCostBlock(); - - if (!basicBlock.llvm()->getTerminator()) // If block not terminated - { - if (nextBasicBlock) - m_builder.CreateBr(nextBasicBlock); // Branch to the next block - else - m_builder.CreateRet(Constant::get(ReturnCode::Stop)); // Return STOP code - } -} - - - -void Compiler::removeDeadBlocks() -{ - // Remove dead basic blocks - auto sthErased = false; - do - { - sthErased = false; - for (auto it = basicBlocks.begin(); it != basicBlocks.end();) - { - auto llvmBB = it->second.llvm(); - if (llvm::pred_begin(llvmBB) == llvm::pred_end(llvmBB)) - { - llvmBB->eraseFromParent(); - basicBlocks.erase(it++); - sthErased = true; - } - else - ++it; - } - } - while (sthErased); - - // Remove jump table block if no predecessors - if (llvm::pred_begin(m_jumpTableBlock->llvm()) == llvm::pred_end(m_jumpTableBlock->llvm())) - { - m_jumpTableBlock->llvm()->eraseFromParent(); - m_jumpTableBlock.reset(); - } -} - -void Compiler::dumpBasicBlockGraph(std::ostream& out) -{ - out << "digraph BB {\n" - << " node [shape=record, fontname=Courier, fontsize=10];\n" - << " entry [share=record, label=\"entry block\"];\n"; - - std::vector blocks; - for (auto& pair : basicBlocks) - blocks.push_back(&pair.second); - if (m_jumpTableBlock) - blocks.push_back(m_jumpTableBlock.get()); - if (m_badJumpBlock) - blocks.push_back(m_badJumpBlock.get()); - - // std::map phiNodesPerBlock; - - // Output nodes - for (auto bb : blocks) - { - std::string blockName = bb->llvm()->getName(); - - std::ostringstream oss; - bb->dump(oss, true); - - out << " \"" << blockName << "\" [shape=record, label=\" { " << blockName << "|" << oss.str() << "} \"];\n"; - } - - // Output edges - for (auto bb : blocks) - { - std::string blockName = bb->llvm()->getName(); - - auto end = llvm::pred_end(bb->llvm()); - for (llvm::pred_iterator it = llvm::pred_begin(bb->llvm()); it != end; ++it) - { - out << " \"" << (*it)->getName().str() << "\" -> \"" << blockName << "\" [" - << ((m_jumpTableBlock.get() && *it == m_jumpTableBlock.get()->llvm()) ? "style = dashed, " : "") - //<< "label = \"" - //<< phiNodesPerBlock[bb] - << "];\n"; - } - } - - out << "}\n"; -} - -void Compiler::dump() -{ - for (auto& entry : basicBlocks) - entry.second.dump(); - if (m_jumpTableBlock != nullptr) - m_jumpTableBlock->dump(); -} - -} -} -} - From c376cda830506d995d332efdd78e40dd34f85b21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 30 Oct 2014 19:17:19 +0100 Subject: [PATCH 294/641] Fix u256 to APInt conversion --- libevmjit/Type.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libevmjit/Type.cpp b/libevmjit/Type.cpp index 447da6a4b..ec11acef5 100644 --- a/libevmjit/Type.cpp +++ b/libevmjit/Type.cpp @@ -43,10 +43,7 @@ llvm::ConstantInt* Constant::get(uint64_t _n) llvm::ConstantInt* Constant::get(u256 _n) { - auto& backend = _n.backend(); - auto words = reinterpret_cast(backend.limbs()); - auto nWords = backend.limb_bits == 64 ? backend.size() : (backend.size() + 1) / 2; - llvm::APInt n(256, nWords, words); + llvm::APInt n(256, _n.str(0, std::ios_base::hex), 16); assert(n.toString(10, false) == _n.str()); return static_cast(llvm::ConstantInt::get(Type::i256, n)); } From 20277e8b0beee7f3d148b9f290942db9250e42a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 30 Oct 2014 19:17:55 +0100 Subject: [PATCH 295/641] Create dedicated function for pushdata reading --- libevmjit/Utils.cpp | 17 +++++++++++++++++ libevmjit/Utils.h | 6 ++++++ 2 files changed, 23 insertions(+) diff --git a/libevmjit/Utils.cpp b/libevmjit/Utils.cpp index 0fd9c0e41..966dc69bd 100644 --- a/libevmjit/Utils.cpp +++ b/libevmjit/Utils.cpp @@ -35,6 +35,23 @@ i256 eth2llvm(u256 _u) return i; } +u256 readPushData(const byte*& _curr, const byte* _end) +{ + auto pushInst = *_curr; + assert(Instruction(pushInst) >= Instruction::PUSH1 && Instruction(pushInst) <= Instruction::PUSH32); + auto numBytes = pushInst - static_cast(Instruction::PUSH1) + 1; + u256 value; + ++_curr; // Point the data + for (decltype(numBytes) i = 0; i < numBytes; ++i) + { + byte b = (_curr != _end) ? *_curr++ : 0; + value <<= 8; + value |= b; + } + --_curr; // Point the last real byte read + return value; +} + } } } diff --git a/libevmjit/Utils.h b/libevmjit/Utils.h index 7a3afda64..9fa9f050e 100644 --- a/libevmjit/Utils.h +++ b/libevmjit/Utils.h @@ -5,6 +5,7 @@ #include #include +#include namespace dev { @@ -29,6 +30,11 @@ static_assert(sizeof(i256) == 32, "Wrong i265 size"); u256 llvm2eth(i256); i256 eth2llvm(u256); +/// Reads PUSH data from pointed fragment of bytecode and constructs number out of it +/// Reading out of bytecode means reading 0 +/// @param _curr is updates and points the last real byte read +u256 readPushData(const byte*& _curr, const byte* _end); + #define ANY_PUSH PUSH1: \ case Instruction::PUSH2: \ case Instruction::PUSH3: \ From 01b6974a18ad93924bdace7e25161a9ff3c529bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 30 Oct 2014 19:22:01 +0100 Subject: [PATCH 296/641] Use readPushData() in instruction compilation --- libevmjit/Compiler.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index c63418753..92357e8d8 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -554,15 +554,11 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, case Instruction::ANY_PUSH: { - const auto numBytes = static_cast(inst) - static_cast(Instruction::PUSH1) + 1; - auto value = llvm::APInt(256, 0); - for (auto lastPC = currentPC + numBytes; currentPC < lastPC;) - { - value <<= 8; - value |= bytecode[++currentPC]; - } + auto curr = bytecode.begin() + currentPC; // TODO: replace currentPC with iterator + auto value = readPushData(curr, bytecode.end()); + currentPC = curr - bytecode.begin(); - stack.push(m_builder.getInt(value)); + stack.push(Constant::get(value)); break; } From 1728f58cbaae9fe508b85e4030c0074b4598bcf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 30 Oct 2014 19:28:10 +0100 Subject: [PATCH 297/641] Use readPushData() in basic block analysis --- libevmjit/Compiler.cpp | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 92357e8d8..1e394eba0 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -56,29 +56,20 @@ void Compiler::createBasicBlocks(bytesConstRef bytecode) ProgramCounter currentPC = curr - bytecode.begin(); validJumpTargets[currentPC] = true; - auto inst = static_cast(*curr); + auto inst = Instruction(*curr); switch (inst) { case Instruction::ANY_PUSH: { - auto numBytes = static_cast(inst) - static_cast(Instruction::PUSH1) + 1; - auto next = curr + numBytes + 1; - if (next >= bytecode.end()) + auto val = readPushData(curr, bytecode.end()); + auto next = curr + 1; + if (next == bytecode.end()) break; - auto nextInst = static_cast(*next); - + auto nextInst = Instruction(*next); if (nextInst == Instruction::JUMP || nextInst == Instruction::JUMPI) { - // Compute target PC of the jump. - u256 val = 0; - for (auto iter = curr + 1; iter < next; ++iter) - { - val <<= 8; - val |= *iter; - } - // Create a block for the JUMP target. ProgramCounter targetPC = val < bytecode.size() ? val.convert_to() : bytecode.size(); splitPoints.insert(targetPC); @@ -86,8 +77,6 @@ void Compiler::createBasicBlocks(bytesConstRef bytecode) ProgramCounter jumpPC = (next - bytecode.begin()); directJumpTargets[jumpPC] = targetPC; } - - curr += numBytes; break; } From 41648959356322398eb0262d9805e5436f04f13c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 31 Oct 2014 08:26:41 +0100 Subject: [PATCH 298/641] Deprecate Memory::require(size) function. Risk of unsigned integer overflow. --- libevmjit/Compiler.cpp | 9 +++------ libevmjit/Memory.cpp | 2 +- libevmjit/Memory.h | 7 +++---- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 1e394eba0..0c955ab3b 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -785,12 +785,9 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, gasMeter.commitCostBlock(gas); - // Require memory for the max of in and out buffers - auto inSizeReq = m_builder.CreateAdd(inOff, inSize, "inSizeReq"); - auto outSizeReq = m_builder.CreateAdd(outOff, outSize, "outSizeReq"); - auto cmp = m_builder.CreateICmpUGT(inSizeReq, outSizeReq); - auto sizeReq = m_builder.CreateSelect(cmp, inSizeReq, outSizeReq, "sizeReq"); - memory.require(sizeReq); + // Require memory for in and out buffers + memory.require(outOff, outSize); // Out buffer first as we guess it will be after the in one + memory.require(inOff, inSize); auto receiveAddress = codeAddress; if (inst == Instruction::CALLCODE) diff --git a/libevmjit/Memory.cpp b/libevmjit/Memory.cpp index 84aa105fe..8528bd9d2 100644 --- a/libevmjit/Memory.cpp +++ b/libevmjit/Memory.cpp @@ -171,7 +171,7 @@ void Memory::require(llvm::Value* _size) void Memory::require(llvm::Value* _offset, llvm::Value* _size) { - auto sizeRequired = m_builder.CreateAdd(_offset, _size, "sizeRequired"); + auto sizeRequired = m_builder.CreateNUWAdd(_offset, _size, "sizeRequired"); require(sizeRequired); } diff --git a/libevmjit/Memory.h b/libevmjit/Memory.h index f315b9295..90c60c5fd 100644 --- a/libevmjit/Memory.h +++ b/libevmjit/Memory.h @@ -24,9 +24,6 @@ public: void copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value* _srcIndex, llvm::Value* _destMemIdx, llvm::Value* _byteCount); - /// Requires this amount of memory. And counts gas fee for that memory. - void require(llvm::Value* _size); - /// Requires the amount of memory to for data defined by offset and size. And counts gas fee for that memory. void require(llvm::Value* _offset, llvm::Value* _size); @@ -36,7 +33,9 @@ private: llvm::Function* createFunc(bool _isStore, llvm::Type* _type, GasMeter& _gasMeter); llvm::Function* createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _runtimeManager); -private: + /// Requires this amount of memory. And counts gas fee for that memory. + void require(llvm::Value* _size); + llvm::GlobalVariable* m_data; llvm::GlobalVariable* m_size; From cfb98606f563bb5c079374d656462438c4ee87bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 31 Oct 2014 08:50:25 +0100 Subject: [PATCH 299/641] Remove Memory::require(size) interface [#81773288] --- libevmjit/Memory.cpp | 32 ++++++++++++++------------------ libevmjit/Memory.h | 3 --- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/libevmjit/Memory.cpp b/libevmjit/Memory.cpp index 8528bd9d2..309fb2964 100644 --- a/libevmjit/Memory.cpp +++ b/libevmjit/Memory.cpp @@ -28,8 +28,7 @@ Memory::Memory(RuntimeManager& _runtimeManager, GasMeter& _gasMeter): RuntimeHelper(_runtimeManager) { auto module = getModule(); - auto i64Ty = m_builder.getInt64Ty(); - llvm::Type* argTypes[] = {i64Ty, i64Ty}; + llvm::Type* argTypes[] = {Type::i256, Type::i256}; auto dumpTy = llvm::FunctionType::get(m_builder.getVoidTy(), llvm::ArrayRef(argTypes), false); m_memDump = llvm::Function::Create(dumpTy, llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_memory_dump", module); @@ -54,19 +53,23 @@ Memory::Memory(RuntimeManager& _runtimeManager, GasMeter& _gasMeter): llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _runtimeManager) { - auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "mem.require", getModule()); + llvm::Type* argTypes[] = {Type::i256, Type::i256}; + auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, argTypes, false), llvm::Function::PrivateLinkage, "mem.require", getModule()); + auto offset = func->arg_begin(); + offset->setName("offset"); + auto size = offset->getNextNode(); + size->setName("size"); - auto checkBB = llvm::BasicBlock::Create(func->getContext(), "check", func); - auto resizeBB = llvm::BasicBlock::Create(func->getContext(), "resize", func); - auto returnBB = llvm::BasicBlock::Create(func->getContext(), "return", func); + auto checkBB = llvm::BasicBlock::Create(func->getContext(), "Check", func); + auto resizeBB = llvm::BasicBlock::Create(func->getContext(), "Resize", func); + auto returnBB = llvm::BasicBlock::Create(func->getContext(), "Return", func); InsertPointGuard guard(m_builder); // Restores insert point at function exit // BB "check" m_builder.SetInsertPoint(checkBB); - llvm::Value* sizeRequired = func->arg_begin(); - sizeRequired->setName("sizeRequired"); - auto size = m_builder.CreateLoad(m_size, "size"); + auto sizeRequired = m_builder.CreateNUWAdd(offset, size, "sizeRequired"); + auto currSize = m_builder.CreateLoad(m_size, "currSize"); auto resizeNeeded = m_builder.CreateICmpULE(size, sizeRequired, "resizeNeeded"); m_builder.CreateCondBr(resizeNeeded, resizeBB, returnBB); // OPT branch weights? @@ -164,15 +167,9 @@ llvm::Value* Memory::getSize() return m_builder.CreateLoad(m_size); } -void Memory::require(llvm::Value* _size) -{ - m_builder.CreateCall(m_require, _size); -} - void Memory::require(llvm::Value* _offset, llvm::Value* _size) { - auto sizeRequired = m_builder.CreateNUWAdd(_offset, _size, "sizeRequired"); - require(sizeRequired); + m_builder.CreateCall2(m_require, _offset, _size); } void Memory::copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value* _srcIdx, @@ -180,8 +177,7 @@ void Memory::copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value* { auto zero256 = llvm::ConstantInt::get(Type::i256, 0); - auto reqMemSize = m_builder.CreateAdd(_destMemIdx, _reqBytes, "req_mem_size"); - require(reqMemSize); + require(_destMemIdx, _reqBytes); auto srcPtr = m_builder.CreateGEP(_srcPtr, _srcIdx, "src_idx"); diff --git a/libevmjit/Memory.h b/libevmjit/Memory.h index 90c60c5fd..37bfb15f5 100644 --- a/libevmjit/Memory.h +++ b/libevmjit/Memory.h @@ -33,9 +33,6 @@ private: llvm::Function* createFunc(bool _isStore, llvm::Type* _type, GasMeter& _gasMeter); llvm::Function* createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _runtimeManager); - /// Requires this amount of memory. And counts gas fee for that memory. - void require(llvm::Value* _size); - llvm::GlobalVariable* m_data; llvm::GlobalVariable* m_size; From 340d9ea6782e474271c0990e0f34414dd7e0d646 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 31 Oct 2014 11:09:53 +0100 Subject: [PATCH 300/641] Change Constant::get to support negative values --- libevmjit/Compiler.cpp | 2 +- libevmjit/Type.cpp | 4 ++-- libevmjit/Type.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 0c955ab3b..8a38e257f 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -366,7 +366,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, case Instruction::BNOT: { auto value = stack.pop(); - auto ret = m_builder.CreateXor(value, llvm::APInt(256, -1, true), "bnot"); + auto ret = m_builder.CreateXor(value, Constant::get(-1), "bnot"); stack.push(ret); break; } diff --git a/libevmjit/Type.cpp b/libevmjit/Type.cpp index ec11acef5..37757dfdf 100644 --- a/libevmjit/Type.cpp +++ b/libevmjit/Type.cpp @@ -36,9 +36,9 @@ void Type::init(llvm::LLVMContext& _context) RuntimePtr = RuntimeData::getType()->getPointerTo(); } -llvm::ConstantInt* Constant::get(uint64_t _n) +llvm::ConstantInt* Constant::get(int64_t _n) { - return llvm::ConstantInt::get(Type::i256, _n); + return llvm::ConstantInt::getSigned(Type::i256, _n); } llvm::ConstantInt* Constant::get(u256 _n) diff --git a/libevmjit/Type.h b/libevmjit/Type.h index c80e46777..4658f94bb 100644 --- a/libevmjit/Type.h +++ b/libevmjit/Type.h @@ -51,7 +51,7 @@ enum class ReturnCode struct Constant { /// Returns word-size constant - static llvm::ConstantInt* get(uint64_t _n); + static llvm::ConstantInt* get(int64_t _n); static llvm::ConstantInt* get(u256 _n); static llvm::ConstantInt* get(ReturnCode _returnCode); From d555d4af8fe08c34361bbc098aed76e1fc9c52b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 31 Oct 2014 11:14:25 +0100 Subject: [PATCH 301/641] Handle unsigned integer overflow in Memory::require() [Delivers #81773288] --- libevmjit/Memory.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/libevmjit/Memory.cpp b/libevmjit/Memory.cpp index 309fb2964..322c53ee3 100644 --- a/libevmjit/Memory.cpp +++ b/libevmjit/Memory.cpp @@ -8,6 +8,7 @@ #include #include +#include #include @@ -68,17 +69,26 @@ llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _ // BB "check" m_builder.SetInsertPoint(checkBB); - auto sizeRequired = m_builder.CreateNUWAdd(offset, size, "sizeRequired"); + auto uaddWO = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::uadd_with_overflow, Type::i256); + auto uaddRes = m_builder.CreateCall2(uaddWO, offset, size, "res"); + auto sizeRequired = m_builder.CreateExtractValue(uaddRes, 0, "sizeReq"); + auto overflow1 = m_builder.CreateExtractValue(uaddRes, 1, "overflow1"); auto currSize = m_builder.CreateLoad(m_size, "currSize"); - auto resizeNeeded = m_builder.CreateICmpULE(size, sizeRequired, "resizeNeeded"); + auto tooSmall = m_builder.CreateICmpULE(size, sizeRequired, "tooSmall"); + auto resizeNeeded = m_builder.CreateOr(tooSmall, overflow1, "resizeNeeded"); m_builder.CreateCondBr(resizeNeeded, resizeBB, returnBB); // OPT branch weights? // BB "resize" m_builder.SetInsertPoint(resizeBB); // Check gas first - auto wordsRequired = m_builder.CreateUDiv(m_builder.CreateAdd(sizeRequired, Constant::get(31)), Constant::get(32), "wordsRequired"); - sizeRequired = m_builder.CreateMul(wordsRequired, Constant::get(32), "roundedSizeRequired"); - auto words = m_builder.CreateUDiv(size, Constant::get(32), "words"); // size is always 32*k + uaddRes = m_builder.CreateCall2(uaddWO, sizeRequired, Constant::get(31), "res"); + auto wordsRequired = m_builder.CreateExtractValue(uaddRes, 0); + auto overflow2 = m_builder.CreateExtractValue(uaddRes, 1, "overflow2"); + auto overflow = m_builder.CreateOr(overflow1, overflow2, "overflow"); + wordsRequired = m_builder.CreateSelect(overflow, Constant::get(-1), wordsRequired); + wordsRequired = m_builder.CreateUDiv(wordsRequired, Constant::get(32), "wordsReq"); + sizeRequired = m_builder.CreateMul(wordsRequired, Constant::get(32), "roundedSizeReq"); + auto words = m_builder.CreateUDiv(currSize, Constant::get(32), "words"); // size is always 32*k auto newWords = m_builder.CreateSub(wordsRequired, words, "addtionalWords"); _gasMeter.checkMemory(newWords, m_builder); // Resize From ec07859aedd18ebfd9b40cfa2a182e49c5b3f30a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 31 Oct 2014 12:44:43 +0100 Subject: [PATCH 302/641] Update Visual Studio project file for LibEthereum --- windows/LibEthereum.vcxproj | 4 ++-- windows/LibEthereum.vcxproj.filters | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/windows/LibEthereum.vcxproj b/windows/LibEthereum.vcxproj index 956252979..9faae62c3 100644 --- a/windows/LibEthereum.vcxproj +++ b/windows/LibEthereum.vcxproj @@ -103,8 +103,8 @@ true + - @@ -319,8 +319,8 @@ true true + - diff --git a/windows/LibEthereum.vcxproj.filters b/windows/LibEthereum.vcxproj.filters index d96ee47a5..5e1497b86 100644 --- a/windows/LibEthereum.vcxproj.filters +++ b/windows/LibEthereum.vcxproj.filters @@ -4,9 +4,6 @@ Windows - - libethereum - libethereum @@ -205,14 +202,14 @@ libdevcrypto + + libethereum + Windows - - libethereum - libethereum @@ -441,6 +438,9 @@ libdevcrypto + + libethereum + From 5dc0a266c4f24f1aabc1a9e4203877af02b23462 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 31 Oct 2014 15:16:34 +0100 Subject: [PATCH 303/641] Empty lines removal --- libevmjit/Compiler.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 8a38e257f..121ae37d5 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -462,7 +462,6 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, const auto byteNum = stack.pop(); auto value = stack.pop(); - // 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"); @@ -471,7 +470,6 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto byteNumValid = m_builder.CreateICmpULT(byteNum, Constant::get(32)); value = m_builder.CreateSelect(byteNumValid, value, Constant::get(0)); stack.push(value); - break; } @@ -521,7 +519,6 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, m_builder.CreateSelect(bittest, val1, val0), word); stack.push(result); - break; } From b039d7ee8e98aa22e9693e52d5ad3090b25000f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 31 Oct 2014 15:17:03 +0100 Subject: [PATCH 304/641] Use common builder in GasMeter and Memory --- libevmjit/GasMeter.cpp | 7 +++---- libevmjit/GasMeter.h | 4 ++-- libevmjit/Memory.cpp | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/libevmjit/GasMeter.cpp b/libevmjit/GasMeter.cpp index 5f6f81e72..a0656ace4 100644 --- a/libevmjit/GasMeter.cpp +++ b/libevmjit/GasMeter.cpp @@ -169,11 +169,10 @@ void GasMeter::commitCostBlock(llvm::Value* _additionalCost) assert(m_blockCost == 0); } -void GasMeter::checkMemory(llvm::Value* _additionalMemoryInWords, llvm::IRBuilder<>& _builder) +void GasMeter::checkMemory(llvm::Value* _additionalMemoryInWords) { - // Memory uses other builder, but that can be changes later - auto cost = _builder.CreateMul(_additionalMemoryInWords, Constant::get(static_cast(c_memoryGas)), "memcost"); - _builder.CreateCall(m_gasCheckFunc, cost); + auto cost = m_builder.CreateNUWMul(_additionalMemoryInWords, Constant::get(static_cast(c_memoryGas)), "memcost"); + m_builder.CreateCall(m_gasCheckFunc, cost); } } diff --git a/libevmjit/GasMeter.h b/libevmjit/GasMeter.h index dcfde92a3..3de227651 100644 --- a/libevmjit/GasMeter.h +++ b/libevmjit/GasMeter.h @@ -32,7 +32,7 @@ public: void giveBack(llvm::Value* _gas); /// Generate code that checks the cost of additional memory used by program - void checkMemory(llvm::Value* _additionalMemoryInWords, llvm::IRBuilder<>& _builder); + void checkMemory(llvm::Value* _additionalMemoryInWords); private: /// Cumulative gas cost of a block of instructions @@ -40,7 +40,7 @@ private: uint64_t m_blockCost = 0; llvm::CallInst* m_checkCall = nullptr; - llvm::Function* m_gasCheckFunc; + llvm::Function* m_gasCheckFunc = nullptr; RuntimeManager& m_runtimeManager; }; diff --git a/libevmjit/Memory.cpp b/libevmjit/Memory.cpp index 322c53ee3..beedd9cb9 100644 --- a/libevmjit/Memory.cpp +++ b/libevmjit/Memory.cpp @@ -90,7 +90,7 @@ llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _ sizeRequired = m_builder.CreateMul(wordsRequired, Constant::get(32), "roundedSizeReq"); auto words = m_builder.CreateUDiv(currSize, Constant::get(32), "words"); // size is always 32*k auto newWords = m_builder.CreateSub(wordsRequired, words, "addtionalWords"); - _gasMeter.checkMemory(newWords, m_builder); + _gasMeter.checkMemory(newWords); // Resize m_builder.CreateStore(sizeRequired, m_size); auto newData = m_builder.CreateCall2(m_resize, _runtimeManager.getRuntimePtr(), m_size, "newData"); From 23c7da66fa406dab7df9e8a7151bc3e597cf56a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 31 Oct 2014 15:28:27 +0100 Subject: [PATCH 305/641] Rename Type::i256 -> Type::Word --- libevmjit/Arith256.cpp | 8 ++++---- libevmjit/BasicBlock.cpp | 2 +- libevmjit/Compiler.cpp | 20 ++++++++++---------- libevmjit/Endianness.cpp | 4 ++-- libevmjit/GasMeter.cpp | 4 ++-- libevmjit/Memory.cpp | 26 +++++++++++++------------- libevmjit/Runtime.cpp | 2 +- libevmjit/Stack.cpp | 2 +- libevmjit/Type.cpp | 10 +++++----- libevmjit/Type.h | 2 +- 10 files changed, 40 insertions(+), 40 deletions(-) diff --git a/libevmjit/Arith256.cpp b/libevmjit/Arith256.cpp index 61b0ba35e..82e31e61d 100644 --- a/libevmjit/Arith256.cpp +++ b/libevmjit/Arith256.cpp @@ -18,10 +18,10 @@ Arith256::Arith256(llvm::IRBuilder<>& _builder) : { using namespace llvm; - m_result = m_builder.CreateAlloca(Type::i256, nullptr, "arith.result"); - m_arg1 = m_builder.CreateAlloca(Type::i256, nullptr, "arith.arg1"); - m_arg2 = m_builder.CreateAlloca(Type::i256, nullptr, "arith.arg2"); - m_arg3 = m_builder.CreateAlloca(Type::i256, nullptr, "arith.arg3"); + m_result = m_builder.CreateAlloca(Type::Word, nullptr, "arith.result"); + m_arg1 = m_builder.CreateAlloca(Type::Word, nullptr, "arith.arg1"); + m_arg2 = m_builder.CreateAlloca(Type::Word, nullptr, "arith.arg2"); + m_arg3 = m_builder.CreateAlloca(Type::Word, nullptr, "arith.arg3"); using Linkage = GlobalValue::LinkageTypes; diff --git a/libevmjit/BasicBlock.cpp b/libevmjit/BasicBlock.cpp index a35462cbe..0c604f1b3 100644 --- a/libevmjit/BasicBlock.cpp +++ b/libevmjit/BasicBlock.cpp @@ -171,7 +171,7 @@ llvm::Value* BasicBlock::LocalStack::get(size_t _index) assert(m_initialStack[initialIdx] == nullptr); // Create a dummy value. std::string name = "get_" + boost::lexical_cast(_index); - m_initialStack[initialIdx] = m_builder.CreatePHI(Type::i256, 0, name); + m_initialStack[initialIdx] = m_builder.CreatePHI(Type::Word, 0, name); *itemIter = m_initialStack[initialIdx]; } diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 121ae37d5..537a0082b 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -376,7 +376,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto lhs = stack.pop(); auto rhs = stack.pop(); auto res1 = m_builder.CreateICmpULT(lhs, rhs); - auto res256 = m_builder.CreateZExt(res1, Type::i256); + auto res256 = m_builder.CreateZExt(res1, Type::Word); stack.push(res256); break; } @@ -386,7 +386,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto lhs = stack.pop(); auto rhs = stack.pop(); auto res1 = m_builder.CreateICmpUGT(lhs, rhs); - auto res256 = m_builder.CreateZExt(res1, Type::i256); + auto res256 = m_builder.CreateZExt(res1, Type::Word); stack.push(res256); break; } @@ -396,7 +396,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto lhs = stack.pop(); auto rhs = stack.pop(); auto res1 = m_builder.CreateICmpSLT(lhs, rhs); - auto res256 = m_builder.CreateZExt(res1, Type::i256); + auto res256 = m_builder.CreateZExt(res1, Type::Word); stack.push(res256); break; } @@ -406,7 +406,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto lhs = stack.pop(); auto rhs = stack.pop(); auto res1 = m_builder.CreateICmpSGT(lhs, rhs); - auto res256 = m_builder.CreateZExt(res1, Type::i256); + auto res256 = m_builder.CreateZExt(res1, Type::Word); stack.push(res256); break; } @@ -416,7 +416,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto lhs = stack.pop(); auto rhs = stack.pop(); auto res1 = m_builder.CreateICmpEQ(lhs, rhs); - auto res256 = m_builder.CreateZExt(res1, Type::i256); + auto res256 = m_builder.CreateZExt(res1, Type::Word); stack.push(res256); break; } @@ -425,7 +425,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, { auto top = stack.pop(); auto iszero = m_builder.CreateICmpEQ(top, Constant::get(0), "iszero"); - auto result = m_builder.CreateZExt(iszero, Type::i256); + auto result = m_builder.CreateZExt(iszero, Type::Word); stack.push(result); break; } @@ -465,7 +465,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef 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"); - value = m_builder.CreateZExt(byte, Type::i256); + value = m_builder.CreateZExt(byte, Type::Word); auto byteNumValid = m_builder.CreateICmpULT(byteNum, Constant::get(32)); value = m_builder.CreateSelect(byteNumValid, value, Constant::get(0)); @@ -499,7 +499,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto word = stack.pop(); auto k32_ = m_builder.CreateTrunc(idx, m_builder.getIntNTy(5), "k_32"); - auto k32 = m_builder.CreateZExt(k32_, Type::i256); + auto k32 = m_builder.CreateZExt(k32_, Type::Word); auto k32x8 = m_builder.CreateMul(k32, Constant::get(8), "kx8"); // test for word >> (k * 8 + 7) @@ -510,11 +510,11 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto mask_ = m_builder.CreateShl(Constant::get(1), bitpos); auto mask = m_builder.CreateSub(mask_, Constant::get(1), "mask"); - auto negmask = m_builder.CreateXor(mask, llvm::ConstantInt::getAllOnesValue(Type::i256), "negmask"); + auto negmask = m_builder.CreateXor(mask, llvm::ConstantInt::getAllOnesValue(Type::Word), "negmask"); auto val1 = m_builder.CreateOr(word, negmask); auto val0 = m_builder.CreateAnd(word, mask); - auto kInRange = m_builder.CreateICmpULE(idx, llvm::ConstantInt::get(Type::i256, 30)); + auto kInRange = m_builder.CreateICmpULE(idx, llvm::ConstantInt::get(Type::Word, 30)); auto result = m_builder.CreateSelect(kInRange, m_builder.CreateSelect(bittest, val1, val0), word); diff --git a/libevmjit/Endianness.cpp b/libevmjit/Endianness.cpp index f0da5f9d4..e062fb77e 100644 --- a/libevmjit/Endianness.cpp +++ b/libevmjit/Endianness.cpp @@ -15,8 +15,8 @@ namespace jit llvm::Value* Endianness::bswap(llvm::IRBuilder<>& _builder, llvm::Value* _word) { // TODO: Native is Little Endian - assert(_word->getType() == Type::i256); - auto bswap = llvm::Intrinsic::getDeclaration(_builder.GetInsertBlock()->getParent()->getParent(), llvm::Intrinsic::bswap, Type::i256); + assert(_word->getType() == Type::Word); + auto bswap = llvm::Intrinsic::getDeclaration(_builder.GetInsertBlock()->getParent()->getParent(), llvm::Intrinsic::bswap, Type::Word); return _builder.CreateCall(bswap, _word); } diff --git a/libevmjit/GasMeter.cpp b/libevmjit/GasMeter.cpp index a0656ace4..7a6a0ebd2 100644 --- a/libevmjit/GasMeter.cpp +++ b/libevmjit/GasMeter.cpp @@ -84,7 +84,7 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager) { auto module = getModule(); - m_gasCheckFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "gas.check", module); + m_gasCheckFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::Word, false), llvm::Function::PrivateLinkage, "gas.check", module); InsertPointGuard guard(m_builder); auto checkBB = llvm::BasicBlock::Create(_builder.getContext(), "Check", m_gasCheckFunc); @@ -113,7 +113,7 @@ void GasMeter::count(Instruction _inst) if (!m_checkCall) { // Create gas check call with mocked block cost at begining of current cost-block - m_checkCall = m_builder.CreateCall(m_gasCheckFunc, llvm::UndefValue::get(Type::i256)); + m_checkCall = m_builder.CreateCall(m_gasCheckFunc, llvm::UndefValue::get(Type::Word)); } m_blockCost += getStepCost(_inst); diff --git a/libevmjit/Memory.cpp b/libevmjit/Memory.cpp index beedd9cb9..c06b22637 100644 --- a/libevmjit/Memory.cpp +++ b/libevmjit/Memory.cpp @@ -29,7 +29,7 @@ Memory::Memory(RuntimeManager& _runtimeManager, GasMeter& _gasMeter): RuntimeHelper(_runtimeManager) { auto module = getModule(); - llvm::Type* argTypes[] = {Type::i256, Type::i256}; + llvm::Type* argTypes[] = {Type::Word, Type::Word}; auto dumpTy = llvm::FunctionType::get(m_builder.getVoidTy(), llvm::ArrayRef(argTypes), false); m_memDump = llvm::Function::Create(dumpTy, llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_memory_dump", module); @@ -37,7 +37,7 @@ Memory::Memory(RuntimeManager& _runtimeManager, GasMeter& _gasMeter): m_data = new llvm::GlobalVariable(*module, Type::BytePtr, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::BytePtr), "mem.data"); m_data->setUnnamedAddr(true); // Address is not important - m_size = new llvm::GlobalVariable(*module, Type::i256, false, llvm::GlobalVariable::PrivateLinkage, Constant::get(0), "mem.size"); + m_size = new llvm::GlobalVariable(*module, Type::Word, false, llvm::GlobalVariable::PrivateLinkage, Constant::get(0), "mem.size"); m_size->setUnnamedAddr(true); // Address is not important llvm::Type* resizeArgs[] = {Type::RuntimePtr, Type::WordPtr}; @@ -47,14 +47,14 @@ Memory::Memory(RuntimeManager& _runtimeManager, GasMeter& _gasMeter): m_resize->setAttributes(llvm::AttributeSet::get(m_resize->getContext(), 1, attrBuilder)); m_require = createRequireFunc(_gasMeter, _runtimeManager); - m_loadWord = createFunc(false, Type::i256, _gasMeter); - m_storeWord = createFunc(true, Type::i256, _gasMeter); + m_loadWord = createFunc(false, Type::Word, _gasMeter); + m_storeWord = createFunc(true, Type::Word, _gasMeter); m_storeByte = createFunc(true, Type::Byte, _gasMeter); } llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _runtimeManager) { - llvm::Type* argTypes[] = {Type::i256, Type::i256}; + llvm::Type* argTypes[] = {Type::Word, Type::Word}; auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, argTypes, false), llvm::Function::PrivateLinkage, "mem.require", getModule()); auto offset = func->arg_begin(); offset->setName("offset"); @@ -67,9 +67,9 @@ llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _ InsertPointGuard guard(m_builder); // Restores insert point at function exit - // BB "check" + // BB "Check" m_builder.SetInsertPoint(checkBB); - auto uaddWO = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::uadd_with_overflow, Type::i256); + auto uaddWO = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::uadd_with_overflow, Type::Word); auto uaddRes = m_builder.CreateCall2(uaddWO, offset, size, "res"); auto sizeRequired = m_builder.CreateExtractValue(uaddRes, 0, "sizeReq"); auto overflow1 = m_builder.CreateExtractValue(uaddRes, 1, "overflow1"); @@ -78,7 +78,7 @@ llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _ auto resizeNeeded = m_builder.CreateOr(tooSmall, overflow1, "resizeNeeded"); m_builder.CreateCondBr(resizeNeeded, resizeBB, returnBB); // OPT branch weights? - // BB "resize" + // BB "Resize" m_builder.SetInsertPoint(resizeBB); // Check gas first uaddRes = m_builder.CreateCall2(uaddWO, sizeRequired, Constant::get(31), "res"); @@ -97,7 +97,7 @@ llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _ m_builder.CreateStore(newData, m_data); m_builder.CreateBr(returnBB); - // BB "return" + // BB "Return" m_builder.SetInsertPoint(returnBB); m_builder.CreateRetVoid(); return func; @@ -105,11 +105,11 @@ llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _ llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, GasMeter&) { - auto isWord = _valueType == Type::i256; + auto isWord = _valueType == Type::Word; - llvm::Type* storeArgs[] = {Type::i256, _valueType}; + llvm::Type* storeArgs[] = {Type::Word, _valueType}; auto name = _isStore ? isWord ? "mstore" : "mstore8" : "mload"; - auto funcType = _isStore ? llvm::FunctionType::get(Type::Void, storeArgs, false) : llvm::FunctionType::get(Type::i256, Type::i256, false); + auto funcType = _isStore ? llvm::FunctionType::get(Type::Void, storeArgs, false) : llvm::FunctionType::get(Type::Word, Type::Word, false); auto func = llvm::Function::Create(funcType, llvm::Function::PrivateLinkage, name, getModule()); InsertPointGuard guard(m_builder); // Restores insert point at function exit @@ -185,7 +185,7 @@ void Memory::require(llvm::Value* _offset, llvm::Value* _size) void Memory::copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value* _srcIdx, llvm::Value* _destMemIdx, llvm::Value* _reqBytes) { - auto zero256 = llvm::ConstantInt::get(Type::i256, 0); + auto zero256 = llvm::ConstantInt::get(Type::Word, 0); require(_destMemIdx, _reqBytes); diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 361089ba1..292eb02bd 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -22,7 +22,7 @@ llvm::StructType* RuntimeData::getType() { llvm::Type* elems[] = { - llvm::ArrayType::get(Type::i256, _size), + llvm::ArrayType::get(Type::Word, _size), Type::BytePtr, Type::BytePtr, Type::BytePtr diff --git a/libevmjit/Stack.cpp b/libevmjit/Stack.cpp index d6538a22d..bb157b847 100644 --- a/libevmjit/Stack.cpp +++ b/libevmjit/Stack.cpp @@ -18,7 +18,7 @@ Stack::Stack(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager): CompilerHelper(_builder), m_runtimeManager(_runtimeManager) { - m_arg = m_builder.CreateAlloca(Type::i256, nullptr, "stack.arg"); + m_arg = m_builder.CreateAlloca(Type::Word, nullptr, "stack.arg"); using namespace llvm; using Linkage = GlobalValue::LinkageTypes; diff --git a/libevmjit/Type.cpp b/libevmjit/Type.cpp index 37757dfdf..a72ec0eda 100644 --- a/libevmjit/Type.cpp +++ b/libevmjit/Type.cpp @@ -12,7 +12,7 @@ namespace eth namespace jit { -llvm::IntegerType* Type::i256; +llvm::IntegerType* Type::Word; llvm::PointerType* Type::WordPtr; llvm::IntegerType* Type::lowPrecision; llvm::IntegerType* Type::Size; @@ -24,8 +24,8 @@ llvm::PointerType* Type::RuntimePtr; void Type::init(llvm::LLVMContext& _context) { - i256 = llvm::Type::getIntNTy(_context, 256); - WordPtr = i256->getPointerTo(); + Word = llvm::Type::getIntNTy(_context, 256); + WordPtr = Word->getPointerTo(); lowPrecision = llvm::Type::getInt64Ty(_context); // TODO: Size should be architecture-dependent Size = llvm::Type::getInt64Ty(_context); @@ -38,14 +38,14 @@ void Type::init(llvm::LLVMContext& _context) llvm::ConstantInt* Constant::get(int64_t _n) { - return llvm::ConstantInt::getSigned(Type::i256, _n); + return llvm::ConstantInt::getSigned(Type::Word, _n); } llvm::ConstantInt* Constant::get(u256 _n) { llvm::APInt n(256, _n.str(0, std::ios_base::hex), 16); assert(n.toString(10, false) == _n.str()); - return static_cast(llvm::ConstantInt::get(Type::i256, n)); + return static_cast(llvm::ConstantInt::get(Type::Word, n)); } llvm::ConstantInt* Constant::get(ReturnCode _returnCode) diff --git a/libevmjit/Type.h b/libevmjit/Type.h index 4658f94bb..0d8c6c530 100644 --- a/libevmjit/Type.h +++ b/libevmjit/Type.h @@ -14,7 +14,7 @@ namespace jit struct Type { - static llvm::IntegerType* i256; + static llvm::IntegerType* Word; static llvm::PointerType* WordPtr; /// Type for doing low precision arithmetics where 256-bit precision is not supported by native target From aa3ae144220d9255c158c5012118bac2c8c1109d Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Fri, 31 Oct 2014 14:46:32 +0000 Subject: [PATCH 306/641] code cleanup & coding-standardization --- libevmjit/Compiler.cpp | 243 +++++++++++++++++++---------------------- 1 file changed, 112 insertions(+), 131 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 1e394eba0..cdb9a6448 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -32,28 +32,27 @@ namespace eth namespace jit { -Compiler::Compiler(): - m_builder(llvm::getGlobalContext()), - m_jumpTableBlock(), - m_badJumpBlock() +Compiler::Compiler(Options const& _options): + m_options(_options), + m_builder(llvm::getGlobalContext()) { Type::init(m_builder.getContext()); } -void Compiler::createBasicBlocks(bytesConstRef bytecode) +void Compiler::createBasicBlocks(bytesConstRef _bytecode) { std::set splitPoints; // Sorted collections of instruction indices where basic blocks start/end std::map directJumpTargets; std::vector indirectJumpTargets; - boost::dynamic_bitset<> validJumpTargets(std::max(bytecode.size(), size_t(1))); + boost::dynamic_bitset<> validJumpTargets(std::max(_bytecode.size(), size_t(1))); splitPoints.insert(0); // First basic block validJumpTargets[0] = true; - for (auto curr = bytecode.begin(); curr != bytecode.end(); ++curr) + for (auto curr = _bytecode.begin(); curr != _bytecode.end(); ++curr) { - ProgramCounter currentPC = curr - bytecode.begin(); + ProgramCounter currentPC = curr - _bytecode.begin(); validJumpTargets[currentPC] = true; auto inst = Instruction(*curr); @@ -62,19 +61,19 @@ void Compiler::createBasicBlocks(bytesConstRef bytecode) case Instruction::ANY_PUSH: { - auto val = readPushData(curr, bytecode.end()); + auto val = readPushData(curr, _bytecode.end()); auto next = curr + 1; - if (next == bytecode.end()) + if (next == _bytecode.end()) break; auto nextInst = Instruction(*next); if (nextInst == Instruction::JUMP || nextInst == Instruction::JUMPI) { // Create a block for the JUMP target. - ProgramCounter targetPC = val < bytecode.size() ? val.convert_to() : bytecode.size(); + ProgramCounter targetPC = val < _bytecode.size() ? val.convert_to() : _bytecode.size(); splitPoints.insert(targetPC); - ProgramCounter jumpPC = (next - bytecode.begin()); + ProgramCounter jumpPC = (next - _bytecode.begin()); directJumpTargets[jumpPC] = targetPC; } break; @@ -83,7 +82,7 @@ void Compiler::createBasicBlocks(bytesConstRef bytecode) case Instruction::JUMPDEST: { // A basic block starts at the next instruction. - if (currentPC + 1 < bytecode.size()) + if (currentPC + 1 < _bytecode.size()) { splitPoints.insert(currentPC + 1); indirectJumpTargets.push_back(currentPC + 1); @@ -98,7 +97,7 @@ void Compiler::createBasicBlocks(bytesConstRef bytecode) case Instruction::SUICIDE: { // Create a basic block starting at the following instruction. - if (curr + 1 < bytecode.end()) + if (curr + 1 < _bytecode.end()) { splitPoints.insert(currentPC + 1); } @@ -113,7 +112,7 @@ void Compiler::createBasicBlocks(bytesConstRef bytecode) // Remove split points generated from jumps out of code or into data. for (auto it = splitPoints.cbegin(); it != splitPoints.cend();) { - if (*it > bytecode.size() || !validJumpTargets[*it]) + if (*it > _bytecode.size() || !validJumpTargets[*it]) it = splitPoints.erase(it); else ++it; @@ -123,7 +122,7 @@ void Compiler::createBasicBlocks(bytesConstRef bytecode) { auto beginInstIdx = *it; ++it; - auto endInstIdx = it != splitPoints.cend() ? *it : bytecode.size(); + auto endInstIdx = it != splitPoints.cend() ? *it : _bytecode.size(); basicBlocks.emplace(std::piecewise_construct, std::forward_as_tuple(beginInstIdx), std::forward_as_tuple(beginInstIdx, endInstIdx, m_mainFunc, m_builder)); } @@ -133,7 +132,7 @@ void Compiler::createBasicBlocks(bytesConstRef bytecode) for (auto it = directJumpTargets.cbegin(); it != directJumpTargets.cend(); ++it) { - if (it->second >= bytecode.size()) + if (it->second >= _bytecode.size()) { // Jumping out of code means STOP m_directJumpTargets[it->first] = m_stopBB; @@ -154,12 +153,10 @@ void Compiler::createBasicBlocks(bytesConstRef bytecode) } for (auto it = indirectJumpTargets.cbegin(); it != indirectJumpTargets.cend(); ++it) - { m_indirectJumpTargets.push_back(&basicBlocks.find(*it)->second); - } } -std::unique_ptr Compiler::compile(bytesConstRef bytecode) +std::unique_ptr Compiler::compile(bytesConstRef _bytecode) { auto module = std::unique_ptr(new llvm::Module("main", m_builder.getContext())); @@ -173,7 +170,7 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) auto entryBlock = llvm::BasicBlock::Create(m_builder.getContext(), "entry", m_mainFunc); m_builder.SetInsertPoint(entryBlock); - createBasicBlocks(bytecode); + createBasicBlocks(_bytecode); // Init runtime structures. RuntimeManager runtimeManager(m_builder); @@ -191,13 +188,11 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) auto iterCopy = basicBlockPairIt; ++iterCopy; auto nextBasicBlock = (iterCopy != basicBlocks.end()) ? iterCopy->second.llvm() : nullptr; - compileBasicBlock(basicBlock, bytecode, runtimeManager, arith, memory, ext, gasMeter, nextBasicBlock); + compileBasicBlock(basicBlock, _bytecode, runtimeManager, arith, memory, ext, gasMeter, nextBasicBlock); } // Code for special blocks: // TODO: move to separate function. - // Note: Right now the codegen for special blocks depends only on createBasicBlock(), - // not on the codegen for 'regular' blocks. But it has to be done before linkBasicBlocks(). m_builder.SetInsertPoint(m_stopBB); m_builder.CreateRet(Constant::get(ReturnCode::Stop)); @@ -218,75 +213,59 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) } } else - { m_builder.CreateBr(m_badJumpBlock->llvm()); - } removeDeadBlocks(); - if (getenv("EVMCC_DEBUG_BLOCKS")) - { - std::ofstream ofs("blocks-init.dot"); - dumpBasicBlockGraph(ofs); - ofs.close(); - std::cerr << "\n\nAfter dead block elimination \n\n"; - dump(); - } + dumpCFGifRequired("blocks-init.dot"); - //if (getenv("EVMCC_OPTIMIZE_STACK")) - //{ + if (m_options.optimizeStack) + { std::vector blockList; for (auto& entry : basicBlocks) blockList.push_back(&entry.second); - if (m_jumpTableBlock != nullptr) + if (m_jumpTableBlock) blockList.push_back(m_jumpTableBlock.get()); BasicBlock::linkLocalStacks(blockList, m_builder); - if (getenv("EVMCC_DEBUG_BLOCKS")) - { - std::ofstream ofs("blocks-opt.dot"); - dumpBasicBlockGraph(ofs); - ofs.close(); - std::cerr << "\n\nAfter stack optimization \n\n"; - dump(); - } - //} + dumpCFGifRequired("blocks-opt.dot"); + } for (auto& entry : basicBlocks) entry.second.localStack().synchronize(stack); - if (m_jumpTableBlock != nullptr) + if (m_jumpTableBlock) m_jumpTableBlock->localStack().synchronize(stack); - if (getenv("EVMCC_DEBUG_BLOCKS")) + dumpCFGifRequired("blocks-sync.dot"); + + if (m_jumpTableBlock && m_options.rewriteSwitchToBranches) { - std::ofstream ofs("blocks-sync.dot"); - dumpBasicBlockGraph(ofs); - ofs.close(); - std::cerr << "\n\nAfter stack synchronization \n\n"; - dump(); + llvm::FunctionPassManager fpManager(module.get()); + fpManager.add(llvm::createLowerSwitchPass()); + fpManager.doInitialization(); + fpManager.run(*m_mainFunc); } - llvm::FunctionPassManager fpManager(module.get()); - fpManager.add(llvm::createLowerSwitchPass()); - fpManager.doInitialization(); - fpManager.run(*m_mainFunc); - return module; } -void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, RuntimeManager& _runtimeManager, Arith256& arith, Memory& memory, Ext& ext, GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock) +void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytesConstRef _bytecode, RuntimeManager& _runtimeManager, + Arith256& _arith, Memory& _memory, Ext& _ext, GasMeter& _gasMeter, llvm::BasicBlock* _nextBasicBlock) { - m_builder.SetInsertPoint(basicBlock.llvm()); - auto& stack = basicBlock.localStack(); + if (!_nextBasicBlock) // this is the last block in the code + _nextBasicBlock = m_stopBB; + + m_builder.SetInsertPoint(_basicBlock.llvm()); + auto& stack = _basicBlock.localStack(); - for (auto currentPC = basicBlock.begin(); currentPC != basicBlock.end(); ++currentPC) + for (auto currentPC = _basicBlock.begin(); currentPC != _basicBlock.end(); ++currentPC) { - auto inst = static_cast(bytecode[currentPC]); + auto inst = static_cast(_bytecode[currentPC]); - gasMeter.count(inst); + _gasMeter.count(inst); switch (inst) { @@ -313,7 +292,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, { auto lhs = stack.pop(); auto rhs = stack.pop(); - auto res = arith.mul(lhs, rhs); + auto res = _arith.mul(lhs, rhs); stack.push(res); break; } @@ -322,7 +301,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, { auto lhs = stack.pop(); auto rhs = stack.pop(); - auto res = arith.div(lhs, rhs); + auto res = _arith.div(lhs, rhs); stack.push(res); break; } @@ -331,7 +310,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, { auto lhs = stack.pop(); auto rhs = stack.pop(); - auto res = arith.sdiv(lhs, rhs); + auto res = _arith.sdiv(lhs, rhs); stack.push(res); break; } @@ -340,7 +319,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, { auto lhs = stack.pop(); auto rhs = stack.pop(); - auto res = arith.mod(lhs, rhs); + auto res = _arith.mod(lhs, rhs); stack.push(res); break; } @@ -349,7 +328,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, { auto lhs = stack.pop(); auto rhs = stack.pop(); - auto res = arith.smod(lhs, rhs); + auto res = _arith.smod(lhs, rhs); stack.push(res); break; } @@ -358,7 +337,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, { auto left = stack.pop(); auto right = stack.pop(); - auto ret = ext.exp(left, right); + auto ret = _ext.exp(left, right); stack.push(ret); break; } @@ -480,7 +459,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto lhs = stack.pop(); auto rhs = stack.pop(); auto mod = stack.pop(); - auto res = arith.addmod(lhs, rhs, mod); + auto res = _arith.addmod(lhs, rhs, mod); stack.push(res); break; } @@ -490,7 +469,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto lhs = stack.pop(); auto rhs = stack.pop(); auto mod = stack.pop(); - auto res = arith.mulmod(lhs, rhs, mod); + auto res = _arith.mulmod(lhs, rhs, mod); stack.push(res); break; } @@ -529,8 +508,8 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, { auto inOff = stack.pop(); auto inSize = stack.pop(); - memory.require(inOff, inSize); - auto hash = ext.sha3(inOff, inSize); + _memory.require(inOff, inSize); + auto hash = _ext.sha3(inOff, inSize); stack.push(hash); break; } @@ -543,9 +522,9 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, case Instruction::ANY_PUSH: { - auto curr = bytecode.begin() + currentPC; // TODO: replace currentPC with iterator - auto value = readPushData(curr, bytecode.end()); - currentPC = curr - bytecode.begin(); + auto curr = _bytecode.begin() + currentPC; // TODO: replace currentPC with iterator + auto value = readPushData(curr, _bytecode.end()); + currentPC = curr - _bytecode.begin(); stack.push(Constant::get(value)); break; @@ -568,7 +547,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, case Instruction::MLOAD: { auto addr = stack.pop(); - auto word = memory.loadWord(addr); + auto word = _memory.loadWord(addr); stack.push(word); break; } @@ -577,7 +556,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, { auto addr = stack.pop(); auto word = stack.pop(); - memory.storeWord(addr, word); + _memory.storeWord(addr, word); break; } @@ -585,13 +564,13 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, { auto addr = stack.pop(); auto word = stack.pop(); - memory.storeByte(addr, word); + _memory.storeByte(addr, word); break; } case Instruction::MSIZE: { - auto word = memory.getSize(); + auto word = _memory.getSize(); stack.push(word); break; } @@ -599,7 +578,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, case Instruction::SLOAD: { auto index = stack.pop(); - auto value = ext.store(index); + auto value = _ext.store(index); stack.push(value); break; } @@ -608,8 +587,8 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, { auto index = stack.pop(); auto value = stack.pop(); - gasMeter.countSStore(ext, index, value); - ext.setStore(index, value); + _gasMeter.countSStore(_ext, index, value); + _ext.setStore(index, value); break; } @@ -621,7 +600,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, // 2. m_directJumpTargets[currentPC] is defined (meaning that the previous instruction is a PUSH) // Otherwise generate a indirect jump (a switch). llvm::BasicBlock* targetBlock = nullptr; - if (currentPC != basicBlock.begin()) + if (currentPC != _basicBlock.begin()) { auto pairIter = m_directJumpTargets.find(currentPC); if (pairIter != m_directJumpTargets.end()) @@ -647,17 +626,13 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto zero = Constant::get(0); auto cond = m_builder.CreateICmpNE(val, zero, "nonzero"); - - if (!nextBasicBlock) // In case JUMPI is the last instruction - nextBasicBlock = m_stopBB; - if (targetBlock) { stack.pop(); - m_builder.CreateCondBr(cond, targetBlock, nextBasicBlock); + m_builder.CreateCondBr(cond, targetBlock, _nextBasicBlock); } else - m_builder.CreateCondBr(cond, m_jumpTableBlock->llvm(), nextBasicBlock); + m_builder.CreateCondBr(cond, m_jumpTableBlock->llvm(), _nextBasicBlock); } break; @@ -699,7 +674,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, case Instruction::BALANCE: { auto address = stack.pop(); - auto value = ext.balance(address); + auto value = _ext.balance(address); stack.push(value); break; } @@ -707,7 +682,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, case Instruction::EXTCODESIZE: { auto addr = stack.pop(); - auto value = ext.codesizeAt(addr); + auto value = _ext.codesizeAt(addr); stack.push(value); break; } @@ -721,7 +696,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto srcPtr = _runtimeManager.getCallData(); auto srcSize = _runtimeManager.get(RuntimeData::CallDataSize); - memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); + _memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); break; } @@ -734,7 +709,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto srcPtr = _runtimeManager.getCode(); // TODO: Code & its size are constants, feature #80814234 auto srcSize = _runtimeManager.get(RuntimeData::CodeSize); - memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); + _memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); break; } @@ -745,17 +720,17 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto srcIdx = stack.pop(); auto reqBytes = stack.pop(); - auto srcPtr = ext.codeAt(extAddr); - auto srcSize = ext.codesizeAt(extAddr); + auto srcPtr = _ext.codeAt(extAddr); + auto srcSize = _ext.codesizeAt(extAddr); - memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); + _memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); break; } case Instruction::CALLDATALOAD: { auto index = stack.pop(); - auto value = ext.calldataload(index); + auto value = _ext.calldataload(index); stack.push(value); break; } @@ -765,9 +740,9 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto endowment = stack.pop(); auto initOff = stack.pop(); auto initSize = stack.pop(); - memory.require(initOff, initSize); + _memory.require(initOff, initSize); - auto address = ext.create(endowment, initOff, initSize); + auto address = _ext.create(endowment, initOff, initSize); stack.push(address); break; } @@ -783,21 +758,21 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto outOff = stack.pop(); auto outSize = stack.pop(); - gasMeter.commitCostBlock(gas); + _gasMeter.commitCostBlock(gas); - // Require memory for the max of in and out buffers + // Require _memory for the max of in and out buffers auto inSizeReq = m_builder.CreateAdd(inOff, inSize, "inSizeReq"); auto outSizeReq = m_builder.CreateAdd(outOff, outSize, "outSizeReq"); auto cmp = m_builder.CreateICmpUGT(inSizeReq, outSizeReq); auto sizeReq = m_builder.CreateSelect(cmp, inSizeReq, outSizeReq, "sizeReq"); - memory.require(sizeReq); + _memory.require(sizeReq); auto receiveAddress = codeAddress; if (inst == Instruction::CALLCODE) receiveAddress = _runtimeManager.get(RuntimeData::Address); - auto ret = ext.call(gas, receiveAddress, value, inOff, inSize, outOff, outSize, codeAddress); - gasMeter.giveBack(gas); + auto ret = _ext.call(gas, receiveAddress, value, inOff, inSize, outOff, outSize, codeAddress); + _gasMeter.giveBack(gas); stack.push(ret); break; } @@ -807,7 +782,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto index = stack.pop(); auto size = stack.pop(); - memory.require(index, size); + _memory.require(index, size); _runtimeManager.registerReturnData(index, size); m_builder.CreateRet(Constant::get(ReturnCode::Return)); @@ -815,13 +790,14 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, } case Instruction::SUICIDE: - { - auto address = stack.pop(); - ext.suicide(address); - // Fall through - } case Instruction::STOP: { + if (inst == Instruction::SUICIDE) + { + auto address = stack.pop(); + _ext.suicide(address); + } + m_builder.CreateRet(Constant::get(ReturnCode::Stop)); break; } @@ -834,15 +810,11 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, } } - gasMeter.commitCostBlock(); + _gasMeter.commitCostBlock(); - if (!basicBlock.llvm()->getTerminator()) // If block not terminated - { - if (nextBasicBlock) - m_builder.CreateBr(nextBasicBlock); // Branch to the next block - else - m_builder.CreateRet(Constant::get(ReturnCode::Stop)); // Return STOP code - } + // Block may have no terminator if the next instruction is a jump destination. + if (!_basicBlock.llvm()->getTerminator()) + m_builder.CreateBr(_nextBasicBlock); } @@ -877,11 +849,22 @@ void Compiler::removeDeadBlocks() } } -void Compiler::dumpBasicBlockGraph(std::ostream& out) +void Compiler::dumpCFGifRequired(std::string const& _dotfilePath) +{ + if (! m_options.dumpCFG) + return; + + // TODO: handle i/o failures + std::ofstream ofs(_dotfilePath); + dumpCFGtoStream(ofs); + ofs.close(); +} + +void Compiler::dumpCFGtoStream(std::ostream& _out) { - out << "digraph BB {\n" - << " node [shape=record, fontname=Courier, fontsize=10];\n" - << " entry [share=record, label=\"entry block\"];\n"; + _out << "digraph BB {\n" + << " node [shape=record, fontname=Courier, fontsize=10];\n" + << " entry [share=record, label=\"entry block\"];\n"; std::vector blocks; for (auto& pair : basicBlocks) @@ -901,7 +884,7 @@ void Compiler::dumpBasicBlockGraph(std::ostream& out) std::ostringstream oss; bb->dump(oss, true); - out << " \"" << blockName << "\" [shape=record, label=\" { " << blockName << "|" << oss.str() << "} \"];\n"; + _out << " \"" << blockName << "\" [shape=record, label=\" { " << blockName << "|" << oss.str() << "} \"];\n"; } // Output edges @@ -912,15 +895,13 @@ void Compiler::dumpBasicBlockGraph(std::ostream& out) auto end = llvm::pred_end(bb->llvm()); for (llvm::pred_iterator it = llvm::pred_begin(bb->llvm()); it != end; ++it) { - out << " \"" << (*it)->getName().str() << "\" -> \"" << blockName << "\" [" - << ((m_jumpTableBlock.get() && *it == m_jumpTableBlock.get()->llvm()) ? "style = dashed, " : "") - //<< "label = \"" - //<< phiNodesPerBlock[bb] - << "];\n"; + _out << " \"" << (*it)->getName().str() << "\" -> \"" << blockName << "\" [" + << ((m_jumpTableBlock.get() && *it == m_jumpTableBlock.get()->llvm()) ? "style = dashed, " : "") + << "];\n"; } } - out << "}\n"; + _out << "}\n"; } void Compiler::dump() From bb4c21e5f3add80b537b222fa0ceeb2a8561d48a Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Fri, 31 Oct 2014 14:47:16 +0000 Subject: [PATCH 307/641] allow --jit as non first argument --- test/vm.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/vm.cpp b/test/vm.cpp index 102de7c4f..3fe12dc1f 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -535,7 +535,9 @@ void doTests(json_spirit::mValue& v, bool _fillin) auto argc = boost::unit_test::framework::master_test_suite().argc; auto argv = boost::unit_test::framework::master_test_suite().argv; - auto useJit = argc >= 2 && std::string(argv[1]) == "--jit"; + auto useJit = false; + for (auto i = 0; i < argc && !useJit; ++i) + useJit |= std::string(argv[i]) == "--jit"; auto vmKind = useJit ? VMFace::JIT : VMFace::Interpreter; dev::test::FakeExtVM fev; @@ -585,8 +587,8 @@ void doTests(json_spirit::mValue& v, bool _fillin) cnote << "Execution time: " << std::chrono::duration_cast(testDuration).count() << " ms"; + break; } - break; } auto gas = vm->gas(); @@ -826,7 +828,7 @@ BOOST_AUTO_TEST_CASE(vmSystemOperationsTest) BOOST_AUTO_TEST_CASE(userDefinedFile) { - if (boost::unit_test::framework::master_test_suite().argc == 2) + if (boost::unit_test::framework::master_test_suite().argc >= 2) { string filename = boost::unit_test::framework::master_test_suite().argv[1]; int currentVerbosity = g_logVerbosity; From a19f3df3b39515bbc84599a4cfe925c254323af6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 31 Oct 2014 15:50:03 +0100 Subject: [PATCH 308/641] Coding style: use "o_" prefix for output function arguments --- libevmjit/Arith256.cpp | 28 ++++++++++++++-------------- libevmjit/Ext.cpp | 40 ++++++++++++++++++++-------------------- libevmjit/Memory.cpp | 4 +--- libevmjit/Stack.cpp | 8 ++++---- 4 files changed, 39 insertions(+), 41 deletions(-) diff --git a/libevmjit/Arith256.cpp b/libevmjit/Arith256.cpp index 82e31e61d..79a8fe79c 100644 --- a/libevmjit/Arith256.cpp +++ b/libevmjit/Arith256.cpp @@ -103,55 +103,55 @@ extern "C" using namespace dev::eth::jit; - EXPORT void arith_mul(i256* _arg1, i256* _arg2, i256* _result) + EXPORT void arith_mul(i256* _arg1, i256* _arg2, i256* o_result) { dev::u256 arg1 = llvm2eth(*_arg1); dev::u256 arg2 = llvm2eth(*_arg2); - *_result = eth2llvm(arg1 * arg2); + *o_result = eth2llvm(arg1 * arg2); } - EXPORT void arith_div(i256* _arg1, i256* _arg2, i256* _result) + EXPORT void arith_div(i256* _arg1, i256* _arg2, i256* o_result) { dev::u256 arg1 = llvm2eth(*_arg1); dev::u256 arg2 = llvm2eth(*_arg2); - *_result = eth2llvm(arg2 == 0 ? arg2 : arg1 / arg2); + *o_result = eth2llvm(arg2 == 0 ? arg2 : arg1 / arg2); } - EXPORT void arith_mod(i256* _arg1, i256* _arg2, i256* _result) + EXPORT void arith_mod(i256* _arg1, i256* _arg2, i256* o_result) { dev::u256 arg1 = llvm2eth(*_arg1); dev::u256 arg2 = llvm2eth(*_arg2); - *_result = eth2llvm(arg2 == 0 ? arg2 : arg1 % arg2); + *o_result = eth2llvm(arg2 == 0 ? arg2 : arg1 % arg2); } - EXPORT void arith_sdiv(i256* _arg1, i256* _arg2, i256* _result) + EXPORT void arith_sdiv(i256* _arg1, i256* _arg2, i256* o_result) { dev::u256 arg1 = llvm2eth(*_arg1); dev::u256 arg2 = llvm2eth(*_arg2); - *_result = eth2llvm(arg2 == 0 ? arg2 : dev::s2u(dev::u2s(arg1) / dev::u2s(arg2))); + *o_result = eth2llvm(arg2 == 0 ? arg2 : dev::s2u(dev::u2s(arg1) / dev::u2s(arg2))); } - EXPORT void arith_smod(i256* _arg1, i256* _arg2, i256* _result) + EXPORT void arith_smod(i256* _arg1, i256* _arg2, i256* o_result) { dev::u256 arg1 = llvm2eth(*_arg1); dev::u256 arg2 = llvm2eth(*_arg2); - *_result = eth2llvm(arg2 == 0 ? arg2 : dev::s2u(dev::u2s(arg1) % dev::u2s(arg2))); + *o_result = eth2llvm(arg2 == 0 ? arg2 : dev::s2u(dev::u2s(arg1) % dev::u2s(arg2))); } - EXPORT void arith_mulmod(i256* _arg1, i256* _arg2, i256* _arg3, i256* _result) + EXPORT void arith_mulmod(i256* _arg1, i256* _arg2, i256* _arg3, i256* o_result) { dev::u256 arg1 = llvm2eth(*_arg1); dev::u256 arg2 = llvm2eth(*_arg2); dev::u256 arg3 = llvm2eth(*_arg3); - *_result = eth2llvm(dev::u256((dev::bigint(arg1) * dev::bigint(arg2)) % arg3)); + *o_result = eth2llvm(dev::u256((dev::bigint(arg1) * dev::bigint(arg2)) % arg3)); } - EXPORT void arith_addmod(i256* _arg1, i256* _arg2, i256* _arg3, i256* _result) + EXPORT void arith_addmod(i256* _arg1, i256* _arg2, i256* _arg3, i256* o_result) { dev::u256 arg1 = llvm2eth(*_arg1); dev::u256 arg2 = llvm2eth(*_arg2); dev::u256 arg3 = llvm2eth(*_arg3); - *_result = eth2llvm(dev::u256((dev::bigint(arg1) + dev::bigint(arg2)) % arg3)); + *o_result = eth2llvm(dev::u256((dev::bigint(arg1) + dev::bigint(arg2)) % arg3)); } } diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 0fe795a1f..f39ab5755 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -168,11 +168,11 @@ extern "C" using namespace dev::eth::jit; - EXPORT void ext_store(Runtime* _rt, i256* _index, i256* _value) + EXPORT void ext_store(Runtime* _rt, i256* _index, i256* o_value) { auto index = llvm2eth(*_index); auto value = _rt->getExt().store(index); // Interface uses native endianness - *_value = eth2llvm(value); + *o_value = eth2llvm(value); } EXPORT void ext_setStore(Runtime* _rt, i256* _index, i256* _value) @@ -187,28 +187,28 @@ extern "C" ext.setStore(index, value); // Interface uses native endianness } - EXPORT void ext_calldataload(Runtime* _rt, i256* _index, i256* _value) + EXPORT void ext_calldataload(Runtime* _rt, i256* _index, i256* o_value) { auto index = static_cast(llvm2eth(*_index)); assert(index + 31 > index); // TODO: Handle large index - auto b = reinterpret_cast(_value); + auto b = reinterpret_cast(o_value); for (size_t i = index, j = 0; i <= index + 31; ++i, ++j) b[j] = i < _rt->getExt().data.size() ? _rt->getExt().data[i] : 0; // Keep Big Endian // TODO: It all can be done by adding padding to data or by using min() algorithm without branch } - EXPORT void ext_balance(Runtime* _rt, h256* _address, i256* _value) + EXPORT void ext_balance(Runtime* _rt, h256* _address, i256* o_value) { auto u = _rt->getExt().balance(right160(*_address)); - *_value = eth2llvm(u); + *o_value = eth2llvm(u); } - EXPORT void ext_suicide(Runtime* _rt, h256* _address) + EXPORT void ext_suicide(Runtime* _rt, h256 const* _address) { _rt->getExt().suicide(right160(*_address)); } - EXPORT void ext_create(Runtime* _rt, i256* _endowment, i256* _initOff, i256* _initSize, h256* _address) + EXPORT void ext_create(Runtime* _rt, i256* _endowment, i256* _initOff, i256* _initSize, h256* o_address) { auto&& ext = _rt->getExt(); auto endowment = llvm2eth(*_endowment); @@ -222,21 +222,21 @@ extern "C" auto&& initRef = bytesConstRef(_rt->getMemory().data() + initOff, initSize); OnOpFunc onOp {}; // TODO: Handle that thing h256 address(ext.create(endowment, &gas, initRef, onOp), h256::AlignRight); - *_address = address; + *o_address = address; } else - *_address = {}; + *o_address = {}; } - EXPORT void ext_call(Runtime* _rt, i256* _gas, h256* _receiveAddress, i256* _value, i256* _inOff, i256* _inSize, i256* _outOff, i256* _outSize, h256* _codeAddress, i256* _ret) + EXPORT void ext_call(Runtime* _rt, i256* io_gas, h256* _receiveAddress, i256* _value, i256* _inOff, i256* _inSize, i256* _outOff, i256* _outSize, h256* _codeAddress, i256* o_ret) { auto&& ext = _rt->getExt(); auto value = llvm2eth(*_value); auto ret = false; - auto gas = llvm2eth(*_gas); + auto gas = llvm2eth(*io_gas); if (ext.balance(ext.myAddress) >= value) { ext.subBalance(value); @@ -252,25 +252,25 @@ extern "C" ret = ext.call(receiveAddress, value, inRef, &gas, outRef, onOp, {}, codeAddress); } - *_gas = eth2llvm(gas); - _ret->a = ret ? 1 : 0; + *io_gas = eth2llvm(gas); + o_ret->a = ret ? 1 : 0; } - EXPORT void ext_sha3(Runtime* _rt, i256* _inOff, i256* _inSize, i256* _ret) + EXPORT void ext_sha3(Runtime* _rt, i256* _inOff, i256* _inSize, i256* o_ret) { auto inOff = static_cast(llvm2eth(*_inOff)); auto inSize = static_cast(llvm2eth(*_inSize)); auto dataRef = bytesConstRef(_rt->getMemory().data() + inOff, inSize); auto hash = sha3(dataRef); - *_ret = *reinterpret_cast(&hash); + *o_ret = *reinterpret_cast(&hash); } - EXPORT void ext_exp(Runtime*, i256* _left, i256* _right, i256* _ret) + EXPORT void ext_exp(Runtime*, i256* _left, i256* _right, i256* o_ret) { bigint left = llvm2eth(*_left); bigint right = llvm2eth(*_right); auto ret = static_cast(boost::multiprecision::powm(left, right, bigint(2) << 256)); - *_ret = eth2llvm(ret); + *o_ret = eth2llvm(ret); } EXPORT unsigned char* ext_codeAt(Runtime* _rt, h256* _addr256) @@ -281,12 +281,12 @@ extern "C" return const_cast(code.data()); } - EXPORT void ext_codesizeAt(Runtime* _rt, h256* _addr256, i256* _ret) + EXPORT void ext_codesizeAt(Runtime* _rt, h256* _addr256, i256* o_ret) { auto&& ext = _rt->getExt(); auto addr = right160(*_addr256); auto& code = ext.codeAt(addr); - *_ret = eth2llvm(u256(code.size())); + *o_ret = eth2llvm(u256(code.size())); } } diff --git a/libevmjit/Memory.cpp b/libevmjit/Memory.cpp index c06b22637..c3e904ef8 100644 --- a/libevmjit/Memory.cpp +++ b/libevmjit/Memory.cpp @@ -224,7 +224,6 @@ void Memory::dump(uint64_t _begin, uint64_t _end) extern "C" { - using namespace dev::eth::jit; EXPORT uint8_t* mem_resize(Runtime* _rt, i256* _size) @@ -234,5 +233,4 @@ extern "C" memory.resize(size); return memory.data(); } - -} // extern "C" +} diff --git a/libevmjit/Stack.cpp b/libevmjit/Stack.cpp index bb157b847..494750b43 100644 --- a/libevmjit/Stack.cpp +++ b/libevmjit/Stack.cpp @@ -79,7 +79,7 @@ extern "C" stack.erase(stack.end() - _count, stack.end()); } - EXPORT void stack_push(Runtime* _rt, i256* _word) + EXPORT void stack_push(Runtime* _rt, i256 const* _word) { auto& stack = _rt->getStack(); stack.push_back(*_word); @@ -88,17 +88,17 @@ extern "C" Stack::maxStackSize = stack.size(); } - EXPORT void stack_get(Runtime* _rt, uint64_t _index, i256* _ret) + EXPORT void stack_get(Runtime* _rt, uint64_t _index, i256* o_ret) { auto& stack = _rt->getStack(); // TODO: encode _index and stack size in the return code if (stack.size() <= _index) longjmp(_rt->getJmpBuf(), static_cast(ReturnCode::StackTooSmall)); - *_ret = *(stack.rbegin() + _index); + *o_ret = *(stack.rbegin() + _index); } - EXPORT void stack_set(Runtime* _rt, uint64_t _index, i256* _word) + EXPORT void stack_set(Runtime* _rt, uint64_t _index, i256 const* _word) { auto& stack = _rt->getStack(); // TODO: encode _index and stack size in the return code From c52fd78fb66d63bb292123f7e617845201b92625 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 31 Oct 2014 15:57:54 +0100 Subject: [PATCH 309/641] Use llvm.longjmp intrinsic for longjmp [Delivers #81792986] --- libevmjit/Runtime.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 292eb02bd..96a5f75a3 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -3,6 +3,7 @@ #include #include +#include #include @@ -105,7 +106,7 @@ RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder): CompilerHelper(_bui { m_dataPtr = new llvm::GlobalVariable(*getModule(), Type::RuntimePtr, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::RuntimePtr), "rt"); llvm::Type* args[] = {Type::BytePtr, m_builder.getInt32Ty()}; - m_longjmp = llvm::Function::Create(llvm::FunctionType::get(Type::Void, args, false), llvm::Function::ExternalLinkage, "longjmp", getModule()); + m_longjmp = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::longjmp); // Export data auto mainFunc = getMainFunction(); From 44a9ea0fb850378bfd8e7d0ea843892762a410a9 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Fri, 31 Oct 2014 15:46:05 +0000 Subject: [PATCH 310/641] code cleanup and coding-standardization --- libevmjit/Compiler.cpp | 4 +- libevmjit/Compiler.cpp.orig | 924 ++++++++++++++++++++++++++++++++++++ libevmjit/Compiler.h | 69 +-- libevmjit/VM.cpp | 3 +- 4 files changed, 970 insertions(+), 30 deletions(-) create mode 100644 libevmjit/Compiler.cpp.orig diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 6b0d5f2e1..928baee22 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -761,8 +761,8 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytesConstRef _bytecod _gasMeter.commitCostBlock(gas); // Require memory for in and out buffers - memory.require(outOff, outSize); // Out buffer first as we guess it will be after the in one - memory.require(inOff, inSize); + _memory.require(outOff, outSize); // Out buffer first as we guess it will be after the in one + _memory.require(inOff, inSize); auto receiveAddress = codeAddress; if (inst == Instruction::CALLCODE) diff --git a/libevmjit/Compiler.cpp.orig b/libevmjit/Compiler.cpp.orig new file mode 100644 index 000000000..9c6043ff2 --- /dev/null +++ b/libevmjit/Compiler.cpp.orig @@ -0,0 +1,924 @@ + +#include "Compiler.h" + +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#include "Type.h" +#include "Memory.h" +#include "Stack.h" +#include "Ext.h" +#include "GasMeter.h" +#include "Utils.h" +#include "Endianness.h" +#include "Arith256.h" +#include "Runtime.h" + +namespace dev +{ +namespace eth +{ +namespace jit +{ + +Compiler::Compiler(Options const& _options): + m_options(_options), + m_builder(llvm::getGlobalContext()) +{ + Type::init(m_builder.getContext()); +} + +void Compiler::createBasicBlocks(bytesConstRef _bytecode) +{ + std::set splitPoints; // Sorted collections of instruction indices where basic blocks start/end + + std::map directJumpTargets; + std::vector indirectJumpTargets; + boost::dynamic_bitset<> validJumpTargets(std::max(_bytecode.size(), size_t(1))); + + splitPoints.insert(0); // First basic block + validJumpTargets[0] = true; + + for (auto curr = _bytecode.begin(); curr != _bytecode.end(); ++curr) + { + ProgramCounter currentPC = curr - _bytecode.begin(); + validJumpTargets[currentPC] = true; + + auto inst = Instruction(*curr); + switch (inst) + { + + case Instruction::ANY_PUSH: + { + auto val = readPushData(curr, _bytecode.end()); + auto next = curr + 1; + if (next == _bytecode.end()) + break; + + auto nextInst = Instruction(*next); + if (nextInst == Instruction::JUMP || nextInst == Instruction::JUMPI) + { + // Create a block for the JUMP target. + ProgramCounter targetPC = val < _bytecode.size() ? val.convert_to() : _bytecode.size(); + splitPoints.insert(targetPC); + + ProgramCounter jumpPC = (next - _bytecode.begin()); + directJumpTargets[jumpPC] = targetPC; + } + break; + } + + case Instruction::JUMPDEST: + { + // A basic block starts at the next instruction. + if (currentPC + 1 < _bytecode.size()) + { + splitPoints.insert(currentPC + 1); + indirectJumpTargets.push_back(currentPC + 1); + } + break; + } + + case Instruction::JUMP: + case Instruction::JUMPI: + case Instruction::RETURN: + case Instruction::STOP: + case Instruction::SUICIDE: + { + // Create a basic block starting at the following instruction. + if (curr + 1 < _bytecode.end()) + { + splitPoints.insert(currentPC + 1); + } + break; + } + + default: + break; + } + } + + // Remove split points generated from jumps out of code or into data. + for (auto it = splitPoints.cbegin(); it != splitPoints.cend();) + { + if (*it > _bytecode.size() || !validJumpTargets[*it]) + it = splitPoints.erase(it); + else + ++it; + } + + for (auto it = splitPoints.cbegin(); it != splitPoints.cend();) + { + auto beginInstIdx = *it; + ++it; + auto endInstIdx = it != splitPoints.cend() ? *it : _bytecode.size(); + basicBlocks.emplace(std::piecewise_construct, std::forward_as_tuple(beginInstIdx), std::forward_as_tuple(beginInstIdx, endInstIdx, m_mainFunc, m_builder)); + } + + m_stopBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Stop", m_mainFunc); + m_badJumpBlock = std::unique_ptr(new BasicBlock("BadJumpBlock", m_mainFunc, m_builder)); + m_jumpTableBlock = std::unique_ptr(new BasicBlock("JumpTableBlock", m_mainFunc, m_builder)); + + for (auto it = directJumpTargets.cbegin(); it != directJumpTargets.cend(); ++it) + { + if (it->second >= _bytecode.size()) + { + // Jumping out of code means STOP + m_directJumpTargets[it->first] = m_stopBB; + continue; + } + + auto blockIter = basicBlocks.find(it->second); + if (blockIter != basicBlocks.end()) + { + m_directJumpTargets[it->first] = blockIter->second.llvm(); + } + else + { + clog(JIT) << "Bad JUMP at PC " << it->first + << ": " << it->second << " is not a valid PC"; + m_directJumpTargets[it->first] = m_badJumpBlock->llvm(); + } + } + + for (auto it = indirectJumpTargets.cbegin(); it != indirectJumpTargets.cend(); ++it) + m_indirectJumpTargets.push_back(&basicBlocks.find(*it)->second); +} + +std::unique_ptr Compiler::compile(bytesConstRef _bytecode) +{ + auto module = std::unique_ptr(new llvm::Module("main", m_builder.getContext())); + + // Create main function + llvm::Type* mainFuncArgTypes[] = {m_builder.getInt32Ty(), Type::RuntimePtr}; // There must be int in first place because LLVM does not support other signatures + auto mainFuncType = llvm::FunctionType::get(Type::MainReturn, mainFuncArgTypes, false); + m_mainFunc = llvm::Function::Create(mainFuncType, llvm::Function::ExternalLinkage, "main", module.get()); + m_mainFunc->arg_begin()->getNextNode()->setName("rt"); + + // Create the basic blocks. + auto entryBlock = llvm::BasicBlock::Create(m_builder.getContext(), "entry", m_mainFunc); + m_builder.SetInsertPoint(entryBlock); + + createBasicBlocks(_bytecode); + + // Init runtime structures. + RuntimeManager runtimeManager(m_builder); + GasMeter gasMeter(m_builder, runtimeManager); + Memory memory(runtimeManager, gasMeter); + Ext ext(runtimeManager); + Stack stack(m_builder, runtimeManager); + Arith256 arith(m_builder); + + m_builder.CreateBr(basicBlocks.begin()->second); + + for (auto basicBlockPairIt = basicBlocks.begin(); basicBlockPairIt != basicBlocks.end(); ++basicBlockPairIt) + { + auto& basicBlock = basicBlockPairIt->second; + auto iterCopy = basicBlockPairIt; + ++iterCopy; + auto nextBasicBlock = (iterCopy != basicBlocks.end()) ? iterCopy->second.llvm() : nullptr; + compileBasicBlock(basicBlock, _bytecode, runtimeManager, arith, memory, ext, gasMeter, nextBasicBlock); + } + + // Code for special blocks: + // TODO: move to separate function. + m_builder.SetInsertPoint(m_stopBB); + m_builder.CreateRet(Constant::get(ReturnCode::Stop)); + + m_builder.SetInsertPoint(m_badJumpBlock->llvm()); + m_builder.CreateRet(Constant::get(ReturnCode::BadJumpDestination)); + + m_builder.SetInsertPoint(m_jumpTableBlock->llvm()); + if (m_indirectJumpTargets.size() > 0) + { + auto dest = m_jumpTableBlock->localStack().pop(); + auto switchInstr = m_builder.CreateSwitch(dest, m_badJumpBlock->llvm(), + m_indirectJumpTargets.size()); + for (auto it = m_indirectJumpTargets.cbegin(); it != m_indirectJumpTargets.cend(); ++it) + { + auto& bb = *it; + auto dest = Constant::get(bb->begin()); + switchInstr->addCase(dest, bb->llvm()); + } + } + else + m_builder.CreateBr(m_badJumpBlock->llvm()); + + removeDeadBlocks(); + + dumpCFGifRequired("blocks-init.dot"); + + if (m_options.optimizeStack) + { + std::vector blockList; + for (auto& entry : basicBlocks) + blockList.push_back(&entry.second); + + if (m_jumpTableBlock) + blockList.push_back(m_jumpTableBlock.get()); + + BasicBlock::linkLocalStacks(blockList, m_builder); + + dumpCFGifRequired("blocks-opt.dot"); + } + + for (auto& entry : basicBlocks) + entry.second.localStack().synchronize(stack); + if (m_jumpTableBlock) + m_jumpTableBlock->localStack().synchronize(stack); + + dumpCFGifRequired("blocks-sync.dot"); + + if (m_jumpTableBlock && m_options.rewriteSwitchToBranches) + { + llvm::FunctionPassManager fpManager(module.get()); + fpManager.add(llvm::createLowerSwitchPass()); + fpManager.doInitialization(); + fpManager.run(*m_mainFunc); + } + + return module; +} + + +void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytesConstRef _bytecode, RuntimeManager& _runtimeManager, + Arith256& _arith, Memory& _memory, Ext& _ext, GasMeter& _gasMeter, llvm::BasicBlock* _nextBasicBlock) +{ + if (!_nextBasicBlock) // this is the last block in the code + _nextBasicBlock = m_stopBB; + + m_builder.SetInsertPoint(_basicBlock.llvm()); + auto& stack = _basicBlock.localStack(); + + for (auto currentPC = _basicBlock.begin(); currentPC != _basicBlock.end(); ++currentPC) + { + auto inst = static_cast(_bytecode[currentPC]); + + _gasMeter.count(inst); + + switch (inst) + { + + case Instruction::ADD: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto result = m_builder.CreateAdd(lhs, rhs); + stack.push(result); + break; + } + + case Instruction::SUB: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto result = m_builder.CreateSub(lhs, rhs); + stack.push(result); + break; + } + + case Instruction::MUL: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = _arith.mul(lhs, rhs); + stack.push(res); + break; + } + + case Instruction::DIV: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = _arith.div(lhs, rhs); + stack.push(res); + break; + } + + case Instruction::SDIV: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = _arith.sdiv(lhs, rhs); + stack.push(res); + break; + } + + case Instruction::MOD: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = _arith.mod(lhs, rhs); + stack.push(res); + break; + } + + case Instruction::SMOD: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = _arith.smod(lhs, rhs); + stack.push(res); + break; + } + + case Instruction::EXP: + { + auto left = stack.pop(); + auto right = stack.pop(); + auto ret = _ext.exp(left, right); + stack.push(ret); + break; + } + + case Instruction::BNOT: + { + auto value = stack.pop(); + auto ret = m_builder.CreateXor(value, Constant::get(-1), "bnot"); + stack.push(ret); + break; + } + + case Instruction::LT: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res1 = m_builder.CreateICmpULT(lhs, rhs); + auto res256 = m_builder.CreateZExt(res1, Type::i256); + stack.push(res256); + break; + } + + case Instruction::GT: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res1 = m_builder.CreateICmpUGT(lhs, rhs); + auto res256 = m_builder.CreateZExt(res1, Type::i256); + stack.push(res256); + break; + } + + case Instruction::SLT: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res1 = m_builder.CreateICmpSLT(lhs, rhs); + auto res256 = m_builder.CreateZExt(res1, Type::i256); + stack.push(res256); + break; + } + + case Instruction::SGT: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res1 = m_builder.CreateICmpSGT(lhs, rhs); + auto res256 = m_builder.CreateZExt(res1, Type::i256); + stack.push(res256); + break; + } + + case Instruction::EQ: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res1 = m_builder.CreateICmpEQ(lhs, rhs); + auto res256 = m_builder.CreateZExt(res1, Type::i256); + stack.push(res256); + break; + } + + case Instruction::NOT: + { + auto top = stack.pop(); + auto iszero = m_builder.CreateICmpEQ(top, Constant::get(0), "iszero"); + auto result = m_builder.CreateZExt(iszero, Type::i256); + stack.push(result); + break; + } + + case Instruction::AND: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = m_builder.CreateAnd(lhs, rhs); + stack.push(res); + break; + } + + case Instruction::OR: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = m_builder.CreateOr(lhs, rhs); + stack.push(res); + break; + } + + case Instruction::XOR: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto res = m_builder.CreateXor(lhs, rhs); + stack.push(res); + break; + } + + case Instruction::BYTE: + { + const auto byteNum = stack.pop(); + auto value = stack.pop(); + + // + 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"); + value = m_builder.CreateZExt(byte, Type::i256); + + auto byteNumValid = m_builder.CreateICmpULT(byteNum, Constant::get(32)); + value = m_builder.CreateSelect(byteNumValid, value, Constant::get(0)); + stack.push(value); + + break; + } + + case Instruction::ADDMOD: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto mod = stack.pop(); + auto res = _arith.addmod(lhs, rhs, mod); + stack.push(res); + break; + } + + case Instruction::MULMOD: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto mod = stack.pop(); + auto res = _arith.mulmod(lhs, rhs, mod); + stack.push(res); + break; + } + + case Instruction::SIGNEXTEND: + { + auto idx = stack.pop(); + auto word = stack.pop(); + + auto k32_ = m_builder.CreateTrunc(idx, m_builder.getIntNTy(5), "k_32"); + auto k32 = m_builder.CreateZExt(k32_, Type::i256); + auto k32x8 = m_builder.CreateMul(k32, Constant::get(8), "kx8"); + + // test for word >> (k * 8 + 7) + auto bitpos = m_builder.CreateAdd(k32x8, Constant::get(7), "bitpos"); + auto bitval = m_builder.CreateLShr(word, bitpos, "bitval"); + auto bittest = m_builder.CreateTrunc(bitval, m_builder.getInt1Ty(), "bittest"); + + auto mask_ = m_builder.CreateShl(Constant::get(1), bitpos); + auto mask = m_builder.CreateSub(mask_, Constant::get(1), "mask"); + + auto negmask = m_builder.CreateXor(mask, llvm::ConstantInt::getAllOnesValue(Type::i256), "negmask"); + auto val1 = m_builder.CreateOr(word, negmask); + auto val0 = m_builder.CreateAnd(word, mask); + + auto kInRange = m_builder.CreateICmpULE(idx, llvm::ConstantInt::get(Type::i256, 30)); + auto result = m_builder.CreateSelect(kInRange, + m_builder.CreateSelect(bittest, val1, val0), + word); + stack.push(result); + + break; + } + + case Instruction::SHA3: + { + auto inOff = stack.pop(); + auto inSize = stack.pop(); + _memory.require(inOff, inSize); + auto hash = _ext.sha3(inOff, inSize); + stack.push(hash); + break; + } + + case Instruction::POP: + { + stack.pop(); + break; + } + + case Instruction::ANY_PUSH: + { + auto curr = _bytecode.begin() + currentPC; // TODO: replace currentPC with iterator + auto value = readPushData(curr, _bytecode.end()); + currentPC = curr - _bytecode.begin(); + + stack.push(Constant::get(value)); + break; + } + + case Instruction::ANY_DUP: + { + auto index = static_cast(inst) - static_cast(Instruction::DUP1); + stack.dup(index); + break; + } + + case Instruction::ANY_SWAP: + { + auto index = static_cast(inst) - static_cast(Instruction::SWAP1) + 1; + stack.swap(index); + break; + } + + case Instruction::MLOAD: + { + auto addr = stack.pop(); + auto word = _memory.loadWord(addr); + stack.push(word); + break; + } + + case Instruction::MSTORE: + { + auto addr = stack.pop(); + auto word = stack.pop(); + _memory.storeWord(addr, word); + break; + } + + case Instruction::MSTORE8: + { + auto addr = stack.pop(); + auto word = stack.pop(); + _memory.storeByte(addr, word); + break; + } + + case Instruction::MSIZE: + { + auto word = _memory.getSize(); + stack.push(word); + break; + } + + case Instruction::SLOAD: + { + auto index = stack.pop(); + auto value = _ext.store(index); + stack.push(value); + break; + } + + case Instruction::SSTORE: + { + auto index = stack.pop(); + auto value = stack.pop(); + _gasMeter.countSStore(_ext, index, value); + _ext.setStore(index, value); + break; + } + + case Instruction::JUMP: + case Instruction::JUMPI: + { + // Generate direct jump iff: + // 1. this is not the first instruction in the block + // 2. m_directJumpTargets[currentPC] is defined (meaning that the previous instruction is a PUSH) + // Otherwise generate a indirect jump (a switch). + llvm::BasicBlock* targetBlock = nullptr; + if (currentPC != _basicBlock.begin()) + { + auto pairIter = m_directJumpTargets.find(currentPC); + if (pairIter != m_directJumpTargets.end()) + targetBlock = pairIter->second; + } + + if (inst == Instruction::JUMP) + { + if (targetBlock) + { + // The target address is computed at compile time, + // just pop it without looking... + stack.pop(); + m_builder.CreateBr(targetBlock); + } + else + m_builder.CreateBr(m_jumpTableBlock->llvm()); + } + else // JUMPI + { + stack.swap(1); + auto val = stack.pop(); + auto zero = Constant::get(0); + auto cond = m_builder.CreateICmpNE(val, zero, "nonzero"); + + if (targetBlock) + { + stack.pop(); + m_builder.CreateCondBr(cond, targetBlock, _nextBasicBlock); + } + else + m_builder.CreateCondBr(cond, m_jumpTableBlock->llvm(), _nextBasicBlock); + } + + break; + } + + case Instruction::JUMPDEST: + { + // Nothing to do + break; + } + + case Instruction::PC: + { + auto value = Constant::get(currentPC); + stack.push(value); + break; + } + + case Instruction::GAS: + case Instruction::ADDRESS: + case Instruction::CALLER: + case Instruction::ORIGIN: + case Instruction::CALLVALUE: + case Instruction::CALLDATASIZE: + case Instruction::CODESIZE: + case Instruction::GASPRICE: + case Instruction::PREVHASH: + case Instruction::COINBASE: + case Instruction::TIMESTAMP: + case Instruction::NUMBER: + case Instruction::DIFFICULTY: + case Instruction::GASLIMIT: + { + // Pushes an element of runtime data on stack + stack.push(_runtimeManager.get(inst)); + break; + } + + case Instruction::BALANCE: + { + auto address = stack.pop(); + auto value = _ext.balance(address); + stack.push(value); + break; + } + + case Instruction::EXTCODESIZE: + { + auto addr = stack.pop(); + auto value = _ext.codesizeAt(addr); + stack.push(value); + break; + } + + case Instruction::CALLDATACOPY: + { + auto destMemIdx = stack.pop(); + auto srcIdx = stack.pop(); + auto reqBytes = stack.pop(); + + auto srcPtr = _runtimeManager.getCallData(); + auto srcSize = _runtimeManager.get(RuntimeData::CallDataSize); + + _memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); + break; + } + + case Instruction::CODECOPY: + { + auto destMemIdx = stack.pop(); + auto srcIdx = stack.pop(); + auto reqBytes = stack.pop(); + + auto srcPtr = _runtimeManager.getCode(); // TODO: Code & its size are constants, feature #80814234 + auto srcSize = _runtimeManager.get(RuntimeData::CodeSize); + + _memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); + break; + } + + case Instruction::EXTCODECOPY: + { + auto extAddr = stack.pop(); + auto destMemIdx = stack.pop(); + auto srcIdx = stack.pop(); + auto reqBytes = stack.pop(); + + auto srcPtr = _ext.codeAt(extAddr); + auto srcSize = _ext.codesizeAt(extAddr); + + _memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); + break; + } + + case Instruction::CALLDATALOAD: + { + auto index = stack.pop(); + auto value = _ext.calldataload(index); + stack.push(value); + break; + } + + case Instruction::CREATE: + { + auto endowment = stack.pop(); + auto initOff = stack.pop(); + auto initSize = stack.pop(); + _memory.require(initOff, initSize); + + auto address = _ext.create(endowment, initOff, initSize); + stack.push(address); + break; + } + + case Instruction::CALL: + case Instruction::CALLCODE: + { + auto gas = stack.pop(); + auto codeAddress = stack.pop(); + auto value = stack.pop(); + auto inOff = stack.pop(); + auto inSize = stack.pop(); + auto outOff = stack.pop(); + auto outSize = stack.pop(); + + _gasMeter.commitCostBlock(gas); + +<<<<<<< HEAD + // Require _memory for the max of in and out buffers + auto inSizeReq = m_builder.CreateAdd(inOff, inSize, "inSizeReq"); + auto outSizeReq = m_builder.CreateAdd(outOff, outSize, "outSizeReq"); + auto cmp = m_builder.CreateICmpUGT(inSizeReq, outSizeReq); + auto sizeReq = m_builder.CreateSelect(cmp, inSizeReq, outSizeReq, "sizeReq"); + _memory.require(sizeReq); +======= + // Require memory for in and out buffers + memory.require(outOff, outSize); // Out buffer first as we guess it will be after the in one + memory.require(inOff, inSize); +>>>>>>> ec07859aedd18ebfd9b40cfa2a182e49c5b3f30a + + auto receiveAddress = codeAddress; + if (inst == Instruction::CALLCODE) + receiveAddress = _runtimeManager.get(RuntimeData::Address); + + auto ret = _ext.call(gas, receiveAddress, value, inOff, inSize, outOff, outSize, codeAddress); + _gasMeter.giveBack(gas); + stack.push(ret); + break; + } + + case Instruction::RETURN: + { + auto index = stack.pop(); + auto size = stack.pop(); + + _memory.require(index, size); + _runtimeManager.registerReturnData(index, size); + + m_builder.CreateRet(Constant::get(ReturnCode::Return)); + break; + } + + case Instruction::SUICIDE: + case Instruction::STOP: + { + if (inst == Instruction::SUICIDE) + { + auto address = stack.pop(); + _ext.suicide(address); + } + + m_builder.CreateRet(Constant::get(ReturnCode::Stop)); + break; + } + + default: // Invalid instruction - runtime exception + { + _runtimeManager.raiseException(ReturnCode::BadInstruction); + } + + } + } + + _gasMeter.commitCostBlock(); + + // Block may have no terminator if the next instruction is a jump destination. + if (!_basicBlock.llvm()->getTerminator()) + m_builder.CreateBr(_nextBasicBlock); +} + + + +void Compiler::removeDeadBlocks() +{ + // Remove dead basic blocks + auto sthErased = false; + do + { + sthErased = false; + for (auto it = basicBlocks.begin(); it != basicBlocks.end();) + { + auto llvmBB = it->second.llvm(); + if (llvm::pred_begin(llvmBB) == llvm::pred_end(llvmBB)) + { + llvmBB->eraseFromParent(); + basicBlocks.erase(it++); + sthErased = true; + } + else + ++it; + } + } + while (sthErased); + + // Remove jump table block if no predecessors + if (llvm::pred_begin(m_jumpTableBlock->llvm()) == llvm::pred_end(m_jumpTableBlock->llvm())) + { + m_jumpTableBlock->llvm()->eraseFromParent(); + m_jumpTableBlock.reset(); + } +} + +void Compiler::dumpCFGifRequired(std::string const& _dotfilePath) +{ + if (! m_options.dumpCFG) + return; + + // TODO: handle i/o failures + std::ofstream ofs(_dotfilePath); + dumpCFGtoStream(ofs); + ofs.close(); +} + +void Compiler::dumpCFGtoStream(std::ostream& _out) +{ + _out << "digraph BB {\n" + << " node [shape=record, fontname=Courier, fontsize=10];\n" + << " entry [share=record, label=\"entry block\"];\n"; + + std::vector blocks; + for (auto& pair : basicBlocks) + blocks.push_back(&pair.second); + if (m_jumpTableBlock) + blocks.push_back(m_jumpTableBlock.get()); + if (m_badJumpBlock) + blocks.push_back(m_badJumpBlock.get()); + + // std::map phiNodesPerBlock; + + // Output nodes + for (auto bb : blocks) + { + std::string blockName = bb->llvm()->getName(); + + std::ostringstream oss; + bb->dump(oss, true); + + _out << " \"" << blockName << "\" [shape=record, label=\" { " << blockName << "|" << oss.str() << "} \"];\n"; + } + + // Output edges + for (auto bb : blocks) + { + std::string blockName = bb->llvm()->getName(); + + auto end = llvm::pred_end(bb->llvm()); + for (llvm::pred_iterator it = llvm::pred_begin(bb->llvm()); it != end; ++it) + { + _out << " \"" << (*it)->getName().str() << "\" -> \"" << blockName << "\" [" + << ((m_jumpTableBlock.get() && *it == m_jumpTableBlock.get()->llvm()) ? "style = dashed, " : "") + << "];\n"; + } + } + + _out << "}\n"; +} + +void Compiler::dump() +{ + for (auto& entry : basicBlocks) + entry.second.dump(); + if (m_jumpTableBlock != nullptr) + m_jumpTableBlock->dump(); +} + +} +} +} + diff --git a/libevmjit/Compiler.h b/libevmjit/Compiler.h index d58745a06..12b7f6e0e 100644 --- a/libevmjit/Compiler.h +++ b/libevmjit/Compiler.h @@ -18,55 +18,70 @@ class Compiler { public: - using ProgramCounter = uint64_t; + struct Options + { + /// Optimize stack operations between basic blocks + bool optimizeStack; + + /// Rewrite switch instructions to sequences of branches + bool rewriteSwitchToBranches; - Compiler(); + /// Dump CFG as a .dot file for graphviz + bool dumpCFG; - std::unique_ptr compile(bytesConstRef bytecode); + Options(): + optimizeStack(true), + rewriteSwitchToBranches(true), + dumpCFG(false) + {} + }; + + using ProgramCounter = uint64_t; - void dumpBasicBlockGraph(std::ostream& out); + Compiler(Options const& _options); + std::unique_ptr compile(bytesConstRef _bytecode); private: - void createBasicBlocks(bytesConstRef bytecode); + void createBasicBlocks(bytesConstRef _bytecode); - void compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, class RuntimeManager& _runtimeManager, class Arith256& arith, class Memory& memory, class Ext& ext, class GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock); + void compileBasicBlock(BasicBlock& _basicBlock, bytesConstRef _bytecode, class RuntimeManager& _runtimeManager, class Arith256& _arith, class Memory& _memory, class Ext& _ext, class GasMeter& _gasMeter, llvm::BasicBlock* _nextBasicBlock); void removeDeadBlocks(); - /// Dump all basic blocks to stderr. Useful in a debugging session. + /// Dumps basic block graph in graphviz format to a file, if option dumpCFG is enabled. + void dumpCFGifRequired(std::string const& _dotfilePath); + + /// Dumps basic block graph in graphviz format to a stream. + void dumpCFGtoStream(std::ostream& _out); + + /// Dumps all basic blocks to stderr. Useful in a debugging session. void dump(); + /// Compiler options + Options const& m_options; + + /// Helper class for generating IR llvm::IRBuilder<> m_builder; - /** - * Maps a program counter pc to a basic block that starts at pc (if any). - */ - std::map basicBlocks; + /// Maps a program counter pc to a basic block that starts at pc (if any). + std::map basicBlocks = {}; - /** - * Maps a pc at which there is a JUMP or JUMPI to the target block of the jump. - */ - std::map m_directJumpTargets; + /// Maps a pc at which there is a JUMP or JUMPI to the target block of the jump. + std::map m_directJumpTargets = {}; - /** - * A list of possible blocks to which there may be indirect jumps. - */ - std::vector m_indirectJumpTargets; + /// A list of possible blocks to which there may be indirect jumps. + std::vector m_indirectJumpTargets = {}; /// Stop basic block - terminates execution with STOP code (0) llvm::BasicBlock* m_stopBB = nullptr; - /** - * Block with a jump table. - */ - std::unique_ptr m_jumpTableBlock; + /// Block with a jump table. + std::unique_ptr m_jumpTableBlock = nullptr; - /** - * Default destination for indirect jumps. - */ - std::unique_ptr m_badJumpBlock; + /// Default destination for indirect jumps. + std::unique_ptr m_badJumpBlock = nullptr; /// Main program function llvm::Function* m_mainFunc = nullptr; diff --git a/libevmjit/VM.cpp b/libevmjit/VM.cpp index b42b09499..f60dbe783 100644 --- a/libevmjit/VM.cpp +++ b/libevmjit/VM.cpp @@ -16,7 +16,8 @@ namespace jit bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const&, uint64_t) { - auto module = Compiler().compile(_ext.code); + Compiler::Options defaultOptions; + auto module = Compiler(defaultOptions).compile(_ext.code); ExecutionEngine engine; auto exitCode = engine.run(std::move(module), m_gas, &_ext); From 11d78d44b13c34c8121cd5e9e48052cca24944cf Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Fri, 31 Oct 2014 15:46:44 +0000 Subject: [PATCH 311/641] removed *.orig file --- libevmjit/Compiler.cpp.orig | 924 ------------------------------------ 1 file changed, 924 deletions(-) delete mode 100644 libevmjit/Compiler.cpp.orig diff --git a/libevmjit/Compiler.cpp.orig b/libevmjit/Compiler.cpp.orig deleted file mode 100644 index 9c6043ff2..000000000 --- a/libevmjit/Compiler.cpp.orig +++ /dev/null @@ -1,924 +0,0 @@ - -#include "Compiler.h" - -#include - -#include - -#include -#include -#include -#include - -#include -#include - -#include - -#include "Type.h" -#include "Memory.h" -#include "Stack.h" -#include "Ext.h" -#include "GasMeter.h" -#include "Utils.h" -#include "Endianness.h" -#include "Arith256.h" -#include "Runtime.h" - -namespace dev -{ -namespace eth -{ -namespace jit -{ - -Compiler::Compiler(Options const& _options): - m_options(_options), - m_builder(llvm::getGlobalContext()) -{ - Type::init(m_builder.getContext()); -} - -void Compiler::createBasicBlocks(bytesConstRef _bytecode) -{ - std::set splitPoints; // Sorted collections of instruction indices where basic blocks start/end - - std::map directJumpTargets; - std::vector indirectJumpTargets; - boost::dynamic_bitset<> validJumpTargets(std::max(_bytecode.size(), size_t(1))); - - splitPoints.insert(0); // First basic block - validJumpTargets[0] = true; - - for (auto curr = _bytecode.begin(); curr != _bytecode.end(); ++curr) - { - ProgramCounter currentPC = curr - _bytecode.begin(); - validJumpTargets[currentPC] = true; - - auto inst = Instruction(*curr); - switch (inst) - { - - case Instruction::ANY_PUSH: - { - auto val = readPushData(curr, _bytecode.end()); - auto next = curr + 1; - if (next == _bytecode.end()) - break; - - auto nextInst = Instruction(*next); - if (nextInst == Instruction::JUMP || nextInst == Instruction::JUMPI) - { - // Create a block for the JUMP target. - ProgramCounter targetPC = val < _bytecode.size() ? val.convert_to() : _bytecode.size(); - splitPoints.insert(targetPC); - - ProgramCounter jumpPC = (next - _bytecode.begin()); - directJumpTargets[jumpPC] = targetPC; - } - break; - } - - case Instruction::JUMPDEST: - { - // A basic block starts at the next instruction. - if (currentPC + 1 < _bytecode.size()) - { - splitPoints.insert(currentPC + 1); - indirectJumpTargets.push_back(currentPC + 1); - } - break; - } - - case Instruction::JUMP: - case Instruction::JUMPI: - case Instruction::RETURN: - case Instruction::STOP: - case Instruction::SUICIDE: - { - // Create a basic block starting at the following instruction. - if (curr + 1 < _bytecode.end()) - { - splitPoints.insert(currentPC + 1); - } - break; - } - - default: - break; - } - } - - // Remove split points generated from jumps out of code or into data. - for (auto it = splitPoints.cbegin(); it != splitPoints.cend();) - { - if (*it > _bytecode.size() || !validJumpTargets[*it]) - it = splitPoints.erase(it); - else - ++it; - } - - for (auto it = splitPoints.cbegin(); it != splitPoints.cend();) - { - auto beginInstIdx = *it; - ++it; - auto endInstIdx = it != splitPoints.cend() ? *it : _bytecode.size(); - basicBlocks.emplace(std::piecewise_construct, std::forward_as_tuple(beginInstIdx), std::forward_as_tuple(beginInstIdx, endInstIdx, m_mainFunc, m_builder)); - } - - m_stopBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Stop", m_mainFunc); - m_badJumpBlock = std::unique_ptr(new BasicBlock("BadJumpBlock", m_mainFunc, m_builder)); - m_jumpTableBlock = std::unique_ptr(new BasicBlock("JumpTableBlock", m_mainFunc, m_builder)); - - for (auto it = directJumpTargets.cbegin(); it != directJumpTargets.cend(); ++it) - { - if (it->second >= _bytecode.size()) - { - // Jumping out of code means STOP - m_directJumpTargets[it->first] = m_stopBB; - continue; - } - - auto blockIter = basicBlocks.find(it->second); - if (blockIter != basicBlocks.end()) - { - m_directJumpTargets[it->first] = blockIter->second.llvm(); - } - else - { - clog(JIT) << "Bad JUMP at PC " << it->first - << ": " << it->second << " is not a valid PC"; - m_directJumpTargets[it->first] = m_badJumpBlock->llvm(); - } - } - - for (auto it = indirectJumpTargets.cbegin(); it != indirectJumpTargets.cend(); ++it) - m_indirectJumpTargets.push_back(&basicBlocks.find(*it)->second); -} - -std::unique_ptr Compiler::compile(bytesConstRef _bytecode) -{ - auto module = std::unique_ptr(new llvm::Module("main", m_builder.getContext())); - - // Create main function - llvm::Type* mainFuncArgTypes[] = {m_builder.getInt32Ty(), Type::RuntimePtr}; // There must be int in first place because LLVM does not support other signatures - auto mainFuncType = llvm::FunctionType::get(Type::MainReturn, mainFuncArgTypes, false); - m_mainFunc = llvm::Function::Create(mainFuncType, llvm::Function::ExternalLinkage, "main", module.get()); - m_mainFunc->arg_begin()->getNextNode()->setName("rt"); - - // Create the basic blocks. - auto entryBlock = llvm::BasicBlock::Create(m_builder.getContext(), "entry", m_mainFunc); - m_builder.SetInsertPoint(entryBlock); - - createBasicBlocks(_bytecode); - - // Init runtime structures. - RuntimeManager runtimeManager(m_builder); - GasMeter gasMeter(m_builder, runtimeManager); - Memory memory(runtimeManager, gasMeter); - Ext ext(runtimeManager); - Stack stack(m_builder, runtimeManager); - Arith256 arith(m_builder); - - m_builder.CreateBr(basicBlocks.begin()->second); - - for (auto basicBlockPairIt = basicBlocks.begin(); basicBlockPairIt != basicBlocks.end(); ++basicBlockPairIt) - { - auto& basicBlock = basicBlockPairIt->second; - auto iterCopy = basicBlockPairIt; - ++iterCopy; - auto nextBasicBlock = (iterCopy != basicBlocks.end()) ? iterCopy->second.llvm() : nullptr; - compileBasicBlock(basicBlock, _bytecode, runtimeManager, arith, memory, ext, gasMeter, nextBasicBlock); - } - - // Code for special blocks: - // TODO: move to separate function. - m_builder.SetInsertPoint(m_stopBB); - m_builder.CreateRet(Constant::get(ReturnCode::Stop)); - - m_builder.SetInsertPoint(m_badJumpBlock->llvm()); - m_builder.CreateRet(Constant::get(ReturnCode::BadJumpDestination)); - - m_builder.SetInsertPoint(m_jumpTableBlock->llvm()); - if (m_indirectJumpTargets.size() > 0) - { - auto dest = m_jumpTableBlock->localStack().pop(); - auto switchInstr = m_builder.CreateSwitch(dest, m_badJumpBlock->llvm(), - m_indirectJumpTargets.size()); - for (auto it = m_indirectJumpTargets.cbegin(); it != m_indirectJumpTargets.cend(); ++it) - { - auto& bb = *it; - auto dest = Constant::get(bb->begin()); - switchInstr->addCase(dest, bb->llvm()); - } - } - else - m_builder.CreateBr(m_badJumpBlock->llvm()); - - removeDeadBlocks(); - - dumpCFGifRequired("blocks-init.dot"); - - if (m_options.optimizeStack) - { - std::vector blockList; - for (auto& entry : basicBlocks) - blockList.push_back(&entry.second); - - if (m_jumpTableBlock) - blockList.push_back(m_jumpTableBlock.get()); - - BasicBlock::linkLocalStacks(blockList, m_builder); - - dumpCFGifRequired("blocks-opt.dot"); - } - - for (auto& entry : basicBlocks) - entry.second.localStack().synchronize(stack); - if (m_jumpTableBlock) - m_jumpTableBlock->localStack().synchronize(stack); - - dumpCFGifRequired("blocks-sync.dot"); - - if (m_jumpTableBlock && m_options.rewriteSwitchToBranches) - { - llvm::FunctionPassManager fpManager(module.get()); - fpManager.add(llvm::createLowerSwitchPass()); - fpManager.doInitialization(); - fpManager.run(*m_mainFunc); - } - - return module; -} - - -void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytesConstRef _bytecode, RuntimeManager& _runtimeManager, - Arith256& _arith, Memory& _memory, Ext& _ext, GasMeter& _gasMeter, llvm::BasicBlock* _nextBasicBlock) -{ - if (!_nextBasicBlock) // this is the last block in the code - _nextBasicBlock = m_stopBB; - - m_builder.SetInsertPoint(_basicBlock.llvm()); - auto& stack = _basicBlock.localStack(); - - for (auto currentPC = _basicBlock.begin(); currentPC != _basicBlock.end(); ++currentPC) - { - auto inst = static_cast(_bytecode[currentPC]); - - _gasMeter.count(inst); - - switch (inst) - { - - case Instruction::ADD: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto result = m_builder.CreateAdd(lhs, rhs); - stack.push(result); - break; - } - - case Instruction::SUB: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto result = m_builder.CreateSub(lhs, rhs); - stack.push(result); - break; - } - - case Instruction::MUL: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = _arith.mul(lhs, rhs); - stack.push(res); - break; - } - - case Instruction::DIV: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = _arith.div(lhs, rhs); - stack.push(res); - break; - } - - case Instruction::SDIV: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = _arith.sdiv(lhs, rhs); - stack.push(res); - break; - } - - case Instruction::MOD: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = _arith.mod(lhs, rhs); - stack.push(res); - break; - } - - case Instruction::SMOD: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = _arith.smod(lhs, rhs); - stack.push(res); - break; - } - - case Instruction::EXP: - { - auto left = stack.pop(); - auto right = stack.pop(); - auto ret = _ext.exp(left, right); - stack.push(ret); - break; - } - - case Instruction::BNOT: - { - auto value = stack.pop(); - auto ret = m_builder.CreateXor(value, Constant::get(-1), "bnot"); - stack.push(ret); - break; - } - - case Instruction::LT: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res1 = m_builder.CreateICmpULT(lhs, rhs); - auto res256 = m_builder.CreateZExt(res1, Type::i256); - stack.push(res256); - break; - } - - case Instruction::GT: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res1 = m_builder.CreateICmpUGT(lhs, rhs); - auto res256 = m_builder.CreateZExt(res1, Type::i256); - stack.push(res256); - break; - } - - case Instruction::SLT: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res1 = m_builder.CreateICmpSLT(lhs, rhs); - auto res256 = m_builder.CreateZExt(res1, Type::i256); - stack.push(res256); - break; - } - - case Instruction::SGT: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res1 = m_builder.CreateICmpSGT(lhs, rhs); - auto res256 = m_builder.CreateZExt(res1, Type::i256); - stack.push(res256); - break; - } - - case Instruction::EQ: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res1 = m_builder.CreateICmpEQ(lhs, rhs); - auto res256 = m_builder.CreateZExt(res1, Type::i256); - stack.push(res256); - break; - } - - case Instruction::NOT: - { - auto top = stack.pop(); - auto iszero = m_builder.CreateICmpEQ(top, Constant::get(0), "iszero"); - auto result = m_builder.CreateZExt(iszero, Type::i256); - stack.push(result); - break; - } - - case Instruction::AND: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = m_builder.CreateAnd(lhs, rhs); - stack.push(res); - break; - } - - case Instruction::OR: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = m_builder.CreateOr(lhs, rhs); - stack.push(res); - break; - } - - case Instruction::XOR: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = m_builder.CreateXor(lhs, rhs); - stack.push(res); - break; - } - - case Instruction::BYTE: - { - const auto byteNum = stack.pop(); - auto value = stack.pop(); - - // - 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"); - value = m_builder.CreateZExt(byte, Type::i256); - - auto byteNumValid = m_builder.CreateICmpULT(byteNum, Constant::get(32)); - value = m_builder.CreateSelect(byteNumValid, value, Constant::get(0)); - stack.push(value); - - break; - } - - case Instruction::ADDMOD: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto mod = stack.pop(); - auto res = _arith.addmod(lhs, rhs, mod); - stack.push(res); - break; - } - - case Instruction::MULMOD: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto mod = stack.pop(); - auto res = _arith.mulmod(lhs, rhs, mod); - stack.push(res); - break; - } - - case Instruction::SIGNEXTEND: - { - auto idx = stack.pop(); - auto word = stack.pop(); - - auto k32_ = m_builder.CreateTrunc(idx, m_builder.getIntNTy(5), "k_32"); - auto k32 = m_builder.CreateZExt(k32_, Type::i256); - auto k32x8 = m_builder.CreateMul(k32, Constant::get(8), "kx8"); - - // test for word >> (k * 8 + 7) - auto bitpos = m_builder.CreateAdd(k32x8, Constant::get(7), "bitpos"); - auto bitval = m_builder.CreateLShr(word, bitpos, "bitval"); - auto bittest = m_builder.CreateTrunc(bitval, m_builder.getInt1Ty(), "bittest"); - - auto mask_ = m_builder.CreateShl(Constant::get(1), bitpos); - auto mask = m_builder.CreateSub(mask_, Constant::get(1), "mask"); - - auto negmask = m_builder.CreateXor(mask, llvm::ConstantInt::getAllOnesValue(Type::i256), "negmask"); - auto val1 = m_builder.CreateOr(word, negmask); - auto val0 = m_builder.CreateAnd(word, mask); - - auto kInRange = m_builder.CreateICmpULE(idx, llvm::ConstantInt::get(Type::i256, 30)); - auto result = m_builder.CreateSelect(kInRange, - m_builder.CreateSelect(bittest, val1, val0), - word); - stack.push(result); - - break; - } - - case Instruction::SHA3: - { - auto inOff = stack.pop(); - auto inSize = stack.pop(); - _memory.require(inOff, inSize); - auto hash = _ext.sha3(inOff, inSize); - stack.push(hash); - break; - } - - case Instruction::POP: - { - stack.pop(); - break; - } - - case Instruction::ANY_PUSH: - { - auto curr = _bytecode.begin() + currentPC; // TODO: replace currentPC with iterator - auto value = readPushData(curr, _bytecode.end()); - currentPC = curr - _bytecode.begin(); - - stack.push(Constant::get(value)); - break; - } - - case Instruction::ANY_DUP: - { - auto index = static_cast(inst) - static_cast(Instruction::DUP1); - stack.dup(index); - break; - } - - case Instruction::ANY_SWAP: - { - auto index = static_cast(inst) - static_cast(Instruction::SWAP1) + 1; - stack.swap(index); - break; - } - - case Instruction::MLOAD: - { - auto addr = stack.pop(); - auto word = _memory.loadWord(addr); - stack.push(word); - break; - } - - case Instruction::MSTORE: - { - auto addr = stack.pop(); - auto word = stack.pop(); - _memory.storeWord(addr, word); - break; - } - - case Instruction::MSTORE8: - { - auto addr = stack.pop(); - auto word = stack.pop(); - _memory.storeByte(addr, word); - break; - } - - case Instruction::MSIZE: - { - auto word = _memory.getSize(); - stack.push(word); - break; - } - - case Instruction::SLOAD: - { - auto index = stack.pop(); - auto value = _ext.store(index); - stack.push(value); - break; - } - - case Instruction::SSTORE: - { - auto index = stack.pop(); - auto value = stack.pop(); - _gasMeter.countSStore(_ext, index, value); - _ext.setStore(index, value); - break; - } - - case Instruction::JUMP: - case Instruction::JUMPI: - { - // Generate direct jump iff: - // 1. this is not the first instruction in the block - // 2. m_directJumpTargets[currentPC] is defined (meaning that the previous instruction is a PUSH) - // Otherwise generate a indirect jump (a switch). - llvm::BasicBlock* targetBlock = nullptr; - if (currentPC != _basicBlock.begin()) - { - auto pairIter = m_directJumpTargets.find(currentPC); - if (pairIter != m_directJumpTargets.end()) - targetBlock = pairIter->second; - } - - if (inst == Instruction::JUMP) - { - if (targetBlock) - { - // The target address is computed at compile time, - // just pop it without looking... - stack.pop(); - m_builder.CreateBr(targetBlock); - } - else - m_builder.CreateBr(m_jumpTableBlock->llvm()); - } - else // JUMPI - { - stack.swap(1); - auto val = stack.pop(); - auto zero = Constant::get(0); - auto cond = m_builder.CreateICmpNE(val, zero, "nonzero"); - - if (targetBlock) - { - stack.pop(); - m_builder.CreateCondBr(cond, targetBlock, _nextBasicBlock); - } - else - m_builder.CreateCondBr(cond, m_jumpTableBlock->llvm(), _nextBasicBlock); - } - - break; - } - - case Instruction::JUMPDEST: - { - // Nothing to do - break; - } - - case Instruction::PC: - { - auto value = Constant::get(currentPC); - stack.push(value); - break; - } - - case Instruction::GAS: - case Instruction::ADDRESS: - case Instruction::CALLER: - case Instruction::ORIGIN: - case Instruction::CALLVALUE: - case Instruction::CALLDATASIZE: - case Instruction::CODESIZE: - case Instruction::GASPRICE: - case Instruction::PREVHASH: - case Instruction::COINBASE: - case Instruction::TIMESTAMP: - case Instruction::NUMBER: - case Instruction::DIFFICULTY: - case Instruction::GASLIMIT: - { - // Pushes an element of runtime data on stack - stack.push(_runtimeManager.get(inst)); - break; - } - - case Instruction::BALANCE: - { - auto address = stack.pop(); - auto value = _ext.balance(address); - stack.push(value); - break; - } - - case Instruction::EXTCODESIZE: - { - auto addr = stack.pop(); - auto value = _ext.codesizeAt(addr); - stack.push(value); - break; - } - - case Instruction::CALLDATACOPY: - { - auto destMemIdx = stack.pop(); - auto srcIdx = stack.pop(); - auto reqBytes = stack.pop(); - - auto srcPtr = _runtimeManager.getCallData(); - auto srcSize = _runtimeManager.get(RuntimeData::CallDataSize); - - _memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); - break; - } - - case Instruction::CODECOPY: - { - auto destMemIdx = stack.pop(); - auto srcIdx = stack.pop(); - auto reqBytes = stack.pop(); - - auto srcPtr = _runtimeManager.getCode(); // TODO: Code & its size are constants, feature #80814234 - auto srcSize = _runtimeManager.get(RuntimeData::CodeSize); - - _memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); - break; - } - - case Instruction::EXTCODECOPY: - { - auto extAddr = stack.pop(); - auto destMemIdx = stack.pop(); - auto srcIdx = stack.pop(); - auto reqBytes = stack.pop(); - - auto srcPtr = _ext.codeAt(extAddr); - auto srcSize = _ext.codesizeAt(extAddr); - - _memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); - break; - } - - case Instruction::CALLDATALOAD: - { - auto index = stack.pop(); - auto value = _ext.calldataload(index); - stack.push(value); - break; - } - - case Instruction::CREATE: - { - auto endowment = stack.pop(); - auto initOff = stack.pop(); - auto initSize = stack.pop(); - _memory.require(initOff, initSize); - - auto address = _ext.create(endowment, initOff, initSize); - stack.push(address); - break; - } - - case Instruction::CALL: - case Instruction::CALLCODE: - { - auto gas = stack.pop(); - auto codeAddress = stack.pop(); - auto value = stack.pop(); - auto inOff = stack.pop(); - auto inSize = stack.pop(); - auto outOff = stack.pop(); - auto outSize = stack.pop(); - - _gasMeter.commitCostBlock(gas); - -<<<<<<< HEAD - // Require _memory for the max of in and out buffers - auto inSizeReq = m_builder.CreateAdd(inOff, inSize, "inSizeReq"); - auto outSizeReq = m_builder.CreateAdd(outOff, outSize, "outSizeReq"); - auto cmp = m_builder.CreateICmpUGT(inSizeReq, outSizeReq); - auto sizeReq = m_builder.CreateSelect(cmp, inSizeReq, outSizeReq, "sizeReq"); - _memory.require(sizeReq); -======= - // Require memory for in and out buffers - memory.require(outOff, outSize); // Out buffer first as we guess it will be after the in one - memory.require(inOff, inSize); ->>>>>>> ec07859aedd18ebfd9b40cfa2a182e49c5b3f30a - - auto receiveAddress = codeAddress; - if (inst == Instruction::CALLCODE) - receiveAddress = _runtimeManager.get(RuntimeData::Address); - - auto ret = _ext.call(gas, receiveAddress, value, inOff, inSize, outOff, outSize, codeAddress); - _gasMeter.giveBack(gas); - stack.push(ret); - break; - } - - case Instruction::RETURN: - { - auto index = stack.pop(); - auto size = stack.pop(); - - _memory.require(index, size); - _runtimeManager.registerReturnData(index, size); - - m_builder.CreateRet(Constant::get(ReturnCode::Return)); - break; - } - - case Instruction::SUICIDE: - case Instruction::STOP: - { - if (inst == Instruction::SUICIDE) - { - auto address = stack.pop(); - _ext.suicide(address); - } - - m_builder.CreateRet(Constant::get(ReturnCode::Stop)); - break; - } - - default: // Invalid instruction - runtime exception - { - _runtimeManager.raiseException(ReturnCode::BadInstruction); - } - - } - } - - _gasMeter.commitCostBlock(); - - // Block may have no terminator if the next instruction is a jump destination. - if (!_basicBlock.llvm()->getTerminator()) - m_builder.CreateBr(_nextBasicBlock); -} - - - -void Compiler::removeDeadBlocks() -{ - // Remove dead basic blocks - auto sthErased = false; - do - { - sthErased = false; - for (auto it = basicBlocks.begin(); it != basicBlocks.end();) - { - auto llvmBB = it->second.llvm(); - if (llvm::pred_begin(llvmBB) == llvm::pred_end(llvmBB)) - { - llvmBB->eraseFromParent(); - basicBlocks.erase(it++); - sthErased = true; - } - else - ++it; - } - } - while (sthErased); - - // Remove jump table block if no predecessors - if (llvm::pred_begin(m_jumpTableBlock->llvm()) == llvm::pred_end(m_jumpTableBlock->llvm())) - { - m_jumpTableBlock->llvm()->eraseFromParent(); - m_jumpTableBlock.reset(); - } -} - -void Compiler::dumpCFGifRequired(std::string const& _dotfilePath) -{ - if (! m_options.dumpCFG) - return; - - // TODO: handle i/o failures - std::ofstream ofs(_dotfilePath); - dumpCFGtoStream(ofs); - ofs.close(); -} - -void Compiler::dumpCFGtoStream(std::ostream& _out) -{ - _out << "digraph BB {\n" - << " node [shape=record, fontname=Courier, fontsize=10];\n" - << " entry [share=record, label=\"entry block\"];\n"; - - std::vector blocks; - for (auto& pair : basicBlocks) - blocks.push_back(&pair.second); - if (m_jumpTableBlock) - blocks.push_back(m_jumpTableBlock.get()); - if (m_badJumpBlock) - blocks.push_back(m_badJumpBlock.get()); - - // std::map phiNodesPerBlock; - - // Output nodes - for (auto bb : blocks) - { - std::string blockName = bb->llvm()->getName(); - - std::ostringstream oss; - bb->dump(oss, true); - - _out << " \"" << blockName << "\" [shape=record, label=\" { " << blockName << "|" << oss.str() << "} \"];\n"; - } - - // Output edges - for (auto bb : blocks) - { - std::string blockName = bb->llvm()->getName(); - - auto end = llvm::pred_end(bb->llvm()); - for (llvm::pred_iterator it = llvm::pred_begin(bb->llvm()); it != end; ++it) - { - _out << " \"" << (*it)->getName().str() << "\" -> \"" << blockName << "\" [" - << ((m_jumpTableBlock.get() && *it == m_jumpTableBlock.get()->llvm()) ? "style = dashed, " : "") - << "];\n"; - } - } - - _out << "}\n"; -} - -void Compiler::dump() -{ - for (auto& entry : basicBlocks) - entry.second.dump(); - if (m_jumpTableBlock != nullptr) - m_jumpTableBlock->dump(); -} - -} -} -} - From 683f956a2e6d08e4e99560766704acd7f118b249 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Fri, 31 Oct 2014 15:47:36 +0000 Subject: [PATCH 312/641] added struct for compiler options --- evmcc/evmcc.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/evmcc/evmcc.cpp b/evmcc/evmcc.cpp index 047fdf252..191b87dcf 100644 --- a/evmcc/evmcc.cpp +++ b/evmcc/evmcc.cpp @@ -101,7 +101,10 @@ int main(int argc, char** argv) { auto compilationStartTime = std::chrono::high_resolution_clock::now(); - auto compiler = eth::jit::Compiler(); + eth::jit::Compiler::Options options; + options.dumpCFG = opt_dump_graph; + + auto compiler = eth::jit::Compiler(options); auto module = compiler.compile({bytecode.data(), bytecode.size()}); auto compilationEndTime = std::chrono::high_resolution_clock::now(); @@ -115,14 +118,6 @@ int main(int argc, char** argv) << std::endl; } - if (opt_dump_graph) - { - std::ofstream ofs("blocks.dot"); - compiler.dumpBasicBlockGraph(ofs); - ofs.close(); - std::cout << "Basic blocks graph written to block.dot\n"; - } - if (opt_interpret) { auto engine = eth::jit::ExecutionEngine(); From e756b4ae1e7921960c0b3592a878403953558e2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 31 Oct 2014 16:59:21 +0100 Subject: [PATCH 313/641] Rename BNOT -> NOT, NOT -> ISZERO --- libevmjit/Compiler.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 39c9edc7c..51b1ee403 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -342,7 +342,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytesConstRef _bytecod break; } - case Instruction::BNOT: + case Instruction::NOT: { auto value = stack.pop(); auto ret = m_builder.CreateXor(value, Constant::get(-1), "bnot"); @@ -400,7 +400,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytesConstRef _bytecod break; } - case Instruction::NOT: + case Instruction::ISZERO: { auto top = stack.pop(); auto iszero = m_builder.CreateICmpEQ(top, Constant::get(0), "iszero"); From 1c9fb4acb726a851106b1a471e9e7136218470af Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Mon, 3 Nov 2014 10:31:09 +0000 Subject: [PATCH 314/641] 1) JUMP/I semantics updated. 2) Members of BasicBlock::LocalStack pulled out to BasicBlock --- libevmjit/BasicBlock.cpp | 142 ++++++++++++++++++++------------------- libevmjit/BasicBlock.h | 59 +++++++--------- libevmjit/Compiler.cpp | 15 ++--- 3 files changed, 102 insertions(+), 114 deletions(-) diff --git a/libevmjit/BasicBlock.cpp b/libevmjit/BasicBlock.cpp index 0c604f1b3..1cc0e13fd 100644 --- a/libevmjit/BasicBlock.cpp +++ b/libevmjit/BasicBlock.cpp @@ -26,38 +26,36 @@ BasicBlock::BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx, m_beginInstIdx(_beginInstIdx), m_endInstIdx(_endInstIdx), m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {NamePrefix, std::to_string(_beginInstIdx)}, _mainFunc)), - m_stack(_builder, m_llvmBB) + m_stack(*this), + m_builder(_builder) {} BasicBlock::BasicBlock(std::string _name, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder) : m_beginInstIdx(0), m_endInstIdx(0), m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), _name, _mainFunc)), - m_stack(_builder, m_llvmBB) + m_stack(*this), + m_builder(_builder) {} -BasicBlock::LocalStack::LocalStack(llvm::IRBuilder<>& _builder, llvm::BasicBlock* _llvmBB) : - m_llvmBB(_llvmBB), - m_builder(_builder), - m_initialStack(), - m_currentStack(), - m_tosOffset(0) +BasicBlock::LocalStack::LocalStack(BasicBlock& _owner) : + m_bblock(_owner) {} void BasicBlock::LocalStack::push(llvm::Value* _value) { - m_currentStack.push_back(_value); - m_tosOffset += 1; + m_bblock.m_currentStack.push_back(_value); + m_bblock.m_tosOffset += 1; } llvm::Value* BasicBlock::LocalStack::pop() { auto result = get(0); - if (m_currentStack.size() > 0) - m_currentStack.pop_back(); + if (m_bblock.m_currentStack.size() > 0) + m_bblock.m_currentStack.pop_back(); - m_tosOffset -= 1; + m_bblock.m_tosOffset -= 1; return result; } @@ -83,7 +81,56 @@ void BasicBlock::LocalStack::swap(size_t _index) set(0, val); } -void BasicBlock::LocalStack::synchronize(Stack& _evmStack) +std::vector::iterator BasicBlock::LocalStack::getItemIterator(size_t _index) +{ + auto& currentStack = m_bblock.m_currentStack; + if (_index < currentStack.size()) + return currentStack.end() - _index - 1; + + // Need to map more elements from the EVM stack + auto nNewItems = 1 + _index - currentStack.size(); + currentStack.insert(currentStack.begin(), nNewItems, nullptr); + + return currentStack.end() - _index - 1; +} + +llvm::Value* BasicBlock::LocalStack::get(size_t _index) +{ + auto& initialStack = m_bblock.m_initialStack; + auto itemIter = getItemIterator(_index); + + if (*itemIter == nullptr) + { + // Need to fetch a new item from the EVM stack + assert(static_cast(_index) >= m_bblock.m_tosOffset); + size_t initialIdx = _index - m_bblock.m_tosOffset; + if (initialIdx >= initialStack.size()) + { + auto nNewItems = 1 + initialIdx - initialStack.size(); + initialStack.insert(initialStack.end(), nNewItems, nullptr); + } + + assert(initialStack[initialIdx] == nullptr); + // Create a dummy value. + std::string name = "get_" + boost::lexical_cast(_index); + initialStack[initialIdx] = m_bblock.m_builder.CreatePHI(Type::Word, 0, name); + *itemIter = initialStack[initialIdx]; + } + + return *itemIter; +} + +void BasicBlock::LocalStack::set(size_t _index, llvm::Value* _word) +{ + auto itemIter = getItemIterator(_index); + *itemIter = _word; +} + + + + + +void BasicBlock::synchronizeLocalStack(Stack& _evmStack) { auto blockTerminator = m_llvmBB->getTerminator(); assert(blockTerminator != nullptr); @@ -141,51 +188,6 @@ void BasicBlock::LocalStack::synchronize(Stack& _evmStack) m_tosOffset = 0; } -std::vector::iterator BasicBlock::LocalStack::getItemIterator(size_t _index) -{ - if (_index < m_currentStack.size()) - return m_currentStack.end() - _index - 1; - - // Need to map more elements from the EVM stack - auto nNewItems = 1 + _index - m_currentStack.size(); - m_currentStack.insert(m_currentStack.begin(), nNewItems, nullptr); - - return m_currentStack.end() - _index - 1; -} - -llvm::Value* BasicBlock::LocalStack::get(size_t _index) -{ - auto itemIter = getItemIterator(_index); - - if (*itemIter == nullptr) - { - // Need to fetch a new item from the EVM stack - assert(static_cast(_index) >= m_tosOffset); - size_t initialIdx = _index - m_tosOffset; - if (initialIdx >= m_initialStack.size()) - { - auto nNewItems = 1 + initialIdx - m_initialStack.size(); - m_initialStack.insert(m_initialStack.end(), nNewItems, nullptr); - } - - assert(m_initialStack[initialIdx] == nullptr); - // Create a dummy value. - std::string name = "get_" + boost::lexical_cast(_index); - m_initialStack[initialIdx] = m_builder.CreatePHI(Type::Word, 0, name); - *itemIter = m_initialStack[initialIdx]; - } - - return *itemIter; -} - -void BasicBlock::LocalStack::set(size_t _index, llvm::Value* _word) -{ - auto itemIter = getItemIterator(_index); - *itemIter = _word; -} - - - void BasicBlock::linkLocalStacks(std::vector basicBlocks, llvm::IRBuilder<>& _builder) { struct BBInfo @@ -202,14 +204,14 @@ void BasicBlock::linkLocalStacks(std::vector basicBlocks, llvm::IRB inputItems(0), outputItems(0) { - auto& initialStack = bblock.localStack().m_initialStack; + auto& initialStack = bblock.m_initialStack; for (auto it = initialStack.begin(); it != initialStack.end() && *it != nullptr; ++it, ++inputItems); //if (bblock.localStack().m_tosOffset > 0) // outputItems = bblock.localStack().m_tosOffset; - auto& exitStack = bblock.localStack().m_currentStack; + auto& exitStack = bblock.m_currentStack; for (auto it = exitStack.rbegin(); it != exitStack.rend() && *it != nullptr; ++it, ++outputItems); @@ -281,7 +283,7 @@ void BasicBlock::linkLocalStacks(std::vector basicBlocks, llvm::IRB auto& bblock = info.bblock; llvm::BasicBlock::iterator fstNonPhi(bblock.llvm()->getFirstNonPHI()); - auto phiIter = bblock.localStack().m_initialStack.begin(); + auto phiIter = bblock.m_initialStack.begin(); for (size_t index = 0; index < info.inputItems; ++index, ++phiIter) { assert(llvm::isa(*phiIter)); @@ -289,7 +291,7 @@ void BasicBlock::linkLocalStacks(std::vector basicBlocks, llvm::IRB for (auto predIt : info.predecessors) { - auto& predExitStack = predIt->bblock.localStack().m_currentStack; + auto& predExitStack = predIt->bblock.m_currentStack; auto value = *(predExitStack.end() - 1 - index); phi->addIncoming(value, predIt->bblock.llvm()); } @@ -305,10 +307,10 @@ void BasicBlock::linkLocalStacks(std::vector basicBlocks, llvm::IRB // The items pulled directly from predecessors block must be removed // from the list of items that has to be popped from the initial stack. - auto& initialStack = bblock.localStack().m_initialStack; + auto& initialStack = bblock.m_initialStack; initialStack.erase(initialStack.begin(), initialStack.begin() + info.inputItems); // Initial stack shrinks, so the size difference grows: - bblock.localStack().m_tosOffset += info.inputItems; + bblock.m_tosOffset += info.inputItems; } // We must account for the items that were pushed directly to successor @@ -319,9 +321,9 @@ void BasicBlock::linkLocalStacks(std::vector basicBlocks, llvm::IRB auto& info = entry.second; auto& bblock = info.bblock; - auto& exitStack = bblock.localStack().m_currentStack; + auto& exitStack = bblock.m_currentStack; exitStack.erase(exitStack.end() - info.outputItems, exitStack.end()); - bblock.localStack().m_tosOffset -= info.outputItems; + bblock.m_tosOffset -= info.outputItems; } } @@ -335,7 +337,7 @@ void BasicBlock::dump(std::ostream& _out, bool _dotOutput) llvm::raw_os_ostream out(_out); out << (_dotOutput ? "" : "Initial stack:\n"); - for (auto val : m_stack.m_initialStack) + for (auto val : m_initialStack) { if (val == nullptr) out << " ?"; @@ -352,11 +354,11 @@ void BasicBlock::dump(std::ostream& _out, bool _dotOutput) out << *ins << (_dotOutput ? "\\l" : "\n"); if (! _dotOutput) - out << "Current stack (offset = " << m_stack.m_tosOffset << "):\n"; + out << "Current stack (offset = " << m_tosOffset << "):\n"; else out << "|"; - for (auto val = m_stack.m_currentStack.rbegin(); val != m_stack.m_currentStack.rend(); ++val) + for (auto val = m_currentStack.rbegin(); val != m_currentStack.rend(); ++val) { if (*val == nullptr) out << " ?"; diff --git a/libevmjit/BasicBlock.h b/libevmjit/BasicBlock.h index ffa9ca109..f0643f342 100644 --- a/libevmjit/BasicBlock.h +++ b/libevmjit/BasicBlock.h @@ -21,7 +21,6 @@ public: class LocalStack { public: - /// Pushes value on stack void push(llvm::Value* _value); @@ -35,12 +34,8 @@ public: /// @param _index Index of value to be swaped. Must be > 0. void swap(size_t _index); - /// Synchronize current local stack with the EVM stack. - void synchronize(Stack& _evmStack); - private: - - LocalStack(llvm::IRBuilder<>& _builder, llvm::BasicBlock* _llvmBB); + LocalStack(BasicBlock& _owner); LocalStack(LocalStack const&) = delete; void operator=(LocalStack const&) = delete; friend BasicBlock; @@ -54,34 +49,7 @@ public: std::vector::iterator getItemIterator(size_t _index); private: - - llvm::BasicBlock* m_llvmBB; - - llvm::IRBuilder<>& m_builder; - - /** - * This stack contains LLVM values that correspond to items found at - * the EVM stack when the current basic block starts executing. - * Location 0 corresponds to the top of the EVM stack, location 1 is - * the item below the top and so on. The stack grows as the code - * accesses more items on the EVM stack but once a value is put on - * the stack, it will never be replaced. - */ - std::vector m_initialStack; - - /** - * This stack tracks the contents of the EVM stack as the current basic - * block executes. It may grow on both sides, as the code pushes items on - * top of the stack or changes existing items. - */ - std::vector m_currentStack; - - /** - * How many items higher is the current stack than the initial one. - * May be negative. - */ - int m_tosOffset; - + BasicBlock& m_bblock; }; /// Basic block name prefix. The rest is beging instruction index. @@ -105,6 +73,9 @@ public: /// to avoid excessive pushing/popping on the EVM stack. static void linkLocalStacks(std::vector _basicBlocks, llvm::IRBuilder<>& _builder); + /// Synchronize current local stack with the EVM stack. + void synchronizeLocalStack(Stack& _evmStack); + /// Prints local stack and block instructions to stderr. /// Useful for calling in a debugger session. void dump(); @@ -113,11 +84,31 @@ public: private: ProgramCounter const m_beginInstIdx; ProgramCounter const m_endInstIdx; + llvm::BasicBlock* const m_llvmBB; /// Basic black state vector (stack) - current/end values and their positions on stack /// @internal Must be AFTER m_llvmBB LocalStack m_stack; + + llvm::IRBuilder<>& m_builder; + + /// This stack contains LLVM values that correspond to items found at + /// the EVM stack when the current basic block starts executing. + /// Location 0 corresponds to the top of the EVM stack, location 1 is + /// the item below the top and so on. The stack grows as the code + /// accesses more items on the EVM stack but once a value is put on + /// the stack, it will never be replaced. + std::vector m_initialStack = {}; + + /// This stack tracks the contents of the EVM stack as the basic block + /// executes. It may grow on both sides, as the code pushes items on + /// top of the stack or changes existing items. + std::vector m_currentStack = {}; + + /// How many items higher is the current stack than the initial one. + /// May be negative. + int m_tosOffset = 0; }; } diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 51b1ee403..295f3a131 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -81,12 +81,9 @@ void Compiler::createBasicBlocks(bytesConstRef _bytecode) case Instruction::JUMPDEST: { - // A basic block starts at the next instruction. - if (currentPC + 1 < _bytecode.size()) - { - splitPoints.insert(currentPC + 1); - indirectJumpTargets.push_back(currentPC + 1); - } + // A basic block starts here. + splitPoints.insert(currentPC); + indirectJumpTargets.push_back(currentPC); break; } @@ -98,9 +95,7 @@ void Compiler::createBasicBlocks(bytesConstRef _bytecode) { // Create a basic block starting at the following instruction. if (curr + 1 < _bytecode.end()) - { splitPoints.insert(currentPC + 1); - } break; } @@ -234,9 +229,9 @@ std::unique_ptr Compiler::compile(bytesConstRef _bytecode) } for (auto& entry : basicBlocks) - entry.second.localStack().synchronize(stack); + entry.second.synchronizeLocalStack(stack); if (m_jumpTableBlock) - m_jumpTableBlock->localStack().synchronize(stack); + m_jumpTableBlock->synchronizeLocalStack(stack); dumpCFGifRequired("blocks-sync.dot"); From f8a577989140f69518b34e50f442f8dbdac65496 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Mon, 3 Nov 2014 10:31:34 +0000 Subject: [PATCH 315/641] unused var removed --- libevmjit/Runtime.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 96a5f75a3..982dd9f36 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -105,7 +105,6 @@ bytesConstRef Runtime::getReturnData() const RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder): CompilerHelper(_builder) { m_dataPtr = new llvm::GlobalVariable(*getModule(), Type::RuntimePtr, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::RuntimePtr), "rt"); - llvm::Type* args[] = {Type::BytePtr, m_builder.getInt32Ty()}; m_longjmp = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::longjmp); // Export data From 3d70090fe43bb1693129bd7d6ca03ccfea059091 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 3 Nov 2014 16:54:03 +0100 Subject: [PATCH 316/641] jsonrpc 0.3.0 working, needs cleanup --- cmake/EthDependenciesDeprecated.cmake | 38 +- eth/main.cpp | 2 +- libqethereum/QEthereum.h | 3 +- libweb3jsonrpc/CMakeLists.txt | 2 + libweb3jsonrpc/CorsHttpServer.h | 3 +- libweb3jsonrpc/WebThreeStubServer.cpp | 2 +- libweb3jsonrpc/WebThreeStubServer.h | 3 +- libweb3jsonrpc/abstractwebthreestubserver.h | 368 +++++----- libweb3jsonrpc/spec.json | 100 +-- neth/main.cpp | 2 +- test/CMakeLists.txt | 1 + test/jsonrpc.cpp | 11 +- test/webthreestubclient.h | 713 ++++++++------------ 13 files changed, 560 insertions(+), 688 deletions(-) diff --git a/cmake/EthDependenciesDeprecated.cmake b/cmake/EthDependenciesDeprecated.cmake index d1c51f6c4..d815bef3e 100644 --- a/cmake/EthDependenciesDeprecated.cmake +++ b/cmake/EthDependenciesDeprecated.cmake @@ -125,21 +125,47 @@ else() message(STATUS "Failed to find the miniupnpc headers!") endif () - find_path( JSONRPC_ID jsonrpc/rpc.h - /usr/include - /usr/local/include - ) + find_path( JSONRPC_ID jsonrpccpp/server.h + /usr/include + /usr/local/include + ) + if ( JSONRPC_ID ) message(STATUS "Found jsonrpc headers") - find_library( JSONRPC_LS NAMES jsonrpc + find_library( JSONRPC_LS NAMES jsonrpccpp-server PATHS /usr/lib /usr/local/lib /opt/local/lib /usr/lib/*/ ) - if ( JSONRPC_LS ) + + find_library( JSONRPC_COMMON_LS NAMES jsonrpccpp-common + PATHS + /usr/lib + /usr/local/lib + /opt/local/lib + /usr/lib/*/ + ) + + find_library( JSONCPP_LS NAMES jsoncpp + /usr/lib + /usr/local/lib + /opt/local/lib + /usr/lib/*/ + ) + + find_library( JSONRPC_CLIENT_LS NAMES jsonrpccpp-client + PATHS + /usr/lib/ + /usr/local/lib + /opt/local/lib + /usr/lib/*/ + ) + + if ( JSONRPC_LS AND JSONRPC_COMMON_LS ) message(STATUS "Found jsonrpc library: ${JSONRPC_LS}") + message(STATUS "Found jsonrpc-common library: ${JSONRPC_COMMON_LS}") add_definitions(-DETH_JSONRPC) else () message(STATUS "Failed to find the jsonrpc library!") diff --git a/eth/main.cpp b/eth/main.cpp index 759dd40d0..447729c1a 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -28,7 +28,7 @@ #include #include #if ETH_JSONRPC -#include +//#include #include #endif #include diff --git a/libqethereum/QEthereum.h b/libqethereum/QEthereum.h index 4f276b7e1..b4c17fdab 100644 --- a/libqethereum/QEthereum.h +++ b/libqethereum/QEthereum.h @@ -25,7 +25,8 @@ #include #include -#include +#include +//#include class QWebThree: public QObject { diff --git a/libweb3jsonrpc/CMakeLists.txt b/libweb3jsonrpc/CMakeLists.txt index b24a11196..6966cd10a 100644 --- a/libweb3jsonrpc/CMakeLists.txt +++ b/libweb3jsonrpc/CMakeLists.txt @@ -23,7 +23,9 @@ if(MINIUPNPC_LS) endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS}) +target_link_libraries(${EXECUTABLE} ${JSONCPP_LS}) target_link_libraries(${EXECUTABLE} ${JSONRPC_LS}) +target_link_libraries(${EXECUTABLE} ${JSONRPC_COMMON_LS}) target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) if(READLINE_LS) target_link_libraries(${EXECUTABLE} ${READLINE_LS}) diff --git a/libweb3jsonrpc/CorsHttpServer.h b/libweb3jsonrpc/CorsHttpServer.h index d3bd8a6e9..5dd3130a4 100644 --- a/libweb3jsonrpc/CorsHttpServer.h +++ b/libweb3jsonrpc/CorsHttpServer.h @@ -19,7 +19,8 @@ * @date 2014 */ -#include +#include +//#include namespace jsonrpc { diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index e7eb62e04..ed5907f53 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -217,7 +217,7 @@ static Json::Value toJson(h256 const& _h, shh::Envelope const& _e, shh::Message WebThreeStubServer::WebThreeStubServer(jsonrpc::AbstractServerConnector* _conn, WebThreeDirect& _web3, std::vector const& _accounts): - AbstractWebThreeStubServer(_conn), + AbstractWebThreeStubServer(*_conn), m_web3(_web3) { setAccounts(_accounts); diff --git a/libweb3jsonrpc/WebThreeStubServer.h b/libweb3jsonrpc/WebThreeStubServer.h index b18faf95a..193f1f6ff 100644 --- a/libweb3jsonrpc/WebThreeStubServer.h +++ b/libweb3jsonrpc/WebThreeStubServer.h @@ -29,7 +29,8 @@ #pragma warning(pop) #include -#include +//#include +#include #include #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" diff --git a/libweb3jsonrpc/abstractwebthreestubserver.h b/libweb3jsonrpc/abstractwebthreestubserver.h index ac6893933..90ee422a0 100644 --- a/libweb3jsonrpc/abstractwebthreestubserver.h +++ b/libweb3jsonrpc/abstractwebthreestubserver.h @@ -1,323 +1,287 @@ /** - * THIS FILE IS GENERATED BY jsonrpcstub, DO NOT CHANGE IT!!!!! + * This file is generated by jsonrpcstub, DO NOT CHANGE IT MANUALLY! */ -#ifndef _ABSTRACTWEBTHREESTUBSERVER_H_ -#define _ABSTRACTWEBTHREESTUBSERVER_H_ +#ifndef JSONRPC_CPP_STUB_ABSTRACTWEBTHREESTUBSERVER_H_ +#define JSONRPC_CPP_STUB_ABSTRACTWEBTHREESTUBSERVER_H_ -#include +#include class AbstractWebThreeStubServer : public jsonrpc::AbstractServer { public: - AbstractWebThreeStubServer(jsonrpc::AbstractServerConnector* conn) : - jsonrpc::AbstractServer(conn) + AbstractWebThreeStubServer(jsonrpc::AbstractServerConnector &conn) : jsonrpc::AbstractServer(conn) { - this->bindAndAddMethod(new jsonrpc::Procedure("account", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::accountI); - this->bindAndAddMethod(new jsonrpc::Procedure("accounts", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::accountsI); - this->bindAndAddMethod(new jsonrpc::Procedure("addToGroup", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::addToGroupI); - this->bindAndAddMethod(new jsonrpc::Procedure("balanceAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::balanceAtI); - this->bindAndAddMethod(new jsonrpc::Procedure("blockByHash", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::blockByHashI); - this->bindAndAddMethod(new jsonrpc::Procedure("blockByNumber", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::blockByNumberI); - this->bindAndAddMethod(new jsonrpc::Procedure("call", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::callI); - this->bindAndAddMethod(new jsonrpc::Procedure("changed", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::changedI); - this->bindAndAddMethod(new jsonrpc::Procedure("codeAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::codeAtI); this->bindAndAddMethod(new jsonrpc::Procedure("coinbase", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::coinbaseI); - this->bindAndAddMethod(new jsonrpc::Procedure("compile", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::compileI); - this->bindAndAddMethod(new jsonrpc::Procedure("countAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_REAL, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::countAtI); - this->bindAndAddMethod(new jsonrpc::Procedure("defaultBlock", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::defaultBlockI); - this->bindAndAddMethod(new jsonrpc::Procedure("gasPrice", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::gasPriceI); - this->bindAndAddMethod(new jsonrpc::Procedure("get", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::getI); - this->bindAndAddMethod(new jsonrpc::Procedure("getMessages", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::getMessagesI); - this->bindAndAddMethod(new jsonrpc::Procedure("getString", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::getStringI); - this->bindAndAddMethod(new jsonrpc::Procedure("haveIdentity", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::haveIdentityI); + this->bindAndAddMethod(new jsonrpc::Procedure("setCoinbase", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::setCoinbaseI); this->bindAndAddMethod(new jsonrpc::Procedure("listening", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::listeningI); + this->bindAndAddMethod(new jsonrpc::Procedure("setListening", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::setListeningI); this->bindAndAddMethod(new jsonrpc::Procedure("mining", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::miningI); - this->bindAndAddMethod(new jsonrpc::Procedure("newFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::newFilterI); - this->bindAndAddMethod(new jsonrpc::Procedure("newFilterString", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::newFilterStringI); - this->bindAndAddMethod(new jsonrpc::Procedure("newGroup", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::newGroupI); - this->bindAndAddMethod(new jsonrpc::Procedure("newIdentity", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::newIdentityI); - this->bindAndAddMethod(new jsonrpc::Procedure("number", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::numberI); + this->bindAndAddMethod(new jsonrpc::Procedure("setMining", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::setMiningI); + this->bindAndAddMethod(new jsonrpc::Procedure("gasPrice", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::gasPriceI); + this->bindAndAddMethod(new jsonrpc::Procedure("account", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::accountI); + this->bindAndAddMethod(new jsonrpc::Procedure("accounts", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::accountsI); this->bindAndAddMethod(new jsonrpc::Procedure("peerCount", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::peerCountI); - this->bindAndAddMethod(new jsonrpc::Procedure("post", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::postI); - this->bindAndAddMethod(new jsonrpc::Procedure("put", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING,"param3",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::putI); - this->bindAndAddMethod(new jsonrpc::Procedure("putString", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING,"param3",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::putStringI); - this->bindAndAddMethod(new jsonrpc::Procedure("setCoinbase", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::setCoinbaseI); + this->bindAndAddMethod(new jsonrpc::Procedure("defaultBlock", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::defaultBlockI); this->bindAndAddMethod(new jsonrpc::Procedure("setDefaultBlock", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::setDefaultBlockI); - this->bindAndAddMethod(new jsonrpc::Procedure("setListening", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::setListeningI); - this->bindAndAddMethod(new jsonrpc::Procedure("setMining", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::setMiningI); - this->bindAndAddMethod(new jsonrpc::Procedure("shhChanged", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::shhChangedI); - this->bindAndAddMethod(new jsonrpc::Procedure("shhNewFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::shhNewFilterI); - this->bindAndAddMethod(new jsonrpc::Procedure("shhUninstallFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::shhUninstallFilterI); + this->bindAndAddMethod(new jsonrpc::Procedure("number", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::numberI); + this->bindAndAddMethod(new jsonrpc::Procedure("balanceAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::balanceAtI); this->bindAndAddMethod(new jsonrpc::Procedure("stateAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::stateAtI); + this->bindAndAddMethod(new jsonrpc::Procedure("countAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_REAL, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::countAtI); + this->bindAndAddMethod(new jsonrpc::Procedure("codeAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::codeAtI); this->bindAndAddMethod(new jsonrpc::Procedure("transact", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::transactI); + this->bindAndAddMethod(new jsonrpc::Procedure("call", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::callI); + this->bindAndAddMethod(new jsonrpc::Procedure("blockByHash", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::blockByHashI); + this->bindAndAddMethod(new jsonrpc::Procedure("blockByNumber", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::blockByNumberI); this->bindAndAddMethod(new jsonrpc::Procedure("transactionByHash", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::transactionByHashI); this->bindAndAddMethod(new jsonrpc::Procedure("transactionByNumber", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_INTEGER,"param2",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::transactionByNumberI); this->bindAndAddMethod(new jsonrpc::Procedure("uncleByHash", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::uncleByHashI); this->bindAndAddMethod(new jsonrpc::Procedure("uncleByNumber", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_INTEGER,"param2",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::uncleByNumberI); + this->bindAndAddMethod(new jsonrpc::Procedure("compile", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::compileI); + this->bindAndAddMethod(new jsonrpc::Procedure("newFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::newFilterI); + this->bindAndAddMethod(new jsonrpc::Procedure("newFilterString", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::newFilterStringI); this->bindAndAddMethod(new jsonrpc::Procedure("uninstallFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::uninstallFilterI); - + this->bindAndAddMethod(new jsonrpc::Procedure("changed", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::changedI); + this->bindAndAddMethod(new jsonrpc::Procedure("getMessages", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::getMessagesI); + this->bindAndAddMethod(new jsonrpc::Procedure("put", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING,"param3",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::putI); + this->bindAndAddMethod(new jsonrpc::Procedure("get", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::getI); + this->bindAndAddMethod(new jsonrpc::Procedure("putString", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING,"param3",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::putStringI); + this->bindAndAddMethod(new jsonrpc::Procedure("getString", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::getStringI); + this->bindAndAddMethod(new jsonrpc::Procedure("post", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::postI); + this->bindAndAddMethod(new jsonrpc::Procedure("newIdentity", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::newIdentityI); + this->bindAndAddMethod(new jsonrpc::Procedure("haveIdentity", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::haveIdentityI); + this->bindAndAddMethod(new jsonrpc::Procedure("newGroup", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::newGroupI); + this->bindAndAddMethod(new jsonrpc::Procedure("addToGroup", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::addToGroupI); + this->bindAndAddMethod(new jsonrpc::Procedure("shhNewFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::shhNewFilterI); + this->bindAndAddMethod(new jsonrpc::Procedure("shhUninstallFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::shhUninstallFilterI); + this->bindAndAddMethod(new jsonrpc::Procedure("shhChanged", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::shhChangedI); } - - inline virtual void accountI(const Json::Value& request, Json::Value& response) + + inline virtual void coinbaseI(const Json::Value &request, Json::Value &response) { - response = this->account(); + (void)request; + response = this->coinbase(); } - - inline virtual void accountsI(const Json::Value& request, Json::Value& response) + inline virtual void setCoinbaseI(const Json::Value &request, Json::Value &response) { - response = this->accounts(); + response = this->setCoinbase(request[0u].asString()); } - - inline virtual void addToGroupI(const Json::Value& request, Json::Value& response) + inline virtual void listeningI(const Json::Value &request, Json::Value &response) { - response = this->addToGroup(request[0u].asString(), request[1u].asString()); + (void)request; + response = this->listening(); } - - inline virtual void balanceAtI(const Json::Value& request, Json::Value& response) + inline virtual void setListeningI(const Json::Value &request, Json::Value &response) { - response = this->balanceAt(request[0u].asString()); + response = this->setListening(request[0u].asBool()); } - - inline virtual void blockByHashI(const Json::Value& request, Json::Value& response) + inline virtual void miningI(const Json::Value &request, Json::Value &response) { - response = this->blockByHash(request[0u].asString()); + (void)request; + response = this->mining(); } - - inline virtual void blockByNumberI(const Json::Value& request, Json::Value& response) + inline virtual void setMiningI(const Json::Value &request, Json::Value &response) { - response = this->blockByNumber(request[0u].asInt()); + response = this->setMining(request[0u].asBool()); } - - inline virtual void callI(const Json::Value& request, Json::Value& response) + inline virtual void gasPriceI(const Json::Value &request, Json::Value &response) { - response = this->call(request[0u]); + (void)request; + response = this->gasPrice(); } - - inline virtual void changedI(const Json::Value& request, Json::Value& response) + inline virtual void accountI(const Json::Value &request, Json::Value &response) { - response = this->changed(request[0u].asInt()); + (void)request; + response = this->account(); } - - inline virtual void codeAtI(const Json::Value& request, Json::Value& response) + inline virtual void accountsI(const Json::Value &request, Json::Value &response) { - response = this->codeAt(request[0u].asString()); + (void)request; + response = this->accounts(); } - - inline virtual void coinbaseI(const Json::Value& request, Json::Value& response) + inline virtual void peerCountI(const Json::Value &request, Json::Value &response) { - response = this->coinbase(); + (void)request; + response = this->peerCount(); } - - inline virtual void compileI(const Json::Value& request, Json::Value& response) + inline virtual void defaultBlockI(const Json::Value &request, Json::Value &response) { - response = this->compile(request[0u].asString()); + (void)request; + response = this->defaultBlock(); } - - inline virtual void countAtI(const Json::Value& request, Json::Value& response) + inline virtual void setDefaultBlockI(const Json::Value &request, Json::Value &response) { - response = this->countAt(request[0u].asString()); + response = this->setDefaultBlock(request[0u].asInt()); } - - inline virtual void defaultBlockI(const Json::Value& request, Json::Value& response) + inline virtual void numberI(const Json::Value &request, Json::Value &response) { - response = this->defaultBlock(); + (void)request; + response = this->number(); } - - inline virtual void gasPriceI(const Json::Value& request, Json::Value& response) + inline virtual void balanceAtI(const Json::Value &request, Json::Value &response) { - response = this->gasPrice(); + response = this->balanceAt(request[0u].asString()); } - - inline virtual void getI(const Json::Value& request, Json::Value& response) + inline virtual void stateAtI(const Json::Value &request, Json::Value &response) { - response = this->get(request[0u].asString(), request[1u].asString()); + response = this->stateAt(request[0u].asString(), request[1u].asString()); } - - inline virtual void getMessagesI(const Json::Value& request, Json::Value& response) + inline virtual void countAtI(const Json::Value &request, Json::Value &response) { - response = this->getMessages(request[0u].asInt()); + response = this->countAt(request[0u].asString()); } - - inline virtual void getStringI(const Json::Value& request, Json::Value& response) + inline virtual void codeAtI(const Json::Value &request, Json::Value &response) { - response = this->getString(request[0u].asString(), request[1u].asString()); + response = this->codeAt(request[0u].asString()); } - - inline virtual void haveIdentityI(const Json::Value& request, Json::Value& response) + inline virtual void transactI(const Json::Value &request, Json::Value &response) { - response = this->haveIdentity(request[0u].asString()); + response = this->transact(request[0u]); } - - inline virtual void listeningI(const Json::Value& request, Json::Value& response) + inline virtual void callI(const Json::Value &request, Json::Value &response) { - response = this->listening(); + response = this->call(request[0u]); } - - inline virtual void miningI(const Json::Value& request, Json::Value& response) + inline virtual void blockByHashI(const Json::Value &request, Json::Value &response) { - response = this->mining(); + response = this->blockByHash(request[0u].asString()); } - - inline virtual void newFilterI(const Json::Value& request, Json::Value& response) + inline virtual void blockByNumberI(const Json::Value &request, Json::Value &response) { - response = this->newFilter(request[0u]); + response = this->blockByNumber(request[0u].asInt()); } - - inline virtual void newFilterStringI(const Json::Value& request, Json::Value& response) + inline virtual void transactionByHashI(const Json::Value &request, Json::Value &response) { - response = this->newFilterString(request[0u].asString()); + response = this->transactionByHash(request[0u].asString(), request[1u].asInt()); } - - inline virtual void newGroupI(const Json::Value& request, Json::Value& response) + inline virtual void transactionByNumberI(const Json::Value &request, Json::Value &response) { - response = this->newGroup(request[0u].asString(), request[1u].asString()); + response = this->transactionByNumber(request[0u].asInt(), request[1u].asInt()); } - - inline virtual void newIdentityI(const Json::Value& request, Json::Value& response) + inline virtual void uncleByHashI(const Json::Value &request, Json::Value &response) { - response = this->newIdentity(); + response = this->uncleByHash(request[0u].asString(), request[1u].asInt()); } - - inline virtual void numberI(const Json::Value& request, Json::Value& response) + inline virtual void uncleByNumberI(const Json::Value &request, Json::Value &response) { - response = this->number(); + response = this->uncleByNumber(request[0u].asInt(), request[1u].asInt()); } - - inline virtual void peerCountI(const Json::Value& request, Json::Value& response) + inline virtual void compileI(const Json::Value &request, Json::Value &response) { - response = this->peerCount(); + response = this->compile(request[0u].asString()); } - - inline virtual void postI(const Json::Value& request, Json::Value& response) + inline virtual void newFilterI(const Json::Value &request, Json::Value &response) { - response = this->post(request[0u]); + response = this->newFilter(request[0u]); } - - inline virtual void putI(const Json::Value& request, Json::Value& response) + inline virtual void newFilterStringI(const Json::Value &request, Json::Value &response) { - response = this->put(request[0u].asString(), request[1u].asString(), request[2u].asString()); + response = this->newFilterString(request[0u].asString()); } - - inline virtual void putStringI(const Json::Value& request, Json::Value& response) + inline virtual void uninstallFilterI(const Json::Value &request, Json::Value &response) { - response = this->putString(request[0u].asString(), request[1u].asString(), request[2u].asString()); + response = this->uninstallFilter(request[0u].asInt()); } - - inline virtual void setCoinbaseI(const Json::Value& request, Json::Value& response) + inline virtual void changedI(const Json::Value &request, Json::Value &response) { - response = this->setCoinbase(request[0u].asString()); + response = this->changed(request[0u].asInt()); } - - inline virtual void setDefaultBlockI(const Json::Value& request, Json::Value& response) + inline virtual void getMessagesI(const Json::Value &request, Json::Value &response) { - response = this->setDefaultBlock(request[0u].asInt()); + response = this->getMessages(request[0u].asInt()); } - - inline virtual void setListeningI(const Json::Value& request, Json::Value& response) + inline virtual void putI(const Json::Value &request, Json::Value &response) { - response = this->setListening(request[0u].asBool()); + response = this->put(request[0u].asString(), request[1u].asString(), request[2u].asString()); } - - inline virtual void setMiningI(const Json::Value& request, Json::Value& response) + inline virtual void getI(const Json::Value &request, Json::Value &response) { - response = this->setMining(request[0u].asBool()); + response = this->get(request[0u].asString(), request[1u].asString()); } - - inline virtual void shhChangedI(const Json::Value& request, Json::Value& response) + inline virtual void putStringI(const Json::Value &request, Json::Value &response) { - response = this->shhChanged(request[0u].asInt()); + response = this->putString(request[0u].asString(), request[1u].asString(), request[2u].asString()); } - - inline virtual void shhNewFilterI(const Json::Value& request, Json::Value& response) + inline virtual void getStringI(const Json::Value &request, Json::Value &response) { - response = this->shhNewFilter(request[0u]); + response = this->getString(request[0u].asString(), request[1u].asString()); } - - inline virtual void shhUninstallFilterI(const Json::Value& request, Json::Value& response) + inline virtual void postI(const Json::Value &request, Json::Value &response) { - response = this->shhUninstallFilter(request[0u].asInt()); + response = this->post(request[0u]); } - - inline virtual void stateAtI(const Json::Value& request, Json::Value& response) + inline virtual void newIdentityI(const Json::Value &request, Json::Value &response) { - response = this->stateAt(request[0u].asString(), request[1u].asString()); + (void)request; + response = this->newIdentity(); } - - inline virtual void transactI(const Json::Value& request, Json::Value& response) + inline virtual void haveIdentityI(const Json::Value &request, Json::Value &response) { - response = this->transact(request[0u]); + response = this->haveIdentity(request[0u].asString()); } - - inline virtual void transactionByHashI(const Json::Value& request, Json::Value& response) + inline virtual void newGroupI(const Json::Value &request, Json::Value &response) { - response = this->transactionByHash(request[0u].asString(), request[1u].asInt()); + response = this->newGroup(request[0u].asString(), request[1u].asString()); } - - inline virtual void transactionByNumberI(const Json::Value& request, Json::Value& response) + inline virtual void addToGroupI(const Json::Value &request, Json::Value &response) { - response = this->transactionByNumber(request[0u].asInt(), request[1u].asInt()); + response = this->addToGroup(request[0u].asString(), request[1u].asString()); } - - inline virtual void uncleByHashI(const Json::Value& request, Json::Value& response) + inline virtual void shhNewFilterI(const Json::Value &request, Json::Value &response) { - response = this->uncleByHash(request[0u].asString(), request[1u].asInt()); + response = this->shhNewFilter(request[0u]); } - - inline virtual void uncleByNumberI(const Json::Value& request, Json::Value& response) + inline virtual void shhUninstallFilterI(const Json::Value &request, Json::Value &response) { - response = this->uncleByNumber(request[0u].asInt(), request[1u].asInt()); + response = this->shhUninstallFilter(request[0u].asInt()); } - - inline virtual void uninstallFilterI(const Json::Value& request, Json::Value& response) + inline virtual void shhChangedI(const Json::Value &request, Json::Value &response) { - response = this->uninstallFilter(request[0u].asInt()); + response = this->shhChanged(request[0u].asInt()); } - - - virtual std::string account() = 0; - virtual Json::Value accounts() = 0; - virtual std::string addToGroup(const std::string& param1, const std::string& param2) = 0; - virtual std::string balanceAt(const std::string& param1) = 0; - virtual Json::Value blockByHash(const std::string& param1) = 0; - virtual Json::Value blockByNumber(const int& param1) = 0; - virtual std::string call(const Json::Value& param1) = 0; - virtual bool changed(const int& param1) = 0; - virtual std::string codeAt(const std::string& param1) = 0; virtual std::string coinbase() = 0; - virtual std::string compile(const std::string& param1) = 0; - virtual double countAt(const std::string& param1) = 0; - virtual int defaultBlock() = 0; - virtual std::string gasPrice() = 0; - virtual std::string get(const std::string& param1, const std::string& param2) = 0; - virtual Json::Value getMessages(const int& param1) = 0; - virtual std::string getString(const std::string& param1, const std::string& param2) = 0; - virtual bool haveIdentity(const std::string& param1) = 0; + virtual bool setCoinbase(const std::string& param1) = 0; virtual bool listening() = 0; + virtual bool setListening(const bool& param1) = 0; virtual bool mining() = 0; - virtual int newFilter(const Json::Value& param1) = 0; - virtual int newFilterString(const std::string& param1) = 0; - virtual std::string newGroup(const std::string& param1, const std::string& param2) = 0; - virtual std::string newIdentity() = 0; - virtual int number() = 0; + virtual bool setMining(const bool& param1) = 0; + virtual std::string gasPrice() = 0; + virtual std::string account() = 0; + virtual Json::Value accounts() = 0; virtual int peerCount() = 0; - virtual bool post(const Json::Value& param1) = 0; - virtual bool put(const std::string& param1, const std::string& param2, const std::string& param3) = 0; - virtual bool putString(const std::string& param1, const std::string& param2, const std::string& param3) = 0; - virtual bool setCoinbase(const std::string& param1) = 0; + virtual int defaultBlock() = 0; virtual bool setDefaultBlock(const int& param1) = 0; - virtual bool setListening(const bool& param1) = 0; - virtual bool setMining(const bool& param1) = 0; - virtual Json::Value shhChanged(const int& param1) = 0; - virtual int shhNewFilter(const Json::Value& param1) = 0; - virtual bool shhUninstallFilter(const int& param1) = 0; + virtual int number() = 0; + virtual std::string balanceAt(const std::string& param1) = 0; virtual std::string stateAt(const std::string& param1, const std::string& param2) = 0; + virtual double countAt(const std::string& param1) = 0; + virtual std::string codeAt(const std::string& param1) = 0; virtual std::string transact(const Json::Value& param1) = 0; + virtual std::string call(const Json::Value& param1) = 0; + virtual Json::Value blockByHash(const std::string& param1) = 0; + virtual Json::Value blockByNumber(const int& param1) = 0; virtual Json::Value transactionByHash(const std::string& param1, const int& param2) = 0; virtual Json::Value transactionByNumber(const int& param1, const int& param2) = 0; virtual Json::Value uncleByHash(const std::string& param1, const int& param2) = 0; virtual Json::Value uncleByNumber(const int& param1, const int& param2) = 0; + virtual std::string compile(const std::string& param1) = 0; + virtual int newFilter(const Json::Value& param1) = 0; + virtual int newFilterString(const std::string& param1) = 0; virtual bool uninstallFilter(const int& param1) = 0; - + virtual bool changed(const int& param1) = 0; + virtual Json::Value getMessages(const int& param1) = 0; + virtual bool put(const std::string& param1, const std::string& param2, const std::string& param3) = 0; + virtual std::string get(const std::string& param1, const std::string& param2) = 0; + virtual bool putString(const std::string& param1, const std::string& param2, const std::string& param3) = 0; + virtual std::string getString(const std::string& param1, const std::string& param2) = 0; + virtual bool post(const Json::Value& param1) = 0; + virtual std::string newIdentity() = 0; + virtual bool haveIdentity(const std::string& param1) = 0; + virtual std::string newGroup(const std::string& param1, const std::string& param2) = 0; + virtual std::string addToGroup(const std::string& param1, const std::string& param2) = 0; + virtual int shhNewFilter(const Json::Value& param1) = 0; + virtual bool shhUninstallFilter(const int& param1) = 0; + virtual Json::Value shhChanged(const int& param1) = 0; }; -#endif //_ABSTRACTWEBTHREESTUBSERVER_H_ + +#endif //JSONRPC_CPP_ABSTRACTWEBTHREESTUBSERVER_H_ diff --git a/libweb3jsonrpc/spec.json b/libweb3jsonrpc/spec.json index 1e7065970..aea50adf9 100644 --- a/libweb3jsonrpc/spec.json +++ b/libweb3jsonrpc/spec.json @@ -1,55 +1,55 @@ [ - { "method": "coinbase", "params": [], "order": [], "returns" : "" }, - { "method": "setCoinbase", "params": [""], "order": [], "returns" : true }, - { "method": "listening", "params": [], "order": [], "returns" : false }, - { "method": "setListening", "params": [false], "order" : [], "returns" : true }, - { "method": "mining", "params": [], "order": [], "returns" : false }, - { "method": "setMining", "params": [false], "order" : [], "returns" : true }, - { "method": "gasPrice", "params": [], "order": [], "returns" : "" }, - { "method": "account", "params": [], "order": [], "returns" : "" }, - { "method": "accounts", "params": [], "order": [], "returns" : [] }, - { "method": "peerCount", "params": [], "order": [], "returns" : 0 }, - { "method": "defaultBlock", "params": [], "order": [], "returns" : 0}, - { "method": "setDefaultBlock", "params": [0], "order": [], "returns" : true}, - { "method": "number", "params": [], "order": [], "returns" : 0}, - - { "method": "balanceAt", "params": [""], "order": [], "returns" : ""}, - { "method": "stateAt", "params": ["", ""], "order": [], "returns": ""}, - { "method": "countAt", "params": [""], "order": [], "returns" : 0.0}, - { "method": "codeAt", "params": [""], "order": [], "returns": ""}, - - { "method": "transact", "params": [{}], "order": [], "returns": ""}, - { "method": "call", "params": [{}], "order": [], "returns": ""}, - - { "method": "blockByHash", "params": [""],"order": [], "returns": {}}, - { "method": "blockByNumber", "params": [0],"order": [], "returns": {}}, - { "method": "transactionByHash", "params": ["", 0], "order": [], "returns": {}}, - { "method": "transactionByNumber", "params": [0, 0], "order": [], "returns": {}}, - { "method": "uncleByHash", "params": ["", 0], "order": [], "returns": {}}, - { "method": "uncleByNumber", "params": [0, 0], "order": [], "returns": {}}, - - { "method": "compile", "params": [""], "order": [], "returns": ""}, - - { "method": "newFilter", "params": [{}], "order": [], "returns": 0}, - { "method": "newFilterString", "params": [""], "order": [], "returns": 0}, - { "method": "uninstallFilter", "params": [0], "order": [], "returns": true}, - { "method": "changed", "params": [0], "order": [], "returns": false}, - { "method": "getMessages", "params": [0], "order": [], "returns": []}, - - { "method": "put", "params": ["", "", ""], "order": [], "returns": true}, - { "method": "get", "params": ["", ""], "order": [], "returns": ""}, - { "method": "putString", "params": ["", "", ""], "order": [], "returns": true}, - { "method": "getString", "params": ["", ""], "order": [], "returns": ""}, - - { "method": "post", "params": [{}], "order": [], "returns": true}, - { "method": "newIdentity", "params": [], "order": [], "returns": ""}, - { "method": "haveIdentity", "params": [""], "order": [], "returns": false}, - { "method": "newGroup", "params": ["", ""], "order": [], "returns": ""}, - { "method": "addToGroup", "params": ["", ""], "order": [], "returns": ""}, + { "name": "coinbase", "params": [], "order": [], "returns" : "" }, + { "name": "setCoinbase", "params": [""], "order": [], "returns" : true }, + { "name": "listening", "params": [], "order": [], "returns" : false }, + { "name": "setListening", "params": [false], "order" : [], "returns" : true }, + { "name": "mining", "params": [], "order": [], "returns" : false }, + { "name": "setMining", "params": [false], "order" : [], "returns" : true }, + { "name": "gasPrice", "params": [], "order": [], "returns" : "" }, + { "name": "account", "params": [], "order": [], "returns" : "" }, + { "name": "accounts", "params": [], "order": [], "returns" : [] }, + { "name": "peerCount", "params": [], "order": [], "returns" : 0 }, + { "name": "defaultBlock", "params": [], "order": [], "returns" : 0}, + { "name": "setDefaultBlock", "params": [0], "order": [], "returns" : true}, + { "name": "number", "params": [], "order": [], "returns" : 0}, + + { "name": "balanceAt", "params": [""], "order": [], "returns" : ""}, + { "name": "stateAt", "params": ["", ""], "order": [], "returns": ""}, + { "name": "countAt", "params": [""], "order": [], "returns" : 0.0}, + { "name": "codeAt", "params": [""], "order": [], "returns": ""}, + + { "name": "transact", "params": [{}], "order": [], "returns": ""}, + { "name": "call", "params": [{}], "order": [], "returns": ""}, + + { "name": "blockByHash", "params": [""],"order": [], "returns": {}}, + { "name": "blockByNumber", "params": [0],"order": [], "returns": {}}, + { "name": "transactionByHash", "params": ["", 0], "order": [], "returns": {}}, + { "name": "transactionByNumber", "params": [0, 0], "order": [], "returns": {}}, + { "name": "uncleByHash", "params": ["", 0], "order": [], "returns": {}}, + { "name": "uncleByNumber", "params": [0, 0], "order": [], "returns": {}}, + + { "name": "compile", "params": [""], "order": [], "returns": ""}, + + { "name": "newFilter", "params": [{}], "order": [], "returns": 0}, + { "name": "newFilterString", "params": [""], "order": [], "returns": 0}, + { "name": "uninstallFilter", "params": [0], "order": [], "returns": true}, + { "name": "changed", "params": [0], "order": [], "returns": false}, + { "name": "getMessages", "params": [0], "order": [], "returns": []}, + + { "name": "put", "params": ["", "", ""], "order": [], "returns": true}, + { "name": "get", "params": ["", ""], "order": [], "returns": ""}, + { "name": "putString", "params": ["", "", ""], "order": [], "returns": true}, + { "name": "getString", "params": ["", ""], "order": [], "returns": ""}, + + { "name": "post", "params": [{}], "order": [], "returns": true}, + { "name": "newIdentity", "params": [], "order": [], "returns": ""}, + { "name": "haveIdentity", "params": [""], "order": [], "returns": false}, + { "name": "newGroup", "params": ["", ""], "order": [], "returns": ""}, + { "name": "addToGroup", "params": ["", ""], "order": [], "returns": ""}, - { "method": "shhNewFilter", "params": [{}], "order": [], "returns": 0}, - { "method": "shhUninstallFilter", "params": [0], "order": [], "returns": true}, - { "method": "shhChanged", "params": [0], "order": [], "returns": []} + { "name": "shhNewFilter", "params": [{}], "order": [], "returns": 0}, + { "name": "shhUninstallFilter", "params": [0], "order": [], "returns": true}, + { "name": "shhChanged", "params": [0], "order": [], "returns": []} ] diff --git a/neth/main.cpp b/neth/main.cpp index 4e3a0f40a..8512cf77b 100644 --- a/neth/main.cpp +++ b/neth/main.cpp @@ -27,7 +27,7 @@ #include #include #if ETH_JSONRPC -#include +#include #endif #include #include diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a11c9fa16..63094fa23 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -18,6 +18,7 @@ target_link_libraries(testeth ${CRYPTOPP_LS}) target_link_libraries(testeth webthree) if(JSONRPC_LS) target_link_libraries(testeth web3jsonrpc) +target_link_libraries(testeth ${JSONRPC_CLIENT_LS}) endif() target_link_libraries(createRandomTest ethereum) diff --git a/test/jsonrpc.cpp b/test/jsonrpc.cpp index 033339ec2..f261a5164 100644 --- a/test/jsonrpc.cpp +++ b/test/jsonrpc.cpp @@ -29,8 +29,10 @@ #include #include #include -#include -#include +#include +#include +//#include +//#include #include #include "JsonSpiritHeaders.h" #include "TestHelper.h" @@ -54,7 +56,8 @@ dev::WebThreeDirect web3(name, dbPath, true, s, np); unique_ptr jsonrpcServer; unique_ptr jsonrpcClient; - +jsonrpc::HttpClient httpClient("http://localhost:8080"); + struct JsonrpcFixture { JsonrpcFixture() { @@ -66,7 +69,7 @@ struct JsonrpcFixture { jsonrpcServer->setIdentities({}); jsonrpcServer->StartListening(); - jsonrpcClient = unique_ptr(new WebThreeStubClient(new jsonrpc::HttpClient("http://localhost:8080"))); + jsonrpcClient = unique_ptr(new WebThreeStubClient(httpClient)); } ~JsonrpcFixture() { diff --git a/test/webthreestubclient.h b/test/webthreestubclient.h index 6beee5bb6..abe146efc 100644 --- a/test/webthreestubclient.h +++ b/test/webthreestubclient.h @@ -1,587 +1,460 @@ /** - * THIS FILE IS GENERATED BY jsonrpcstub, DO NOT CHANGE IT!!!!! + * This file is generated by jsonrpcstub, DO NOT CHANGE IT MANUALLY! */ -#ifndef _WEBTHREESTUBCLIENT_H_ -#define _WEBTHREESTUBCLIENT_H_ +#ifndef JSONRPC_CPP_STUB_WEBTHREESTUBCLIENT_H_ +#define JSONRPC_CPP_STUB_WEBTHREESTUBCLIENT_H_ -#include +#include -class WebThreeStubClient +class WebThreeStubClient : public jsonrpc::Client { public: - WebThreeStubClient(jsonrpc::AbstractClientConnector* conn) - { - this->client = new jsonrpc::Client(conn); - } - ~WebThreeStubClient() - { - delete this->client; - } + WebThreeStubClient(jsonrpc::IClientConnector &conn) : jsonrpc::Client(conn) {} - std::string account() throw (jsonrpc::JsonRpcException) + std::string coinbase() throw (jsonrpc::JsonRpcException) { Json::Value p; p = Json::nullValue; - Json::Value result = this->client->CallMethod("account",p); - if (result.isString()) - return result.asString(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + Json::Value result = this->CallMethod("coinbase",p); + if (result.isString()) + return result.asString(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - Json::Value accounts() throw (jsonrpc::JsonRpcException) + bool setCoinbase(const std::string& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; - p = Json::nullValue; - Json::Value result = this->client->CallMethod("accounts",p); - if (result.isArray()) - return result; - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + p.append(param1); + Json::Value result = this->CallMethod("setCoinbase",p); + if (result.isBool()) + return result.asBool(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - std::string addToGroup(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) + bool listening() throw (jsonrpc::JsonRpcException) { Json::Value p; - p.append(param1); -p.append(param2); - - Json::Value result = this->client->CallMethod("addToGroup",p); - if (result.isString()) - return result.asString(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + p = Json::nullValue; + Json::Value result = this->CallMethod("listening",p); + if (result.isBool()) + return result.asBool(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - std::string balanceAt(const std::string& param1) throw (jsonrpc::JsonRpcException) + bool setListening(const bool& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - - Json::Value result = this->client->CallMethod("balanceAt",p); - if (result.isString()) - return result.asString(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + Json::Value result = this->CallMethod("setListening",p); + if (result.isBool()) + return result.asBool(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - Json::Value blockByHash(const std::string& param1) throw (jsonrpc::JsonRpcException) + bool mining() throw (jsonrpc::JsonRpcException) { Json::Value p; - p.append(param1); - - Json::Value result = this->client->CallMethod("blockByHash",p); - if (result.isObject()) - return result; - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + p = Json::nullValue; + Json::Value result = this->CallMethod("mining",p); + if (result.isBool()) + return result.asBool(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - Json::Value blockByNumber(const int& param1) throw (jsonrpc::JsonRpcException) + bool setMining(const bool& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - - Json::Value result = this->client->CallMethod("blockByNumber",p); - if (result.isObject()) - return result; - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + Json::Value result = this->CallMethod("setMining",p); + if (result.isBool()) + return result.asBool(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - std::string call(const Json::Value& param1) throw (jsonrpc::JsonRpcException) + std::string gasPrice() throw (jsonrpc::JsonRpcException) { Json::Value p; - p.append(param1); - - Json::Value result = this->client->CallMethod("call",p); - if (result.isString()) - return result.asString(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + p = Json::nullValue; + Json::Value result = this->CallMethod("gasPrice",p); + if (result.isString()) + return result.asString(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - bool changed(const int& param1) throw (jsonrpc::JsonRpcException) + std::string account() throw (jsonrpc::JsonRpcException) { Json::Value p; - p.append(param1); - - Json::Value result = this->client->CallMethod("changed",p); - if (result.isBool()) - return result.asBool(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + p = Json::nullValue; + Json::Value result = this->CallMethod("account",p); + if (result.isString()) + return result.asString(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - std::string codeAt(const std::string& param1) throw (jsonrpc::JsonRpcException) + Json::Value accounts() throw (jsonrpc::JsonRpcException) { Json::Value p; - p.append(param1); - - Json::Value result = this->client->CallMethod("codeAt",p); - if (result.isString()) - return result.asString(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + p = Json::nullValue; + Json::Value result = this->CallMethod("accounts",p); + if (result.isArray()) + return result; + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - std::string coinbase() throw (jsonrpc::JsonRpcException) + int peerCount() throw (jsonrpc::JsonRpcException) { Json::Value p; p = Json::nullValue; - Json::Value result = this->client->CallMethod("coinbase",p); - if (result.isString()) - return result.asString(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + Json::Value result = this->CallMethod("peerCount",p); + if (result.isInt()) + return result.asInt(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - std::string compile(const std::string& param1) throw (jsonrpc::JsonRpcException) + int defaultBlock() throw (jsonrpc::JsonRpcException) { Json::Value p; - p.append(param1); - - Json::Value result = this->client->CallMethod("compile",p); - if (result.isString()) - return result.asString(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + p = Json::nullValue; + Json::Value result = this->CallMethod("defaultBlock",p); + if (result.isInt()) + return result.asInt(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - double countAt(const std::string& param1) throw (jsonrpc::JsonRpcException) + bool setDefaultBlock(const int& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - - Json::Value result = this->client->CallMethod("countAt",p); - if (result.isDouble()) - return result.asDouble(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + Json::Value result = this->CallMethod("setDefaultBlock",p); + if (result.isBool()) + return result.asBool(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - int defaultBlock() throw (jsonrpc::JsonRpcException) + int number() throw (jsonrpc::JsonRpcException) { Json::Value p; p = Json::nullValue; - Json::Value result = this->client->CallMethod("defaultBlock",p); - if (result.isInt()) - return result.asInt(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + Json::Value result = this->CallMethod("number",p); + if (result.isInt()) + return result.asInt(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - std::string gasPrice() throw (jsonrpc::JsonRpcException) + std::string balanceAt(const std::string& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; - p = Json::nullValue; - Json::Value result = this->client->CallMethod("gasPrice",p); - if (result.isString()) - return result.asString(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + p.append(param1); + Json::Value result = this->CallMethod("balanceAt",p); + if (result.isString()) + return result.asString(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - std::string get(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) + std::string stateAt(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); -p.append(param2); - - Json::Value result = this->client->CallMethod("get",p); - if (result.isString()) - return result.asString(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + p.append(param2); + Json::Value result = this->CallMethod("stateAt",p); + if (result.isString()) + return result.asString(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - Json::Value getMessages(const int& param1) throw (jsonrpc::JsonRpcException) + double countAt(const std::string& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - - Json::Value result = this->client->CallMethod("getMessages",p); - if (result.isArray()) - return result; - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + Json::Value result = this->CallMethod("countAt",p); + if (result.isDouble()) + return result.asDouble(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - std::string getString(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) + std::string codeAt(const std::string& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); -p.append(param2); - - Json::Value result = this->client->CallMethod("getString",p); - if (result.isString()) - return result.asString(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + Json::Value result = this->CallMethod("codeAt",p); + if (result.isString()) + return result.asString(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - bool haveIdentity(const std::string& param1) throw (jsonrpc::JsonRpcException) + std::string transact(const Json::Value& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - - Json::Value result = this->client->CallMethod("haveIdentity",p); - if (result.isBool()) - return result.asBool(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + Json::Value result = this->CallMethod("transact",p); + if (result.isString()) + return result.asString(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - bool listening() throw (jsonrpc::JsonRpcException) + std::string call(const Json::Value& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; - p = Json::nullValue; - Json::Value result = this->client->CallMethod("listening",p); - if (result.isBool()) - return result.asBool(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + p.append(param1); + Json::Value result = this->CallMethod("call",p); + if (result.isString()) + return result.asString(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - bool mining() throw (jsonrpc::JsonRpcException) + Json::Value blockByHash(const std::string& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; - p = Json::nullValue; - Json::Value result = this->client->CallMethod("mining",p); - if (result.isBool()) - return result.asBool(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + p.append(param1); + Json::Value result = this->CallMethod("blockByHash",p); + if (result.isObject()) + return result; + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - int newFilter(const Json::Value& param1) throw (jsonrpc::JsonRpcException) + Json::Value blockByNumber(const int& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - - Json::Value result = this->client->CallMethod("newFilter",p); - if (result.isInt()) - return result.asInt(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + Json::Value result = this->CallMethod("blockByNumber",p); + if (result.isObject()) + return result; + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - int newFilterString(const std::string& param1) throw (jsonrpc::JsonRpcException) + Json::Value transactionByHash(const std::string& param1, const int& param2) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - - Json::Value result = this->client->CallMethod("newFilterString",p); - if (result.isInt()) - return result.asInt(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + p.append(param2); + Json::Value result = this->CallMethod("transactionByHash",p); + if (result.isObject()) + return result; + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - std::string newGroup(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) + Json::Value transactionByNumber(const int& param1, const int& param2) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); -p.append(param2); - - Json::Value result = this->client->CallMethod("newGroup",p); - if (result.isString()) - return result.asString(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + p.append(param2); + Json::Value result = this->CallMethod("transactionByNumber",p); + if (result.isObject()) + return result; + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - std::string newIdentity() throw (jsonrpc::JsonRpcException) + Json::Value uncleByHash(const std::string& param1, const int& param2) throw (jsonrpc::JsonRpcException) { Json::Value p; - p = Json::nullValue; - Json::Value result = this->client->CallMethod("newIdentity",p); - if (result.isString()) - return result.asString(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + p.append(param1); + p.append(param2); + Json::Value result = this->CallMethod("uncleByHash",p); + if (result.isObject()) + return result; + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - int number() throw (jsonrpc::JsonRpcException) + Json::Value uncleByNumber(const int& param1, const int& param2) throw (jsonrpc::JsonRpcException) { Json::Value p; - p = Json::nullValue; - Json::Value result = this->client->CallMethod("number",p); - if (result.isInt()) - return result.asInt(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + p.append(param1); + p.append(param2); + Json::Value result = this->CallMethod("uncleByNumber",p); + if (result.isObject()) + return result; + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - int peerCount() throw (jsonrpc::JsonRpcException) + std::string compile(const std::string& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; - p = Json::nullValue; - Json::Value result = this->client->CallMethod("peerCount",p); - if (result.isInt()) - return result.asInt(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + p.append(param1); + Json::Value result = this->CallMethod("compile",p); + if (result.isString()) + return result.asString(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - bool post(const Json::Value& param1) throw (jsonrpc::JsonRpcException) + int newFilter(const Json::Value& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - - Json::Value result = this->client->CallMethod("post",p); - if (result.isBool()) - return result.asBool(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + Json::Value result = this->CallMethod("newFilter",p); + if (result.isInt()) + return result.asInt(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - bool put(const std::string& param1, const std::string& param2, const std::string& param3) throw (jsonrpc::JsonRpcException) + int newFilterString(const std::string& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); -p.append(param2); -p.append(param3); - - Json::Value result = this->client->CallMethod("put",p); - if (result.isBool()) - return result.asBool(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + Json::Value result = this->CallMethod("newFilterString",p); + if (result.isInt()) + return result.asInt(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - bool putString(const std::string& param1, const std::string& param2, const std::string& param3) throw (jsonrpc::JsonRpcException) + bool uninstallFilter(const int& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); -p.append(param2); -p.append(param3); - - Json::Value result = this->client->CallMethod("putString",p); - if (result.isBool()) - return result.asBool(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + Json::Value result = this->CallMethod("uninstallFilter",p); + if (result.isBool()) + return result.asBool(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - bool setCoinbase(const std::string& param1) throw (jsonrpc::JsonRpcException) + bool changed(const int& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - - Json::Value result = this->client->CallMethod("setCoinbase",p); - if (result.isBool()) - return result.asBool(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + Json::Value result = this->CallMethod("changed",p); + if (result.isBool()) + return result.asBool(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - bool setDefaultBlock(const int& param1) throw (jsonrpc::JsonRpcException) + Json::Value getMessages(const int& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - - Json::Value result = this->client->CallMethod("setDefaultBlock",p); - if (result.isBool()) - return result.asBool(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + Json::Value result = this->CallMethod("getMessages",p); + if (result.isArray()) + return result; + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - bool setListening(const bool& param1) throw (jsonrpc::JsonRpcException) + bool put(const std::string& param1, const std::string& param2, const std::string& param3) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - - Json::Value result = this->client->CallMethod("setListening",p); - if (result.isBool()) - return result.asBool(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + p.append(param2); + p.append(param3); + Json::Value result = this->CallMethod("put",p); + if (result.isBool()) + return result.asBool(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - bool setMining(const bool& param1) throw (jsonrpc::JsonRpcException) + std::string get(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - - Json::Value result = this->client->CallMethod("setMining",p); - if (result.isBool()) - return result.asBool(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + p.append(param2); + Json::Value result = this->CallMethod("get",p); + if (result.isString()) + return result.asString(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - Json::Value shhChanged(const int& param1) throw (jsonrpc::JsonRpcException) + bool putString(const std::string& param1, const std::string& param2, const std::string& param3) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - - Json::Value result = this->client->CallMethod("shhChanged",p); - if (result.isArray()) - return result; - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + p.append(param2); + p.append(param3); + Json::Value result = this->CallMethod("putString",p); + if (result.isBool()) + return result.asBool(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - int shhNewFilter(const Json::Value& param1) throw (jsonrpc::JsonRpcException) + std::string getString(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - - Json::Value result = this->client->CallMethod("shhNewFilter",p); - if (result.isInt()) - return result.asInt(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + p.append(param2); + Json::Value result = this->CallMethod("getString",p); + if (result.isString()) + return result.asString(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - bool shhUninstallFilter(const int& param1) throw (jsonrpc::JsonRpcException) + bool post(const Json::Value& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - - Json::Value result = this->client->CallMethod("shhUninstallFilter",p); - if (result.isBool()) - return result.asBool(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + Json::Value result = this->CallMethod("post",p); + if (result.isBool()) + return result.asBool(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - std::string stateAt(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) + std::string newIdentity() throw (jsonrpc::JsonRpcException) { Json::Value p; - p.append(param1); -p.append(param2); - - Json::Value result = this->client->CallMethod("stateAt",p); - if (result.isString()) - return result.asString(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + p = Json::nullValue; + Json::Value result = this->CallMethod("newIdentity",p); + if (result.isString()) + return result.asString(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - std::string transact(const Json::Value& param1) throw (jsonrpc::JsonRpcException) + bool haveIdentity(const std::string& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - - Json::Value result = this->client->CallMethod("transact",p); - if (result.isString()) - return result.asString(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + Json::Value result = this->CallMethod("haveIdentity",p); + if (result.isBool()) + return result.asBool(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - Json::Value transactionByHash(const std::string& param1, const int& param2) throw (jsonrpc::JsonRpcException) + std::string newGroup(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); -p.append(param2); - - Json::Value result = this->client->CallMethod("transactionByHash",p); - if (result.isObject()) - return result; - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + p.append(param2); + Json::Value result = this->CallMethod("newGroup",p); + if (result.isString()) + return result.asString(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - Json::Value transactionByNumber(const int& param1, const int& param2) throw (jsonrpc::JsonRpcException) + std::string addToGroup(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); -p.append(param2); - - Json::Value result = this->client->CallMethod("transactionByNumber",p); - if (result.isObject()) - return result; - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + p.append(param2); + Json::Value result = this->CallMethod("addToGroup",p); + if (result.isString()) + return result.asString(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - Json::Value uncleByHash(const std::string& param1, const int& param2) throw (jsonrpc::JsonRpcException) + int shhNewFilter(const Json::Value& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); -p.append(param2); - - Json::Value result = this->client->CallMethod("uncleByHash",p); - if (result.isObject()) - return result; - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + Json::Value result = this->CallMethod("shhNewFilter",p); + if (result.isInt()) + return result.asInt(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - Json::Value uncleByNumber(const int& param1, const int& param2) throw (jsonrpc::JsonRpcException) + bool shhUninstallFilter(const int& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); -p.append(param2); - - Json::Value result = this->client->CallMethod("uncleByNumber",p); - if (result.isObject()) - return result; - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + Json::Value result = this->CallMethod("shhUninstallFilter",p); + if (result.isBool()) + return result.asBool(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - bool uninstallFilter(const int& param1) throw (jsonrpc::JsonRpcException) + Json::Value shhChanged(const int& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - - Json::Value result = this->client->CallMethod("uninstallFilter",p); - if (result.isBool()) - return result.asBool(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - + Json::Value result = this->CallMethod("shhChanged",p); + if (result.isArray()) + return result; + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - - private: - jsonrpc::Client* client; }; -#endif //_WEBTHREESTUBCLIENT_H_ + +#endif //JSONRPC_CPP_WEBTHREESTUBCLIENT_H_ From 7c81eca7e0fbe8c53e4abf93a4c40e3eaacb45f4 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 3 Nov 2014 17:00:39 +0100 Subject: [PATCH 317/641] updated README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 23a202510..8b5ff903d 100644 --- a/README.md +++ b/README.md @@ -36,5 +36,5 @@ Please read [CodingStandards.txt](CodingStandards.txt) thoroughly before making libweb3jsonrpc/abstractwebthreestubserver.h is autogenerated from the jsonrpcstub executable that comes with the libjsonrpc library (json-rpc-cpp project). It shouldn't be maually altered. ```bash -jsonrpcstub -s -c spec.json WebThreeStub +jsonrpcstub spec.json --cpp-server=AbstractWebThreeStubServer ``` From fe303b4013790e65f9618b406a3b877cdccddd08 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Mon, 3 Nov 2014 16:04:31 +0000 Subject: [PATCH 318/641] (1) Handling evmcc options with boost::program_options. (2) Writing out .ll and .bc files --- evmcc/CMakeLists.txt | 5 +- evmcc/evmcc.cpp | 166 +++++++++++++++++++++++++++---------------- 2 files changed, 109 insertions(+), 62 deletions(-) diff --git a/evmcc/CMakeLists.txt b/evmcc/CMakeLists.txt index 230013aef..488893509 100644 --- a/evmcc/CMakeLists.txt +++ b/evmcc/CMakeLists.txt @@ -8,6 +8,7 @@ set(EXECUTABLE evmcc) add_executable(${EXECUTABLE} ${SRC_LIST}) +target_link_libraries(${EXECUTABLE} boost_program_options) target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} ethereum) @@ -40,8 +41,8 @@ message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") include_directories(${LLVM_INCLUDE_DIRS}) add_definitions(${LLVM_DEFINITIONS}) -# llvm_map_components_to_libnames(llvm_libs core support mcjit x86asmparser x86codegen) -# target_link_libraries(evmcc ${llvm_libs}) +llvm_map_components_to_libnames(llvm_libs bitwriter) +target_link_libraries(evmcc ${llvm_libs}) # end of LLVM specific commands diff --git a/evmcc/evmcc.cpp b/evmcc/evmcc.cpp index 191b87dcf..535a9aed9 100644 --- a/evmcc/evmcc.cpp +++ b/evmcc/evmcc.cpp @@ -7,6 +7,10 @@ #include #include +#include + +#include +#include #include #include @@ -15,67 +19,76 @@ #include -void show_usage() +void parseProgramOptions(int _argc, char** _argv, boost::program_options::variables_map& _varMap) { - // FIXME: Use arg[0] as program name? - std::cerr << "usage: evmcc (-b|-c|-d)+ \n"; -} + namespace opt = boost::program_options; + + opt::options_description explicitOpts("Allowed options"); + explicitOpts.add_options() + ("help,h", "show usage information") + ("compile,c", "compile the code to LLVM IR") + ("interpret,i", "compile the code to LLVM IR and execute") + ("gas,g", opt::value(), "set initial gas for execution") + ("disassemble,d", "dissassemble the code") + ("dump-cfg", "dump control flow graph to graphviz file") + ("optimize-stack,os", "optimize stack use between basic blocks") + ("output-ll", opt::value(), "dump generated LLVM IR to file") + ("output-bc", opt::value(), "dump generated LLVM bitcode to file") + ("verbose,V", "enable verbose output"); + + opt::options_description implicitOpts("Input files"); + implicitOpts.add_options() + ("input-file", opt::value(), "input file"); + + opt::options_description allOpts(""); + allOpts.add(explicitOpts).add(implicitOpts); + + opt::positional_options_description inputOpts; + inputOpts.add("input-file", 1); + + const char* errorMsg = nullptr; + try + { + auto parser = opt::command_line_parser(_argc, _argv).options(allOpts).positional(inputOpts); + opt::store(parser.run(), _varMap); + opt::notify(_varMap); + } + catch (boost::program_options::error& err) + { + errorMsg = err.what(); + } + if (!errorMsg && _varMap.count("input-file") == 0) + errorMsg = "missing input file name"; -int main(int argc, char** argv) -{ - std::string input_file; - bool opt_dissassemble = false; - bool opt_show_bytes = false; - bool opt_compile = false; - bool opt_interpret = false; - bool opt_dump_graph = false; - bool opt_unknown = false; - bool opt_verbose = false; - size_t initialGas = 10000; - - for (int i = 1; i < argc; i++) + if (_varMap.count("disassemble") == 0 + && _varMap.count("compile") == 0 + && _varMap.count("interpret") == 0) { - std::string option = argv[i]; - if (option == "-b") - opt_show_bytes = true; - else if (option == "-c") - opt_compile = true; - else if (option == "-d") - opt_dissassemble = true; - else if (option == "-i") - opt_interpret = true; - else if (option == "--dump-cfg") - opt_dump_graph = true; - else if (option == "-g" && i + 1 < argc) - { - std::string gasValue = argv[++i]; - initialGas = boost::lexical_cast(gasValue); - std::cerr << "Initial gas set to " << initialGas << "\n"; - } - else if (option == "-v") - opt_verbose = true; - else if (option[0] != '-' && input_file.empty()) - input_file = option; - else - { - opt_unknown = true; - break; - } + errorMsg = "at least one of -c, -i, -d is required"; } - if (opt_unknown || - input_file.empty() || - (!opt_show_bytes && !opt_compile && !opt_dissassemble && !opt_interpret)) + if (errorMsg || _varMap.count("help")) { - show_usage(); - exit(1); + if (errorMsg) + std::cerr << "Error: " << errorMsg << std::endl; + + std::cout << "Usage: " << _argv[0] << " input-file " << std::endl + << explicitOpts << std::endl; + std::exit(errorMsg ? 1 : 0); } +} + +int main(int argc, char** argv) +{ + boost::program_options::variables_map options; + parseProgramOptions(argc, argv, options); - std::ifstream ifs(input_file); + auto inputFile = options["input-file"].as(); + std::ifstream ifs(inputFile); if (!ifs.is_open()) { - std::cerr << "cannot open file " << input_file << std::endl; + std::cerr << "cannot open input file " << inputFile << std::endl; exit(1); } @@ -88,37 +101,70 @@ int main(int argc, char** argv) bytes bytecode = fromHex(src); - if (opt_show_bytes) - std::cout << memDump(bytecode) << std::endl; - - if (opt_dissassemble) + if (options.count("disassemble")) { std::string assembly = eth::disassemble(bytecode); std::cout << assembly << std::endl; } - if (opt_compile || opt_interpret) + if (options.count("compile") || options.count("interpret")) { + size_t initialGas = 10000; + + if (options.count("gas")) + initialGas = options["gas"].as(); + auto compilationStartTime = std::chrono::high_resolution_clock::now(); - eth::jit::Compiler::Options options; - options.dumpCFG = opt_dump_graph; + eth::jit::Compiler::Options compilerOptions; + compilerOptions.dumpCFG = options.count("dump-cfg") > 0; + compilerOptions.optimizeStack = options.count("optimize-stack") > 0; - auto compiler = eth::jit::Compiler(options); + auto compiler = eth::jit::Compiler(compilerOptions); auto module = compiler.compile({bytecode.data(), bytecode.size()}); auto compilationEndTime = std::chrono::high_resolution_clock::now(); module->dump(); - if (opt_verbose) + if (options.count("output-ll")) + { + auto outputFile = options["output-ll"].as(); + std::ofstream ofs(outputFile); + if (!ofs.is_open()) + { + std::cerr << "cannot open output file " << outputFile << std::endl; + exit(1); + } + llvm::raw_os_ostream ros(ofs); + module->print(ros, nullptr); + ofs.close(); + } + + if (options.count("output-bc")) + { + auto outputFile = options["output-bc"].as(); + std::ofstream ofs(outputFile); + if (!ofs.is_open()) + { + std::cerr << "cannot open output file " << outputFile << std::endl; + exit(1); + } + llvm::raw_os_ostream ros(ofs); + llvm::WriteBitcodeToFile(module.get(), ros); + ros.flush(); + ofs.close(); + } + + + if (options.count("verbose")) { std::cerr << "*** Compilation time: " << std::chrono::duration_cast(compilationEndTime - compilationStartTime).count() << std::endl; } - if (opt_interpret) + if (options.count("interpret")) { auto engine = eth::jit::ExecutionEngine(); u256 gas = initialGas; From 23c39172f8dc3072cd908724f92a1f4e6ef44187 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Tue, 4 Nov 2014 11:15:16 +0100 Subject: [PATCH 319/641] little cleanup after upgrading jsonrpc --- CMakeLists.txt | 4 +- cmake/EthDependenciesDeprecated.cmake | 68 ++++++++++++++------------- eth/CMakeLists.txt | 2 +- eth/main.cpp | 1 - libqethereum/CMakeLists.txt | 2 +- libqethereum/QEthereum.h | 1 - libweb3jsonrpc/CMakeLists.txt | 2 +- libweb3jsonrpc/CorsHttpServer.h | 1 - libweb3jsonrpc/WebThreeStubServer.h | 1 - neth/CMakeLists.txt | 2 +- test/CMakeLists.txt | 2 +- test/jsonrpc.cpp | 2 - 12 files changed, 42 insertions(+), 46 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b4aa2352f..5e99e1c41 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -119,7 +119,7 @@ endif() add_subdirectory(lllc) add_subdirectory(solc) add_subdirectory(sc) -if (JSONRPC_LS) +if (JSONRPC_SERVER_LS) add_subdirectory(libweb3jsonrpc) endif() if (NOT LANGUAGES) @@ -150,7 +150,7 @@ if (NOT LANGUAGES) if ("${TARGET_PLATFORM}" STREQUAL "w64") cmake_policy(SET CMP0020 NEW) endif () - if (NOT JSONRPC_LS) + if (NOT JSONRPC_SERVER_LS) message(FATAL_ERROR "Alethzero requires jsonrpc.") endif() diff --git a/cmake/EthDependenciesDeprecated.cmake b/cmake/EthDependenciesDeprecated.cmake index d815bef3e..8c6d07e48 100644 --- a/cmake/EthDependenciesDeprecated.cmake +++ b/cmake/EthDependenciesDeprecated.cmake @@ -125,48 +125,50 @@ else() message(STATUS "Failed to find the miniupnpc headers!") endif () - find_path( JSONRPC_ID jsonrpccpp/server.h - /usr/include - /usr/local/include - ) + find_path( JSONRPC_ID jsonrpccpp/server.h + /usr/include + /usr/local/include + ) if ( JSONRPC_ID ) message(STATUS "Found jsonrpc headers") - find_library( JSONRPC_LS NAMES jsonrpccpp-server + + find_library( JSONCPP_LS NAMES jsoncpp + /usr/lib + /usr/local/lib + /opt/local/lib + /usr/lib/*/ + ) + + find_library( JSONRPC_SERVER_LS NAMES jsonrpccpp-server PATHS /usr/lib /usr/local/lib /opt/local/lib /usr/lib/*/ ) - - find_library( JSONRPC_COMMON_LS NAMES jsonrpccpp-common - PATHS - /usr/lib - /usr/local/lib - /opt/local/lib - /usr/lib/*/ - ) - - find_library( JSONCPP_LS NAMES jsoncpp - /usr/lib - /usr/local/lib - /opt/local/lib - /usr/lib/*/ - ) - - find_library( JSONRPC_CLIENT_LS NAMES jsonrpccpp-client - PATHS - /usr/lib/ - /usr/local/lib - /opt/local/lib - /usr/lib/*/ - ) - - if ( JSONRPC_LS AND JSONRPC_COMMON_LS ) - message(STATUS "Found jsonrpc library: ${JSONRPC_LS}") - message(STATUS "Found jsonrpc-common library: ${JSONRPC_COMMON_LS}") - add_definitions(-DETH_JSONRPC) + + find_library( JSONRPC_COMMON_LS NAMES jsonrpccpp-common + PATHS + /usr/lib + /usr/local/lib + /opt/local/lib + /usr/lib/*/ + ) + + find_library( JSONRPC_CLIENT_LS NAMES jsonrpccpp-client + PATHS + /usr/lib/ + /usr/local/lib + /opt/local/lib + /usr/lib/*/ + ) + + if ( JSONRPC_SERVER_LS AND JSONRPC_COMMON_LS ) + message(STATUS "Found jsonrpc-server library: ${JSONRPC_SERVER_LS}") + message(STATUS "Found jsonrpc-client library: ${JSONRPC_CLIENT_LS}") + message(STATUS "Found jsonrpc-common library: ${JSONRPC_COMMON_LS}") + add_definitions(-DETH_JSONRPC) else () message(STATUS "Failed to find the jsonrpc library!") endif () diff --git a/eth/CMakeLists.txt b/eth/CMakeLists.txt index 7c997b256..1d6325ecc 100644 --- a/eth/CMakeLists.txt +++ b/eth/CMakeLists.txt @@ -17,7 +17,7 @@ if(MINIUPNPC_LS) endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS}) -if(JSONRPC_LS) +if(JSONRPC_SERVER_LS) target_link_libraries(${EXECUTABLE} web3jsonrpc) endif() if(READLINE_LS) diff --git a/eth/main.cpp b/eth/main.cpp index 447729c1a..25ebe5cdc 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -28,7 +28,6 @@ #include #include #if ETH_JSONRPC -//#include #include #endif #include diff --git a/libqethereum/CMakeLists.txt b/libqethereum/CMakeLists.txt index ba7cd3b67..709f7f066 100644 --- a/libqethereum/CMakeLists.txt +++ b/libqethereum/CMakeLists.txt @@ -59,7 +59,7 @@ endif() include_directories(/) qt5_use_modules(${EXECUTABLE} Core Gui WebKit WebKitWidgets Widgets Network Quick Qml) -target_link_libraries(${EXECUTABLE} ethereum secp256k1 ${CRYPTOPP_LS} ${JSONRPC_LS}) +target_link_libraries(${EXECUTABLE} ethereum secp256k1 ${CRYPTOPP_LS} ${JSONRPC_SERVER_LS}) if (APPLE) if (${ADDFRAMEWORKS}) diff --git a/libqethereum/QEthereum.h b/libqethereum/QEthereum.h index b4c17fdab..eeb5a493b 100644 --- a/libqethereum/QEthereum.h +++ b/libqethereum/QEthereum.h @@ -26,7 +26,6 @@ #include #include #include -//#include class QWebThree: public QObject { diff --git a/libweb3jsonrpc/CMakeLists.txt b/libweb3jsonrpc/CMakeLists.txt index 6966cd10a..ec8adbffb 100644 --- a/libweb3jsonrpc/CMakeLists.txt +++ b/libweb3jsonrpc/CMakeLists.txt @@ -24,8 +24,8 @@ endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS}) target_link_libraries(${EXECUTABLE} ${JSONCPP_LS}) -target_link_libraries(${EXECUTABLE} ${JSONRPC_LS}) target_link_libraries(${EXECUTABLE} ${JSONRPC_COMMON_LS}) +target_link_libraries(${EXECUTABLE} ${JSONRPC_SERVER_LS}) target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) if(READLINE_LS) target_link_libraries(${EXECUTABLE} ${READLINE_LS}) diff --git a/libweb3jsonrpc/CorsHttpServer.h b/libweb3jsonrpc/CorsHttpServer.h index 5dd3130a4..e697ecaa1 100644 --- a/libweb3jsonrpc/CorsHttpServer.h +++ b/libweb3jsonrpc/CorsHttpServer.h @@ -20,7 +20,6 @@ */ #include -//#include namespace jsonrpc { diff --git a/libweb3jsonrpc/WebThreeStubServer.h b/libweb3jsonrpc/WebThreeStubServer.h index 193f1f6ff..5a1f04d8e 100644 --- a/libweb3jsonrpc/WebThreeStubServer.h +++ b/libweb3jsonrpc/WebThreeStubServer.h @@ -29,7 +29,6 @@ #pragma warning(pop) #include -//#include #include #include #pragma GCC diagnostic push diff --git a/neth/CMakeLists.txt b/neth/CMakeLists.txt index ac275f663..d8b3d8f75 100644 --- a/neth/CMakeLists.txt +++ b/neth/CMakeLists.txt @@ -18,7 +18,7 @@ target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS}) -if(JSONRPC_LS) +if(JSONRPC_SERVER_LS) target_link_libraries(${EXECUTABLE} web3jsonrpc) endif() diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 63094fa23..52a73f84a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -16,7 +16,7 @@ target_link_libraries(testeth gmp) target_link_libraries(testeth solidity) target_link_libraries(testeth ${CRYPTOPP_LS}) target_link_libraries(testeth webthree) -if(JSONRPC_LS) +if(JSONRPC_SERVER_LS) target_link_libraries(testeth web3jsonrpc) target_link_libraries(testeth ${JSONRPC_CLIENT_LS}) endif() diff --git a/test/jsonrpc.cpp b/test/jsonrpc.cpp index f261a5164..1eee21357 100644 --- a/test/jsonrpc.cpp +++ b/test/jsonrpc.cpp @@ -31,8 +31,6 @@ #include #include #include -//#include -//#include #include #include "JsonSpiritHeaders.h" #include "TestHelper.h" From 874abf6e0b16f892f11d93b4ea2f595ced11623f Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Tue, 4 Nov 2014 12:03:24 +0100 Subject: [PATCH 320/641] fixed WebThreeStubServer constructor --- alethzero/MainWin.cpp | 2 +- eth/main.cpp | 9 ++++++--- libweb3jsonrpc/WebThreeStubServer.cpp | 4 ++-- libweb3jsonrpc/WebThreeStubServer.h | 2 +- neth/main.cpp | 7 +++++-- test/jsonrpc.cpp | 4 +++- third/MainWin.cpp | 2 +- 7 files changed, 19 insertions(+), 11 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index f413532b7..46d09f8c1 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -149,7 +149,7 @@ Main::Main(QWidget *parent) : m_webThree.reset(new WebThreeDirect(string("AlethZero/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir() + "/AlethZero", false, {"eth", "shh"})); - m_server = unique_ptr(new WebThreeStubServer(&m_qwebConnector, *web3(), keysAsVector(m_myKeys))); + m_server = unique_ptr(new WebThreeStubServer(m_qwebConnector, *web3(), keysAsVector(m_myKeys))); m_server->setIdentities(keysAsVector(owned())); m_server->StartListening(); diff --git a/eth/main.cpp b/eth/main.cpp index 25ebe5cdc..fb9e7e4a0 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -336,10 +336,12 @@ int main(int argc, char** argv) web3.connect(remoteHost, remotePort); #if ETH_JSONRPC - auto_ptr jsonrpcServer; + unique_ptr jsonrpcServer; + unique_ptr jsonrpcConnector; if (jsonrpc > -1) { - jsonrpcServer = auto_ptr(new WebThreeStubServer(new jsonrpc::CorsHttpServer(jsonrpc), web3, {us})); + jsonrpcConnector = unique_ptr(new jsonrpc::CorsHttpServer(jsonrpc)); + jsonrpcServer = unique_ptr(new WebThreeStubServer(*jsonrpcConnector.get(), web3, {us})); jsonrpcServer->setIdentities({us}); jsonrpcServer->StartListening(); } @@ -427,7 +429,8 @@ int main(int argc, char** argv) { if (jsonrpc < 0) jsonrpc = 8080; - jsonrpcServer = auto_ptr(new WebThreeStubServer(new jsonrpc::CorsHttpServer(jsonrpc), web3, {us})); + jsonrpcConnector = unique_ptr(new jsonrpc::CorsHttpServer(jsonrpc)); + jsonrpcServer = auto_ptr(new WebThreeStubServer(*jsonrpcConnector.get(), web3, {us})); jsonrpcServer->setIdentities({us}); jsonrpcServer->StartListening(); } diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index ed5907f53..aacc64a4e 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -216,8 +216,8 @@ static Json::Value toJson(h256 const& _h, shh::Envelope const& _e, shh::Message } -WebThreeStubServer::WebThreeStubServer(jsonrpc::AbstractServerConnector* _conn, WebThreeDirect& _web3, std::vector const& _accounts): - AbstractWebThreeStubServer(*_conn), +WebThreeStubServer::WebThreeStubServer(jsonrpc::AbstractServerConnector& _conn, WebThreeDirect& _web3, std::vector const& _accounts): + AbstractWebThreeStubServer(_conn), m_web3(_web3) { setAccounts(_accounts); diff --git a/libweb3jsonrpc/WebThreeStubServer.h b/libweb3jsonrpc/WebThreeStubServer.h index 5a1f04d8e..f6b5cb224 100644 --- a/libweb3jsonrpc/WebThreeStubServer.h +++ b/libweb3jsonrpc/WebThreeStubServer.h @@ -60,7 +60,7 @@ class Interface; class WebThreeStubServer: public AbstractWebThreeStubServer { public: - WebThreeStubServer(jsonrpc::AbstractServerConnector* _conn, dev::WebThreeDirect& _web3, std::vector const& _accounts); + WebThreeStubServer(jsonrpc::AbstractServerConnector& _conn, dev::WebThreeDirect& _web3, std::vector const& _accounts); virtual std::string account(); virtual Json::Value accounts(); diff --git a/neth/main.cpp b/neth/main.cpp index 8512cf77b..b2b9a155f 100644 --- a/neth/main.cpp +++ b/neth/main.cpp @@ -476,9 +476,11 @@ int main(int argc, char** argv) #if ETH_JSONRPC auto_ptr jsonrpcServer; + unique_ptr jsonrpcConnector; if (jsonrpc > -1) { - jsonrpcServer = auto_ptr(new WebThreeStubServer(new jsonrpc::HttpServer(jsonrpc), web3, {us})); + jsonrpcConnector = unique_ptr(new jsonrpc::HttpServer(jsonrpc)); + jsonrpcServer = auto_ptr(new WebThreeStubServer(*jsonrpcConnector.get(), web3, {us})); jsonrpcServer->setIdentities({us}); jsonrpcServer->StartListening(); } @@ -552,7 +554,8 @@ int main(int argc, char** argv) { if (jsonrpc < 0) jsonrpc = 8080; - jsonrpcServer = auto_ptr(new WebThreeStubServer(new jsonrpc::HttpServer(jsonrpc), web3, {us})); + jsonrpcConnector = unique_ptr(new jsonrpc::HttpServer(jsonrpc)); + jsonrpcServer = auto_ptr(new WebThreeStubServer(*jsonrpcConnector.get(), web3, {us})); jsonrpcServer->setIdentities({us}); jsonrpcServer->StartListening(); } diff --git a/test/jsonrpc.cpp b/test/jsonrpc.cpp index 1eee21357..80c4f5018 100644 --- a/test/jsonrpc.cpp +++ b/test/jsonrpc.cpp @@ -54,6 +54,7 @@ dev::WebThreeDirect web3(name, dbPath, true, s, np); unique_ptr jsonrpcServer; unique_ptr jsonrpcClient; +unique_ptr jsonrpcConnector; jsonrpc::HttpClient httpClient("http://localhost:8080"); struct JsonrpcFixture { @@ -63,7 +64,8 @@ struct JsonrpcFixture { web3.setIdealPeerCount(5); web3.ethereum()->setForceMining(true); - jsonrpcServer = unique_ptr(new WebThreeStubServer(new jsonrpc::CorsHttpServer(8080), web3, {})); + jsonrpcConnector = unique_ptr(new jsonrpc::CorsHttpServer(8080)); + jsonrpcServer = unique_ptr(new WebThreeStubServer(*jsonrpcConnector.get(), web3, {})); jsonrpcServer->setIdentities({}); jsonrpcServer->StartListening(); diff --git a/third/MainWin.cpp b/third/MainWin.cpp index c2dcb7ce2..7be9d8db3 100644 --- a/third/MainWin.cpp +++ b/third/MainWin.cpp @@ -117,7 +117,7 @@ Main::Main(QWidget *parent) : m_web3.reset(new WebThreeDirect("Third", getDataDir() + "/Third", false, {"eth", "shh"})); m_web3->connect(Host::pocHost()); - m_server = unique_ptr(new WebThreeStubServer(&m_qwebConnector, *web3(), keysAsVector(m_myKeys))); + m_server = unique_ptr(new WebThreeStubServer(m_qwebConnector, *web3(), keysAsVector(m_myKeys))); m_server->setIdentities(keysAsVector(owned())); m_server->StartListening(); From 851bae4dd56244d1fb7cd0b8575a47293cb5e76d Mon Sep 17 00:00:00 2001 From: sveneh Date: Tue, 4 Nov 2014 17:03:12 +0100 Subject: [PATCH 321/641] Test to bring in dependencies via CMake ExternalProject. Testing for libcryptopp only --- cmake/EthDependenciesDeprecated.cmake | 39 +++++++++++++-------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/cmake/EthDependenciesDeprecated.cmake b/cmake/EthDependenciesDeprecated.cmake index d1c51f6c4..06e3285c4 100644 --- a/cmake/EthDependenciesDeprecated.cmake +++ b/cmake/EthDependenciesDeprecated.cmake @@ -3,6 +3,19 @@ # deprecated. TODO will rewrite to proper CMake packages +include(ExternalProject) + +ExternalProject_Add(project_cryptopp + URL http://www.cryptopp.com/cryptopp562.zip + BINARY_DIR project_cryptopp-prefix/src/project_cryptopp + CONFIGURE_COMMAND "" + BUILD_COMMAND make -j 3 + INSTALL_COMMAND "" +) + + + + if("${TARGET_PLATFORM}" STREQUAL "w64") # set(MINIUPNPC_LS /usr/x86_64-w64-mingw32/lib/libminiupnpc.a) @@ -11,24 +24,9 @@ if("${TARGET_PLATFORM}" STREQUAL "w64") set(CRYPTOPP_ID /usr/x86_64-w64-mingw32/include/cryptopp) else() # Look for available Crypto++ version and if it is >= 5.6.2 - find_path(ID cryptlib.h - ../cryptopp/src - ../../cryptopp/src - /usr/include/cryptopp - /usr/include/crypto++ - /usr/local/include/cryptopp - /usr/local/include/crypto++ - /opt/local/include/cryptopp - /opt/local/include/crypto++ - ) - find_library(LS NAMES cryptoppeth cryptopp - ../cryptopp/src/../target/build/release - ../../cryptopp/src/../target/build/release - PATHS - /usr/lib - /usr/local/lib - /opt/local/lib - ) + + set(CRYPTOPP_ID ${CMAKE_CURRENT_BINARY_DIR}/project_cryptopp-prefix/src/project_cryptopp) + set(CRYPTOPP_LS cryptopp) if (ID AND LS) message(STATUS "Found Crypto++: ${ID}, ${LS}") @@ -180,9 +178,8 @@ else() set(QTQML 1) endif() -if(CRYPTOPP_ID) - include_directories(${CRYPTOPP_ID}) -endif() +include_directories(${CRYPTOPP_ID}) + if(PYTHON_ID) include_directories(${PYTHON_ID}) endif() From e33517a47d1b417df036cd5650d53b68181126f4 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Tue, 4 Nov 2014 19:45:33 +0100 Subject: [PATCH 322/641] cryptopp as external project --- cmake/EthDependenciesDeprecated.cmake | 15 ++++++--------- libdevcrypto/CMakeLists.txt | 1 + 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/cmake/EthDependenciesDeprecated.cmake b/cmake/EthDependenciesDeprecated.cmake index 06e3285c4..a87553dc1 100644 --- a/cmake/EthDependenciesDeprecated.cmake +++ b/cmake/EthDependenciesDeprecated.cmake @@ -6,17 +6,13 @@ include(ExternalProject) ExternalProject_Add(project_cryptopp - URL http://www.cryptopp.com/cryptopp562.zip - BINARY_DIR project_cryptopp-prefix/src/project_cryptopp - CONFIGURE_COMMAND "" - BUILD_COMMAND make -j 3 - INSTALL_COMMAND "" + URL http://www.cryptopp.com/cryptopp562.zip + BINARY_DIR project_cryptopp-prefix/src/project_cryptopp + CONFIGURE_COMMAND "" + BUILD_COMMAND make -j 3 + INSTALL_COMMAND "" ) - - - - if("${TARGET_PLATFORM}" STREQUAL "w64") # set(MINIUPNPC_LS /usr/x86_64-w64-mingw32/lib/libminiupnpc.a) set(LEVELDB_LS leveldb) @@ -27,6 +23,7 @@ else() set(CRYPTOPP_ID ${CMAKE_CURRENT_BINARY_DIR}/project_cryptopp-prefix/src/project_cryptopp) set(CRYPTOPP_LS cryptopp) + link_directories(${CMAKE_CURRENT_BINARY_DIR}/project_cryptopp-prefix/src/project_cryptopp) if (ID AND LS) message(STATUS "Found Crypto++: ${ID}, ${LS}") diff --git a/libdevcrypto/CMakeLists.txt b/libdevcrypto/CMakeLists.txt index e7f112f95..d9b0c96c9 100644 --- a/libdevcrypto/CMakeLists.txt +++ b/libdevcrypto/CMakeLists.txt @@ -15,6 +15,7 @@ file(GLOB HEADERS "*.h") include_directories(..) +add_dependencies(${EXECUTABLE} project_cryptopp) target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} secp256k1) target_link_libraries(${EXECUTABLE} gmp) From 99abfb03e08269d3e7594ed861d55c95e0fa8ec8 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Tue, 4 Nov 2014 22:02:11 +0000 Subject: [PATCH 323/641] fixed bug in llvm ir computing required memory size --- libevmjit/Memory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libevmjit/Memory.cpp b/libevmjit/Memory.cpp index c3e904ef8..89cef4d48 100644 --- a/libevmjit/Memory.cpp +++ b/libevmjit/Memory.cpp @@ -74,7 +74,7 @@ llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _ auto sizeRequired = m_builder.CreateExtractValue(uaddRes, 0, "sizeReq"); auto overflow1 = m_builder.CreateExtractValue(uaddRes, 1, "overflow1"); auto currSize = m_builder.CreateLoad(m_size, "currSize"); - auto tooSmall = m_builder.CreateICmpULE(size, sizeRequired, "tooSmall"); + auto tooSmall = m_builder.CreateICmpULE(currSize, sizeRequired, "tooSmall"); auto resizeNeeded = m_builder.CreateOr(tooSmall, overflow1, "resizeNeeded"); m_builder.CreateCondBr(resizeNeeded, resizeBB, returnBB); // OPT branch weights? From cb82c778519856ae51aa433c40d4c04577f4cded Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 5 Nov 2014 12:07:44 +0100 Subject: [PATCH 324/641] extdep dir --- extdep/CMakeLists.txt | 3 +++ extdep/cryptopp.cmake | 11 +++++++++++ 2 files changed, 14 insertions(+) create mode 100644 extdep/CMakeLists.txt create mode 100644 extdep/cryptopp.cmake diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt new file mode 100644 index 000000000..8ee232835 --- /dev/null +++ b/extdep/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.0) + +include(cryptopp.cmake) diff --git a/extdep/cryptopp.cmake b/extdep/cryptopp.cmake new file mode 100644 index 000000000..4e4ee85d7 --- /dev/null +++ b/extdep/cryptopp.cmake @@ -0,0 +1,11 @@ +include(ExternalProject) + +ExternalProject_Add(cryptopp + URL http://www.cryptopp.com/cryptopp562.zip + BINARY_DIR cryptopp-prefix/src/cryptopp + CONFIGURE_COMMAND "" + BUILD_COMMAND make -j 3 + INSTALL_COMMAND "" + ) + + From e88f8e72ed5cd5273452dd96272a711a9dbb2641 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 5 Nov 2014 12:14:49 +0100 Subject: [PATCH 325/641] miniupnpc cmake --- extdep/CMakeLists.txt | 2 ++ extdep/miniupnpc.cmake | 11 +++++++++++ 2 files changed, 13 insertions(+) create mode 100644 extdep/miniupnpc.cmake diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index 8ee232835..bcf906661 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -1,3 +1,5 @@ cmake_minimum_required(VERSION 3.0) include(cryptopp.cmake) +include(miniupnpc.cmake) + diff --git a/extdep/miniupnpc.cmake b/extdep/miniupnpc.cmake new file mode 100644 index 000000000..ae79f6369 --- /dev/null +++ b/extdep/miniupnpc.cmake @@ -0,0 +1,11 @@ +include(ExternalProject) + +ExternalProject_Add(miniupnpc + URL http://miniupnp.tuxfamily.org/files/download.php?file=miniupnpc-1.9.20141027.tar.gz + BINARY_DIR miniupnpc-prefix/src/miniupnpc + CONFIGURE_COMMAND "" + BUILD_COMMAND make -j 3 + INSTALL_COMMAND "" + ) + + From 54f4710bba7b632b03c32cb3738130d473a609d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 5 Nov 2014 12:37:37 +0100 Subject: [PATCH 326/641] Add LLVMBitWriter.lib to dependencies on Visual Studio --- windows/LLVM.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/windows/LLVM.props b/windows/LLVM.props index 7a779144b..a4e6f2c0f 100644 --- a/windows/LLVM.props +++ b/windows/LLVM.props @@ -7,7 +7,7 @@ ../../_build/llvm/$(Platform) $(LLVMSrcDir)\include;$(LLVMBuildDir)\include $(LLVMBuildDir)\$(Configuration)\lib - LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib + LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMBitWriter.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib From ba26796dbe45a971aeb235043ddc50bab59a0793 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 5 Nov 2014 12:38:30 +0100 Subject: [PATCH 327/641] Build boost/program_options on Windows --- windows/bootstrap.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/windows/bootstrap.sh b/windows/bootstrap.sh index 642c3f5c8..cd8e84086 100644 --- a/windows/bootstrap.sh +++ b/windows/bootstrap.sh @@ -152,7 +152,7 @@ compile_boost() fi if [ ! -d "stage/$platform" ]; then - targets="--with-filesystem --with-system --with-thread --with-date_time --with-regex --with-test" + targets="--with-filesystem --with-system --with-thread --with-date_time --with-regex --with-test --with-program_options" (set -x; ./b2 -j4 --build-type=complete link=static runtime-link=shared variant=debug,release threading=multi $addressModel $targets stage) (set -x; mv stage/lib stage/$platform) fi From 2a0aa9cd5a0b1571ccb10c95f2ceecadc2c3105d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 5 Nov 2014 12:38:51 +0100 Subject: [PATCH 328/641] Clean up evmcc.vcxproj --- windows/evmcc.vcxproj | 3 --- 1 file changed, 3 deletions(-) diff --git a/windows/evmcc.vcxproj b/windows/evmcc.vcxproj index 1448bb5a8..e7bf633fa 100644 --- a/windows/evmcc.vcxproj +++ b/windows/evmcc.vcxproj @@ -119,7 +119,6 @@ Console true - LibEthereum.lib;LibEvmJit.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) @@ -138,7 +137,6 @@ Console true - %(AdditionalDependencies) @@ -158,7 +156,6 @@ true true true - LibEthereum.lib;LibEvmJit.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) From e5186e5c546ba60ed5803dcf2cbed4fe938069f5 Mon Sep 17 00:00:00 2001 From: sveneh Date: Thu, 6 Nov 2014 10:33:13 +0100 Subject: [PATCH 329/641] Initial change to support external dependency management via cmake. Proof of work, just for crypto++ dependency. Not yet functional. --- cmake/FindCryptoPP.cmake | 107 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 cmake/FindCryptoPP.cmake diff --git a/cmake/FindCryptoPP.cmake b/cmake/FindCryptoPP.cmake new file mode 100644 index 000000000..8fc743075 --- /dev/null +++ b/cmake/FindCryptoPP.cmake @@ -0,0 +1,107 @@ +# Module for locating the CryptoPP encryption library. +# +# Cutomizable variables: +# CRYPTOPP_ROOT_DIR +# This variable points to the CryptoPP root directory. On Windows the +# library location typically will have to be provided explicitly using the +# -D command-line option. The directory should include the include/cryptopp, +# lib and/or bin sub-directories. +# +# Read-Only variables: +# CRYPTOPP_FOUND +# Indicates that the library has been found. +# +# CRYPTOPP_INCLUDE_DIR +# Points to the CryptoPP include directory. +# +# CRYPTOPP_LIBRARIES +# Points to the CryptoPP libraries that should be passed to +# target_link_libararies. +# +# Copyright (c) 2010-2011 Sergiu Dotenco +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +INCLUDE (FindPackageHandleStandardArgs) + +SET (_CRYPTOPP_POSSIBLE_DIRS ${CRYPTOPP_ROOT_DIR}) +SET (_CRYPTOPP_POSSIBLE_INCLUDE_SUFFIXES include) +SET (_CRYPTOPP_POSSIBLE_LIB_SUFFIXES /lib /lib64) + +FIND_PATH (CRYPTOPP_ROOT_DIR + NAMES include/cryptopp/cryptlib.h + PATHS ${_CRYPTOPP_POSSIBLE_DIRS} + DOC "CryptoPP root directory") + +# Re-use the previous path: +FIND_PATH (CRYPTOPP_INCLUDE_DIR + NAMES cryptopp/cryptlib.h + PATHS ${CRYPTOPP_ROOT_DIR} + PATH_SUFFIXES ${_CRYPTOPP_POSSIBLE_INCLUDE_SUFFIXES} + DOC "CryptoPP include directory") + + FIND_LIBRARY (CRYPTOPP_LIBRARIES + NAMES cryptlib cryptopp libcryptopp + PATHS /usr/lib + PATH_SUFFIXES "" lib64) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS (CryptoPP DEFAULT_MSG CRYPTOPP_INCLUDE_DIR + CRYPTOPP_LIBRARIES) + +IF (CRYPTOPP_FOUND) + FILE (STRINGS ${CRYPTOPP_INCLUDE_DIR}/cryptopp/config.h + _CRYPTOPP_VERSION_TMP REGEX "^#define CRYPTOPP_VERSION[ \t]+[0-9]+$") + + STRING (REGEX REPLACE + "^#define CRYPTOPP_VERSION[ \t]+([0-9]+)" "\\1" _CRYPTOPP_VERSION_TMP + ${_CRYPTOPP_VERSION_TMP}) + + STRING (REGEX REPLACE "([0-9]+)[0-9][0-9]" "\\1" CRYPTOPP_VERSION_MAJOR + ${_CRYPTOPP_VERSION_TMP}) + STRING (REGEX REPLACE "[0-9]([0-9])[0-9]" "\\1" CRYPTOPP_VERSION_MINOR + ${_CRYPTOPP_VERSION_TMP}) + STRING (REGEX REPLACE "[0-9][0-9]([0-9])" "\\1" CRYPTOPP_VERSION_PATCH + ${_CRYPTOPP_VERSION_TMP}) + + SET (CRYPTOPP_VERSION_COUNT 3) + SET (CRYPTOPP_VERSION + ${CRYPTOPP_VERSION_MAJOR}.${CRYPTOPP_VERSION_MINOR}.${CRYPTOPP_VERSION_PATCH}) +ENDIF (CRYPTOPP_FOUND) + +IF (CRYPTOPP_FOUND) + IF (NOT CRYPTOPP_CACHED) + IF (NOT PACKAGE_FIND_QUIETLY) + MESSAGE (STATUS "CryptoPP version: ${CRYPTOPP_VERSION}") + ENDIF (NOT PACKAGE_FIND_QUIETLY) + + SET (CRYPTOPP_CACHED TRUE CACHE INTERNAL "" FORCE) + ENDIF (NOT CRYPTOPP_CACHED) +ELSE (CRYPTOPP_FOUND) + SET (CRYPTOPP_CACHED FALSE CACHE INTERNAL "" FORCE) + + IF (NOT PACKAGE_FIND_QUIETLY) + IF (PACKAGE_FIND_REQUIRED) + MESSAGE (FATAL_ERROR + "CryptoPP required but some files were not found. " + "Specify the CryptPP location using CRYPTOPP_ROOT_DIR") + ENDIF (PACKAGE_FIND_REQUIRED) + ENDIF (NOT PACKAGE_FIND_QUIETLY) +ENDIF (CRYPTOPP_FOUND) + +MARK_AS_ADVANCED (CRYPTOPP_INCLUDE_DIR CRYPTOPP_LIBRARIES) From 26d57961b4daa9b3f6cf27010f87970d80739fd9 Mon Sep 17 00:00:00 2001 From: sveneh Date: Thu, 6 Nov 2014 10:41:37 +0100 Subject: [PATCH 330/641] ... addition to last commit, these were lost. --- .gitignore | 2 + CMakeLists.txt | 24 +++--- cmake/EthDependenciesDeprecated.cmake | 35 --------- cmake/FindCryptoPP.cmake | 109 +++++++++++++------------- extdep/CMakeLists.txt | 10 ++- extdep/cryptopp.cmake | 12 +-- libdevcrypto/CMakeLists.txt | 6 +- libdevcrypto/CryptoPP.h | 24 +++--- libdevcrypto/EC.cpp | 4 +- libethcore/CMakeLists.txt | 2 +- test/CMakeLists.txt | 4 +- 11 files changed, 106 insertions(+), 126 deletions(-) diff --git a/.gitignore b/.gitignore index b38a3f1e3..ca18feb5b 100644 --- a/.gitignore +++ b/.gitignore @@ -29,7 +29,9 @@ build_xc *.user.* *~ +# build system build.*/ +extdep/install *.pyc diff --git a/CMakeLists.txt b/CMakeLists.txt index b4aa2352f..8d2ea151f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,17 @@ function(configureProject) endfunction() +# all dependencies that are not directly included in the cpp-ethereum distribution are defined here +# for this to work, download the dependency via the cmake script in extdep or install them manually! +function(checkExternalDependencies) + set(ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/extdep/install") + + set (CRYPTOPP_ROOT_DIR ${ETH_DEPENDENCY_INSTALL_DIR}) + find_package (CryptoPP 5.6.2 REQUIRED) +endfunction() + + + function(createBuildInfo) # Set build platform; to be written to BuildInfo.h if (CMAKE_COMPILER_IS_MINGW) @@ -66,6 +77,8 @@ function(createBuildInfo) set(SRC_LIST BuildInfo.h) endfunction() + + ###################################################################################################### @@ -88,19 +101,12 @@ if ("${TARGET_PLATFORM}" STREQUAL "linux") set(CMAKE_THREAD_LIBS_INIT pthread) endif () -# Set default build type to Release w/debug info -# if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE) -# set(CMAKE_BUILD_TYPE RelWithDebInfo) -# endif() - - include(EthCompilerSettings) message("-- CXXFLAGS: ${CMAKE_CXX_FLAGS}") -#add_definitions("-DETH_BUILD_TYPE=${ETH_BUILD_TYPE}") -#add_definitions("-DETH_BUILD_PLATFORM=${ETH_BUILD_PLATFORM}") - +checkExternalDependencies() +# TODO this will go away soon! include(EthDependenciesDeprecated) createBuildInfo() diff --git a/cmake/EthDependenciesDeprecated.cmake b/cmake/EthDependenciesDeprecated.cmake index a87553dc1..87a981fc9 100644 --- a/cmake/EthDependenciesDeprecated.cmake +++ b/cmake/EthDependenciesDeprecated.cmake @@ -3,45 +3,10 @@ # deprecated. TODO will rewrite to proper CMake packages -include(ExternalProject) - -ExternalProject_Add(project_cryptopp - URL http://www.cryptopp.com/cryptopp562.zip - BINARY_DIR project_cryptopp-prefix/src/project_cryptopp - CONFIGURE_COMMAND "" - BUILD_COMMAND make -j 3 - INSTALL_COMMAND "" -) - if("${TARGET_PLATFORM}" STREQUAL "w64") # set(MINIUPNPC_LS /usr/x86_64-w64-mingw32/lib/libminiupnpc.a) set(LEVELDB_LS leveldb) - set(CRYPTOPP_LS cryptopp) - set(CRYPTOPP_ID /usr/x86_64-w64-mingw32/include/cryptopp) else() - # Look for available Crypto++ version and if it is >= 5.6.2 - - set(CRYPTOPP_ID ${CMAKE_CURRENT_BINARY_DIR}/project_cryptopp-prefix/src/project_cryptopp) - set(CRYPTOPP_LS cryptopp) - link_directories(${CMAKE_CURRENT_BINARY_DIR}/project_cryptopp-prefix/src/project_cryptopp) - - if (ID AND LS) - message(STATUS "Found Crypto++: ${ID}, ${LS}") - set(_CRYPTOPP_VERSION_HEADER ${ID}/config.h) - if(EXISTS ${_CRYPTOPP_VERSION_HEADER}) - file(STRINGS ${_CRYPTOPP_VERSION_HEADER} _CRYPTOPP_VERSION REGEX "^#define CRYPTOPP_VERSION[ \t]+[0-9]+$") - string(REGEX REPLACE "^#define CRYPTOPP_VERSION[ \t]+([0-9]+)" "\\1" _CRYPTOPP_VERSION ${_CRYPTOPP_VERSION}) - if(${_CRYPTOPP_VERSION} LESS 562) - message(FATAL_ERROR "Crypto++ version found is smaller than 5.6.2.") - else() - set(CRYPTOPP_ID ${ID} CACHE FILEPATH "") - set(CRYPTOPP_LS ${LS} CACHE FILEPATH "") - message(STATUS "Crypto++ found and version greater or equal to 5.6.2") - endif() - endif() - else() - message(STATUS "Crypto++ Not Found: ${CRYPTOPP_ID}, ${CRYPTOPP_LS}") - endif() find_path( LEVELDB_ID leveldb/db.h /usr/include diff --git a/cmake/FindCryptoPP.cmake b/cmake/FindCryptoPP.cmake index 8fc743075..74a01e83a 100644 --- a/cmake/FindCryptoPP.cmake +++ b/cmake/FindCryptoPP.cmake @@ -1,24 +1,25 @@ -# Module for locating the CryptoPP encryption library. +# Module for locating the Crypto++ encryption library. # -# Cutomizable variables: +# Customizable variables: # CRYPTOPP_ROOT_DIR # This variable points to the CryptoPP root directory. On Windows the # library location typically will have to be provided explicitly using the # -D command-line option. The directory should include the include/cryptopp, # lib and/or bin sub-directories. # -# Read-Only variables: +# Read-only variables: # CRYPTOPP_FOUND -# Indicates that the library has been found. +# Indicates whether the library has been found. # -# CRYPTOPP_INCLUDE_DIR +# CRYPTOPP_INCLUDE_DIRS # Points to the CryptoPP include directory. # # CRYPTOPP_LIBRARIES # Points to the CryptoPP libraries that should be passed to # target_link_libararies. # -# Copyright (c) 2010-2011 Sergiu Dotenco +# +# Copyright (c) 2012 Sergiu Dotenco # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -40,68 +41,68 @@ INCLUDE (FindPackageHandleStandardArgs) -SET (_CRYPTOPP_POSSIBLE_DIRS ${CRYPTOPP_ROOT_DIR}) -SET (_CRYPTOPP_POSSIBLE_INCLUDE_SUFFIXES include) -SET (_CRYPTOPP_POSSIBLE_LIB_SUFFIXES /lib /lib64) - FIND_PATH (CRYPTOPP_ROOT_DIR - NAMES include/cryptopp/cryptlib.h - PATHS ${_CRYPTOPP_POSSIBLE_DIRS} + NAMES cryptopp/cryptlib.h include/cryptopp/cryptlib.h + PATHS ENV CRYPTOPPROOT DOC "CryptoPP root directory") # Re-use the previous path: FIND_PATH (CRYPTOPP_INCLUDE_DIR NAMES cryptopp/cryptlib.h - PATHS ${CRYPTOPP_ROOT_DIR} - PATH_SUFFIXES ${_CRYPTOPP_POSSIBLE_INCLUDE_SUFFIXES} + HINTS ${CRYPTOPP_ROOT_DIR} + PATH_SUFFIXES include DOC "CryptoPP include directory") - FIND_LIBRARY (CRYPTOPP_LIBRARIES - NAMES cryptlib cryptopp libcryptopp - PATHS /usr/lib - PATH_SUFFIXES "" lib64) +FIND_LIBRARY (CRYPTOPP_LIBRARY_DEBUG + NAMES cryptlibd cryptoppd + HINTS ${CRYPTOPP_ROOT_DIR} + PATH_SUFFIXES lib + DOC "CryptoPP debug library") + +FIND_LIBRARY (CRYPTOPP_LIBRARY_RELEASE + NAMES cryptlib cryptopp + HINTS ${CRYPTOPP_ROOT_DIR} + PATH_SUFFIXES lib + DOC "CryptoPP release library") -FIND_PACKAGE_HANDLE_STANDARD_ARGS (CryptoPP DEFAULT_MSG CRYPTOPP_INCLUDE_DIR - CRYPTOPP_LIBRARIES) +IF (CRYPTOPP_LIBRARY_DEBUG AND CRYPTOPP_LIBRARY_RELEASE) + SET (CRYPTOPP_LIBRARY + optimized ${CRYPTOPP_LIBRARY_RELEASE} + debug ${CRYPTOPP_LIBRARY_DEBUG} CACHE DOC "CryptoPP library") +ELSEIF (CRYPTOPP_LIBRARY_RELEASE) + SET (CRYPTOPP_LIBRARY ${CRYPTOPP_LIBRARY_RELEASE} CACHE DOC + "CryptoPP library") +ENDIF (CRYPTOPP_LIBRARY_DEBUG AND CRYPTOPP_LIBRARY_RELEASE) -IF (CRYPTOPP_FOUND) - FILE (STRINGS ${CRYPTOPP_INCLUDE_DIR}/cryptopp/config.h - _CRYPTOPP_VERSION_TMP REGEX "^#define CRYPTOPP_VERSION[ \t]+[0-9]+$") +IF (CRYPTOPP_INCLUDE_DIR) + SET (_CRYPTOPP_VERSION_HEADER ${CRYPTOPP_INCLUDE_DIR}/cryptopp/config.h) - STRING (REGEX REPLACE - "^#define CRYPTOPP_VERSION[ \t]+([0-9]+)" "\\1" _CRYPTOPP_VERSION_TMP - ${_CRYPTOPP_VERSION_TMP}) + IF (EXISTS ${_CRYPTOPP_VERSION_HEADER}) + FILE (STRINGS ${_CRYPTOPP_VERSION_HEADER} _CRYPTOPP_VERSION_TMP REGEX + "^#define CRYPTOPP_VERSION[ \t]+[0-9]+$") - STRING (REGEX REPLACE "([0-9]+)[0-9][0-9]" "\\1" CRYPTOPP_VERSION_MAJOR - ${_CRYPTOPP_VERSION_TMP}) - STRING (REGEX REPLACE "[0-9]([0-9])[0-9]" "\\1" CRYPTOPP_VERSION_MINOR - ${_CRYPTOPP_VERSION_TMP}) - STRING (REGEX REPLACE "[0-9][0-9]([0-9])" "\\1" CRYPTOPP_VERSION_PATCH - ${_CRYPTOPP_VERSION_TMP}) + STRING (REGEX REPLACE + "^#define CRYPTOPP_VERSION[ \t]+([0-9]+)" "\\1" _CRYPTOPP_VERSION_TMP + ${_CRYPTOPP_VERSION_TMP}) - SET (CRYPTOPP_VERSION_COUNT 3) - SET (CRYPTOPP_VERSION - ${CRYPTOPP_VERSION_MAJOR}.${CRYPTOPP_VERSION_MINOR}.${CRYPTOPP_VERSION_PATCH}) -ENDIF (CRYPTOPP_FOUND) + STRING (REGEX REPLACE "([0-9]+)[0-9][0-9]" "\\1" CRYPTOPP_VERSION_MAJOR + ${_CRYPTOPP_VERSION_TMP}) + STRING (REGEX REPLACE "[0-9]([0-9])[0-9]" "\\1" CRYPTOPP_VERSION_MINOR + ${_CRYPTOPP_VERSION_TMP}) + STRING (REGEX REPLACE "[0-9][0-9]([0-9])" "\\1" CRYPTOPP_VERSION_PATCH + ${_CRYPTOPP_VERSION_TMP}) -IF (CRYPTOPP_FOUND) - IF (NOT CRYPTOPP_CACHED) - IF (NOT PACKAGE_FIND_QUIETLY) - MESSAGE (STATUS "CryptoPP version: ${CRYPTOPP_VERSION}") - ENDIF (NOT PACKAGE_FIND_QUIETLY) + SET (CRYPTOPP_VERSION_COUNT 3) + SET (CRYPTOPP_VERSION + ${CRYPTOPP_VERSION_MAJOR}.${CRYPTOPP_VERSION_MINOR}.${CRYPTOPP_VERSION_PATCH}) + ENDIF (EXISTS ${_CRYPTOPP_VERSION_HEADER}) +ENDIF (CRYPTOPP_INCLUDE_DIR) - SET (CRYPTOPP_CACHED TRUE CACHE INTERNAL "" FORCE) - ENDIF (NOT CRYPTOPP_CACHED) -ELSE (CRYPTOPP_FOUND) - SET (CRYPTOPP_CACHED FALSE CACHE INTERNAL "" FORCE) +SET (CRYPTOPP_INCLUDE_DIRS ${CRYPTOPP_INCLUDE_DIR}) +SET (CRYPTOPP_LIBRARIES ${CRYPTOPP_LIBRARY}) - IF (NOT PACKAGE_FIND_QUIETLY) - IF (PACKAGE_FIND_REQUIRED) - MESSAGE (FATAL_ERROR - "CryptoPP required but some files were not found. " - "Specify the CryptPP location using CRYPTOPP_ROOT_DIR") - ENDIF (PACKAGE_FIND_REQUIRED) - ENDIF (NOT PACKAGE_FIND_QUIETLY) -ENDIF (CRYPTOPP_FOUND) +MARK_AS_ADVANCED (CRYPTOPP_INCLUDE_DIR CRYPTOPP_LIBRARY CRYPTOPP_LIBRARY_DEBUG + CRYPTOPP_LIBRARY_RELEASE) -MARK_AS_ADVANCED (CRYPTOPP_INCLUDE_DIR CRYPTOPP_LIBRARIES) +FIND_PACKAGE_HANDLE_STANDARD_ARGS (CryptoPP REQUIRED_VARS CRYPTOPP_ROOT_DIR + CRYPTOPP_INCLUDE_DIR CRYPTOPP_LIBRARY VERSION_VAR CRYPTOPP_VERSION) diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index bcf906661..abf3d6998 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -1,5 +1,11 @@ -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 2.8) + +include(ExternalProject) + +# dependencies will be installed into this directory +set(ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/install") + include(cryptopp.cmake) -include(miniupnpc.cmake) +#include(miniupnpc.cmake) diff --git a/extdep/cryptopp.cmake b/extdep/cryptopp.cmake index 4e4ee85d7..e60a1fa5e 100644 --- a/extdep/cryptopp.cmake +++ b/extdep/cryptopp.cmake @@ -1,11 +1,11 @@ -include(ExternalProject) - -ExternalProject_Add(cryptopp - URL http://www.cryptopp.com/cryptopp562.zip +ExternalProject_Add( + cryptopp + URL https://github.com/mmoss/cryptopp/archive/v5.6.2.zip BINARY_DIR cryptopp-prefix/src/cryptopp CONFIGURE_COMMAND "" - BUILD_COMMAND make -j 3 + BUILD_COMMAND scons --shared --prefix=${ETH_DEPENDENCY_INSTALL_DIR} INSTALL_COMMAND "" - ) +) + diff --git a/libdevcrypto/CMakeLists.txt b/libdevcrypto/CMakeLists.txt index ed5e4416d..1dd709ffe 100644 --- a/libdevcrypto/CMakeLists.txt +++ b/libdevcrypto/CMakeLists.txt @@ -11,14 +11,14 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -include_directories(..) +include_directories(..) +include_directories(${CRYPTOPP_INCLUDE_DIR}) -add_dependencies(${EXECUTABLE} project_cryptopp) target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} secp256k1) target_link_libraries(${EXECUTABLE} gmp) target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) -target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS}) +target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LIBRARIES}) if("${TARGET_PLATFORM}" STREQUAL "w64") target_link_libraries(${EXECUTABLE} boost_system-mt-s) diff --git a/libdevcrypto/CryptoPP.h b/libdevcrypto/CryptoPP.h index 6070b651b..52a28df1a 100644 --- a/libdevcrypto/CryptoPP.h +++ b/libdevcrypto/CryptoPP.h @@ -33,18 +33,18 @@ #pragma GCC diagnostic ignored "-Wunused-variable" #pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor" #pragma GCC diagnostic ignored "-Wextra" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #pragma warning(pop) #pragma GCC diagnostic pop diff --git a/libdevcrypto/EC.cpp b/libdevcrypto/EC.cpp index 5086e3203..4edd6a648 100644 --- a/libdevcrypto/EC.cpp +++ b/libdevcrypto/EC.cpp @@ -14,7 +14,8 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file EC.cpp +/** + * @file EC.cpp * @author Alex Leverington * @date 2014 * @@ -29,7 +30,6 @@ #pragma GCC diagnostic ignored "-Wunused-variable" #pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor" #pragma GCC diagnostic ignored "-Wextra" -#include #pragma warning(pop) #pragma GCC diagnostic pop #include "CryptoPP.h" diff --git a/libethcore/CMakeLists.txt b/libethcore/CMakeLists.txt index f5cf00b57..49cfc1941 100644 --- a/libethcore/CMakeLists.txt +++ b/libethcore/CMakeLists.txt @@ -12,13 +12,13 @@ else() endif() include_directories(..) +include_directories(${CRYPTOPP_INCLUDE_DIR}) target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} secp256k1) target_link_libraries(${EXECUTABLE} gmp) target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) -target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS}) if("${TARGET_PLATFORM}" STREQUAL "w64") target_link_libraries(${EXECUTABLE} boost_system-mt-s) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a11c9fa16..f591e011b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -14,10 +14,10 @@ target_link_libraries(testeth ethcore) target_link_libraries(testeth secp256k1) target_link_libraries(testeth gmp) target_link_libraries(testeth solidity) -target_link_libraries(testeth ${CRYPTOPP_LS}) +target_link_libraries(testeth ${CRYPTOPP_LIBRARIES}) target_link_libraries(testeth webthree) if(JSONRPC_LS) -target_link_libraries(testeth web3jsonrpc) + target_link_libraries(testeth web3jsonrpc) endif() target_link_libraries(createRandomTest ethereum) From 130681763337bd552c87e1f0ed1ab205c8fed2da Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 6 Nov 2014 11:27:39 +0100 Subject: [PATCH 331/641] cryptopp compiling on macos --- extdep/CMakeLists.txt | 1 + extdep/cryptopp.cmake | 12 ++++++++++-- extdep/curl.cmake | 11 +++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 extdep/curl.cmake diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index abf3d6998..766053655 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -5,6 +5,7 @@ include(ExternalProject) # dependencies will be installed into this directory set(ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/install") +file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}) include(cryptopp.cmake) #include(miniupnpc.cmake) diff --git a/extdep/cryptopp.cmake b/extdep/cryptopp.cmake index e60a1fa5e..a8e28b43e 100644 --- a/extdep/cryptopp.cmake +++ b/extdep/cryptopp.cmake @@ -1,3 +1,12 @@ +if(${APPLE}) +ExternalProject_Add(cryptopp + URL http://www.cryptopp.com/cryptopp562.zip + BINARY_DIR cryptopp-prefix/src/cryptopp + CONFIGURE_COMMAND "" + BUILD_COMMAND make -j 3 + INSTALL_COMMAND make dynamic install PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} + ) +else() ExternalProject_Add( cryptopp URL https://github.com/mmoss/cryptopp/archive/v5.6.2.zip @@ -6,6 +15,5 @@ ExternalProject_Add( BUILD_COMMAND scons --shared --prefix=${ETH_DEPENDENCY_INSTALL_DIR} INSTALL_COMMAND "" ) - - +endif() diff --git a/extdep/curl.cmake b/extdep/curl.cmake new file mode 100644 index 000000000..c98c98b9f --- /dev/null +++ b/extdep/curl.cmake @@ -0,0 +1,11 @@ +include(ExternalProject) + +ExternalProject_Add(curl + URL http://curl.haxx.se/download/curl-7.38.0.tar.bz2 + BINARY_DIR curl-prefix/src/curl + CONFIGURE_COMMAND ./configure --with-darwinssl + BUILD_COMMAND make -j 3 + INSTALL_COMMAND "" + ) + + From 33368e31642aa388ea89a0c372b29e603351a2c0 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 6 Nov 2014 11:49:40 +0100 Subject: [PATCH 332/641] curl properly building to build dir --- extdep/CMakeLists.txt | 1 + extdep/cryptopp.cmake | 3 +-- extdep/curl.cmake | 9 +++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index 766053655..c89457f01 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -8,5 +8,6 @@ set(ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/install") file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}) include(cryptopp.cmake) +include(curl.cmake) #include(miniupnpc.cmake) diff --git a/extdep/cryptopp.cmake b/extdep/cryptopp.cmake index a8e28b43e..0f83d0115 100644 --- a/extdep/cryptopp.cmake +++ b/extdep/cryptopp.cmake @@ -7,8 +7,7 @@ ExternalProject_Add(cryptopp INSTALL_COMMAND make dynamic install PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} ) else() -ExternalProject_Add( - cryptopp +ExternalProject_Add(cryptopp URL https://github.com/mmoss/cryptopp/archive/v5.6.2.zip BINARY_DIR cryptopp-prefix/src/cryptopp CONFIGURE_COMMAND "" diff --git a/extdep/curl.cmake b/extdep/curl.cmake index c98c98b9f..5d915c79b 100644 --- a/extdep/curl.cmake +++ b/extdep/curl.cmake @@ -1,11 +1,12 @@ -include(ExternalProject) - +if(${APPLE}) ExternalProject_Add(curl URL http://curl.haxx.se/download/curl-7.38.0.tar.bz2 BINARY_DIR curl-prefix/src/curl - CONFIGURE_COMMAND ./configure --with-darwinssl + CONFIGURE_COMMAND ./configure --with-darwinssl --prefix=${ETH_DEPENDENCY_INSTALL_DIR} --exec-prefix=${ETH_DEPENDENCY_INSTALL_DIR} BUILD_COMMAND make -j 3 - INSTALL_COMMAND "" + INSTALL_COMMAND make install ) +else() +endif() From cec5c56ca640b1cb7470ca4eb68e40c56b5e20b0 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 6 Nov 2014 12:26:21 +0100 Subject: [PATCH 333/641] jsonrpc is building properly to intall folder --- extdep/CMakeLists.txt | 1 + extdep/FindCURL.cmake | 9 +++++++++ extdep/json-rpc-cpp.cmake | 11 +++++++++++ 3 files changed, 21 insertions(+) create mode 100644 extdep/FindCURL.cmake create mode 100644 extdep/json-rpc-cpp.cmake diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index c89457f01..f28ad1c8e 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -9,5 +9,6 @@ file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}) include(cryptopp.cmake) include(curl.cmake) +include(json-rpc-cpp.cmake) #include(miniupnpc.cmake) diff --git a/extdep/FindCURL.cmake b/extdep/FindCURL.cmake new file mode 100644 index 000000000..6a82ebb22 --- /dev/null +++ b/extdep/FindCURL.cmake @@ -0,0 +1,9 @@ +# hacky way to resolve nested dependencies +find_library(CURL_LIBRARY NAMES curl + PATHS + ${ETH_DEPENDENCY_INSTALL_DIR}/lib + ) + +set(CURL_LIBRARIES ${CURL_LIBRARY}) +set(CURL_INCLUDE_DIRS ${ETH_DEPENDENCY_INSTALL_DIR}/include) + diff --git a/extdep/json-rpc-cpp.cmake b/extdep/json-rpc-cpp.cmake new file mode 100644 index 000000000..28c5f7cf1 --- /dev/null +++ b/extdep/json-rpc-cpp.cmake @@ -0,0 +1,11 @@ +ExternalProject_Add(json-rpc-cpp + DEPENDS curl + GIT_REPOSITORY https://github.com/cinemast/libjson-rpc-cpp.git + GIT_TAG eaca2481e2889d5a5b748383fb02b1d395969cd4 + BINARY_DIR json-rpc-cpp-prefix/src/json-rpc-cpp + CONFIGURE_COMMAND cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_MODULE_PATH:PATH=${CMAKE_CURRENT_SOURCE_DIR} -DETH_DEPENDENCY_INSTALL_DIR:PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST -Wno-dev . + BUILD_COMMAND make jsonrpc -j 3 + INSTALL_COMMAND make install + ) + + From ff174957112cdb4312b10711da28dd99f63ebac2 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 6 Nov 2014 12:41:43 +0100 Subject: [PATCH 334/641] miniupnpc mac build --- extdep/CMakeLists.txt | 2 +- extdep/miniupnpc.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index f28ad1c8e..121f21067 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -10,5 +10,5 @@ file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}) include(cryptopp.cmake) include(curl.cmake) include(json-rpc-cpp.cmake) -#include(miniupnpc.cmake) +include(miniupnpc.cmake) diff --git a/extdep/miniupnpc.cmake b/extdep/miniupnpc.cmake index ae79f6369..b690ec2f2 100644 --- a/extdep/miniupnpc.cmake +++ b/extdep/miniupnpc.cmake @@ -5,7 +5,7 @@ ExternalProject_Add(miniupnpc BINARY_DIR miniupnpc-prefix/src/miniupnpc CONFIGURE_COMMAND "" BUILD_COMMAND make -j 3 - INSTALL_COMMAND "" + INSTALL_COMMAND make install INSTALLPREFIX=${ETH_DEPENDENCY_INSTALL_DIR} ) From c29321d01cee6c4c5495930822fd15c4fd6a2fe0 Mon Sep 17 00:00:00 2001 From: sveneh Date: Thu, 6 Nov 2014 15:56:00 +0100 Subject: [PATCH 335/641] full project compile with crypto++ dependency --- CMakeLists.txt | 15 ++++----------- alethzero/CMakeLists.txt | 2 +- cmake/EthDependencies.cmake | 11 +++++++++++ cmake/EthDependenciesDeprecated.cmake | 2 -- eth/CMakeLists.txt | 1 - exp/CMakeLists.txt | 1 - iethxi/CMakeLists.txt | 2 +- libdevcore/CMakeLists.txt | 1 - libethereum/CMakeLists.txt | 1 - libevm/CMakeLists.txt | 1 - libp2p/CMakeLists.txt | 1 - libqethereum/CMakeLists.txt | 2 +- libwebthree/CMakeLists.txt | 1 - libwhisper/CMakeLists.txt | 1 - neth/CMakeLists.txt | 1 - test/CMakeLists.txt | 8 +++++++- third/CMakeLists.txt | 2 +- walleth/CMakeLists.txt | 2 +- 18 files changed, 27 insertions(+), 28 deletions(-) create mode 100644 cmake/EthDependencies.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d2ea151f..f3de28909 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,16 +42,6 @@ function(configureProject) endfunction() -# all dependencies that are not directly included in the cpp-ethereum distribution are defined here -# for this to work, download the dependency via the cmake script in extdep or install them manually! -function(checkExternalDependencies) - set(ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/extdep/install") - - set (CRYPTOPP_ROOT_DIR ${ETH_DEPENDENCY_INSTALL_DIR}) - find_package (CryptoPP 5.6.2 REQUIRED) -endfunction() - - function(createBuildInfo) # Set build platform; to be written to BuildInfo.h @@ -104,7 +94,10 @@ endif () include(EthCompilerSettings) message("-- CXXFLAGS: ${CMAKE_CXX_FLAGS}") -checkExternalDependencies() + +# this must be an include, as a function it would messs up with variable scope! +include(EthDependencies) + # TODO this will go away soon! include(EthDependenciesDeprecated) diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index 1548abbe3..034b0dce9 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -53,7 +53,7 @@ else () endif () qt5_use_modules(${EXECUTEABLE} Core)# Gui Widgets Network WebKit WebKitWidgets) -target_link_libraries(${EXECUTEABLE} webthree qethereum ethereum evm ethcore devcrypto secp256k1 gmp ${CRYPTOPP_LS} serpent lll evmface devcore web3jsonrpc jsqrc) +target_link_libraries(${EXECUTEABLE} webthree qethereum ethereum evm ethcore devcrypto secp256k1 gmp serpent lll evmface devcore web3jsonrpc jsqrc) if (APPLE) # First have qt5 install plugins and frameworks diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake new file mode 100644 index 000000000..5934b1512 --- /dev/null +++ b/cmake/EthDependencies.cmake @@ -0,0 +1,11 @@ +# all dependencies that are not directly included in the cpp-ethereum distribution are defined here +# for this to work, download the dependency via the cmake script in extdep or install them manually! + +set(ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/extdep/install") + +set (CRYPTOPP_ROOT_DIR ${ETH_DEPENDENCY_INSTALL_DIR}) +find_package (CryptoPP 5.6.2 REQUIRED) +message("-- CryptoPP header: ${CRYPTOPP_INCLUDE_DIRS}") +message("-- CryptoPP libs : ${CRYPTOPP_LIBRARIES}") + + diff --git a/cmake/EthDependenciesDeprecated.cmake b/cmake/EthDependenciesDeprecated.cmake index 87a981fc9..4be546a13 100644 --- a/cmake/EthDependenciesDeprecated.cmake +++ b/cmake/EthDependenciesDeprecated.cmake @@ -140,8 +140,6 @@ else() set(QTQML 1) endif() -include_directories(${CRYPTOPP_ID}) - if(PYTHON_ID) include_directories(${PYTHON_ID}) endif() diff --git a/eth/CMakeLists.txt b/eth/CMakeLists.txt index 7c997b256..793223abd 100644 --- a/eth/CMakeLists.txt +++ b/eth/CMakeLists.txt @@ -16,7 +16,6 @@ if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) -target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS}) if(JSONRPC_LS) target_link_libraries(${EXECUTABLE} web3jsonrpc) endif() diff --git a/exp/CMakeLists.txt b/exp/CMakeLists.txt index da6775798..89e5580a4 100644 --- a/exp/CMakeLists.txt +++ b/exp/CMakeLists.txt @@ -11,7 +11,6 @@ add_executable(${EXECUTABLE} ${SRC_LIST}) target_link_libraries(${EXECUTABLE} ethereum) target_link_libraries(${EXECUTABLE} p2p) target_link_libraries(${EXECUTABLE} gmp) -target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS}) if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() diff --git a/iethxi/CMakeLists.txt b/iethxi/CMakeLists.txt index fc8edf1dc..77c26dd4d 100644 --- a/iethxi/CMakeLists.txt +++ b/iethxi/CMakeLists.txt @@ -59,7 +59,7 @@ else () endif () qt5_use_modules(${EXECUTEABLE} Core Gui Widgets Network Quick Qml) -target_link_libraries(${EXECUTEABLE} qethereum ethereum secp256k1 ${CRYPTOPP_LS}) +target_link_libraries(${EXECUTEABLE} qethereum ethereum secp256k1) if (APPLE) if (${ADDFRAMEWORKS}) diff --git a/libdevcore/CMakeLists.txt b/libdevcore/CMakeLists.txt index 7c54301c9..c3857a622 100644 --- a/libdevcore/CMakeLists.txt +++ b/libdevcore/CMakeLists.txt @@ -20,7 +20,6 @@ endif() include_directories(..) if("${TARGET_PLATFORM}" STREQUAL "w64") - include_directories(/usr/x86_64-w64-mingw32/include/cryptopp) target_link_libraries(${EXECUTABLE} boost_system-mt-s) target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) target_link_libraries(${EXECUTABLE} iphlpapi) diff --git a/libethereum/CMakeLists.txt b/libethereum/CMakeLists.txt index cb2049886..3c00ad6a7 100644 --- a/libethereum/CMakeLists.txt +++ b/libethereum/CMakeLists.txt @@ -26,7 +26,6 @@ if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) -target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS}) target_link_libraries(${EXECUTABLE} gmp) if("${TARGET_PLATFORM}" STREQUAL "w64") diff --git a/libevm/CMakeLists.txt b/libevm/CMakeLists.txt index 0c31a9fc3..0a1d8c3cd 100644 --- a/libevm/CMakeLists.txt +++ b/libevm/CMakeLists.txt @@ -25,7 +25,6 @@ if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) -target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS}) if("${TARGET_PLATFORM}" STREQUAL "w64") target_link_libraries(${EXECUTABLE} boost_system-mt-s) diff --git a/libp2p/CMakeLists.txt b/libp2p/CMakeLists.txt index 9e20fd99f..f0aeceae5 100644 --- a/libp2p/CMakeLists.txt +++ b/libp2p/CMakeLists.txt @@ -22,7 +22,6 @@ if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) -target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS}) target_link_libraries(${EXECUTABLE} gmp) if("${TARGET_PLATFORM}" STREQUAL "w64") diff --git a/libqethereum/CMakeLists.txt b/libqethereum/CMakeLists.txt index ba7cd3b67..d7e545ede 100644 --- a/libqethereum/CMakeLists.txt +++ b/libqethereum/CMakeLists.txt @@ -59,7 +59,7 @@ endif() include_directories(/) qt5_use_modules(${EXECUTABLE} Core Gui WebKit WebKitWidgets Widgets Network Quick Qml) -target_link_libraries(${EXECUTABLE} ethereum secp256k1 ${CRYPTOPP_LS} ${JSONRPC_LS}) +target_link_libraries(${EXECUTABLE} ethereum secp256k1 ${JSONRPC_LS}) if (APPLE) if (${ADDFRAMEWORKS}) diff --git a/libwebthree/CMakeLists.txt b/libwebthree/CMakeLists.txt index cc1b290f5..fbaa43b45 100644 --- a/libwebthree/CMakeLists.txt +++ b/libwebthree/CMakeLists.txt @@ -27,7 +27,6 @@ if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) -target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS}) target_link_libraries(${EXECUTABLE} gmp) if("${TARGET_PLATFORM}" STREQUAL "w64") diff --git a/libwhisper/CMakeLists.txt b/libwhisper/CMakeLists.txt index 364d9759a..fdf69650a 100644 --- a/libwhisper/CMakeLists.txt +++ b/libwhisper/CMakeLists.txt @@ -24,7 +24,6 @@ if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) -target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS}) target_link_libraries(${EXECUTABLE} gmp) if("${TARGET_PLATFORM}" STREQUAL "w64") diff --git a/neth/CMakeLists.txt b/neth/CMakeLists.txt index ac275f663..68044fe7c 100644 --- a/neth/CMakeLists.txt +++ b/neth/CMakeLists.txt @@ -17,7 +17,6 @@ if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) -target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS}) if(JSONRPC_LS) target_link_libraries(${EXECUTABLE} web3jsonrpc) endif() diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f591e011b..4f02f96bb 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -4,18 +4,23 @@ aux_source_directory(. SRC_LIST) list(REMOVE_ITEM SRC_LIST "./createRandomTest.cpp") include_directories(..) +include_directories(${CRYPTOPP_INCLUDE_DIR}) file(GLOB HEADERS "*.h") add_executable(testeth ${SRC_LIST} ${HEADERS}) add_executable(createRandomTest createRandomTest.cpp vm.cpp) + target_link_libraries(testeth ethereum) target_link_libraries(testeth ethcore) target_link_libraries(testeth secp256k1) target_link_libraries(testeth gmp) target_link_libraries(testeth solidity) -target_link_libraries(testeth ${CRYPTOPP_LIBRARIES}) target_link_libraries(testeth webthree) + +#TODO this on should not be necessary, it should have been brought in from ethcore dependency... +target_link_libraries(testeth ${CRYPTOPP_LIBRARIES}) + if(JSONRPC_LS) target_link_libraries(testeth web3jsonrpc) endif() @@ -24,6 +29,7 @@ target_link_libraries(createRandomTest ethereum) target_link_libraries(createRandomTest ethcore) target_link_libraries(createRandomTest boost_chrono) target_link_libraries(createRandomTest boost_unit_test_framework) +target_link_libraries(createRandomTest ${CRYPTOPP_LIBRARIES}) if ("${TARGET_PLATFORM}" STREQUAL "w64") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") diff --git a/third/CMakeLists.txt b/third/CMakeLists.txt index 6edea7456..be998b4bd 100644 --- a/third/CMakeLists.txt +++ b/third/CMakeLists.txt @@ -53,7 +53,7 @@ else () endif () qt5_use_modules(${EXECUTEABLE} Core)# Gui Widgets Network WebKit WebKitWidgets) -target_link_libraries(${EXECUTEABLE} webthree qethereum ethereum evm ethcore secp256k1 gmp ${CRYPTOPP_LS} serpent lll evmface devcore web3jsonrpc jsqrc) +target_link_libraries(${EXECUTEABLE} webthree qethereum ethereum evm ethcore secp256k1 gmp serpent lll evmface devcore web3jsonrpc jsqrc) if (APPLE) # First have qt5 install plugins and frameworks diff --git a/walleth/CMakeLists.txt b/walleth/CMakeLists.txt index cac73a726..26e010b97 100644 --- a/walleth/CMakeLists.txt +++ b/walleth/CMakeLists.txt @@ -59,7 +59,7 @@ else () endif () qt5_use_modules(${EXECUTEABLE} Core Gui Widgets Network Quick Qml) -target_link_libraries(${EXECUTEABLE} qethereum ethereum secp256k1 ${CRYPTOPP_LS}) +target_link_libraries(${EXECUTEABLE} qethereum ethereum secp256k1) if (APPLE) if (${ADDFRAMEWORKS}) From 2bd09c250a737294fdf1679adce1c539b03de6c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 6 Nov 2014 17:58:37 +0100 Subject: [PATCH 336/641] Fix compilation with Visual Studio --- libdevcrypto/EC.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libdevcrypto/EC.cpp b/libdevcrypto/EC.cpp index af6d0e65e..7bc17ab99 100644 --- a/libdevcrypto/EC.cpp +++ b/libdevcrypto/EC.cpp @@ -134,7 +134,7 @@ bool crypto::verify(Signature const& _signature, bytesConstRef _message) bool crypto::verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed) { - static size_t derMaxEncodingLength = 72; + static const size_t derMaxEncodingLength = 72; if (_hashed) { assert(_message.size() == 32); @@ -155,8 +155,9 @@ Public crypto::recover(Signature _signature, bytesConstRef _message) { secp256k1_start(); - int pubkeylen = 65; - byte pubkey[pubkeylen]; + static const int c_pubkeylen = 65; + auto pubkeylen = c_pubkeylen; + byte pubkey[c_pubkeylen]; if (!secp256k1_ecdsa_recover_compact(_message.data(), 32, _signature.data(), pubkey, &pubkeylen, 0, (int)_signature[64])) return Public(); @@ -180,8 +181,9 @@ bool crypto::verifySecret(Secret const& _s, Public const& _p) if (!ok) return false; - int pubkeylen = 65; - byte pubkey[pubkeylen]; + static const int c_pubkeylen = 65; + auto pubkeylen = c_pubkeylen; + byte pubkey[c_pubkeylen]; ok = secp256k1_ecdsa_pubkey_create(pubkey, &pubkeylen, _s.data(), 0); if (!ok || pubkeylen != 65) return false; From 69c499e01fe0edf42f8323398d2fd74a207baccf Mon Sep 17 00:00:00 2001 From: sveneh Date: Mon, 10 Nov 2014 16:41:25 +0100 Subject: [PATCH 337/641] provided my own FindJsonRCP.cmake --- cmake/FindJsonRcpCpp.cmake | 46 ++++++++++++++++++++++++++++++++++++++ extdep/json-rpc-cpp.cmake | 11 --------- 2 files changed, 46 insertions(+), 11 deletions(-) create mode 100644 cmake/FindJsonRcpCpp.cmake delete mode 100644 extdep/json-rpc-cpp.cmake diff --git a/cmake/FindJsonRcpCpp.cmake b/cmake/FindJsonRcpCpp.cmake new file mode 100644 index 000000000..1a7d45069 --- /dev/null +++ b/cmake/FindJsonRcpCpp.cmake @@ -0,0 +1,46 @@ +# Find json-rcp-cpp +# +# Find the JSONCpp includes and library +# +# if you nee to add a custom library search path, do it via via CMAKE_FIND_ROOT_PATH +# +# This module defines +# JSON_RCP_CPP_INCLUDE_DIRS, where to find json.h, etc. +# JSON_RCP_CPP_LIBRARIES, the libraries needed to use jsoncpp. +# JSON_RCP_CPP_FOUND, If false, do not try to use jsoncpp. + +if (JSON_RPC_CPP_LIBRARIES AND JSON_RPC_CPP_INCLUDE_DIRS) + # in cache already + set(JSON_RPC_CPP_FOUND TRUE) +endif() + + +# only look in default directories +find_path( + JSON_RPC_CPP_INCLUDE_DIR + NAMES jsonrpc/rpc.h + PATH_SUFFIXES jsonrpc + DOC "json-rpc-cpp include dir" +) + +find_library( + JSON_RPC_CPP_LIBRARY + NAMES jsonrpc + DOC "json-rpc-cpp library" +) + +set (JSON_RPC_CPP_INCLUDE_DIRS ${JSON_RPC_CPP_INCLUDE_DIR}) +set (JSON_RPC_CPP_LIBRARIES ${JSON_RPC_CPP_LIBRARY}) + +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set JSON_RPC_CPP_FOUND to TRUE +# if all listed variables are TRUE +find_package_handle_standard_args(json-rpc-cpp DEFAULT_MSG + JSON_RPC_CPP_LIBRARY JSON_RPC_CPP_INCLUDE_DIR) + + +# include(FindPackageMessage) +# find_package_message ("json-rpc-cpp" "found" "bla") + + +mark_as_advanced (JSON_RPC_CPP_INCLUDE_DIR JSON_RPC_CPP_LIBRARY) diff --git a/extdep/json-rpc-cpp.cmake b/extdep/json-rpc-cpp.cmake deleted file mode 100644 index 28c5f7cf1..000000000 --- a/extdep/json-rpc-cpp.cmake +++ /dev/null @@ -1,11 +0,0 @@ -ExternalProject_Add(json-rpc-cpp - DEPENDS curl - GIT_REPOSITORY https://github.com/cinemast/libjson-rpc-cpp.git - GIT_TAG eaca2481e2889d5a5b748383fb02b1d395969cd4 - BINARY_DIR json-rpc-cpp-prefix/src/json-rpc-cpp - CONFIGURE_COMMAND cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_MODULE_PATH:PATH=${CMAKE_CURRENT_SOURCE_DIR} -DETH_DEPENDENCY_INSTALL_DIR:PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST -Wno-dev . - BUILD_COMMAND make jsonrpc -j 3 - INSTALL_COMMAND make install - ) - - From 8ee3e56e0ae527fbd67dcb4a9a7adefb36a906aa Mon Sep 17 00:00:00 2001 From: sveneh Date: Mon, 10 Nov 2014 19:14:01 +0100 Subject: [PATCH 338/641] WIP: Cryptopp and json-rpc-cpp correctly downloading and compiling on Linux. Main cpp-ethereum buildfile finds dependencies, but does not compile yet --- CMakeLists.txt | 3 --- cmake/EthDependencies.cmake | 15 ++++++++--- cmake/EthDependenciesDeprecated.cmake | 26 ------------------- cmake/FindCryptoPP.cmake | 2 +- ...dJsonRcpCpp.cmake => FindJsonRpcCpp.cmake} | 12 ++++----- extdep/CMakeLists.txt | 5 ++-- extdep/FindCURL.cmake | 2 +- extdep/curl.cmake | 18 +++++++++---- extdep/json-rpc-cpp.cmake | 11 ++++++++ 9 files changed, 44 insertions(+), 50 deletions(-) rename cmake/{FindJsonRcpCpp.cmake => FindJsonRpcCpp.cmake} (85%) create mode 100644 extdep/json-rpc-cpp.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index f3de28909..34a2447b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -149,9 +149,6 @@ if (NOT LANGUAGES) if ("${TARGET_PLATFORM}" STREQUAL "w64") cmake_policy(SET CMP0020 NEW) endif () - if (NOT JSONRPC_LS) - message(FATAL_ERROR "Alethzero requires jsonrpc.") - endif() add_subdirectory(libjsqrc) add_subdirectory(libqethereum) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 5934b1512..376a6c03f 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -1,11 +1,18 @@ # all dependencies that are not directly included in the cpp-ethereum distribution are defined here # for this to work, download the dependency via the cmake script in extdep or install them manually! -set(ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/extdep/install") +# by defining this variable, cmake will look for dependencies first in our own repository before looking in system paths like /usr/local/ ... +# this must be set to point to the same directory as $ETH_DEPENDENCY_INSTALL_DIR in /extdep directory +set (CMAKE_FIND_ROOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/extdep/install") -set (CRYPTOPP_ROOT_DIR ${ETH_DEPENDENCY_INSTALL_DIR}) find_package (CryptoPP 5.6.2 REQUIRED) -message("-- CryptoPP header: ${CRYPTOPP_INCLUDE_DIRS}") -message("-- CryptoPP libs : ${CRYPTOPP_LIBRARIES}") +message(" - CryptoPP header: ${CRYPTOPP_INCLUDE_DIRS}") +message(" - CryptoPP lib : ${CRYPTOPP_LIBRARIES}") +find_package (JsonRpcCpp REQUIRED) +if (${JSON_RPC_CPP_FOUND}) + message (" - json-rpc-cpp header: ${JSON_RPC_CPP_INCLUDE_DIRS}") + message (" - json-rpc-cpp lib : ${JSON_RPC_CPP_LIBRARIES}") + add_definitions(-DETH_JSONRPC) +endif() diff --git a/cmake/EthDependenciesDeprecated.cmake b/cmake/EthDependenciesDeprecated.cmake index 4be546a13..aacb625db 100644 --- a/cmake/EthDependenciesDeprecated.cmake +++ b/cmake/EthDependenciesDeprecated.cmake @@ -85,29 +85,6 @@ else() message(STATUS "Failed to find the miniupnpc headers!") endif () - find_path( JSONRPC_ID jsonrpc/rpc.h - /usr/include - /usr/local/include - ) - if ( JSONRPC_ID ) - message(STATUS "Found jsonrpc headers") - find_library( JSONRPC_LS NAMES jsonrpc - PATHS - /usr/lib - /usr/local/lib - /opt/local/lib - /usr/lib/*/ - ) - if ( JSONRPC_LS ) - message(STATUS "Found jsonrpc library: ${JSONRPC_LS}") - add_definitions(-DETH_JSONRPC) - else () - message(STATUS "Failed to find the jsonrpc library!") - endif () - else () - message(STATUS "Failed to find the jsonrpc headers!") - endif () - find_path( READLINE_ID readline/readline.h /usr/include /usr/local/include @@ -152,9 +129,6 @@ endif() if(READLINE_ID) include_directories(${READLINE_ID}) endif() -if(JSONRPC_ID) - include_directories(${JSONRPC_ID}) -endif() diff --git a/cmake/FindCryptoPP.cmake b/cmake/FindCryptoPP.cmake index 74a01e83a..a9e7183c0 100644 --- a/cmake/FindCryptoPP.cmake +++ b/cmake/FindCryptoPP.cmake @@ -104,5 +104,5 @@ SET (CRYPTOPP_LIBRARIES ${CRYPTOPP_LIBRARY}) MARK_AS_ADVANCED (CRYPTOPP_INCLUDE_DIR CRYPTOPP_LIBRARY CRYPTOPP_LIBRARY_DEBUG CRYPTOPP_LIBRARY_RELEASE) -FIND_PACKAGE_HANDLE_STANDARD_ARGS (CryptoPP REQUIRED_VARS CRYPTOPP_ROOT_DIR +FIND_PACKAGE_HANDLE_STANDARD_ARGS (CryptoPP REQUIRED_VARS CRYPTOPP_INCLUDE_DIR CRYPTOPP_LIBRARY VERSION_VAR CRYPTOPP_VERSION) diff --git a/cmake/FindJsonRcpCpp.cmake b/cmake/FindJsonRpcCpp.cmake similarity index 85% rename from cmake/FindJsonRcpCpp.cmake rename to cmake/FindJsonRpcCpp.cmake index 1a7d45069..c056418b0 100644 --- a/cmake/FindJsonRcpCpp.cmake +++ b/cmake/FindJsonRpcCpp.cmake @@ -9,12 +9,6 @@ # JSON_RCP_CPP_LIBRARIES, the libraries needed to use jsoncpp. # JSON_RCP_CPP_FOUND, If false, do not try to use jsoncpp. -if (JSON_RPC_CPP_LIBRARIES AND JSON_RPC_CPP_INCLUDE_DIRS) - # in cache already - set(JSON_RPC_CPP_FOUND TRUE) -endif() - - # only look in default directories find_path( JSON_RPC_CPP_INCLUDE_DIR @@ -32,10 +26,14 @@ find_library( set (JSON_RPC_CPP_INCLUDE_DIRS ${JSON_RPC_CPP_INCLUDE_DIR}) set (JSON_RPC_CPP_LIBRARIES ${JSON_RPC_CPP_LIBRARY}) +# message (" - json-rcp-cpp header : ${JSON_RPC_CPP_INCLUDE_DIRS}") +# message (" - json-rcp-cpp lib : ${JSON_RPC_CPP_LIBRARIES}") + + include(FindPackageHandleStandardArgs) # handle the QUIETLY and REQUIRED arguments and set JSON_RPC_CPP_FOUND to TRUE # if all listed variables are TRUE -find_package_handle_standard_args(json-rpc-cpp DEFAULT_MSG +find_package_handle_standard_args(json_rpc_cpp DEFAULT_MSG JSON_RPC_CPP_LIBRARY JSON_RPC_CPP_INCLUDE_DIR) diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index 121f21067..666ea5f15 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -2,13 +2,12 @@ cmake_minimum_required(VERSION 2.8) include(ExternalProject) -# dependencies will be installed into this directory +# all dependencies will be installed into this directory set(ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/install") - file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}) include(cryptopp.cmake) include(curl.cmake) include(json-rpc-cpp.cmake) -include(miniupnpc.cmake) +#include(miniupnpc.cmake) diff --git a/extdep/FindCURL.cmake b/extdep/FindCURL.cmake index 6a82ebb22..22d51591c 100644 --- a/extdep/FindCURL.cmake +++ b/extdep/FindCURL.cmake @@ -1,4 +1,4 @@ -# hacky way to resolve nested dependencies +# hacky way to resolve nested dependencies - needed for json-rpc-cpp find_library(CURL_LIBRARY NAMES curl PATHS ${ETH_DEPENDENCY_INSTALL_DIR}/lib diff --git a/extdep/curl.cmake b/extdep/curl.cmake index 5d915c79b..13e10361d 100644 --- a/extdep/curl.cmake +++ b/extdep/curl.cmake @@ -1,12 +1,20 @@ + +set (CONFIG_CMD ./configure --prefix=${ETH_DEPENDENCY_INSTALL_DIR} --exec-prefix=${ETH_DEPENDENCY_INSTALL_DIR}) + if(${APPLE}) -ExternalProject_Add(curl + set(CONFIG_CMD ./configure --with-darwinssl --prefix=${ETH_DEPENDENCY_INSTALL_DIR} --exec-prefix=${ETH_DEPENDENCY_INSTALL_DIR}) +endif() + + + +ExternalProject_Add( + curl URL http://curl.haxx.se/download/curl-7.38.0.tar.bz2 BINARY_DIR curl-prefix/src/curl - CONFIGURE_COMMAND ./configure --with-darwinssl --prefix=${ETH_DEPENDENCY_INSTALL_DIR} --exec-prefix=${ETH_DEPENDENCY_INSTALL_DIR} + CONFIGURE_COMMAND ${CONFIG_CMD} BUILD_COMMAND make -j 3 INSTALL_COMMAND make install - ) -else() +) + -endif() diff --git a/extdep/json-rpc-cpp.cmake b/extdep/json-rpc-cpp.cmake new file mode 100644 index 000000000..28c5f7cf1 --- /dev/null +++ b/extdep/json-rpc-cpp.cmake @@ -0,0 +1,11 @@ +ExternalProject_Add(json-rpc-cpp + DEPENDS curl + GIT_REPOSITORY https://github.com/cinemast/libjson-rpc-cpp.git + GIT_TAG eaca2481e2889d5a5b748383fb02b1d395969cd4 + BINARY_DIR json-rpc-cpp-prefix/src/json-rpc-cpp + CONFIGURE_COMMAND cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_MODULE_PATH:PATH=${CMAKE_CURRENT_SOURCE_DIR} -DETH_DEPENDENCY_INSTALL_DIR:PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST -Wno-dev . + BUILD_COMMAND make jsonrpc -j 3 + INSTALL_COMMAND make install + ) + + From b82e3125ce74880a532c9e7d4b7c7f708a9bc283 Mon Sep 17 00:00:00 2001 From: sveneh Date: Mon, 10 Nov 2014 20:31:15 +0100 Subject: [PATCH 339/641] compiles fine now (on Linux) with both cryptopp and json-rpc-cpp dependencies --- CMakeLists.txt | 8 ++++++-- eth/CMakeLists.txt | 2 +- libweb3jsonrpc/CMakeLists.txt | 4 +--- neth/CMakeLists.txt | 2 +- test/CMakeLists.txt | 2 +- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 34a2447b2..a44fd1591 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -118,7 +118,7 @@ endif() add_subdirectory(lllc) add_subdirectory(solc) add_subdirectory(sc) -if (JSONRPC_LS) +if (JSON_RPC_CPP_FOUND) add_subdirectory(libweb3jsonrpc) endif() if (NOT LANGUAGES) @@ -152,7 +152,11 @@ if (NOT LANGUAGES) add_subdirectory(libjsqrc) add_subdirectory(libqethereum) - add_subdirectory(alethzero) + if (NOT JSON_RPC_CPP_FOUND) + message (FATAL_ERROR "AlethZero requires json-rpc-cpp!") + else() + add_subdirectory(alethzero) + endif() add_subdirectory(third) if(QTQML) #add_subdirectory(iethxi) diff --git a/eth/CMakeLists.txt b/eth/CMakeLists.txt index 793223abd..cb3b01b4e 100644 --- a/eth/CMakeLists.txt +++ b/eth/CMakeLists.txt @@ -16,7 +16,7 @@ if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) -if(JSONRPC_LS) +if(JSON_RPC_CPP_FOUND) target_link_libraries(${EXECUTABLE} web3jsonrpc) endif() if(READLINE_LS) diff --git a/libweb3jsonrpc/CMakeLists.txt b/libweb3jsonrpc/CMakeLists.txt index b24a11196..4184d7cbd 100644 --- a/libweb3jsonrpc/CMakeLists.txt +++ b/libweb3jsonrpc/CMakeLists.txt @@ -22,9 +22,7 @@ if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) -target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS}) -target_link_libraries(${EXECUTABLE} ${JSONRPC_LS}) -target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) +target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_LIBRARIES}) if(READLINE_LS) target_link_libraries(${EXECUTABLE} ${READLINE_LS}) endif() diff --git a/neth/CMakeLists.txt b/neth/CMakeLists.txt index 68044fe7c..d9f551b18 100644 --- a/neth/CMakeLists.txt +++ b/neth/CMakeLists.txt @@ -17,7 +17,7 @@ if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) -if(JSONRPC_LS) +if(JSON_RPC_CPP_FOUND) target_link_libraries(${EXECUTABLE} web3jsonrpc) endif() diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 4f02f96bb..38e3ca1ca 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -21,7 +21,7 @@ target_link_libraries(testeth webthree) #TODO this on should not be necessary, it should have been brought in from ethcore dependency... target_link_libraries(testeth ${CRYPTOPP_LIBRARIES}) -if(JSONRPC_LS) +if(JSON_RPC_CPP_FOUND) target_link_libraries(testeth web3jsonrpc) endif() From 369670a6d9dffe8aa9612172a7cc81f531173d91 Mon Sep 17 00:00:00 2001 From: sveneh Date: Thu, 13 Nov 2014 12:02:37 +0100 Subject: [PATCH 340/641] changes from debris, to allow build on Mac OS --- extdep/cryptopp.cmake | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/extdep/cryptopp.cmake b/extdep/cryptopp.cmake index 0f83d0115..39a848649 100644 --- a/extdep/cryptopp.cmake +++ b/extdep/cryptopp.cmake @@ -1,11 +1,11 @@ if(${APPLE}) ExternalProject_Add(cryptopp - URL http://www.cryptopp.com/cryptopp562.zip - BINARY_DIR cryptopp-prefix/src/cryptopp - CONFIGURE_COMMAND "" - BUILD_COMMAND make -j 3 - INSTALL_COMMAND make dynamic install PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} - ) + URL https://downloads.sourceforge.net/project/cryptopp/cryptopp/5.6.2/cryptopp562.zip + BINARY_DIR cryptopp-prefix/src/cryptopp + CONFIGURE_COMMAND "" + BUILD_COMMAND make CXX=clang++ CXXFLAGS=-DCRYPTOPP_DISABLE_ASM + INSTALL_COMMAND make install PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} +) else() ExternalProject_Add(cryptopp URL https://github.com/mmoss/cryptopp/archive/v5.6.2.zip From 888bdd03dcd9a56d170e48ec23af4dd950066a7d Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 12 Nov 2014 17:51:37 +0100 Subject: [PATCH 341/641] jsonrpccpp 0.2.1 with patch for osx 10.9 --- extdep/json-rpc-cpp.cmake | 4 ++-- extdep/json-rpc-cpp_osx.patch | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 extdep/json-rpc-cpp_osx.patch diff --git a/extdep/json-rpc-cpp.cmake b/extdep/json-rpc-cpp.cmake index 28c5f7cf1..ea26851b9 100644 --- a/extdep/json-rpc-cpp.cmake +++ b/extdep/json-rpc-cpp.cmake @@ -1,9 +1,9 @@ ExternalProject_Add(json-rpc-cpp DEPENDS curl GIT_REPOSITORY https://github.com/cinemast/libjson-rpc-cpp.git - GIT_TAG eaca2481e2889d5a5b748383fb02b1d395969cd4 + GIT_TAG 0.2.1 BINARY_DIR json-rpc-cpp-prefix/src/json-rpc-cpp - CONFIGURE_COMMAND cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_MODULE_PATH:PATH=${CMAKE_CURRENT_SOURCE_DIR} -DETH_DEPENDENCY_INSTALL_DIR:PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST -Wno-dev . + CONFIGURE_COMMAND patch -d src/example < ${CMAKE_CURRENT_SOURCE_DIR}/json-rpc-cpp_osx.patch && cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_MODULE_PATH:PATH=${CMAKE_CURRENT_SOURCE_DIR} -DETH_DEPENDENCY_INSTALL_DIR:PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST -Wno-dev . BUILD_COMMAND make jsonrpc -j 3 INSTALL_COMMAND make install ) diff --git a/extdep/json-rpc-cpp_osx.patch b/extdep/json-rpc-cpp_osx.patch new file mode 100644 index 000000000..39165530d --- /dev/null +++ b/extdep/json-rpc-cpp_osx.patch @@ -0,0 +1,9 @@ +--- ./src/example/CMakeLists.txt 2014-11-12 17:20:52.000000000 +0100 ++++ CMakeListsPatch.txt 2014-11-12 17:26:42.000000000 +0100 +@@ -12,6 +12,3 @@ + add_executable(stubserversample stubserver.cpp) + target_link_libraries(stubserversample jsonrpc) + +- +-add_executable(xbmcremote xbmcremote.cpp) +-target_link_libraries(xbmcremote jsonrpc) From b43f66ab01142e2a2177ce25206f30c9ca8a2311 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Thu, 13 Nov 2014 16:57:01 +0100 Subject: [PATCH 342/641] removed references to Memory::dump() --- libevmjit/Memory.cpp | 18 ------------------ libevmjit/Memory.h | 2 -- 2 files changed, 20 deletions(-) diff --git a/libevmjit/Memory.cpp b/libevmjit/Memory.cpp index 89cef4d48..53cccf92b 100644 --- a/libevmjit/Memory.cpp +++ b/libevmjit/Memory.cpp @@ -147,24 +147,18 @@ llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, GasMet llvm::Value* Memory::loadWord(llvm::Value* _addr) { auto value = m_builder.CreateCall(m_loadWord, _addr); - - dump(0); return value; } void Memory::storeWord(llvm::Value* _addr, llvm::Value* _word) { m_builder.CreateCall2(m_storeWord, _addr, _word); - - dump(0); } void Memory::storeByte(llvm::Value* _addr, llvm::Value* _word) { auto byte = m_builder.CreateTrunc(_word, Type::Byte, "byte"); m_builder.CreateCall2(m_storeByte, _addr, byte); - - dump(0); } llvm::Value* Memory::getData() @@ -205,18 +199,6 @@ void Memory::copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value* m_builder.CreateMemCpy(destPtr, srcPtr, bytesToCopy, 0); } -void Memory::dump(uint64_t _begin, uint64_t _end) -{ - if (getenv("EVMCC_DEBUG_MEMORY") == nullptr) - return; - - auto beginVal = llvm::ConstantInt::get(m_builder.getInt64Ty(), _begin); - auto endVal = llvm::ConstantInt::get(m_builder.getInt64Ty(), _end); - - std::vector args = {beginVal, endVal}; - m_builder.CreateCall(m_memDump, llvm::ArrayRef(args)); -} - } } } diff --git a/libevmjit/Memory.h b/libevmjit/Memory.h index 37bfb15f5..c6ba02a54 100644 --- a/libevmjit/Memory.h +++ b/libevmjit/Memory.h @@ -27,8 +27,6 @@ public: /// Requires the amount of memory to for data defined by offset and size. And counts gas fee for that memory. void require(llvm::Value* _offset, llvm::Value* _size); - void dump(uint64_t _begin, uint64_t _end = 0); - private: llvm::Function* createFunc(bool _isStore, llvm::Type* _type, GasMeter& _gasMeter); llvm::Function* createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _runtimeManager); From a09c3a404d3f944e03178fee30a3e8e86a8b3fe3 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Thu, 13 Nov 2014 17:03:39 +0100 Subject: [PATCH 343/641] codegen for LOG instructions [Delivers #81700490] --- evmcc/evmcc.cpp | 12 ++-- libevmjit/Compiler.cpp | 25 ++++++- libevmjit/ExecutionEngine.cpp | 5 +- libevmjit/ExecutionEngine.h | 2 +- libevmjit/Ext.cpp | 125 ++++++++++++++++++++++++++++++++++ libevmjit/Ext.h | 7 ++ libevmjit/Runtime.cpp | 10 ++- libevmjit/Runtime.h | 4 +- 8 files changed, 178 insertions(+), 12 deletions(-) diff --git a/evmcc/evmcc.cpp b/evmcc/evmcc.cpp index 535a9aed9..48d883fd7 100644 --- a/evmcc/evmcc.cpp +++ b/evmcc/evmcc.cpp @@ -31,9 +31,12 @@ void parseProgramOptions(int _argc, char** _argv, boost::program_options::variab ("gas,g", opt::value(), "set initial gas for execution") ("disassemble,d", "dissassemble the code") ("dump-cfg", "dump control flow graph to graphviz file") - ("optimize-stack,os", "optimize stack use between basic blocks") + ("dont-optimize", "turn off optimizations") + ("optimize-stack", "optimize stack use between basic blocks (default: on)") + ("rewrite-switch", "rewrite LLVM switch to branches (default: on)") ("output-ll", opt::value(), "dump generated LLVM IR to file") ("output-bc", opt::value(), "dump generated LLVM bitcode to file") + ("show-logs", "output LOG statements to stderr") ("verbose,V", "enable verbose output"); opt::options_description implicitOpts("Input files"); @@ -118,7 +121,9 @@ int main(int argc, char** argv) eth::jit::Compiler::Options compilerOptions; compilerOptions.dumpCFG = options.count("dump-cfg") > 0; - compilerOptions.optimizeStack = options.count("optimize-stack") > 0; + bool optimize = options.count("dont-optimize") == 0; + compilerOptions.optimizeStack = optimize || options.count("optimize-stack") > 0; + compilerOptions.rewriteSwitchToBranches = optimize || options.count("rewrite-switch") > 0; auto compiler = eth::jit::Compiler(compilerOptions); auto module = compiler.compile({bytecode.data(), bytecode.size()}); @@ -156,7 +161,6 @@ int main(int argc, char** argv) ofs.close(); } - if (options.count("verbose")) { std::cerr << "*** Compilation time: " @@ -168,7 +172,7 @@ int main(int argc, char** argv) { auto engine = eth::jit::ExecutionEngine(); u256 gas = initialGas; - auto result = engine.run(std::move(module), gas); + auto result = engine.run(std::move(module), gas, options.count("show-logs") > 0); return result; } } diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 295f3a131..8ce490040 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -508,7 +508,11 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytesConstRef _bytecod case Instruction::POP: { - stack.pop(); + auto val = stack.pop(); + static_cast(val); + // Generate a dummy use of val to make sure that a get(0) will be emitted at this point, + // so that StackTooSmall will be thrown + // m_builder.CreateICmpEQ(val, val, "dummy"); break; } @@ -791,6 +795,25 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytesConstRef _bytecod break; } + case Instruction::LOG0: + case Instruction::LOG1: + case Instruction::LOG2: + case Instruction::LOG3: + case Instruction::LOG4: + { + auto beginIdx = stack.pop(); + auto numBytes = stack.pop(); + _memory.require(beginIdx, numBytes); + + std::array topics; + auto numTopics = static_cast(inst) - static_cast(Instruction::LOG0); + for (size_t i = 0; i < numTopics; ++i) + topics[i] = stack.pop(); + + _ext.log(beginIdx, numBytes, numTopics, topics); + break; + } + default: // Invalid instruction - runtime exception { _runtimeManager.raiseException(ReturnCode::BadInstruction); diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp index 4c617d9ea..9f2149524 100644 --- a/libevmjit/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -37,10 +37,9 @@ namespace jit ExecutionEngine::ExecutionEngine() { - } -int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, ExtVMFace* _ext) +int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, bool _outputLogs, ExtVMFace* _ext) { auto module = _module.get(); // Keep ownership of the module in _module @@ -110,7 +109,7 @@ int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, ExtV ReturnCode returnCode; std::jmp_buf buf; - Runtime runtime(_gas, *_ext, buf); + Runtime runtime(_gas, *_ext, buf, _outputLogs); auto r = setjmp(buf); if (r == 0) { diff --git a/libevmjit/ExecutionEngine.h b/libevmjit/ExecutionEngine.h index 15a4e6ef7..0c425e415 100644 --- a/libevmjit/ExecutionEngine.h +++ b/libevmjit/ExecutionEngine.h @@ -18,7 +18,7 @@ class ExecutionEngine public: ExecutionEngine(); - int run(std::unique_ptr module, u256& _gas, ExtVMFace* _ext = nullptr); + int run(std::unique_ptr module, u256& _gas, bool _outputLogs, ExtVMFace* _ext = nullptr); bytes returnData; }; diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index f39ab5755..17cbf5dc4 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -59,6 +59,11 @@ Ext::Ext(RuntimeManager& _runtimeManager): m_exp = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 4}, false), Linkage::ExternalLinkage, "ext_exp", module); m_codeAt = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, {argsTypes, 2}, false), Linkage::ExternalLinkage, "ext_codeAt", module); m_codesizeAt = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 3}, false), Linkage::ExternalLinkage, "ext_codesizeAt", module); + m_log0 = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 3}, false), Linkage::ExternalLinkage, "ext_log0", module); + m_log1 = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 4}, false), Linkage::ExternalLinkage, "ext_log1", module); + m_log2 = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 5}, false), Linkage::ExternalLinkage, "ext_log2", module); + m_log3 = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 6}, false), Linkage::ExternalLinkage, "ext_log3", module); + m_log4 = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 7}, false), Linkage::ExternalLinkage, "ext_log4", module); } llvm::Value* Ext::store(llvm::Value* _index) @@ -160,6 +165,21 @@ llvm::Value* Ext::codesizeAt(llvm::Value* _addr) return m_builder.CreateLoad(m_args[1]); } +void Ext::log(llvm::Value* _memIdx, llvm::Value* _numBytes, size_t _numTopics, std::array const& _topics) +{ + static llvm::Value* args[] = {nullptr, m_args[0], m_args[1], m_arg2, m_arg3, m_arg4, m_arg5}; + static llvm::Value* funcs[] = {m_log0, m_log1, m_log2, m_log3, m_log4}; + + args[0] = getRuntimeManager().getRuntimePtr(); + m_builder.CreateStore(_memIdx, m_args[0]); + m_builder.CreateStore(_numBytes, m_args[1]); + + for (size_t i = 0; i < _numTopics; ++i) + m_builder.CreateStore(_topics[i], args[i + 3]); + + m_builder.CreateCall(funcs[_numTopics], llvm::ArrayRef(args, _numTopics + 3)); +} + } @@ -289,6 +309,111 @@ extern "C" *o_ret = eth2llvm(u256(code.size())); } + void ext_show_bytes(bytesConstRef _bytes) + { + for (auto b : _bytes) + std::cerr << std::hex << std::setw(2) << std::setfill('0') << static_cast(b) << " "; + std::cerr << std::endl; + } + + EXPORT void ext_log0(Runtime* _rt, i256* _memIdx, i256* _numBytes) + { + auto&& ext = _rt->getExt(); + + auto memIdx = static_cast(llvm2eth(*_memIdx)); + auto numBytes = static_cast(llvm2eth(*_numBytes)); + + auto dataRef = bytesConstRef(_rt->getMemory().data() + memIdx, numBytes); + ext.log({}, dataRef); + + if (_rt->outputLogs()) + { + std::cerr << "LOG: "; + ext_show_bytes(dataRef); + } + } + + EXPORT void ext_log1(Runtime* _rt, i256* _memIdx, i256* _numBytes, i256* _topic1) + { + auto&& ext = _rt->getExt(); + + auto memIdx = static_cast(llvm2eth(*_memIdx)); + auto numBytes = static_cast(llvm2eth(*_numBytes)); + + auto topic1 = llvm2eth(*_topic1); + + auto dataRef = bytesConstRef(_rt->getMemory().data() + memIdx, numBytes); + ext.log({topic1}, dataRef); + + if (_rt->outputLogs()) + { + std::cerr << "LOG [" << topic1 << "]: "; + ext_show_bytes(dataRef); + } + } + + EXPORT void ext_log2(Runtime* _rt, i256* _memIdx, i256* _numBytes, i256* _topic1, i256* _topic2) + { + auto&& ext = _rt->getExt(); + + auto memIdx = static_cast(llvm2eth(*_memIdx)); + auto numBytes = static_cast(llvm2eth(*_numBytes)); + + auto topic1 = llvm2eth(*_topic1); + auto topic2 = llvm2eth(*_topic2); + + auto dataRef = bytesConstRef(_rt->getMemory().data() + memIdx, numBytes); + ext.log({topic1, topic2}, dataRef); + + if (_rt->outputLogs()) + { + std::cerr << "LOG [" << topic1 << "][" << topic2 << "]: "; + ext_show_bytes(dataRef); + } + } + + EXPORT void ext_log3(Runtime* _rt, i256* _memIdx, i256* _numBytes, i256* _topic1, i256* _topic2, i256* _topic3) + { + auto&& ext = _rt->getExt(); + + auto memIdx = static_cast(llvm2eth(*_memIdx)); + auto numBytes = static_cast(llvm2eth(*_numBytes)); + + auto topic1 = llvm2eth(*_topic1); + auto topic2 = llvm2eth(*_topic2); + auto topic3 = llvm2eth(*_topic3); + + auto dataRef = bytesConstRef(_rt->getMemory().data() + memIdx, numBytes); + ext.log({topic1, topic2, topic3}, dataRef); + + if (_rt->outputLogs()) + { + std::cerr << "LOG [" << topic1 << "][" << topic2 << "][" << topic3 << "]: "; + ext_show_bytes(dataRef); + } + } + + EXPORT void ext_log4(Runtime* _rt, i256* _memIdx, i256* _numBytes, i256* _topic1, i256* _topic2, i256* _topic3, i256* _topic4) + { + auto&& ext = _rt->getExt(); + + auto memIdx = static_cast(llvm2eth(*_memIdx)); + auto numBytes = static_cast(llvm2eth(*_numBytes)); + + auto topic1 = llvm2eth(*_topic1); + auto topic2 = llvm2eth(*_topic2); + auto topic3 = llvm2eth(*_topic3); + auto topic4 = llvm2eth(*_topic4); + + auto dataRef = bytesConstRef(_rt->getMemory().data() + memIdx, numBytes); + ext.log({topic1, topic2, topic3, topic4}, dataRef); + + if (_rt->outputLogs()) + { + std::cerr << "LOG [" << topic1 << "][" << topic2 << "][" << topic3 << "][" << topic4 << "]: "; + ext_show_bytes(dataRef); + } + } } } } diff --git a/libevmjit/Ext.h b/libevmjit/Ext.h index 8e70af7d0..54380dda6 100644 --- a/libevmjit/Ext.h +++ b/libevmjit/Ext.h @@ -31,8 +31,10 @@ public: llvm::Value* codeAt(llvm::Value* _addr); llvm::Value* codesizeAt(llvm::Value* _addr); + void log(llvm::Value* _memIdx, llvm::Value* _numBytes, size_t _numTopics, std::array const& _topics); private: + llvm::Value* m_args[2]; llvm::Value* m_arg2; llvm::Value* m_arg3; @@ -53,6 +55,11 @@ private: llvm::Function* m_exp; llvm::Function* m_codeAt; llvm::Function* m_codesizeAt; + llvm::Function* m_log0; + llvm::Function* m_log1; + llvm::Function* m_log2; + llvm::Function* m_log3; + llvm::Function* m_log4; }; diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 982dd9f36..8e52b648a 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -58,8 +58,9 @@ llvm::Twine getName(RuntimeData::Index _index) } } -Runtime::Runtime(u256 _gas, ExtVMFace& _ext, jmp_buf _jmpBuf): - m_ext(_ext) +Runtime::Runtime(u256 _gas, ExtVMFace& _ext, jmp_buf _jmpBuf, bool _outputLogs): + m_ext(_ext), + m_outputLogs(_outputLogs) { set(RuntimeData::Gas, _gas); set(RuntimeData::Address, fromAddress(_ext.myAddress)); @@ -101,6 +102,11 @@ bytesConstRef Runtime::getReturnData() const return {m_memory.data() + offset, size}; } +bool Runtime::outputLogs() const +{ + return m_outputLogs; +} + RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder): CompilerHelper(_builder) { diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index 8c784b394..8f485794a 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -63,7 +63,7 @@ using MemoryImpl = bytes; class Runtime { public: - Runtime(u256 _gas, ExtVMFace& _ext, jmp_buf _jmpBuf); + Runtime(u256 _gas, ExtVMFace& _ext, jmp_buf _jmpBuf, bool _outputLogs); Runtime(const Runtime&) = delete; void operator=(const Runtime&) = delete; @@ -77,6 +77,7 @@ public: u256 getGas() const; bytesConstRef getReturnData() const; decltype(&jmp_buf{}[0]) getJmpBuf() { return m_data.jmpBuf; } + bool outputLogs() const; private: void set(RuntimeData::Index _index, u256 _value); @@ -86,6 +87,7 @@ private: StackImpl m_stack; MemoryImpl m_memory; ExtVMFace& m_ext; + bool m_outputLogs; ///< write LOG statements to console }; class RuntimeManager: public CompilerHelper From bb243c4a284b685d96b46d57d160149feb11e1df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 14 Nov 2014 10:50:22 +0100 Subject: [PATCH 344/641] Fix VC proj --- windows/LibEthereum.vcxproj | 7 ++++--- windows/LibEthereum.vcxproj.filters | 15 +++++++++------ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/windows/LibEthereum.vcxproj b/windows/LibEthereum.vcxproj index 92fdfe8ca..be1940b8e 100644 --- a/windows/LibEthereum.vcxproj +++ b/windows/LibEthereum.vcxproj @@ -125,6 +125,7 @@ + true @@ -146,7 +147,6 @@ - @@ -342,6 +342,7 @@ + true @@ -369,7 +370,7 @@ - + @@ -573,4 +574,4 @@ - + \ No newline at end of file diff --git a/windows/LibEthereum.vcxproj.filters b/windows/LibEthereum.vcxproj.filters index cc39c8eaa..09770f5ed 100644 --- a/windows/LibEthereum.vcxproj.filters +++ b/windows/LibEthereum.vcxproj.filters @@ -40,9 +40,6 @@ libevmcore - - liblll - liblll @@ -205,6 +202,9 @@ libethereum + + libevmcore + @@ -252,8 +252,8 @@ liblll - - libevmcore + + libevmcore liblll @@ -441,6 +441,9 @@ libethereum + + libevmcore + @@ -477,4 +480,4 @@ {d838fece-fc20-42f6-bff5-97c236159b80} - + \ No newline at end of file From bb6d39f7cc7cd09bdbf7acf03fda52c78e47b07f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 14 Nov 2014 10:51:47 +0100 Subject: [PATCH 345/641] Update Instruction.h location --- evmcc/evmcc.cpp | 2 +- libevmjit/Compiler.cpp | 2 +- libevmjit/GasMeter.cpp | 2 +- libevmjit/GasMeter.h | 2 +- libevmjit/Utils.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/evmcc/evmcc.cpp b/evmcc/evmcc.cpp index 535a9aed9..81824f010 100644 --- a/evmcc/evmcc.cpp +++ b/evmcc/evmcc.cpp @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 295f3a131..2b970586e 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -13,7 +13,7 @@ #include #include -#include +#include #include "Type.h" #include "Memory.h" diff --git a/libevmjit/GasMeter.cpp b/libevmjit/GasMeter.cpp index 7a6a0ebd2..734931c32 100644 --- a/libevmjit/GasMeter.cpp +++ b/libevmjit/GasMeter.cpp @@ -5,7 +5,7 @@ #include #include -#include +#include #include #include "Type.h" diff --git a/libevmjit/GasMeter.h b/libevmjit/GasMeter.h index 3de227651..4be6c1a02 100644 --- a/libevmjit/GasMeter.h +++ b/libevmjit/GasMeter.h @@ -1,7 +1,7 @@ #pragma once -#include +#include #include "CompilerHelper.h" diff --git a/libevmjit/Utils.h b/libevmjit/Utils.h index 9fa9f050e..c3ed53a70 100644 --- a/libevmjit/Utils.h +++ b/libevmjit/Utils.h @@ -5,7 +5,7 @@ #include #include -#include +#include namespace dev { From 078b208b040d3e94f1fd71e6dddd0a803b587e7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 14 Nov 2014 11:07:05 +0100 Subject: [PATCH 346/641] Handle bytecode as bytes --- evmcc/evmcc.cpp | 2 +- libevmjit/Compiler.cpp | 6 +++--- libevmjit/Compiler.h | 6 +++--- libevmjit/ExecutionEngine.cpp | 3 +-- libevmjit/Utils.cpp | 2 +- libevmjit/Utils.h | 2 +- 6 files changed, 10 insertions(+), 11 deletions(-) diff --git a/evmcc/evmcc.cpp b/evmcc/evmcc.cpp index 81824f010..a04956fab 100644 --- a/evmcc/evmcc.cpp +++ b/evmcc/evmcc.cpp @@ -121,7 +121,7 @@ int main(int argc, char** argv) compilerOptions.optimizeStack = options.count("optimize-stack") > 0; auto compiler = eth::jit::Compiler(compilerOptions); - auto module = compiler.compile({bytecode.data(), bytecode.size()}); + auto module = compiler.compile(bytecode); auto compilationEndTime = std::chrono::high_resolution_clock::now(); diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 2b970586e..717ecff22 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -39,7 +39,7 @@ Compiler::Compiler(Options const& _options): Type::init(m_builder.getContext()); } -void Compiler::createBasicBlocks(bytesConstRef _bytecode) +void Compiler::createBasicBlocks(bytes const& _bytecode) { std::set splitPoints; // Sorted collections of instruction indices where basic blocks start/end @@ -151,7 +151,7 @@ void Compiler::createBasicBlocks(bytesConstRef _bytecode) m_indirectJumpTargets.push_back(&basicBlocks.find(*it)->second); } -std::unique_ptr Compiler::compile(bytesConstRef _bytecode) +std::unique_ptr Compiler::compile(bytes const& _bytecode) { auto module = std::unique_ptr(new llvm::Module("main", m_builder.getContext())); @@ -247,7 +247,7 @@ std::unique_ptr Compiler::compile(bytesConstRef _bytecode) } -void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytesConstRef _bytecode, RuntimeManager& _runtimeManager, +void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode, RuntimeManager& _runtimeManager, Arith256& _arith, Memory& _memory, Ext& _ext, GasMeter& _gasMeter, llvm::BasicBlock* _nextBasicBlock) { if (!_nextBasicBlock) // this is the last block in the code diff --git a/libevmjit/Compiler.h b/libevmjit/Compiler.h index 12b7f6e0e..a618f41a3 100644 --- a/libevmjit/Compiler.h +++ b/libevmjit/Compiler.h @@ -40,13 +40,13 @@ public: Compiler(Options const& _options); - std::unique_ptr compile(bytesConstRef _bytecode); + std::unique_ptr compile(bytes const& _bytecode); private: - void createBasicBlocks(bytesConstRef _bytecode); + void createBasicBlocks(bytes const& _bytecode); - void compileBasicBlock(BasicBlock& _basicBlock, bytesConstRef _bytecode, class RuntimeManager& _runtimeManager, class Arith256& _arith, class Memory& _memory, class Ext& _ext, class GasMeter& _gasMeter, llvm::BasicBlock* _nextBasicBlock); + void compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode, class RuntimeManager& _runtimeManager, class Arith256& _arith, class Memory& _memory, class Ext& _ext, class GasMeter& _gasMeter, llvm::BasicBlock* _nextBasicBlock); void removeDeadBlocks(); diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp index 4c617d9ea..f3e4132e9 100644 --- a/libevmjit/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -100,8 +100,7 @@ int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, ExtV _ext->currentBlock.gasLimit = 1008; std::string calldata = "Hello the Beautiful World of Ethereum!"; _ext->data = calldata; - unsigned char fakecode[] = {0x0d, 0x0e, 0x0a, 0x0d, 0x0b, 0x0e, 0xe, 0xf}; - _ext->code = decltype(_ext->code)(fakecode, 8); + _ext->code = { 0x0d, 0x0e, 0x0a, 0x0d, 0x0b, 0x0e, 0xe, 0xf }; } auto entryFunc = module->getFunction("main"); diff --git a/libevmjit/Utils.cpp b/libevmjit/Utils.cpp index 966dc69bd..548ee0e1f 100644 --- a/libevmjit/Utils.cpp +++ b/libevmjit/Utils.cpp @@ -35,7 +35,7 @@ i256 eth2llvm(u256 _u) return i; } -u256 readPushData(const byte*& _curr, const byte* _end) +u256 readPushData(bytes::const_iterator& _curr, bytes::const_iterator _end) { auto pushInst = *_curr; assert(Instruction(pushInst) >= Instruction::PUSH1 && Instruction(pushInst) <= Instruction::PUSH32); diff --git a/libevmjit/Utils.h b/libevmjit/Utils.h index c3ed53a70..54291f3e0 100644 --- a/libevmjit/Utils.h +++ b/libevmjit/Utils.h @@ -33,7 +33,7 @@ i256 eth2llvm(u256); /// Reads PUSH data from pointed fragment of bytecode and constructs number out of it /// Reading out of bytecode means reading 0 /// @param _curr is updates and points the last real byte read -u256 readPushData(const byte*& _curr, const byte* _end); +u256 readPushData(bytes::const_iterator& _curr, bytes::const_iterator _end); #define ANY_PUSH PUSH1: \ case Instruction::PUSH2: \ From ec4301014bf53814f9ff5de09913460e26d3ddb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 14 Nov 2014 11:07:14 +0100 Subject: [PATCH 347/641] Fix VM tester --- test/vm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/vm.cpp b/test/vm.cpp index 1c6022f50..67f088376 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -313,7 +313,7 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) try { output = vm->go(fev, fev.simpleTrace()).toVector(); - gas = vm.gas(); + gas = vm->gas(); } catch (OutOfGas const&) { From d4f18b45bc967bc1e5530852a4e8b1158a65ada8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 14 Nov 2014 11:44:51 +0100 Subject: [PATCH 348/641] Test unexpected storage entries --- test/TestHelper.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index c1a141abb..be05ef7fc 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -287,6 +287,12 @@ void checkStorage(map _expectedStore, map _resultStore, BOOST_CHECK_MESSAGE(expectedStoreValue == resultStoreValue, _expectedAddr << ": store[" << expectedStoreKey << "] = " << resultStoreValue << ", expected " << expectedStoreValue); } } + + for (auto&& resultStorePair : _resultStore) + { + if (!_expectedStore.count(resultStorePair.first)) + BOOST_ERROR("unexpected result store key " << resultStorePair.first); + } } std::string getTestPath() From 3d501db9dacbe7a4dc2eb961186d3b22a4a32b34 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Fri, 14 Nov 2014 14:39:06 +0100 Subject: [PATCH 349/641] libevmface -> libevmcore: updated cmake files --- evmcc/CMakeLists.txt | 2 +- libevmjit/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/evmcc/CMakeLists.txt b/evmcc/CMakeLists.txt index 488893509..26a586271 100644 --- a/evmcc/CMakeLists.txt +++ b/evmcc/CMakeLists.txt @@ -13,7 +13,7 @@ target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} ethereum) target_link_libraries(${EXECUTABLE} evm) -target_link_libraries(${EXECUTABLE} evmface) +target_link_libraries(${EXECUTABLE} evmcore) target_link_libraries(${EXECUTABLE} evmjit) if ("${TARGET_PLATFORM}" STREQUAL "w64") diff --git a/libevmjit/CMakeLists.txt b/libevmjit/CMakeLists.txt index cc63e72db..b06316dd2 100644 --- a/libevmjit/CMakeLists.txt +++ b/libevmjit/CMakeLists.txt @@ -18,7 +18,7 @@ include_directories(..) target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} evm) -target_link_libraries(${EXECUTABLE} evmface) +target_link_libraries(${EXECUTABLE} evmcore) if ("${TARGET_PLATFORM}" STREQUAL "w64") From d088957f088b6a43ea820e67345f053ec9875101 Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Fri, 14 Nov 2014 14:40:34 +0100 Subject: [PATCH 350/641] made _ext a mandatory arg of Runtime::run() --- evmcc/evmcc.cpp | 2 +- libevmjit/ExecutionEngine.h | 2 +- libevmjit/VM.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/evmcc/evmcc.cpp b/evmcc/evmcc.cpp index e3f7e9c8e..f8e2b12f0 100644 --- a/evmcc/evmcc.cpp +++ b/evmcc/evmcc.cpp @@ -172,7 +172,7 @@ int main(int argc, char** argv) { auto engine = eth::jit::ExecutionEngine(); u256 gas = initialGas; - auto result = engine.run(std::move(module), gas, options.count("show-logs") > 0); + auto result = engine.run(std::move(module), gas, options.count("show-logs") > 0, nullptr); return result; } } diff --git a/libevmjit/ExecutionEngine.h b/libevmjit/ExecutionEngine.h index 0c425e415..c47562981 100644 --- a/libevmjit/ExecutionEngine.h +++ b/libevmjit/ExecutionEngine.h @@ -18,7 +18,7 @@ class ExecutionEngine public: ExecutionEngine(); - int run(std::unique_ptr module, u256& _gas, bool _outputLogs, ExtVMFace* _ext = nullptr); + int run(std::unique_ptr module, u256& _gas, bool _outputLogs, ExtVMFace* _ext); bytes returnData; }; diff --git a/libevmjit/VM.cpp b/libevmjit/VM.cpp index 0c89587e9..e19156d6e 100644 --- a/libevmjit/VM.cpp +++ b/libevmjit/VM.cpp @@ -20,7 +20,7 @@ bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const&, uint64_t) auto module = Compiler(defaultOptions).compile(_ext.code); ExecutionEngine engine; - auto exitCode = engine.run(std::move(module), m_gas, &_ext); + auto exitCode = engine.run(std::move(module), m_gas, false, &_ext); switch (static_cast(exitCode)) { From 0389030674f3f95c99c899564c363246a09c51e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 14 Nov 2014 15:06:38 +0100 Subject: [PATCH 351/641] Move mock of ExtVMFace to evmcc tool --- evmcc/evmcc.cpp | 20 +++++++++++++++++++- libevmjit/ExecutionEngine.cpp | 24 ++---------------------- libevmjit/ExecutionEngine.h | 2 +- libevmjit/VM.cpp | 2 +- 4 files changed, 23 insertions(+), 25 deletions(-) diff --git a/evmcc/evmcc.cpp b/evmcc/evmcc.cpp index f8e2b12f0..16ab23e9b 100644 --- a/evmcc/evmcc.cpp +++ b/evmcc/evmcc.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -172,7 +173,24 @@ int main(int argc, char** argv) { auto engine = eth::jit::ExecutionEngine(); u256 gas = initialGas; - auto result = engine.run(std::move(module), gas, options.count("show-logs") > 0, nullptr); + + // Create fake ExtVM interface + eth::ExtVMFace ext; + ext.myAddress = Address(1122334455667788); + ext.caller = Address(0xfacefacefaceface); + ext.origin = Address(101010101010101010); + ext.value = 0xabcd; + ext.gasPrice = 1002; + ext.previousBlock.hash = u256(1003); + ext.currentBlock.coinbaseAddress = Address(1004); + ext.currentBlock.timestamp = 1005; + ext.currentBlock.number = 1006; + ext.currentBlock.difficulty = 1007; + ext.currentBlock.gasLimit = 1008; + ext.data = std::string("Hello the Beautiful World of Ethereum!"); + ext.code = { 0x0d, 0x0e, 0x0a, 0x0d, 0x0b, 0x0e, 0xe, 0xf }; + + auto result = engine.run(std::move(module), gas, options.count("show-logs") > 0, ext); return result; } } diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp index bdc107630..02b12d373 100644 --- a/libevmjit/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -39,7 +39,7 @@ ExecutionEngine::ExecutionEngine() { } -int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, bool _outputLogs, ExtVMFace* _ext) +int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, bool _outputLogs, ExtVMFace& _ext) { auto module = _module.get(); // Keep ownership of the module in _module @@ -82,33 +82,13 @@ int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, bool clog(JIT) << "Module finalization time: " << std::chrono::duration_cast(finalizationEndTime - finalizationStartTime).count(); - // Create fake ExtVM interface - if (!_ext) - { - _ext = new ExtVMFace; - _ext->myAddress = Address(1122334455667788); - _ext->caller = Address(0xfacefacefaceface); - _ext->origin = Address(101010101010101010); - _ext->value = 0xabcd; - _ext->gasPrice = 1002; - _ext->previousBlock.hash = u256(1003); - _ext->currentBlock.coinbaseAddress = Address(1004); - _ext->currentBlock.timestamp = 1005; - _ext->currentBlock.number = 1006; - _ext->currentBlock.difficulty = 1007; - _ext->currentBlock.gasLimit = 1008; - std::string calldata = "Hello the Beautiful World of Ethereum!"; - _ext->data = calldata; - _ext->code = { 0x0d, 0x0e, 0x0a, 0x0d, 0x0b, 0x0e, 0xe, 0xf }; - } - auto entryFunc = module->getFunction("main"); if (!entryFunc) BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("main function not found")); ReturnCode returnCode; std::jmp_buf buf; - Runtime runtime(_gas, *_ext, buf, _outputLogs); + Runtime runtime(_gas, _ext, buf, _outputLogs); auto r = setjmp(buf); if (r == 0) { diff --git a/libevmjit/ExecutionEngine.h b/libevmjit/ExecutionEngine.h index c47562981..8cf1ec746 100644 --- a/libevmjit/ExecutionEngine.h +++ b/libevmjit/ExecutionEngine.h @@ -18,7 +18,7 @@ class ExecutionEngine public: ExecutionEngine(); - int run(std::unique_ptr module, u256& _gas, bool _outputLogs, ExtVMFace* _ext); + int run(std::unique_ptr module, u256& _gas, bool _outputLogs, ExtVMFace& _ext); bytes returnData; }; diff --git a/libevmjit/VM.cpp b/libevmjit/VM.cpp index e19156d6e..9b60fccf1 100644 --- a/libevmjit/VM.cpp +++ b/libevmjit/VM.cpp @@ -20,7 +20,7 @@ bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const&, uint64_t) auto module = Compiler(defaultOptions).compile(_ext.code); ExecutionEngine engine; - auto exitCode = engine.run(std::move(module), m_gas, false, &_ext); + auto exitCode = engine.run(std::move(module), m_gas, false, _ext); switch (static_cast(exitCode)) { From f56e2edcd2e5fcedbcd83697c0de7a83765bde25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 14 Nov 2014 15:40:07 +0100 Subject: [PATCH 352/641] After merge changes --- windows/LibEthereum.vcxproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/windows/LibEthereum.vcxproj b/windows/LibEthereum.vcxproj index 1b63f2872..77b8f7e1a 100644 --- a/windows/LibEthereum.vcxproj +++ b/windows/LibEthereum.vcxproj @@ -480,21 +480,25 @@ + + + + From 2c340cd2c1b8a96063c01d9b3fbb6e3de0a8ceaf Mon Sep 17 00:00:00 2001 From: sveneh Date: Sun, 16 Nov 2014 21:25:35 +0100 Subject: [PATCH 353/641] Fixed issues caused by downgrading json-rpc-cpp to 0.2.1 introduced platform-specific direcory in extdep/install/ --- cmake/EthDependencies.cmake | 10 +++++++--- eth/CMakeLists.txt | 1 + extdep/CMakeLists.txt | 6 ++++-- extdep/cryptopp.cmake | 29 ++++++++++++++++------------- extdep/curl.cmake | 15 ++++----------- extdep/json-rpc-cpp.cmake | 18 ++++++++++++++---- extdep/json-rpc-cpp_linux.patch | 13 +++++++++++++ neth/CMakeLists.txt | 1 + 8 files changed, 60 insertions(+), 33 deletions(-) create mode 100644 extdep/json-rpc-cpp_linux.patch diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 376a6c03f..09de078c0 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -3,14 +3,18 @@ # by defining this variable, cmake will look for dependencies first in our own repository before looking in system paths like /usr/local/ ... # this must be set to point to the same directory as $ETH_DEPENDENCY_INSTALL_DIR in /extdep directory -set (CMAKE_FIND_ROOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/extdep/install") +string(TOLOWER ${CMAKE_SYSTEM_NAME} system_name) +set (CMAKE_FIND_ROOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/extdep/install/${system_name}") -find_package (CryptoPP 5.6.2 REQUIRED) + +# Dependencies must have a version number + EXACT, to ensure reproducible builds + +find_package (CryptoPP 5.6.2 EXACT REQUIRED) message(" - CryptoPP header: ${CRYPTOPP_INCLUDE_DIRS}") message(" - CryptoPP lib : ${CRYPTOPP_LIBRARIES}") -find_package (JsonRpcCpp REQUIRED) +find_package (JsonRpcCpp 0.2.1 EXACT REQUIRED) if (${JSON_RPC_CPP_FOUND}) message (" - json-rpc-cpp header: ${JSON_RPC_CPP_INCLUDE_DIRS}") message (" - json-rpc-cpp lib : ${JSON_RPC_CPP_LIBRARIES}") diff --git a/eth/CMakeLists.txt b/eth/CMakeLists.txt index cb3b01b4e..fbd7d6835 100644 --- a/eth/CMakeLists.txt +++ b/eth/CMakeLists.txt @@ -3,6 +3,7 @@ cmake_policy(SET CMP0015 NEW) aux_source_directory(. SRC_LIST) include_directories(..) +include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) set(EXECUTABLE eth) diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index 666ea5f15..88f4fba0a 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -2,8 +2,10 @@ cmake_minimum_required(VERSION 2.8) include(ExternalProject) -# all dependencies will be installed into this directory -set(ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/install") + +# all dependencies will be installed into this directory, separated by platform +string(TOLOWER ${CMAKE_SYSTEM_NAME} SYSTEM_NAME) +set(ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/install/${SYSTEM_NAME}") file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}) include(cryptopp.cmake) diff --git a/extdep/cryptopp.cmake b/extdep/cryptopp.cmake index 39a848649..3a1513e29 100644 --- a/extdep/cryptopp.cmake +++ b/extdep/cryptopp.cmake @@ -1,18 +1,21 @@ -if(${APPLE}) -ExternalProject_Add(cryptopp - URL https://downloads.sourceforge.net/project/cryptopp/cryptopp/5.6.2/cryptopp562.zip - BINARY_DIR cryptopp-prefix/src/cryptopp - CONFIGURE_COMMAND "" - BUILD_COMMAND make CXX=clang++ CXXFLAGS=-DCRYPTOPP_DISABLE_ASM - INSTALL_COMMAND make install PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} +# CryptoPP does not have good cross-platform support, there exist several different other projects to make it work ... + +if(APPLE) + ExternalProject_Add(cryptopp + URL https://downloads.sourceforge.net/project/cryptopp/cryptopp/5.6.2/cryptopp562.zip + BINARY_DIR cryptopp-prefix/src/cryptopp + CONFIGURE_COMMAND "" + BUILD_COMMAND make CXX=clang++ CXXFLAGS=-DCRYPTOPP_DISABLE_ASM + INSTALL_COMMAND make install PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} ) +# on Linux, the default Makefile does not work. else() -ExternalProject_Add(cryptopp - URL https://github.com/mmoss/cryptopp/archive/v5.6.2.zip - BINARY_DIR cryptopp-prefix/src/cryptopp - CONFIGURE_COMMAND "" - BUILD_COMMAND scons --shared --prefix=${ETH_DEPENDENCY_INSTALL_DIR} - INSTALL_COMMAND "" + ExternalProject_Add(cryptopp + URL https://github.com/mmoss/cryptopp/archive/v5.6.2.zip + BINARY_DIR cryptopp-prefix/src/cryptopp + CONFIGURE_COMMAND "" + BUILD_COMMAND scons --shared --prefix=${ETH_DEPENDENCY_INSTALL_DIR} + INSTALL_COMMAND "" ) endif() diff --git a/extdep/curl.cmake b/extdep/curl.cmake index 13e10361d..fa06d7ba0 100644 --- a/extdep/curl.cmake +++ b/extdep/curl.cmake @@ -1,20 +1,13 @@ - -set (CONFIG_CMD ./configure --prefix=${ETH_DEPENDENCY_INSTALL_DIR} --exec-prefix=${ETH_DEPENDENCY_INSTALL_DIR}) - -if(${APPLE}) +if(APPLE) set(CONFIG_CMD ./configure --with-darwinssl --prefix=${ETH_DEPENDENCY_INSTALL_DIR} --exec-prefix=${ETH_DEPENDENCY_INSTALL_DIR}) +else() + set (CONFIG_CMD ./configure --prefix=${ETH_DEPENDENCY_INSTALL_DIR} --exec-prefix=${ETH_DEPENDENCY_INSTALL_DIR}) endif() - - -ExternalProject_Add( - curl +ExternalProject_Add(curl URL http://curl.haxx.se/download/curl-7.38.0.tar.bz2 BINARY_DIR curl-prefix/src/curl CONFIGURE_COMMAND ${CONFIG_CMD} BUILD_COMMAND make -j 3 INSTALL_COMMAND make install ) - - - diff --git a/extdep/json-rpc-cpp.cmake b/extdep/json-rpc-cpp.cmake index ea26851b9..8d3b29c19 100644 --- a/extdep/json-rpc-cpp.cmake +++ b/extdep/json-rpc-cpp.cmake @@ -1,11 +1,21 @@ +# json-rpc-cpp is under heavy development, and multiplatform builds are not yet available. All the platforms currently need patches to make them work. + +if(APPLE) + set(PATCH_CMD patch -d src/example < ${CMAKE_CURRENT_SOURCE_DIR}/json-rpc-cpp_osx.patch) + set(CONFIG_CMD cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_MODULE_PATH:PATH=${CMAKE_CURRENT_SOURCE_DIR} -DETH_DEPENDENCY_INSTALL_DIR:PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST -Wno-dev .) +else() + set(PATCH_CMD patch --input=${CMAKE_CURRENT_SOURCE_DIR}/json-rpc-cpp_linux.patch --strip=1) + set(CONFIG_CMD cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_MODULE_PATH:PATH=${CMAKE_CURRENT_SOURCE_DIR} -DETH_DEPENDENCY_INSTALL_DIR:PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST .) +endif() + + ExternalProject_Add(json-rpc-cpp DEPENDS curl GIT_REPOSITORY https://github.com/cinemast/libjson-rpc-cpp.git GIT_TAG 0.2.1 BINARY_DIR json-rpc-cpp-prefix/src/json-rpc-cpp - CONFIGURE_COMMAND patch -d src/example < ${CMAKE_CURRENT_SOURCE_DIR}/json-rpc-cpp_osx.patch && cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_MODULE_PATH:PATH=${CMAKE_CURRENT_SOURCE_DIR} -DETH_DEPENDENCY_INSTALL_DIR:PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST -Wno-dev . + PATCH_COMMAND ${PATCH_CMD} + CONFIGURE_COMMAND ${CONFIG_CMD} BUILD_COMMAND make jsonrpc -j 3 INSTALL_COMMAND make install - ) - - +) diff --git a/extdep/json-rpc-cpp_linux.patch b/extdep/json-rpc-cpp_linux.patch new file mode 100644 index 000000000..40662f2a8 --- /dev/null +++ b/extdep/json-rpc-cpp_linux.patch @@ -0,0 +1,13 @@ +diff --git a/src/jsonrpc/CMakeLists.txt b/src/jsonrpc/CMakeLists.txt +index 79e8515..4e93eef 100644 +--- a/src/jsonrpc/CMakeLists.txt ++++ b/src/jsonrpc/CMakeLists.txt +@@ -12,7 +12,7 @@ set(VERSION_STRING ${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}) + set_target_properties(jsonrpc jsonrpcStatic PROPERTIES VERSION "${VERSION_STRING}" SOVERSION "${VERSION_MAJOR}") + + +-target_link_libraries(jsonrpc ${CURL_LIBRARIES}) ++target_link_libraries(jsonrpc ${CURL_LIBRARIES} dl pthread) + target_link_libraries(jsonrpcStatic ${CURL_LIBRARIES}) + + install(FILES ${jsonrpc_header} DESTINATION include/jsonrpc) diff --git a/neth/CMakeLists.txt b/neth/CMakeLists.txt index d9f551b18..bef34c4e3 100644 --- a/neth/CMakeLists.txt +++ b/neth/CMakeLists.txt @@ -4,6 +4,7 @@ aux_source_directory(. SRC_LIST) include_directories(..) include_directories(${LEVELDB_ID}) +include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) set(EXECUTABLE neth) From 63c8a8384cb2e97b25ad6ba4035b66641ae88661 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zaw=C5=82ocki?= Date: Mon, 17 Nov 2014 18:10:54 +0100 Subject: [PATCH 354/641] fixed libevmjit dependencies in cmake files --- eth/CMakeLists.txt | 1 + evmcc/CMakeLists.txt | 5 ++--- libevmjit/CMakeLists.txt | 1 - neth/CMakeLists.txt | 1 + test/CMakeLists.txt | 2 ++ 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/eth/CMakeLists.txt b/eth/CMakeLists.txt index 70ed25f5e..9239e79ac 100644 --- a/eth/CMakeLists.txt +++ b/eth/CMakeLists.txt @@ -14,6 +14,7 @@ target_link_libraries(${EXECUTABLE} secp256k1) target_link_libraries(${EXECUTABLE} gmp) if(EVMJIT) + target_link_libraries(${EXECUTABLE} evm) target_link_libraries(${EXECUTABLE} evmjit) endif() diff --git a/evmcc/CMakeLists.txt b/evmcc/CMakeLists.txt index 26a586271..a087539dc 100644 --- a/evmcc/CMakeLists.txt +++ b/evmcc/CMakeLists.txt @@ -11,10 +11,9 @@ add_executable(${EXECUTABLE} ${SRC_LIST}) target_link_libraries(${EXECUTABLE} boost_program_options) target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} ethcore) -target_link_libraries(${EXECUTABLE} ethereum) -target_link_libraries(${EXECUTABLE} evm) -target_link_libraries(${EXECUTABLE} evmcore) target_link_libraries(${EXECUTABLE} evmjit) +target_link_libraries(${EXECUTABLE} evm) +target_link_libraries(${EXECUTABLE} ethereum) if ("${TARGET_PLATFORM}" STREQUAL "w64") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") diff --git a/libevmjit/CMakeLists.txt b/libevmjit/CMakeLists.txt index b06316dd2..0b3226e14 100644 --- a/libevmjit/CMakeLists.txt +++ b/libevmjit/CMakeLists.txt @@ -17,7 +17,6 @@ include_directories(..) target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} ethcore) -target_link_libraries(${EXECUTABLE} evm) target_link_libraries(${EXECUTABLE} evmcore) diff --git a/neth/CMakeLists.txt b/neth/CMakeLists.txt index 8d8bf2ab5..c3d14c983 100644 --- a/neth/CMakeLists.txt +++ b/neth/CMakeLists.txt @@ -23,6 +23,7 @@ target_link_libraries(${EXECUTABLE} web3jsonrpc) endif() if(EVMJIT) + target_link_libraries(${EXECUTABLE} evm) target_link_libraries(${EXECUTABLE} evmjit) endif() diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 951db2c99..8d8430b5c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -21,6 +21,7 @@ if(JSONRPC_LS) target_link_libraries(testeth web3jsonrpc) endif() if (EVMJIT) + target_link_libraries(testeth evm) target_link_libraries(testeth evmjit) endif() @@ -29,6 +30,7 @@ target_link_libraries(createRandomTest ethcore) target_link_libraries(createRandomTest boost_chrono) target_link_libraries(createRandomTest boost_unit_test_framework) if (EVMJIT) + target_link_libraries(createRandomTest evm) target_link_libraries(createRandomTest evmjit) endif() From a66d369926b08e704d23c5ba13a1a399457e7538 Mon Sep 17 00:00:00 2001 From: sveneh Date: Tue, 18 Nov 2014 10:44:30 +0100 Subject: [PATCH 355/641] switched to a fork of json-rpc-cpp, roughly resembling v0.3.2. This fork has already preliminary windows support --- extdep/CMakeLists.txt | 3 ++- extdep/json-rpc-cpp.cmake | 14 ++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index 88f4fba0a..d2245277f 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -9,7 +9,8 @@ set(ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/install/${SYSTEM_NAM file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}) include(cryptopp.cmake) -include(curl.cmake) +# will be re-eanbled later +# include(curl.cmake) include(json-rpc-cpp.cmake) #include(miniupnpc.cmake) diff --git a/extdep/json-rpc-cpp.cmake b/extdep/json-rpc-cpp.cmake index 8d3b29c19..165a07ff4 100644 --- a/extdep/json-rpc-cpp.cmake +++ b/extdep/json-rpc-cpp.cmake @@ -1,21 +1,19 @@ -# json-rpc-cpp is under heavy development, and multiplatform builds are not yet available. All the platforms currently need patches to make them work. +# json-rpc-cpp is under heavy development, and multiplatform builds are not yet available. +# we use a forked repository which already has preliminary windows support if(APPLE) - set(PATCH_CMD patch -d src/example < ${CMAKE_CURRENT_SOURCE_DIR}/json-rpc-cpp_osx.patch) set(CONFIG_CMD cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_MODULE_PATH:PATH=${CMAKE_CURRENT_SOURCE_DIR} -DETH_DEPENDENCY_INSTALL_DIR:PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST -Wno-dev .) else() - set(PATCH_CMD patch --input=${CMAKE_CURRENT_SOURCE_DIR}/json-rpc-cpp_linux.patch --strip=1) set(CONFIG_CMD cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_MODULE_PATH:PATH=${CMAKE_CURRENT_SOURCE_DIR} -DETH_DEPENDENCY_INSTALL_DIR:PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST .) endif() ExternalProject_Add(json-rpc-cpp - DEPENDS curl - GIT_REPOSITORY https://github.com/cinemast/libjson-rpc-cpp.git - GIT_TAG 0.2.1 + # DEPENDS curl # re-enable later, when we build curl again + GIT_REPOSITORY https://github.com/gogo40/libjson-rpc-cpp.git + GIT_TAG 27f5da7a70c7a82b0614982cac829d6fd5fc8314 # this is roughly verson 0.3.2 BINARY_DIR json-rpc-cpp-prefix/src/json-rpc-cpp - PATCH_COMMAND ${PATCH_CMD} CONFIGURE_COMMAND ${CONFIG_CMD} - BUILD_COMMAND make jsonrpc -j 3 + BUILD_COMMAND make -j 3 INSTALL_COMMAND make install ) From 28d69e0981e575fd1a68e39a2683808f7aebf432 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Tue, 18 Nov 2014 11:46:57 +0100 Subject: [PATCH 356/641] common changes --- alethzero/OurWebThreeStubServer.cpp | 2 +- alethzero/OurWebThreeStubServer.h | 2 +- test/jsonrpc.cpp | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/alethzero/OurWebThreeStubServer.cpp b/alethzero/OurWebThreeStubServer.cpp index a40727e1e..fec0f9e8d 100644 --- a/alethzero/OurWebThreeStubServer.cpp +++ b/alethzero/OurWebThreeStubServer.cpp @@ -24,7 +24,7 @@ using namespace std; using namespace dev; using namespace dev::eth; -OurWebThreeStubServer::OurWebThreeStubServer(jsonrpc::AbstractServerConnector* _conn, dev::WebThreeDirect& _web3, std::vector const& _accounts): +OurWebThreeStubServer::OurWebThreeStubServer(jsonrpc::AbstractServerConnector& _conn, dev::WebThreeDirect& _web3, std::vector const& _accounts): WebThreeStubServer(_conn, _web3, _accounts) {} diff --git a/alethzero/OurWebThreeStubServer.h b/alethzero/OurWebThreeStubServer.h index b3492df5e..ef13964b9 100644 --- a/alethzero/OurWebThreeStubServer.h +++ b/alethzero/OurWebThreeStubServer.h @@ -29,7 +29,7 @@ class OurWebThreeStubServer: public QObject, public WebThreeStubServer Q_OBJECT public: - OurWebThreeStubServer(jsonrpc::AbstractServerConnector* _conn, dev::WebThreeDirect& _web3, std::vector const& _accounts); + OurWebThreeStubServer(jsonrpc::AbstractServerConnector& _conn, dev::WebThreeDirect& _web3, std::vector const& _accounts); virtual std::string shh_newIdentity() override; diff --git a/test/jsonrpc.cpp b/test/jsonrpc.cpp index 4c748a954..727791f6e 100644 --- a/test/jsonrpc.cpp +++ b/test/jsonrpc.cpp @@ -29,8 +29,8 @@ #include #include #include -#include -#include +#include +#include #include #include "JsonSpiritHeaders.h" #include "TestHelper.h" @@ -61,11 +61,11 @@ struct Setup web3->setIdealPeerCount(5); web3->ethereum()->setForceMining(true); - jsonrpcServer = unique_ptr(new WebThreeStubServer(new jsonrpc::CorsHttpServer(8080), *web3, {})); + jsonrpcServer = unique_ptr(new WebThreeStubServer(jsonrpc::CorsHttpServer(8080), *web3, {})); jsonrpcServer->setIdentities({}); jsonrpcServer->StartListening(); - jsonrpcClient = unique_ptr(new WebThreeStubClient(new jsonrpc::HttpClient("http://localhost:8080"))); + jsonrpcClient = unique_ptr(new WebThreeStubClient(jsonrpc::HttpClient("http://localhost:8080"))); } }; From cc92d2e501ae300c145437936a4ed622b4459aa8 Mon Sep 17 00:00:00 2001 From: sveneh Date: Tue, 18 Nov 2014 12:09:53 +0100 Subject: [PATCH 357/641] changed the source repository for libjson-rpc-cpp AGAIN, as the forked one did not build on OS X. Back to the official repo again. Windows support we will have to do ourself. --- extdep/json-rpc-cpp.cmake | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/extdep/json-rpc-cpp.cmake b/extdep/json-rpc-cpp.cmake index 165a07ff4..810fd3a0a 100644 --- a/extdep/json-rpc-cpp.cmake +++ b/extdep/json-rpc-cpp.cmake @@ -1,5 +1,5 @@ -# json-rpc-cpp is under heavy development, and multiplatform builds are not yet available. -# we use a forked repository which already has preliminary windows support +# json-rpc-cpp is under heavy development, not yet stable, and multiplatform builds are not yet available. +# DO NOT MESS WITH THESE SETTINGS! IF YOU HAVE TO MAKE CHANGES HERE, CONSULT sven@ethdev.com BEFOREHAND!! if(APPLE) set(CONFIG_CMD cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_MODULE_PATH:PATH=${CMAKE_CURRENT_SOURCE_DIR} -DETH_DEPENDENCY_INSTALL_DIR:PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST -Wno-dev .) @@ -8,10 +8,11 @@ else() endif() +# DO NOT CHANGE ANYTHING HERE! ExternalProject_Add(json-rpc-cpp # DEPENDS curl # re-enable later, when we build curl again - GIT_REPOSITORY https://github.com/gogo40/libjson-rpc-cpp.git - GIT_TAG 27f5da7a70c7a82b0614982cac829d6fd5fc8314 # this is roughly verson 0.3.2 + GIT_REPOSITORY https://github.com/cinemast/libjson-rpc-cpp.git + GIT_TAG v0.3.2 BINARY_DIR json-rpc-cpp-prefix/src/json-rpc-cpp CONFIGURE_COMMAND ${CONFIG_CMD} BUILD_COMMAND make -j 3 From 67bc10efd67a43fb5f27d5d731210487af508b66 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Tue, 18 Nov 2014 12:22:10 +0100 Subject: [PATCH 358/641] fixed test --- test/jsonrpc.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/jsonrpc.cpp b/test/jsonrpc.cpp index 727791f6e..25468dcc0 100644 --- a/test/jsonrpc.cpp +++ b/test/jsonrpc.cpp @@ -61,11 +61,12 @@ struct Setup web3->setIdealPeerCount(5); web3->ethereum()->setForceMining(true); - jsonrpcServer = unique_ptr(new WebThreeStubServer(jsonrpc::CorsHttpServer(8080), *web3, {})); + auto server = new jsonrpc::CorsHttpServer(8080); + jsonrpcServer = unique_ptr(new WebThreeStubServer(*server, *web3, {})); jsonrpcServer->setIdentities({}); jsonrpcServer->StartListening(); - - jsonrpcClient = unique_ptr(new WebThreeStubClient(jsonrpc::HttpClient("http://localhost:8080"))); + auto client = new jsonrpc::HttpClient("http://localhost:8080"); + jsonrpcClient = unique_ptr(new WebThreeStubClient(*client)); } }; From ddac0ebb31b205ec24573aba6729bfb3db928bd8 Mon Sep 17 00:00:00 2001 From: administrator Date: Thu, 20 Nov 2014 03:28:25 -0800 Subject: [PATCH 359/641] now also builds correctly on OS X --- extdep/cryptopp.cmake | 1 + libweb3jsonrpc/CMakeLists.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/extdep/cryptopp.cmake b/extdep/cryptopp.cmake index 3a1513e29..abb035c11 100644 --- a/extdep/cryptopp.cmake +++ b/extdep/cryptopp.cmake @@ -1,5 +1,6 @@ # CryptoPP does not have good cross-platform support, there exist several different other projects to make it work ... +# TODO the OS X build throws a lot of warnings, but compiles fine if(APPLE) ExternalProject_Add(cryptopp URL https://downloads.sourceforge.net/project/cryptopp/cryptopp/5.6.2/cryptopp562.zip diff --git a/libweb3jsonrpc/CMakeLists.txt b/libweb3jsonrpc/CMakeLists.txt index 8d45bcfd9..7d0695b30 100644 --- a/libweb3jsonrpc/CMakeLists.txt +++ b/libweb3jsonrpc/CMakeLists.txt @@ -25,6 +25,7 @@ if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) +target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_LIBRARIES}) if(READLINE_LS) target_link_libraries(${EXECUTABLE} ${READLINE_LS}) From 39f0fd1320a9b6c065113100b3a7875de937a6a0 Mon Sep 17 00:00:00 2001 From: sveneh Date: Thu, 20 Nov 2014 14:00:05 +0100 Subject: [PATCH 360/641] cleanup, Readme --- extdep/CMakeLists.txt | 4 ++-- extdep/Readme.md | 16 ++++++++++++++++ extdep/json-rpc-cpp_linux.patch | 13 ------------- extdep/json-rpc-cpp_osx.patch | 9 --------- 4 files changed, 18 insertions(+), 24 deletions(-) create mode 100644 extdep/Readme.md delete mode 100644 extdep/json-rpc-cpp_linux.patch delete mode 100644 extdep/json-rpc-cpp_osx.patch diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index d2245277f..5ef5e63d5 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -4,8 +4,8 @@ include(ExternalProject) # all dependencies will be installed into this directory, separated by platform -string(TOLOWER ${CMAKE_SYSTEM_NAME} SYSTEM_NAME) -set(ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/install/${SYSTEM_NAME}") +string(TOLOWER ${CMAKE_SYSTEM_NAME} _system_name) +set(ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/install/${_system_name}") file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}) include(cryptopp.cmake) diff --git a/extdep/Readme.md b/extdep/Readme.md new file mode 100644 index 000000000..1706f1fb9 --- /dev/null +++ b/extdep/Readme.md @@ -0,0 +1,16 @@ +# cpp-ethereum external dependencies + +**This is Work-in-Progress!** + +This directory hosts the external libraries that are needed to build cpp-ethereum. + +To automatically download, build, and link libraries, do +``` +cd extdep; mkdir build; cd build; cmake ..; make +``` +this will take some time. + + +To check which libraries are already included, check `CMakeLists.txt`. Other libraries still need to be fetched via the system's package manager. + +Libraries will be installed in `cpp-ethereum/extdep/install/` diff --git a/extdep/json-rpc-cpp_linux.patch b/extdep/json-rpc-cpp_linux.patch deleted file mode 100644 index 40662f2a8..000000000 --- a/extdep/json-rpc-cpp_linux.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/src/jsonrpc/CMakeLists.txt b/src/jsonrpc/CMakeLists.txt -index 79e8515..4e93eef 100644 ---- a/src/jsonrpc/CMakeLists.txt -+++ b/src/jsonrpc/CMakeLists.txt -@@ -12,7 +12,7 @@ set(VERSION_STRING ${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}) - set_target_properties(jsonrpc jsonrpcStatic PROPERTIES VERSION "${VERSION_STRING}" SOVERSION "${VERSION_MAJOR}") - - --target_link_libraries(jsonrpc ${CURL_LIBRARIES}) -+target_link_libraries(jsonrpc ${CURL_LIBRARIES} dl pthread) - target_link_libraries(jsonrpcStatic ${CURL_LIBRARIES}) - - install(FILES ${jsonrpc_header} DESTINATION include/jsonrpc) diff --git a/extdep/json-rpc-cpp_osx.patch b/extdep/json-rpc-cpp_osx.patch deleted file mode 100644 index 39165530d..000000000 --- a/extdep/json-rpc-cpp_osx.patch +++ /dev/null @@ -1,9 +0,0 @@ ---- ./src/example/CMakeLists.txt 2014-11-12 17:20:52.000000000 +0100 -+++ CMakeListsPatch.txt 2014-11-12 17:26:42.000000000 +0100 -@@ -12,6 +12,3 @@ - add_executable(stubserversample stubserver.cpp) - target_link_libraries(stubserversample jsonrpc) - -- --add_executable(xbmcremote xbmcremote.cpp) --target_link_libraries(xbmcremote jsonrpc) From 7a121c38b818449d4bb664277dfc15cdbf168b91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 20 Nov 2014 20:13:28 +0100 Subject: [PATCH 361/641] Do not catch OutOfGas exception in tests separately --- test/vm.cpp | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/test/vm.cpp b/test/vm.cpp index 03e03566c..3f8e0a233 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -306,7 +306,6 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) auto vm = VMFace::create(vmKind, fev.gas); bytes output; - auto outOfGas = false; auto startTime = std::chrono::high_resolution_clock::now(); u256 gas; @@ -316,11 +315,6 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) output = vm->go(fev, fev.simpleTrace()).toVector(); gas = vm->gas(); } - catch (OutOfGas const&) - { - outOfGas = true; - gas = 0; - } catch (VMException const& _e) { cnote << "VM did throw an exception: " << diagnostic_information(_e); @@ -373,11 +367,11 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) o["exec"] = mValue(fev.exportExec()); if (!vmExceptionOccured) { - o["post"] = mValue(fev.exportState()); - o["callcreates"] = fev.exportCallCreates(); - o["out"] = "0x" + toHex(output); - fev.push(o, "gas", gas); - } + o["post"] = mValue(fev.exportState()); + o["callcreates"] = fev.exportCallCreates(); + o["out"] = "0x" + toHex(output); + fev.push(o, "gas", gas); + } } else { @@ -397,10 +391,7 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) checkOutput(output, o); BOOST_CHECK_EQUAL(toInt(o["gas"]), gas); - - if (outOfGas) - BOOST_CHECK_MESSAGE(gas == 0, "Remaining gas not 0 in out-of-gas state"); - + auto& expectedAddrs = test.addresses; auto& resultAddrs = fev.addresses; for (auto&& expectedPair : expectedAddrs) From e29befcb960f37d7801ec9ce9d9352f9a7211238 Mon Sep 17 00:00:00 2001 From: debris Date: Mon, 24 Nov 2014 09:08:41 +0100 Subject: [PATCH 362/641] cryptopp msbuild --- extdep/CMakeLists.txt | 5 +++-- extdep/cryptopp.cmake | 25 ++++++++++++++++++------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index 5ef5e63d5..7551d2e98 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -6,11 +6,12 @@ include(ExternalProject) # all dependencies will be installed into this directory, separated by platform string(TOLOWER ${CMAKE_SYSTEM_NAME} _system_name) set(ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/install/${_system_name}") -file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}) +file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/lib) +file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/include) include(cryptopp.cmake) # will be re-eanbled later # include(curl.cmake) -include(json-rpc-cpp.cmake) +#include(json-rpc-cpp.cmake) #include(miniupnpc.cmake) diff --git a/extdep/cryptopp.cmake b/extdep/cryptopp.cmake index abb035c11..9f54244bc 100644 --- a/extdep/cryptopp.cmake +++ b/extdep/cryptopp.cmake @@ -3,12 +3,23 @@ # TODO the OS X build throws a lot of warnings, but compiles fine if(APPLE) ExternalProject_Add(cryptopp - URL https://downloads.sourceforge.net/project/cryptopp/cryptopp/5.6.2/cryptopp562.zip - BINARY_DIR cryptopp-prefix/src/cryptopp - CONFIGURE_COMMAND "" - BUILD_COMMAND make CXX=clang++ CXXFLAGS=-DCRYPTOPP_DISABLE_ASM - INSTALL_COMMAND make install PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -) + URL https://downloads.sourceforge.net/project/cryptopp/cryptopp/5.6.2/cryptopp562.zip + BINARY_DIR cryptopp-prefix/src/cryptopp + CONFIGURE_COMMAND "" + BUILD_COMMAND make CXX=clang++ CXXFLAGS=-DCRYPTOPP_DISABLE_ASM + INSTALL_COMMAND make install PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} + ) +elseif(WIN32) + file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/include/cryptopp) + + ExternalProject_Add(cryptopp + SVN_REPOSITORY http://svn.code.sf.net/p/cryptopp/code/trunk/c5 + SVN_REVISION -r "541" + BINARY_DIR cryptopp-prefix/src/cryptopp + CONFIGURE_COMMAND devenv cryptest.sln /upgrade + BUILD_COMMAND devenv cryptest.sln /build release + INSTALL_COMMAND cmd /c cp Win32/DLL_Output/Release/cryptopp.dll ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp Win32/DLL_Output/Release/cryptopp.lib ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp *.h ${ETH_DEPENDENCY_INSTALL_DIR}/include/cryptopp + ) # on Linux, the default Makefile does not work. else() ExternalProject_Add(cryptopp @@ -17,6 +28,6 @@ else() CONFIGURE_COMMAND "" BUILD_COMMAND scons --shared --prefix=${ETH_DEPENDENCY_INSTALL_DIR} INSTALL_COMMAND "" -) + ) endif() From 3918a50dbb741dc5d7f7ea29786f84ba181b633f Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Mon, 24 Nov 2014 22:42:50 +0100 Subject: [PATCH 363/641] EVM code updated in vmPerformanceTests --- evmcc/test/vmtests/vmPerformanceTest.json | 71 +++++------------------ 1 file changed, 15 insertions(+), 56 deletions(-) diff --git a/evmcc/test/vmtests/vmPerformanceTest.json b/evmcc/test/vmtests/vmPerformanceTest.json index 07baa6709..b3e47ae16 100644 --- a/evmcc/test/vmtests/vmPerformanceTest.json +++ b/evmcc/test/vmtests/vmPerformanceTest.json @@ -12,7 +12,7 @@ "exec" : { "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x60015d68010000000000000000908060010115600358", + "code" : "0x60015b68010000000000000000908060010109600356", "data" : "0x", "gas" : "1000000", "gasPrice" : "100000000000000", @@ -24,7 +24,7 @@ "post" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", - "code" : "0x60015d68010000000000000000908060010115600358", + "code" : "0x60015b68010000000000000000908060010109600356", "nonce" : "0", "storage" : { } @@ -33,7 +33,7 @@ "pre" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", - "code" : "0x60015d68010000000000000000908060010115600358", + "code" : "0x60015b68010000000000000000908060010109600356", "nonce" : "0", "storage" : { } } @@ -54,7 +54,7 @@ "exec" : { "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x620186a06080545d60006080530b0f60295960a0536080530160a0546001608053036080546008585d", + "code" : "0x620f42406080525b6000608051111560285760a0516080510160a0526001608051036080526007565b", "data" : "0x", "gas" : "10000000", "gasPrice" : "100000000000000", @@ -66,7 +66,7 @@ "post" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", - "code" : "0x620186a06080545d60006080530b0f60295960a0536080530160a0546001608053036080546008585d", + "code" : "0x620f42406080525b6000608051111560285760a0516080510160a0526001608051036080526007565b", "nonce" : "0", "storage" : { } @@ -75,48 +75,7 @@ "pre" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", - "code" : "0x620186a06080545d60006080530b0f60295960a0536080530160a0546001608053036080546008585d", - "nonce" : "0", - "storage" : { } - } - } - }, - - "recloop0x40000" : { - "callcreates" : [ ], - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "256", - "currentGasLimit" : "10000000", - "currentNumber" : "0", - "currentTimestamp" : "1", - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "exec" : { - "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x600c6204000060006015585d60005460206000f25d6000820e602e59602a60018303600183016015585d6030585d805d905090509058", - "data" : "0x", - "gas" : "10000000", - "gasPrice" : "100000000000000", - "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "value" : "1000000000000000000" - }, - "gas" : "4232808", - "out" : "0x0000000000000000000000000000000000000000000000000000000000040000", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x600c6204000060006015585d60005460206000f25d6000820e602e59602a60018303600183016015585d6030585d805d905090509058", - "nonce" : "0", - "storage" : { - } - } - }, - "pre" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x600c6204000060006015585d60005460206000f25d6000820e602e59602a60018303600183016015585d6030585d805d905090509058", + "code" : "0x620f42406080525b6000608051111560285760a0516080510160a0526001608051036080526007565b", "nonce" : "0", "storage" : { } } @@ -137,7 +96,7 @@ "exec" : { "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x600860196011585d60005460206000f25d6003810a6031596022600282036011585d602c600183036011585d016034585d60015d90509058", + "code" : "0x600760196010565b60005260206000f25b600381106030576021600282036010565b602b600183036010565b016033565b60015b90509056", "data" : "0x", "gas" : "10000000", "gasPrice" : "100000000000000", @@ -149,7 +108,7 @@ "post" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", - "code" : "0x600860196011585d60005460206000f25d6003810a6031596022600282036011585d602c600183036011585d016034585d60015d90509058", + "code" : "0x600760196010565b60005260206000f25b600381106030576021600282036010565b602b600183036010565b016033565b60015b90509056", "nonce" : "0", "storage" : { } @@ -158,7 +117,7 @@ "pre" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", - "code" : "0x600860196011585d60005460206000f25d6003810a6031596022600282036011585d602c600183036011585d016034585d60015d90509058", + "code" : "0x600760196010565b60005260206000f25b600381106030576021600282036010565b602b600183036010565b016033565b60015b90509056", "nonce" : "0", "storage" : { } @@ -180,7 +139,7 @@ "exec" : { "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x600a600360066013585d60005460206000f25d6000820e604b596000810e603a59603660018303603284600185036013585d6013585d6047585d60466001830360016013585d5d6050585d600181015d905090509058", + "code" : "0x6009600360066012565b60005260206000f25b60008214604a5760008114603957603560018303603184600185036012565b6012565b6046565b60456001830360016012565b5b604f565b600181015b905090509056", "data" : "0x", "gas" : "10000000", "gasPrice" : "100000000000000", @@ -192,7 +151,7 @@ "post" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", - "code" : "0x600a600360066013585d60005460206000f25d6000820e604b596000810e603a59603660018303603284600185036013585d6013585d6047585d60466001830360016013585d5d6050585d600181015d905090509058", + "code" : "0x6009600360066012565b60005260206000f25b60008214604a5760008114603957603560018303603184600185036012565b6012565b6046565b60456001830360016012565b5b604f565b600181015b905090509056", "nonce" : "0", "storage" : { } @@ -201,7 +160,7 @@ "pre" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", - "code" : "0x600a600360066013585d60005460206000f25d6000820e604b596000810e603a59603660018303603284600185036013585d6013585d6047585d60466001830360016013585d5d6050585d600181015d905090509058", + "code" : "0x6009600360066012565b60005260206000f25b60008214604a5760008114603957603560018303603184600185036012565b6012565b6046565b60456001830360016012565b5b604f565b600181015b905090509056", "nonce" : "0", "storage" : { } @@ -223,7 +182,7 @@ "exec" : { "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x6127105d600190038060000e6104615961001b600160005458005d610026600260005458005d610031600360005458005d61003c600460005458005d610047600560005458005d610052600660005458005d61005d600760005458005d610068600860005458005d610073600960005458005d61007e600a60005458005d610089600b60005458005d610094600c60005458005d61009f600d60005458005d6100aa600e60005458005d6100b5600f60005458005d6100c0601060005458005d6100cb601160005458005d6100d6601260005458005d6100e1601360005458005d6100ec601460005458005d6100f7601560005458005d610102601660005458005d61010d601760005458005d610118601860005458005d610123601960005458005d61012e601a60005458005d610139601b60005458005d610144601c60005458005d61014f601d60005458005d61015a601e60005458005d610165601f60005458005d610170602060005458005d61017b602160005458005d610186602260005458005d610191602360005458005d61019c602460005458005d6101a7602560005458005d6101b2602660005458005d6101bd602760005458005d6101c8602860005458005d6101d3602960005458005d6101de602a60005458005d6101e9602b60005458005d6101f4602c60005458005d6101ff602d60005458005d61020a602e60005458005d610215602f60005458005d610220603060005458005d61022b603160005458005d610236603260005458005d610241603360005458005d61024c603460005458005d610257603560005458005d610262603660005458005d61026d603760005458005d610278603860005458005d610283603960005458005d61028e603a60005458005d610299603b60005458005d6102a4603c60005458005d6102af603d60005458005d6102ba603e60005458005d6102c5603f60005458005d6102d0604060005458005d6102db604160005458005d6102e6604260005458005d6102f1604360005458005d6102fc604460005458005d610307604560005458005d610312604660005458005d61031d604760005458005d610328604860005458005d610333604960005458005d61033e604a60005458005d610349604b60005458005d610354604c60005458005d61035f604d60005458005d61036a604e60005458005d610375604f60005458005d610380605060005458005d61038b605160005458005d610396605260005458005d6103a1605360005458005d6103ac605460005458005d6103b7605560005458005d6103c2605660005458005d6103cd605760005458005d6103d8605860005458005d6103e3605960005458005d6103ee605a60005458005d6103f9605b60005458005d610404605c60005458005d61040f605d60005458005d61041a605e60005458005d610425605f60005458005d610430606060005458005d61043b606160005458005d610446606260005458005d610451606360005458005d61045c606460005458005d610004585d60206000f2", + "code" : "0x6103e85b60019003806000146104605761001a600160005256005b610025600260005256005b610030600360005256005b61003b600460005256005b610046600560005256005b610051600660005256005b61005c600760005256005b610067600860005256005b610072600960005256005b61007d600a60005256005b610088600b60005256005b610093600c60005256005b61009e600d60005256005b6100a9600e60005256005b6100b4600f60005256005b6100bf601060005256005b6100ca601160005256005b6100d5601260005256005b6100e0601360005256005b6100eb601460005256005b6100f6601560005256005b610101601660005256005b61010c601760005256005b610117601860005256005b610122601960005256005b61012d601a60005256005b610138601b60005256005b610143601c60005256005b61014e601d60005256005b610159601e60005256005b610164601f60005256005b61016f602060005256005b61017a602160005256005b610185602260005256005b610190602360005256005b61019b602460005256005b6101a6602560005256005b6101b1602660005256005b6101bc602760005256005b6101c7602860005256005b6101d2602960005256005b6101dd602a60005256005b6101e8602b60005256005b6101f3602c60005256005b6101fe602d60005256005b610209602e60005256005b610214602f60005256005b61021f603060005256005b61022a603160005256005b610235603260005256005b610240603360005256005b61024b603460005256005b610256603560005256005b610261603660005256005b61026c603760005256005b610277603860005256005b610282603960005256005b61028d603a60005256005b610298603b60005256005b6102a3603c60005256005b6102ae603d60005256005b6102b9603e60005256005b6102c4603f60005256005b6102cf604060005256005b6102da604160005256005b6102e5604260005256005b6102f0604360005256005b6102fb604460005256005b610306604560005256005b610311604660005256005b61031c604760005256005b610327604860005256005b610332604960005256005b61033d604a60005256005b610348604b60005256005b610353604c60005256005b61035e604d60005256005b610369604e60005256005b610374604f60005256005b61037f605060005256005b61038a605160005256005b610395605260005256005b6103a0605360005256005b6103ab605460005256005b6103b6605560005256005b6103c1605660005256005b6103cc605760005256005b6103d7605860005256005b6103e2605960005256005b6103ed605a60005256005b6103f8605b60005256005b610403605c60005256005b61040e605d60005256005b610419605e60005256005b610424605f60005256005b61042f606060005256005b61043a606160005256005b610445606260005256005b610450606360005256005b61045b606460005256005b610003565b60206000f2", "data" : "0x", "gas" : "10000000", "gasPrice" : "100000000000000", @@ -235,7 +194,7 @@ "post" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", - "code" : "0x6127105d600190038060000e6104615961001b600160005458005d610026600260005458005d610031600360005458005d61003c600460005458005d610047600560005458005d610052600660005458005d61005d600760005458005d610068600860005458005d610073600960005458005d61007e600a60005458005d610089600b60005458005d610094600c60005458005d61009f600d60005458005d6100aa600e60005458005d6100b5600f60005458005d6100c0601060005458005d6100cb601160005458005d6100d6601260005458005d6100e1601360005458005d6100ec601460005458005d6100f7601560005458005d610102601660005458005d61010d601760005458005d610118601860005458005d610123601960005458005d61012e601a60005458005d610139601b60005458005d610144601c60005458005d61014f601d60005458005d61015a601e60005458005d610165601f60005458005d610170602060005458005d61017b602160005458005d610186602260005458005d610191602360005458005d61019c602460005458005d6101a7602560005458005d6101b2602660005458005d6101bd602760005458005d6101c8602860005458005d6101d3602960005458005d6101de602a60005458005d6101e9602b60005458005d6101f4602c60005458005d6101ff602d60005458005d61020a602e60005458005d610215602f60005458005d610220603060005458005d61022b603160005458005d610236603260005458005d610241603360005458005d61024c603460005458005d610257603560005458005d610262603660005458005d61026d603760005458005d610278603860005458005d610283603960005458005d61028e603a60005458005d610299603b60005458005d6102a4603c60005458005d6102af603d60005458005d6102ba603e60005458005d6102c5603f60005458005d6102d0604060005458005d6102db604160005458005d6102e6604260005458005d6102f1604360005458005d6102fc604460005458005d610307604560005458005d610312604660005458005d61031d604760005458005d610328604860005458005d610333604960005458005d61033e604a60005458005d610349604b60005458005d610354604c60005458005d61035f604d60005458005d61036a604e60005458005d610375604f60005458005d610380605060005458005d61038b605160005458005d610396605260005458005d6103a1605360005458005d6103ac605460005458005d6103b7605560005458005d6103c2605660005458005d6103cd605760005458005d6103d8605860005458005d6103e3605960005458005d6103ee605a60005458005d6103f9605b60005458005d610404605c60005458005d61040f605d60005458005d61041a605e60005458005d610425605f60005458005d610430606060005458005d61043b606160005458005d610446606260005458005d610451606360005458005d61045c606460005458005d610004585d60206000f2", + "code" : "0x6103e85b60019003806000146104605761001a600160005256005b610025600260005256005b610030600360005256005b61003b600460005256005b610046600560005256005b610051600660005256005b61005c600760005256005b610067600860005256005b610072600960005256005b61007d600a60005256005b610088600b60005256005b610093600c60005256005b61009e600d60005256005b6100a9600e60005256005b6100b4600f60005256005b6100bf601060005256005b6100ca601160005256005b6100d5601260005256005b6100e0601360005256005b6100eb601460005256005b6100f6601560005256005b610101601660005256005b61010c601760005256005b610117601860005256005b610122601960005256005b61012d601a60005256005b610138601b60005256005b610143601c60005256005b61014e601d60005256005b610159601e60005256005b610164601f60005256005b61016f602060005256005b61017a602160005256005b610185602260005256005b610190602360005256005b61019b602460005256005b6101a6602560005256005b6101b1602660005256005b6101bc602760005256005b6101c7602860005256005b6101d2602960005256005b6101dd602a60005256005b6101e8602b60005256005b6101f3602c60005256005b6101fe602d60005256005b610209602e60005256005b610214602f60005256005b61021f603060005256005b61022a603160005256005b610235603260005256005b610240603360005256005b61024b603460005256005b610256603560005256005b610261603660005256005b61026c603760005256005b610277603860005256005b610282603960005256005b61028d603a60005256005b610298603b60005256005b6102a3603c60005256005b6102ae603d60005256005b6102b9603e60005256005b6102c4603f60005256005b6102cf604060005256005b6102da604160005256005b6102e5604260005256005b6102f0604360005256005b6102fb604460005256005b610306604560005256005b610311604660005256005b61031c604760005256005b610327604860005256005b610332604960005256005b61033d604a60005256005b610348604b60005256005b610353604c60005256005b61035e604d60005256005b610369604e60005256005b610374604f60005256005b61037f605060005256005b61038a605160005256005b610395605260005256005b6103a0605360005256005b6103ab605460005256005b6103b6605560005256005b6103c1605660005256005b6103cc605760005256005b6103d7605860005256005b6103e2605960005256005b6103ed605a60005256005b6103f8605b60005256005b610403605c60005256005b61040e605d60005256005b610419605e60005256005b610424605f60005256005b61042f606060005256005b61043a606160005256005b610445606260005256005b610450606360005256005b61045b606460005256005b610003565b60206000f2", "nonce" : "0", "storage" : { } @@ -244,7 +203,7 @@ "pre" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", - "code" : "0x6127105d600190038060000e6104615961001b600160005458005d610026600260005458005d610031600360005458005d61003c600460005458005d610047600560005458005d610052600660005458005d61005d600760005458005d610068600860005458005d610073600960005458005d61007e600a60005458005d610089600b60005458005d610094600c60005458005d61009f600d60005458005d6100aa600e60005458005d6100b5600f60005458005d6100c0601060005458005d6100cb601160005458005d6100d6601260005458005d6100e1601360005458005d6100ec601460005458005d6100f7601560005458005d610102601660005458005d61010d601760005458005d610118601860005458005d610123601960005458005d61012e601a60005458005d610139601b60005458005d610144601c60005458005d61014f601d60005458005d61015a601e60005458005d610165601f60005458005d610170602060005458005d61017b602160005458005d610186602260005458005d610191602360005458005d61019c602460005458005d6101a7602560005458005d6101b2602660005458005d6101bd602760005458005d6101c8602860005458005d6101d3602960005458005d6101de602a60005458005d6101e9602b60005458005d6101f4602c60005458005d6101ff602d60005458005d61020a602e60005458005d610215602f60005458005d610220603060005458005d61022b603160005458005d610236603260005458005d610241603360005458005d61024c603460005458005d610257603560005458005d610262603660005458005d61026d603760005458005d610278603860005458005d610283603960005458005d61028e603a60005458005d610299603b60005458005d6102a4603c60005458005d6102af603d60005458005d6102ba603e60005458005d6102c5603f60005458005d6102d0604060005458005d6102db604160005458005d6102e6604260005458005d6102f1604360005458005d6102fc604460005458005d610307604560005458005d610312604660005458005d61031d604760005458005d610328604860005458005d610333604960005458005d61033e604a60005458005d610349604b60005458005d610354604c60005458005d61035f604d60005458005d61036a604e60005458005d610375604f60005458005d610380605060005458005d61038b605160005458005d610396605260005458005d6103a1605360005458005d6103ac605460005458005d6103b7605560005458005d6103c2605660005458005d6103cd605760005458005d6103d8605860005458005d6103e3605960005458005d6103ee605a60005458005d6103f9605b60005458005d610404605c60005458005d61040f605d60005458005d61041a605e60005458005d610425605f60005458005d610430606060005458005d61043b606160005458005d610446606260005458005d610451606360005458005d61045c606460005458005d610004585d60206000f2", + "code" : "0x6103e85b60019003806000146104605761001a600160005256005b610025600260005256005b610030600360005256005b61003b600460005256005b610046600560005256005b610051600660005256005b61005c600760005256005b610067600860005256005b610072600960005256005b61007d600a60005256005b610088600b60005256005b610093600c60005256005b61009e600d60005256005b6100a9600e60005256005b6100b4600f60005256005b6100bf601060005256005b6100ca601160005256005b6100d5601260005256005b6100e0601360005256005b6100eb601460005256005b6100f6601560005256005b610101601660005256005b61010c601760005256005b610117601860005256005b610122601960005256005b61012d601a60005256005b610138601b60005256005b610143601c60005256005b61014e601d60005256005b610159601e60005256005b610164601f60005256005b61016f602060005256005b61017a602160005256005b610185602260005256005b610190602360005256005b61019b602460005256005b6101a6602560005256005b6101b1602660005256005b6101bc602760005256005b6101c7602860005256005b6101d2602960005256005b6101dd602a60005256005b6101e8602b60005256005b6101f3602c60005256005b6101fe602d60005256005b610209602e60005256005b610214602f60005256005b61021f603060005256005b61022a603160005256005b610235603260005256005b610240603360005256005b61024b603460005256005b610256603560005256005b610261603660005256005b61026c603760005256005b610277603860005256005b610282603960005256005b61028d603a60005256005b610298603b60005256005b6102a3603c60005256005b6102ae603d60005256005b6102b9603e60005256005b6102c4603f60005256005b6102cf604060005256005b6102da604160005256005b6102e5604260005256005b6102f0604360005256005b6102fb604460005256005b610306604560005256005b610311604660005256005b61031c604760005256005b610327604860005256005b610332604960005256005b61033d604a60005256005b610348604b60005256005b610353604c60005256005b61035e604d60005256005b610369604e60005256005b610374604f60005256005b61037f605060005256005b61038a605160005256005b610395605260005256005b6103a0605360005256005b6103ab605460005256005b6103b6605560005256005b6103c1605660005256005b6103cc605760005256005b6103d7605860005256005b6103e2605960005256005b6103ed605a60005256005b6103f8605b60005256005b610403605c60005256005b61040e605d60005256005b610419605e60005256005b610424605f60005256005b61042f606060005256005b61043a606160005256005b610445606260005256005b610450606360005256005b61045b606460005256005b610003565b60206000f2", "nonce" : "0", "storage" : { } From 8b8a67c7b6e67edcb2126fcf9c2bb80f69689e87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zaw=C5=82ocki?= Date: Tue, 25 Nov 2014 00:42:07 +0100 Subject: [PATCH 364/641] output gas updated in vmPerformanceTest.json --- evmcc/test/vmtests/vmPerformanceTest.json | 46 +++++++++++------------ 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/evmcc/test/vmtests/vmPerformanceTest.json b/evmcc/test/vmtests/vmPerformanceTest.json index b3e47ae16..604e45993 100644 --- a/evmcc/test/vmtests/vmPerformanceTest.json +++ b/evmcc/test/vmtests/vmPerformanceTest.json @@ -4,7 +4,7 @@ "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", "currentDifficulty" : "256", - "currentGasLimit" : "1000000", + "currentGasLimit" : "10000000", "currentNumber" : "0", "currentTimestamp" : "1", "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" @@ -14,7 +14,7 @@ "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", "code" : "0x60015b68010000000000000000908060010109600356", "data" : "0x", - "gas" : "1000000", + "gas" : "10000000", "gasPrice" : "100000000000000", "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", "value" : "1000000000000000000" @@ -46,7 +46,7 @@ "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", "currentDifficulty" : "256", - "currentGasLimit" : "10000000", + "currentGasLimit" : "100000000", "currentNumber" : "0", "currentTimestamp" : "1", "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" @@ -56,13 +56,13 @@ "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", "code" : "0x620f42406080525b6000608051111560285760a0516080510160a0526001608051036080526007565b", "data" : "0x", - "gas" : "10000000", + "gas" : "30000000", "gasPrice" : "100000000000000", "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", "value" : "1000000000000000000" }, - "gas" : "7799983", - "out" : "0x0", + "gas" : "6999982", + "out" : "0x00", "post" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", @@ -88,7 +88,7 @@ "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", "currentDifficulty" : "256", - "currentGasLimit" : "10000000", + "currentGasLimit" : "100000000", "currentNumber" : "0", "currentTimestamp" : "1", "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" @@ -96,19 +96,19 @@ "exec" : { "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x600760196010565b60005260206000f25b600381106030576021600282036010565b602b600183036010565b016033565b60015b90509056", + "code" : "0x6007601e6010565b60005260206000f25b600381106030576021600282036010565b602b600183036010565b016033565b60015b90509056", "data" : "0x", - "gas" : "10000000", + "gas" : "40000000", "gasPrice" : "100000000000000", "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", "value" : "1000000000000000000" }, - "gas" : "7374139", - "out" : "0x0000000000000000000000000000000000000000000000000000000000012511", + "gas" : "5886377", + "out" : "0x00000000000000000000000000000000000000000000000000000000000cb228", "post" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", - "code" : "0x600760196010565b60005260206000f25b600381106030576021600282036010565b602b600183036010565b016033565b60015b90509056", + "code" : "0x6007601e6010565b60005260206000f25b600381106030576021600282036010565b602b600183036010565b016033565b60015b90509056", "nonce" : "0", "storage" : { } @@ -117,7 +117,7 @@ "pre" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", - "code" : "0x600760196010565b60005260206000f25b600381106030576021600282036010565b602b600183036010565b016033565b60015b90509056", + "code" : "0x6007601e6010565b60005260206000f25b600381106030576021600282036010565b602b600183036010565b016033565b60015b90509056", "nonce" : "0", "storage" : { } @@ -125,13 +125,13 @@ } }, - "ackermann36" : { + "ackermann37" : { "callcreates" : [ ], "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", "currentDifficulty" : "256", - "currentGasLimit" : "10000000", + "currentGasLimit" : "20000000", "currentNumber" : "0", "currentTimestamp" : "1", "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" @@ -139,19 +139,19 @@ "exec" : { "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x6009600360066012565b60005260206000f25b60008214604a5760008114603957603560018303603184600185036012565b6012565b6046565b60456001830360016012565b5b604f565b600181015b905090509056", + "code" : "0x6009600360076012565b60005260206000f25b60008214604a5760008114603957603560018303603184600185036012565b6012565b6046565b60456001830360016012565b5b604f565b600181015b905090509056", "data" : "0x", - "gas" : "10000000", + "gas" : "20000000", "gasPrice" : "100000000000000", "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", "value" : "1000000000000000000" }, - "gas" : "5865402", - "out" : "0x00000000000000000000000000000000000000000000000000000000000001fd", + "gas" : "913456", + "out" : "0x00000000000000000000000000000000000000000000000000000000000003fd", "post" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", - "code" : "0x6009600360066012565b60005260206000f25b60008214604a5760008114603957603560018303603184600185036012565b6012565b6046565b60456001830360016012565b5b604f565b600181015b905090509056", + "code" : "0x6009600360076012565b60005260206000f25b60008214604a5760008114603957603560018303603184600185036012565b6012565b6046565b60456001830360016012565b5b604f565b600181015b905090509056", "nonce" : "0", "storage" : { } @@ -160,7 +160,7 @@ "pre" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", - "code" : "0x6009600360066012565b60005260206000f25b60008214604a5760008114603957603560018303603184600185036012565b6012565b6046565b60456001830360016012565b5b604f565b600181015b905090509056", + "code" : "0x6009600360076012565b60005260206000f25b60008214604a5760008114603957603560018303603184600185036012565b6012565b6046565b60456001830360016012565b5b604f565b600181015b905090509056", "nonce" : "0", "storage" : { } @@ -184,12 +184,12 @@ "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", "code" : "0x6103e85b60019003806000146104605761001a600160005256005b610025600260005256005b610030600360005256005b61003b600460005256005b610046600560005256005b610051600660005256005b61005c600760005256005b610067600860005256005b610072600960005256005b61007d600a60005256005b610088600b60005256005b610093600c60005256005b61009e600d60005256005b6100a9600e60005256005b6100b4600f60005256005b6100bf601060005256005b6100ca601160005256005b6100d5601260005256005b6100e0601360005256005b6100eb601460005256005b6100f6601560005256005b610101601660005256005b61010c601760005256005b610117601860005256005b610122601960005256005b61012d601a60005256005b610138601b60005256005b610143601c60005256005b61014e601d60005256005b610159601e60005256005b610164601f60005256005b61016f602060005256005b61017a602160005256005b610185602260005256005b610190602360005256005b61019b602460005256005b6101a6602560005256005b6101b1602660005256005b6101bc602760005256005b6101c7602860005256005b6101d2602960005256005b6101dd602a60005256005b6101e8602b60005256005b6101f3602c60005256005b6101fe602d60005256005b610209602e60005256005b610214602f60005256005b61021f603060005256005b61022a603160005256005b610235603260005256005b610240603360005256005b61024b603460005256005b610256603560005256005b610261603660005256005b61026c603760005256005b610277603860005256005b610282603960005256005b61028d603a60005256005b610298603b60005256005b6102a3603c60005256005b6102ae603d60005256005b6102b9603e60005256005b6102c4603f60005256005b6102cf604060005256005b6102da604160005256005b6102e5604260005256005b6102f0604360005256005b6102fb604460005256005b610306604560005256005b610311604660005256005b61031c604760005256005b610327604860005256005b610332604960005256005b61033d604a60005256005b610348604b60005256005b610353604c60005256005b61035e604d60005256005b610369604e60005256005b610374604f60005256005b61037f605060005256005b61038a605160005256005b610395605260005256005b6103a0605360005256005b6103ab605460005256005b6103b6605560005256005b6103c1605660005256005b6103cc605760005256005b6103d7605860005256005b6103e2605960005256005b6103ed605a60005256005b6103f8605b60005256005b610403605c60005256005b61040e605d60005256005b610419605e60005256005b610424605f60005256005b61042f606060005256005b61043a606160005256005b610445606260005256005b610450606360005256005b61045b606460005256005b610003565b60206000f2", "data" : "0x", - "gas" : "10000000", + "gas" : "1000000", "gasPrice" : "100000000000000", "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", "value" : "1000000000000000000" }, - "gas" : "4900496", + "gas" : "389596", "out" : "0x0000000000000000000000000000000000000000000000000000000000000064", "post" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { From 01167d1b354fe26da5eafed510975b811005ac49 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 26 Nov 2014 15:42:36 +0100 Subject: [PATCH 365/641] argtable && jsoncpp msbuild --- extdep/CMakeLists.txt | 4 +++- extdep/argtable2.cmake | 12 ++++++++++++ extdep/jsoncpp.cmake | 15 +++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 extdep/argtable2.cmake create mode 100644 extdep/jsoncpp.cmake diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index 7551d2e98..4871d5486 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -9,7 +9,9 @@ set(ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/install/${_system_na file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/lib) file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/include) -include(cryptopp.cmake) +include(jsoncpp.cmake) +#include(argtable2.cmake) +#include(cryptopp.cmake) # will be re-eanbled later # include(curl.cmake) #include(json-rpc-cpp.cmake) diff --git a/extdep/argtable2.cmake b/extdep/argtable2.cmake new file mode 100644 index 000000000..3da2f7534 --- /dev/null +++ b/extdep/argtable2.cmake @@ -0,0 +1,12 @@ +if(APPLE) + +elseif(WIN32) +ExternalProject_Add(argtable2 + URL http://sourceforge.net/projects/argtable/files/argtable/argtable-2.13/argtable2-13.tar.gz + BINARY_DIR argtable2-prefix/src/argtable2 + CONFIGURE_COMMAND cmake . + BUILD_COMMAND devenv argtable2.sln /build release + INSTALL_COMMAND cmd /c cp src/Release/argtable2.lib ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp src/argtable2.h ${ETH_DEPENDENCY_INSTALL_DIR}/include +) +else() +endif() diff --git a/extdep/jsoncpp.cmake b/extdep/jsoncpp.cmake new file mode 100644 index 000000000..b3bdef5e2 --- /dev/null +++ b/extdep/jsoncpp.cmake @@ -0,0 +1,15 @@ +if(APPLE) + +elseif(WIN32) + +file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/include/jsoncpp) +ExternalProject_Add(jsoncpp + GIT_REPOSITORY https://github.com/open-source-parsers/jsoncpp + GIT_TAG svn-import + BINARY_DIR jsoncpp-prefix/src/jsoncpp + CONFIGURE_COMMAND cmake . + BUILD_COMMAND devenv jsoncpp.sln /build release + INSTALL_COMMAND cmd /c cp lib/Release/jsoncpp.lib ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp -R include/json ${ETH_DEPENDENCY_INSTALL_DIR}/include/jsoncpp +) +else() +endif() From 8dd7affd09165fe44ea7a625dfe4677923c9349f Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 26 Nov 2014 20:39:16 +0100 Subject: [PATCH 366/641] jsonrpc visual studio windows build! --- extdep/CMakeLists.txt | 10 ++++++---- extdep/argtable2.cmake | 3 ++- extdep/curl.cmake | 29 +++++++++++++++++++++++------ extdep/json-rpc-cpp.cmake | 37 +++++++++++++++++++++++++++++-------- 4 files changed, 60 insertions(+), 19 deletions(-) diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index 4871d5486..5686a0c5d 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -9,11 +9,13 @@ set(ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/install/${_system_na file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/lib) file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/include) +include(curl.cmake) include(jsoncpp.cmake) -#include(argtable2.cmake) -#include(cryptopp.cmake) +include(argtable2.cmake) +include(json-rpc-cpp.cmake) +include(cryptopp.cmake) + # will be re-eanbled later # include(curl.cmake) -#include(json-rpc-cpp.cmake) -#include(miniupnpc.cmake) +# include(miniupnpc.cmake) diff --git a/extdep/argtable2.cmake b/extdep/argtable2.cmake index 3da2f7534..88063a40f 100644 --- a/extdep/argtable2.cmake +++ b/extdep/argtable2.cmake @@ -2,7 +2,8 @@ if(APPLE) elseif(WIN32) ExternalProject_Add(argtable2 - URL http://sourceforge.net/projects/argtable/files/argtable/argtable-2.13/argtable2-13.tar.gz + GIT_REPOSITORY https://github.com/debris/argtable.git + GIT_TAG master BINARY_DIR argtable2-prefix/src/argtable2 CONFIGURE_COMMAND cmake . BUILD_COMMAND devenv argtable2.sln /build release diff --git a/extdep/curl.cmake b/extdep/curl.cmake index fa06d7ba0..d4963c1d5 100644 --- a/extdep/curl.cmake +++ b/extdep/curl.cmake @@ -1,13 +1,30 @@ if(APPLE) - set(CONFIG_CMD ./configure --with-darwinssl --prefix=${ETH_DEPENDENCY_INSTALL_DIR} --exec-prefix=${ETH_DEPENDENCY_INSTALL_DIR}) -else() - set (CONFIG_CMD ./configure --prefix=${ETH_DEPENDENCY_INSTALL_DIR} --exec-prefix=${ETH_DEPENDENCY_INSTALL_DIR}) -endif() +ExternalProject_Add(curl + URL http://curl.haxx.se/download/curl-7.38.0.tar.bz2 + BINARY_DIR curl-prefix/src/curl + CONFIGURE_COMMAND ./configure --with-darwinssl --prefix=${ETH_DEPENDENCY_INSTALL_DIR} --exec-prefix=${ETH_DEPENDENCY_INSTALL_DIR} + BUILD_COMMAND make -j 3 + INSTALL_COMMAND make install + ) +elseif(WIN32) +ExternalProject_Add(curl + GIT_REPOSITORY https://github.com/debris/libcurl-7.29 + GIT_TAG master + BINARY_DIR curl-prefix/src/curl + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND cmd /c cp lib/release/libcurl.lib ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp -R include/curl ${ETH_DEPENDENCY_INSTALL_DIR}/include + ) +else() ExternalProject_Add(curl URL http://curl.haxx.se/download/curl-7.38.0.tar.bz2 BINARY_DIR curl-prefix/src/curl - CONFIGURE_COMMAND ${CONFIG_CMD} + CONFIGURE_COMMAND CONFIG_CMD ./configure --prefix=${ETH_DEPENDENCY_INSTALL_DIR} --exec-prefix=${ETH_DEPENDENCY_INSTALL_DIR} BUILD_COMMAND make -j 3 INSTALL_COMMAND make install -) + ) + +endif() + + diff --git a/extdep/json-rpc-cpp.cmake b/extdep/json-rpc-cpp.cmake index 810fd3a0a..baba1bb19 100644 --- a/extdep/json-rpc-cpp.cmake +++ b/extdep/json-rpc-cpp.cmake @@ -1,20 +1,41 @@ # json-rpc-cpp is under heavy development, not yet stable, and multiplatform builds are not yet available. # DO NOT MESS WITH THESE SETTINGS! IF YOU HAVE TO MAKE CHANGES HERE, CONSULT sven@ethdev.com BEFOREHAND!! -if(APPLE) - set(CONFIG_CMD cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_MODULE_PATH:PATH=${CMAKE_CURRENT_SOURCE_DIR} -DETH_DEPENDENCY_INSTALL_DIR:PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST -Wno-dev .) -else() - set(CONFIG_CMD cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_MODULE_PATH:PATH=${CMAKE_CURRENT_SOURCE_DIR} -DETH_DEPENDENCY_INSTALL_DIR:PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST .) -endif() +# DO NOT CHANGE ANYTHING HERE! +if(APPLE) +ExternalProject_Add(json-rpc-cpp + # DEPENDS argtable2 jsoncpp + # DEPENDS curl # re-enable later, when we build curl again + GIT_REPOSITORY https://github.com/cinemast/libjson-rpc-cpp.git + GIT_TAG v0.3.2 + BINARY_DIR json-rpc-cpp-prefix/src/json-rpc-cpp + CONFIGURE_COMMAND cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_MODULE_PATH:PATH=${CMAKE_CURRENT_SOURCE_DIR} -DETH_DEPENDENCY_INSTALL_DIR:PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST -Wno-dev . + BUILD_COMMAND make -j 3 + INSTALL_COMMAND make install + ) -# DO NOT CHANGE ANYTHING HERE! +elseif(WIN32) ExternalProject_Add(json-rpc-cpp + DEPENDS argtable2 jsoncpp curl + GIT_REPOSITORY https://github.com/debris/libjson-rpc-cpp.git + GIT_TAG windows + BINARY_DIR json-rpc-cpp-prefix/src/json-rpc-cpp + CONFIGURE_COMMAND cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DJSONCPP_INCLUDE_DIRS=${ETH_DEPENDENCY_INSTALL_DIR}/include -DJSONCPP_LIBRARIES=${ETH_DEPENDENCY_INSTALL_DIR}/lib/jsoncpp.lib -DCURL_LIBRARIES=${ETH_DEPENDENCY_INSTALL_DIR}/lib/libcurl.lib -DCURL_INCLUDE_DIRS=${ETH_DEPENDENCY_INSTALL_DIR}/include . + BUILD_COMMAND devenv libjson-rpc-cpp.sln /build release + INSTALL_COMMAND cmd /c cp lib/Release/* ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp -R src/jsonrpccpp ${ETH_DEPENDENCY_INSTALL_DIR}/include + ) +else() +ExternalProject_Add(json-rpc-cpp + # DEPENDS argtable2 jsoncpp # DEPENDS curl # re-enable later, when we build curl again GIT_REPOSITORY https://github.com/cinemast/libjson-rpc-cpp.git GIT_TAG v0.3.2 BINARY_DIR json-rpc-cpp-prefix/src/json-rpc-cpp - CONFIGURE_COMMAND ${CONFIG_CMD} + CONFIGURE_COMMAND cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_MODULE_PATH:PATH=${CMAKE_CURRENT_SOURCE_DIR} -DETH_DEPENDENCY_INSTALL_DIR:PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST . BUILD_COMMAND make -j 3 INSTALL_COMMAND make install -) + ) + +endif() + From bcee6e6921662b46c3a445da9d52aac9f7b3cb6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 26 Nov 2014 21:37:40 +0100 Subject: [PATCH 367/641] I don't know what I was thinking: always use interpreter in Executive (for now) --- libethereum/Executive.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index f7cbcf3e3..f609c9c14 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -137,7 +137,7 @@ bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _g m_s.m_cache[m_newAddress] = Account(m_s.balance(m_newAddress) + _endowment, Account::ContractConception); // Execute _init. - m_vm = VMFace::create(VMFace::JIT, _gas).release(); + m_vm = VMFace::create(VMFace::Interpreter, _gas).release(); m_ext = new ExtVM(m_s, m_newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _init, m_ms); return _init.empty(); } From 941184f6a778833aa914f095caf18962f7002ed4 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 26 Nov 2014 21:45:09 +0100 Subject: [PATCH 368/641] json-rpc-cpp improved config method --- extdep/json-rpc-cpp.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extdep/json-rpc-cpp.cmake b/extdep/json-rpc-cpp.cmake index baba1bb19..387597615 100644 --- a/extdep/json-rpc-cpp.cmake +++ b/extdep/json-rpc-cpp.cmake @@ -21,7 +21,7 @@ ExternalProject_Add(json-rpc-cpp GIT_REPOSITORY https://github.com/debris/libjson-rpc-cpp.git GIT_TAG windows BINARY_DIR json-rpc-cpp-prefix/src/json-rpc-cpp - CONFIGURE_COMMAND cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DJSONCPP_INCLUDE_DIRS=${ETH_DEPENDENCY_INSTALL_DIR}/include -DJSONCPP_LIBRARIES=${ETH_DEPENDENCY_INSTALL_DIR}/lib/jsoncpp.lib -DCURL_LIBRARIES=${ETH_DEPENDENCY_INSTALL_DIR}/lib/libcurl.lib -DCURL_INCLUDE_DIRS=${ETH_DEPENDENCY_INSTALL_DIR}/include . + CONFIGURE_COMMAND cmake -DCMAKE_PREFIX_PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCURL_LIBRARIES=${ETH_DEPENDENCY_INSTALL_DIR}/lib/libcurl.lib . BUILD_COMMAND devenv libjson-rpc-cpp.sln /build release INSTALL_COMMAND cmd /c cp lib/Release/* ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp -R src/jsonrpccpp ${ETH_DEPENDENCY_INSTALL_DIR}/include ) From cd612bb808774dea7adcb7155dc90c131de2ef57 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 26 Nov 2014 22:05:24 +0100 Subject: [PATCH 369/641] leveldb and snappy for apple build --- extdep/CMakeLists.txt | 3 ++- extdep/leveldb.cmake | 22 ++++++++++++++++++++++ extdep/leveldb_osx.patch | 18 ++++++++++++++++++ extdep/snappy.cmake | 14 ++++++++++++++ 4 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 extdep/leveldb.cmake create mode 100644 extdep/leveldb_osx.patch create mode 100644 extdep/snappy.cmake diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index 5686a0c5d..4a3214d75 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -2,7 +2,6 @@ cmake_minimum_required(VERSION 2.8) include(ExternalProject) - # all dependencies will be installed into this directory, separated by platform string(TOLOWER ${CMAKE_SYSTEM_NAME} _system_name) set(ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/install/${_system_name}") @@ -14,6 +13,8 @@ include(jsoncpp.cmake) include(argtable2.cmake) include(json-rpc-cpp.cmake) include(cryptopp.cmake) +include(snappy.cmake) +include(leveldb.cmake) # will be re-eanbled later # include(curl.cmake) diff --git a/extdep/leveldb.cmake b/extdep/leveldb.cmake new file mode 100644 index 000000000..82d9f5a05 --- /dev/null +++ b/extdep/leveldb.cmake @@ -0,0 +1,22 @@ +if(APPLE) +ExternalProject_Add(leveldb + DEPENDS snappy + URL https://leveldb.googlecode.com/files/leveldb-1.15.0.tar.gz + BINARY_DIR leveldb-prefix/src/leveldb + CONFIGURE_COMMAND patch < ${CMAKE_CURRENT_SOURCE_DIR}/leveldb_osx.patch + BUILD_COMMAND export ETH_DEPENDENCY_INSTALL_DIR=${ETH_DEPENDENCY_INSTALL_DIR} && make -j 3 + INSTALL_COMMAND cp -rf include/leveldb ${ETH_DEPENDENCY_INSTALL_DIR}/include/ && mv libleveldb.a ${ETH_DEPENDENCY_INSTALL_DIR}/lib && mv libleveldb.dylib.1.15 ${ETH_DEPENDENCY_INSTALL_DIR}/lib/libleveldb.dylib + ) +elseif(WIN32) +ExternalProject_Add(leveldb + GIT_REPOSITORY https://code.google.com/p/leveldb + GIT_TAG windows + BINARY_DIR leveldb-prefix/src/leveldb + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + ) +else() + +endif() + diff --git a/extdep/leveldb_osx.patch b/extdep/leveldb_osx.patch new file mode 100644 index 000000000..ac9e8f528 --- /dev/null +++ b/extdep/leveldb_osx.patch @@ -0,0 +1,18 @@ +--- Makefile 2014-11-07 00:54:05.000000000 +0100 ++++ MakefilePatch 2014-11-07 00:56:59.000000000 +0100 +@@ -17,11 +17,11 @@ + # this file is generated by the previous line to set build flags and sources + include build_config.mk + +-CFLAGS += -I. -I./include $(PLATFORM_CCFLAGS) $(OPT) +-CXXFLAGS += -I. -I./include $(PLATFORM_CXXFLAGS) $(OPT) ++CFLAGS += -I. -I./include $(PLATFORM_CCFLAGS) $(OPT) ++CXXFLAGS += -I. -I./include $(PLATFORM_CXXFLAGS) $(OPT) -DSNAPPY -I$(ETH_DEPENDENCY_INSTALL_DIR)/include + +-LDFLAGS += $(PLATFORM_LDFLAGS) +-LIBS += $(PLATFORM_LIBS) ++LDFLAGS += $(PLATFORM_LDFLAGS) -L$(ETH_DEPENDENCY_INSTALL_DIR)/lib ++LIBS += $(PLATFORM_LIBS) -lsnappy + + LIBOBJECTS = $(SOURCES:.cc=.o) + MEMENVOBJECTS = $(MEMENV_SOURCES:.cc=.o) diff --git a/extdep/snappy.cmake b/extdep/snappy.cmake new file mode 100644 index 000000000..a15418304 --- /dev/null +++ b/extdep/snappy.cmake @@ -0,0 +1,14 @@ +if(APPLE) +ExternalProject_Add(snappy + URL https://snappy.googlecode.com/files/snappy-1.1.1.tar.gz + BINARY_DIR snappy-prefix/src/snappy + CONFIGURE_COMMAND ./configure --disable-dependency-tracking --prefix=${ETH_DEPENDENCY_INSTALL_DIR} + BUILD_COMMAND "" + INSTALL_COMMAND make install + ) +elseif(WIN32) + +else() + +endif() + From 2dd4f2168a775373ac691a57066ac2da1108d0d2 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 26 Nov 2014 22:08:42 +0100 Subject: [PATCH 370/641] fixed CMAKE_PREFIX_PATH && MSVC compiler rejection --- cmake/EthCompilerSettings.cmake | 4 +++- cmake/EthDependencies.cmake | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index 6103970c4..8530a54b7 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -10,8 +10,10 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") endif () elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") else () - message(FATAL_ERROR "Your C++ compiler does not support C++11.") + message(FATAL_ERROR "Your C++ compiler does not support C++11. You have ${CMAKE_CXX_COMPILER_ID}") endif () diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 34d8f18a6..1d6d3418d 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -4,7 +4,7 @@ # by defining this variable, cmake will look for dependencies first in our own repository before looking in system paths like /usr/local/ ... # this must be set to point to the same directory as $ETH_DEPENDENCY_INSTALL_DIR in /extdep directory string(TOLOWER ${CMAKE_SYSTEM_NAME} _system_name) -set (CMAKE_FIND_ROOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/extdep/install/${_system_name}") +set (CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}/extdep/install/${_system_name}") # Dependencies must have a version number + EXACT, to ensure reproducible builds From 859cbb451dea323c7f86fd8ad7af18f440d809c4 Mon Sep 17 00:00:00 2001 From: debris Date: Thu, 27 Nov 2014 10:17:28 +0100 Subject: [PATCH 371/641] leveldb on windows --- cmake/EthDependencies.cmake | 6 ++++++ cmake/FindLevelDB.cmake | 35 +++++++++++++++++++++++++++++++++++ extdep/CMakeLists.txt | 1 - extdep/leveldb.cmake | 6 +++--- 4 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 cmake/FindLevelDB.cmake diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 1d6d3418d..c234cdee4 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -13,6 +13,12 @@ find_package (CryptoPP 5.6.2 EXACT REQUIRED) message(" - CryptoPP header: ${CRYPTOPP_INCLUDE_DIRS}") message(" - CryptoPP lib : ${CRYPTOPP_LIBRARIES}") +# TODO the Jsoncpp package does not yet check for correct version number + +find_package (LevelDB REQUIRED) +message(" - LevelDB header: ${LEVELDB_INCLUDE_DIR}") +message(" - LevelDB lib: ${LEVELDB_LIBRARY}") + # TODO the Jsoncpp package does not yet check for correct version number find_package (Jsoncpp 0.60 EXACT REQUIRED) message(" - Jsoncpp header: ${JSONCPP_INCLUDE_DIRS}") diff --git a/cmake/FindLevelDB.cmake b/cmake/FindLevelDB.cmake new file mode 100644 index 000000000..7daff29f6 --- /dev/null +++ b/cmake/FindLevelDB.cmake @@ -0,0 +1,35 @@ +# Find leveldb +# +# Find the leveldb includes and library +# +# if you nee to add a custom library search path, do it via via CMAKE_FIND_ROOT_PATH +# +# This module defines +# LEVELDB_INCLUDE_DIR, where to find header, etc. +# LEVELDB_LIBRARY, the libraries needed to use leveldb. +# LEVELDB_FOUND, If false, do not try to use leveldb. + +# only look in default directories +find_path( + LEVELDB_INCLUDE_DIR + NAMES leveldb/db.h + DOC "leveldb include dir" +) + +find_library( + LEVELDB_LIBRARY + NAMES leveldb + DOC "leveldb library" +) + +# message (" - leveldb header : ${LEVELDB_INCLUDE_DIR}") +# message (" - leveldb lib : ${LEVELDB_LIBRARY}") + + +# handle the QUIETLY and REQUIRED arguments and set JSON_RPC_CPP_FOUND to TRUE +# if all listed variables are TRUE, hide their existence from configuration view +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(leveldb DEFAULT_MSG + LEVELDB_INCLUDE_DIR LEVELDB_LIBRARY) +mark_as_advanced (LEVELDB_INCLUDE_DIR LEVELDB_LIBRARY) + diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index 4a3214d75..53f3751ed 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -17,6 +17,5 @@ include(snappy.cmake) include(leveldb.cmake) # will be re-eanbled later -# include(curl.cmake) # include(miniupnpc.cmake) diff --git a/extdep/leveldb.cmake b/extdep/leveldb.cmake index 82d9f5a05..8b494457f 100644 --- a/extdep/leveldb.cmake +++ b/extdep/leveldb.cmake @@ -9,12 +9,12 @@ ExternalProject_Add(leveldb ) elseif(WIN32) ExternalProject_Add(leveldb - GIT_REPOSITORY https://code.google.com/p/leveldb - GIT_TAG windows + GIT_REPOSITORY https://github.com/debris/leveldb-win32.git + GIT_TAG master BINARY_DIR leveldb-prefix/src/leveldb CONFIGURE_COMMAND "" BUILD_COMMAND "" - INSTALL_COMMAND "" + INSTALL_COMMAND cmd /c cp lib/LibLevelDB.lib ${ETH_DEPENDENCY_INSTALL_DIR}/lib/leveldb.lib && cp -R include/leveldb ${ETH_DEPENDENCY_INSTALL_DIR}/include ) else() From 5d7f374a3882dabc7519fcc60cc0b5d4e9f6bdf4 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 27 Nov 2014 11:38:13 +0100 Subject: [PATCH 372/641] leveldb downloaded locally --- cmake/EthDependenciesDeprecated.cmake | 29 --------------------------- cmake/FindLevelDB.cmake | 6 +++--- eth/CMakeLists.txt | 3 ++- exp/CMakeLists.txt | 3 ++- libdevcore/CMakeLists.txt | 4 ++-- libdevcrypto/CMakeLists.txt | 3 ++- libethcore/CMakeLists.txt | 8 ++++---- libethereum/CMakeLists.txt | 3 ++- libevm/CMakeLists.txt | 3 ++- libp2p/CMakeLists.txt | 3 ++- libweb3jsonrpc/CMakeLists.txt | 3 ++- libwebthree/CMakeLists.txt | 3 ++- libwhisper/CMakeLists.txt | 7 ++++--- neth/CMakeLists.txt | 4 ++-- 14 files changed, 31 insertions(+), 51 deletions(-) diff --git a/cmake/EthDependenciesDeprecated.cmake b/cmake/EthDependenciesDeprecated.cmake index 6876943fa..47ad733e4 100644 --- a/cmake/EthDependenciesDeprecated.cmake +++ b/cmake/EthDependenciesDeprecated.cmake @@ -5,34 +5,8 @@ if("${TARGET_PLATFORM}" STREQUAL "w64") # set(MINIUPNPC_LS /usr/x86_64-w64-mingw32/lib/libminiupnpc.a) - set(LEVELDB_LS leveldb) else() - find_path( LEVELDB_ID leveldb/db.h - /usr/include - /usr/local/include - ) - if ( LEVELDB_ID STREQUAL "LEVELDB_ID-NOTFOUND" ) - message(FATAL_ERROR "Failed to find the LevelDB headers") - else () - message(STATUS "Found LevelDB Headers") - - # Check for accessory dev libraries leveldb and miniupnpc - find_library( LEVELDB_LS NAMES leveldb - PATHS - /usr/lib - /usr/local/lib - /opt/local/lib - /usr/lib/*/ - ) - if ( LEVELDB_LS STREQUAL "LEVELDB_LS-NOTFOUND" ) - message(FATAL_ERROR "Failed to find the LevelDB Library!") - else () - message(STATUS "Found LevelDB Library: ${LEVELDB_LS}") - add_definitions(-DETH_LEVELDB) - endif () - endif () - find_path( PYTHON_ID pyconfig.h ${PYTHON_INCLUDE_DIR} /usr/include/python2.7 @@ -123,9 +97,6 @@ endif() if(MINIUPNPC_ID) include_directories(${MINIUPNPC_ID}) endif() -if(LEVELDB_ID) - include_directories(${LEVELDB_ID}) -endif() if(READLINE_ID) include_directories(${READLINE_ID}) endif() diff --git a/cmake/FindLevelDB.cmake b/cmake/FindLevelDB.cmake index 7daff29f6..770c9e65f 100644 --- a/cmake/FindLevelDB.cmake +++ b/cmake/FindLevelDB.cmake @@ -13,14 +13,14 @@ find_path( LEVELDB_INCLUDE_DIR NAMES leveldb/db.h - DOC "leveldb include dir" -) + DOC "leveldb include dir" + ) find_library( LEVELDB_LIBRARY NAMES leveldb DOC "leveldb library" -) + ) # message (" - leveldb header : ${LEVELDB_INCLUDE_DIR}") # message (" - leveldb lib : ${LEVELDB_LIBRARY}") diff --git a/eth/CMakeLists.txt b/eth/CMakeLists.txt index 2bf2dcc49..934169e1f 100644 --- a/eth/CMakeLists.txt +++ b/eth/CMakeLists.txt @@ -4,6 +4,7 @@ aux_source_directory(. SRC_LIST) include_directories(..) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) +include_directories(${LEVELDB_INCLUDE_DIR}) set(EXECUTABLE eth) @@ -16,7 +17,7 @@ target_link_libraries(${EXECUTABLE} gmp) if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() -target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) if(JSON_RPC_CPP_FOUND) target_link_libraries(${EXECUTABLE} web3jsonrpc) endif() diff --git a/exp/CMakeLists.txt b/exp/CMakeLists.txt index 89e5580a4..26ee835d4 100644 --- a/exp/CMakeLists.txt +++ b/exp/CMakeLists.txt @@ -3,6 +3,7 @@ cmake_policy(SET CMP0015 NEW) aux_source_directory(. SRC_LIST) include_directories(..) +include_directories(${LEVELDB_INCLUDE_DIR}) set(EXECUTABLE exp) @@ -14,7 +15,7 @@ target_link_libraries(${EXECUTABLE} gmp) if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() -target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) if ("${TARGET_PLATFORM}" STREQUAL "w64") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") diff --git a/libdevcore/CMakeLists.txt b/libdevcore/CMakeLists.txt index c3857a622..939f20593 100644 --- a/libdevcore/CMakeLists.txt +++ b/libdevcore/CMakeLists.txt @@ -7,6 +7,8 @@ endif() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) +include_directories(..) +include_directories(${LEVELDB_INCLUDE_DIR}) set(EXECUTABLE devcore) @@ -17,8 +19,6 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -include_directories(..) - if("${TARGET_PLATFORM}" STREQUAL "w64") target_link_libraries(${EXECUTABLE} boost_system-mt-s) target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) diff --git a/libdevcrypto/CMakeLists.txt b/libdevcrypto/CMakeLists.txt index 1dd709ffe..7de842fc5 100644 --- a/libdevcrypto/CMakeLists.txt +++ b/libdevcrypto/CMakeLists.txt @@ -13,11 +13,12 @@ endif() include_directories(..) include_directories(${CRYPTOPP_INCLUDE_DIR}) +include_directories(${LEVELDB_INCLUDE_DIR}) target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} secp256k1) target_link_libraries(${EXECUTABLE} gmp) -target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LIBRARIES}) if("${TARGET_PLATFORM}" STREQUAL "w64") diff --git a/libethcore/CMakeLists.txt b/libethcore/CMakeLists.txt index 49cfc1941..0c50320c3 100644 --- a/libethcore/CMakeLists.txt +++ b/libethcore/CMakeLists.txt @@ -1,6 +1,9 @@ cmake_policy(SET CMP0015 NEW) aux_source_directory(. SRC_LIST) +include_directories(..) +include_directories(${CRYPTOPP_INCLUDE_DIR}) +include_directories(${LEVELDB_INCLUDE_DIR}) set(EXECUTABLE ethcore) @@ -11,14 +14,11 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -include_directories(..) -include_directories(${CRYPTOPP_INCLUDE_DIR}) - target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} secp256k1) target_link_libraries(${EXECUTABLE} gmp) -target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) if("${TARGET_PLATFORM}" STREQUAL "w64") target_link_libraries(${EXECUTABLE} boost_system-mt-s) diff --git a/libethereum/CMakeLists.txt b/libethereum/CMakeLists.txt index 3c00ad6a7..3266a8801 100644 --- a/libethereum/CMakeLists.txt +++ b/libethereum/CMakeLists.txt @@ -14,6 +14,7 @@ else() endif() include_directories(..) +include_directories(${LEVELDB_INCLUDE_DIR}) target_link_libraries(${EXECUTABLE} evm) target_link_libraries(${EXECUTABLE} lll) @@ -25,7 +26,7 @@ target_link_libraries(${EXECUTABLE} secp256k1) if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() -target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) target_link_libraries(${EXECUTABLE} gmp) if("${TARGET_PLATFORM}" STREQUAL "w64") diff --git a/libevm/CMakeLists.txt b/libevm/CMakeLists.txt index cddd6b9c9..2812be808 100644 --- a/libevm/CMakeLists.txt +++ b/libevm/CMakeLists.txt @@ -14,6 +14,7 @@ else() endif() include_directories(..) +include_directories(${LEVELDB_INCLUDE_DIR}) target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} devcrypto) @@ -24,7 +25,7 @@ target_link_libraries(${EXECUTABLE} gmp) if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() -target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) if("${TARGET_PLATFORM}" STREQUAL "w64") target_link_libraries(${EXECUTABLE} boost_system-mt-s) diff --git a/libp2p/CMakeLists.txt b/libp2p/CMakeLists.txt index f0aeceae5..207d10127 100644 --- a/libp2p/CMakeLists.txt +++ b/libp2p/CMakeLists.txt @@ -14,6 +14,7 @@ else() endif() include_directories(..) +include_directories(${LEVELDB_INCLUDE_DIR}) target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} devcore) @@ -21,7 +22,7 @@ target_link_libraries(${EXECUTABLE} secp256k1) if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() -target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) target_link_libraries(${EXECUTABLE} gmp) if("${TARGET_PLATFORM}" STREQUAL "w64") diff --git a/libweb3jsonrpc/CMakeLists.txt b/libweb3jsonrpc/CMakeLists.txt index 7d0695b30..5fb2662e1 100644 --- a/libweb3jsonrpc/CMakeLists.txt +++ b/libweb3jsonrpc/CMakeLists.txt @@ -4,6 +4,7 @@ aux_source_directory(. SRC_LIST) include_directories(..) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) +include_directories(${LEVELDB_INCLUDE_DIR}) link_directories(../libethcore) link_directories(../libwebthree) @@ -24,7 +25,7 @@ target_link_libraries(${EXECUTABLE} serpent) if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() -target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_LIBRARIES}) if(READLINE_LS) diff --git a/libwebthree/CMakeLists.txt b/libwebthree/CMakeLists.txt index fbaa43b45..4ec5b2ea4 100644 --- a/libwebthree/CMakeLists.txt +++ b/libwebthree/CMakeLists.txt @@ -14,6 +14,7 @@ else() endif() include_directories(..) +include_directories(${LEVELDB_INCLUDE_DIR}) target_link_libraries(${EXECUTABLE} ethereum) target_link_libraries(${EXECUTABLE} evm) @@ -26,7 +27,7 @@ target_link_libraries(${EXECUTABLE} secp256k1) if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() -target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) target_link_libraries(${EXECUTABLE} gmp) if("${TARGET_PLATFORM}" STREQUAL "w64") diff --git a/libwhisper/CMakeLists.txt b/libwhisper/CMakeLists.txt index fdf69650a..62bc5edaf 100644 --- a/libwhisper/CMakeLists.txt +++ b/libwhisper/CMakeLists.txt @@ -4,6 +4,9 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) +include_directories(..) +include_directories(${LEVELDB_INCLUDE_DIR}) + set(EXECUTABLE whisper) file(GLOB HEADERS "*.h") @@ -13,8 +16,6 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -include_directories(..) - target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} devcore) @@ -23,7 +24,7 @@ target_link_libraries(${EXECUTABLE} secp256k1) if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() -target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) target_link_libraries(${EXECUTABLE} gmp) if("${TARGET_PLATFORM}" STREQUAL "w64") diff --git a/neth/CMakeLists.txt b/neth/CMakeLists.txt index bae84b5fa..46195a1eb 100644 --- a/neth/CMakeLists.txt +++ b/neth/CMakeLists.txt @@ -3,8 +3,8 @@ cmake_policy(SET CMP0015 NEW) aux_source_directory(. SRC_LIST) include_directories(..) -include_directories(${LEVELDB_ID}) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) +include_directories(${LEVELDB_INCLUDE_DIR}) set(EXECUTABLE neth) @@ -17,7 +17,7 @@ target_link_libraries(${EXECUTABLE} gmp) if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() -target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) if(JSON_RPC_CPP_FOUND) target_link_libraries(${EXECUTABLE} web3jsonrpc) endif() From 79f2e52ec6fbe2fcb80822dc1ce708754ec2490c Mon Sep 17 00:00:00 2001 From: sveneh Date: Thu, 27 Nov 2014 20:01:34 +0100 Subject: [PATCH 373/641] use CMAKE_PREFIX_PATH instead of CMAKE_FILE_ROOT_PATH; removed the requirement to use EXACT version numbers for dependencies, cleanup --- cmake/EthDependencies.cmake | 8 ++++---- extdep/CMakeLists.txt | 2 -- extdep/json-rpc-cpp.cmake | 8 ++------ test/CMakeLists.txt | 1 - 4 files changed, 6 insertions(+), 13 deletions(-) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 34d8f18a6..04e57cce7 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -4,22 +4,22 @@ # by defining this variable, cmake will look for dependencies first in our own repository before looking in system paths like /usr/local/ ... # this must be set to point to the same directory as $ETH_DEPENDENCY_INSTALL_DIR in /extdep directory string(TOLOWER ${CMAKE_SYSTEM_NAME} _system_name) -set (CMAKE_FIND_ROOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/extdep/install/${_system_name}") +set (CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}/extdep/install/${_system_name}") -# Dependencies must have a version number + EXACT, to ensure reproducible builds +# Dependencies must have a version number, to ensure reproducible build. The version provided here is the one that is in the extdep repository. If you use system libraries, version numbers may be different. find_package (CryptoPP 5.6.2 EXACT REQUIRED) message(" - CryptoPP header: ${CRYPTOPP_INCLUDE_DIRS}") message(" - CryptoPP lib : ${CRYPTOPP_LIBRARIES}") # TODO the Jsoncpp package does not yet check for correct version number -find_package (Jsoncpp 0.60 EXACT REQUIRED) +find_package (Jsoncpp 0.60 REQUIRED) message(" - Jsoncpp header: ${JSONCPP_INCLUDE_DIRS}") message(" - Jsoncpp lib : ${JSONCPP_LIBRARIES}") # TODO the JsonRpcCpp package does not yet check for correct version number -find_package (JsonRpcCpp 0.3.2 EXACT REQUIRED) +find_package (JsonRpcCpp 0.3.2 REQUIRED) if (${JSON_RPC_CPP_FOUND}) message (" - json-rpc-cpp header: ${JSON_RPC_CPP_INCLUDE_DIRS}") message (" - json-rpc-cpp lib : ${JSON_RPC_CPP_LIBRARIES}") diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index 5ef5e63d5..0e05115dc 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -2,7 +2,6 @@ cmake_minimum_required(VERSION 2.8) include(ExternalProject) - # all dependencies will be installed into this directory, separated by platform string(TOLOWER ${CMAKE_SYSTEM_NAME} _system_name) set(ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/install/${_system_name}") @@ -13,4 +12,3 @@ include(cryptopp.cmake) # include(curl.cmake) include(json-rpc-cpp.cmake) #include(miniupnpc.cmake) - diff --git a/extdep/json-rpc-cpp.cmake b/extdep/json-rpc-cpp.cmake index 810fd3a0a..b26af7bb5 100644 --- a/extdep/json-rpc-cpp.cmake +++ b/extdep/json-rpc-cpp.cmake @@ -1,11 +1,7 @@ # json-rpc-cpp is under heavy development, not yet stable, and multiplatform builds are not yet available. # DO NOT MESS WITH THESE SETTINGS! IF YOU HAVE TO MAKE CHANGES HERE, CONSULT sven@ethdev.com BEFOREHAND!! -if(APPLE) - set(CONFIG_CMD cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_MODULE_PATH:PATH=${CMAKE_CURRENT_SOURCE_DIR} -DETH_DEPENDENCY_INSTALL_DIR:PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST -Wno-dev .) -else() - set(CONFIG_CMD cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_MODULE_PATH:PATH=${CMAKE_CURRENT_SOURCE_DIR} -DETH_DEPENDENCY_INSTALL_DIR:PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST .) -endif() +set(_config_cmd cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_MODULE_PATH:PATH=${CMAKE_CURRENT_SOURCE_DIR} -DETH_DEPENDENCY_INSTALL_DIR:PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST .) # DO NOT CHANGE ANYTHING HERE! @@ -14,7 +10,7 @@ ExternalProject_Add(json-rpc-cpp GIT_REPOSITORY https://github.com/cinemast/libjson-rpc-cpp.git GIT_TAG v0.3.2 BINARY_DIR json-rpc-cpp-prefix/src/json-rpc-cpp - CONFIGURE_COMMAND ${CONFIG_CMD} + CONFIGURE_COMMAND ${_config_cmd} BUILD_COMMAND make -j 3 INSTALL_COMMAND make install ) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index fe0408a2b..71b88dbaa 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -19,7 +19,6 @@ target_link_libraries(testeth gmp) target_link_libraries(testeth solidity) target_link_libraries(testeth webthree) -#TODO this on should not be necessary, it should have been brought in from ethcore dependency... target_link_libraries(testeth ${CRYPTOPP_LIBRARIES}) if(JSON_RPC_CPP_FOUND) From 312e05ab49fb300c1f66a416873cc93abfb19253 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zaw=C5=82ocki?= Date: Fri, 28 Nov 2014 00:37:24 +0100 Subject: [PATCH 374/641] resolved circular dependency between libevm and libevmjit --- exp/CMakeLists.txt | 1 + libethereum/CMakeLists.txt | 3 +++ libethereum/Executive.cpp | 4 ++-- libethereum/State.cpp | 4 ++-- libethereum/State.h | 8 +++++--- libevm/VM.h | 4 +++- libevm/VMFace.cpp | 12 ++---------- libevm/VMFace.h | 6 +----- libevmjit/VM.cpp | 1 + libevmjit/VM.h | 8 +++++++- test/createRandomTest.cpp | 3 ++- test/vm.cpp | 10 +++++++--- 12 files changed, 36 insertions(+), 28 deletions(-) diff --git a/exp/CMakeLists.txt b/exp/CMakeLists.txt index fce739007..156de203f 100644 --- a/exp/CMakeLists.txt +++ b/exp/CMakeLists.txt @@ -18,6 +18,7 @@ endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) if(EVMJIT) + target_link_libraries(${EXECUTABLE} evm) target_link_libraries(${EXECUTABLE} evmjit) endif() diff --git a/libethereum/CMakeLists.txt b/libethereum/CMakeLists.txt index cb2049886..6088525fb 100644 --- a/libethereum/CMakeLists.txt +++ b/libethereum/CMakeLists.txt @@ -28,6 +28,9 @@ endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS}) target_link_libraries(${EXECUTABLE} gmp) +if (EVMJIT) + target_link_libraries(${EXECUTABLE} evmjit) +endif() if("${TARGET_PLATFORM}" STREQUAL "w64") target_link_libraries(${EXECUTABLE} boost_system-mt-s) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index f609c9c14..87e675e15 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -118,7 +118,7 @@ bool Executive::call(Address _receiveAddress, Address _senderAddress, u256 _valu if (m_s.addressHasCode(_receiveAddress)) { - m_vm = VMFace::create(VMFace::Interpreter, _gas).release(); + m_vm = VMFactory::create(VMFactory::Interpreter, _gas).release(); bytes const& c = m_s.code(_receiveAddress); m_ext = new ExtVM(m_s, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &c, m_ms); } @@ -137,7 +137,7 @@ bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _g m_s.m_cache[m_newAddress] = Account(m_s.balance(m_newAddress) + _endowment, Account::ContractConception); // Execute _init. - m_vm = VMFace::create(VMFace::Interpreter, _gas).release(); + m_vm = VMFactory::create(VMFactory::Interpreter, _gas).release(); m_ext = new ExtVM(m_s, m_newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _init, m_ms); return _init.empty(); } diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 4e5f5226c..2f8f4063f 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -1214,7 +1214,7 @@ bool State::call(Address _receiveAddress, Address _codeAddress, Address _senderA } else if (addressHasCode(_codeAddress)) { - auto vmObj = VMFace::create(getVMKind(), *_gas); + auto vmObj = VMFactory::create(getVMKind(), *_gas); auto& vm = *vmObj; ExtVM evm(*this, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &code(_codeAddress), o_ms, _level); bool revert = false; @@ -1274,7 +1274,7 @@ h160 State::create(Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas, m_cache[newAddress] = Account(balance(newAddress) + _endowment, Account::ContractConception); // Execute init code. - auto vmObj = VMFace::create(getVMKind(), *_gas); + auto vmObj = VMFactory::create(getVMKind(), *_gas); auto& vm = *vmObj; ExtVM evm(*this, newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _code, o_ms, _level); bool revert = false; diff --git a/libethereum/State.h b/libethereum/State.h index 96d53bc9e..f7bc0d119 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,7 @@ #include "TransactionReceipt.h" #include "Executive.h" #include "AccountDiff.h" +#include "VMFactory.h" namespace dev { @@ -261,10 +263,10 @@ public: void cleanup(bool _fullCommit); /// Sets VM kind to be used by the state - void setVMKind(VMFace::Kind _kind) { m_vmKind = _kind; } + void setVMKind(VMFactory::Kind _kind) { m_vmKind = _kind; } /// Get the kind of VM used by the state - VMFace::Kind getVMKind() const { return m_vmKind; } + VMFactory::Kind getVMKind() const { return m_vmKind; } private: /// Undo the changes to the state for committing to mine. @@ -333,7 +335,7 @@ private: u256 m_blockReward; - VMFace::Kind m_vmKind = VMFace::Interpreter; ///< The kind of VM used by the state + VMFactory::Kind m_vmKind = VMFactory::Interpreter; ///< The kind of VM used by the state static std::string c_defaultPath; diff --git a/libevm/VM.h b/libevm/VM.h index b7a98d262..f39bc9d4f 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -36,6 +36,8 @@ namespace dev namespace eth { +class VMFactory; + /** */ class VM : public VMFace @@ -53,7 +55,7 @@ public: u256s const& stack() const { return m_stack; } private: - friend VMFace; + friend VMFactory; explicit VM(u256 _gas = 0): VMFace(_gas) {} template diff --git a/libevm/VMFace.cpp b/libevm/VMFace.cpp index 3313ee926..9f8c6549c 100644 --- a/libevm/VMFace.cpp +++ b/libevm/VMFace.cpp @@ -22,15 +22,7 @@ using namespace dev; using namespace dev::eth; -std::unique_ptr VMFace::create(VMFace::Kind _kind, u256 _gas) +void VMFace::reset(u256 _gas) noexcept { - std::unique_ptr vm; -#if ETH_EVMJIT - vm.reset(_kind == Kind::JIT ? static_cast(new jit::VM) : new VM); -#else - (void) _kind; // suppress unused var warning - vm.reset(new VM); -#endif - vm->reset(_gas); - return vm; + m_gas = _gas; } diff --git a/libevm/VMFace.h b/libevm/VMFace.h index 76dc8a219..6617db1da 100644 --- a/libevm/VMFace.h +++ b/libevm/VMFace.h @@ -62,16 +62,12 @@ public: VMFace(VMFace const&) = delete; void operator=(VMFace const&) = delete; - virtual void reset(u256 _gas = 0) noexcept { m_gas = _gas; } + virtual void reset(u256 _gas = 0) noexcept; virtual bytesConstRef go(ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) = 0; u256 gas() const { return m_gas; } - enum Kind: bool { Interpreter, JIT }; - - static std::unique_ptr create(Kind, u256 _gas = 0); - protected: u256 m_gas = 0; }; diff --git a/libevmjit/VM.cpp b/libevmjit/VM.cpp index 9b60fccf1..b968008aa 100644 --- a/libevmjit/VM.cpp +++ b/libevmjit/VM.cpp @@ -2,6 +2,7 @@ #include "VM.h" #include +#include #include "ExecutionEngine.h" #include "Compiler.h" diff --git a/libevmjit/VM.h b/libevmjit/VM.h index 93b359cd7..1c6c71181 100644 --- a/libevmjit/VM.h +++ b/libevmjit/VM.h @@ -9,6 +9,9 @@ namespace dev { namespace eth { + +class VMFactory; + namespace jit { @@ -16,8 +19,11 @@ class VM: public VMFace { virtual bytesConstRef go(ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) override final; + enum Kind: bool { Interpreter, JIT }; + static std::unique_ptr create(Kind, u256 _gas = 0); + private: - friend VMFace; + friend VMFactory; explicit VM(u256 _gas = 0): VMFace(_gas) {} bytes m_output; diff --git a/test/createRandomTest.cpp b/test/createRandomTest.cpp index f22e5c0aa..87bb13846 100644 --- a/test/createRandomTest.cpp +++ b/test/createRandomTest.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include "vm.h" @@ -128,7 +129,7 @@ void doMyTests(json_spirit::mValue& v) assert(o.count("exec") > 0); - auto vmObj = eth::VMFace::create(eth::VMFace::Interpreter); + auto vmObj = eth::VMFactory::create(eth::VMFactory::Interpreter); auto& vm = *vmObj; test::FakeExtVM fev; fev.importEnv(o["env"].get_obj()); diff --git a/test/vm.cpp b/test/vm.cpp index b34dc1829..ce0fe0808 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -22,6 +22,7 @@ #include #include +#include #include "vm.h" using namespace std; using namespace json_spirit; @@ -322,8 +323,11 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) auto useJit = false; for (auto i = 0; i < argc && !useJit; ++i) useJit |= std::string(argv[i]) == "--jit"; - auto vmKind = useJit ? VMFace::JIT : VMFace::Interpreter; - +#if ETH_EVMJIT + auto vmKind = useJit ? VMFactory::JIT : VMFactory::Interpreter; +#else + auto vmKind == VMFactory::Interpreter; +#endif dev::test::FakeExtVM fev; fev.importEnv(o["env"].get_obj()); @@ -339,7 +343,7 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) fev.code = fev.thisTxCode; } - auto vm = VMFace::create(vmKind, fev.gas); + auto vm = VMFactory::create(vmKind, fev.gas); bytes output; auto startTime = std::chrono::high_resolution_clock::now(); From 5a173029ad555bd452c3a1b6f618b65b6bf51a40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zaw=C5=82ocki?= Date: Fri, 28 Nov 2014 01:23:40 +0100 Subject: [PATCH 375/641] forgot to add new source files --- libethereum/VMFactory.cpp | 28 ++++++++++++++++++++++++++++ libethereum/VMFactory.h | 28 ++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 libethereum/VMFactory.cpp create mode 100644 libethereum/VMFactory.h diff --git a/libethereum/VMFactory.cpp b/libethereum/VMFactory.cpp new file mode 100644 index 000000000..1c8de319b --- /dev/null +++ b/libethereum/VMFactory.cpp @@ -0,0 +1,28 @@ +#include + +#if ETH_EVMJIT + #include +#endif + +#include "VMFactory.h" + +namespace dev +{ +namespace eth +{ + +std::unique_ptr VMFactory::create(VMFactory::Kind _kind, u256 _gas) +{ +#if ETH_EVMJIT + auto vm = _kind == Kind::JIT ? static_cast(new jit::VM) + : static_cast(new VM); +#else + VMFace* vm = new VM; +#endif + + vm->reset(_gas); + return std::unique_ptr(vm); +} + +} +} diff --git a/libethereum/VMFactory.h b/libethereum/VMFactory.h new file mode 100644 index 000000000..5d8edc391 --- /dev/null +++ b/libethereum/VMFactory.h @@ -0,0 +1,28 @@ +#pragma once + +#include + +namespace dev +{ +namespace eth +{ + +/** + */ + +class VMFactory +{ +public: + enum Kind: bool { + Interpreter, +#if ETH_EVMJIT + JIT +#endif + }; + + static std::unique_ptr create(Kind, u256 _gas = 0); +}; + + +} +} From ce0fe1dfccc101f3a166f58c07a0dbc3a9879663 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zaw=C5=82ocki?= Date: Fri, 28 Nov 2014 01:32:57 +0100 Subject: [PATCH 376/641] added reference to libevmjit to alethzero's CMakeLists.txt --- alethzero/CMakeLists.txt | 3 +++ exp/CMakeLists.txt | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index 01dfb88dc..721ab79ba 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -54,6 +54,9 @@ endif () qt5_use_modules(${EXECUTEABLE} Core)# Gui Widgets Network WebKit WebKitWidgets) target_link_libraries(${EXECUTEABLE} webthree qethereum ethereum evm ethcore devcrypto secp256k1 gmp ${CRYPTOPP_LS} serpent lll solidity evmcore devcore web3jsonrpc jsqrc) +if (EVMJIT) + target_link_libraries(${EXECUTEABLE} evmjit) +endif() if (APPLE) # First have qt5 install plugins and frameworks diff --git a/exp/CMakeLists.txt b/exp/CMakeLists.txt index 156de203f..fce739007 100644 --- a/exp/CMakeLists.txt +++ b/exp/CMakeLists.txt @@ -18,7 +18,6 @@ endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) if(EVMJIT) - target_link_libraries(${EXECUTABLE} evm) target_link_libraries(${EXECUTABLE} evmjit) endif() From 1e7c9739ac6afd1e792452c0a5a4989960a89c9b Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 28 Nov 2014 02:41:38 +0100 Subject: [PATCH 377/641] common changes for windows build --- extdep/CMakeLists.txt | 18 ++++--- extdep/configure.bat | 111 ++++++++++++++++++++++++++++++++++++++++++ extdep/icu.cmake | 18 +++++++ extdep/jom.cmake | 18 +++++++ extdep/qt.cmake | 31 ++++++++++++ extdep/tools.bat | 2 + 6 files changed, 191 insertions(+), 7 deletions(-) create mode 100644 extdep/configure.bat create mode 100644 extdep/icu.cmake create mode 100644 extdep/jom.cmake create mode 100644 extdep/qt.cmake create mode 100644 extdep/tools.bat diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index 53f3751ed..53c1ea3fe 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -7,14 +7,18 @@ string(TOLOWER ${CMAKE_SYSTEM_NAME} _system_name) set(ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/install/${_system_name}") file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/lib) file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/include) +file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/bin) -include(curl.cmake) -include(jsoncpp.cmake) -include(argtable2.cmake) -include(json-rpc-cpp.cmake) -include(cryptopp.cmake) -include(snappy.cmake) -include(leveldb.cmake) +include(icu.cmake) +include(jom.cmake) +include(qt.cmake) +#include(curl.cmake) +#include(jsoncpp.cmake) +#include(argtable2.cmake) +#include(json-rpc-cpp.cmake) +#include(cryptopp.cmake) +#include(snappy.cmake) +#include(leveldb.cmake) # will be re-eanbled later # include(miniupnpc.cmake) diff --git a/extdep/configure.bat b/extdep/configure.bat new file mode 100644 index 000000000..bd810938a --- /dev/null +++ b/extdep/configure.bat @@ -0,0 +1,111 @@ +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:: +:: Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +:: Contact: http://www.qt-project.org/legal +:: +:: This file is part of the tools applications of the Qt Toolkit. +:: +:: $QT_BEGIN_LICENSE:LGPL$ +:: Commercial License Usage +:: Licensees holding valid commercial Qt licenses may use this file in +:: accordance with the commercial license agreement provided with the +:: Software or, alternatively, in accordance with the terms contained in +:: a written agreement between you and Digia. For licensing terms and +:: conditions see http://qt.digia.com/licensing. For further information +:: use the contact form at http://qt.digia.com/contact-us. +:: +:: GNU Lesser General Public License Usage +:: Alternatively, this file may be used under the terms of the GNU Lesser +:: General Public License version 2.1 as published by the Free Software +:: Foundation and appearing in the file LICENSE.LGPL included in the +:: packaging of this file. Please review the following information to +:: ensure the GNU Lesser General Public License version 2.1 requirements +:: will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +:: +:: In addition, as a special exception, Digia gives you certain additional +:: rights. These rights are described in the Digia Qt LGPL Exception +:: version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +:: +:: GNU General Public License Usage +:: Alternatively, this file may be used under the terms of the GNU +:: General Public License version 3.0 as published by the Free Software +:: Foundation and appearing in the file LICENSE.GPL included in the +:: packaging of this file. Please review the following information to +:: ensure the GNU General Public License version 3.0 requirements will be +:: met: http://www.gnu.org/copyleft/gpl.html. +:: +:: +:: $QT_END_LICENSE$ +:: +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + +@echo off +set QTSRC=%~dp0 +set QTDIR=%CD% +::if not exist %QTSRC%\.gitignore goto sconf +echo Please wait while bootstrapping configure ... + +for %%C in (cl.exe icl.exe g++.exe perl.exe) do set %%C=%%~$PATH:C + +if "%perl.exe%" == "" ( + echo Perl not found in PATH. Aborting. >&2 + exit /b 1 +) +if not exist mkspecs ( + md mkspecs + if errorlevel 1 goto exit +) +perl %QTSRC%bin\syncqt.pl -minimal -module QtCore -outdir %QTDIR% %QTSRC% +if errorlevel 1 goto exit + +if not exist tools\configure ( + md tools\configure + if errorlevel 1 goto exit +) +cd tools\configure +if errorlevel 1 goto exit + +echo #### Generated by configure.bat - DO NOT EDIT! ####> Makefile +echo/>> Makefile +for /f "tokens=3 usebackq" %%V in (`findstr QT_VERSION_STR %QTSRC%\src\corelib\global\qglobal.h`) do @echo QTVERSION = %%~V>> Makefile +if not "%cl.exe%" == "" ( + echo CXX = cl>>Makefile + echo EXTRA_CXXFLAGS =>>Makefile + rem This must have a trailing space. + echo QTSRC = %QTSRC% >> Makefile + set tmpl=win32 + set make=nmake +) else if not "%icl.exe%" == "" ( + echo CXX = icl>>Makefile + echo EXTRA_CXXFLAGS = /Zc:forScope>>Makefile + rem This must have a trailing space. + echo QTSRC = %QTSRC% >> Makefile + set tmpl=win32 + set make=nmake +) else if not "%g++.exe%" == "" ( + echo CXX = g++>>Makefile + echo EXTRA_CXXFLAGS =>>Makefile + rem This must NOT have a trailing space. + echo QTSRC = %QTSRC:\=/%>> Makefile + set tmpl=mingw + set make=mingw32-make +) else ( + echo No suitable compiler found in PATH. Aborting. >&2 + cd ..\.. + exit /b 1 +) +echo/>> Makefile +type %QTSRC%tools\configure\Makefile.%tmpl% >> Makefile + +%make% +if errorlevel 1 (cd ..\.. & exit /b 1) + +cd ..\.. + +:conf +configure.exe -srcdir %QTSRC% %* +goto exit + +:sconf +%QTSRC%\configure.exe %* +:exit diff --git a/extdep/icu.cmake b/extdep/icu.cmake new file mode 100644 index 000000000..c05862b91 --- /dev/null +++ b/extdep/icu.cmake @@ -0,0 +1,18 @@ +if(APPLE) + +# patch for VS2013 and Windows Qt build +elseif(WIN32) +ExternalProject_Add(icu + GIT_REPOSITORY https://github.com/debris/icu-win32.git + GIT_TAG master + BINARY_DIR icu-prefix/src/icu + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND cmd /c cp lib/*.lib ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp -R include/unicode ${ETH_DEPENDENCY_INSTALL_DIR}/include + ) + +else() + +endif() + + diff --git a/extdep/jom.cmake b/extdep/jom.cmake new file mode 100644 index 000000000..0370eed8e --- /dev/null +++ b/extdep/jom.cmake @@ -0,0 +1,18 @@ +if(APPLE) + + +elseif(WIN32) +# nmake is not working for qt on windows, do not know why +ExternalProject_Add(jom + URL http://download.qt-project.org/official_releases/jom/jom.zip + BINARY_DIR jom-prefix/src/jom + CONFIGURE_COMMAND "" + BUILD_COMMAND echo %cd% + INSTALL_COMMAND cp jom.exe ${ETH_DEPENDENCY_INSTALL_DIR}/bin + ) + +else() + +endif() + + diff --git a/extdep/qt.cmake b/extdep/qt.cmake new file mode 100644 index 000000000..2f9216f74 --- /dev/null +++ b/extdep/qt.cmake @@ -0,0 +1,31 @@ +if(APPLE) + +elseif(WIN32) +ExternalProject_Add(qt + DEPENDS icu jom + URL http://download.qt-project.org/official_releases/qt/5.2/5.2.1/single/qt-everywhere-opensource-src-5.2.1.tar.gz + BINARY_DIR qt-prefix/src/qt + PATCH_COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/configure.bat qtbase + CONFIGURE_COMMAND configure -prefix ${ETH_DEPENDENCY_INSTALL_DIR} -opensource -confirm-license -release -opengl desktop -platform win32-msvc2013 -icu -I ${ETH_DEPENDENCY_INSTALL_DIR}/include -L ${ETH_DEPENDENCY_INSTALL_DIR}/lib -nomake tests -nomake examples + + BUILD_COMMAND cmd /c ${CMAKE_CURRENT_SOURCE_DIR}/tools.bat && jom + INSTALL_COMMAND cmd /c ${CMAKE_CURRENT_SOURCE_DIR}/tools.bat && jom install + ) + +ExternalProject_Add_Step(qt configure_paths + COMMAND set PATH=${ETH_DEPENDENCY_INSTALL_DIR}/bin;%cd%/gnuwin32/bin;%cd%/qtbase/bin;%PATH% + DEPENDEES patch + DEPENDERS configure + ) + +#ExternalProject_Add_Step(qt configure_visual +# COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/tools.bat +# DEPENDEES patch +# DEPENDERS configure +# ) + +else() + +endif() + + diff --git a/extdep/tools.bat b/extdep/tools.bat new file mode 100644 index 000000000..bd588c480 --- /dev/null +++ b/extdep/tools.bat @@ -0,0 +1,2 @@ +rem : import VC environment vars +call "%VS120COMNTOOLS%\..\..\VC\vcvarsall.bat" x86 \ No newline at end of file From bb1f01f9c065d26406107a8d23653b63711189b2 Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 28 Nov 2014 10:38:41 +0100 Subject: [PATCH 378/641] common changes --- extdep/icu.cmake | 2 +- extdep/qt.cmake | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/extdep/icu.cmake b/extdep/icu.cmake index c05862b91..3728280e1 100644 --- a/extdep/icu.cmake +++ b/extdep/icu.cmake @@ -8,7 +8,7 @@ ExternalProject_Add(icu BINARY_DIR icu-prefix/src/icu CONFIGURE_COMMAND "" BUILD_COMMAND "" - INSTALL_COMMAND cmd /c cp lib/*.lib ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp -R include/unicode ${ETH_DEPENDENCY_INSTALL_DIR}/include + INSTALL_COMMAND cmd /c cp lib/* ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp -R include/uni ${ETH_DEPENDENCY_INSTALL_DIR}/include && cp bin/* ${ETH_DEPENDENCY_INSTALL_DIR}/bin ) else() diff --git a/extdep/qt.cmake b/extdep/qt.cmake index 2f9216f74..863810d1c 100644 --- a/extdep/qt.cmake +++ b/extdep/qt.cmake @@ -5,11 +5,12 @@ ExternalProject_Add(qt DEPENDS icu jom URL http://download.qt-project.org/official_releases/qt/5.2/5.2.1/single/qt-everywhere-opensource-src-5.2.1.tar.gz BINARY_DIR qt-prefix/src/qt + UPDATE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/tools.bat PATCH_COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/configure.bat qtbase CONFIGURE_COMMAND configure -prefix ${ETH_DEPENDENCY_INSTALL_DIR} -opensource -confirm-license -release -opengl desktop -platform win32-msvc2013 -icu -I ${ETH_DEPENDENCY_INSTALL_DIR}/include -L ${ETH_DEPENDENCY_INSTALL_DIR}/lib -nomake tests -nomake examples - - BUILD_COMMAND cmd /c ${CMAKE_CURRENT_SOURCE_DIR}/tools.bat && jom - INSTALL_COMMAND cmd /c ${CMAKE_CURRENT_SOURCE_DIR}/tools.bat && jom install + + BUILD_COMMAND nmake + INSTALL_COMMAND nmake install ) ExternalProject_Add_Step(qt configure_paths From 0a8fb84ce7c212c61bd39ba64ad21c4e5c8bf832 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zaw=C5=82ocki?= Date: Fri, 28 Nov 2014 11:56:50 +0100 Subject: [PATCH 379/641] fixed bug in implementation of LOG --- libevmjit/Ext.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 17cbf5dc4..6eb35acda 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -167,8 +167,8 @@ llvm::Value* Ext::codesizeAt(llvm::Value* _addr) void Ext::log(llvm::Value* _memIdx, llvm::Value* _numBytes, size_t _numTopics, std::array const& _topics) { - static llvm::Value* args[] = {nullptr, m_args[0], m_args[1], m_arg2, m_arg3, m_arg4, m_arg5}; - static llvm::Value* funcs[] = {m_log0, m_log1, m_log2, m_log3, m_log4}; + llvm::Value* args[] = {nullptr, m_args[0], m_args[1], m_arg2, m_arg3, m_arg4, m_arg5}; + llvm::Value* funcs[] = {m_log0, m_log1, m_log2, m_log3, m_log4}; args[0] = getRuntimeManager().getRuntimePtr(); m_builder.CreateStore(_memIdx, m_args[0]); @@ -320,8 +320,8 @@ extern "C" { auto&& ext = _rt->getExt(); - auto memIdx = static_cast(llvm2eth(*_memIdx)); - auto numBytes = static_cast(llvm2eth(*_numBytes)); + auto memIdx = llvm2eth(*_memIdx).convert_to(); + auto numBytes = llvm2eth(*_numBytes).convert_to(); auto dataRef = bytesConstRef(_rt->getMemory().data() + memIdx, numBytes); ext.log({}, dataRef); From 72b9da57123222b3e0f5347835e02c3e2b6ad96a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zaw=C5=82ocki?= Date: Fri, 28 Nov 2014 15:25:41 +0100 Subject: [PATCH 380/641] correct calculation of LOG cost --- libevmjit/Compiler.cpp | 3 +++ libevmjit/GasMeter.cpp | 18 ++++++++++++++++++ libevmjit/GasMeter.h | 3 +++ 3 files changed, 24 insertions(+) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 94e1450cd..1cc86d8aa 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -805,6 +805,9 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode auto numBytes = stack.pop(); _memory.require(beginIdx, numBytes); + // This will commit the current cost block + _gasMeter.countLogData(numBytes); + std::array topics; auto numTopics = static_cast(inst) - static_cast(Instruction::LOG0); for (size_t i = 0; i < numTopics; ++i) diff --git a/libevmjit/GasMeter.cpp b/libevmjit/GasMeter.cpp index 734931c32..48499259a 100644 --- a/libevmjit/GasMeter.cpp +++ b/libevmjit/GasMeter.cpp @@ -47,6 +47,16 @@ uint64_t getStepCost(Instruction inst) // TODO: Add this function to FeeSructure case Instruction::CREATE: return static_cast(c_createGas); + case Instruction::LOG0: + case Instruction::LOG1: + case Instruction::LOG2: + case Instruction::LOG3: + case Instruction::LOG4: + { + auto numTopics = static_cast(inst) - static_cast(Instruction::LOG0); + return static_cast(c_logGas) + numTopics * static_cast(c_logTopicGas); + } + default: // Assumes instruction code is valid return static_cast(c_stepGas); } @@ -138,6 +148,14 @@ void GasMeter::countSStore(Ext& _ext, llvm::Value* _index, llvm::Value* _newValu createCall(m_gasCheckFunc, cost); } +void GasMeter::countLogData(llvm::Value* _dataLength) +{ + assert(m_checkCall); + assert(m_blockCost > 0); // LOGn instruction is already counted + auto cost = m_builder.CreateMul(_dataLength, Constant::get(c_logDataGas), "logdata_cost"); + commitCostBlock(cost); +} + void GasMeter::giveBack(llvm::Value* _gas) { m_runtimeManager.setGas(m_builder.CreateAdd(m_runtimeManager.getGas(), _gas)); diff --git a/libevmjit/GasMeter.h b/libevmjit/GasMeter.h index 4be6c1a02..dfb4fb548 100644 --- a/libevmjit/GasMeter.h +++ b/libevmjit/GasMeter.h @@ -24,6 +24,9 @@ public: /// Calculate & count gas cost for SSTORE instruction void countSStore(class Ext& _ext, llvm::Value* _index, llvm::Value* _newValue); + /// Count gas cost of LOG data + void countLogData(llvm::Value* _dataLength); + /// Finalize cost-block by checking gas needed for the block before the block /// @param _additionalCost adds additional cost to cost-block before commit void commitCostBlock(llvm::Value* _additionalCost = nullptr); From 2424736ffef5cf5bc9b493db092a7837cc882d9c Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 1 Dec 2014 14:57:10 +0100 Subject: [PATCH 381/641] qt building on mac --- extdep/qt.cmake | 15 ++++++++------- extdep/qt_osx.patch | 11 +++++++++++ 2 files changed, 19 insertions(+), 7 deletions(-) create mode 100644 extdep/qt_osx.patch diff --git a/extdep/qt.cmake b/extdep/qt.cmake index 863810d1c..42f4331ab 100644 --- a/extdep/qt.cmake +++ b/extdep/qt.cmake @@ -1,5 +1,12 @@ if(APPLE) - +ExternalProject_add(qt + URL http://qtmirror.ics.com/pub/qtproject/official_releases/qt/5.3/5.3.2/single/qt-everywhere-opensource-src-5.3.2.tar.gz + BINARY_DIR qt-prefix/src/qt + PATCH_COMMAND patch -d qtmultimedia/src/plugins/avfoundation/mediaplayer < ${CMAKE_CURRENT_SOURCE_DIR}/qt_osx.patch + CONFIGURE_COMMAND ./configure -prefix ${ETH_DEPENDENCY_INSTALL_DIR} -system-zlib -qt-libpng -qt-libjpeg -confirm-license -opensource -nomake tests -release -nomake examples -no-xcb -arch x86_64 + BUILD_COMMAND make + INSTALL_COMMAND make install + ) elseif(WIN32) ExternalProject_Add(qt DEPENDS icu jom @@ -19,12 +26,6 @@ ExternalProject_Add_Step(qt configure_paths DEPENDERS configure ) -#ExternalProject_Add_Step(qt configure_visual -# COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/tools.bat -# DEPENDEES patch -# DEPENDERS configure -# ) - else() endif() diff --git a/extdep/qt_osx.patch b/extdep/qt_osx.patch new file mode 100644 index 000000000..7900f6094 --- /dev/null +++ b/extdep/qt_osx.patch @@ -0,0 +1,11 @@ +--- avfmediaplayersession.mm 2014-09-11 12:48:26.000000000 +0200 ++++ avfmediaplayersessionPatch.mm 2014-12-01 12:53:14.000000000 +0100 +@@ -295,7 +295,7 @@ + //AVPlayerItem "status" property value observer. + if (context == AVFMediaPlayerSessionObserverStatusObservationContext) + { +- AVPlayerStatus status = [[change objectForKey:NSKeyValueChangeNewKey] integerValue]; ++ AVPlayerStatus status = (AVPlayerStatus)[[change objectForKey:NSKeyValueChangeNewKey] integerValue]; + switch (status) + { + //Indicates that the status of the player is not yet known because From 12485073f0b631d8e7cefda5a964ad28dbc9f384 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 1 Dec 2014 14:59:36 +0100 Subject: [PATCH 382/641] common changes --- extdep/CMakeLists.txt | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index 0cb2851d4..975207c8b 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -12,16 +12,13 @@ file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/bin) include(icu.cmake) include(jom.cmake) include(qt.cmake) -#include(curl.cmake) -#include(jsoncpp.cmake) -#include(argtable2.cmake) -#include(json-rpc-cpp.cmake) -#include(cryptopp.cmake) -#include(snappy.cmake) -#include(leveldb.cmake) +include(curl.cmake) +include(jsoncpp.cmake) +include(argtable2.cmake) +include(json-rpc-cpp.cmake) +include(cryptopp.cmake) +include(snappy.cmake) +include(leveldb.cmake) # will be re-eanbled later # include(miniupnpc.cmake) -# include(curl.cmake) - -#include(miniupnpc.cmake) From 965af120d6fd51a09b007c92921855a0d715014b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 1 Dec 2014 15:58:49 +0100 Subject: [PATCH 383/641] C Interface draft 1 --- libevmjit/interface.c | 30 ++++++++++++++++++++++++++++++ windows/LibEvmJit.vcxproj | 1 + windows/LibEvmJit.vcxproj.filters | 3 +++ 3 files changed, 34 insertions(+) create mode 100644 libevmjit/interface.c diff --git a/libevmjit/interface.c b/libevmjit/interface.c new file mode 100644 index 000000000..47589578b --- /dev/null +++ b/libevmjit/interface.c @@ -0,0 +1,30 @@ +#include + +// 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; + +// 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); diff --git a/windows/LibEvmJit.vcxproj b/windows/LibEvmJit.vcxproj index a9288a212..50824fb2d 100644 --- a/windows/LibEvmJit.vcxproj +++ b/windows/LibEvmJit.vcxproj @@ -131,6 +131,7 @@ + diff --git a/windows/LibEvmJit.vcxproj.filters b/windows/LibEvmJit.vcxproj.filters index ae89fe550..1a0d86e56 100644 --- a/windows/LibEvmJit.vcxproj.filters +++ b/windows/LibEvmJit.vcxproj.filters @@ -48,6 +48,9 @@ libevmjit + + libevmjit + From 652d08ab437e6c424b3ec13d68b40140d5d32d91 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 1 Dec 2014 18:08:22 +0100 Subject: [PATCH 384/641] cleaning cmakes in progress --- alethzero/CMakeLists.txt | 71 ++++++++++------------------ cmake/EthDependencies.cmake | 14 ++++++ libqethereum/CMakeLists.txt | 94 +------------------------------------ third/CMakeLists.txt | 14 ++---- 4 files changed, 44 insertions(+), 149 deletions(-) diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index 170f026a7..8d31f173c 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -1,34 +1,16 @@ +cmake_policy(SET CMP0015 OLD) + set(CMAKE_INCLUDE_CURRENT_DIR ON) aux_source_directory(. SRC_LIST) include_directories(..) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) -if (APPLE) - # Add homebrew path for qt5 - set(CMAKE_PREFIX_PATH /usr/local/opt/qt5) - include_directories(/usr/local/opt/qt5/include /usr/local/include) -elseif ("${TARGET_PLATFORM}" STREQUAL "w64") - set(SRC_LIST ${SRC_LIST} ../windows/qt_plugin_import.cpp) - include_directories(/usr/x86_64-w64-mingw32/include /usr/x86_64-w64-mingw32/include/QtCore /usr/x86_64-w64-mingw32/include/QtGui /usr/x86_64-w64-mingw32/include/QtQuick /usr/x86_64-w64-mingw32/include/QtQml /usr/x86_64-w64-mingw32/include/QtNetwork /usr/x86_64-w64-mingw32/include/QtWidgets /usr/x86_64-w64-mingw32/include/QtWebKit /usr/x86_64-w64-mingw32/include/QtWebKitWidgets) -elseif (UNIX) - set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ";$ENV{QTDIR}/lib/cmake") -endif () - -find_package(Qt5Core REQUIRED) -find_package(Qt5Gui REQUIRED) -find_package(Qt5Quick REQUIRED) -find_package(Qt5Qml REQUIRED) -find_package(Qt5Network REQUIRED) -find_package(Qt5Widgets REQUIRED) -find_package(Qt5WebKit REQUIRED) -find_package(Qt5WebKitWidgets REQUIRED) - qt5_wrap_ui(ui_Main.h Main.ui) # Set name of binary and add_executable() file(GLOB HEADERS "*.h") if (APPLE) - set(EXECUTEABLE AlethZero) + set(EXECUTABLE AlethZero) set(BIN_INSTALL_DIR ".") set(DOC_INSTALL_DIR ".") @@ -39,34 +21,34 @@ if (APPLE) set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION}") set(MACOSX_BUNDLE_COPYRIGHT "${PROJECT_COPYRIGHT_YEAR} ${PROJECT_VENDOR}") set(MACOSX_BUNDLE_GUI_IDENTIFIER "${PROJECT_DOMAIN_SECOND}.${PROJECT_DOMAIN_FIRST}") - set(MACOSX_BUNDLE_BUNDLE_NAME ${EXECUTEABLE}) + set(MACOSX_BUNDLE_BUNDLE_NAME ${EXECUTABLE}) set(MACOSX_BUNDLE_ICON_FILE alethzero) include(BundleUtilities) - add_executable(${EXECUTEABLE} MACOSX_BUNDLE alethzero.icns Main.ui ${SRC_LIST} ${HEADERS}) - set_target_properties(${EXECUTEABLE} PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/EthereumMacOSXBundleInfo.plist.in") - SET_SOURCE_FILES_PROPERTIES(${EXECUTEABLE} PROPERTIES MACOSX_PACKAGE_LOCATION MacOS) + add_executable(${EXECUTABLE} MACOSX_BUNDLE alethzero.icns Main.ui ${SRC_LIST} ${HEADERS}) + set_target_properties(${EXECUTABLE} PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/EthereumMacOSXBundleInfo.plist.in") + SET_SOURCE_FILES_PROPERTIES(${EXECUTABLE} PROPERTIES MACOSX_PACKAGE_LOCATION MacOS) SET_SOURCE_FILES_PROPERTIES(${MACOSX_BUNDLE_ICON_FILE}.icns PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") - else () - set(EXECUTEABLE alethzero) - add_executable(${EXECUTEABLE} Main.ui ${SRC_LIST} ${HEADERS}) + set(EXECUTABLE alethzero) + add_executable(${EXECUTABLE} Main.ui ${SRC_LIST} ${HEADERS}) endif () -qt5_use_modules(${EXECUTEABLE} Core)# Gui Widgets Network WebKit WebKitWidgets) -target_link_libraries(${EXECUTEABLE} webthree qethereum ethereum evm ethcore devcrypto secp256k1 gmp serpent lll solidity evmcore devcore web3jsonrpc jsqrc ${JSONCPP_LIBRARIES}) +qt5_use_modules(${EXECUTABLE} Core) +target_link_libraries(${EXECUTABLE} webthree qethereum ethereum evm ethcore devcrypto secp256k1 gmp serpent lll solidity evmcore devcore web3jsonrpc jsqrc ${JSONCPP_LIBRARIES}) if (APPLE) # First have qt5 install plugins and frameworks - add_custom_command(TARGET ${EXECUTEABLE} POST_BUILD - COMMAND /usr/local/opt/qt5/bin/macdeployqt ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTEABLE}.app + # replace CMAKE_PREFIX_PATH with QT_PATH ? + add_custom_command(TARGET ${EXECUTABLE} POST_BUILD + COMMAND ${CMAKE_PREFIX_PATH}/bin/macdeployqt ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) # This tool and next will inspect linked libraries in order to determine which dependencies are required if (${CMAKE_CFG_INTDIR} STREQUAL ".") - set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${EXECUTEABLE}.app") + set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${EXECUTABLE}.app") else () - set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/\$ENV{CONFIGURATION}/${EXECUTEABLE}.app") + set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/\$ENV{CONFIGURATION}/${EXECUTABLE}.app") endif () install(CODE " include(BundleUtilities) @@ -83,20 +65,17 @@ if (APPLE) elseif ("${TARGET_PLATFORM}" STREQUAL "w64") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-keep-inline-dllexport -static-libgcc -static-libstdc++ -static") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-s -Wl,-subsystem,windows -mthreads -L/usr/x86_64-w64-mingw32/plugins/platforms") - target_link_libraries(${EXECUTEABLE} gcc) - target_link_libraries(${EXECUTEABLE} mingw32 qtmain mswsock iphlpapi qwindows shlwapi Qt5PlatformSupport opengl32 gdi32 comdlg32 oleaut32 imm32 winmm ole32 uuid ws2_32) - target_link_libraries(${EXECUTEABLE} boost_system-mt-s) - target_link_libraries(${EXECUTEABLE} boost_filesystem-mt-s) - target_link_libraries(${EXECUTEABLE} boost_thread_win32-mt-s) - target_link_libraries(${EXECUTEABLE} crypt32) - target_link_libraries(${EXECUTEABLE} Qt5PlatformSupport) + target_link_libraries(${EXECUTABLE} gcc) + target_link_libraries(${EXECUTABLE} mingw32 qtmain mswsock iphlpapi qwindows shlwapi Qt5PlatformSupport opengl32 gdi32 comdlg32 oleaut32 imm32 winmm ole32 uuid ws2_32) + target_link_libraries(${EXECUTABLE} boost_system-mt-s) + target_link_libraries(${EXECUTABLE} boost_filesystem-mt-s) + target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) + target_link_libraries(${EXECUTABLE} crypt32) + target_link_libraries(${EXECUTABLE} Qt5PlatformSupport) set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) elseif (UNIX) + else () - target_link_libraries(${EXECUTEABLE} boost_system) - target_link_libraries(${EXECUTEABLE} boost_filesystem) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTEABLE} ${CMAKE_THREAD_LIBS_INIT}) - install( TARGETS ${EXECUTEABLE} RUNTIME DESTINATION bin ) + message(STATUS "platform not supported") endif () diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 854344819..7b938ae5f 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -29,3 +29,17 @@ if (${JSON_RPC_CPP_FOUND}) message (" - json-rpc-cpp lib : ${JSON_RPC_CPP_LIBRARIES}") add_definitions(-DETH_JSONRPC) endif() + +find_package (QT5Core REQUIRED) +find_package (QT5Gui REQUIRED) +find_package (Qt5Quick REQUIRED) +find_package (Qt5Qml REQUIRED) +find_package (Qt5Network REQUIRED) +find_package (Qt5Widgets REQUIRED) +find_package (Qt5WebKit REQUIRED) +find_package (Qt5WebKitWidgets REQUIRED) + + + + + diff --git a/libqethereum/CMakeLists.txt b/libqethereum/CMakeLists.txt index 7b2ab6ab6..c58c30426 100644 --- a/libqethereum/CMakeLists.txt +++ b/libqethereum/CMakeLists.txt @@ -1,111 +1,21 @@ -cmake_policy(SET CMP0015 NEW) - -if ("${TARGET_PLATFORM}" STREQUAL "w64") - cmake_policy(SET CMP0020 NEW) -endif () - +cmake_policy(SET CMP0015 OLD) set(CMAKE_INCLUDE_CURRENT_DIR ON) aux_source_directory(. SRC_LIST) include_directories(..) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) -link_directories(../libethereum) - -# Find Qt5 for Apple and update src_list for windows -if (APPLE) - # homebrew defaults to qt4 and installs qt5 as 'keg-only' - # which places it into /usr/local/opt insteadof /usr/local. - - set(CMAKE_PREFIX_PATH /usr/local/opt/qt5) - include_directories(/usr/local/opt/qt5/include /usr/local/include) -elseif ("${TARGET_PLATFORM}" STREQUAL "w64") - set(SRC_LIST ${SRC_LIST} ../windows/qt_plugin_import.cpp) -elseif (UNIX) - set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ";$ENV{QTDIR}/lib/cmake") -endif () - -find_package(Qt5Gui REQUIRED) -find_package(Qt5Quick REQUIRED) -find_package(Qt5Qml REQUIRED) -find_package(Qt5Network REQUIRED) -find_package(Qt5Widgets REQUIRED) -find_package(Qt5WebKit REQUIRED) -find_package(Qt5WebKitWidgets REQUIRED) set(EXECUTABLE qethereum) -# Set name of binary and add_executable() -if (APPLE) - set(CMAKE_INSTALL_PREFIX ./) - set(BIN_INSTALL_DIR ".") - set(DOC_INSTALL_DIR ".") - - set(PROJECT_VERSION "${ETH_VERSION}") - set(MACOSX_BUNDLE_INFO_STRING "${PROJECT_NAME} ${PROJECT_VERSION}") - set(MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_NAME} ${PROJECT_VERSION}") - set(MACOSX_BUNDLE_LONG_VERSION_STRING "${PROJECT_NAME} ${PROJECT_VERSION}") - set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION}") - set(MACOSX_BUNDLE_COPYRIGHT "${PROJECT_COPYRIGHT_YEAR} ${PROJECT_VENDOR}") - set(MACOSX_BUNDLE_GUI_IDENTIFIER "${PROJECT_DOMAIN_SECOND}.${PROJECT_DOMAIN_FIRST}") - set(MACOSX_BUNDLE_BUNDLE_NAME ${EXECUTABLE}) - include(BundleUtilities) -endif () file(GLOB HEADERS "*.h") + if(ETH_STATIC) add_library(${EXECUTABLE} STATIC ${RESOURCE_ADDED} ${SRC_LIST} ${HEADERS}) else() add_library(${EXECUTABLE} SHARED ${RESOURCE_ADDED} ${SRC_LIST} ${HEADERS}) endif() -include_directories(/) qt5_use_modules(${EXECUTABLE} Core Gui WebKit WebKitWidgets Widgets Network Quick Qml) target_link_libraries(${EXECUTABLE} ethereum secp256k1 ${JSON_RPC_CPP_LIBRARIES}) -if (APPLE) - if (${ADDFRAMEWORKS}) - set_target_properties(${EXECUTABLE} PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/EthereumMacOSXBundleInfo.plist.in") - endif () - - SET_SOURCE_FILES_PROPERTIES(${EXECUTABLE} PROPERTIES MACOSX_PACKAGE_LOCATION MacOS) - - # This is a workaround for when the build-type defaults to Debug, and when a multi-config generator like xcode is used, where the type - # will not be set but defaults to release. - set(generator_lowercase "${CMAKE_GENERATOR}") - string(TOLOWER "${CMAKE_GENERATOR}" generator_lowercase) - if ("${generator_lowercase}" STREQUAL "xcode") - # TODO: Not sure how to resolve this. Possibly \${TARGET_BUILD_DIR} - set(binary_build_dir "${CMAKE_CURRENT_BINARY_DIR}/Debug") - else () - set(binary_build_dir "${CMAKE_CURRENT_BINARY_DIR}") - endif () - - set(APPS ${binary_build_dir}/${EXECUTABLE}) - - if (${ADDFRAMEWORKS}) - add_custom_target(addframeworks ALL - COMMAND /usr/local/opt/qt5/bin/macdeployqt ${binary_build_dir}/${EXECUTABLE} - WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - DEPENDS ${PROJECT_NAME} - ) - endif () - -elseif ("${TARGET_PLATFORM}" STREQUAL "w64") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-keep-inline-dllexport -static-libgcc -static-libstdc++ -static") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-s -Wl,-subsystem,windows -mthreads -L/usr/x86_64-w64-mingw32/plugins/platforms") - target_link_libraries(${EXECUTABLE} gcc) - target_link_libraries(${EXECUTABLE} mingw32 qtmain mswsock iphlpapi qwindows shlwapi Qt5PlatformSupport gdi32 comdlg32 oleaut32 imm32 winmm ole32 uuid ws2_32) - target_link_libraries(${EXECUTABLE} boost_system-mt-s) - target_link_libraries(${EXECUTABLE} boost_filesystem-mt-s) - target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) - target_link_libraries(${EXECUTABLE} Qt5PlatformSupport) - set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) -elseif (UNIX) -else () - target_link_libraries(${EXECUTABLE} boost_system) - target_link_libraries(${EXECUTABLE} boost_filesystem) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) - install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) -endif () - diff --git a/third/CMakeLists.txt b/third/CMakeLists.txt index 3583bf6fa..383985318 100644 --- a/third/CMakeLists.txt +++ b/third/CMakeLists.txt @@ -5,8 +5,8 @@ include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) if (APPLE) # Add homebrew path for qt5 - set(CMAKE_PREFIX_PATH /usr/local/opt/qt5) - include_directories(/usr/local/opt/qt5/include /usr/local/include) + #set(CMAKE_PREFIX_PATH /usr/local/opt/qt5) + #include_directories(/usr/local/opt/qt5/include /usr/local/include) elseif ("${TARGET_PLATFORM}" STREQUAL "w64") set(SRC_LIST ${SRC_LIST} ../windows/qt_plugin_import.cpp) include_directories(/usr/x86_64-w64-mingw32/include /usr/x86_64-w64-mingw32/include/QtCore /usr/x86_64-w64-mingw32/include/QtGui /usr/x86_64-w64-mingw32/include/QtQuick /usr/x86_64-w64-mingw32/include/QtQml /usr/x86_64-w64-mingw32/include/QtNetwork /usr/x86_64-w64-mingw32/include/QtWidgets /usr/x86_64-w64-mingw32/include/QtWebKit /usr/x86_64-w64-mingw32/include/QtWebKitWidgets) @@ -14,14 +14,6 @@ elseif (UNIX) set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ";$ENV{QTDIR}/lib/cmake") endif () -find_package(Qt5Core REQUIRED) -find_package(Qt5Gui REQUIRED) -find_package(Qt5Quick REQUIRED) -find_package(Qt5Qml REQUIRED) -find_package(Qt5Network REQUIRED) -find_package(Qt5Widgets REQUIRED) -find_package(Qt5WebKit REQUIRED) -find_package(Qt5WebKitWidgets REQUIRED) qt5_wrap_ui(ui_Main.h Main.ui) @@ -59,7 +51,7 @@ target_link_libraries(${EXECUTEABLE} webthree qethereum ethereum evm ethcore sec if (APPLE) # First have qt5 install plugins and frameworks add_custom_command(TARGET ${EXECUTEABLE} POST_BUILD - COMMAND /usr/local/opt/qt5/bin/macdeployqt ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTEABLE}.app + COMMAND ${CMAKE_PREFIX_PATH}/bin/macdeployqt ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTEABLE}.app WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) # This tool and next will inspect linked libraries in order to determine which dependencies are required From 428468e2d221f5ab86acc06180b09ab905a456f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 1 Dec 2014 18:17:44 +0100 Subject: [PATCH 385/641] MSVS update --- windows/LibEthereum.vcxproj | 4 +++- windows/LibEthereum.vcxproj.filters | 16 +++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/windows/LibEthereum.vcxproj b/windows/LibEthereum.vcxproj index 4ae5d5bf8..66efe7dc2 100644 --- a/windows/LibEthereum.vcxproj +++ b/windows/LibEthereum.vcxproj @@ -125,6 +125,7 @@ + @@ -342,6 +343,7 @@ + @@ -574,4 +576,4 @@ - + \ No newline at end of file diff --git a/windows/LibEthereum.vcxproj.filters b/windows/LibEthereum.vcxproj.filters index fd03dd451..85f1fdedc 100644 --- a/windows/LibEthereum.vcxproj.filters +++ b/windows/LibEthereum.vcxproj.filters @@ -190,12 +190,6 @@ libdevcrypto - - libdevcrypto - - - libdevcrypto - libethereum @@ -205,6 +199,11 @@ libevm + + + + libethereum + @@ -444,6 +443,9 @@ libevm + + libethereum + @@ -480,4 +482,4 @@ {d838fece-fc20-42f6-bff5-97c236159b80} - + \ No newline at end of file From 27a0ad1e766826e03446f6f35841c4dc60b601cb Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 1 Dec 2014 19:20:52 +0100 Subject: [PATCH 386/641] cmake cleanup cd. --- alethzero/CMakeLists.txt | 19 ++++++++++++-- eth/CMakeLists.txt | 25 +++++++++++-------- exp/CMakeLists.txt | 35 +++++++------------------- libdevcore/CMakeLists.txt | 26 ++++++------------- libdevcore/CommonData.cpp | 3 ++- libdevcrypto/CMakeLists.txt | 33 +++++------------------- libweb3jsonrpc/CMakeLists.txt | 47 ++++++++++------------------------- 7 files changed, 69 insertions(+), 119 deletions(-) diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index 8d31f173c..0f2da0df0 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -1,4 +1,5 @@ cmake_policy(SET CMP0015 OLD) +#set(CMAKE_AUTOMOC OFF) set(CMAKE_INCLUDE_CURRENT_DIR ON) aux_source_directory(. SRC_LIST) @@ -35,7 +36,22 @@ else () endif () qt5_use_modules(${EXECUTABLE} Core) -target_link_libraries(${EXECUTABLE} webthree qethereum ethereum evm ethcore devcrypto secp256k1 gmp serpent lll solidity evmcore devcore web3jsonrpc jsqrc ${JSONCPP_LIBRARIES}) +target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) +target_link_libraries(${EXECUTABLE} webthree) +target_link_libraries(${EXECUTABLE} qethereum) +target_link_libraries(${EXECUTABLE} ethereum) +target_link_libraries(${EXECUTABLE} evm) +target_link_libraries(${EXECUTABLE} ethcore) +target_link_libraries(${EXECUTABLE} devcrypto) +target_link_libraries(${EXECUTABLE} secp256k1) +target_link_libraries(${EXECUTABLE} gmp) +target_link_libraries(${EXECUTABLE} serpent) +target_link_libraries(${EXECUTABLE} lll) +target_link_libraries(${EXECUTABLE} solidity) +target_link_libraries(${EXECUTABLE} evmcore) +target_link_libraries(${EXECUTABLE} devcore) +target_link_libraries(${EXECUTABLE} web3jsonrpc) +target_link_libraries(${EXECUTABLE} jsqrc) if (APPLE) # First have qt5 install plugins and frameworks @@ -74,7 +90,6 @@ elseif ("${TARGET_PLATFORM}" STREQUAL "w64") target_link_libraries(${EXECUTABLE} Qt5PlatformSupport) set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) elseif (UNIX) - else () message(STATUS "platform not supported") endif () diff --git a/eth/CMakeLists.txt b/eth/CMakeLists.txt index 934169e1f..5ccac182b 100644 --- a/eth/CMakeLists.txt +++ b/eth/CMakeLists.txt @@ -1,30 +1,35 @@ -cmake_policy(SET CMP0015 NEW) +cmake_policy(SET CMP0015 OLD) +set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) -include_directories(..) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) include_directories(${LEVELDB_INCLUDE_DIR}) +include_directories(..) set(EXECUTABLE eth) file(GLOB HEADERS "*.h") + add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) -target_link_libraries(${EXECUTABLE} webthree) -target_link_libraries(${EXECUTABLE} secp256k1) -target_link_libraries(${EXECUTABLE} gmp) if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() -target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) + if(JSON_RPC_CPP_FOUND) target_link_libraries(${EXECUTABLE} web3jsonrpc) endif() + if(READLINE_LS) target_link_libraries(${EXECUTABLE} ${READLINE_LS}) endif() +target_link_libraries(${EXECUTABLE} webthree) +target_link_libraries(${EXECUTABLE} secp256k1) +target_link_libraries(${EXECUTABLE} gmp) + if ("${TARGET_PLATFORM}" STREQUAL "w64") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") target_link_libraries(${EXECUTABLE} boost_system-mt-s) @@ -39,10 +44,10 @@ if ("${TARGET_PLATFORM}" STREQUAL "w64") set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) elseif (UNIX) else () - target_link_libraries(${EXECUTABLE} boost_system) - target_link_libraries(${EXECUTABLE} boost_filesystem) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) + #target_link_libraries(${EXECUTABLE} boost_system) + #target_link_libraries(${EXECUTABLE} boost_filesystem) + #find_package(Threads REQUIRED) + #target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) endif () install( TARGETS ${EXECUTABLE} DESTINATION bin ) diff --git a/exp/CMakeLists.txt b/exp/CMakeLists.txt index 26ee835d4..6fcea5341 100644 --- a/exp/CMakeLists.txt +++ b/exp/CMakeLists.txt @@ -1,41 +1,24 @@ cmake_policy(SET CMP0015 NEW) +set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) -include_directories(..) include_directories(${LEVELDB_INCLUDE_DIR}) +include_directories(..) set(EXECUTABLE exp) add_executable(${EXECUTABLE} ${SRC_LIST}) -target_link_libraries(${EXECUTABLE} ethereum) -target_link_libraries(${EXECUTABLE} p2p) -target_link_libraries(${EXECUTABLE} gmp) +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) + if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() -target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) -if ("${TARGET_PLATFORM}" STREQUAL "w64") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") - target_link_libraries(${EXECUTABLE} gcc) - target_link_libraries(${EXECUTABLE} gdi32) - target_link_libraries(${EXECUTABLE} ws2_32) - target_link_libraries(${EXECUTABLE} mswsock) - target_link_libraries(${EXECUTABLE} shlwapi) - target_link_libraries(${EXECUTABLE} iphlpapi) - target_link_libraries(${EXECUTABLE} boost_system-mt-s) - target_link_libraries(${EXECUTABLE} boost_filesystem-mt-s) - target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) - set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) -elseif (UNIX) -else () - target_link_libraries(${EXECUTABLE} boost_system) - target_link_libraries(${EXECUTABLE} boost_filesystem) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -endif () - -install( TARGETS ${EXECUTABLE} DESTINATION bin ) +target_link_libraries(${EXECUTABLE} ethereum) +target_link_libraries(${EXECUTABLE} p2p) +target_link_libraries(${EXECUTABLE} gmp) + +install( TARGETS ${EXECUTABLE} DESTINATION bin) diff --git a/libdevcore/CMakeLists.txt b/libdevcore/CMakeLists.txt index 939f20593..3ff0733b4 100644 --- a/libdevcore/CMakeLists.txt +++ b/libdevcore/CMakeLists.txt @@ -1,32 +1,24 @@ -cmake_policy(SET CMP0015 NEW) - -if (CMAKE_MAJOR_VERSION GREATER 1 AND CMAKE_MINOR_VERSION GREATER 7 AND CMAKE_PATCH_VERSION GREATER 11) - cmake_policy(SET CMP0022 NEW) -endif() +cmake_policy(SET CMP0015 OLD) +set(CMAKE_AUTOMOC OFF) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) -include_directories(..) + include_directories(${LEVELDB_INCLUDE_DIR}) +include_directories(..) set(EXECUTABLE devcore) file(GLOB HEADERS "*.h") + if(ETH_STATIC) add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -if("${TARGET_PLATFORM}" STREQUAL "w64") - target_link_libraries(${EXECUTABLE} boost_system-mt-s) - target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) - target_link_libraries(${EXECUTABLE} iphlpapi) - target_link_libraries(${EXECUTABLE} ws2_32) - target_link_libraries(${EXECUTABLE} mswsock) - target_link_libraries(${EXECUTABLE} shlwapi) -elseif (APPLE) +if (APPLE) # Latest mavericks boost libraries only come with -mt target_link_libraries(${EXECUTABLE} boost_system-mt) target_link_libraries(${EXECUTABLE} boost_filesystem-mt) @@ -38,11 +30,7 @@ elseif (UNIX) target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY} ${Boost_SYSTEM_LIBRARY}) find_package(Threads REQUIRED) target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -else () - target_link_libraries(${EXECUTABLE} boost_thread) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -endif () +endif() install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libdevcore/CommonData.cpp b/libdevcore/CommonData.cpp index bd7841402..d34b565eb 100644 --- a/libdevcore/CommonData.cpp +++ b/libdevcore/CommonData.cpp @@ -23,7 +23,8 @@ #include #include "Exceptions.h" -#include +#include "Log.h" + using namespace std; using namespace dev; diff --git a/libdevcrypto/CMakeLists.txt b/libdevcrypto/CMakeLists.txt index 7de842fc5..423a9ccc6 100644 --- a/libdevcrypto/CMakeLists.txt +++ b/libdevcrypto/CMakeLists.txt @@ -1,4 +1,5 @@ -cmake_policy(SET CMP0015 NEW) +cmake_policy(SET CMP0015 OLD) +set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) @@ -11,44 +12,22 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -include_directories(..) include_directories(${CRYPTOPP_INCLUDE_DIR}) include_directories(${LEVELDB_INCLUDE_DIR}) +include_directories(..) +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LIBRARIES}) target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} secp256k1) target_link_libraries(${EXECUTABLE} gmp) -target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) -target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LIBRARIES}) -if("${TARGET_PLATFORM}" STREQUAL "w64") - target_link_libraries(${EXECUTABLE} boost_system-mt-s) - target_link_libraries(${EXECUTABLE} boost_filesystem-mt-s) - target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) - target_link_libraries(${EXECUTABLE} iphlpapi) - target_link_libraries(${EXECUTABLE} ws2_32) - target_link_libraries(${EXECUTABLE} mswsock) - target_link_libraries(${EXECUTABLE} shlwapi) -elseif (APPLE) +if (APPLE) # Latest mavericks boost libraries only come with -mt - target_link_libraries(${EXECUTABLE} boost_system-mt) target_link_libraries(${EXECUTABLE} boost_filesystem-mt) - target_link_libraries(${EXECUTABLE} boost_thread-mt) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) elseif (UNIX) find_package(Boost 1.53 REQUIRED COMPONENTS filesystem) - target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARY}) target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -else () - target_link_libraries(${EXECUTABLE} boost_system) - target_link_libraries(${EXECUTABLE} boost_filesystem) - target_link_libraries(${EXECUTABLE} boost_thread) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) endif () install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) diff --git a/libweb3jsonrpc/CMakeLists.txt b/libweb3jsonrpc/CMakeLists.txt index 5fb2662e1..97130718e 100644 --- a/libweb3jsonrpc/CMakeLists.txt +++ b/libweb3jsonrpc/CMakeLists.txt @@ -1,56 +1,35 @@ -cmake_policy(SET CMP0015 NEW) +cmake_policy(SET CMP0015 OLD) +set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) -include_directories(..) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) include_directories(${LEVELDB_INCLUDE_DIR}) -link_directories(../libethcore) -link_directories(../libwebthree) +include_directories(..) set(EXECUTABLE web3jsonrpc) + file(GLOB HEADERS "*.h") -if(ETH_STATIC) +if (ETH_STATIC) add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -target_link_libraries(${EXECUTABLE} webthree) -target_link_libraries(${EXECUTABLE} secp256k1) -target_link_libraries(${EXECUTABLE} gmp) -target_link_libraries(${EXECUTABLE} solidity) -target_link_libraries(${EXECUTABLE} serpent) -if(MINIUPNPC_LS) - target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) -endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_LIBRARIES}) -if(READLINE_LS) -target_link_libraries(${EXECUTABLE} ${READLINE_LS}) + +if (MINIUPNPC_LS) + target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() -if ("${TARGET_PLATFORM}" STREQUAL "w64") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") - target_link_libraries(${EXECUTABLE} boost_system-mt-s) - target_link_libraries(${EXECUTABLE} boost_filesystem-mt-s) - target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) - target_link_libraries(${EXECUTABLE} gcc) - target_link_libraries(${EXECUTABLE} gdi32) - target_link_libraries(${EXECUTABLE} ws2_32) - target_link_libraries(${EXECUTABLE} mswsock) - target_link_libraries(${EXECUTABLE} shlwapi) - target_link_libraries(${EXECUTABLE} iphlpapi) - set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) -elseif (UNIX) -else () - target_link_libraries(${EXECUTABLE} boost_system) - target_link_libraries(${EXECUTABLE} boost_filesystem) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -endif () +target_link_libraries(${EXECUTABLE} webthree) +target_link_libraries(${EXECUTABLE} secp256k1) +target_link_libraries(${EXECUTABLE} gmp) +target_link_libraries(${EXECUTABLE} solidity) +target_link_libraries(${EXECUTABLE} serpent) install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) From 110964ffe2e7183c42e1feadddd47ee876e5d287 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 1 Dec 2014 20:24:20 +0100 Subject: [PATCH 387/641] common changes in cleanup --- alethzero/CMakeLists.txt | 1 + libethcore/CMakeLists.txt | 38 +++++++++---------------------------- libethereum/CMakeLists.txt | 36 ++++++++++++----------------------- libethereumx/CMakeLists.txt | 34 ++++++++++----------------------- libevm/CMakeLists.txt | 29 +++++++++------------------- libqethereum/CMakeLists.txt | 2 ++ libserpent/CMakeLists.txt | 1 - 7 files changed, 43 insertions(+), 98 deletions(-) diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index 0f2da0df0..b7c41cda3 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -37,6 +37,7 @@ endif () qt5_use_modules(${EXECUTABLE} Core) target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) target_link_libraries(${EXECUTABLE} webthree) target_link_libraries(${EXECUTABLE} qethereum) target_link_libraries(${EXECUTABLE} ethereum) diff --git a/libethcore/CMakeLists.txt b/libethcore/CMakeLists.txt index 0c50320c3..99ae26776 100644 --- a/libethcore/CMakeLists.txt +++ b/libethcore/CMakeLists.txt @@ -1,54 +1,34 @@ cmake_policy(SET CMP0015 NEW) +set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) -include_directories(..) + include_directories(${CRYPTOPP_INCLUDE_DIR}) include_directories(${LEVELDB_INCLUDE_DIR}) +include_directories(..) set(EXECUTABLE ethcore) file(GLOB HEADERS "*.h") + if(ETH_STATIC) add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) + add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} secp256k1) target_link_libraries(${EXECUTABLE} gmp) -target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) -if("${TARGET_PLATFORM}" STREQUAL "w64") - target_link_libraries(${EXECUTABLE} boost_system-mt-s) - target_link_libraries(${EXECUTABLE} boost_filesystem-mt-s) - target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) - target_link_libraries(${EXECUTABLE} iphlpapi) - target_link_libraries(${EXECUTABLE} ws2_32) - target_link_libraries(${EXECUTABLE} mswsock) - target_link_libraries(${EXECUTABLE} shlwapi) -elseif (APPLE) - # Latest mavericks boost libraries only come with -mt +if (APPLE) target_link_libraries(${EXECUTABLE} boost_system-mt) - target_link_libraries(${EXECUTABLE} boost_filesystem-mt) - target_link_libraries(${EXECUTABLE} boost_thread-mt) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) elseif (UNIX) - find_package(Boost 1.53 REQUIRED COMPONENTS filesystem) + find_package(Boost 1.53 REQUIRED COMPONENTS system) target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -else () - target_link_libraries(${EXECUTABLE} boost_system) - target_link_libraries(${EXECUTABLE} boost_filesystem) - target_link_libraries(${EXECUTABLE} boost_thread) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -endif () +endif() install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libethereum/CMakeLists.txt b/libethereum/CMakeLists.txt index 3266a8801..ce1b830f5 100644 --- a/libethereum/CMakeLists.txt +++ b/libethereum/CMakeLists.txt @@ -1,4 +1,5 @@ -cmake_policy(SET CMP0015 NEW) +cmake_policy(SET CMP0015 OLD) +set(CMAKE_AUTOMOC OFF) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") @@ -7,14 +8,21 @@ aux_source_directory(. SRC_LIST) set(EXECUTABLE ethereum) file(GLOB HEADERS "*.h") -if(ETH_STATIC) + +if (ETH_STATIC) add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -include_directories(..) include_directories(${LEVELDB_INCLUDE_DIR}) +include_directories(..) + +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) + +if (MINIUPNPC_LS) +target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) +endif() target_link_libraries(${EXECUTABLE} evm) target_link_libraries(${EXECUTABLE} lll) @@ -23,22 +31,9 @@ target_link_libraries(${EXECUTABLE} p2p) target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} secp256k1) -if(MINIUPNPC_LS) -target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) -endif() -target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) target_link_libraries(${EXECUTABLE} gmp) -if("${TARGET_PLATFORM}" STREQUAL "w64") - target_link_libraries(${EXECUTABLE} boost_system-mt-s) - target_link_libraries(${EXECUTABLE} boost_regex-mt-s) - target_link_libraries(${EXECUTABLE} boost_filesystem-mt-s) - target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) - target_link_libraries(${EXECUTABLE} iphlpapi) - target_link_libraries(${EXECUTABLE} ws2_32) - target_link_libraries(${EXECUTABLE} mswsock) - target_link_libraries(${EXECUTABLE} shlwapi) -elseif (APPLE) +if (APPLE) # Latest mavericks boost libraries only come with -mt target_link_libraries(${EXECUTABLE} boost_system-mt) target_link_libraries(${EXECUTABLE} boost_regex-mt) @@ -53,13 +48,6 @@ elseif (UNIX) target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY}) target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARY}) target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -else () - target_link_libraries(${EXECUTABLE} boost_system) - target_link_libraries(${EXECUTABLE} boost_regex) - target_link_libraries(${EXECUTABLE} boost_filesystem) - target_link_libraries(${EXECUTABLE} boost_thread) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) endif () install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) diff --git a/libethereumx/CMakeLists.txt b/libethereumx/CMakeLists.txt index 1c74bf2c3..1063f7981 100644 --- a/libethereumx/CMakeLists.txt +++ b/libethereumx/CMakeLists.txt @@ -1,12 +1,13 @@ cmake_policy(SET CMP0015 NEW) +set(CMAKE_AUTOMOC OFF) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) +include_directories(..) set(EXECUTABLE ethereumx) -# set(CMAKE_INSTALL_PREFIX ../lib) if(ETH_STATIC) add_library(${EXECUTABLE} STATIC ${SRC_LIST}) else() @@ -15,30 +16,22 @@ endif() file(GLOB HEADERS "*.h") -include_directories(..) + +target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) +target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS}) + +if (MINIUPNPC_LS) +target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) +endif() target_link_libraries(${EXECUTABLE} ethereum) target_link_libraries(${EXECUTABLE} evm) target_link_libraries(${EXECUTABLE} lll) target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} secp256k1) -if(MINIUPNPC_LS) -target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) -endif() -target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) -target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS}) target_link_libraries(${EXECUTABLE} gmp) -if("${TARGET_PLATFORM}" STREQUAL "w64") - target_link_libraries(${EXECUTABLE} boost_system-mt-s) - target_link_libraries(${EXECUTABLE} boost_regex-mt-s) - target_link_libraries(${EXECUTABLE} boost_filesystem-mt-s) - target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) - target_link_libraries(${EXECUTABLE} iphlpapi) - target_link_libraries(${EXECUTABLE} ws2_32) - target_link_libraries(${EXECUTABLE} mswsock) - target_link_libraries(${EXECUTABLE} shlwapi) -elseif (APPLE) +if (APPLE) # Latest mavericks boost libraries only come with -mt target_link_libraries(${EXECUTABLE} boost_system-mt) target_link_libraries(${EXECUTABLE} boost_regex-mt) @@ -53,13 +46,6 @@ elseif (UNIX) target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY}) target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARY}) target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -else () - target_link_libraries(${EXECUTABLE} boost_system) - target_link_libraries(${EXECUTABLE} boost_regex) - target_link_libraries(${EXECUTABLE} boost_filesystem) - target_link_libraries(${EXECUTABLE} boost_thread) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) endif () install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) diff --git a/libevm/CMakeLists.txt b/libevm/CMakeLists.txt index 2812be808..8815d123c 100644 --- a/libevm/CMakeLists.txt +++ b/libevm/CMakeLists.txt @@ -1,4 +1,5 @@ cmake_policy(SET CMP0015 NEW) +set(CMAKE_AUTOMOC OFF) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") @@ -13,8 +14,14 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -include_directories(..) include_directories(${LEVELDB_INCLUDE_DIR}) +include_directories(..) + +if(MINIUPNPC_LS) +target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) +endif() + +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} devcrypto) @@ -22,20 +29,8 @@ target_link_libraries(${EXECUTABLE} evmcore) target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} secp256k1) target_link_libraries(${EXECUTABLE} gmp) -if(MINIUPNPC_LS) -target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) -endif() -target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) -if("${TARGET_PLATFORM}" STREQUAL "w64") - target_link_libraries(${EXECUTABLE} boost_system-mt-s) - target_link_libraries(${EXECUTABLE} boost_filesystem-mt-s) - target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) - target_link_libraries(${EXECUTABLE} iphlpapi) - target_link_libraries(${EXECUTABLE} ws2_32) - target_link_libraries(${EXECUTABLE} mswsock) - target_link_libraries(${EXECUTABLE} shlwapi) -elseif (APPLE) +if (APPLE) # Latest mavericks boost libraries only come with -mt target_link_libraries(${EXECUTABLE} boost_system-mt) target_link_libraries(${EXECUTABLE} boost_filesystem-mt) @@ -48,12 +43,6 @@ elseif (UNIX) target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY}) target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARY}) target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -else () - target_link_libraries(${EXECUTABLE} boost_system) - target_link_libraries(${EXECUTABLE} boost_filesystem) - target_link_libraries(${EXECUTABLE} boost_thread) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) endif () install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) diff --git a/libqethereum/CMakeLists.txt b/libqethereum/CMakeLists.txt index c58c30426..bcc49e997 100644 --- a/libqethereum/CMakeLists.txt +++ b/libqethereum/CMakeLists.txt @@ -19,3 +19,5 @@ endif() qt5_use_modules(${EXECUTABLE} Core Gui WebKit WebKitWidgets Widgets Network Quick Qml) target_link_libraries(${EXECUTABLE} ethereum secp256k1 ${JSON_RPC_CPP_LIBRARIES}) +install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) +install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libserpent/CMakeLists.txt b/libserpent/CMakeLists.txt index c2fe89cc0..06f5dc93b 100644 --- a/libserpent/CMakeLists.txt +++ b/libserpent/CMakeLists.txt @@ -41,5 +41,4 @@ endif () install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) -#install( FILES ${CMAKE_CURRENT_BINARY_DIR}/libserpent.so DESTINATION lib ) From 3015713894354ea32075cb2b672f48796e70a488 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 1 Dec 2014 21:30:00 +0100 Subject: [PATCH 388/641] common changes --- alethzero/CMakeLists.txt | 6 ++++-- extdep/CMakeLists.txt | 5 +++++ extdep/leveldb.cmake | 4 ++-- libqethereum/CMakeLists.txt | 5 ++++- libweb3jsonrpc/CMakeLists.txt | 3 ++- test/CMakeLists.txt | 1 + 6 files changed, 18 insertions(+), 6 deletions(-) diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index b7c41cda3..aa759b37a 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_policy(SET CMP0015 OLD) +#cmake_policy(SET CMP0015 OLD) #set(CMAKE_AUTOMOC OFF) set(CMAKE_INCLUDE_CURRENT_DIR ON) @@ -37,7 +37,9 @@ endif () qt5_use_modules(${EXECUTABLE} Core) target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) -target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) +#target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) +#target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_COMMON_LIBRARY}) +#target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_SERVER_LIBRARY}) target_link_libraries(${EXECUTABLE} webthree) target_link_libraries(${EXECUTABLE} qethereum) target_link_libraries(${EXECUTABLE} ethereum) diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index 975207c8b..9ee9e7728 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -22,3 +22,8 @@ include(leveldb.cmake) # will be re-eanbled later # include(miniupnpc.cmake) + + +# BUG +# becouse extdep/cmakelist.txt is subfolder of ethereum project its being install into binary destination on macos. it's a bug + diff --git a/extdep/leveldb.cmake b/extdep/leveldb.cmake index 8b494457f..5399b34b8 100644 --- a/extdep/leveldb.cmake +++ b/extdep/leveldb.cmake @@ -1,11 +1,11 @@ -if(APPLE) +if (APPLE) ExternalProject_Add(leveldb DEPENDS snappy URL https://leveldb.googlecode.com/files/leveldb-1.15.0.tar.gz BINARY_DIR leveldb-prefix/src/leveldb CONFIGURE_COMMAND patch < ${CMAKE_CURRENT_SOURCE_DIR}/leveldb_osx.patch BUILD_COMMAND export ETH_DEPENDENCY_INSTALL_DIR=${ETH_DEPENDENCY_INSTALL_DIR} && make -j 3 - INSTALL_COMMAND cp -rf include/leveldb ${ETH_DEPENDENCY_INSTALL_DIR}/include/ && mv libleveldb.a ${ETH_DEPENDENCY_INSTALL_DIR}/lib && mv libleveldb.dylib.1.15 ${ETH_DEPENDENCY_INSTALL_DIR}/lib/libleveldb.dylib + INSTALL_COMMAND cp -rf include/leveldb ${ETH_DEPENDENCY_INSTALL_DIR}/include/ && cp libleveldb.a ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp libleveldb.dylib.1.15 ${ETH_DEPENDENCY_INSTALL_DIR}/lib/libleveldb.dylib ) elseif(WIN32) ExternalProject_Add(leveldb diff --git a/libqethereum/CMakeLists.txt b/libqethereum/CMakeLists.txt index bcc49e997..56e0ba94a 100644 --- a/libqethereum/CMakeLists.txt +++ b/libqethereum/CMakeLists.txt @@ -17,7 +17,10 @@ else() endif() qt5_use_modules(${EXECUTABLE} Core Gui WebKit WebKitWidgets Widgets Network Quick Qml) -target_link_libraries(${EXECUTABLE} ethereum secp256k1 ${JSON_RPC_CPP_LIBRARIES}) +target_link_libraries(${EXECUTABLE} ethereum) +target_link_libraries(${EXECUTABLE} secp256k1) +target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_COMMON_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_SERVER_LIBRARY}) install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libweb3jsonrpc/CMakeLists.txt b/libweb3jsonrpc/CMakeLists.txt index 97130718e..fcc9f0ee9 100644 --- a/libweb3jsonrpc/CMakeLists.txt +++ b/libweb3jsonrpc/CMakeLists.txt @@ -19,7 +19,8 @@ endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) -target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_LIBRARIES}) +target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_COMMON_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_SERVER_LIBRARY}) if (MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 71b88dbaa..59eb34bc8 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -24,6 +24,7 @@ target_link_libraries(testeth ${CRYPTOPP_LIBRARIES}) if(JSON_RPC_CPP_FOUND) target_link_libraries(testeth ${JSONCPP_LIBRARIES}) target_link_libraries(testeth web3jsonrpc) + target_link_libraries(testeth ${JSON_RPC_CPP_CLIENT_LIBRARY}) endif() target_link_libraries(createRandomTest ethereum) From 0d876d099037edeec634f8ac9e526c5d01683560 Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 2 Dec 2014 10:25:14 +0100 Subject: [PATCH 389/641] common changes --- extdep/jom.cmake | 2 +- extdep/qt.cmake | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/extdep/jom.cmake b/extdep/jom.cmake index 0370eed8e..e5bc5542e 100644 --- a/extdep/jom.cmake +++ b/extdep/jom.cmake @@ -7,7 +7,7 @@ ExternalProject_Add(jom URL http://download.qt-project.org/official_releases/jom/jom.zip BINARY_DIR jom-prefix/src/jom CONFIGURE_COMMAND "" - BUILD_COMMAND echo %cd% + BUILD_COMMAND "" INSTALL_COMMAND cp jom.exe ${ETH_DEPENDENCY_INSTALL_DIR}/bin ) diff --git a/extdep/qt.cmake b/extdep/qt.cmake index 863810d1c..afa40c97b 100644 --- a/extdep/qt.cmake +++ b/extdep/qt.cmake @@ -19,12 +19,6 @@ ExternalProject_Add_Step(qt configure_paths DEPENDERS configure ) -#ExternalProject_Add_Step(qt configure_visual -# COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/tools.bat -# DEPENDEES patch -# DEPENDERS configure -# ) - else() endif() From 0f503f1577db9ec48c70402ac82b94d664fac7a1 Mon Sep 17 00:00:00 2001 From: sveneh Date: Tue, 2 Dec 2014 19:01:24 +0100 Subject: [PATCH 390/641] converted whitespaces to tabs according to style guide; handling if json-rpc-cpp is not available --- CMakeLists.txt | 2 +- cmake/EthDependencies.cmake | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 73dc83d80..3b10caa60 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -139,7 +139,7 @@ if (NOT LANGUAGES) add_subdirectory(exp) endif () if(NOT ("${TARGET_PLATFORM}" STREQUAL "w64")) - add_subdirectory(neth) + add_subdirectory(neth) endif () if(QTQML) add_definitions(-DETH_QTQML) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 04e57cce7..776657bd3 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -19,9 +19,10 @@ message(" - Jsoncpp header: ${JSONCPP_INCLUDE_DIRS}") message(" - Jsoncpp lib : ${JSONCPP_LIBRARIES}") # TODO the JsonRpcCpp package does not yet check for correct version number -find_package (JsonRpcCpp 0.3.2 REQUIRED) +# json-rpc-cpp support is currently not mandatory +find_package (JsonRpcCpp 0.3.2) if (${JSON_RPC_CPP_FOUND}) - message (" - json-rpc-cpp header: ${JSON_RPC_CPP_INCLUDE_DIRS}") - message (" - json-rpc-cpp lib : ${JSON_RPC_CPP_LIBRARIES}") + message (" - json-rpc-cpp header: ${JSON_RPC_CPP_INCLUDE_DIRS}") + message (" - json-rpc-cpp lib : ${JSON_RPC_CPP_LIBRARIES}") add_definitions(-DETH_JSONRPC) endif() From 2121aad995d8a2d095b3e6fe2743e7c96fac7600 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 3 Dec 2014 09:34:04 +0100 Subject: [PATCH 391/641] common changes --- alethzero/CMakeLists.txt | 2 +- extdep/CMakeLists.txt | 4 +-- iethxi/CMakeLists.txt | 68 +++++++++++++--------------------------- 3 files changed, 23 insertions(+), 51 deletions(-) diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index aa759b37a..5b3704c14 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -94,6 +94,6 @@ elseif ("${TARGET_PLATFORM}" STREQUAL "w64") set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) elseif (UNIX) else () - message(STATUS "platform not supported") + message(ERROR "platform not supported") endif () diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index 9ee9e7728..6c73d3719 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -23,7 +23,5 @@ include(leveldb.cmake) # will be re-eanbled later # include(miniupnpc.cmake) - -# BUG -# becouse extdep/cmakelist.txt is subfolder of ethereum project its being install into binary destination on macos. it's a bug +# if install phase of extep fails, even if libs are already created, the ethereum install will fail diff --git a/iethxi/CMakeLists.txt b/iethxi/CMakeLists.txt index 77c26dd4d..c2203a4f6 100644 --- a/iethxi/CMakeLists.txt +++ b/iethxi/CMakeLists.txt @@ -1,9 +1,4 @@ -cmake_policy(SET CMP0015 NEW) - -if ("${TARGET_PLATFORM}" STREQUAL "w64") - cmake_policy(SET CMP0020 NEW) -endif () - +cmake_policy(SET CMP0015 OLD) set(CMAKE_INCLUDE_CURRENT_DIR ON) aux_source_directory(. SRC_LIST) @@ -13,31 +8,12 @@ link_directories(../libethcore) link_directories(../libethereum) link_directories(../libqethereum) -# Find Qt5 for Apple and update src_list for windows -if (APPLE) - # homebrew defaults to qt4 and installs qt5 as 'keg-only' - # which places it into /usr/local/opt insteadof /usr/local. - - set(CMAKE_PREFIX_PATH /usr/local/opt/qt5) - include_directories(/usr/local/opt/qt5/include /usr/local/include) -elseif ("${TARGET_PLATFORM}" STREQUAL "w64") - set(SRC_LIST ${SRC_LIST} ../windows/qt_plugin_import.cpp) -elseif (UNIX) - set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ";$ENV{QTDIR}/lib/cmake") -endif () - - -find_package(Qt5Widgets REQUIRED) -find_package(Qt5Gui REQUIRED) -find_package(Qt5Quick REQUIRED) -find_package(Qt5Qml REQUIRED) -find_package(Qt5Network REQUIRED) qt5_wrap_ui(ui_Main.h Main.ui) qt5_add_resources(RESOURCE_ADDED Resources.qrc) # Set name of binary and add_executable() if (APPLE) - set(EXECUTEABLE IEthXi) + set(EXECUTABLE IEthXi) set(CMAKE_INSTALL_PREFIX ./) set(BIN_INSTALL_DIR ".") set(DOC_INSTALL_DIR ".") @@ -49,24 +25,26 @@ if (APPLE) set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION}") set(MACOSX_BUNDLE_COPYRIGHT "${PROJECT_COPYRIGHT_YEAR} ${PROJECT_VENDOR}") set(MACOSX_BUNDLE_GUI_IDENTIFIER "${PROJECT_DOMAIN_SECOND}.${PROJECT_DOMAIN_FIRST}") - set(MACOSX_BUNDLE_BUNDLE_NAME ${EXECUTEABLE}) + set(MACOSX_BUNDLE_BUNDLE_NAME ${EXECUTABLE}) include(BundleUtilities) - add_executable(${EXECUTEABLE} MACOSX_BUNDLE Main.ui ${RESOURCE_ADDED} ${SRC_LIST}) + add_executable(${EXECUTABLE} MACOSX_BUNDLE Main.ui ${RESOURCE_ADDED} ${SRC_LIST}) else () - set(EXECUTEABLE iethxi) - add_executable(${EXECUTEABLE} Main.ui ${RESOURCE_ADDED} ${SRC_LIST}) + set(EXECUTABLE iethxi) + add_executable(${EXECUTABLE} Main.ui ${RESOURCE_ADDED} ${SRC_LIST}) endif () -qt5_use_modules(${EXECUTEABLE} Core Gui Widgets Network Quick Qml) -target_link_libraries(${EXECUTEABLE} qethereum ethereum secp256k1) +qt5_use_modules(${EXECUTABLE} Core Gui Widgets Network Quick Qml) +target_link_libraries(${EXECUTABLE} qethereum) +target_link_libraries(${EXECUTABLE} ethereum) +target_link_libraries(${EXECUTABLE} secp256k1) if (APPLE) if (${ADDFRAMEWORKS}) - set_target_properties(${EXECUTEABLE} PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/EthereumMacOSXBundleInfo.plist.in") + set_target_properties(${EXECUTABLE} PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/EthereumMacOSXBundleInfo.plist.in") endif () - SET_SOURCE_FILES_PROPERTIES(${EXECUTEABLE} PROPERTIES MACOSX_PACKAGE_LOCATION MacOS) + SET_SOURCE_FILES_PROPERTIES(${EXECUTABLE} PROPERTIES MACOSX_PACKAGE_LOCATION MacOS) # This is a workaround for when the build-type defaults to Debug, and when a multi-config generator like xcode is used, where the type # will not be set but defaults to release. @@ -79,7 +57,7 @@ if (APPLE) set(binary_build_dir "${CMAKE_CURRENT_BINARY_DIR}") endif () - set(APPS ${binary_build_dir}/${EXECUTEABLE}.app) + set(APPS ${binary_build_dir}/${EXECUTABLE}.app) # This tool and the next will automatically looked at the linked libraries in order to determine what dependencies are required. Thus, target_link_libaries only needs to add ethereum and secp256k1 (above) install(CODE " @@ -90,7 +68,7 @@ if (APPLE) if (${ADDFRAMEWORKS}) add_custom_target(addframeworks ALL - COMMAND /usr/local/opt/qt5/bin/macdeployqt ${binary_build_dir}/${EXECUTEABLE}.app + COMMAND /usr/local/opt/qt5/bin/macdeployqt ${binary_build_dir}/${EXECUTABLE}.app WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} DEPENDS ${PROJECT_NAME} ) @@ -99,19 +77,15 @@ if (APPLE) elseif ("${TARGET_PLATFORM}" STREQUAL "w64") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-keep-inline-dllexport -static-libgcc -static-libstdc++ -static") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-s -Wl,-subsystem,windows -mthreads -L/usr/x86_64-w64-mingw32/plugins/platforms") - target_link_libraries(${EXECUTEABLE} gcc) - target_link_libraries(${EXECUTEABLE} mingw32 qtmain mswsock iphlpapi qwindows shlwapi Qt5PlatformSupport gdi32 comdlg32 oleaut32 imm32 winmm ole32 uuid ws2_32) - target_link_libraries(${EXECUTEABLE} boost_system-mt-s) - target_link_libraries(${EXECUTEABLE} boost_filesystem-mt-s) - target_link_libraries(${EXECUTEABLE} boost_thread_win32-mt-s) - target_link_libraries(${EXECUTEABLE} Qt5PlatformSupport) + target_link_libraries(${EXECUTABLE} gcc) + target_link_libraries(${EXECUTABLE} mingw32 qtmain mswsock iphlpapi qwindows shlwapi Qt5PlatformSupport gdi32 comdlg32 oleaut32 imm32 winmm ole32 uuid ws2_32) + target_link_libraries(${EXECUTABLE} boost_system-mt-s) + target_link_libraries(${EXECUTABLE} boost_filesystem-mt-s) + target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) + target_link_libraries(${EXECUTABLE} Qt5PlatformSupport) set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) elseif (UNIX) else () - target_link_libraries(${EXECUTEABLE} boost_system) - target_link_libraries(${EXECUTEABLE} boost_filesystem) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTEABLE} ${CMAKE_THREAD_LIBS_INIT}) - install( TARGETS ${EXECUTEABLE} RUNTIME DESTINATION bin ) + message(ERROR "platform not supported") endif () From d134a9b4e3b1911a97930a47dfd0b6186ed58d35 Mon Sep 17 00:00:00 2001 From: sveneh Date: Wed, 3 Dec 2014 10:40:55 +0100 Subject: [PATCH 392/641] inital script for CI building. Currently only builds dependencies --- build.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100755 build.py diff --git a/build.py b/build.py new file mode 100755 index 000000000..099a8721d --- /dev/null +++ b/build.py @@ -0,0 +1,27 @@ +#!/usr/bin/python +# cpp-ethereum build script +# to be used from CI server, or to build locally +# uses python instead of bash script for better cross-platform support + +# TODO Initial version. Needs much more improvements + +import argparse +import os +import subprocess + +def build_dependencies(): + if os.path.exists("extdep"): + os.chdir("extdep") + if not os.path.exists("build"): + os.makedirs("build") + os.chdir("build") + subprocess.check_call(["cmake", ".."]) + subprocess.check_call("make") + +parser = argparse.ArgumentParser() +parser.add_argument("cmd", help="what to build") + +args = parser.parse_args() +if args.cmd == "dep": + build_dependencies() + From 7b0688378aa424a3d9badd60633303b719ad3765 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 3 Dec 2014 11:44:12 +0100 Subject: [PATCH 393/641] changed structure of extdep --- extdep/CMakeLists.txt | 30 ++++++++++++------- extdep/{ => cmake}/FindCURL.cmake | 0 extdep/{ => compile}/argtable2.cmake | 0 extdep/{ => compile}/cryptopp.cmake | 0 extdep/{ => compile}/curl.cmake | 0 extdep/{ => compile}/icu.cmake | 0 extdep/{ => compile}/jom.cmake | 0 extdep/{ => compile}/json-rpc-cpp.cmake | 4 +-- extdep/{ => compile}/jsoncpp.cmake | 0 extdep/{ => compile}/leveldb.cmake | 2 +- extdep/{ => compile}/leveldb_osx.patch | 0 extdep/{ => compile}/qt.cmake | 6 ++-- .../qt_configure.bat} | 0 extdep/{ => compile}/qt_osx.patch | 0 extdep/{tools.bat => compile/qt_tools.bat} | 0 extdep/{ => compile}/snappy.cmake | 0 extdep/precompiled/json-rpc-cpp.cmake | 8 +++++ 17 files changed, 34 insertions(+), 16 deletions(-) rename extdep/{ => cmake}/FindCURL.cmake (100%) rename extdep/{ => compile}/argtable2.cmake (100%) rename extdep/{ => compile}/cryptopp.cmake (100%) rename extdep/{ => compile}/curl.cmake (100%) rename extdep/{ => compile}/icu.cmake (100%) rename extdep/{ => compile}/jom.cmake (100%) rename extdep/{ => compile}/json-rpc-cpp.cmake (86%) rename extdep/{ => compile}/jsoncpp.cmake (100%) rename extdep/{ => compile}/leveldb.cmake (91%) rename extdep/{ => compile}/leveldb_osx.patch (100%) rename extdep/{ => compile}/qt.cmake (84%) rename extdep/{configure.bat => compile/qt_configure.bat} (100%) rename extdep/{ => compile}/qt_osx.patch (100%) rename extdep/{tools.bat => compile/qt_tools.bat} (100%) rename extdep/{ => compile}/snappy.cmake (100%) create mode 100644 extdep/precompiled/json-rpc-cpp.cmake diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index 6c73d3719..7b906058a 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -5,20 +5,30 @@ include(ExternalProject) # all dependencies will be installed into this directory, separated by platform string(TOLOWER ${CMAKE_SYSTEM_NAME} _system_name) set(ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/install/${_system_name}") +set(ETH_DEPENDENCY_SERVER "http://poc-7.ethdev.com/precompiled/${_system_name}") file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/lib) file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/include) file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/bin) -include(icu.cmake) -include(jom.cmake) -include(qt.cmake) -include(curl.cmake) -include(jsoncpp.cmake) -include(argtable2.cmake) -include(json-rpc-cpp.cmake) -include(cryptopp.cmake) -include(snappy.cmake) -include(leveldb.cmake) +if (ETH_COMPILE) + # json-rpc-cpp and its dependencies + include(compile/jsoncpp.cmake) + include(compile/argtable2.cmake) + include(compile/curl.cmake) + include(compile/json-rpc-cpp.cmake) + + # qt at its dependencies + include(compile/icu.cmake) + include(compile/jom.cmake) + include(compile/qt.cmake) + + # leveldb and its dependencies + include(compile/snappy.cmake) + include(compile/leveldb.cmake) + +else() + include(precompiled/json-rpc-cpp.cmake) +endif() # will be re-eanbled later # include(miniupnpc.cmake) diff --git a/extdep/FindCURL.cmake b/extdep/cmake/FindCURL.cmake similarity index 100% rename from extdep/FindCURL.cmake rename to extdep/cmake/FindCURL.cmake diff --git a/extdep/argtable2.cmake b/extdep/compile/argtable2.cmake similarity index 100% rename from extdep/argtable2.cmake rename to extdep/compile/argtable2.cmake diff --git a/extdep/cryptopp.cmake b/extdep/compile/cryptopp.cmake similarity index 100% rename from extdep/cryptopp.cmake rename to extdep/compile/cryptopp.cmake diff --git a/extdep/curl.cmake b/extdep/compile/curl.cmake similarity index 100% rename from extdep/curl.cmake rename to extdep/compile/curl.cmake diff --git a/extdep/icu.cmake b/extdep/compile/icu.cmake similarity index 100% rename from extdep/icu.cmake rename to extdep/compile/icu.cmake diff --git a/extdep/jom.cmake b/extdep/compile/jom.cmake similarity index 100% rename from extdep/jom.cmake rename to extdep/compile/jom.cmake diff --git a/extdep/json-rpc-cpp.cmake b/extdep/compile/json-rpc-cpp.cmake similarity index 86% rename from extdep/json-rpc-cpp.cmake rename to extdep/compile/json-rpc-cpp.cmake index db336f1ac..b4f28a315 100644 --- a/extdep/json-rpc-cpp.cmake +++ b/extdep/compile/json-rpc-cpp.cmake @@ -9,7 +9,7 @@ ExternalProject_Add(json-rpc-cpp GIT_REPOSITORY https://github.com/cinemast/libjson-rpc-cpp.git GIT_TAG v0.3.2 BINARY_DIR json-rpc-cpp-prefix/src/json-rpc-cpp - CONFIGURE_COMMAND cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_MODULE_PATH:PATH=${CMAKE_CURRENT_SOURCE_DIR} -DETH_DEPENDENCY_INSTALL_DIR:PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST -Wno-dev . + CONFIGURE_COMMAND cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_MODULE_PATH:PATH=${CMAKE_CURRENT_SOURCE_DIR}/cmake -DETH_DEPENDENCY_INSTALL_DIR:PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST -Wno-dev . BUILD_COMMAND make -j 3 INSTALL_COMMAND make install ) @@ -31,7 +31,7 @@ ExternalProject_Add(json-rpc-cpp GIT_REPOSITORY https://github.com/cinemast/libjson-rpc-cpp.git GIT_TAG v0.3.2 BINARY_DIR json-rpc-cpp-prefix/src/json-rpc-cpp - CONFIGURE_COMMAND cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_MODULE_PATH:PATH=${CMAKE_CURRENT_SOURCE_DIR} -DETH_DEPENDENCY_INSTALL_DIR:PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST . + CONFIGURE_COMMAND cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_MODULE_PATH:PATH=${CMAKE_CURRENT_SOURCE_DIR}/cmake -DETH_DEPENDENCY_INSTALL_DIR:PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST . BUILD_COMMAND make -j 3 INSTALL_COMMAND make install ) diff --git a/extdep/jsoncpp.cmake b/extdep/compile/jsoncpp.cmake similarity index 100% rename from extdep/jsoncpp.cmake rename to extdep/compile/jsoncpp.cmake diff --git a/extdep/leveldb.cmake b/extdep/compile/leveldb.cmake similarity index 91% rename from extdep/leveldb.cmake rename to extdep/compile/leveldb.cmake index 5399b34b8..a22773d59 100644 --- a/extdep/leveldb.cmake +++ b/extdep/compile/leveldb.cmake @@ -3,7 +3,7 @@ ExternalProject_Add(leveldb DEPENDS snappy URL https://leveldb.googlecode.com/files/leveldb-1.15.0.tar.gz BINARY_DIR leveldb-prefix/src/leveldb - CONFIGURE_COMMAND patch < ${CMAKE_CURRENT_SOURCE_DIR}/leveldb_osx.patch + CONFIGURE_COMMAND patch < ${CMAKE_CURRENT_SOURCE_DIR}/compile/leveldb_osx.patch BUILD_COMMAND export ETH_DEPENDENCY_INSTALL_DIR=${ETH_DEPENDENCY_INSTALL_DIR} && make -j 3 INSTALL_COMMAND cp -rf include/leveldb ${ETH_DEPENDENCY_INSTALL_DIR}/include/ && cp libleveldb.a ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp libleveldb.dylib.1.15 ${ETH_DEPENDENCY_INSTALL_DIR}/lib/libleveldb.dylib ) diff --git a/extdep/leveldb_osx.patch b/extdep/compile/leveldb_osx.patch similarity index 100% rename from extdep/leveldb_osx.patch rename to extdep/compile/leveldb_osx.patch diff --git a/extdep/qt.cmake b/extdep/compile/qt.cmake similarity index 84% rename from extdep/qt.cmake rename to extdep/compile/qt.cmake index 42f4331ab..2ff0e1e5b 100644 --- a/extdep/qt.cmake +++ b/extdep/compile/qt.cmake @@ -2,7 +2,7 @@ if(APPLE) ExternalProject_add(qt URL http://qtmirror.ics.com/pub/qtproject/official_releases/qt/5.3/5.3.2/single/qt-everywhere-opensource-src-5.3.2.tar.gz BINARY_DIR qt-prefix/src/qt - PATCH_COMMAND patch -d qtmultimedia/src/plugins/avfoundation/mediaplayer < ${CMAKE_CURRENT_SOURCE_DIR}/qt_osx.patch + PATCH_COMMAND patch -d qtmultimedia/src/plugins/avfoundation/mediaplayer < ${CMAKE_CURRENT_SOURCE_DIR}/compile/qt_osx.patch CONFIGURE_COMMAND ./configure -prefix ${ETH_DEPENDENCY_INSTALL_DIR} -system-zlib -qt-libpng -qt-libjpeg -confirm-license -opensource -nomake tests -release -nomake examples -no-xcb -arch x86_64 BUILD_COMMAND make INSTALL_COMMAND make install @@ -12,8 +12,8 @@ ExternalProject_Add(qt DEPENDS icu jom URL http://download.qt-project.org/official_releases/qt/5.2/5.2.1/single/qt-everywhere-opensource-src-5.2.1.tar.gz BINARY_DIR qt-prefix/src/qt - UPDATE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/tools.bat - PATCH_COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/configure.bat qtbase + UPDATE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/compile/qt_tools.bat + PATCH_COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/compile/qt_configure.bat qtbase/configure.bat CONFIGURE_COMMAND configure -prefix ${ETH_DEPENDENCY_INSTALL_DIR} -opensource -confirm-license -release -opengl desktop -platform win32-msvc2013 -icu -I ${ETH_DEPENDENCY_INSTALL_DIR}/include -L ${ETH_DEPENDENCY_INSTALL_DIR}/lib -nomake tests -nomake examples BUILD_COMMAND nmake diff --git a/extdep/configure.bat b/extdep/compile/qt_configure.bat similarity index 100% rename from extdep/configure.bat rename to extdep/compile/qt_configure.bat diff --git a/extdep/qt_osx.patch b/extdep/compile/qt_osx.patch similarity index 100% rename from extdep/qt_osx.patch rename to extdep/compile/qt_osx.patch diff --git a/extdep/tools.bat b/extdep/compile/qt_tools.bat similarity index 100% rename from extdep/tools.bat rename to extdep/compile/qt_tools.bat diff --git a/extdep/snappy.cmake b/extdep/compile/snappy.cmake similarity index 100% rename from extdep/snappy.cmake rename to extdep/compile/snappy.cmake diff --git a/extdep/precompiled/json-rpc-cpp.cmake b/extdep/precompiled/json-rpc-cpp.cmake new file mode 100644 index 000000000..ef60eb54f --- /dev/null +++ b/extdep/precompiled/json-rpc-cpp.cmake @@ -0,0 +1,8 @@ +ExternalProject_Add(json-rpc-cpp + URL ${ETH_DEPENDENCY_SERVER}/json-rpc-cpp.tar.gz + BINARY_DIR json-rpc-cpp-prefix/src/json-rpc-cpp + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND cmake -E copy_directory . ${ETH_DEPENDENCY_INSTALL_DIR} + ) + From 674b73dff757e751d653a256786b1515b017697b Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 3 Dec 2014 16:15:33 +0100 Subject: [PATCH 394/641] handling symlinks --- extdep/CMakeLists.txt | 10 ++++-- extdep/eth_download.cmake | 44 +++++++++++++++++++++++++++ extdep/precompiled/json-rpc-cpp.cmake | 8 ----- 3 files changed, 52 insertions(+), 10 deletions(-) create mode 100644 extdep/eth_download.cmake delete mode 100644 extdep/precompiled/json-rpc-cpp.cmake diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index 7b906058a..54412e6a6 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -1,6 +1,7 @@ cmake_minimum_required(VERSION 2.8) include(ExternalProject) +include(eth_download.cmake) # all dependencies will be installed into this directory, separated by platform string(TOLOWER ${CMAKE_SYSTEM_NAME} _system_name) @@ -26,12 +27,17 @@ if (ETH_COMPILE) include(compile/snappy.cmake) include(compile/leveldb.cmake) + # cryptopp + include(compile/cryptopp.cmake) else() - include(precompiled/json-rpc-cpp.cmake) + eth_download("json-rpc-cpp") + eth_download("qt") + eth_download("cryptopp") + #include(compile/snappy.cmake) + eth_download("leveldb") endif() # will be re-eanbled later # include(miniupnpc.cmake) - # if install phase of extep fails, even if libs are already created, the ethereum install will fail diff --git a/extdep/eth_download.cmake b/extdep/eth_download.cmake new file mode 100644 index 000000000..dafd065b7 --- /dev/null +++ b/extdep/eth_download.cmake @@ -0,0 +1,44 @@ +# this macro requires the following variables to be specified: +# +# ETH_DEPENDENCY_SERVER - server from which dependencies should be downloaded +# ETH_DEPENDENCY_INSTALL_DIR - install location for all dependencies +# +# usage: +# +# eth_download("json-rpc-cpp") +# eth_download("json-rpc-cpp" "0.3.2") +# +# TODO: +# check if install_command is handling symlinks correctly on linux and windows + +macro(eth_download eth_package_name) + + set (extra_macro_args ${ARGN}) + if (extra_macro_args GREATER 0) + set(eth_tar_name "${eth_package_name}-${ARGV1}.tar.gz") + else() + set(eth_tar_name "${eth_package_name}.tar.gz") + endif() + + message(STATUS "download path for ${eth_package_name} is : ${ETH_DEPENDENCY_SERVER}/${eth_tar_name}.tar.gz") + + # we need that to copy symlinks + # see http://superuser.com/questions/138587/how-to-copy-symbolic-links + if (APPLE) + set (eth_package_install cp -a . ${ETH_DEPENDENCY_INSTALL_DIR}) + elseif (UNIX) + set (eth_package_install cp -a . ${ETH_DEPENDENCY_INSTALL_DIR}) + else () + set (eth_package_install cmake -E copy_directory . ${ETH_DEPENDENCY_INSTALL_DIR}) + endif() + + + ExternalProject_Add(${eth_package_name} + URL ${ETH_DEPENDENCY_SERVER}/${eth_tar_name} + BINARY_DIR ${eth_package_name}-prefix/src/${eth_package_name} + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND ${eth_package_install} + ) +endmacro() + diff --git a/extdep/precompiled/json-rpc-cpp.cmake b/extdep/precompiled/json-rpc-cpp.cmake deleted file mode 100644 index ef60eb54f..000000000 --- a/extdep/precompiled/json-rpc-cpp.cmake +++ /dev/null @@ -1,8 +0,0 @@ -ExternalProject_Add(json-rpc-cpp - URL ${ETH_DEPENDENCY_SERVER}/json-rpc-cpp.tar.gz - BINARY_DIR json-rpc-cpp-prefix/src/json-rpc-cpp - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND cmake -E copy_directory . ${ETH_DEPENDENCY_INSTALL_DIR} - ) - From 1ff8b68e91244417899ec2f4df9bbb0fd1e5323b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 3 Dec 2014 16:50:00 +0100 Subject: [PATCH 395/641] Add evmjit submodule --- .gitmodules | 4 ++++ evmjit | 1 + 2 files changed, 5 insertions(+) create mode 100644 .gitmodules create mode 160000 evmjit diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..d7fb4f437 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "evmjit"] + path = evmjit + url = ../evmjit + branch = develop diff --git a/evmjit b/evmjit new file mode 160000 index 000000000..49b82cdba --- /dev/null +++ b/evmjit @@ -0,0 +1 @@ +Subproject commit 49b82cdbac09c3c2058e0b4326645e5da37f7133 From f9a56e06182dabe9bab8a344069ea9817dc40cd4 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 3 Dec 2014 21:52:01 +0100 Subject: [PATCH 396/641] improved eth_download.cmake --- cmake/EthDependencies.cmake | 3 +++ extdep/CMakeLists.txt | 14 +++++++++----- extdep/compile/leveldb.cmake | 5 +++-- extdep/eth_download.cmake | 33 +++++++++++++++++++++++++-------- 4 files changed, 40 insertions(+), 15 deletions(-) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 7b938ae5f..bf7ff487a 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -6,6 +6,9 @@ string(TOLOWER ${CMAKE_SYSTEM_NAME} _system_name) set (CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}/extdep/install/${_system_name}") +# mac os +# https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/UsingDynamicLibraries.html +set(ENV{DYLD_FALLBACK_LIBRARY_PATH} ${CMAKE_PREFIX_PATH}/lib) # Dependencies must have a version number, to ensure reproducible build. The version provided here is the one that is in the extdep repository. If you use system libraries, version numbers may be different. diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index 54412e6a6..642e10eee 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -1,6 +1,7 @@ cmake_minimum_required(VERSION 2.8) include(ExternalProject) +include(CMakeParseArguments) include(eth_download.cmake) # all dependencies will be installed into this directory, separated by platform @@ -30,11 +31,14 @@ if (ETH_COMPILE) # cryptopp include(compile/cryptopp.cmake) else() - eth_download("json-rpc-cpp") - eth_download("qt") - eth_download("cryptopp") - #include(compile/snappy.cmake) - eth_download("leveldb") + eth_download(json-rpc-cpp VERSION 0.3.2) + eth_download(qt) + eth_download(cryptopp) + eth_download(snappy) + eth_download(leveldb) + + #include(compile/leveldb.cmake) + #eth_download("leveldb") endif() # will be re-eanbled later diff --git a/extdep/compile/leveldb.cmake b/extdep/compile/leveldb.cmake index a22773d59..9774c8c57 100644 --- a/extdep/compile/leveldb.cmake +++ b/extdep/compile/leveldb.cmake @@ -1,9 +1,10 @@ if (APPLE) ExternalProject_Add(leveldb - DEPENDS snappy + #DEPENDS snappy URL https://leveldb.googlecode.com/files/leveldb-1.15.0.tar.gz BINARY_DIR leveldb-prefix/src/leveldb - CONFIGURE_COMMAND patch < ${CMAKE_CURRENT_SOURCE_DIR}/compile/leveldb_osx.patch + #CONFIGURE_COMMAND patch < ${CMAKE_CURRENT_SOURCE_DIR}/compile/leveldb_osx.patch + CONFIGURE_COMMAND "" BUILD_COMMAND export ETH_DEPENDENCY_INSTALL_DIR=${ETH_DEPENDENCY_INSTALL_DIR} && make -j 3 INSTALL_COMMAND cp -rf include/leveldb ${ETH_DEPENDENCY_INSTALL_DIR}/include/ && cp libleveldb.a ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp libleveldb.dylib.1.15 ${ETH_DEPENDENCY_INSTALL_DIR}/lib/libleveldb.dylib ) diff --git a/extdep/eth_download.cmake b/extdep/eth_download.cmake index dafd065b7..1567eafaa 100644 --- a/extdep/eth_download.cmake +++ b/extdep/eth_download.cmake @@ -6,7 +6,13 @@ # usage: # # eth_download("json-rpc-cpp") -# eth_download("json-rpc-cpp" "0.3.2") +# eth_download("json-rpc-cpp" VERSION "0.3.2") +# +# parsing arguments +# http://www.cmake.org/cmake/help/v3.0/module/CMakeParseArguments.html +# +# for macos you may need to specify OSX_SCRIPT with install_name_tool to fix dylib +# http://stackoverflow.com/questions/2985315/using-install-name-tool-whats-going-wrong # # TODO: # check if install_command is handling symlinks correctly on linux and windows @@ -14,30 +20,41 @@ macro(eth_download eth_package_name) set (extra_macro_args ${ARGN}) - if (extra_macro_args GREATER 0) - set(eth_tar_name "${eth_package_name}-${ARGV1}.tar.gz") + set (options) + set (one_value_args VERSION OSX_SCRIPT UNIX_SCRIPT WIN_SCRIPT) + set (multi_value_args) + cmake_parse_arguments (ETH_DOWNLOAD "${options}" "${one_value_args}" "${multi_value_args}" ${extra_macro_args}) + + if (ETH_DOWNLOAD_VERSION) + set(eth_tar_name "${eth_package_name}-${ETH_DOWNLOAD_VERSION}.tar.gz") else() set(eth_tar_name "${eth_package_name}.tar.gz") endif() - message(STATUS "download path for ${eth_package_name} is : ${ETH_DEPENDENCY_SERVER}/${eth_tar_name}.tar.gz") + message(STATUS "download path for ${eth_package_name} is : ${ETH_DEPENDENCY_SERVER}/${eth_tar_name}") # we need that to copy symlinks # see http://superuser.com/questions/138587/how-to-copy-symbolic-links if (APPLE) - set (eth_package_install cp -a . ${ETH_DEPENDENCY_INSTALL_DIR}) + set (eth_package_copy cp -a . ${ETH_DEPENDENCY_INSTALL_DIR}) + set (eth_package_install ${ETH_DOWNLOAD_OSX_SCRIPT}) elseif (UNIX) - set (eth_package_install cp -a . ${ETH_DEPENDENCY_INSTALL_DIR}) + set (eth_package_copy cp -a . ${ETH_DEPENDENCY_INSTALL_DIR}) + set (eth_package_install ${ETH_DOWNLOAD_UNIX_SCRIPT}) else () - set (eth_package_install cmake -E copy_directory . ${ETH_DEPENDENCY_INSTALL_DIR}) + set (eth_package_copy cmake -E copy_directory . ${ETH_DEPENDENCY_INSTALL_DIR}) + set (eth_package_install ${ETH_DOWNLOAD_WIN_SCRIPT}) endif() + if (eth_package_install) + message(STATUS "install script is at: ${eth_package_install}") + endif() ExternalProject_Add(${eth_package_name} URL ${ETH_DEPENDENCY_SERVER}/${eth_tar_name} BINARY_DIR ${eth_package_name}-prefix/src/${eth_package_name} CONFIGURE_COMMAND "" - BUILD_COMMAND "" + BUILD_COMMAND ${eth_package_copy} INSTALL_COMMAND ${eth_package_install} ) endmacro() From 8c03370649c788b1491d6d8e758d39caf3d239e2 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 3 Dec 2014 22:40:32 +0100 Subject: [PATCH 397/641] fixing precompiled dylibs in progress --- extdep/CMakeLists.txt | 3 ++- extdep/eth_download.cmake | 4 +++- extdep/scripts/snappy_osx.sh | 8 ++++++++ 3 files changed, 13 insertions(+), 2 deletions(-) create mode 100755 extdep/scripts/snappy_osx.sh diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index 642e10eee..8f38cd1bf 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -34,7 +34,8 @@ else() eth_download(json-rpc-cpp VERSION 0.3.2) eth_download(qt) eth_download(cryptopp) - eth_download(snappy) + eth_download(snappy + OSX_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/scripts/snappy_osx.sh) eth_download(leveldb) #include(compile/leveldb.cmake) diff --git a/extdep/eth_download.cmake b/extdep/eth_download.cmake index 1567eafaa..0b4d6b6fb 100644 --- a/extdep/eth_download.cmake +++ b/extdep/eth_download.cmake @@ -48,6 +48,8 @@ macro(eth_download eth_package_name) if (eth_package_install) message(STATUS "install script is at: ${eth_package_install}") + else () + set (eth_package_install echo 0) # cause empty string is not handled properly endif() ExternalProject_Add(${eth_package_name} @@ -55,7 +57,7 @@ macro(eth_download eth_package_name) BINARY_DIR ${eth_package_name}-prefix/src/${eth_package_name} CONFIGURE_COMMAND "" BUILD_COMMAND ${eth_package_copy} - INSTALL_COMMAND ${eth_package_install} + INSTALL_COMMAND ${eth_package_install} . ${ETH_DEPENDENCY_INSTALL_DIR} ) endmacro() diff --git a/extdep/scripts/snappy_osx.sh b/extdep/scripts/snappy_osx.sh new file mode 100755 index 000000000..01304fcf1 --- /dev/null +++ b/extdep/scripts/snappy_osx.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +ETH_DEPENDENCY_SOURCE_DIR=$1 +ETH_DEPENDENCY_INSTALL_DIR=$2 + +SNAPPY_DYLIB=${ETH_DEPENDENCY_INSTALL_DIR}/lib/libsnappy.dylib +install_name_tool -id ${SNAPPY_DYLIB} ${SNAPPY_DYLIB} + From aafd5c8d9a22b324483cee79b073be7657378f8a Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 3 Dec 2014 23:10:46 +0100 Subject: [PATCH 398/641] leveldb precompiled dylib is working! --- extdep/CMakeLists.txt | 3 ++- extdep/eth_download.cmake | 15 +++++++++++++-- extdep/scripts/leveldb_osx.sh | 12 ++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) create mode 100755 extdep/scripts/leveldb_osx.sh diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index 8f38cd1bf..582d8a2f2 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -36,7 +36,8 @@ else() eth_download(cryptopp) eth_download(snappy OSX_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/scripts/snappy_osx.sh) - eth_download(leveldb) + eth_download(leveldb + OSX_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/scripts/leveldb_osx.sh) #include(compile/leveldb.cmake) #eth_download("leveldb") diff --git a/extdep/eth_download.cmake b/extdep/eth_download.cmake index 0b4d6b6fb..96d6c5122 100644 --- a/extdep/eth_download.cmake +++ b/extdep/eth_download.cmake @@ -8,6 +8,16 @@ # eth_download("json-rpc-cpp") # eth_download("json-rpc-cpp" VERSION "0.3.2") # +# params: +# VERSION - exact version we want to use +# OSX_SCRIPT - script which will be executed on apple in install phase +# UNIX_SCRIPT - script which will be executed on unix in install phase +# WIN_SCRIPT - script which will be executed on win in install phase + +# OSX_SCRIPT, WIN_SCRIPT, UNIX_SCRIPT are taking 2 params: +# $1 is package_source, +# $2 is ETH_DEPENDENCY_INSTALL_DIR +# # parsing arguments # http://www.cmake.org/cmake/help/v3.0/module/CMakeParseArguments.html # @@ -47,7 +57,8 @@ macro(eth_download eth_package_name) endif() if (eth_package_install) - message(STATUS "install script is at: ${eth_package_install}") + message(STATUS "install script: ${eth_package_install}") + set (eth_package_install ${eth_package_install} . ${ETH_DEPENDENCY_INSTALL_DIR}) else () set (eth_package_install echo 0) # cause empty string is not handled properly endif() @@ -57,7 +68,7 @@ macro(eth_download eth_package_name) BINARY_DIR ${eth_package_name}-prefix/src/${eth_package_name} CONFIGURE_COMMAND "" BUILD_COMMAND ${eth_package_copy} - INSTALL_COMMAND ${eth_package_install} . ${ETH_DEPENDENCY_INSTALL_DIR} + INSTALL_COMMAND ${eth_package_install} ) endmacro() diff --git a/extdep/scripts/leveldb_osx.sh b/extdep/scripts/leveldb_osx.sh new file mode 100755 index 000000000..06b4a2dbd --- /dev/null +++ b/extdep/scripts/leveldb_osx.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +ETH_DEPENDENCY_SOURCE_DIR=$1 +ETH_DEPENDENCY_INSTALL_DIR=$2 + +OLD_SNAPPY_DYLIB="/Users/marekkotewicz/ethereum/cpp-ethereum/extdep/install/darwin/lib/libsnappy.1.dylib" +SNAPPY_DYLIB=${ETH_DEPENDENCY_INSTALL_DIR}/lib/libsnappy.dylib +LEVELDB_DYLIB=${ETH_DEPENDENCY_INSTALL_DIR}/lib/libleveldb.dylib + +install_name_tool -id ${LEVELDB_DYLIB} ${LEVELDB_DYLIB} +install_name_tool -change ${OLD_SNAPPY_DYLIB} ${SNAPPY_DYLIB} ${LEVELDB_DYLIB} + From 895a70271d6489a0e1673c2c7f3ab3db435fd6a6 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 4 Dec 2014 00:30:05 +0100 Subject: [PATCH 399/641] fixed json-rpc-cpp install step --- extdep/CMakeLists.txt | 8 +++----- extdep/compile/json-rpc-cpp.cmake | 2 +- extdep/scripts/json-rpc-cpp_osx.sh | 29 +++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 6 deletions(-) create mode 100755 extdep/scripts/json-rpc-cpp_osx.sh diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index 582d8a2f2..274f9755b 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -31,13 +31,11 @@ if (ETH_COMPILE) # cryptopp include(compile/cryptopp.cmake) else() - eth_download(json-rpc-cpp VERSION 0.3.2) + eth_download(json-rpc-cpp OSX_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/scripts/json-rpc-cpp_osx.sh) + eth_download(snappy OSX_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/scripts/snappy_osx.sh) + eth_download(leveldb OSX_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/scripts/leveldb_osx.sh) eth_download(qt) eth_download(cryptopp) - eth_download(snappy - OSX_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/scripts/snappy_osx.sh) - eth_download(leveldb - OSX_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/scripts/leveldb_osx.sh) #include(compile/leveldb.cmake) #eth_download("leveldb") diff --git a/extdep/compile/json-rpc-cpp.cmake b/extdep/compile/json-rpc-cpp.cmake index b4f28a315..cb2985e58 100644 --- a/extdep/compile/json-rpc-cpp.cmake +++ b/extdep/compile/json-rpc-cpp.cmake @@ -11,7 +11,7 @@ ExternalProject_Add(json-rpc-cpp BINARY_DIR json-rpc-cpp-prefix/src/json-rpc-cpp CONFIGURE_COMMAND cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_MODULE_PATH:PATH=${CMAKE_CURRENT_SOURCE_DIR}/cmake -DETH_DEPENDENCY_INSTALL_DIR:PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST -Wno-dev . BUILD_COMMAND make -j 3 - INSTALL_COMMAND make install + INSTALL_COMMAND make install && ${CMAKE_CURRENT_SOURCE_DIR}/scripts/json-rpc-cpp_osx.sh . ${ETH_DEPENDENCY_INSTALL_DIR} ) elseif(WIN32) diff --git a/extdep/scripts/json-rpc-cpp_osx.sh b/extdep/scripts/json-rpc-cpp_osx.sh new file mode 100755 index 000000000..8a6b96c7b --- /dev/null +++ b/extdep/scripts/json-rpc-cpp_osx.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +ETH_DEPENDENCY_SOURCE_DIR=$1 +ETH_DEPENDENCY_INSTALL_DIR=$2 + +OLD_COMMON_DYLIB="libjsonrpccpp-common.0.dylib" + +COMMON_DYLIB=${ETH_DEPENDENCY_INSTALL_DIR}/lib/libjsonrpccpp-common.0.dylib +SERVER_DYLIB=${ETH_DEPENDENCY_INSTALL_DIR}/lib/libjsonrpccpp-server.0.dylib +CLIENT_DYLIB=${ETH_DEPENDENCY_INSTALL_DIR}/lib/libjsonrpccpp-client.0.dylib + +# fix bin +STAB_EXEC=${ETH_DEPENDENCY_INSTALL_DIR}/bin/jsonrpcstub +install_name_tool -change ${OLD_COMMON_DYLIB} ${COMMON_DYLIB} ${STAB_EXEC} + +# fix common +install_name_tool -id ${COMMON_DYLIB} ${COMMON_DYLIB} + +# fix server +install_name_tool -id ${SERVER_DYLIB} ${SERVER_DYLIB} +install_name_tool -change ${OLD_COMMON_DYLIB} ${COMMON_DYLIB} ${SERVER_DYLIB} + +# fix client +install_name_tool -id ${CLIENT_DYLIB} ${CLIENT_DYLIB} +install_name_tool -change ${OLD_COMMON_DYLIB} ${COMMON_DYLIB} ${CLIENT_DYLIB} + +# TODO fix argtable and jsoncpp once they are downloaded as dependencies + + From be820a55fc152b1c42260a1253220349b66e0b22 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 4 Dec 2014 00:47:37 +0100 Subject: [PATCH 400/641] fixed merge bug --- libethereum/Client.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index fcb47474f..d130194cc 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -634,7 +634,6 @@ LogEntries Client::logs(LogFilter const& _f) const } #if ETH_DEBUG else -#if ETH_DEBUG skipped++; #endif if (n == end) From 6b5d89d55907206ad8c8c8d58afbc76649fe38b5 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 4 Dec 2014 09:55:54 +0100 Subject: [PATCH 401/641] removed automocs --- alethzero/CMakeLists.txt | 3 +-- eth/CMakeLists.txt | 2 +- libevmcore/CMakeLists.txt | 1 + liblll/CMakeLists.txt | 1 + libp2p/CMakeLists.txt | 1 + libserpent/CMakeLists.txt | 1 + libsolidity/CMakeLists.txt | 1 + libwebthree/CMakeLists.txt | 1 + libwhisper/CMakeLists.txt | 1 + lllc/CMakeLists.txt | 1 + sc/CMakeLists.txt | 1 - secp256k1/CMakeLists.txt | 1 + solc/CMakeLists.txt | 1 + 13 files changed, 12 insertions(+), 4 deletions(-) diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index 5b3704c14..5b6c5c3c4 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -1,5 +1,4 @@ -#cmake_policy(SET CMP0015 OLD) -#set(CMAKE_AUTOMOC OFF) +cmake_policy(SET CMP0015 NEW) set(CMAKE_INCLUDE_CURRENT_DIR ON) aux_source_directory(. SRC_LIST) diff --git a/eth/CMakeLists.txt b/eth/CMakeLists.txt index 5ccac182b..2b88efbc2 100644 --- a/eth/CMakeLists.txt +++ b/eth/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_policy(SET CMP0015 OLD) +cmake_policy(SET CMP0015 NEW) set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) diff --git a/libevmcore/CMakeLists.txt b/libevmcore/CMakeLists.txt index 738303271..b889e7163 100644 --- a/libevmcore/CMakeLists.txt +++ b/libevmcore/CMakeLists.txt @@ -1,4 +1,5 @@ cmake_policy(SET CMP0015 NEW) +set(CMAKE_AUTOMOC OFF) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") diff --git a/liblll/CMakeLists.txt b/liblll/CMakeLists.txt index 8b1581785..4e6941359 100644 --- a/liblll/CMakeLists.txt +++ b/liblll/CMakeLists.txt @@ -1,4 +1,5 @@ cmake_policy(SET CMP0015 NEW) +set(CMAKE_AUTOMOC OFF) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") diff --git a/libp2p/CMakeLists.txt b/libp2p/CMakeLists.txt index 207d10127..bae400caf 100644 --- a/libp2p/CMakeLists.txt +++ b/libp2p/CMakeLists.txt @@ -1,4 +1,5 @@ cmake_policy(SET CMP0015 NEW) +set(CMAKE_AUTOMOC OFF) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") diff --git a/libserpent/CMakeLists.txt b/libserpent/CMakeLists.txt index 06f5dc93b..315970a7a 100644 --- a/libserpent/CMakeLists.txt +++ b/libserpent/CMakeLists.txt @@ -1,4 +1,5 @@ cmake_policy(SET CMP0015 NEW) +set(CMAKE_AUTOMOC OFF) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index ea2ef4b74..260493b0e 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -1,4 +1,5 @@ cmake_policy(SET CMP0015 NEW) +set(CMAKE_AUTOMOC OFF) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") diff --git a/libwebthree/CMakeLists.txt b/libwebthree/CMakeLists.txt index 4ec5b2ea4..dc623a2fa 100644 --- a/libwebthree/CMakeLists.txt +++ b/libwebthree/CMakeLists.txt @@ -1,4 +1,5 @@ cmake_policy(SET CMP0015 NEW) +set(CMAKE_AUTOMOC OFF) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") diff --git a/libwhisper/CMakeLists.txt b/libwhisper/CMakeLists.txt index 62bc5edaf..080c24c05 100644 --- a/libwhisper/CMakeLists.txt +++ b/libwhisper/CMakeLists.txt @@ -1,4 +1,5 @@ cmake_policy(SET CMP0015 NEW) +set(CMAKE_AUTOMOC OFF) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") diff --git a/lllc/CMakeLists.txt b/lllc/CMakeLists.txt index a9b53c74c..3310354fb 100644 --- a/lllc/CMakeLists.txt +++ b/lllc/CMakeLists.txt @@ -1,4 +1,5 @@ cmake_policy(SET CMP0015 NEW) +set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) diff --git a/sc/CMakeLists.txt b/sc/CMakeLists.txt index 9aa23b03b..d977ee967 100644 --- a/sc/CMakeLists.txt +++ b/sc/CMakeLists.txt @@ -31,4 +31,3 @@ endif () install( TARGETS ${EXECUTABLE} DESTINATION bin ) -cmake_policy(SET CMP0015 NEW) diff --git a/secp256k1/CMakeLists.txt b/secp256k1/CMakeLists.txt index 9b017f15f..cdfadb265 100644 --- a/secp256k1/CMakeLists.txt +++ b/secp256k1/CMakeLists.txt @@ -1,4 +1,5 @@ cmake_policy(SET CMP0015 NEW) +set(CMAKE_AUTOMOC OFF) set(CMAKE_ASM_COMPILER "yasm") diff --git a/solc/CMakeLists.txt b/solc/CMakeLists.txt index 386d4a1a8..ab402ed8e 100644 --- a/solc/CMakeLists.txt +++ b/solc/CMakeLists.txt @@ -1,4 +1,5 @@ cmake_policy(SET CMP0015 NEW) +set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) From 8ab7030ebc86a2444eadcb7a8734014ce1acd8bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zaw=C5=82ocki?= Date: Thu, 4 Dec 2014 12:43:10 +0100 Subject: [PATCH 402/641] added some more VM performance tests --- .../test/vmtests/vmArithPerformanceTest.json | 260 ++++++++++++++++++ 1 file changed, 260 insertions(+) create mode 100644 evmcc/test/vmtests/vmArithPerformanceTest.json diff --git a/evmcc/test/vmtests/vmArithPerformanceTest.json b/evmcc/test/vmtests/vmArithPerformanceTest.json new file mode 100644 index 000000000..d9017517f --- /dev/null +++ b/evmcc/test/vmtests/vmArithPerformanceTest.json @@ -0,0 +1,260 @@ +{ + "arith-1" : { + "callcreates" : [ ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "10000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "code" : "0x600a60005260005160105760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600556", + "data" : "0x", + "gas" : "1000000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "999538", + "out" : "0x0000000000000000000000000000000000000000000000000000001b9c636491", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600a60005260005160105760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600556", + "nonce" : "0", + "storage" : { + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600a60005260005160105760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600556", + "nonce" : "0", + "storage" : { } + } + } + } + + , + + "arith-2" : { + "callcreates" : [ ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "10000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "code" : "0x606460005260005160105760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600556", + "data" : "0x", + "gas" : "1000000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "995488", + "out" : "0x0000000000000000000000000000000000000000000000000000001b9c636491", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x606460005260005160105760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600556", + "nonce" : "0", + "storage" : { + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x606460005260005160105760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600556", + "nonce" : "0", + "storage" : { } + } + } + } + + , + + "arith-3" : { + "callcreates" : [ ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "10000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "code" : "0x6103e860005260005160115760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600656", + "data" : "0x", + "gas" : "1000000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "954988", + "out" : "0x0000000000000000000000000000000000000000000000000000001b9c636491", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x6103e860005260005160115760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600656", + "nonce" : "0", + "storage" : { + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x6103e860005260005160115760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600656", + "nonce" : "0", + "storage" : { } + } + } + } + + , + + "arith-4" : { + "callcreates" : [ ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "10000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "code" : "0x61271060005260005160115760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600656", + "data" : "0x", + "gas" : "1000000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "549988", + "out" : "0x0000000000000000000000000000000000000000000000000000001b9c636491", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x61271060005260005160115760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600656", + "nonce" : "0", + "storage" : { + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x61271060005260005160115760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600656", + "nonce" : "0", + "storage" : { } + } + } + } + + + , + + + "arith-5" : { + "callcreates" : [ ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "10000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "code" : "0x620186a060005260005160125760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600756", + "data" : "0x", + "gas" : "10000000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "5499988", + "out" : "0x0000000000000000000000000000000000000000000000000000001b9c636491", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x620186a060005260005160125760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600756", + "nonce" : "0", + "storage" : { + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x620186a060005260005160125760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600756", + "nonce" : "0", + "storage" : { } + } + } + } + +, + + "arith-6" : { + "callcreates" : [ ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "100000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "code" : "0x620f424060005260005160125760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600756", + "data" : "0x", + "gas" : "100000000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "54999988", + "out" : "0x0000000000000000000000000000000000000000000000000000001b9c636491", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x620f424060005260005160125760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600756", + "nonce" : "0", + "storage" : { + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x620f424060005260005160125760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600756", + "nonce" : "0", + "storage" : { } + } + } + } + +} From e087c5afcfbe7a997b34e6096cca0540d89056d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 4 Dec 2014 16:55:04 +0100 Subject: [PATCH 403/641] Windows configuration for evmjit submodule --- evmjit | 2 +- windows/Eth.vcxproj | 4 +- windows/Ethereum.sln | 19 +++- windows/LibEvmJit.vcxproj | 70 +++++++------ windows/LibEvmJit.vcxproj.filters | 123 +++++++---------------- windows/LibEvmJitCpp.vcxproj | 143 +++++++++++++++++++++++++++ windows/LibEvmJitCpp.vcxproj.filters | 13 +++ windows/TestEthereum.vcxproj | 9 +- windows/evmcc.vcxproj | 4 +- 9 files changed, 252 insertions(+), 135 deletions(-) create mode 100644 windows/LibEvmJitCpp.vcxproj create mode 100644 windows/LibEvmJitCpp.vcxproj.filters diff --git a/evmjit b/evmjit index 49b82cdba..6f84f3d1a 160000 --- a/evmjit +++ b/evmjit @@ -1 +1 @@ -Subproject commit 49b82cdbac09c3c2058e0b4326645e5da37f7133 +Subproject commit 6f84f3d1ade42bcacc99533d4807b9b759a5938b diff --git a/windows/Eth.vcxproj b/windows/Eth.vcxproj index d67d964f8..6736e0f12 100644 --- a/windows/Eth.vcxproj +++ b/windows/Eth.vcxproj @@ -155,8 +155,8 @@ {826e68cb-d3ee-4a8a-b540-59a8c3f38d4f} - - {9c816740-5c11-4377-a3a7-46be12f35fa0} + + {a5d8764c-fd17-4364-afcf-5baf78777569} diff --git a/windows/Ethereum.sln b/windows/Ethereum.sln index 4d2c7a3b4..ba804b16c 100644 --- a/windows/Ethereum.sln +++ b/windows/Ethereum.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Express 2013 for Windows Desktop -VisualStudioVersion = 12.0.30723.0 +# Visual Studio 2013 +VisualStudioVersion = 12.0.31101.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libs", "Libs", "{988F2383-FA1D-408B-BCF6-C0EE7AB0A560}" EndProject @@ -47,6 +47,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "evmcc", "evmcc.vcxproj", "{ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibEvmJit", "LibEvmJit.vcxproj", "{9C816740-5C11-4377-A3A7-46BE12F35FA0}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibEvmJitCpp", "LibEvmJitCpp.vcxproj", "{A5D8764C-FD17-4364-AFCF-5BAF78777569}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Mixed Platforms = Debug|Mixed Platforms @@ -257,6 +259,18 @@ Global {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|Win32.Build.0 = Release|Win32 {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|x64.ActiveCfg = Release|x64 {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|x64.Build.0 = Release|x64 + {A5D8764C-FD17-4364-AFCF-5BAF78777569}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {A5D8764C-FD17-4364-AFCF-5BAF78777569}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {A5D8764C-FD17-4364-AFCF-5BAF78777569}.Debug|Win32.ActiveCfg = Debug|Win32 + {A5D8764C-FD17-4364-AFCF-5BAF78777569}.Debug|Win32.Build.0 = Debug|Win32 + {A5D8764C-FD17-4364-AFCF-5BAF78777569}.Debug|x64.ActiveCfg = Debug|x64 + {A5D8764C-FD17-4364-AFCF-5BAF78777569}.Debug|x64.Build.0 = Debug|x64 + {A5D8764C-FD17-4364-AFCF-5BAF78777569}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {A5D8764C-FD17-4364-AFCF-5BAF78777569}.Release|Mixed Platforms.Build.0 = Release|Win32 + {A5D8764C-FD17-4364-AFCF-5BAF78777569}.Release|Win32.ActiveCfg = Release|Win32 + {A5D8764C-FD17-4364-AFCF-5BAF78777569}.Release|Win32.Build.0 = Release|Win32 + {A5D8764C-FD17-4364-AFCF-5BAF78777569}.Release|x64.ActiveCfg = Release|x64 + {A5D8764C-FD17-4364-AFCF-5BAF78777569}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -272,5 +286,6 @@ Global {DF3C5B07-A1A2-4F16-B37F-A27333622CDD} = {988F2383-FA1D-408B-BCF6-C0EE7AB0A560} {F174E81A-2A66-4693-B917-11BB42D3658C} = {988F2383-FA1D-408B-BCF6-C0EE7AB0A560} {9C816740-5C11-4377-A3A7-46BE12F35FA0} = {988F2383-FA1D-408B-BCF6-C0EE7AB0A560} + {A5D8764C-FD17-4364-AFCF-5BAF78777569} = {988F2383-FA1D-408B-BCF6-C0EE7AB0A560} EndGlobalSection EndGlobal diff --git a/windows/LibEvmJit.vcxproj b/windows/LibEvmJit.vcxproj index 50824fb2d..077757aab 100644 --- a/windows/LibEvmJit.vcxproj +++ b/windows/LibEvmJit.vcxproj @@ -123,42 +123,48 @@ - - - - - - - - - - - - - - - + + {826e68cb-d3ee-4a8a-b540-59a8c3f38d4f} + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - {826e68cb-d3ee-4a8a-b540-59a8c3f38d4f} - + + + + + + + + + + + + + + + + + + + + diff --git a/windows/LibEvmJit.vcxproj.filters b/windows/LibEvmJit.vcxproj.filters index 1a0d86e56..06f1ed308 100644 --- a/windows/LibEvmJit.vcxproj.filters +++ b/windows/LibEvmJit.vcxproj.filters @@ -1,99 +1,42 @@  - - {9bb7d84d-6d6c-48af-a954-60049208b2f1} - + + + + + + + + + + + + + + + - - libevmjit - - - libevmjit - - - libevmjit - - - libevmjit - - - libevmjit - - - libevmjit - - - libevmjit - - - libevmjit - - - libevmjit - - - libevmjit - - - libevmjit - - - libevmjit - - - libevmjit - - - libevmjit - - - libevmjit - + + + + + + + + + + + + + + + + + - - libevmjit - - - libevmjit - - - libevmjit - - - libevmjit - - - libevmjit - - - libevmjit - - - libevmjit - - - libevmjit - - - libevmjit - - - libevmjit - - - libevmjit - - - libevmjit - - - libevmjit - - - libevmjit - + \ No newline at end of file diff --git a/windows/LibEvmJitCpp.vcxproj b/windows/LibEvmJitCpp.vcxproj new file mode 100644 index 000000000..a5094e49c --- /dev/null +++ b/windows/LibEvmJitCpp.vcxproj @@ -0,0 +1,143 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {A5D8764C-FD17-4364-AFCF-5BAF78777569} + LibEvmJitCpp + + + + StaticLibrary + true + v120 + + + StaticLibrary + true + v120 + + + StaticLibrary + false + v120 + true + + + StaticLibrary + false + v120 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + + + true + + + + + Level3 + Disabled + true + + + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + true + + + + + + + + + + + + + + + {9c816740-5c11-4377-a3a7-46be12f35fa0} + + + + + + \ No newline at end of file diff --git a/windows/LibEvmJitCpp.vcxproj.filters b/windows/LibEvmJitCpp.vcxproj.filters new file mode 100644 index 000000000..0c37264b0 --- /dev/null +++ b/windows/LibEvmJitCpp.vcxproj.filters @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/windows/TestEthereum.vcxproj b/windows/TestEthereum.vcxproj index d81fe613a..93bb98e23 100644 --- a/windows/TestEthereum.vcxproj +++ b/windows/TestEthereum.vcxproj @@ -73,7 +73,7 @@ true - true + false false @@ -189,11 +189,8 @@ - - {826e68cb-d3ee-4a8a-b540-59a8c3f38d4f} - - - {9c816740-5c11-4377-a3a7-46be12f35fa0} + + {a5d8764c-fd17-4364-afcf-5baf78777569} diff --git a/windows/evmcc.vcxproj b/windows/evmcc.vcxproj index e7bf633fa..a0e64ad6f 100644 --- a/windows/evmcc.vcxproj +++ b/windows/evmcc.vcxproj @@ -22,8 +22,8 @@ - - {9c816740-5c11-4377-a3a7-46be12f35fa0} + + {a5d8764c-fd17-4364-afcf-5baf78777569} From ecbe9033624cf3705c3f082beb21b1a97ec94bb3 Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 5 Dec 2014 04:55:58 +0100 Subject: [PATCH 404/641] windows build in progress --- cmake/EthDependencies.cmake | 4 ++++ extdep/CMakeLists.txt | 10 +++++++--- extdep/compile/icu.cmake | 3 ++- extdep/compile/jom.cmake | 2 +- extdep/compile/qt.cmake | 5 ++--- 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 260d04751..1a8cbfa3b 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -5,6 +5,10 @@ # this must be set to point to the same directory as $ETH_DEPENDENCY_INSTALL_DIR in /extdep directory string(TOLOWER ${CMAKE_SYSTEM_NAME} _system_name) set (CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}/extdep/install/${_system_name}") +if (WIN32) + set (CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "C:/Program Files/Windows Kits/8.1/Lib/winv6.3/um/x86") + #set (CMAKE_PREFIX_PATH "C:/Program Files/Windows Kits/8.1/Lib/winv6.3/um/x64") +endif() # Dependencies must have a version number, to ensure reproducible build. The version provided here is the one that is in the extdep repository. If you use system libraries, version numbers may be different. diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index 274f9755b..a2e5fefd5 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -30,15 +30,19 @@ if (ETH_COMPILE) # cryptopp include(compile/cryptopp.cmake) + + # boost + include(compile/boost.cmake) else() eth_download(json-rpc-cpp OSX_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/scripts/json-rpc-cpp_osx.sh) - eth_download(snappy OSX_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/scripts/snappy_osx.sh) + if (APPLE) + eth_download(snappy OSX_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/scripts/snappy_osx.sh) + endif() eth_download(leveldb OSX_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/scripts/leveldb_osx.sh) eth_download(qt) eth_download(cryptopp) + eth_download(boost) - #include(compile/leveldb.cmake) - #eth_download("leveldb") endif() # will be re-eanbled later diff --git a/extdep/compile/icu.cmake b/extdep/compile/icu.cmake index 3728280e1..c0c4d46fc 100644 --- a/extdep/compile/icu.cmake +++ b/extdep/compile/icu.cmake @@ -8,7 +8,8 @@ ExternalProject_Add(icu BINARY_DIR icu-prefix/src/icu CONFIGURE_COMMAND "" BUILD_COMMAND "" - INSTALL_COMMAND cmd /c cp lib/* ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp -R include/uni ${ETH_DEPENDENCY_INSTALL_DIR}/include && cp bin/* ${ETH_DEPENDENCY_INSTALL_DIR}/bin + #INSTALL_COMMAND cmd /c cp lib/* ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp -R include/uni ${ETH_DEPENDENCY_INSTALL_DIR}/include && cp bin/* ${ETH_DEPENDENCY_INSTALL_DIR}/bin + INSTALL_COMMAND cmake -E copy_directory . ${ETH_DEPENDENCY_INSTALL_DIR} ) else() diff --git a/extdep/compile/jom.cmake b/extdep/compile/jom.cmake index e5bc5542e..17ae6caab 100644 --- a/extdep/compile/jom.cmake +++ b/extdep/compile/jom.cmake @@ -8,7 +8,7 @@ ExternalProject_Add(jom BINARY_DIR jom-prefix/src/jom CONFIGURE_COMMAND "" BUILD_COMMAND "" - INSTALL_COMMAND cp jom.exe ${ETH_DEPENDENCY_INSTALL_DIR}/bin +INSTALL_COMMAND cmake -E copy jom.exe ${ETH_DEPENDENCY_INSTALL_DIR}/bin ) else() diff --git a/extdep/compile/qt.cmake b/extdep/compile/qt.cmake index 2ff0e1e5b..049b3ba94 100644 --- a/extdep/compile/qt.cmake +++ b/extdep/compile/qt.cmake @@ -10,12 +10,11 @@ ExternalProject_add(qt elseif(WIN32) ExternalProject_Add(qt DEPENDS icu jom - URL http://download.qt-project.org/official_releases/qt/5.2/5.2.1/single/qt-everywhere-opensource-src-5.2.1.tar.gz + URL http://qtmirror.ics.com/pub/qtproject/official_releases/qt/5.3/5.3.2/single/qt-everywhere-opensource-src-5.3.2.tar.gz BINARY_DIR qt-prefix/src/qt UPDATE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/compile/qt_tools.bat - PATCH_COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/compile/qt_configure.bat qtbase/configure.bat + #PATCH_COMMAND cmake -E copy ${CMAKE_CURRENT_SOURCE_DIR}/compile/qt_configure.bat qtbase/configure.bat CONFIGURE_COMMAND configure -prefix ${ETH_DEPENDENCY_INSTALL_DIR} -opensource -confirm-license -release -opengl desktop -platform win32-msvc2013 -icu -I ${ETH_DEPENDENCY_INSTALL_DIR}/include -L ${ETH_DEPENDENCY_INSTALL_DIR}/lib -nomake tests -nomake examples - BUILD_COMMAND nmake INSTALL_COMMAND nmake install ) From 7bb2de3c4add54ba3e9a7efc695408c37ad9942c Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 5 Dec 2014 05:41:16 +0100 Subject: [PATCH 405/641] cmake project generated on windows --- cmake/EthDependencies.cmake | 10 ++++++++++ cmake/EthDependenciesDeprecated.cmake | 10 +++++----- extdep/CMakeLists.txt | 2 ++ 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 1a8cbfa3b..ae2483cda 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -44,6 +44,16 @@ find_package (Qt5WebKit REQUIRED) find_package (Qt5WebKitWidgets REQUIRED) +# we have to specify here if we want static and boost version, that is really important + +# win32 msvc 2013 boost +set(Boost_USE_STATIC_LIBS ON) +set(Boost_USE_MULTITHREADED ON) +set(Boost_COMPILER -vc120) + +find_package(Boost 1.55.0 REQUIRED COMPONENTS thread date_time system regex) + + diff --git a/cmake/EthDependenciesDeprecated.cmake b/cmake/EthDependenciesDeprecated.cmake index 47ad733e4..72ad9c769 100644 --- a/cmake/EthDependenciesDeprecated.cmake +++ b/cmake/EthDependenciesDeprecated.cmake @@ -82,11 +82,11 @@ else() message(STATUS "Failed to find the readline headers!") endif () - if (LANGUAGES) - find_package(Boost 1.53 REQUIRED COMPONENTS thread date_time) - else() - find_package(Boost 1.53 REQUIRED COMPONENTS thread date_time system regex) - endif() + #if (LANGUAGES) + # find_package(Boost 1.53 REQUIRED COMPONENTS thread date_time) + #else() + # find_package(Boost 1.53 REQUIRED COMPONENTS thread date_time system regex) + #endif() set(QTQML 1) endif() diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index a2e5fefd5..cea32c80f 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -34,7 +34,9 @@ if (ETH_COMPILE) # boost include(compile/boost.cmake) else() + eth_download(jsoncpp) eth_download(json-rpc-cpp OSX_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/scripts/json-rpc-cpp_osx.sh) + if (APPLE) eth_download(snappy OSX_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/scripts/snappy_osx.sh) endif() From abe5c5c37dcd5e1f389918316d9c1a3960e0a619 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 5 Dec 2014 08:49:30 +0100 Subject: [PATCH 406/641] MSVS evmcc project updated --- windows/evmcc.vcxproj | 9 ++++++--- windows/evmcc.vcxproj.filters | 5 ++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/windows/evmcc.vcxproj b/windows/evmcc.vcxproj index a0e64ad6f..6cd0ece89 100644 --- a/windows/evmcc.vcxproj +++ b/windows/evmcc.vcxproj @@ -18,14 +18,17 @@ x64 - - - {a5d8764c-fd17-4364-afcf-5baf78777569} + + + + + + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D} Win32Proj diff --git a/windows/evmcc.vcxproj.filters b/windows/evmcc.vcxproj.filters index 6be5386a1..f70c861ba 100644 --- a/windows/evmcc.vcxproj.filters +++ b/windows/evmcc.vcxproj.filters @@ -1,6 +1,9 @@  - + + + + \ No newline at end of file From 68662deed6bbe09963c32d9a69557ad185e768d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 5 Dec 2014 08:50:54 +0100 Subject: [PATCH 407/641] C++ emvjit connector header includes updated --- libethereum/VMFactory.cpp | 2 +- libevm/VMFace.cpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/libethereum/VMFactory.cpp b/libethereum/VMFactory.cpp index 1c8de319b..a5910ed15 100644 --- a/libethereum/VMFactory.cpp +++ b/libethereum/VMFactory.cpp @@ -1,7 +1,7 @@ #include #if ETH_EVMJIT - #include + #include #endif #include "VMFactory.h" diff --git a/libevm/VMFace.cpp b/libevm/VMFace.cpp index 9f8c6549c..136bd5223 100644 --- a/libevm/VMFace.cpp +++ b/libevm/VMFace.cpp @@ -17,7 +17,6 @@ #include "VMFace.h" #include "VM.h" -#include using namespace dev; using namespace dev::eth; From 51f4383287f9b03ad085376cbb5dc87dc50ebc8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 5 Dec 2014 09:12:28 +0100 Subject: [PATCH 408/641] Removing moved evmjit code --- evmcc/CMakeLists.txt | 51 - evmcc/evmcc.cpp | 199 ---- evmcc/test/arith/addmod.evm | 1 - evmcc/test/arith/addmod.lll | 12 - evmcc/test/arith/arith1.evm | 1 - evmcc/test/arith/arith1.lll | 37 - evmcc/test/arith/arith_bnot.evm | 1 - evmcc/test/arith/arith_bnot.lll | 14 - evmcc/test/arith/div.evm | 1 - evmcc/test/arith/div.lll | 10 - evmcc/test/arith/fib1.evm | 1 - evmcc/test/arith/fib1.lll | 57 -- evmcc/test/arith/mul.evm | 1 - evmcc/test/arith/mul.lll | 13 - evmcc/test/arith/mulmod.evm | 1 - evmcc/test/arith/mulmod.lll | 12 - evmcc/test/except/badinst1.evm | 1 - evmcc/test/ext/calldatacopy1.evm | 1 - evmcc/test/ext/calldatacopy1.lll | 13 - evmcc/test/ext/calldatacopy2.evm | 1 - evmcc/test/ext/calldatacopy2.lll | 13 - evmcc/test/ext/codecopy1.evm | 1 - evmcc/test/ext/codecopy1.lll | 13 - evmcc/test/ext/codecopy2.evm | 1 - evmcc/test/ext/codecopy2.lll | 13 - evmcc/test/ext/codecopy3.evm | 1 - evmcc/test/ext/codecopy3.lll | 13 - evmcc/test/ext/ext_test.evm | 1 - evmcc/test/ext/ext_test.lll | 55 -- evmcc/test/ext/extcodecopy1.evm | 1 - evmcc/test/ext/extcodecopy1.lll | 11 - evmcc/test/ext/store_delete.evm | 1 - evmcc/test/ext/store_delete.lll | 9 - evmcc/test/ext/store_test.evm | 1 - evmcc/test/ext/store_test.lll | 14 - evmcc/test/jump/ackermann.ethel | 7 - evmcc/test/jump/ackermann.evm | 1 - evmcc/test/jump/badindirect1.evm | 1 - evmcc/test/jump/badindirect1.lll | 9 - evmcc/test/jump/badindirect2.evm | 1 - evmcc/test/jump/badindirect2.lll | 12 - evmcc/test/jump/badjump1.evm | 1 - evmcc/test/jump/badjump1.lll | 6 - evmcc/test/jump/badjump2.evm | 1 - evmcc/test/jump/badjump2.lll | 9 - evmcc/test/jump/call1.ethel | 5 - evmcc/test/jump/call1.evm | 1 - evmcc/test/jump/call2.ethel | 5 - evmcc/test/jump/call2.evm | 1 - evmcc/test/jump/fac.ethel | 5 - evmcc/test/jump/fac.evm | 1 - evmcc/test/jump/fac_tail.ethel | 5 - evmcc/test/jump/fac_tail.evm | 1 - evmcc/test/jump/fib1.ethel | 6 - evmcc/test/jump/fib1.evm | 1 - evmcc/test/jump/for1.evm | 1 - evmcc/test/jump/for1.lll | 3 - evmcc/test/jump/for2.evm | 1 - evmcc/test/jump/for2.lll | 3 - evmcc/test/jump/if1.ethel | 1 - evmcc/test/jump/if1.evm | 1 - evmcc/test/jump/if2.ethel | 1 - evmcc/test/jump/if2.evm | 1 - evmcc/test/jump/indirect1.evm | 1 - evmcc/test/jump/indirect1.lll | 13 - evmcc/test/jump/indirect2.evm | 1 - evmcc/test/jump/indirect2.lll | 19 - evmcc/test/jump/indirect3.evm | 1 - evmcc/test/jump/indirect3.lll | 14 - evmcc/test/jump/indirect4.evm | 1 - evmcc/test/jump/indirect4.lll | 15 - evmcc/test/jump/jump1.evm | 1 - evmcc/test/jump/jump1.lll | 11 - evmcc/test/jump/jump2.evm | 1 - evmcc/test/jump/jump2.lll | 10 - evmcc/test/jump/jump3.evm | 1 - evmcc/test/jump/jump3.lll | 10 - evmcc/test/jump/jump4.evm | 1 - evmcc/test/jump/jump4.lll | 17 - evmcc/test/jump/jump5.evm | 1 - evmcc/test/jump/jump5.lll | 16 - evmcc/test/jump/jump6.evm | 1 - evmcc/test/jump/jump6.lll | 32 - evmcc/test/jump/jumpi_at_the_end.evm | 1 - evmcc/test/jump/jumpi_at_the_end.lll | 1 - evmcc/test/jump/loop1.evm | 1 - evmcc/test/jump/loop1.lll | 27 - evmcc/test/jump/loop2.evm | 1 - evmcc/test/jump/loop2.lll | 28 - evmcc/test/jump/rec1.ethel | 4 - evmcc/test/jump/rec1.evm | 1 - evmcc/test/jump/when1.asm | 10 - evmcc/test/jump/when1.evm | 1 - evmcc/test/jump/when1.lll | 2 - evmcc/test/kv.evm | 1 - evmcc/test/kv.lll | 10 - evmcc/test/mem/byte.evm | 1 - evmcc/test/mem/byte.lll | 105 -- evmcc/test/mem/mem2.evm | 1 - evmcc/test/mem/mem2.lll | 15 - evmcc/test/mem/memtest1.evm | 1 - evmcc/test/mem/memtest1.lll | 18 - evmcc/test/mem/mstore1.evm | 1 - evmcc/test/mem/mstore1.lll | 6 - evmcc/test/ret/return1.evm | 1 - evmcc/test/ret/return1.lll | 6 - evmcc/test/ret/return2.evm | 1 - evmcc/test/ret/return2.lll | 6 - evmcc/test/ret/return_test.evm | 1 - evmcc/test/ret/return_test.lll | 15 - evmcc/test/stack/oos.evm | 1 - evmcc/test/stack/oos.lll | 11 - evmcc/test/stack/push_test.evm | 1 - evmcc/test/stack/push_test.lll | 35 - evmcc/test/stack/stack_test.evm | 1 - evmcc/test/stack/stack_test.lll | 8 - evmcc/test/stack/stackjump.evm | 1 - evmcc/test/stack/stackjump.lll | 3 - evmcc/test/stack/swap.evm | 1 - evmcc/test/stack/swap.lll | 31 - evmcc/test/stack/swapswap.evm | 1 - evmcc/test/stack/swapswap.lll | 32 - evmcc/test/stack/test.evm | 1 - .../test/vmtests/vmArithPerformanceTest.json | 260 ----- evmcc/test/vmtests/vmPerformanceTest.json | 214 ---- evmcc/test/vmtests/vm_jump.json | 41 - libevmjit/Arith256.cpp | 159 --- libevmjit/Arith256.h | 47 - libevmjit/BasicBlock.cpp | 382 ------- libevmjit/BasicBlock.h | 117 --- libevmjit/CMakeLists.txt | 58 -- libevmjit/Compiler.cpp | 933 ------------------ libevmjit/Compiler.h | 92 -- libevmjit/CompilerHelper.cpp | 44 - libevmjit/CompilerHelper.h | 83 -- libevmjit/Endianness.cpp | 25 - libevmjit/Endianness.h | 34 - libevmjit/ExecutionEngine.cpp | 132 --- libevmjit/ExecutionEngine.h | 28 - libevmjit/Ext.cpp | 420 -------- libevmjit/Ext.h | 69 -- libevmjit/GasMeter.cpp | 199 ---- libevmjit/GasMeter.h | 54 - libevmjit/Memory.cpp | 218 ---- libevmjit/Memory.h | 49 - libevmjit/Runtime.cpp | 210 ---- libevmjit/Runtime.h | 122 --- libevmjit/Stack.cpp | 112 --- libevmjit/Stack.h | 43 - libevmjit/Type.cpp | 59 -- libevmjit/Type.h | 63 -- libevmjit/Utils.cpp | 57 -- libevmjit/Utils.h | 107 -- libevmjit/VM.cpp | 46 - libevmjit/VM.h | 34 - libevmjit/interface.c | 30 - 156 files changed, 5768 deletions(-) delete mode 100644 evmcc/CMakeLists.txt delete mode 100644 evmcc/evmcc.cpp delete mode 100644 evmcc/test/arith/addmod.evm delete mode 100644 evmcc/test/arith/addmod.lll delete mode 100644 evmcc/test/arith/arith1.evm delete mode 100644 evmcc/test/arith/arith1.lll delete mode 100644 evmcc/test/arith/arith_bnot.evm delete mode 100644 evmcc/test/arith/arith_bnot.lll delete mode 100644 evmcc/test/arith/div.evm delete mode 100644 evmcc/test/arith/div.lll delete mode 100644 evmcc/test/arith/fib1.evm delete mode 100644 evmcc/test/arith/fib1.lll delete mode 100644 evmcc/test/arith/mul.evm delete mode 100644 evmcc/test/arith/mul.lll delete mode 100644 evmcc/test/arith/mulmod.evm delete mode 100644 evmcc/test/arith/mulmod.lll delete mode 100644 evmcc/test/except/badinst1.evm delete mode 100644 evmcc/test/ext/calldatacopy1.evm delete mode 100644 evmcc/test/ext/calldatacopy1.lll delete mode 100644 evmcc/test/ext/calldatacopy2.evm delete mode 100644 evmcc/test/ext/calldatacopy2.lll delete mode 100644 evmcc/test/ext/codecopy1.evm delete mode 100644 evmcc/test/ext/codecopy1.lll delete mode 100644 evmcc/test/ext/codecopy2.evm delete mode 100644 evmcc/test/ext/codecopy2.lll delete mode 100644 evmcc/test/ext/codecopy3.evm delete mode 100644 evmcc/test/ext/codecopy3.lll delete mode 100644 evmcc/test/ext/ext_test.evm delete mode 100644 evmcc/test/ext/ext_test.lll delete mode 100644 evmcc/test/ext/extcodecopy1.evm delete mode 100644 evmcc/test/ext/extcodecopy1.lll delete mode 100644 evmcc/test/ext/store_delete.evm delete mode 100644 evmcc/test/ext/store_delete.lll delete mode 100644 evmcc/test/ext/store_test.evm delete mode 100644 evmcc/test/ext/store_test.lll delete mode 100644 evmcc/test/jump/ackermann.ethel delete mode 100644 evmcc/test/jump/ackermann.evm delete mode 100644 evmcc/test/jump/badindirect1.evm delete mode 100644 evmcc/test/jump/badindirect1.lll delete mode 100644 evmcc/test/jump/badindirect2.evm delete mode 100644 evmcc/test/jump/badindirect2.lll delete mode 100644 evmcc/test/jump/badjump1.evm delete mode 100644 evmcc/test/jump/badjump1.lll delete mode 100644 evmcc/test/jump/badjump2.evm delete mode 100644 evmcc/test/jump/badjump2.lll delete mode 100644 evmcc/test/jump/call1.ethel delete mode 100644 evmcc/test/jump/call1.evm delete mode 100644 evmcc/test/jump/call2.ethel delete mode 100644 evmcc/test/jump/call2.evm delete mode 100644 evmcc/test/jump/fac.ethel delete mode 100644 evmcc/test/jump/fac.evm delete mode 100644 evmcc/test/jump/fac_tail.ethel delete mode 100644 evmcc/test/jump/fac_tail.evm delete mode 100644 evmcc/test/jump/fib1.ethel delete mode 100644 evmcc/test/jump/fib1.evm delete mode 100644 evmcc/test/jump/for1.evm delete mode 100644 evmcc/test/jump/for1.lll delete mode 100644 evmcc/test/jump/for2.evm delete mode 100644 evmcc/test/jump/for2.lll delete mode 100644 evmcc/test/jump/if1.ethel delete mode 100644 evmcc/test/jump/if1.evm delete mode 100644 evmcc/test/jump/if2.ethel delete mode 100644 evmcc/test/jump/if2.evm delete mode 100644 evmcc/test/jump/indirect1.evm delete mode 100644 evmcc/test/jump/indirect1.lll delete mode 100644 evmcc/test/jump/indirect2.evm delete mode 100644 evmcc/test/jump/indirect2.lll delete mode 100644 evmcc/test/jump/indirect3.evm delete mode 100644 evmcc/test/jump/indirect3.lll delete mode 100644 evmcc/test/jump/indirect4.evm delete mode 100644 evmcc/test/jump/indirect4.lll delete mode 100644 evmcc/test/jump/jump1.evm delete mode 100644 evmcc/test/jump/jump1.lll delete mode 100644 evmcc/test/jump/jump2.evm delete mode 100644 evmcc/test/jump/jump2.lll delete mode 100644 evmcc/test/jump/jump3.evm delete mode 100644 evmcc/test/jump/jump3.lll delete mode 100644 evmcc/test/jump/jump4.evm delete mode 100644 evmcc/test/jump/jump4.lll delete mode 100644 evmcc/test/jump/jump5.evm delete mode 100644 evmcc/test/jump/jump5.lll delete mode 100644 evmcc/test/jump/jump6.evm delete mode 100644 evmcc/test/jump/jump6.lll delete mode 100644 evmcc/test/jump/jumpi_at_the_end.evm delete mode 100644 evmcc/test/jump/jumpi_at_the_end.lll delete mode 100644 evmcc/test/jump/loop1.evm delete mode 100644 evmcc/test/jump/loop1.lll delete mode 100644 evmcc/test/jump/loop2.evm delete mode 100644 evmcc/test/jump/loop2.lll delete mode 100644 evmcc/test/jump/rec1.ethel delete mode 100644 evmcc/test/jump/rec1.evm delete mode 100644 evmcc/test/jump/when1.asm delete mode 100644 evmcc/test/jump/when1.evm delete mode 100644 evmcc/test/jump/when1.lll delete mode 100644 evmcc/test/kv.evm delete mode 100644 evmcc/test/kv.lll delete mode 100644 evmcc/test/mem/byte.evm delete mode 100644 evmcc/test/mem/byte.lll delete mode 100644 evmcc/test/mem/mem2.evm delete mode 100644 evmcc/test/mem/mem2.lll delete mode 100644 evmcc/test/mem/memtest1.evm delete mode 100644 evmcc/test/mem/memtest1.lll delete mode 100644 evmcc/test/mem/mstore1.evm delete mode 100644 evmcc/test/mem/mstore1.lll delete mode 100644 evmcc/test/ret/return1.evm delete mode 100644 evmcc/test/ret/return1.lll delete mode 100644 evmcc/test/ret/return2.evm delete mode 100644 evmcc/test/ret/return2.lll delete mode 100644 evmcc/test/ret/return_test.evm delete mode 100644 evmcc/test/ret/return_test.lll delete mode 100644 evmcc/test/stack/oos.evm delete mode 100644 evmcc/test/stack/oos.lll delete mode 100644 evmcc/test/stack/push_test.evm delete mode 100644 evmcc/test/stack/push_test.lll delete mode 100644 evmcc/test/stack/stack_test.evm delete mode 100644 evmcc/test/stack/stack_test.lll delete mode 100644 evmcc/test/stack/stackjump.evm delete mode 100644 evmcc/test/stack/stackjump.lll delete mode 100644 evmcc/test/stack/swap.evm delete mode 100644 evmcc/test/stack/swap.lll delete mode 100644 evmcc/test/stack/swapswap.evm delete mode 100644 evmcc/test/stack/swapswap.lll delete mode 100644 evmcc/test/stack/test.evm delete mode 100644 evmcc/test/vmtests/vmArithPerformanceTest.json delete mode 100644 evmcc/test/vmtests/vmPerformanceTest.json delete mode 100644 evmcc/test/vmtests/vm_jump.json delete mode 100644 libevmjit/Arith256.cpp delete mode 100644 libevmjit/Arith256.h delete mode 100644 libevmjit/BasicBlock.cpp delete mode 100644 libevmjit/BasicBlock.h delete mode 100644 libevmjit/CMakeLists.txt delete mode 100644 libevmjit/Compiler.cpp delete mode 100644 libevmjit/Compiler.h delete mode 100644 libevmjit/CompilerHelper.cpp delete mode 100644 libevmjit/CompilerHelper.h delete mode 100644 libevmjit/Endianness.cpp delete mode 100644 libevmjit/Endianness.h delete mode 100644 libevmjit/ExecutionEngine.cpp delete mode 100644 libevmjit/ExecutionEngine.h delete mode 100644 libevmjit/Ext.cpp delete mode 100644 libevmjit/Ext.h delete mode 100644 libevmjit/GasMeter.cpp delete mode 100644 libevmjit/GasMeter.h delete mode 100644 libevmjit/Memory.cpp delete mode 100644 libevmjit/Memory.h delete mode 100644 libevmjit/Runtime.cpp delete mode 100644 libevmjit/Runtime.h delete mode 100644 libevmjit/Stack.cpp delete mode 100644 libevmjit/Stack.h delete mode 100644 libevmjit/Type.cpp delete mode 100644 libevmjit/Type.h delete mode 100644 libevmjit/Utils.cpp delete mode 100644 libevmjit/Utils.h delete mode 100644 libevmjit/VM.cpp delete mode 100644 libevmjit/VM.h delete mode 100644 libevmjit/interface.c diff --git a/evmcc/CMakeLists.txt b/evmcc/CMakeLists.txt deleted file mode 100644 index a087539dc..000000000 --- a/evmcc/CMakeLists.txt +++ /dev/null @@ -1,51 +0,0 @@ -cmake_policy(SET CMP0015 NEW) - -aux_source_directory(. SRC_LIST) - -include_directories(..) - -set(EXECUTABLE evmcc) - -add_executable(${EXECUTABLE} ${SRC_LIST}) - -target_link_libraries(${EXECUTABLE} boost_program_options) -target_link_libraries(${EXECUTABLE} devcore) -target_link_libraries(${EXECUTABLE} ethcore) -target_link_libraries(${EXECUTABLE} evmjit) -target_link_libraries(${EXECUTABLE} evm) -target_link_libraries(${EXECUTABLE} ethereum) - -if ("${TARGET_PLATFORM}" STREQUAL "w64") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") - target_link_libraries(${EXECUTABLE} gcc) - target_link_libraries(${EXECUTABLE} gdi32) - target_link_libraries(${EXECUTABLE} ws2_32) - target_link_libraries(${EXECUTABLE} mswsock) - target_link_libraries(${EXECUTABLE} shlwapi) - target_link_libraries(${EXECUTABLE} iphlpapi) - target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) - set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) -else () - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -endif () - -# LLVM specific commands - -find_package(LLVM REQUIRED CONFIG) - -message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") -message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") - -include_directories(${LLVM_INCLUDE_DIRS}) -add_definitions(${LLVM_DEFINITIONS}) - -llvm_map_components_to_libnames(llvm_libs bitwriter) -target_link_libraries(evmcc ${llvm_libs}) - -# end of LLVM specific commands - - -install( TARGETS ${EXECUTABLE} DESTINATION bin ) - -cmake_policy(SET CMP0015 NEW) diff --git a/evmcc/evmcc.cpp b/evmcc/evmcc.cpp deleted file mode 100644 index 16ab23e9b..000000000 --- a/evmcc/evmcc.cpp +++ /dev/null @@ -1,199 +0,0 @@ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - - -void parseProgramOptions(int _argc, char** _argv, boost::program_options::variables_map& _varMap) -{ - namespace opt = boost::program_options; - - opt::options_description explicitOpts("Allowed options"); - explicitOpts.add_options() - ("help,h", "show usage information") - ("compile,c", "compile the code to LLVM IR") - ("interpret,i", "compile the code to LLVM IR and execute") - ("gas,g", opt::value(), "set initial gas for execution") - ("disassemble,d", "dissassemble the code") - ("dump-cfg", "dump control flow graph to graphviz file") - ("dont-optimize", "turn off optimizations") - ("optimize-stack", "optimize stack use between basic blocks (default: on)") - ("rewrite-switch", "rewrite LLVM switch to branches (default: on)") - ("output-ll", opt::value(), "dump generated LLVM IR to file") - ("output-bc", opt::value(), "dump generated LLVM bitcode to file") - ("show-logs", "output LOG statements to stderr") - ("verbose,V", "enable verbose output"); - - opt::options_description implicitOpts("Input files"); - implicitOpts.add_options() - ("input-file", opt::value(), "input file"); - - opt::options_description allOpts(""); - allOpts.add(explicitOpts).add(implicitOpts); - - opt::positional_options_description inputOpts; - inputOpts.add("input-file", 1); - - const char* errorMsg = nullptr; - try - { - auto parser = opt::command_line_parser(_argc, _argv).options(allOpts).positional(inputOpts); - opt::store(parser.run(), _varMap); - opt::notify(_varMap); - } - catch (boost::program_options::error& err) - { - errorMsg = err.what(); - } - - if (!errorMsg && _varMap.count("input-file") == 0) - errorMsg = "missing input file name"; - - if (_varMap.count("disassemble") == 0 - && _varMap.count("compile") == 0 - && _varMap.count("interpret") == 0) - { - errorMsg = "at least one of -c, -i, -d is required"; - } - - if (errorMsg || _varMap.count("help")) - { - if (errorMsg) - std::cerr << "Error: " << errorMsg << std::endl; - - std::cout << "Usage: " << _argv[0] << " input-file " << std::endl - << explicitOpts << std::endl; - std::exit(errorMsg ? 1 : 0); - } -} - -int main(int argc, char** argv) -{ - boost::program_options::variables_map options; - parseProgramOptions(argc, argv, options); - - auto inputFile = options["input-file"].as(); - std::ifstream ifs(inputFile); - if (!ifs.is_open()) - { - std::cerr << "cannot open input file " << inputFile << std::endl; - exit(1); - } - - std::string src((std::istreambuf_iterator(ifs)), - (std::istreambuf_iterator())); - - boost::algorithm::trim(src); - - using namespace dev; - - bytes bytecode = fromHex(src); - - if (options.count("disassemble")) - { - std::string assembly = eth::disassemble(bytecode); - std::cout << assembly << std::endl; - } - - if (options.count("compile") || options.count("interpret")) - { - size_t initialGas = 10000; - - if (options.count("gas")) - initialGas = options["gas"].as(); - - auto compilationStartTime = std::chrono::high_resolution_clock::now(); - - eth::jit::Compiler::Options compilerOptions; - compilerOptions.dumpCFG = options.count("dump-cfg") > 0; - bool optimize = options.count("dont-optimize") == 0; - compilerOptions.optimizeStack = optimize || options.count("optimize-stack") > 0; - compilerOptions.rewriteSwitchToBranches = optimize || options.count("rewrite-switch") > 0; - - auto compiler = eth::jit::Compiler(compilerOptions); - auto module = compiler.compile(bytecode); - - auto compilationEndTime = std::chrono::high_resolution_clock::now(); - - module->dump(); - - if (options.count("output-ll")) - { - auto outputFile = options["output-ll"].as(); - std::ofstream ofs(outputFile); - if (!ofs.is_open()) - { - std::cerr << "cannot open output file " << outputFile << std::endl; - exit(1); - } - llvm::raw_os_ostream ros(ofs); - module->print(ros, nullptr); - ofs.close(); - } - - if (options.count("output-bc")) - { - auto outputFile = options["output-bc"].as(); - std::ofstream ofs(outputFile); - if (!ofs.is_open()) - { - std::cerr << "cannot open output file " << outputFile << std::endl; - exit(1); - } - llvm::raw_os_ostream ros(ofs); - llvm::WriteBitcodeToFile(module.get(), ros); - ros.flush(); - ofs.close(); - } - - if (options.count("verbose")) - { - std::cerr << "*** Compilation time: " - << std::chrono::duration_cast(compilationEndTime - compilationStartTime).count() - << std::endl; - } - - if (options.count("interpret")) - { - auto engine = eth::jit::ExecutionEngine(); - u256 gas = initialGas; - - // Create fake ExtVM interface - eth::ExtVMFace ext; - ext.myAddress = Address(1122334455667788); - ext.caller = Address(0xfacefacefaceface); - ext.origin = Address(101010101010101010); - ext.value = 0xabcd; - ext.gasPrice = 1002; - ext.previousBlock.hash = u256(1003); - ext.currentBlock.coinbaseAddress = Address(1004); - ext.currentBlock.timestamp = 1005; - ext.currentBlock.number = 1006; - ext.currentBlock.difficulty = 1007; - ext.currentBlock.gasLimit = 1008; - ext.data = std::string("Hello the Beautiful World of Ethereum!"); - ext.code = { 0x0d, 0x0e, 0x0a, 0x0d, 0x0b, 0x0e, 0xe, 0xf }; - - auto result = engine.run(std::move(module), gas, options.count("show-logs") > 0, ext); - return result; - } - } - - return 0; -} diff --git a/evmcc/test/arith/addmod.evm b/evmcc/test/arith/addmod.evm deleted file mode 100644 index 4ca71e065..000000000 --- a/evmcc/test/arith/addmod.evm +++ /dev/null @@ -1 +0,0 @@ -60646107b760271460005560006001f2 diff --git a/evmcc/test/arith/addmod.lll b/evmcc/test/arith/addmod.lll deleted file mode 100644 index 11a6b2cb9..000000000 --- a/evmcc/test/arith/addmod.lll +++ /dev/null @@ -1,12 +0,0 @@ -;; Should return (1975 + 39) `mod` 100 = 14 = 0x0e -(asm -100 -1975 -39 -ADDMOD -0 -MSTORE8 -0 -1 -RETURN -) \ No newline at end of file diff --git a/evmcc/test/arith/arith1.evm b/evmcc/test/arith/arith1.evm deleted file mode 100644 index c7a029f52..000000000 --- a/evmcc/test/arith/arith1.evm +++ /dev/null @@ -1 +0,0 @@ -60016001900160070260050160029004600490066021900560150160030260059007600303600960110860005460086000f2 diff --git a/evmcc/test/arith/arith1.lll b/evmcc/test/arith/arith1.lll deleted file mode 100644 index 4757a7420..000000000 --- a/evmcc/test/arith/arith1.lll +++ /dev/null @@ -1,37 +0,0 @@ - -(asm -1 -1 -SWAP1 -ADD ;; 2 -7 -MUL ;; 14 -5 -ADD ;; 19 -2 -SWAP1 -DIV ;; 9 -4 -SWAP1 -MOD ;; 1 -33 -SWAP1 -SDIV;; 0 -21 -ADD ;; 21 -3 -MUL ;; 63 -5 -SWAP1 -SMOD;; 3 -3 -SUB ;; 0 -9 -17 -EXP ;; 17^9 -0 -MSTORE -8 -0 -RETURN -) \ No newline at end of file diff --git a/evmcc/test/arith/arith_bnot.evm b/evmcc/test/arith/arith_bnot.evm deleted file mode 100644 index 4cfaf8f55..000000000 --- a/evmcc/test/arith/arith_bnot.evm +++ /dev/null @@ -1 +0,0 @@ -6201e2406000546000530960005460206000f2 diff --git a/evmcc/test/arith/arith_bnot.lll b/evmcc/test/arith/arith_bnot.lll deleted file mode 100644 index a83b05a9a..000000000 --- a/evmcc/test/arith/arith_bnot.lll +++ /dev/null @@ -1,14 +0,0 @@ - -(asm -123456 -0 -MSTORE -0 -MLOAD -BNOT -0 -MSTORE -32 -0 -RETURN -) \ No newline at end of file diff --git a/evmcc/test/arith/div.evm b/evmcc/test/arith/div.evm deleted file mode 100644 index b68d5d202..000000000 --- a/evmcc/test/arith/div.evm +++ /dev/null @@ -1 +0,0 @@ -60027ffedcba9876543210fedcba9876543210fedcba9876543210fedcba98765432100460005460206000f2 diff --git a/evmcc/test/arith/div.lll b/evmcc/test/arith/div.lll deleted file mode 100644 index 72c22bfdc..000000000 --- a/evmcc/test/arith/div.lll +++ /dev/null @@ -1,10 +0,0 @@ -(asm -0x2 -0xfedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210 -DIV -0 -MSTORE -32 -0 -RETURN -) diff --git a/evmcc/test/arith/fib1.evm b/evmcc/test/arith/fib1.evm deleted file mode 100644 index 4c141314e..000000000 --- a/evmcc/test/arith/fib1.evm +++ /dev/null @@ -1 +0,0 @@ -60016001818101818101818101818101818101818101818101818101818101818101818101818101818101818101818101818101818101 diff --git a/evmcc/test/arith/fib1.lll b/evmcc/test/arith/fib1.lll deleted file mode 100644 index 286bed275..000000000 --- a/evmcc/test/arith/fib1.lll +++ /dev/null @@ -1,57 +0,0 @@ -;; Fibbonacci unrolled - -(asm -1 -1 -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -) \ No newline at end of file diff --git a/evmcc/test/arith/mul.evm b/evmcc/test/arith/mul.evm deleted file mode 100644 index 7e8afd268..000000000 --- a/evmcc/test/arith/mul.evm +++ /dev/null @@ -1 +0,0 @@ -7001234567890abcdef0fedcba09876543217001234567890abcdef0fedcba09876543217001234567890abcdef0fedcba0987654321020260005460206000f2 diff --git a/evmcc/test/arith/mul.lll b/evmcc/test/arith/mul.lll deleted file mode 100644 index b0fa343bb..000000000 --- a/evmcc/test/arith/mul.lll +++ /dev/null @@ -1,13 +0,0 @@ -(asm -0x1234567890abcdef0fedcba0987654321 -0x1234567890abcdef0fedcba0987654321 -0x1234567890abcdef0fedcba0987654321 -MUL -MUL -0 -MSTORE -32 -0 -RETURN -;; 47d0817e4167b1eb4f9fc722b133ef9d7d9a6fb4c2c1c442d000107a5e419561 -) diff --git a/evmcc/test/arith/mulmod.evm b/evmcc/test/arith/mulmod.evm deleted file mode 100644 index e34a06154..000000000 --- a/evmcc/test/arith/mulmod.evm +++ /dev/null @@ -1 +0,0 @@ -6064601b60251560005560006001f2 diff --git a/evmcc/test/arith/mulmod.lll b/evmcc/test/arith/mulmod.lll deleted file mode 100644 index 5e87f0843..000000000 --- a/evmcc/test/arith/mulmod.lll +++ /dev/null @@ -1,12 +0,0 @@ -;; Should return (27 * 37) `mod` 100 = 99 = 0x63 -(asm -100 -27 -37 -MULMOD -0 -MSTORE8 -0 -1 -RETURN -) \ No newline at end of file diff --git a/evmcc/test/except/badinst1.evm b/evmcc/test/except/badinst1.evm deleted file mode 100644 index 69aadac5e..000000000 --- a/evmcc/test/except/badinst1.evm +++ /dev/null @@ -1 +0,0 @@ -4a diff --git a/evmcc/test/ext/calldatacopy1.evm b/evmcc/test/ext/calldatacopy1.evm deleted file mode 100644 index f20019651..000000000 --- a/evmcc/test/ext/calldatacopy1.evm +++ /dev/null @@ -1 +0,0 @@ -60326000600a37600053600a6014f2 diff --git a/evmcc/test/ext/calldatacopy1.lll b/evmcc/test/ext/calldatacopy1.lll deleted file mode 100644 index 3d2ae0a78..000000000 --- a/evmcc/test/ext/calldatacopy1.lll +++ /dev/null @@ -1,13 +0,0 @@ -(asm -50 ;; byte count -0 ;; source index in calldata array -10 ;; dest index in memory -CALLDATACOPY - -0 -MLOAD ;; to dump memory - -10 -20 -RETURN -) \ No newline at end of file diff --git a/evmcc/test/ext/calldatacopy2.evm b/evmcc/test/ext/calldatacopy2.evm deleted file mode 100644 index e8eea8da7..000000000 --- a/evmcc/test/ext/calldatacopy2.evm +++ /dev/null @@ -1 +0,0 @@ -606464e8d4a510006000376000536000600af2 diff --git a/evmcc/test/ext/calldatacopy2.lll b/evmcc/test/ext/calldatacopy2.lll deleted file mode 100644 index 6bbea48d8..000000000 --- a/evmcc/test/ext/calldatacopy2.lll +++ /dev/null @@ -1,13 +0,0 @@ -(asm -100 ;; byte count -1000000000000 ;; source index in calldata array -0 ;; dest index in memory -CALLDATACOPY - -0 -MLOAD ;; to dump memory - -0 -10 -RETURN -) \ No newline at end of file diff --git a/evmcc/test/ext/codecopy1.evm b/evmcc/test/ext/codecopy1.evm deleted file mode 100644 index d286f9232..000000000 --- a/evmcc/test/ext/codecopy1.evm +++ /dev/null @@ -1 +0,0 @@ -60146000600a39600053600a6014f2 diff --git a/evmcc/test/ext/codecopy1.lll b/evmcc/test/ext/codecopy1.lll deleted file mode 100644 index 85a02b5d7..000000000 --- a/evmcc/test/ext/codecopy1.lll +++ /dev/null @@ -1,13 +0,0 @@ -(asm -20 ;; byte count -0 ;; source index in code array -10 ;; dest index in memory -CODECOPY - -0 -MLOAD ;; to dump memory - -10 -20 -RETURN -) \ No newline at end of file diff --git a/evmcc/test/ext/codecopy2.evm b/evmcc/test/ext/codecopy2.evm deleted file mode 100644 index 71cd92525..000000000 --- a/evmcc/test/ext/codecopy2.evm +++ /dev/null @@ -1 +0,0 @@ -606464e8d4a510006000396000536000600af2 diff --git a/evmcc/test/ext/codecopy2.lll b/evmcc/test/ext/codecopy2.lll deleted file mode 100644 index dcbbcaa46..000000000 --- a/evmcc/test/ext/codecopy2.lll +++ /dev/null @@ -1,13 +0,0 @@ -(asm -100 ;; byte count -1000000000000 ;; source index in code array -0 ;; dest index in memory -CODECOPY - -0 -MLOAD ;; to dump memory - -0 -10 -RETURN -) \ No newline at end of file diff --git a/evmcc/test/ext/codecopy3.evm b/evmcc/test/ext/codecopy3.evm deleted file mode 100644 index e4b6a9253..000000000 --- a/evmcc/test/ext/codecopy3.evm +++ /dev/null @@ -1 +0,0 @@ -3860006000396000536000600af2 diff --git a/evmcc/test/ext/codecopy3.lll b/evmcc/test/ext/codecopy3.lll deleted file mode 100644 index 80d9982c6..000000000 --- a/evmcc/test/ext/codecopy3.lll +++ /dev/null @@ -1,13 +0,0 @@ -(asm -CODESIZE ;; byte count -0 ;; source index in code array -0 ;; dest index in memory -CODECOPY - -0 -MLOAD ;; to dump memory - -0 -10 -RETURN -) \ No newline at end of file diff --git a/evmcc/test/ext/ext_test.evm b/evmcc/test/ext/ext_test.evm deleted file mode 100644 index 580bd9675..000000000 --- a/evmcc/test/ext/ext_test.evm +++ /dev/null @@ -1 +0,0 @@ -5a3031333234363a4041424344455a36600035602635601335387f1111222233334444555566667777888899990000aaaabbbbccccddddeeeeffff600054602060006000f06020600060206000600030610bb8f1600053611000545b60200260002030ff60016002f2 diff --git a/evmcc/test/ext/ext_test.lll b/evmcc/test/ext/ext_test.lll deleted file mode 100644 index 3287ae95f..000000000 --- a/evmcc/test/ext/ext_test.lll +++ /dev/null @@ -1,55 +0,0 @@ - -(asm -PC -ADDRESS -BALANCE -CALLER -ORIGIN -CALLVALUE -CALLDATASIZE -GASPRICE -PREVHASH -COINBASE -TIMESTAMP -NUMBER -DIFFICULTY -GASLIMIT -PC -CALLDATASIZE -0 -CALLDATALOAD -38 -CALLDATALOAD -19 -CALLDATALOAD -CODESIZE -0x1111222233334444555566667777888899990000aaaabbbbccccddddeeeeffff -0 -MSTORE -32 -0 -0 -CREATE -32 -0 -32 -0 -0 -ADDRESS -3000 -CALL -0 -MLOAD -4096 -MSTORE -MSIZE -32 -MUL -0 -SHA3 -ADDRESS -SUICIDE -1 -2 -RETURN -) \ No newline at end of file diff --git a/evmcc/test/ext/extcodecopy1.evm b/evmcc/test/ext/extcodecopy1.evm deleted file mode 100644 index 6132b52d8..000000000 --- a/evmcc/test/ext/extcodecopy1.evm +++ /dev/null @@ -1 +0,0 @@ -60c86000600a303c60005360006020f2 diff --git a/evmcc/test/ext/extcodecopy1.lll b/evmcc/test/ext/extcodecopy1.lll deleted file mode 100644 index c37054574..000000000 --- a/evmcc/test/ext/extcodecopy1.lll +++ /dev/null @@ -1,11 +0,0 @@ -(asm -200 ;; byte count -0 ;; source index in code array -10 ;; dest index in memory -ADDRESS -EXTCODECOPY - -0 MLOAD ;; to dump memory - -0 32 RETURN -) \ No newline at end of file diff --git a/evmcc/test/ext/store_delete.evm b/evmcc/test/ext/store_delete.evm deleted file mode 100644 index d6acae03d..000000000 --- a/evmcc/test/ext/store_delete.evm +++ /dev/null @@ -1 +0,0 @@ -6104d26063576000606357 diff --git a/evmcc/test/ext/store_delete.lll b/evmcc/test/ext/store_delete.lll deleted file mode 100644 index 3d8f0f23a..000000000 --- a/evmcc/test/ext/store_delete.lll +++ /dev/null @@ -1,9 +0,0 @@ - -(asm -1234 -99 -SSTORE -0 -99 -SSTORE -) \ No newline at end of file diff --git a/evmcc/test/ext/store_test.evm b/evmcc/test/ext/store_test.evm deleted file mode 100644 index 54c9419b5..000000000 --- a/evmcc/test/ext/store_test.evm +++ /dev/null @@ -1 +0,0 @@ -607b607c60015760005760015660005603 diff --git a/evmcc/test/ext/store_test.lll b/evmcc/test/ext/store_test.lll deleted file mode 100644 index c40471c40..000000000 --- a/evmcc/test/ext/store_test.lll +++ /dev/null @@ -1,14 +0,0 @@ - -(asm -123 -124 -1 -SSTORE -0 -SSTORE -1 -SLOAD -0 -SLOAD -SUB -) \ No newline at end of file diff --git a/evmcc/test/jump/ackermann.ethel b/evmcc/test/jump/ackermann.ethel deleted file mode 100644 index 971fd2b8d..000000000 --- a/evmcc/test/jump/ackermann.ethel +++ /dev/null @@ -1,7 +0,0 @@ -let A m n = - if m == 0 then n+1 - else if n == 0 then A (m-1) 1 - else A (m-1) (A (m) (n-1)) - -return A 3 8 - diff --git a/evmcc/test/jump/ackermann.evm b/evmcc/test/jump/ackermann.evm deleted file mode 100644 index 964844045..000000000 --- a/evmcc/test/jump/ackermann.evm +++ /dev/null @@ -1 +0,0 @@ -6009600360086012585d60005460206000f26000820e6047596000810e603859603460018303603084600185036012585d6012585d60445860436001830360016012585d604b5860018101905090509058 \ No newline at end of file diff --git a/evmcc/test/jump/badindirect1.evm b/evmcc/test/jump/badindirect1.evm deleted file mode 100644 index b2a8aad67..000000000 --- a/evmcc/test/jump/badindirect1.evm +++ /dev/null @@ -1 +0,0 @@ -601b602502585d diff --git a/evmcc/test/jump/badindirect1.lll b/evmcc/test/jump/badindirect1.lll deleted file mode 100644 index d6291be68..000000000 --- a/evmcc/test/jump/badindirect1.lll +++ /dev/null @@ -1,9 +0,0 @@ -;; Indirect jump out of code - -(asm -27 -37 -MUL -JUMP -JUMPDEST -) \ No newline at end of file diff --git a/evmcc/test/jump/badindirect2.evm b/evmcc/test/jump/badindirect2.evm deleted file mode 100644 index 22217523d..000000000 --- a/evmcc/test/jump/badindirect2.evm +++ /dev/null @@ -1 +0,0 @@ -60016003600302596000600058 diff --git a/evmcc/test/jump/badindirect2.lll b/evmcc/test/jump/badindirect2.lll deleted file mode 100644 index 53a6294f7..000000000 --- a/evmcc/test/jump/badindirect2.lll +++ /dev/null @@ -1,12 +0,0 @@ -;; Indirect jump into data - -(asm -1 ;; 0 -3 -3 -MUL ;; 6 -JUMPI ;; 7 -0 ;; 8 -0 -JUMP -) \ No newline at end of file diff --git a/evmcc/test/jump/badjump1.evm b/evmcc/test/jump/badjump1.evm deleted file mode 100644 index 5c11a8661..000000000 --- a/evmcc/test/jump/badjump1.evm +++ /dev/null @@ -1 +0,0 @@ -6103e758 diff --git a/evmcc/test/jump/badjump1.lll b/evmcc/test/jump/badjump1.lll deleted file mode 100644 index 1834a62ef..000000000 --- a/evmcc/test/jump/badjump1.lll +++ /dev/null @@ -1,6 +0,0 @@ -;; Direct jump out of code. - -(asm -999 -JUMP -) \ No newline at end of file diff --git a/evmcc/test/jump/badjump2.evm b/evmcc/test/jump/badjump2.evm deleted file mode 100644 index 900a1c15a..000000000 --- a/evmcc/test/jump/badjump2.evm +++ /dev/null @@ -1 +0,0 @@ -6004586000600058 diff --git a/evmcc/test/jump/badjump2.lll b/evmcc/test/jump/badjump2.lll deleted file mode 100644 index ce61276d7..000000000 --- a/evmcc/test/jump/badjump2.lll +++ /dev/null @@ -1,9 +0,0 @@ -;; Direct jump into data - -(asm -4 ;; 0 0-3 -JUMP ;; 2 -0 ;; 3 3-4 -0 ;; 5 4-7 -JUMP ;; 6 -) \ No newline at end of file diff --git a/evmcc/test/jump/call1.ethel b/evmcc/test/jump/call1.ethel deleted file mode 100644 index 414ad0124..000000000 --- a/evmcc/test/jump/call1.ethel +++ /dev/null @@ -1,5 +0,0 @@ -let f n = n + 1 - -return f 2 - - diff --git a/evmcc/test/jump/call1.evm b/evmcc/test/jump/call1.evm deleted file mode 100644 index 252aaf778..000000000 --- a/evmcc/test/jump/call1.evm +++ /dev/null @@ -1 +0,0 @@ -600760026010585d60005460206000f28060010190509058 \ No newline at end of file diff --git a/evmcc/test/jump/call2.ethel b/evmcc/test/jump/call2.ethel deleted file mode 100644 index bdeb9b734..000000000 --- a/evmcc/test/jump/call2.ethel +++ /dev/null @@ -1,5 +0,0 @@ -let f a b = a + b - -return f 2 3 - - diff --git a/evmcc/test/jump/call2.evm b/evmcc/test/jump/call2.evm deleted file mode 100644 index 6832e044d..000000000 --- a/evmcc/test/jump/call2.evm +++ /dev/null @@ -1 +0,0 @@ -6009600260036012585d60005460206000f2818101905090509058 \ No newline at end of file diff --git a/evmcc/test/jump/fac.ethel b/evmcc/test/jump/fac.ethel deleted file mode 100644 index 8bfe94dd6..000000000 --- a/evmcc/test/jump/fac.ethel +++ /dev/null @@ -1,5 +0,0 @@ -let fac n = - if n == 0 then 1 - else n * fac (n-1) - -return fac 60 \ No newline at end of file diff --git a/evmcc/test/jump/fac.evm b/evmcc/test/jump/fac.evm deleted file mode 100644 index 04cd3e4f4..000000000 --- a/evmcc/test/jump/fac.evm +++ /dev/null @@ -1 +0,0 @@ -6007603c6010585d60005460206000f26000810e6026596020600182036010585d8102602858600190509058 \ No newline at end of file diff --git a/evmcc/test/jump/fac_tail.ethel b/evmcc/test/jump/fac_tail.ethel deleted file mode 100644 index 9ce5ecac7..000000000 --- a/evmcc/test/jump/fac_tail.ethel +++ /dev/null @@ -1,5 +0,0 @@ -let fac a n = - if n == 0 then a - else fac (a*n) (n-1) - -return fac 1 60 \ No newline at end of file diff --git a/evmcc/test/jump/fac_tail.evm b/evmcc/test/jump/fac_tail.evm deleted file mode 100644 index 8384d94e4..000000000 --- a/evmcc/test/jump/fac_tail.evm +++ /dev/null @@ -1 +0,0 @@ -60096001603c6012585d60005460206000f26000810e6029596025818302600183036012585d602a5881905090509058 \ No newline at end of file diff --git a/evmcc/test/jump/fib1.ethel b/evmcc/test/jump/fib1.ethel deleted file mode 100644 index 81b869f41..000000000 --- a/evmcc/test/jump/fib1.ethel +++ /dev/null @@ -1,6 +0,0 @@ -let fib n = - if n < 3 then 1 - else fib (n-1) + fib (n-2) - -return fib 10 - diff --git a/evmcc/test/jump/fib1.evm b/evmcc/test/jump/fib1.evm deleted file mode 100644 index 5042a192f..000000000 --- a/evmcc/test/jump/fib1.evm +++ /dev/null @@ -1 +0,0 @@ -6007600a6010585d60005460206000f26003810a602f596020600282036010585d602a600183036010585d01603158600190509058 \ No newline at end of file diff --git a/evmcc/test/jump/for1.evm b/evmcc/test/jump/for1.evm deleted file mode 100644 index f8e65cbf2..000000000 --- a/evmcc/test/jump/for1.evm +++ /dev/null @@ -1 +0,0 @@ -600a60805460006080530b0f60255960a0536080530160a054600160805303608054600558 diff --git a/evmcc/test/jump/for1.lll b/evmcc/test/jump/for1.lll deleted file mode 100644 index 419fc9b54..000000000 --- a/evmcc/test/jump/for1.lll +++ /dev/null @@ -1,3 +0,0 @@ -(for [i]:10 (> @i 0) [i](- @i 1) - [j](+ @i @j) -) diff --git a/evmcc/test/jump/for2.evm b/evmcc/test/jump/for2.evm deleted file mode 100644 index 628297778..000000000 --- a/evmcc/test/jump/for2.evm +++ /dev/null @@ -1 +0,0 @@ -6000608054600a6080530a0f60255960a0536080530160a054600160805301608054600558 diff --git a/evmcc/test/jump/for2.lll b/evmcc/test/jump/for2.lll deleted file mode 100644 index de17d65ac..000000000 --- a/evmcc/test/jump/for2.lll +++ /dev/null @@ -1,3 +0,0 @@ -(for [i]:0 (< @i 10) [i](+ @i 1) - [j](+ @i @j) -) diff --git a/evmcc/test/jump/if1.ethel b/evmcc/test/jump/if1.ethel deleted file mode 100644 index 85c3e126b..000000000 --- a/evmcc/test/jump/if1.ethel +++ /dev/null @@ -1 +0,0 @@ -return if 0 then 1 else 2 \ No newline at end of file diff --git a/evmcc/test/jump/if1.evm b/evmcc/test/jump/if1.evm deleted file mode 100644 index 51fbe04bd..000000000 --- a/evmcc/test/jump/if1.evm +++ /dev/null @@ -1 +0,0 @@ -60006300000010596002630000001258600160005460206000f2 \ No newline at end of file diff --git a/evmcc/test/jump/if2.ethel b/evmcc/test/jump/if2.ethel deleted file mode 100644 index 2a58d6365..000000000 --- a/evmcc/test/jump/if2.ethel +++ /dev/null @@ -1 +0,0 @@ -return if 1 then 1 else 2 \ No newline at end of file diff --git a/evmcc/test/jump/if2.evm b/evmcc/test/jump/if2.evm deleted file mode 100644 index 6d823b374..000000000 --- a/evmcc/test/jump/if2.evm +++ /dev/null @@ -1 +0,0 @@ -60016300000010596002630000001258600160005460206000f2 \ No newline at end of file diff --git a/evmcc/test/jump/indirect1.evm b/evmcc/test/jump/indirect1.evm deleted file mode 100644 index ab6928304..000000000 --- a/evmcc/test/jump/indirect1.evm +++ /dev/null @@ -1 +0,0 @@ -600460030158005d6001600054 diff --git a/evmcc/test/jump/indirect1.lll b/evmcc/test/jump/indirect1.lll deleted file mode 100644 index 1ee7dc347..000000000 --- a/evmcc/test/jump/indirect1.lll +++ /dev/null @@ -1,13 +0,0 @@ -;; Indirect JUMP - -(asm -4 ;; 0 -3 ;; 2 -ADD ;; 4 -JUMP ;; 5 -STOP ;; 6 -JUMPDEST ;; 7 -1 -0 -MSTORE -) \ No newline at end of file diff --git a/evmcc/test/jump/indirect2.evm b/evmcc/test/jump/indirect2.evm deleted file mode 100644 index e9697eaa1..000000000 --- a/evmcc/test/jump/indirect2.evm +++ /dev/null @@ -1 +0,0 @@ -600860060158005d6001600054005d600260005400 diff --git a/evmcc/test/jump/indirect2.lll b/evmcc/test/jump/indirect2.lll deleted file mode 100644 index f2f068630..000000000 --- a/evmcc/test/jump/indirect2.lll +++ /dev/null @@ -1,19 +0,0 @@ -;; Indirect JUMP - -(asm -8 ;; 0 -6 ;; 2 -ADD ;; 4 -JUMP ;; 5 --> 14 -STOP ;; 6 -JUMPDEST ;; 7 -1 ;; 8 -0 ;; 10 -MSTORE ;; 12 -STOP ;; 13 -JUMPDEST ;; 14 -2 -0 -MSTORE -STOP -) \ No newline at end of file diff --git a/evmcc/test/jump/indirect3.evm b/evmcc/test/jump/indirect3.evm deleted file mode 100644 index 1fb0a356c..000000000 --- a/evmcc/test/jump/indirect3.evm +++ /dev/null @@ -1 +0,0 @@ -6001600460050159005d6001600054 diff --git a/evmcc/test/jump/indirect3.lll b/evmcc/test/jump/indirect3.lll deleted file mode 100644 index d6a679f9a..000000000 --- a/evmcc/test/jump/indirect3.lll +++ /dev/null @@ -1,14 +0,0 @@ -;; Indirect JUMP - -(asm -1 ;; 0 -4 ;; 2 -5 ;; 4 -ADD ;; 6 -JUMPI ;; 7 -STOP ;; 8 -JUMPDEST ;; 9 -1 -0 -MSTORE -) \ No newline at end of file diff --git a/evmcc/test/jump/indirect4.evm b/evmcc/test/jump/indirect4.evm deleted file mode 100644 index f0e31a8f4..000000000 --- a/evmcc/test/jump/indirect4.evm +++ /dev/null @@ -1 +0,0 @@ -60006007600501596001600054005d00 diff --git a/evmcc/test/jump/indirect4.lll b/evmcc/test/jump/indirect4.lll deleted file mode 100644 index 7fbe0b833..000000000 --- a/evmcc/test/jump/indirect4.lll +++ /dev/null @@ -1,15 +0,0 @@ -;; Indirect JUMP - -(asm -0 ;; 0 -7 ;; 2 -5 ;; 4 -ADD ;; 6 -JUMPI ;; 7 -1 ;; 8 -0 ;; 9 -MSTORE ;; 10 -STOP ;; 11 -JUMPDEST ;; 12 -STOP -) \ No newline at end of file diff --git a/evmcc/test/jump/jump1.evm b/evmcc/test/jump/jump1.evm deleted file mode 100644 index 0df9b4036..000000000 --- a/evmcc/test/jump/jump1.evm +++ /dev/null @@ -1 +0,0 @@ -600458006001600154 diff --git a/evmcc/test/jump/jump1.lll b/evmcc/test/jump/jump1.lll deleted file mode 100644 index 33119edb3..000000000 --- a/evmcc/test/jump/jump1.lll +++ /dev/null @@ -1,11 +0,0 @@ -;; Direct JUMP. -;; output: memory[1] == 1 - -(asm -4 ;; 0 -JUMP ;; 2 -STOP ;; 3 -1 ;; 4 -1 ;; 6 -MSTORE ;; 8 -) \ No newline at end of file diff --git a/evmcc/test/jump/jump2.evm b/evmcc/test/jump/jump2.evm deleted file mode 100644 index 35d75941d..000000000 --- a/evmcc/test/jump/jump2.evm +++ /dev/null @@ -1 +0,0 @@ -6008586001600154 diff --git a/evmcc/test/jump/jump2.lll b/evmcc/test/jump/jump2.lll deleted file mode 100644 index a70d50ecb..000000000 --- a/evmcc/test/jump/jump2.lll +++ /dev/null @@ -1,10 +0,0 @@ -;; Direct JUMP to the end of code. -;; output: memory should have size 0. - -(asm -8 ;; 0 -JUMP ;; 2 -1 ;; 3 -1 ;; 5 -MSTORE ;; 7 -) \ No newline at end of file diff --git a/evmcc/test/jump/jump3.evm b/evmcc/test/jump/jump3.evm deleted file mode 100644 index 599d4a764..000000000 --- a/evmcc/test/jump/jump3.evm +++ /dev/null @@ -1 +0,0 @@ -602a586001600154 diff --git a/evmcc/test/jump/jump3.lll b/evmcc/test/jump/jump3.lll deleted file mode 100644 index bc897e30c..000000000 --- a/evmcc/test/jump/jump3.lll +++ /dev/null @@ -1,10 +0,0 @@ -;; Direct JUMP past the end of code. -;; output: memory should have size 0. - -(asm -42 -JUMP -1 -1 -MSTORE -) \ No newline at end of file diff --git a/evmcc/test/jump/jump4.evm b/evmcc/test/jump/jump4.evm deleted file mode 100644 index 41713f43e..000000000 --- a/evmcc/test/jump/jump4.evm +++ /dev/null @@ -1 +0,0 @@ -600b6009580000600558005d6001600154 diff --git a/evmcc/test/jump/jump4.lll b/evmcc/test/jump/jump4.lll deleted file mode 100644 index 131baee2d..000000000 --- a/evmcc/test/jump/jump4.lll +++ /dev/null @@ -1,17 +0,0 @@ -;; Direct JUMP. -;; output: memory[1] = 1 - -(asm -11 ;; 0 -9 ;; 2 -JUMP ;; 4 --> 9 -STOP ;; 5 -STOP ;; 6 -5 ;; 7 -JUMP ;; 9 --> 11 -STOP ;; 10 -JUMPDEST -1 ;; 11 -1 -MSTORE -) \ No newline at end of file diff --git a/evmcc/test/jump/jump5.evm b/evmcc/test/jump/jump5.evm deleted file mode 100644 index c36d9615b..000000000 --- a/evmcc/test/jump/jump5.evm +++ /dev/null @@ -1 +0,0 @@ -6005600e585d600160015400600f5800 diff --git a/evmcc/test/jump/jump5.lll b/evmcc/test/jump/jump5.lll deleted file mode 100644 index d28b7d4ac..000000000 --- a/evmcc/test/jump/jump5.lll +++ /dev/null @@ -1,16 +0,0 @@ -;; Direct JUMP. -;; output: memory[1] = 1 - -(asm -5 ;; 0 -14 ;; 2 -JUMP ;; 4 --> 14 -JUMPDEST ;; 5 -1 ;; 6 -1 ;; 8 -MSTORE ;; 10 -STOP ;; 11 -15 ;; 12 -JUMP ;; 14 --> 5 -STOP ;; 15 -) \ No newline at end of file diff --git a/evmcc/test/jump/jump6.evm b/evmcc/test/jump/jump6.evm deleted file mode 100644 index 029db7191..000000000 --- a/evmcc/test/jump/jump6.evm +++ /dev/null @@ -1 +0,0 @@ -600358600f600d58006014600758005d6001600154005d600260025400 diff --git a/evmcc/test/jump/jump6.lll b/evmcc/test/jump/jump6.lll deleted file mode 100644 index 1116aa663..000000000 --- a/evmcc/test/jump/jump6.lll +++ /dev/null @@ -1,32 +0,0 @@ -;; Direct JUMP. -;; output: memory[1] = 1 - -;; 0, 2 --> 3 .. 7 --> 13 -*-> 15 .. 19 - -(asm -3 ;; 0 -JUMP ;; 2 - -15 ;; 3 <- start -13 ;; 5 -JUMP ;; 7 <- b -STOP ;; 8 - -20 ;; 9 -7 ;; 11 - -JUMP ;; 13 <- a -STOP ;; 14 - -JUMPDEST ;; 15 <- c -1 ;; 16 -1 ;; 18 -MSTORE ;; 19 -STOP ;; 20 - -JUMPDEST ;; 21 <- d -2 ;; 22 -2 ;; 24 -MSTORE ;; 26 -STOP ;; 27 -) \ No newline at end of file diff --git a/evmcc/test/jump/jumpi_at_the_end.evm b/evmcc/test/jump/jumpi_at_the_end.evm deleted file mode 100644 index 2d7411761..000000000 --- a/evmcc/test/jump/jumpi_at_the_end.evm +++ /dev/null @@ -1 +0,0 @@ -600a6000545d6000536001900380600054600659 diff --git a/evmcc/test/jump/jumpi_at_the_end.lll b/evmcc/test/jump/jumpi_at_the_end.lll deleted file mode 100644 index 263ada6a7..000000000 --- a/evmcc/test/jump/jumpi_at_the_end.lll +++ /dev/null @@ -1 +0,0 @@ -(asm 10 0 MSTORE JUMPDEST 0 MLOAD 1 SWAP1 SUB DUP1 0 MSTORE 6 JUMPI) \ No newline at end of file diff --git a/evmcc/test/jump/loop1.evm b/evmcc/test/jump/loop1.evm deleted file mode 100644 index 7724d6308..000000000 --- a/evmcc/test/jump/loop1.evm +++ /dev/null @@ -1 +0,0 @@ -600a600181038060025960005460015460025400 diff --git a/evmcc/test/jump/loop1.lll b/evmcc/test/jump/loop1.lll deleted file mode 100644 index 0044ec1fb..000000000 --- a/evmcc/test/jump/loop1.lll +++ /dev/null @@ -1,27 +0,0 @@ -;; Produces 1 2 3 4 5 6 7 8 9 10 on the stack and exits - -(asm -10 - -;; 2 -1 -DUP2 -SUB -DUP1 -2 -JUMPI - -;; stack = 1 2 3 4 5 6 7 8 9 10 -0 -MSTORE -1 -MSTORE -2 -MSTORE -;;3 -;;MSTORE - -STOP -) - - diff --git a/evmcc/test/jump/loop2.evm b/evmcc/test/jump/loop2.evm deleted file mode 100644 index faffa4e5b..000000000 --- a/evmcc/test/jump/loop2.evm +++ /dev/null @@ -1 +0,0 @@ -600a80600190038060025960005460015460025400 diff --git a/evmcc/test/jump/loop2.lll b/evmcc/test/jump/loop2.lll deleted file mode 100644 index 9996c52ba..000000000 --- a/evmcc/test/jump/loop2.lll +++ /dev/null @@ -1,28 +0,0 @@ -;; Produces 1 2 3 4 5 6 7 8 9 10 on the stack and exits - -(asm -10 - -;; 2 -DUP1 -1 -SWAP1 -SUB -DUP1 -2 -JUMPI - -;; stack = 1 2 3 4 5 6 7 8 9 10 -0 -MSTORE -1 -MSTORE -2 -MSTORE -;;3 -;;MSTORE - -STOP -) - - diff --git a/evmcc/test/jump/rec1.ethel b/evmcc/test/jump/rec1.ethel deleted file mode 100644 index f83c8e81e..000000000 --- a/evmcc/test/jump/rec1.ethel +++ /dev/null @@ -1,4 +0,0 @@ -let f n = - if n == 0 then 2 else f (n-1) - -return f 10 diff --git a/evmcc/test/jump/rec1.evm b/evmcc/test/jump/rec1.evm deleted file mode 100644 index 2ae62aff6..000000000 --- a/evmcc/test/jump/rec1.evm +++ /dev/null @@ -1 +0,0 @@ -6007600a6010585d60005460206000f26000810e6024596020600182036010585d602658600290509058 \ No newline at end of file diff --git a/evmcc/test/jump/when1.asm b/evmcc/test/jump/when1.asm deleted file mode 100644 index 01d41c266..000000000 --- a/evmcc/test/jump/when1.asm +++ /dev/null @@ -1,10 +0,0 @@ -.code: - PUSH 1 - NOT - PUSH [tag0] - JUMPI - PUSH 13 - PUSH 128 - MSTORE -tag0: - diff --git a/evmcc/test/jump/when1.evm b/evmcc/test/jump/when1.evm deleted file mode 100644 index 303b02623..000000000 --- a/evmcc/test/jump/when1.evm +++ /dev/null @@ -1 +0,0 @@ -60010f600b59600d608054 diff --git a/evmcc/test/jump/when1.lll b/evmcc/test/jump/when1.lll deleted file mode 100644 index 990a6e64a..000000000 --- a/evmcc/test/jump/when1.lll +++ /dev/null @@ -1,2 +0,0 @@ -(when (> 1 0) [i] 13) - \ No newline at end of file diff --git a/evmcc/test/kv.evm b/evmcc/test/kv.evm deleted file mode 100644 index 55141ea59..000000000 --- a/evmcc/test/kv.evm +++ /dev/null @@ -1 +0,0 @@ -33604557602a8060106000396000f200604556330e0f602a59366080530a0f602a59602060805301356080533557604060805301608054600958 diff --git a/evmcc/test/kv.lll b/evmcc/test/kv.lll deleted file mode 100644 index c62d9fa70..000000000 --- a/evmcc/test/kv.lll +++ /dev/null @@ -1,10 +0,0 @@ -{ - [[69]] (caller) - (return 0 (lll - (when (= (caller) @@69) - (for {} (< @i (calldatasize)) [i](+ @i 64) - [[ (calldataload @i) ]] (calldataload (+ @i 32)) - ) - ) - 0)) -} diff --git a/evmcc/test/mem/byte.evm b/evmcc/test/mem/byte.evm deleted file mode 100644 index ab63431ee..000000000 --- a/evmcc/test/mem/byte.evm +++ /dev/null @@ -1 +0,0 @@ -7f112233445566778899001122334455667788990011223344556677889900aabb6000137f112233445566778899001122334455667788990011223344556677889900aabb6001137f112233445566778899001122334455667788990011223344556677889900aabb6002137f112233445566778899001122334455667788990011223344556677889900aabb6003137f112233445566778899001122334455667788990011223344556677889900aabb6004137f112233445566778899001122334455667788990011223344556677889900aabb6005137f112233445566778899001122334455667788990011223344556677889900aabb6006137f112233445566778899001122334455667788990011223344556677889900aabb6007137f112233445566778899001122334455667788990011223344556677889900aabb6008137f112233445566778899001122334455667788990011223344556677889900aabb6009137f112233445566778899001122334455667788990011223344556677889900aabb600a137f112233445566778899001122334455667788990011223344556677889900aabb600b137f112233445566778899001122334455667788990011223344556677889900aabb600c137f112233445566778899001122334455667788990011223344556677889900aabb600d137f112233445566778899001122334455667788990011223344556677889900aabb600e137f112233445566778899001122334455667788990011223344556677889900aabb600f137f112233445566778899001122334455667788990011223344556677889900aabb6010137f112233445566778899001122334455667788990011223344556677889900aabb6011137f112233445566778899001122334455667788990011223344556677889900aabb6012137f112233445566778899001122334455667788990011223344556677889900aabb6013137f112233445566778899001122334455667788990011223344556677889900aabb6014137f112233445566778899001122334455667788990011223344556677889900aabb6015137f112233445566778899001122334455667788990011223344556677889900aabb6016137f112233445566778899001122334455667788990011223344556677889900aabb6017137f112233445566778899001122334455667788990011223344556677889900aabb6018137f112233445566778899001122334455667788990011223344556677889900aabb6019137f112233445566778899001122334455667788990011223344556677889900aabb601a137f112233445566778899001122334455667788990011223344556677889900aabb601b137f112233445566778899001122334455667788990011223344556677889900aabb601c137f112233445566778899001122334455667788990011223344556677889900aabb601d137f112233445566778899001122334455667788990011223344556677889900aabb601e137f112233445566778899001122334455667788990011223344556677889900aabb601f137f112233445566778899001122334455667788990011223344556677889900aabb6020137f112233445566778899001122334455667788990011223344556677889900aabb6107de13 diff --git a/evmcc/test/mem/byte.lll b/evmcc/test/mem/byte.lll deleted file mode 100644 index 95b0f99dc..000000000 --- a/evmcc/test/mem/byte.lll +++ /dev/null @@ -1,105 +0,0 @@ - -(asm -0x112233445566778899001122334455667788990011223344556677889900aabb -0 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -1 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -2 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -3 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -4 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -5 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -6 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -7 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -8 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -9 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -10 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -11 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -12 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -13 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -14 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -15 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -16 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -17 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -18 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -19 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -20 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -21 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -22 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -23 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -24 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -25 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -26 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -27 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -28 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -29 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -30 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -31 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -32 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -2014 -BYTE -) \ No newline at end of file diff --git a/evmcc/test/mem/mem2.evm b/evmcc/test/mem/mem2.evm deleted file mode 100644 index 49cc6e8b1..000000000 --- a/evmcc/test/mem/mem2.evm +++ /dev/null @@ -1 +0,0 @@ -6001610d805b01556504409585d6df620493e05462061a80535b01 diff --git a/evmcc/test/mem/mem2.lll b/evmcc/test/mem/mem2.lll deleted file mode 100644 index 5345ee47c..000000000 --- a/evmcc/test/mem/mem2.lll +++ /dev/null @@ -1,15 +0,0 @@ - -(asm ;; [] -1 -3456 -MSIZE -ADD -MSTORE8 ;; [02] -4675432994527 -300000 -MSTORE -400000 -MLOAD -MSIZE -ADD -) \ No newline at end of file diff --git a/evmcc/test/mem/memtest1.evm b/evmcc/test/mem/memtest1.evm deleted file mode 100644 index 0506bf928..000000000 --- a/evmcc/test/mem/memtest1.evm +++ /dev/null @@ -1 +0,0 @@ -6002600055600360015560005360015301600254 diff --git a/evmcc/test/mem/memtest1.lll b/evmcc/test/mem/memtest1.lll deleted file mode 100644 index 4b4389ad8..000000000 --- a/evmcc/test/mem/memtest1.lll +++ /dev/null @@ -1,18 +0,0 @@ - -(asm ;; [] -2 -0 -MSTORE8 ;; [02] -3 -1 -MSTORE8 ;; [02 03] -0 -MLOAD ;; [2 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] -1 -MLOAD ;; [2 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 - ;; 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] -ADD -2 -MSTORE ;; [2 3 5 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 - ;; 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] -) \ No newline at end of file diff --git a/evmcc/test/mem/mstore1.evm b/evmcc/test/mem/mstore1.evm deleted file mode 100644 index ba6141ab1..000000000 --- a/evmcc/test/mem/mstore1.evm +++ /dev/null @@ -1 +0,0 @@ -6001600054 diff --git a/evmcc/test/mem/mstore1.lll b/evmcc/test/mem/mstore1.lll deleted file mode 100644 index 2d2ca32b5..000000000 --- a/evmcc/test/mem/mstore1.lll +++ /dev/null @@ -1,6 +0,0 @@ - -(asm ;; [] -1 -0 -MSTORE ;; [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1] -) \ No newline at end of file diff --git a/evmcc/test/ret/return1.evm b/evmcc/test/ret/return1.evm deleted file mode 100644 index 8092cb007..000000000 --- a/evmcc/test/ret/return1.evm +++ /dev/null @@ -1 +0,0 @@ -600160805460006080530b601b59600160005460206000f2602a58602760005460206000f26002608054 diff --git a/evmcc/test/ret/return1.lll b/evmcc/test/ret/return1.lll deleted file mode 100644 index 159d15ca3..000000000 --- a/evmcc/test/ret/return1.lll +++ /dev/null @@ -1,6 +0,0 @@ -;; code should return 39 -;; i should remain 1 -{ - [i] 1 - ( if (> @i 0) { (return 39) [i] 2 } (return 1) ) -} \ No newline at end of file diff --git a/evmcc/test/ret/return2.evm b/evmcc/test/ret/return2.evm deleted file mode 100644 index e29da7664..000000000 --- a/evmcc/test/ret/return2.evm +++ /dev/null @@ -1 +0,0 @@ -6001620f4240f2 diff --git a/evmcc/test/ret/return2.lll b/evmcc/test/ret/return2.lll deleted file mode 100644 index f5ee68f6e..000000000 --- a/evmcc/test/ret/return2.lll +++ /dev/null @@ -1,6 +0,0 @@ - -(asm -1 -1000000 -RETURN ;; return 1 byte from index 1M -) \ No newline at end of file diff --git a/evmcc/test/ret/return_test.evm b/evmcc/test/ret/return_test.evm deleted file mode 100644 index 977cf7c19..000000000 --- a/evmcc/test/ret/return_test.evm +++ /dev/null @@ -1 +0,0 @@ -60016064546002608454600360a45460606064f2 diff --git a/evmcc/test/ret/return_test.lll b/evmcc/test/ret/return_test.lll deleted file mode 100644 index c87a2d812..000000000 --- a/evmcc/test/ret/return_test.lll +++ /dev/null @@ -1,15 +0,0 @@ - -(asm -1 -100 -MSTORE -2 -132 -MSTORE -3 -164 -MSTORE -96 -100 -RETURN -) \ No newline at end of file diff --git a/evmcc/test/stack/oos.evm b/evmcc/test/stack/oos.evm deleted file mode 100644 index ea2f1c890..000000000 --- a/evmcc/test/stack/oos.evm +++ /dev/null @@ -1 +0,0 @@ -60018194505050509150 diff --git a/evmcc/test/stack/oos.lll b/evmcc/test/stack/oos.lll deleted file mode 100644 index 5394b06ba..000000000 --- a/evmcc/test/stack/oos.lll +++ /dev/null @@ -1,11 +0,0 @@ -(asm ;; x . v y z -1 ;; 1 x . v y z -DUP2 ;; x 1 x . v y z -SWAP5 ;; y 1 x . v x z -POP ;; 1 x . v x z -POP ;; x . v x z -POP ;; . v x z -POP ;; v x z -SWAP2 ;; z x v -POP ;; x v -) diff --git a/evmcc/test/stack/push_test.evm b/evmcc/test/stack/push_test.evm deleted file mode 100644 index d624cee1d..000000000 --- a/evmcc/test/stack/push_test.evm +++ /dev/null @@ -1 +0,0 @@ -60656107d26204a0c763026921f4640bc5588eb165372d0f1dca6e661ba1d901961c71670c55f7bc23038e3868056bc75e2d630fffff69021e19e0c9bab24000016a085d1c6e8050f0ea1c71bd6b0688be36543f3c36e638e37a6c03d41f73d55d0d482ae55555376dc76810d0fe03c91964d31c71c6f46e615dd0360c07d931663b14e38e38b16f2da3f99955a3adcf27ebb1caaaaaaa6e7014ccba6a8bb1ed35bd86bf065c71c71c2b7109491c5d4781b79c9009de6bfb8e38e38de8720414a0f6fdec81304d4c563e740bffffffffa573118427b3b4a05bc8a8a4de8459868000000000017406eb15e7331e727940d4ac54b7cdca1c71c71c71bd750567a91c9fefc96ebaa626a22f98c5e638e38e38e37a76032abd16c5b68006e15d5aa307e383f4e55555555555377701a6427bdc4f0d58eab5f48a3ec67f64e21c71c71c71c6f478080dd0a0c9b9ff2c2a0c740b06853a0a980ee38e38e38e38b17903c679cb5e8f2f9cb3b5d6652b0e7334f746faaaaaaaaaaaaa6e7a01b873815917ebb2bf3b890a1af495d6235bae3c71c71c71c71c2b7b07ae4cca96e1a55dfa49c85ad3c3e60e426b92fb8e38e38e38e38de87c036018bf074e292bcc7d6c8bea0f9699443046178bffffffffffffffa57d0e7d34c64a9c85d4460dbbca87196b61618a4bd2168000000000000000017e05b901f48a5b994d6572502bc4ea43140486666416aa1c71c71c71c71c71bd7f047889870c178fc477414ea231d70467a388fffe31b4e638e38e38e38e38e37a diff --git a/evmcc/test/stack/push_test.lll b/evmcc/test/stack/push_test.lll deleted file mode 100644 index 832daaec1..000000000 --- a/evmcc/test/stack/push_test.lll +++ /dev/null @@ -1,35 +0,0 @@ - -(asm -101 ;; PUSH1 -2002 ;; PUSH2 -303303 ;; PUSH3 -40444404 ;; PUSH4 -50555555505 ;; PUSH5 -60666666666606 -7777777777777777 -888888888888888888 -99999999999999999999 -10000000000000000000001 -10111111111111111111111101 -2022222222222222222222222202 -303333333333333333333333333303 -4044444444444444444444444444444404 -505555555555555555555555555555555505 -60666666666666666666666666666666666606 -7077777777777777777777777777777777777707 -808888888888888888888888888888888888888808 -90999999999999999999999999999999999999999909 -100000000000000000000000000000000000000000000001 -10111111111111111111111111111111111111111111111101 -2022222222222222222222222222222222222222222222222202 -303333333333333333333333333333333333333333333333333303 -40444444444444444444444444444444444444444444444444444404 -50555555555555555555555555555555555555555555555555555555505 -6066666666666666666666666666666666666666666666666666666666606 -707777777777777777777777777777777777777777777777777777777777707 -808888888888888888888888888888888888888888888888888888888888888808 -90999999999999999999999999999999999999999999999999999999999999999909 -100000000000000000000000000000000000000000000000000000000000000000000001 -10111111111111111111111111111111111111111111111111111111111111111111111101 -2022222222222222222222222222222222222222222222222222222222222222222222222202 ;; PUSH32 -) \ No newline at end of file diff --git a/evmcc/test/stack/stack_test.evm b/evmcc/test/stack/stack_test.evm deleted file mode 100644 index 02417c967..000000000 --- a/evmcc/test/stack/stack_test.evm +++ /dev/null @@ -1 +0,0 @@ -65372d0f1dca6e661925338e3e5c2b808280848184505050505050506104576108ae81819290 diff --git a/evmcc/test/stack/stack_test.lll b/evmcc/test/stack/stack_test.lll deleted file mode 100644 index fdf83594c..000000000 --- a/evmcc/test/stack/stack_test.lll +++ /dev/null @@ -1,8 +0,0 @@ - -(asm -123 -SSTORE -SLOAD -123 -SUB -) \ No newline at end of file diff --git a/evmcc/test/stack/stackjump.evm b/evmcc/test/stack/stackjump.evm deleted file mode 100644 index baddec42e..000000000 --- a/evmcc/test/stack/stackjump.evm +++ /dev/null @@ -1 +0,0 @@ -600460066009601358600a036000545b6000f260005401600958 \ No newline at end of file diff --git a/evmcc/test/stack/stackjump.lll b/evmcc/test/stack/stackjump.lll deleted file mode 100644 index f5da5e733..000000000 --- a/evmcc/test/stack/stackjump.lll +++ /dev/null @@ -1,3 +0,0 @@ -(asm -0x4 0x6 0x9 0x13 JUMP 0xa SUB 0x0 MSTORE MSIZE 0x0 RETURN 0x0 MSTORE ADD 0x9 JUMP -) diff --git a/evmcc/test/stack/swap.evm b/evmcc/test/stack/swap.evm deleted file mode 100644 index d17f0ee09..000000000 --- a/evmcc/test/stack/swap.evm +++ /dev/null @@ -1 +0,0 @@ -600560026001600c59505000906001601559505000036000546001601ff2 diff --git a/evmcc/test/stack/swap.lll b/evmcc/test/stack/swap.lll deleted file mode 100644 index 90dee585d..000000000 --- a/evmcc/test/stack/swap.lll +++ /dev/null @@ -1,31 +0,0 @@ -(asm -5 ;; 0 -2 ;; 2 -1 ;; 4 -12 ;; 6 -JUMPI ;; 8 - -POP ;; 9 -POP ;; 10 -STOP ;; 11 - -;; stack = 2,1 -SWAP1 ;; 12 -1 ;; 13 -21 ;; 15 -JUMPI ;; 17 - -POP ;; 18 -POP ;; 19 -STOP ;; 20 - -;; stack = 1,2 -SUB ;; 21 -0 -MSTORE -1 -31 -RETURN ;; returns 03 -) - - diff --git a/evmcc/test/stack/swapswap.evm b/evmcc/test/stack/swapswap.evm deleted file mode 100644 index fb4f1bf75..000000000 --- a/evmcc/test/stack/swapswap.evm +++ /dev/null @@ -1 +0,0 @@ -600260056001600c5950500090906001601659505000036000546001601ff2 diff --git a/evmcc/test/stack/swapswap.lll b/evmcc/test/stack/swapswap.lll deleted file mode 100644 index 1fedf726e..000000000 --- a/evmcc/test/stack/swapswap.lll +++ /dev/null @@ -1,32 +0,0 @@ -(asm -2 ;; 0 -5 ;; 2 -1 ;; 4 -12 ;; 6 -JUMPI ;; 8 - -POP ;; 9 -POP ;; 10 -STOP ;; 11 - -;; stack = 2,1 -SWAP1 ;; 12 -SWAP1 ;; 13 -1 ;; 14 -22 ;; 16 -JUMPI ;; 18 - -POP ;; 19 -POP ;; 20 -STOP ;; 21 - -;; stack = 2,1 -SUB ;; 22 -0 -MSTORE -1 -31 -RETURN ;; returns 03 -) - - diff --git a/evmcc/test/stack/test.evm b/evmcc/test/stack/test.evm deleted file mode 100644 index ea2f1c890..000000000 --- a/evmcc/test/stack/test.evm +++ /dev/null @@ -1 +0,0 @@ -60018194505050509150 diff --git a/evmcc/test/vmtests/vmArithPerformanceTest.json b/evmcc/test/vmtests/vmArithPerformanceTest.json deleted file mode 100644 index d9017517f..000000000 --- a/evmcc/test/vmtests/vmArithPerformanceTest.json +++ /dev/null @@ -1,260 +0,0 @@ -{ - "arith-1" : { - "callcreates" : [ ], - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "256", - "currentGasLimit" : "10000000", - "currentNumber" : "0", - "currentTimestamp" : "1", - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "exec" : { - "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x600a60005260005160105760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600556", - "data" : "0x", - "gas" : "1000000", - "gasPrice" : "100000000000000", - "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "value" : "1000000000000000000" - }, - "gas" : "999538", - "out" : "0x0000000000000000000000000000000000000000000000000000001b9c636491", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x600a60005260005160105760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600556", - "nonce" : "0", - "storage" : { - } - } - }, - "pre" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x600a60005260005160105760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600556", - "nonce" : "0", - "storage" : { } - } - } - } - - , - - "arith-2" : { - "callcreates" : [ ], - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "256", - "currentGasLimit" : "10000000", - "currentNumber" : "0", - "currentTimestamp" : "1", - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "exec" : { - "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x606460005260005160105760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600556", - "data" : "0x", - "gas" : "1000000", - "gasPrice" : "100000000000000", - "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "value" : "1000000000000000000" - }, - "gas" : "995488", - "out" : "0x0000000000000000000000000000000000000000000000000000001b9c636491", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x606460005260005160105760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600556", - "nonce" : "0", - "storage" : { - } - } - }, - "pre" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x606460005260005160105760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600556", - "nonce" : "0", - "storage" : { } - } - } - } - - , - - "arith-3" : { - "callcreates" : [ ], - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "256", - "currentGasLimit" : "10000000", - "currentNumber" : "0", - "currentTimestamp" : "1", - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "exec" : { - "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x6103e860005260005160115760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600656", - "data" : "0x", - "gas" : "1000000", - "gasPrice" : "100000000000000", - "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "value" : "1000000000000000000" - }, - "gas" : "954988", - "out" : "0x0000000000000000000000000000000000000000000000000000001b9c636491", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x6103e860005260005160115760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600656", - "nonce" : "0", - "storage" : { - } - } - }, - "pre" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x6103e860005260005160115760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600656", - "nonce" : "0", - "storage" : { } - } - } - } - - , - - "arith-4" : { - "callcreates" : [ ], - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "256", - "currentGasLimit" : "10000000", - "currentNumber" : "0", - "currentTimestamp" : "1", - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "exec" : { - "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x61271060005260005160115760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600656", - "data" : "0x", - "gas" : "1000000", - "gasPrice" : "100000000000000", - "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "value" : "1000000000000000000" - }, - "gas" : "549988", - "out" : "0x0000000000000000000000000000000000000000000000000000001b9c636491", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x61271060005260005160115760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600656", - "nonce" : "0", - "storage" : { - } - } - }, - "pre" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x61271060005260005160115760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600656", - "nonce" : "0", - "storage" : { } - } - } - } - - - , - - - "arith-5" : { - "callcreates" : [ ], - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "256", - "currentGasLimit" : "10000000", - "currentNumber" : "0", - "currentTimestamp" : "1", - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "exec" : { - "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x620186a060005260005160125760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600756", - "data" : "0x", - "gas" : "10000000", - "gasPrice" : "100000000000000", - "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "value" : "1000000000000000000" - }, - "gas" : "5499988", - "out" : "0x0000000000000000000000000000000000000000000000000000001b9c636491", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x620186a060005260005160125760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600756", - "nonce" : "0", - "storage" : { - } - } - }, - "pre" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x620186a060005260005160125760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600756", - "nonce" : "0", - "storage" : { } - } - } - } - -, - - "arith-6" : { - "callcreates" : [ ], - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "256", - "currentGasLimit" : "100000000", - "currentNumber" : "0", - "currentTimestamp" : "1", - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "exec" : { - "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x620f424060005260005160125760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600756", - "data" : "0x", - "gas" : "100000000", - "gasPrice" : "100000000000000", - "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "value" : "1000000000000000000" - }, - "gas" : "54999988", - "out" : "0x0000000000000000000000000000000000000000000000000000001b9c636491", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x620f424060005260005160125760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600756", - "nonce" : "0", - "storage" : { - } - } - }, - "pre" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x620f424060005260005160125760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600756", - "nonce" : "0", - "storage" : { } - } - } - } - -} diff --git a/evmcc/test/vmtests/vmPerformanceTest.json b/evmcc/test/vmtests/vmPerformanceTest.json deleted file mode 100644 index 604e45993..000000000 --- a/evmcc/test/vmtests/vmPerformanceTest.json +++ /dev/null @@ -1,214 +0,0 @@ -{ - "mulmodloop" : { - "callcreates" : [ ], - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "256", - "currentGasLimit" : "10000000", - "currentNumber" : "0", - "currentTimestamp" : "1", - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "exec" : { - "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x60015b68010000000000000000908060010109600356", - "data" : "0x", - "gas" : "10000000", - "gasPrice" : "100000000000000", - "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "value" : "1000000000000000000" - }, - "gas" : "0", - "out" : "0x0", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x60015b68010000000000000000908060010109600356", - "nonce" : "0", - "storage" : { - } - } - }, - "pre" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x60015b68010000000000000000908060010109600356", - "nonce" : "0", - "storage" : { } - } - } - }, - - - "for-1e06" : { - "callcreates" : [ ], - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "256", - "currentGasLimit" : "100000000", - "currentNumber" : "0", - "currentTimestamp" : "1", - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "exec" : { - "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x620f42406080525b6000608051111560285760a0516080510160a0526001608051036080526007565b", - "data" : "0x", - "gas" : "30000000", - "gasPrice" : "100000000000000", - "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "value" : "1000000000000000000" - }, - "gas" : "6999982", - "out" : "0x00", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x620f42406080525b6000608051111560285760a0516080510160a0526001608051036080526007565b", - "nonce" : "0", - "storage" : { - } - } - }, - "pre" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x620f42406080525b6000608051111560285760a0516080510160a0526001608051036080526007565b", - "nonce" : "0", - "storage" : { } - } - } - }, - - "fib25" : { - "callcreates" : [ - ], - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "256", - "currentGasLimit" : "100000000", - "currentNumber" : "0", - "currentTimestamp" : "1", - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "exec" : { - "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x6007601e6010565b60005260206000f25b600381106030576021600282036010565b602b600183036010565b016033565b60015b90509056", - "data" : "0x", - "gas" : "40000000", - "gasPrice" : "100000000000000", - "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "value" : "1000000000000000000" - }, - "gas" : "5886377", - "out" : "0x00000000000000000000000000000000000000000000000000000000000cb228", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x6007601e6010565b60005260206000f25b600381106030576021600282036010565b602b600183036010565b016033565b60015b90509056", - "nonce" : "0", - "storage" : { - } - } - }, - "pre" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x6007601e6010565b60005260206000f25b600381106030576021600282036010565b602b600183036010565b016033565b60015b90509056", - "nonce" : "0", - "storage" : { - } - } - } - }, - - "ackermann37" : { - "callcreates" : [ - ], - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "256", - "currentGasLimit" : "20000000", - "currentNumber" : "0", - "currentTimestamp" : "1", - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "exec" : { - "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x6009600360076012565b60005260206000f25b60008214604a5760008114603957603560018303603184600185036012565b6012565b6046565b60456001830360016012565b5b604f565b600181015b905090509056", - "data" : "0x", - "gas" : "20000000", - "gasPrice" : "100000000000000", - "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "value" : "1000000000000000000" - }, - "gas" : "913456", - "out" : "0x00000000000000000000000000000000000000000000000000000000000003fd", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x6009600360076012565b60005260206000f25b60008214604a5760008114603957603560018303603184600185036012565b6012565b6046565b60456001830360016012565b5b604f565b600181015b905090509056", - "nonce" : "0", - "storage" : { - } - } - }, - "pre" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x6009600360076012565b60005260206000f25b60008214604a5760008114603957603560018303603184600185036012565b6012565b6046565b60456001830360016012565b5b604f565b600181015b905090509056", - "nonce" : "0", - "storage" : { - } - } - } - }, - - "jumptable100" : { - "callcreates" : [ - ], - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "256", - "currentGasLimit" : "10000000", - "currentNumber" : "0", - "currentTimestamp" : "1", - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "exec" : { - "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x6103e85b60019003806000146104605761001a600160005256005b610025600260005256005b610030600360005256005b61003b600460005256005b610046600560005256005b610051600660005256005b61005c600760005256005b610067600860005256005b610072600960005256005b61007d600a60005256005b610088600b60005256005b610093600c60005256005b61009e600d60005256005b6100a9600e60005256005b6100b4600f60005256005b6100bf601060005256005b6100ca601160005256005b6100d5601260005256005b6100e0601360005256005b6100eb601460005256005b6100f6601560005256005b610101601660005256005b61010c601760005256005b610117601860005256005b610122601960005256005b61012d601a60005256005b610138601b60005256005b610143601c60005256005b61014e601d60005256005b610159601e60005256005b610164601f60005256005b61016f602060005256005b61017a602160005256005b610185602260005256005b610190602360005256005b61019b602460005256005b6101a6602560005256005b6101b1602660005256005b6101bc602760005256005b6101c7602860005256005b6101d2602960005256005b6101dd602a60005256005b6101e8602b60005256005b6101f3602c60005256005b6101fe602d60005256005b610209602e60005256005b610214602f60005256005b61021f603060005256005b61022a603160005256005b610235603260005256005b610240603360005256005b61024b603460005256005b610256603560005256005b610261603660005256005b61026c603760005256005b610277603860005256005b610282603960005256005b61028d603a60005256005b610298603b60005256005b6102a3603c60005256005b6102ae603d60005256005b6102b9603e60005256005b6102c4603f60005256005b6102cf604060005256005b6102da604160005256005b6102e5604260005256005b6102f0604360005256005b6102fb604460005256005b610306604560005256005b610311604660005256005b61031c604760005256005b610327604860005256005b610332604960005256005b61033d604a60005256005b610348604b60005256005b610353604c60005256005b61035e604d60005256005b610369604e60005256005b610374604f60005256005b61037f605060005256005b61038a605160005256005b610395605260005256005b6103a0605360005256005b6103ab605460005256005b6103b6605560005256005b6103c1605660005256005b6103cc605760005256005b6103d7605860005256005b6103e2605960005256005b6103ed605a60005256005b6103f8605b60005256005b610403605c60005256005b61040e605d60005256005b610419605e60005256005b610424605f60005256005b61042f606060005256005b61043a606160005256005b610445606260005256005b610450606360005256005b61045b606460005256005b610003565b60206000f2", - "data" : "0x", - "gas" : "1000000", - "gasPrice" : "100000000000000", - "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "value" : "1000000000000000000" - }, - "gas" : "389596", - "out" : "0x0000000000000000000000000000000000000000000000000000000000000064", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x6103e85b60019003806000146104605761001a600160005256005b610025600260005256005b610030600360005256005b61003b600460005256005b610046600560005256005b610051600660005256005b61005c600760005256005b610067600860005256005b610072600960005256005b61007d600a60005256005b610088600b60005256005b610093600c60005256005b61009e600d60005256005b6100a9600e60005256005b6100b4600f60005256005b6100bf601060005256005b6100ca601160005256005b6100d5601260005256005b6100e0601360005256005b6100eb601460005256005b6100f6601560005256005b610101601660005256005b61010c601760005256005b610117601860005256005b610122601960005256005b61012d601a60005256005b610138601b60005256005b610143601c60005256005b61014e601d60005256005b610159601e60005256005b610164601f60005256005b61016f602060005256005b61017a602160005256005b610185602260005256005b610190602360005256005b61019b602460005256005b6101a6602560005256005b6101b1602660005256005b6101bc602760005256005b6101c7602860005256005b6101d2602960005256005b6101dd602a60005256005b6101e8602b60005256005b6101f3602c60005256005b6101fe602d60005256005b610209602e60005256005b610214602f60005256005b61021f603060005256005b61022a603160005256005b610235603260005256005b610240603360005256005b61024b603460005256005b610256603560005256005b610261603660005256005b61026c603760005256005b610277603860005256005b610282603960005256005b61028d603a60005256005b610298603b60005256005b6102a3603c60005256005b6102ae603d60005256005b6102b9603e60005256005b6102c4603f60005256005b6102cf604060005256005b6102da604160005256005b6102e5604260005256005b6102f0604360005256005b6102fb604460005256005b610306604560005256005b610311604660005256005b61031c604760005256005b610327604860005256005b610332604960005256005b61033d604a60005256005b610348604b60005256005b610353604c60005256005b61035e604d60005256005b610369604e60005256005b610374604f60005256005b61037f605060005256005b61038a605160005256005b610395605260005256005b6103a0605360005256005b6103ab605460005256005b6103b6605560005256005b6103c1605660005256005b6103cc605760005256005b6103d7605860005256005b6103e2605960005256005b6103ed605a60005256005b6103f8605b60005256005b610403605c60005256005b61040e605d60005256005b610419605e60005256005b610424605f60005256005b61042f606060005256005b61043a606160005256005b610445606260005256005b610450606360005256005b61045b606460005256005b610003565b60206000f2", - "nonce" : "0", - "storage" : { - } - } - }, - "pre" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x6103e85b60019003806000146104605761001a600160005256005b610025600260005256005b610030600360005256005b61003b600460005256005b610046600560005256005b610051600660005256005b61005c600760005256005b610067600860005256005b610072600960005256005b61007d600a60005256005b610088600b60005256005b610093600c60005256005b61009e600d60005256005b6100a9600e60005256005b6100b4600f60005256005b6100bf601060005256005b6100ca601160005256005b6100d5601260005256005b6100e0601360005256005b6100eb601460005256005b6100f6601560005256005b610101601660005256005b61010c601760005256005b610117601860005256005b610122601960005256005b61012d601a60005256005b610138601b60005256005b610143601c60005256005b61014e601d60005256005b610159601e60005256005b610164601f60005256005b61016f602060005256005b61017a602160005256005b610185602260005256005b610190602360005256005b61019b602460005256005b6101a6602560005256005b6101b1602660005256005b6101bc602760005256005b6101c7602860005256005b6101d2602960005256005b6101dd602a60005256005b6101e8602b60005256005b6101f3602c60005256005b6101fe602d60005256005b610209602e60005256005b610214602f60005256005b61021f603060005256005b61022a603160005256005b610235603260005256005b610240603360005256005b61024b603460005256005b610256603560005256005b610261603660005256005b61026c603760005256005b610277603860005256005b610282603960005256005b61028d603a60005256005b610298603b60005256005b6102a3603c60005256005b6102ae603d60005256005b6102b9603e60005256005b6102c4603f60005256005b6102cf604060005256005b6102da604160005256005b6102e5604260005256005b6102f0604360005256005b6102fb604460005256005b610306604560005256005b610311604660005256005b61031c604760005256005b610327604860005256005b610332604960005256005b61033d604a60005256005b610348604b60005256005b610353604c60005256005b61035e604d60005256005b610369604e60005256005b610374604f60005256005b61037f605060005256005b61038a605160005256005b610395605260005256005b6103a0605360005256005b6103ab605460005256005b6103b6605560005256005b6103c1605660005256005b6103cc605760005256005b6103d7605860005256005b6103e2605960005256005b6103ed605a60005256005b6103f8605b60005256005b610403605c60005256005b61040e605d60005256005b610419605e60005256005b610424605f60005256005b61042f606060005256005b61043a606160005256005b610445606260005256005b610450606360005256005b61045b606460005256005b610003565b60206000f2", - "nonce" : "0", - "storage" : { - } - } - } - }, - -} diff --git a/evmcc/test/vmtests/vm_jump.json b/evmcc/test/vmtests/vm_jump.json deleted file mode 100644 index 6b63edeae..000000000 --- a/evmcc/test/vmtests/vm_jump.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "jumpi_at_the_end" : { - "callcreates" : [ ], - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "256", - "currentGasLimit" : "10000000", - "currentNumber" : "0", - "currentTimestamp" : "1", - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "exec" : { - "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "(asm 10 0 MSTORE JUMPDEST 0 MLOAD 1 SWAP1 SUB DUP1 0 MSTORE 6 JUMPI)", - "data" : "0x", - "gas" : "1000", - "gasPrice" : "100000000000000", - "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "value" : "1000000000000000000" - }, - "gas" : "895", - "out" : "0x0", - "pre" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "(asm 10 0 MSTORE JUMPDEST 0 MLOAD 1 SWAP1 SUB DUP1 0 MSTORE 6 JUMPI)", - "nonce" : "0", - "storage" : {} - } - }, - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "(asm 10 0 MSTORE JUMPDEST 0 MLOAD 1 SWAP1 SUB DUP1 0 MSTORE 6 JUMPI)", - "nonce" : "0", - "storage" : {} - } - } - } -} diff --git a/libevmjit/Arith256.cpp b/libevmjit/Arith256.cpp deleted file mode 100644 index 79a8fe79c..000000000 --- a/libevmjit/Arith256.cpp +++ /dev/null @@ -1,159 +0,0 @@ -#include "Arith256.h" -#include "Runtime.h" -#include "Type.h" - -#include - -#include - -namespace dev -{ -namespace eth -{ -namespace jit -{ - -Arith256::Arith256(llvm::IRBuilder<>& _builder) : - CompilerHelper(_builder) -{ - using namespace llvm; - - m_result = m_builder.CreateAlloca(Type::Word, nullptr, "arith.result"); - m_arg1 = m_builder.CreateAlloca(Type::Word, nullptr, "arith.arg1"); - m_arg2 = m_builder.CreateAlloca(Type::Word, nullptr, "arith.arg2"); - m_arg3 = m_builder.CreateAlloca(Type::Word, nullptr, "arith.arg3"); - - using Linkage = GlobalValue::LinkageTypes; - - llvm::Type* arg2Types[] = {Type::WordPtr, Type::WordPtr, Type::WordPtr}; - llvm::Type* arg3Types[] = {Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr}; - - m_mul = Function::Create(FunctionType::get(Type::Void, arg2Types, false), Linkage::ExternalLinkage, "arith_mul", getModule()); - m_div = Function::Create(FunctionType::get(Type::Void, arg2Types, false), Linkage::ExternalLinkage, "arith_div", getModule()); - m_mod = Function::Create(FunctionType::get(Type::Void, arg2Types, false), Linkage::ExternalLinkage, "arith_mod", getModule()); - m_sdiv = Function::Create(FunctionType::get(Type::Void, arg2Types, false), Linkage::ExternalLinkage, "arith_sdiv", getModule()); - m_smod = Function::Create(FunctionType::get(Type::Void, arg2Types, false), Linkage::ExternalLinkage, "arith_smod", getModule()); - m_addmod = Function::Create(FunctionType::get(Type::Void, arg3Types, false), Linkage::ExternalLinkage, "arith_addmod", getModule()); - m_mulmod = Function::Create(FunctionType::get(Type::Void, arg3Types, false), Linkage::ExternalLinkage, "arith_mulmod", getModule()); -} - -Arith256::~Arith256() -{} - -llvm::Value* Arith256::binaryOp(llvm::Function* _op, llvm::Value* _arg1, llvm::Value* _arg2) -{ - m_builder.CreateStore(_arg1, m_arg1); - m_builder.CreateStore(_arg2, m_arg2); - m_builder.CreateCall3(_op, m_arg1, m_arg2, m_result); - return m_builder.CreateLoad(m_result); -} - -llvm::Value* Arith256::ternaryOp(llvm::Function* _op, llvm::Value* _arg1, llvm::Value* _arg2, llvm::Value* _arg3) -{ - m_builder.CreateStore(_arg1, m_arg1); - m_builder.CreateStore(_arg2, m_arg2); - m_builder.CreateStore(_arg3, m_arg3); - m_builder.CreateCall4(_op, m_arg1, m_arg2, m_arg3, m_result); - return m_builder.CreateLoad(m_result); -} - -llvm::Value* Arith256::mul(llvm::Value* _arg1, llvm::Value* _arg2) -{ - return binaryOp(m_mul, _arg1, _arg2); -} - -llvm::Value* Arith256::div(llvm::Value* _arg1, llvm::Value* _arg2) -{ - return binaryOp(m_div, _arg1, _arg2); -} - -llvm::Value* Arith256::mod(llvm::Value* _arg1, llvm::Value* _arg2) -{ - return binaryOp(m_mod, _arg1, _arg2); -} - -llvm::Value* Arith256::sdiv(llvm::Value* _arg1, llvm::Value* _arg2) -{ - return binaryOp(m_sdiv, _arg1, _arg2); -} - -llvm::Value* Arith256::smod(llvm::Value* _arg1, llvm::Value* _arg2) -{ - return binaryOp(m_smod, _arg1, _arg2); -} - -llvm::Value* Arith256::addmod(llvm::Value* _arg1, llvm::Value* _arg2, llvm::Value* _arg3) -{ - return ternaryOp(m_addmod, _arg1, _arg2, _arg3); -} - -llvm::Value* Arith256::mulmod(llvm::Value* _arg1, llvm::Value* _arg2, llvm::Value* _arg3) -{ - return ternaryOp(m_mulmod, _arg1, _arg2, _arg3); -} - - -} -} -} - - -extern "C" -{ - - using namespace dev::eth::jit; - - EXPORT void arith_mul(i256* _arg1, i256* _arg2, i256* o_result) - { - dev::u256 arg1 = llvm2eth(*_arg1); - dev::u256 arg2 = llvm2eth(*_arg2); - *o_result = eth2llvm(arg1 * arg2); - } - - EXPORT void arith_div(i256* _arg1, i256* _arg2, i256* o_result) - { - dev::u256 arg1 = llvm2eth(*_arg1); - dev::u256 arg2 = llvm2eth(*_arg2); - *o_result = eth2llvm(arg2 == 0 ? arg2 : arg1 / arg2); - } - - EXPORT void arith_mod(i256* _arg1, i256* _arg2, i256* o_result) - { - dev::u256 arg1 = llvm2eth(*_arg1); - dev::u256 arg2 = llvm2eth(*_arg2); - *o_result = eth2llvm(arg2 == 0 ? arg2 : arg1 % arg2); - } - - EXPORT void arith_sdiv(i256* _arg1, i256* _arg2, i256* o_result) - { - dev::u256 arg1 = llvm2eth(*_arg1); - dev::u256 arg2 = llvm2eth(*_arg2); - *o_result = eth2llvm(arg2 == 0 ? arg2 : dev::s2u(dev::u2s(arg1) / dev::u2s(arg2))); - } - - EXPORT void arith_smod(i256* _arg1, i256* _arg2, i256* o_result) - { - dev::u256 arg1 = llvm2eth(*_arg1); - dev::u256 arg2 = llvm2eth(*_arg2); - *o_result = eth2llvm(arg2 == 0 ? arg2 : dev::s2u(dev::u2s(arg1) % dev::u2s(arg2))); - } - - EXPORT void arith_mulmod(i256* _arg1, i256* _arg2, i256* _arg3, i256* o_result) - { - dev::u256 arg1 = llvm2eth(*_arg1); - dev::u256 arg2 = llvm2eth(*_arg2); - dev::u256 arg3 = llvm2eth(*_arg3); - *o_result = eth2llvm(dev::u256((dev::bigint(arg1) * dev::bigint(arg2)) % arg3)); - } - - EXPORT void arith_addmod(i256* _arg1, i256* _arg2, i256* _arg3, i256* o_result) - { - dev::u256 arg1 = llvm2eth(*_arg1); - dev::u256 arg2 = llvm2eth(*_arg2); - dev::u256 arg3 = llvm2eth(*_arg3); - *o_result = eth2llvm(dev::u256((dev::bigint(arg1) + dev::bigint(arg2)) % arg3)); - } - -} - - diff --git a/libevmjit/Arith256.h b/libevmjit/Arith256.h deleted file mode 100644 index 2268d5076..000000000 --- a/libevmjit/Arith256.h +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -#include "CompilerHelper.h" - -namespace dev -{ -namespace eth -{ -namespace jit -{ - -class Arith256 : public CompilerHelper -{ -public: - Arith256(llvm::IRBuilder<>& _builder); - virtual ~Arith256(); - - llvm::Value* mul(llvm::Value* _arg1, llvm::Value* _arg2); - llvm::Value* div(llvm::Value* _arg1, llvm::Value* _arg2); - llvm::Value* mod(llvm::Value* _arg1, llvm::Value* _arg2); - llvm::Value* sdiv(llvm::Value* _arg1, llvm::Value* _arg2); - llvm::Value* smod(llvm::Value* _arg1, llvm::Value* _arg2); - llvm::Value* mulmod(llvm::Value* _arg1, llvm::Value* _arg2, llvm::Value* _arg3); - llvm::Value* addmod(llvm::Value* _arg1, llvm::Value* _arg2, llvm::Value* _arg3); - -private: - llvm::Value* binaryOp(llvm::Function* _op, llvm::Value* _arg1, llvm::Value* _arg2); - llvm::Value* ternaryOp(llvm::Function* _op, llvm::Value* _arg1, llvm::Value* _arg2, llvm::Value* _arg3); - - llvm::Function* m_mul; - llvm::Function* m_div; - llvm::Function* m_mod; - llvm::Function* m_sdiv; - llvm::Function* m_smod; - llvm::Function* m_mulmod; - llvm::Function* m_addmod; - - llvm::Value* m_arg1; - llvm::Value* m_arg2; - llvm::Value* m_arg3; - llvm::Value* m_result; -}; - - -} -} -} diff --git a/libevmjit/BasicBlock.cpp b/libevmjit/BasicBlock.cpp deleted file mode 100644 index 1cc0e13fd..000000000 --- a/libevmjit/BasicBlock.cpp +++ /dev/null @@ -1,382 +0,0 @@ - -#include "BasicBlock.h" - -#include - -#include - -#include -#include -#include -#include -#include - -#include "Type.h" - -namespace dev -{ -namespace eth -{ -namespace jit -{ - -const char* BasicBlock::NamePrefix = "Instr."; - -BasicBlock::BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder) : - m_beginInstIdx(_beginInstIdx), - m_endInstIdx(_endInstIdx), - m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {NamePrefix, std::to_string(_beginInstIdx)}, _mainFunc)), - m_stack(*this), - m_builder(_builder) -{} - -BasicBlock::BasicBlock(std::string _name, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder) : - m_beginInstIdx(0), - m_endInstIdx(0), - m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), _name, _mainFunc)), - m_stack(*this), - m_builder(_builder) -{} - -BasicBlock::LocalStack::LocalStack(BasicBlock& _owner) : - m_bblock(_owner) -{} - -void BasicBlock::LocalStack::push(llvm::Value* _value) -{ - m_bblock.m_currentStack.push_back(_value); - m_bblock.m_tosOffset += 1; -} - -llvm::Value* BasicBlock::LocalStack::pop() -{ - auto result = get(0); - - if (m_bblock.m_currentStack.size() > 0) - m_bblock.m_currentStack.pop_back(); - - m_bblock.m_tosOffset -= 1; - return result; -} - -/** - * Pushes a copy of _index-th element (tos is 0-th elem). - */ -void BasicBlock::LocalStack::dup(size_t _index) -{ - auto val = get(_index); - push(val); -} - -/** - * Swaps tos with _index-th element (tos is 0-th elem). - * _index must be > 0. - */ -void BasicBlock::LocalStack::swap(size_t _index) -{ - assert(_index > 0); - auto val = get(_index); - auto tos = get(0); - set(_index, tos); - set(0, val); -} - -std::vector::iterator BasicBlock::LocalStack::getItemIterator(size_t _index) -{ - auto& currentStack = m_bblock.m_currentStack; - if (_index < currentStack.size()) - return currentStack.end() - _index - 1; - - // Need to map more elements from the EVM stack - auto nNewItems = 1 + _index - currentStack.size(); - currentStack.insert(currentStack.begin(), nNewItems, nullptr); - - return currentStack.end() - _index - 1; -} - -llvm::Value* BasicBlock::LocalStack::get(size_t _index) -{ - auto& initialStack = m_bblock.m_initialStack; - auto itemIter = getItemIterator(_index); - - if (*itemIter == nullptr) - { - // Need to fetch a new item from the EVM stack - assert(static_cast(_index) >= m_bblock.m_tosOffset); - size_t initialIdx = _index - m_bblock.m_tosOffset; - if (initialIdx >= initialStack.size()) - { - auto nNewItems = 1 + initialIdx - initialStack.size(); - initialStack.insert(initialStack.end(), nNewItems, nullptr); - } - - assert(initialStack[initialIdx] == nullptr); - // Create a dummy value. - std::string name = "get_" + boost::lexical_cast(_index); - initialStack[initialIdx] = m_bblock.m_builder.CreatePHI(Type::Word, 0, name); - *itemIter = initialStack[initialIdx]; - } - - return *itemIter; -} - -void BasicBlock::LocalStack::set(size_t _index, llvm::Value* _word) -{ - auto itemIter = getItemIterator(_index); - *itemIter = _word; -} - - - - - -void BasicBlock::synchronizeLocalStack(Stack& _evmStack) -{ - auto blockTerminator = m_llvmBB->getTerminator(); - assert(blockTerminator != nullptr); - m_builder.SetInsertPoint(blockTerminator); - - auto currIter = m_currentStack.begin(); - auto endIter = m_currentStack.end(); - - // Update (emit set()) changed values - for (int idx = m_currentStack.size() - 1 - m_tosOffset; - currIter < endIter && idx >= 0; - ++currIter, --idx) - { - assert(static_cast(idx) < m_initialStack.size()); - if (*currIter != m_initialStack[idx]) // value needs update - _evmStack.set(static_cast(idx), *currIter); - } - - if (m_tosOffset < 0) - { - // Pop values - _evmStack.pop(static_cast(-m_tosOffset)); - } - - // Push new values - for (; currIter < endIter; ++currIter) - { - assert(*currIter != nullptr); - _evmStack.push(*currIter); - } - - // Emit get() for all (used) values from the initial stack - for (size_t idx = 0; idx < m_initialStack.size(); ++idx) - { - auto val = m_initialStack[idx]; - 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); - } - phi->eraseFromParent(); - } - - // Reset the stack - m_initialStack.erase(m_initialStack.begin(), m_initialStack.end()); - m_currentStack.erase(m_currentStack.begin(), m_currentStack.end()); - m_tosOffset = 0; -} - -void BasicBlock::linkLocalStacks(std::vector basicBlocks, llvm::IRBuilder<>& _builder) -{ - struct BBInfo - { - BasicBlock& bblock; - std::vector predecessors; - size_t inputItems; - size_t outputItems; - std::vector phisToRewrite; - - BBInfo(BasicBlock& _bblock) : - bblock(_bblock), - predecessors(), - inputItems(0), - outputItems(0) - { - auto& initialStack = bblock.m_initialStack; - for (auto it = initialStack.begin(); - it != initialStack.end() && *it != nullptr; - ++it, ++inputItems); - - //if (bblock.localStack().m_tosOffset > 0) - // outputItems = bblock.localStack().m_tosOffset; - auto& exitStack = bblock.m_currentStack; - for (auto it = exitStack.rbegin(); - it != exitStack.rend() && *it != nullptr; - ++it, ++outputItems); - } - }; - - std::map cfg; - - // Create nodes in cfg - for (auto bb : basicBlocks) - cfg.emplace(bb->llvm(), *bb); - - // Create edges in cfg: for each bb info fill the list - // of predecessor infos. - for (auto& pair : cfg) - { - auto bb = pair.first; - auto& info = pair.second; - - for (auto predIt = llvm::pred_begin(bb); predIt != llvm::pred_end(bb); ++predIt) - { - auto predInfoEntry = cfg.find(*predIt); - if (predInfoEntry != cfg.end()) - info.predecessors.push_back(&predInfoEntry->second); - } - } - - // Iteratively compute inputs and outputs of each block, until reaching fixpoint. - bool valuesChanged = true; - while (valuesChanged) - { - if (getenv("EVMCC_DEBUG_BLOCKS")) - { - for (auto& pair : cfg) - std::cerr << pair.second.bblock.llvm()->getName().str() - << ": in " << pair.second.inputItems - << ", out " << pair.second.outputItems - << "\n"; - } - - valuesChanged = false; - for (auto& pair : cfg) - { - auto& info = pair.second; - - if (info.predecessors.empty()) - info.inputItems = 0; // no consequences for other blocks, so leave valuesChanged false - - for (auto predInfo : info.predecessors) - { - if (predInfo->outputItems < info.inputItems) - { - info.inputItems = predInfo->outputItems; - valuesChanged = true; - } - else if (predInfo->outputItems > info.inputItems) - { - predInfo->outputItems = info.inputItems; - valuesChanged = true; - } - } - } - } - - // Propagate values between blocks. - for (auto& entry : cfg) - { - auto& info = entry.second; - auto& bblock = info.bblock; - - llvm::BasicBlock::iterator fstNonPhi(bblock.llvm()->getFirstNonPHI()); - auto phiIter = bblock.m_initialStack.begin(); - for (size_t index = 0; index < info.inputItems; ++index, ++phiIter) - { - assert(llvm::isa(*phiIter)); - auto phi = llvm::cast(*phiIter); - - for (auto predIt : info.predecessors) - { - auto& predExitStack = predIt->bblock.m_currentStack; - auto value = *(predExitStack.end() - 1 - index); - phi->addIncoming(value, predIt->bblock.llvm()); - } - - // Move phi to the front - if (llvm::BasicBlock::iterator(phi) != bblock.llvm()->begin()) - { - phi->removeFromParent(); - _builder.SetInsertPoint(bblock.llvm(), bblock.llvm()->begin()); - _builder.Insert(phi); - } - } - - // The items pulled directly from predecessors block must be removed - // from the list of items that has to be popped from the initial stack. - auto& initialStack = bblock.m_initialStack; - initialStack.erase(initialStack.begin(), initialStack.begin() + info.inputItems); - // Initial stack shrinks, so the size difference grows: - bblock.m_tosOffset += info.inputItems; - } - - // We must account for the items that were pushed directly to successor - // blocks and thus should not be on the list of items to be pushed onto - // to EVM stack - for (auto& entry : cfg) - { - auto& info = entry.second; - auto& bblock = info.bblock; - - auto& exitStack = bblock.m_currentStack; - exitStack.erase(exitStack.end() - info.outputItems, exitStack.end()); - bblock.m_tosOffset -= info.outputItems; - } -} - -void BasicBlock::dump() -{ - dump(std::cerr, false); -} - -void BasicBlock::dump(std::ostream& _out, bool _dotOutput) -{ - llvm::raw_os_ostream out(_out); - - out << (_dotOutput ? "" : "Initial stack:\n"); - for (auto val : m_initialStack) - { - if (val == nullptr) - out << " ?"; - else if (llvm::isa(val)) - out << *val; - else - out << " " << *val; - - out << (_dotOutput ? "\\l" : "\n"); - } - - out << (_dotOutput ? "| " : "Instructions:\n"); - for (auto ins = m_llvmBB->begin(); ins != m_llvmBB->end(); ++ins) - out << *ins << (_dotOutput ? "\\l" : "\n"); - - if (! _dotOutput) - out << "Current stack (offset = " << m_tosOffset << "):\n"; - else - out << "|"; - - for (auto val = m_currentStack.rbegin(); val != m_currentStack.rend(); ++val) - { - if (*val == nullptr) - out << " ?"; - else if (llvm::isa(*val)) - out << **val; - else - out << " " << **val; - out << (_dotOutput ? "\\l" : "\n"); - } - - if (! _dotOutput) - out << " ...\n----------------------------------------\n"; -} - - - - -} -} -} - diff --git a/libevmjit/BasicBlock.h b/libevmjit/BasicBlock.h deleted file mode 100644 index f0643f342..000000000 --- a/libevmjit/BasicBlock.h +++ /dev/null @@ -1,117 +0,0 @@ -#pragma once - -#include - -#include - -#include "Stack.h" - -namespace dev -{ -namespace eth -{ -namespace jit -{ - -using ProgramCounter = uint64_t; // TODO: Rename - -class BasicBlock -{ -public: - class LocalStack - { - public: - /// Pushes value on stack - void push(llvm::Value* _value); - - /// Pops and returns top value - llvm::Value* pop(); - - /// Duplicates _index'th value on stack - void dup(size_t _index); - - /// Swaps _index'th value on stack with a value on stack top. - /// @param _index Index of value to be swaped. Must be > 0. - void swap(size_t _index); - - private: - LocalStack(BasicBlock& _owner); - LocalStack(LocalStack const&) = delete; - void operator=(LocalStack const&) = delete; - friend BasicBlock; - - /// Gets _index'th value from top (counting from 0) - llvm::Value* get(size_t _index); - - /// Sets _index'th value from top (counting from 0) - void set(size_t _index, llvm::Value* _value); - - std::vector::iterator getItemIterator(size_t _index); - - private: - BasicBlock& m_bblock; - }; - - /// Basic block name prefix. The rest is beging instruction index. - static const char* NamePrefix; - - explicit BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder); - explicit BasicBlock(std::string _name, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder); - - BasicBlock(const BasicBlock&) = delete; - void operator=(const BasicBlock&) = delete; - - operator llvm::BasicBlock*() { return m_llvmBB; } - llvm::BasicBlock* llvm() { return m_llvmBB; } - - ProgramCounter begin() { return m_beginInstIdx; } - ProgramCounter end() { return m_endInstIdx; } - - LocalStack& localStack() { return m_stack; } - - /// Optimization: propagates values between local stacks in basic blocks - /// to avoid excessive pushing/popping on the EVM stack. - static void linkLocalStacks(std::vector _basicBlocks, llvm::IRBuilder<>& _builder); - - /// Synchronize current local stack with the EVM stack. - void synchronizeLocalStack(Stack& _evmStack); - - /// Prints local stack and block instructions to stderr. - /// Useful for calling in a debugger session. - void dump(); - void dump(std::ostream& os, bool _dotOutput = false); - -private: - ProgramCounter const m_beginInstIdx; - ProgramCounter const m_endInstIdx; - - llvm::BasicBlock* const m_llvmBB; - - /// Basic black state vector (stack) - current/end values and their positions on stack - /// @internal Must be AFTER m_llvmBB - LocalStack m_stack; - - llvm::IRBuilder<>& m_builder; - - /// This stack contains LLVM values that correspond to items found at - /// the EVM stack when the current basic block starts executing. - /// Location 0 corresponds to the top of the EVM stack, location 1 is - /// the item below the top and so on. The stack grows as the code - /// accesses more items on the EVM stack but once a value is put on - /// the stack, it will never be replaced. - std::vector m_initialStack = {}; - - /// This stack tracks the contents of the EVM stack as the basic block - /// executes. It may grow on both sides, as the code pushes items on - /// top of the stack or changes existing items. - std::vector m_currentStack = {}; - - /// How many items higher is the current stack than the initial one. - /// May be negative. - int m_tosOffset = 0; -}; - -} -} -} - diff --git a/libevmjit/CMakeLists.txt b/libevmjit/CMakeLists.txt deleted file mode 100644 index 0b3226e14..000000000 --- a/libevmjit/CMakeLists.txt +++ /dev/null @@ -1,58 +0,0 @@ -cmake_policy(SET CMP0015 NEW) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") - -aux_source_directory(. SRC_LIST) - -set(EXECUTABLE evmjit) - -file(GLOB HEADERS "*.h") -if (EVMJIT_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) -else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) -endif() - -include_directories(..) - -target_link_libraries(${EXECUTABLE} devcore) -target_link_libraries(${EXECUTABLE} ethcore) -target_link_libraries(${EXECUTABLE} evmcore) - - -if ("${TARGET_PLATFORM}" STREQUAL "w64") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") - target_link_libraries(${EXECUTABLE} gcc) - target_link_libraries(${EXECUTABLE} gdi32) - target_link_libraries(${EXECUTABLE} ws2_32) - target_link_libraries(${EXECUTABLE} mswsock) - target_link_libraries(${EXECUTABLE} shlwapi) - target_link_libraries(${EXECUTABLE} iphlpapi) - target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) - set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) -else () - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -endif () - -# LLVM specific config - -find_package(LLVM REQUIRED CONFIG) - -message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") -message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") - -include_directories(${LLVM_INCLUDE_DIRS}) -add_definitions(${LLVM_DEFINITIONS}) - -llvm_map_components_to_libnames(llvm_libs core support mcjit x86asmparser x86codegen) -target_link_libraries(evmjit ${llvm_libs}) - -# end of LLVM specific config - - - -install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) -install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) - -cmake_policy(SET CMP0015 NEW) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp deleted file mode 100644 index 1cc86d8aa..000000000 --- a/libevmjit/Compiler.cpp +++ /dev/null @@ -1,933 +0,0 @@ - -#include "Compiler.h" - -#include - -#include - -#include -#include -#include -#include - -#include -#include - -#include - -#include "Type.h" -#include "Memory.h" -#include "Stack.h" -#include "Ext.h" -#include "GasMeter.h" -#include "Utils.h" -#include "Endianness.h" -#include "Arith256.h" -#include "Runtime.h" - -namespace dev -{ -namespace eth -{ -namespace jit -{ - -Compiler::Compiler(Options const& _options): - m_options(_options), - m_builder(llvm::getGlobalContext()) -{ - Type::init(m_builder.getContext()); -} - -void Compiler::createBasicBlocks(bytes const& _bytecode) -{ - std::set splitPoints; // Sorted collections of instruction indices where basic blocks start/end - - std::map directJumpTargets; - std::vector indirectJumpTargets; - boost::dynamic_bitset<> validJumpTargets(std::max(_bytecode.size(), size_t(1))); - - splitPoints.insert(0); // First basic block - validJumpTargets[0] = true; - - for (auto curr = _bytecode.begin(); curr != _bytecode.end(); ++curr) - { - ProgramCounter currentPC = curr - _bytecode.begin(); - validJumpTargets[currentPC] = true; - - auto inst = Instruction(*curr); - switch (inst) - { - - case Instruction::ANY_PUSH: - { - auto val = readPushData(curr, _bytecode.end()); - auto next = curr + 1; - if (next == _bytecode.end()) - break; - - auto nextInst = Instruction(*next); - if (nextInst == Instruction::JUMP || nextInst == Instruction::JUMPI) - { - // Create a block for the JUMP target. - ProgramCounter targetPC = val < _bytecode.size() ? val.convert_to() : _bytecode.size(); - splitPoints.insert(targetPC); - - ProgramCounter jumpPC = (next - _bytecode.begin()); - directJumpTargets[jumpPC] = targetPC; - } - break; - } - - case Instruction::JUMPDEST: - { - // A basic block starts here. - splitPoints.insert(currentPC); - indirectJumpTargets.push_back(currentPC); - break; - } - - case Instruction::JUMP: - case Instruction::JUMPI: - case Instruction::RETURN: - case Instruction::STOP: - case Instruction::SUICIDE: - { - // Create a basic block starting at the following instruction. - if (curr + 1 < _bytecode.end()) - splitPoints.insert(currentPC + 1); - break; - } - - default: - break; - } - } - - // Remove split points generated from jumps out of code or into data. - for (auto it = splitPoints.cbegin(); it != splitPoints.cend();) - { - if (*it > _bytecode.size() || !validJumpTargets[*it]) - it = splitPoints.erase(it); - else - ++it; - } - - for (auto it = splitPoints.cbegin(); it != splitPoints.cend();) - { - auto beginInstIdx = *it; - ++it; - auto endInstIdx = it != splitPoints.cend() ? *it : _bytecode.size(); - basicBlocks.emplace(std::piecewise_construct, std::forward_as_tuple(beginInstIdx), std::forward_as_tuple(beginInstIdx, endInstIdx, m_mainFunc, m_builder)); - } - - m_stopBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Stop", m_mainFunc); - m_badJumpBlock = std::unique_ptr(new BasicBlock("BadJumpBlock", m_mainFunc, m_builder)); - m_jumpTableBlock = std::unique_ptr(new BasicBlock("JumpTableBlock", m_mainFunc, m_builder)); - - for (auto it = directJumpTargets.cbegin(); it != directJumpTargets.cend(); ++it) - { - if (it->second >= _bytecode.size()) - { - // Jumping out of code means STOP - m_directJumpTargets[it->first] = m_stopBB; - continue; - } - - auto blockIter = basicBlocks.find(it->second); - if (blockIter != basicBlocks.end()) - { - m_directJumpTargets[it->first] = blockIter->second.llvm(); - } - else - { - clog(JIT) << "Bad JUMP at PC " << it->first - << ": " << it->second << " is not a valid PC"; - m_directJumpTargets[it->first] = m_badJumpBlock->llvm(); - } - } - - for (auto it = indirectJumpTargets.cbegin(); it != indirectJumpTargets.cend(); ++it) - m_indirectJumpTargets.push_back(&basicBlocks.find(*it)->second); -} - -std::unique_ptr Compiler::compile(bytes const& _bytecode) -{ - auto module = std::unique_ptr(new llvm::Module("main", m_builder.getContext())); - - // Create main function - llvm::Type* mainFuncArgTypes[] = {m_builder.getInt32Ty(), Type::RuntimePtr}; // There must be int in first place because LLVM does not support other signatures - auto mainFuncType = llvm::FunctionType::get(Type::MainReturn, mainFuncArgTypes, false); - m_mainFunc = llvm::Function::Create(mainFuncType, llvm::Function::ExternalLinkage, "main", module.get()); - m_mainFunc->arg_begin()->getNextNode()->setName("rt"); - - // Create the basic blocks. - auto entryBlock = llvm::BasicBlock::Create(m_builder.getContext(), "entry", m_mainFunc); - m_builder.SetInsertPoint(entryBlock); - - createBasicBlocks(_bytecode); - - // Init runtime structures. - RuntimeManager runtimeManager(m_builder); - GasMeter gasMeter(m_builder, runtimeManager); - Memory memory(runtimeManager, gasMeter); - Ext ext(runtimeManager); - Stack stack(m_builder, runtimeManager); - Arith256 arith(m_builder); - - m_builder.CreateBr(basicBlocks.begin()->second); - - for (auto basicBlockPairIt = basicBlocks.begin(); basicBlockPairIt != basicBlocks.end(); ++basicBlockPairIt) - { - auto& basicBlock = basicBlockPairIt->second; - auto iterCopy = basicBlockPairIt; - ++iterCopy; - auto nextBasicBlock = (iterCopy != basicBlocks.end()) ? iterCopy->second.llvm() : nullptr; - compileBasicBlock(basicBlock, _bytecode, runtimeManager, arith, memory, ext, gasMeter, nextBasicBlock); - } - - // Code for special blocks: - // TODO: move to separate function. - m_builder.SetInsertPoint(m_stopBB); - m_builder.CreateRet(Constant::get(ReturnCode::Stop)); - - m_builder.SetInsertPoint(m_badJumpBlock->llvm()); - m_builder.CreateRet(Constant::get(ReturnCode::BadJumpDestination)); - - m_builder.SetInsertPoint(m_jumpTableBlock->llvm()); - if (m_indirectJumpTargets.size() > 0) - { - auto dest = m_jumpTableBlock->localStack().pop(); - auto switchInstr = m_builder.CreateSwitch(dest, m_badJumpBlock->llvm(), - m_indirectJumpTargets.size()); - for (auto it = m_indirectJumpTargets.cbegin(); it != m_indirectJumpTargets.cend(); ++it) - { - auto& bb = *it; - auto dest = Constant::get(bb->begin()); - switchInstr->addCase(dest, bb->llvm()); - } - } - else - m_builder.CreateBr(m_badJumpBlock->llvm()); - - removeDeadBlocks(); - - dumpCFGifRequired("blocks-init.dot"); - - if (m_options.optimizeStack) - { - std::vector blockList; - for (auto& entry : basicBlocks) - blockList.push_back(&entry.second); - - if (m_jumpTableBlock) - blockList.push_back(m_jumpTableBlock.get()); - - BasicBlock::linkLocalStacks(blockList, m_builder); - - dumpCFGifRequired("blocks-opt.dot"); - } - - for (auto& entry : basicBlocks) - entry.second.synchronizeLocalStack(stack); - if (m_jumpTableBlock) - m_jumpTableBlock->synchronizeLocalStack(stack); - - dumpCFGifRequired("blocks-sync.dot"); - - if (m_jumpTableBlock && m_options.rewriteSwitchToBranches) - { - llvm::FunctionPassManager fpManager(module.get()); - fpManager.add(llvm::createLowerSwitchPass()); - fpManager.doInitialization(); - fpManager.run(*m_mainFunc); - } - - return module; -} - - -void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode, RuntimeManager& _runtimeManager, - Arith256& _arith, Memory& _memory, Ext& _ext, GasMeter& _gasMeter, llvm::BasicBlock* _nextBasicBlock) -{ - if (!_nextBasicBlock) // this is the last block in the code - _nextBasicBlock = m_stopBB; - - m_builder.SetInsertPoint(_basicBlock.llvm()); - auto& stack = _basicBlock.localStack(); - - for (auto currentPC = _basicBlock.begin(); currentPC != _basicBlock.end(); ++currentPC) - { - auto inst = static_cast(_bytecode[currentPC]); - - _gasMeter.count(inst); - - switch (inst) - { - - case Instruction::ADD: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto result = m_builder.CreateAdd(lhs, rhs); - stack.push(result); - break; - } - - case Instruction::SUB: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto result = m_builder.CreateSub(lhs, rhs); - stack.push(result); - break; - } - - case Instruction::MUL: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = _arith.mul(lhs, rhs); - stack.push(res); - break; - } - - case Instruction::DIV: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = _arith.div(lhs, rhs); - stack.push(res); - break; - } - - case Instruction::SDIV: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = _arith.sdiv(lhs, rhs); - stack.push(res); - break; - } - - case Instruction::MOD: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = _arith.mod(lhs, rhs); - stack.push(res); - break; - } - - case Instruction::SMOD: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = _arith.smod(lhs, rhs); - stack.push(res); - break; - } - - case Instruction::EXP: - { - auto left = stack.pop(); - auto right = stack.pop(); - auto ret = _ext.exp(left, right); - stack.push(ret); - break; - } - - case Instruction::NOT: - { - auto value = stack.pop(); - auto ret = m_builder.CreateXor(value, Constant::get(-1), "bnot"); - stack.push(ret); - break; - } - - case Instruction::LT: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res1 = m_builder.CreateICmpULT(lhs, rhs); - auto res256 = m_builder.CreateZExt(res1, Type::Word); - stack.push(res256); - break; - } - - case Instruction::GT: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res1 = m_builder.CreateICmpUGT(lhs, rhs); - auto res256 = m_builder.CreateZExt(res1, Type::Word); - stack.push(res256); - break; - } - - case Instruction::SLT: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res1 = m_builder.CreateICmpSLT(lhs, rhs); - auto res256 = m_builder.CreateZExt(res1, Type::Word); - stack.push(res256); - break; - } - - case Instruction::SGT: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res1 = m_builder.CreateICmpSGT(lhs, rhs); - auto res256 = m_builder.CreateZExt(res1, Type::Word); - stack.push(res256); - break; - } - - case Instruction::EQ: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res1 = m_builder.CreateICmpEQ(lhs, rhs); - auto res256 = m_builder.CreateZExt(res1, Type::Word); - stack.push(res256); - break; - } - - case Instruction::ISZERO: - { - auto top = stack.pop(); - auto iszero = m_builder.CreateICmpEQ(top, Constant::get(0), "iszero"); - auto result = m_builder.CreateZExt(iszero, Type::Word); - stack.push(result); - break; - } - - case Instruction::AND: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = m_builder.CreateAnd(lhs, rhs); - stack.push(res); - break; - } - - case Instruction::OR: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = m_builder.CreateOr(lhs, rhs); - stack.push(res); - break; - } - - case Instruction::XOR: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = m_builder.CreateXor(lhs, rhs); - stack.push(res); - break; - } - - case Instruction::BYTE: - { - const auto byteNum = stack.pop(); - auto value = stack.pop(); - - 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"); - value = m_builder.CreateZExt(byte, Type::Word); - - auto byteNumValid = m_builder.CreateICmpULT(byteNum, Constant::get(32)); - value = m_builder.CreateSelect(byteNumValid, value, Constant::get(0)); - stack.push(value); - break; - } - - case Instruction::ADDMOD: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto mod = stack.pop(); - auto res = _arith.addmod(lhs, rhs, mod); - stack.push(res); - break; - } - - case Instruction::MULMOD: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto mod = stack.pop(); - auto res = _arith.mulmod(lhs, rhs, mod); - stack.push(res); - break; - } - - case Instruction::SIGNEXTEND: - { - auto idx = stack.pop(); - auto word = stack.pop(); - - auto k32_ = m_builder.CreateTrunc(idx, m_builder.getIntNTy(5), "k_32"); - auto k32 = m_builder.CreateZExt(k32_, Type::Word); - auto k32x8 = m_builder.CreateMul(k32, Constant::get(8), "kx8"); - - // test for word >> (k * 8 + 7) - auto bitpos = m_builder.CreateAdd(k32x8, Constant::get(7), "bitpos"); - auto bitval = m_builder.CreateLShr(word, bitpos, "bitval"); - auto bittest = m_builder.CreateTrunc(bitval, m_builder.getInt1Ty(), "bittest"); - - auto mask_ = m_builder.CreateShl(Constant::get(1), bitpos); - auto mask = m_builder.CreateSub(mask_, Constant::get(1), "mask"); - - auto negmask = m_builder.CreateXor(mask, llvm::ConstantInt::getAllOnesValue(Type::Word), "negmask"); - auto val1 = m_builder.CreateOr(word, negmask); - auto val0 = m_builder.CreateAnd(word, mask); - - auto kInRange = m_builder.CreateICmpULE(idx, llvm::ConstantInt::get(Type::Word, 30)); - auto result = m_builder.CreateSelect(kInRange, - m_builder.CreateSelect(bittest, val1, val0), - word); - stack.push(result); - break; - } - - case Instruction::SHA3: - { - auto inOff = stack.pop(); - auto inSize = stack.pop(); - _memory.require(inOff, inSize); - auto hash = _ext.sha3(inOff, inSize); - stack.push(hash); - break; - } - - case Instruction::POP: - { - auto val = stack.pop(); - static_cast(val); - // Generate a dummy use of val to make sure that a get(0) will be emitted at this point, - // so that StackTooSmall will be thrown - // m_builder.CreateICmpEQ(val, val, "dummy"); - break; - } - - case Instruction::ANY_PUSH: - { - auto curr = _bytecode.begin() + currentPC; // TODO: replace currentPC with iterator - auto value = readPushData(curr, _bytecode.end()); - currentPC = curr - _bytecode.begin(); - - stack.push(Constant::get(value)); - break; - } - - case Instruction::ANY_DUP: - { - auto index = static_cast(inst) - static_cast(Instruction::DUP1); - stack.dup(index); - break; - } - - case Instruction::ANY_SWAP: - { - auto index = static_cast(inst) - static_cast(Instruction::SWAP1) + 1; - stack.swap(index); - break; - } - - case Instruction::MLOAD: - { - auto addr = stack.pop(); - auto word = _memory.loadWord(addr); - stack.push(word); - break; - } - - case Instruction::MSTORE: - { - auto addr = stack.pop(); - auto word = stack.pop(); - _memory.storeWord(addr, word); - break; - } - - case Instruction::MSTORE8: - { - auto addr = stack.pop(); - auto word = stack.pop(); - _memory.storeByte(addr, word); - break; - } - - case Instruction::MSIZE: - { - auto word = _memory.getSize(); - stack.push(word); - break; - } - - case Instruction::SLOAD: - { - auto index = stack.pop(); - auto value = _ext.store(index); - stack.push(value); - break; - } - - case Instruction::SSTORE: - { - auto index = stack.pop(); - auto value = stack.pop(); - _gasMeter.countSStore(_ext, index, value); - _ext.setStore(index, value); - break; - } - - case Instruction::JUMP: - case Instruction::JUMPI: - { - // Generate direct jump iff: - // 1. this is not the first instruction in the block - // 2. m_directJumpTargets[currentPC] is defined (meaning that the previous instruction is a PUSH) - // Otherwise generate a indirect jump (a switch). - llvm::BasicBlock* targetBlock = nullptr; - if (currentPC != _basicBlock.begin()) - { - auto pairIter = m_directJumpTargets.find(currentPC); - if (pairIter != m_directJumpTargets.end()) - targetBlock = pairIter->second; - } - - if (inst == Instruction::JUMP) - { - if (targetBlock) - { - // The target address is computed at compile time, - // just pop it without looking... - stack.pop(); - m_builder.CreateBr(targetBlock); - } - else - m_builder.CreateBr(m_jumpTableBlock->llvm()); - } - else // JUMPI - { - stack.swap(1); - auto val = stack.pop(); - auto zero = Constant::get(0); - auto cond = m_builder.CreateICmpNE(val, zero, "nonzero"); - - if (targetBlock) - { - stack.pop(); - m_builder.CreateCondBr(cond, targetBlock, _nextBasicBlock); - } - else - m_builder.CreateCondBr(cond, m_jumpTableBlock->llvm(), _nextBasicBlock); - } - - break; - } - - case Instruction::JUMPDEST: - { - // Nothing to do - break; - } - - case Instruction::PC: - { - auto value = Constant::get(currentPC); - stack.push(value); - break; - } - - case Instruction::GAS: - case Instruction::ADDRESS: - case Instruction::CALLER: - case Instruction::ORIGIN: - case Instruction::CALLVALUE: - case Instruction::CALLDATASIZE: - case Instruction::CODESIZE: - case Instruction::GASPRICE: - case Instruction::PREVHASH: - case Instruction::COINBASE: - case Instruction::TIMESTAMP: - case Instruction::NUMBER: - case Instruction::DIFFICULTY: - case Instruction::GASLIMIT: - { - // Pushes an element of runtime data on stack - stack.push(_runtimeManager.get(inst)); - break; - } - - case Instruction::BALANCE: - { - auto address = stack.pop(); - auto value = _ext.balance(address); - stack.push(value); - break; - } - - case Instruction::EXTCODESIZE: - { - auto addr = stack.pop(); - auto value = _ext.codesizeAt(addr); - stack.push(value); - break; - } - - case Instruction::CALLDATACOPY: - { - auto destMemIdx = stack.pop(); - auto srcIdx = stack.pop(); - auto reqBytes = stack.pop(); - - auto srcPtr = _runtimeManager.getCallData(); - auto srcSize = _runtimeManager.get(RuntimeData::CallDataSize); - - _memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); - break; - } - - case Instruction::CODECOPY: - { - auto destMemIdx = stack.pop(); - auto srcIdx = stack.pop(); - auto reqBytes = stack.pop(); - - auto srcPtr = _runtimeManager.getCode(); // TODO: Code & its size are constants, feature #80814234 - auto srcSize = _runtimeManager.get(RuntimeData::CodeSize); - - _memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); - break; - } - - case Instruction::EXTCODECOPY: - { - auto extAddr = stack.pop(); - auto destMemIdx = stack.pop(); - auto srcIdx = stack.pop(); - auto reqBytes = stack.pop(); - - auto srcPtr = _ext.codeAt(extAddr); - auto srcSize = _ext.codesizeAt(extAddr); - - _memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); - break; - } - - case Instruction::CALLDATALOAD: - { - auto index = stack.pop(); - auto value = _ext.calldataload(index); - stack.push(value); - break; - } - - case Instruction::CREATE: - { - auto endowment = stack.pop(); - auto initOff = stack.pop(); - auto initSize = stack.pop(); - _memory.require(initOff, initSize); - - auto address = _ext.create(endowment, initOff, initSize); - stack.push(address); - break; - } - - case Instruction::CALL: - case Instruction::CALLCODE: - { - auto gas = stack.pop(); - auto codeAddress = stack.pop(); - auto value = stack.pop(); - auto inOff = stack.pop(); - auto inSize = stack.pop(); - auto outOff = stack.pop(); - auto outSize = stack.pop(); - - _gasMeter.commitCostBlock(gas); - - // Require memory for in and out buffers - _memory.require(outOff, outSize); // Out buffer first as we guess it will be after the in one - _memory.require(inOff, inSize); - - auto receiveAddress = codeAddress; - if (inst == Instruction::CALLCODE) - receiveAddress = _runtimeManager.get(RuntimeData::Address); - - auto ret = _ext.call(gas, receiveAddress, value, inOff, inSize, outOff, outSize, codeAddress); - _gasMeter.giveBack(gas); - stack.push(ret); - break; - } - - case Instruction::RETURN: - { - auto index = stack.pop(); - auto size = stack.pop(); - - _memory.require(index, size); - _runtimeManager.registerReturnData(index, size); - - m_builder.CreateRet(Constant::get(ReturnCode::Return)); - break; - } - - case Instruction::SUICIDE: - case Instruction::STOP: - { - if (inst == Instruction::SUICIDE) - { - auto address = stack.pop(); - _ext.suicide(address); - } - - m_builder.CreateRet(Constant::get(ReturnCode::Stop)); - break; - } - - case Instruction::LOG0: - case Instruction::LOG1: - case Instruction::LOG2: - case Instruction::LOG3: - case Instruction::LOG4: - { - auto beginIdx = stack.pop(); - auto numBytes = stack.pop(); - _memory.require(beginIdx, numBytes); - - // This will commit the current cost block - _gasMeter.countLogData(numBytes); - - std::array topics; - auto numTopics = static_cast(inst) - static_cast(Instruction::LOG0); - for (size_t i = 0; i < numTopics; ++i) - topics[i] = stack.pop(); - - _ext.log(beginIdx, numBytes, numTopics, topics); - break; - } - - default: // Invalid instruction - runtime exception - { - _runtimeManager.raiseException(ReturnCode::BadInstruction); - } - - } - } - - _gasMeter.commitCostBlock(); - - // Block may have no terminator if the next instruction is a jump destination. - if (!_basicBlock.llvm()->getTerminator()) - m_builder.CreateBr(_nextBasicBlock); -} - - - -void Compiler::removeDeadBlocks() -{ - // Remove dead basic blocks - auto sthErased = false; - do - { - sthErased = false; - for (auto it = basicBlocks.begin(); it != basicBlocks.end();) - { - auto llvmBB = it->second.llvm(); - if (llvm::pred_begin(llvmBB) == llvm::pred_end(llvmBB)) - { - llvmBB->eraseFromParent(); - basicBlocks.erase(it++); - sthErased = true; - } - else - ++it; - } - } - while (sthErased); - - // Remove jump table block if no predecessors - if (llvm::pred_begin(m_jumpTableBlock->llvm()) == llvm::pred_end(m_jumpTableBlock->llvm())) - { - m_jumpTableBlock->llvm()->eraseFromParent(); - m_jumpTableBlock.reset(); - } -} - -void Compiler::dumpCFGifRequired(std::string const& _dotfilePath) -{ - if (! m_options.dumpCFG) - return; - - // TODO: handle i/o failures - std::ofstream ofs(_dotfilePath); - dumpCFGtoStream(ofs); - ofs.close(); -} - -void Compiler::dumpCFGtoStream(std::ostream& _out) -{ - _out << "digraph BB {\n" - << " node [shape=record, fontname=Courier, fontsize=10];\n" - << " entry [share=record, label=\"entry block\"];\n"; - - std::vector blocks; - for (auto& pair : basicBlocks) - blocks.push_back(&pair.second); - if (m_jumpTableBlock) - blocks.push_back(m_jumpTableBlock.get()); - if (m_badJumpBlock) - blocks.push_back(m_badJumpBlock.get()); - - // std::map phiNodesPerBlock; - - // Output nodes - for (auto bb : blocks) - { - std::string blockName = bb->llvm()->getName(); - - std::ostringstream oss; - bb->dump(oss, true); - - _out << " \"" << blockName << "\" [shape=record, label=\" { " << blockName << "|" << oss.str() << "} \"];\n"; - } - - // Output edges - for (auto bb : blocks) - { - std::string blockName = bb->llvm()->getName(); - - auto end = llvm::pred_end(bb->llvm()); - for (llvm::pred_iterator it = llvm::pred_begin(bb->llvm()); it != end; ++it) - { - _out << " \"" << (*it)->getName().str() << "\" -> \"" << blockName << "\" [" - << ((m_jumpTableBlock.get() && *it == m_jumpTableBlock.get()->llvm()) ? "style = dashed, " : "") - << "];\n"; - } - } - - _out << "}\n"; -} - -void Compiler::dump() -{ - for (auto& entry : basicBlocks) - entry.second.dump(); - if (m_jumpTableBlock != nullptr) - m_jumpTableBlock->dump(); -} - -} -} -} - diff --git a/libevmjit/Compiler.h b/libevmjit/Compiler.h deleted file mode 100644 index a618f41a3..000000000 --- a/libevmjit/Compiler.h +++ /dev/null @@ -1,92 +0,0 @@ - -#pragma once - -#include - -#include - -#include "BasicBlock.h" - -namespace dev -{ -namespace eth -{ -namespace jit -{ - -class Compiler -{ -public: - - struct Options - { - /// Optimize stack operations between basic blocks - bool optimizeStack; - - /// Rewrite switch instructions to sequences of branches - bool rewriteSwitchToBranches; - - /// Dump CFG as a .dot file for graphviz - bool dumpCFG; - - Options(): - optimizeStack(true), - rewriteSwitchToBranches(true), - dumpCFG(false) - {} - }; - - using ProgramCounter = uint64_t; - - Compiler(Options const& _options); - - std::unique_ptr compile(bytes const& _bytecode); - -private: - - void createBasicBlocks(bytes const& _bytecode); - - void compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode, class RuntimeManager& _runtimeManager, class Arith256& _arith, class Memory& _memory, class Ext& _ext, class GasMeter& _gasMeter, llvm::BasicBlock* _nextBasicBlock); - - void removeDeadBlocks(); - - /// Dumps basic block graph in graphviz format to a file, if option dumpCFG is enabled. - void dumpCFGifRequired(std::string const& _dotfilePath); - - /// Dumps basic block graph in graphviz format to a stream. - void dumpCFGtoStream(std::ostream& _out); - - /// Dumps all basic blocks to stderr. Useful in a debugging session. - void dump(); - - /// Compiler options - Options const& m_options; - - /// Helper class for generating IR - llvm::IRBuilder<> m_builder; - - /// Maps a program counter pc to a basic block that starts at pc (if any). - std::map basicBlocks = {}; - - /// Maps a pc at which there is a JUMP or JUMPI to the target block of the jump. - std::map m_directJumpTargets = {}; - - /// A list of possible blocks to which there may be indirect jumps. - std::vector m_indirectJumpTargets = {}; - - /// Stop basic block - terminates execution with STOP code (0) - llvm::BasicBlock* m_stopBB = nullptr; - - /// Block with a jump table. - std::unique_ptr m_jumpTableBlock = nullptr; - - /// Default destination for indirect jumps. - std::unique_ptr m_badJumpBlock = nullptr; - - /// Main program function - llvm::Function* m_mainFunc = nullptr; -}; - -} -} -} diff --git a/libevmjit/CompilerHelper.cpp b/libevmjit/CompilerHelper.cpp deleted file mode 100644 index c4835c32e..000000000 --- a/libevmjit/CompilerHelper.cpp +++ /dev/null @@ -1,44 +0,0 @@ - -#include "CompilerHelper.h" - -#include - -#include "Runtime.h" - -namespace dev -{ -namespace eth -{ -namespace jit -{ - -CompilerHelper::CompilerHelper(llvm::IRBuilder<>& _builder) : - m_builder(_builder) -{} - -llvm::Module* CompilerHelper::getModule() -{ - assert(m_builder.GetInsertBlock()); - assert(m_builder.GetInsertBlock()->getParent()); // BB must be in a function - return m_builder.GetInsertBlock()->getParent()->getParent(); -} - -llvm::Function* CompilerHelper::getMainFunction() -{ - assert(m_builder.GetInsertBlock()); - auto mainFunc = m_builder.GetInsertBlock()->getParent(); - assert(mainFunc); - if (mainFunc->getName() == "main") - return mainFunc; - return nullptr; -} - - -RuntimeHelper::RuntimeHelper(RuntimeManager& _runtimeManager): - CompilerHelper(_runtimeManager.getBuilder()), - m_runtimeManager(_runtimeManager) -{} - -} -} -} diff --git a/libevmjit/CompilerHelper.h b/libevmjit/CompilerHelper.h deleted file mode 100644 index 19315fe4a..000000000 --- a/libevmjit/CompilerHelper.h +++ /dev/null @@ -1,83 +0,0 @@ - -#pragma once - -#include - - -namespace dev -{ -namespace eth -{ -namespace jit -{ -class RuntimeManager; - -/// Base class for compiler helpers like Memory, GasMeter, etc. -class CompilerHelper -{ -protected: - CompilerHelper(llvm::IRBuilder<>& _builder); - - CompilerHelper(const CompilerHelper&) = delete; - void operator=(CompilerHelper) = delete; - - /// Reference to the IR module being compiled - llvm::Module* getModule(); - - /// Reference to the main module function - llvm::Function* getMainFunction(); - - /// Reference to parent compiler IR builder - llvm::IRBuilder<>& m_builder; - llvm::IRBuilder<>& getBuilder() { return m_builder; } - - template - llvm::CallInst* createCall(llvm::Function* _func, _Args*... _args) - { - llvm::Value* args[] = {_args...}; - return getBuilder().CreateCall(_func, args); - } - - friend class RuntimeHelper; -}; - - -/// Compiler helper that depends on runtime data -class RuntimeHelper : public CompilerHelper -{ -protected: - RuntimeHelper(RuntimeManager& _runtimeManager); - - RuntimeManager& getRuntimeManager() { return m_runtimeManager; } - -private: - RuntimeManager& m_runtimeManager; -}; - - -/// Saves the insert point of the IR builder and restores it when destructed -struct InsertPointGuard -{ - InsertPointGuard(llvm::IRBuilder<>& _builder) : - m_builder(_builder), - m_insertBB(m_builder.GetInsertBlock()), - m_insertPt(m_builder.GetInsertPoint()) - {} - - InsertPointGuard(const InsertPointGuard&) = delete; - void operator=(InsertPointGuard) = delete; - - ~InsertPointGuard() - { - m_builder.SetInsertPoint(m_insertBB, m_insertPt); - } - -private: - llvm::IRBuilder<>& m_builder; - llvm::BasicBlock* m_insertBB; - llvm::BasicBlock::iterator m_insertPt; -}; - -} -} -} diff --git a/libevmjit/Endianness.cpp b/libevmjit/Endianness.cpp deleted file mode 100644 index e062fb77e..000000000 --- a/libevmjit/Endianness.cpp +++ /dev/null @@ -1,25 +0,0 @@ - -#include "Endianness.h" - -#include - -#include "Type.h" - -namespace dev -{ -namespace eth -{ -namespace jit -{ - -llvm::Value* Endianness::bswap(llvm::IRBuilder<>& _builder, llvm::Value* _word) -{ - // TODO: Native is Little Endian - assert(_word->getType() == Type::Word); - auto bswap = llvm::Intrinsic::getDeclaration(_builder.GetInsertBlock()->getParent()->getParent(), llvm::Intrinsic::bswap, Type::Word); - return _builder.CreateCall(bswap, _word); -} - -} -} -} diff --git a/libevmjit/Endianness.h b/libevmjit/Endianness.h deleted file mode 100644 index 951904358..000000000 --- a/libevmjit/Endianness.h +++ /dev/null @@ -1,34 +0,0 @@ - -#pragma once - -#include - -#include - -namespace dev -{ -namespace eth -{ -namespace jit -{ - -struct Endianness -{ - -#if defined(BOOST_LITTLE_ENDIAN) - static llvm::Value* toBE(llvm::IRBuilder<>& _builder, llvm::Value* _word) { return bswap(_builder, _word); } - static llvm::Value* toNative(llvm::IRBuilder<>& _builder, llvm::Value* _word) { return bswap(_builder, _word); } - -#elif defined(BOOST_BIG_ENDIAN) - static llvm::Value* toBE(llvm::IRBuilder<>&, llvm::Value* _word) { return _word; } - static llvm::Value* toNative(llvm::IRBuilder<>&, llvm::Value* _word) { return _word; } - -#endif // Add support for PDP endianness if needed - -private: - static llvm::Value* bswap(llvm::IRBuilder<>& _builder, llvm::Value* _word); -}; - -} -} -} diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp deleted file mode 100644 index 02b12d373..000000000 --- a/libevmjit/ExecutionEngine.cpp +++ /dev/null @@ -1,132 +0,0 @@ -#include "ExecutionEngine.h" - -#include -#include - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#pragma GCC diagnostic pop - - -#include - -#include "Runtime.h" -#include "Memory.h" -#include "Stack.h" -#include "Type.h" - -namespace dev -{ -namespace eth -{ -namespace jit -{ - -ExecutionEngine::ExecutionEngine() -{ -} - -int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, bool _outputLogs, ExtVMFace& _ext) -{ - auto module = _module.get(); // Keep ownership of the module in _module - - llvm::sys::PrintStackTraceOnErrorSignal(); - static const auto program = "evmcc"; - llvm::PrettyStackTraceProgram X(1, &program); - - auto&& context = llvm::getGlobalContext(); - - llvm::InitializeNativeTarget(); - llvm::InitializeNativeTargetAsmPrinter(); - llvm::InitializeNativeTargetAsmParser(); - - std::string errorMsg; - llvm::EngineBuilder builder(module); - //builder.setMArch(MArch); - //builder.setMCPU(MCPU); - //builder.setMAttrs(MAttrs); - //builder.setRelocationModel(RelocModel); - //builder.setCodeModel(CMModel); - builder.setErrorStr(&errorMsg); - builder.setEngineKind(llvm::EngineKind::JIT); - builder.setUseMCJIT(true); - builder.setMCJITMemoryManager(new llvm::SectionMemoryManager()); - builder.setOptLevel(llvm::CodeGenOpt::None); - - auto triple = llvm::Triple(llvm::sys::getProcessTriple()); - if (triple.getOS() == llvm::Triple::OSType::Win32) - triple.setObjectFormat(llvm::Triple::ObjectFormatType::ELF); // MCJIT does not support COFF format - module->setTargetTriple(triple.str()); - - auto exec = std::unique_ptr(builder.create()); - if (!exec) - BOOST_THROW_EXCEPTION(Exception() << errinfo_comment(errorMsg)); - _module.release(); // Successfully created llvm::ExecutionEngine takes ownership of the module - - auto finalizationStartTime = std::chrono::high_resolution_clock::now(); - exec->finalizeObject(); - auto finalizationEndTime = std::chrono::high_resolution_clock::now(); - clog(JIT) << "Module finalization time: " - << std::chrono::duration_cast(finalizationEndTime - finalizationStartTime).count(); - - auto entryFunc = module->getFunction("main"); - if (!entryFunc) - BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("main function not found")); - - ReturnCode returnCode; - std::jmp_buf buf; - Runtime runtime(_gas, _ext, buf, _outputLogs); - auto r = setjmp(buf); - if (r == 0) - { - - auto executionStartTime = std::chrono::high_resolution_clock::now(); - - auto result = exec->runFunction(entryFunc, {{}, llvm::GenericValue(runtime.getDataPtr())}); - returnCode = static_cast(result.IntVal.getZExtValue()); - - auto executionEndTime = std::chrono::high_resolution_clock::now(); - clog(JIT) << "Execution time : " - << std::chrono::duration_cast(executionEndTime - executionStartTime).count(); - - } - else - returnCode = static_cast(r); - - // Return remaining gas - _gas = returnCode == ReturnCode::OutOfGas ? 0 : runtime.getGas(); - - clog(JIT) << "Max stack size: " << Stack::maxStackSize; - - if (returnCode == ReturnCode::Return) - { - returnData = runtime.getReturnData().toVector(); // TODO: It might be better to place is in Runtime interface - - auto&& log = clog(JIT); - log << "RETURN [ "; - for (auto it = returnData.begin(), end = returnData.end(); it != end; ++it) - log << std::hex << std::setw(2) << std::setfill('0') << (int)*it << " "; - log << "]"; - } - else - cslog(JIT) << "RETURN " << (int)returnCode; - - return static_cast(returnCode); -} - -} -} -} diff --git a/libevmjit/ExecutionEngine.h b/libevmjit/ExecutionEngine.h deleted file mode 100644 index 8cf1ec746..000000000 --- a/libevmjit/ExecutionEngine.h +++ /dev/null @@ -1,28 +0,0 @@ - -#pragma once - -#include - -#include -#include - -namespace dev -{ -namespace eth -{ -namespace jit -{ - -class ExecutionEngine -{ -public: - ExecutionEngine(); - - int run(std::unique_ptr module, u256& _gas, bool _outputLogs, ExtVMFace& _ext); - - bytes returnData; -}; - -} -} -} diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp deleted file mode 100644 index 6eb35acda..000000000 --- a/libevmjit/Ext.cpp +++ /dev/null @@ -1,420 +0,0 @@ - -#include "Ext.h" - -#include -#include -#include - -#include -#include - -#include "Runtime.h" -#include "Type.h" -#include "Endianness.h" - -namespace dev -{ -namespace eth -{ -namespace jit -{ - -// TODO: Copy of fromAddress in VM.h -inline u256 fromAddress(Address _a) -{ - return (u160)_a; -} - -Ext::Ext(RuntimeManager& _runtimeManager): - RuntimeHelper(_runtimeManager), - m_data() -{ - auto&& ctx = m_builder.getContext(); - auto module = getModule(); - - auto i256Ty = m_builder.getIntNTy(256); - - m_args[0] = m_builder.CreateAlloca(i256Ty, nullptr, "ext.index"); - m_args[1] = m_builder.CreateAlloca(i256Ty, nullptr, "ext.value"); - m_arg2 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg2"); - m_arg3 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg3"); - m_arg4 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg4"); - m_arg5 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg5"); - m_arg6 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg6"); - m_arg7 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg7"); - m_arg8 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg8"); - - using Linkage = llvm::GlobalValue::LinkageTypes; - - llvm::Type* argsTypes[] = {Type::RuntimePtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr}; - - m_store = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 3}, false), Linkage::ExternalLinkage, "ext_store", module); - m_setStore = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 3}, false), Linkage::ExternalLinkage, "ext_setStore", module); - m_calldataload = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 3}, false), Linkage::ExternalLinkage, "ext_calldataload", module); - m_balance = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 3}, false), Linkage::ExternalLinkage, "ext_balance", module); - m_suicide = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 2}, false), Linkage::ExternalLinkage, "ext_suicide", module); - m_create = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 5}, false), Linkage::ExternalLinkage, "ext_create", module); - m_call = llvm::Function::Create(llvm::FunctionType::get(Type::Void, argsTypes, false), Linkage::ExternalLinkage, "ext_call", module); - m_sha3 = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 4}, false), Linkage::ExternalLinkage, "ext_sha3", module); - m_exp = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 4}, false), Linkage::ExternalLinkage, "ext_exp", module); - m_codeAt = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, {argsTypes, 2}, false), Linkage::ExternalLinkage, "ext_codeAt", module); - m_codesizeAt = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 3}, false), Linkage::ExternalLinkage, "ext_codesizeAt", module); - m_log0 = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 3}, false), Linkage::ExternalLinkage, "ext_log0", module); - m_log1 = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 4}, false), Linkage::ExternalLinkage, "ext_log1", module); - m_log2 = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 5}, false), Linkage::ExternalLinkage, "ext_log2", module); - m_log3 = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 6}, false), Linkage::ExternalLinkage, "ext_log3", module); - m_log4 = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 7}, false), Linkage::ExternalLinkage, "ext_log4", module); -} - -llvm::Value* Ext::store(llvm::Value* _index) -{ - m_builder.CreateStore(_index, m_args[0]); - m_builder.CreateCall3(m_store, getRuntimeManager().getRuntimePtr(), m_args[0], m_args[1]); // Uses native endianness - return m_builder.CreateLoad(m_args[1]); -} - -void Ext::setStore(llvm::Value* _index, llvm::Value* _value) -{ - m_builder.CreateStore(_index, m_args[0]); - m_builder.CreateStore(_value, m_args[1]); - m_builder.CreateCall3(m_setStore, getRuntimeManager().getRuntimePtr(), m_args[0], m_args[1]); // Uses native endianness -} - -llvm::Value* Ext::calldataload(llvm::Value* _index) -{ - m_builder.CreateStore(_index, m_args[0]); - m_builder.CreateCall3(m_calldataload, getRuntimeManager().getRuntimePtr(), m_args[0], m_args[1]); - auto ret = m_builder.CreateLoad(m_args[1]); - return Endianness::toNative(m_builder, ret); -} - -llvm::Value* Ext::balance(llvm::Value* _address) -{ - auto address = Endianness::toBE(m_builder, _address); - m_builder.CreateStore(address, m_args[0]); - m_builder.CreateCall3(m_balance, getRuntimeManager().getRuntimePtr(), m_args[0], m_args[1]); - return m_builder.CreateLoad(m_args[1]); -} - -void Ext::suicide(llvm::Value* _address) -{ - auto address = Endianness::toBE(m_builder, _address); - m_builder.CreateStore(address, m_args[0]); - m_builder.CreateCall2(m_suicide, getRuntimeManager().getRuntimePtr(), m_args[0]); -} - -llvm::Value* Ext::create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize) -{ - m_builder.CreateStore(_endowment, m_args[0]); - m_builder.CreateStore(_initOff, m_arg2); - m_builder.CreateStore(_initSize, m_arg3); - createCall(m_create, getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_arg3, m_args[1]); - llvm::Value* address = m_builder.CreateLoad(m_args[1]); - address = Endianness::toNative(m_builder, address); - return address; -} - -llvm::Value* Ext::call(llvm::Value*& _gas, llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize, llvm::Value* _codeAddress) -{ - m_builder.CreateStore(_gas, m_args[0]); - auto receiveAddress = Endianness::toBE(m_builder, _receiveAddress); - m_builder.CreateStore(receiveAddress, m_arg2); - m_builder.CreateStore(_value, m_arg3); - m_builder.CreateStore(_inOff, m_arg4); - m_builder.CreateStore(_inSize, m_arg5); - m_builder.CreateStore(_outOff, m_arg6); - m_builder.CreateStore(_outSize, m_arg7); - auto codeAddress = Endianness::toBE(m_builder, _codeAddress); - m_builder.CreateStore(codeAddress, m_arg8); - createCall(m_call, getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_args[1]); - _gas = m_builder.CreateLoad(m_args[0]); // Return gas - return m_builder.CreateLoad(m_args[1]); -} - -llvm::Value* Ext::sha3(llvm::Value* _inOff, llvm::Value* _inSize) -{ - m_builder.CreateStore(_inOff, m_args[0]); - m_builder.CreateStore(_inSize, m_arg2); - createCall(m_sha3, getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_args[1]); - llvm::Value* hash = m_builder.CreateLoad(m_args[1]); - hash = Endianness::toNative(m_builder, hash); - return hash; -} - -llvm::Value* Ext::exp(llvm::Value* _left, llvm::Value* _right) -{ - // TODO: Move ext to Arith256 - m_builder.CreateStore(_left, m_args[0]); - m_builder.CreateStore(_right, m_arg2); - createCall(m_exp, getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_args[1]); - return m_builder.CreateLoad(m_args[1]); -} - -llvm::Value* Ext::codeAt(llvm::Value* _addr) -{ - auto addr = Endianness::toBE(m_builder, _addr); - m_builder.CreateStore(addr, m_args[0]); - return m_builder.CreateCall2(m_codeAt, getRuntimeManager().getRuntimePtr(), m_args[0]); -} - -llvm::Value* Ext::codesizeAt(llvm::Value* _addr) -{ - auto addr = Endianness::toBE(m_builder, _addr); - m_builder.CreateStore(addr, m_args[0]); - createCall(m_codesizeAt, getRuntimeManager().getRuntimePtr(), m_args[0], m_args[1]); - return m_builder.CreateLoad(m_args[1]); -} - -void Ext::log(llvm::Value* _memIdx, llvm::Value* _numBytes, size_t _numTopics, std::array const& _topics) -{ - llvm::Value* args[] = {nullptr, m_args[0], m_args[1], m_arg2, m_arg3, m_arg4, m_arg5}; - llvm::Value* funcs[] = {m_log0, m_log1, m_log2, m_log3, m_log4}; - - args[0] = getRuntimeManager().getRuntimePtr(); - m_builder.CreateStore(_memIdx, m_args[0]); - m_builder.CreateStore(_numBytes, m_args[1]); - - for (size_t i = 0; i < _numTopics; ++i) - m_builder.CreateStore(_topics[i], args[i + 3]); - - m_builder.CreateCall(funcs[_numTopics], llvm::ArrayRef(args, _numTopics + 3)); -} - -} - - -extern "C" -{ - - using namespace dev::eth::jit; - - EXPORT void ext_store(Runtime* _rt, i256* _index, i256* o_value) - { - auto index = llvm2eth(*_index); - auto value = _rt->getExt().store(index); // Interface uses native endianness - *o_value = eth2llvm(value); - } - - EXPORT void ext_setStore(Runtime* _rt, i256* _index, i256* _value) - { - auto index = llvm2eth(*_index); - auto value = llvm2eth(*_value); - auto& ext = _rt->getExt(); - - if (value == 0 && ext.store(index) != 0) // If delete - ext.sub.refunds += c_sstoreRefundGas; // Increase refund counter - - ext.setStore(index, value); // Interface uses native endianness - } - - EXPORT void ext_calldataload(Runtime* _rt, i256* _index, i256* o_value) - { - auto index = static_cast(llvm2eth(*_index)); - assert(index + 31 > index); // TODO: Handle large index - auto b = reinterpret_cast(o_value); - for (size_t i = index, j = 0; i <= index + 31; ++i, ++j) - b[j] = i < _rt->getExt().data.size() ? _rt->getExt().data[i] : 0; // Keep Big Endian - // TODO: It all can be done by adding padding to data or by using min() algorithm without branch - } - - EXPORT void ext_balance(Runtime* _rt, h256* _address, i256* o_value) - { - auto u = _rt->getExt().balance(right160(*_address)); - *o_value = eth2llvm(u); - } - - EXPORT void ext_suicide(Runtime* _rt, h256 const* _address) - { - _rt->getExt().suicide(right160(*_address)); - } - - EXPORT void ext_create(Runtime* _rt, i256* _endowment, i256* _initOff, i256* _initSize, h256* o_address) - { - auto&& ext = _rt->getExt(); - auto endowment = llvm2eth(*_endowment); - - if (ext.balance(ext.myAddress) >= endowment) - { - ext.subBalance(endowment); - u256 gas; // TODO: Handle gas - auto initOff = static_cast(llvm2eth(*_initOff)); - auto initSize = static_cast(llvm2eth(*_initSize)); - auto&& initRef = bytesConstRef(_rt->getMemory().data() + initOff, initSize); - OnOpFunc onOp {}; // TODO: Handle that thing - h256 address(ext.create(endowment, &gas, initRef, onOp), h256::AlignRight); - *o_address = address; - } - else - *o_address = {}; - } - - - - EXPORT void ext_call(Runtime* _rt, i256* io_gas, h256* _receiveAddress, i256* _value, i256* _inOff, i256* _inSize, i256* _outOff, i256* _outSize, h256* _codeAddress, i256* o_ret) - { - auto&& ext = _rt->getExt(); - auto value = llvm2eth(*_value); - - auto ret = false; - auto gas = llvm2eth(*io_gas); - if (ext.balance(ext.myAddress) >= value) - { - ext.subBalance(value); - auto receiveAddress = right160(*_receiveAddress); - auto inOff = static_cast(llvm2eth(*_inOff)); - auto inSize = static_cast(llvm2eth(*_inSize)); - auto outOff = static_cast(llvm2eth(*_outOff)); - auto outSize = static_cast(llvm2eth(*_outSize)); - auto&& inRef = bytesConstRef(_rt->getMemory().data() + inOff, inSize); - auto&& outRef = bytesConstRef(_rt->getMemory().data() + outOff, outSize); - OnOpFunc onOp {}; // TODO: Handle that thing - auto codeAddress = right160(*_codeAddress); - ret = ext.call(receiveAddress, value, inRef, &gas, outRef, onOp, {}, codeAddress); - } - - *io_gas = eth2llvm(gas); - o_ret->a = ret ? 1 : 0; - } - - EXPORT void ext_sha3(Runtime* _rt, i256* _inOff, i256* _inSize, i256* o_ret) - { - auto inOff = static_cast(llvm2eth(*_inOff)); - auto inSize = static_cast(llvm2eth(*_inSize)); - auto dataRef = bytesConstRef(_rt->getMemory().data() + inOff, inSize); - auto hash = sha3(dataRef); - *o_ret = *reinterpret_cast(&hash); - } - - EXPORT void ext_exp(Runtime*, i256* _left, i256* _right, i256* o_ret) - { - bigint left = llvm2eth(*_left); - bigint right = llvm2eth(*_right); - auto ret = static_cast(boost::multiprecision::powm(left, right, bigint(2) << 256)); - *o_ret = eth2llvm(ret); - } - - EXPORT unsigned char* ext_codeAt(Runtime* _rt, h256* _addr256) - { - auto&& ext = _rt->getExt(); - auto addr = right160(*_addr256); - auto& code = ext.codeAt(addr); - return const_cast(code.data()); - } - - EXPORT void ext_codesizeAt(Runtime* _rt, h256* _addr256, i256* o_ret) - { - auto&& ext = _rt->getExt(); - auto addr = right160(*_addr256); - auto& code = ext.codeAt(addr); - *o_ret = eth2llvm(u256(code.size())); - } - - void ext_show_bytes(bytesConstRef _bytes) - { - for (auto b : _bytes) - std::cerr << std::hex << std::setw(2) << std::setfill('0') << static_cast(b) << " "; - std::cerr << std::endl; - } - - EXPORT void ext_log0(Runtime* _rt, i256* _memIdx, i256* _numBytes) - { - auto&& ext = _rt->getExt(); - - auto memIdx = llvm2eth(*_memIdx).convert_to(); - auto numBytes = llvm2eth(*_numBytes).convert_to(); - - auto dataRef = bytesConstRef(_rt->getMemory().data() + memIdx, numBytes); - ext.log({}, dataRef); - - if (_rt->outputLogs()) - { - std::cerr << "LOG: "; - ext_show_bytes(dataRef); - } - } - - EXPORT void ext_log1(Runtime* _rt, i256* _memIdx, i256* _numBytes, i256* _topic1) - { - auto&& ext = _rt->getExt(); - - auto memIdx = static_cast(llvm2eth(*_memIdx)); - auto numBytes = static_cast(llvm2eth(*_numBytes)); - - auto topic1 = llvm2eth(*_topic1); - - auto dataRef = bytesConstRef(_rt->getMemory().data() + memIdx, numBytes); - ext.log({topic1}, dataRef); - - if (_rt->outputLogs()) - { - std::cerr << "LOG [" << topic1 << "]: "; - ext_show_bytes(dataRef); - } - } - - EXPORT void ext_log2(Runtime* _rt, i256* _memIdx, i256* _numBytes, i256* _topic1, i256* _topic2) - { - auto&& ext = _rt->getExt(); - - auto memIdx = static_cast(llvm2eth(*_memIdx)); - auto numBytes = static_cast(llvm2eth(*_numBytes)); - - auto topic1 = llvm2eth(*_topic1); - auto topic2 = llvm2eth(*_topic2); - - auto dataRef = bytesConstRef(_rt->getMemory().data() + memIdx, numBytes); - ext.log({topic1, topic2}, dataRef); - - if (_rt->outputLogs()) - { - std::cerr << "LOG [" << topic1 << "][" << topic2 << "]: "; - ext_show_bytes(dataRef); - } - } - - EXPORT void ext_log3(Runtime* _rt, i256* _memIdx, i256* _numBytes, i256* _topic1, i256* _topic2, i256* _topic3) - { - auto&& ext = _rt->getExt(); - - auto memIdx = static_cast(llvm2eth(*_memIdx)); - auto numBytes = static_cast(llvm2eth(*_numBytes)); - - auto topic1 = llvm2eth(*_topic1); - auto topic2 = llvm2eth(*_topic2); - auto topic3 = llvm2eth(*_topic3); - - auto dataRef = bytesConstRef(_rt->getMemory().data() + memIdx, numBytes); - ext.log({topic1, topic2, topic3}, dataRef); - - if (_rt->outputLogs()) - { - std::cerr << "LOG [" << topic1 << "][" << topic2 << "][" << topic3 << "]: "; - ext_show_bytes(dataRef); - } - } - - EXPORT void ext_log4(Runtime* _rt, i256* _memIdx, i256* _numBytes, i256* _topic1, i256* _topic2, i256* _topic3, i256* _topic4) - { - auto&& ext = _rt->getExt(); - - auto memIdx = static_cast(llvm2eth(*_memIdx)); - auto numBytes = static_cast(llvm2eth(*_numBytes)); - - auto topic1 = llvm2eth(*_topic1); - auto topic2 = llvm2eth(*_topic2); - auto topic3 = llvm2eth(*_topic3); - auto topic4 = llvm2eth(*_topic4); - - auto dataRef = bytesConstRef(_rt->getMemory().data() + memIdx, numBytes); - ext.log({topic1, topic2, topic3, topic4}, dataRef); - - if (_rt->outputLogs()) - { - std::cerr << "LOG [" << topic1 << "][" << topic2 << "][" << topic3 << "][" << topic4 << "]: "; - ext_show_bytes(dataRef); - } - } -} -} -} - diff --git a/libevmjit/Ext.h b/libevmjit/Ext.h deleted file mode 100644 index 54380dda6..000000000 --- a/libevmjit/Ext.h +++ /dev/null @@ -1,69 +0,0 @@ - -#pragma once - -#include - -#include "CompilerHelper.h" - -namespace dev -{ -namespace eth -{ -namespace jit -{ - -class Ext : public RuntimeHelper -{ -public: - Ext(RuntimeManager& _runtimeManager); - - llvm::Value* store(llvm::Value* _index); - void setStore(llvm::Value* _index, llvm::Value* _value); - - llvm::Value* balance(llvm::Value* _address); - void suicide(llvm::Value* _address); - llvm::Value* calldataload(llvm::Value* _index); - llvm::Value* create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize); - llvm::Value* call(llvm::Value*& _gas, llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize, llvm::Value* _codeAddress); - - llvm::Value* sha3(llvm::Value* _inOff, llvm::Value* _inSize); - llvm::Value* exp(llvm::Value* _left, llvm::Value* _right); - llvm::Value* codeAt(llvm::Value* _addr); - llvm::Value* codesizeAt(llvm::Value* _addr); - - void log(llvm::Value* _memIdx, llvm::Value* _numBytes, size_t _numTopics, std::array const& _topics); - -private: - - llvm::Value* m_args[2]; - llvm::Value* m_arg2; - llvm::Value* m_arg3; - llvm::Value* m_arg4; - llvm::Value* m_arg5; - llvm::Value* m_arg6; - llvm::Value* m_arg7; - llvm::Value* m_arg8; - llvm::Value* m_data; - llvm::Function* m_store; - llvm::Function* m_setStore; - llvm::Function* m_calldataload; - llvm::Function* m_balance; - llvm::Function* m_suicide; - llvm::Function* m_create; - llvm::Function* m_call; - llvm::Function* m_sha3; - llvm::Function* m_exp; - llvm::Function* m_codeAt; - llvm::Function* m_codesizeAt; - llvm::Function* m_log0; - llvm::Function* m_log1; - llvm::Function* m_log2; - llvm::Function* m_log3; - llvm::Function* m_log4; -}; - - -} -} -} - diff --git a/libevmjit/GasMeter.cpp b/libevmjit/GasMeter.cpp deleted file mode 100644 index 48499259a..000000000 --- a/libevmjit/GasMeter.cpp +++ /dev/null @@ -1,199 +0,0 @@ - -#include "GasMeter.h" - -#include -#include -#include - -#include -#include - -#include "Type.h" -#include "Ext.h" -#include "Runtime.h" - -namespace dev -{ -namespace eth -{ -namespace jit -{ - -namespace // Helper functions -{ - -uint64_t getStepCost(Instruction inst) // TODO: Add this function to FeeSructure (pull request submitted) -{ - switch (inst) - { - case Instruction::STOP: - case Instruction::SUICIDE: - case Instruction::SSTORE: // Handle cost of SSTORE separately in GasMeter::countSStore() - return 0; - - case Instruction::SLOAD: - return static_cast(c_sloadGas); - - case Instruction::SHA3: - return static_cast(c_sha3Gas); - - case Instruction::BALANCE: - return static_cast(c_sha3Gas); - - case Instruction::CALL: - case Instruction::CALLCODE: - return static_cast(c_callGas); - - case Instruction::CREATE: - return static_cast(c_createGas); - - case Instruction::LOG0: - case Instruction::LOG1: - case Instruction::LOG2: - case Instruction::LOG3: - case Instruction::LOG4: - { - auto numTopics = static_cast(inst) - static_cast(Instruction::LOG0); - return static_cast(c_logGas) + numTopics * static_cast(c_logTopicGas); - } - - default: // Assumes instruction code is valid - return static_cast(c_stepGas); - } -} - -bool isCostBlockEnd(Instruction _inst) -{ - // Basic block terminators like STOP are not needed on the list - // as cost will be commited at the end of basic block - - // CALL & CALLCODE are commited manually - - switch (_inst) - { - case Instruction::CALLDATACOPY: - case Instruction::CODECOPY: - case Instruction::MLOAD: - case Instruction::MSTORE: - case Instruction::MSTORE8: - case Instruction::SSTORE: - case Instruction::GAS: - case Instruction::CREATE: - return true; - - default: - return false; - } -} - -} - -GasMeter::GasMeter(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager) : - CompilerHelper(_builder), - m_runtimeManager(_runtimeManager) -{ - auto module = getModule(); - - m_gasCheckFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::Word, false), llvm::Function::PrivateLinkage, "gas.check", module); - InsertPointGuard guard(m_builder); - - auto checkBB = llvm::BasicBlock::Create(_builder.getContext(), "Check", m_gasCheckFunc); - auto outOfGasBB = llvm::BasicBlock::Create(_builder.getContext(), "OutOfGas", m_gasCheckFunc); - auto updateBB = llvm::BasicBlock::Create(_builder.getContext(), "Update", m_gasCheckFunc); - - m_builder.SetInsertPoint(checkBB); - llvm::Value* cost = m_gasCheckFunc->arg_begin(); - cost->setName("cost"); - auto gas = m_runtimeManager.getGas(); - auto isOutOfGas = m_builder.CreateICmpUGT(cost, gas, "isOutOfGas"); - m_builder.CreateCondBr(isOutOfGas, outOfGasBB, updateBB); - - m_builder.SetInsertPoint(outOfGasBB); - _runtimeManager.raiseException(ReturnCode::OutOfGas); - m_builder.CreateUnreachable(); - - m_builder.SetInsertPoint(updateBB); - gas = m_builder.CreateSub(gas, cost); - m_runtimeManager.setGas(gas); - m_builder.CreateRetVoid(); -} - -void GasMeter::count(Instruction _inst) -{ - if (!m_checkCall) - { - // Create gas check call with mocked block cost at begining of current cost-block - m_checkCall = m_builder.CreateCall(m_gasCheckFunc, llvm::UndefValue::get(Type::Word)); - } - - m_blockCost += getStepCost(_inst); - - if (isCostBlockEnd(_inst)) - commitCostBlock(); -} - -void GasMeter::countSStore(Ext& _ext, llvm::Value* _index, llvm::Value* _newValue) -{ - assert(!m_checkCall); // Everything should've been commited before - - auto oldValue = _ext.store(_index); - auto oldValueIsZero = m_builder.CreateICmpEQ(oldValue, Constant::get(0), "oldValueIsZero"); - auto newValueIsZero = m_builder.CreateICmpEQ(_newValue, Constant::get(0), "newValueIsZero"); - auto oldValueIsntZero = m_builder.CreateICmpNE(oldValue, Constant::get(0), "oldValueIsntZero"); - auto newValueIsntZero = m_builder.CreateICmpNE(_newValue, Constant::get(0), "newValueIsntZero"); - auto isInsert = m_builder.CreateAnd(oldValueIsZero, newValueIsntZero, "isInsert"); - auto isDelete = m_builder.CreateAnd(oldValueIsntZero, newValueIsZero, "isDelete"); - auto cost = m_builder.CreateSelect(isInsert, Constant::get(c_sstoreSetGas), Constant::get(c_sstoreResetGas), "cost"); - cost = m_builder.CreateSelect(isDelete, Constant::get(0), cost, "cost"); - createCall(m_gasCheckFunc, cost); -} - -void GasMeter::countLogData(llvm::Value* _dataLength) -{ - assert(m_checkCall); - assert(m_blockCost > 0); // LOGn instruction is already counted - auto cost = m_builder.CreateMul(_dataLength, Constant::get(c_logDataGas), "logdata_cost"); - commitCostBlock(cost); -} - -void GasMeter::giveBack(llvm::Value* _gas) -{ - m_runtimeManager.setGas(m_builder.CreateAdd(m_runtimeManager.getGas(), _gas)); -} - -void GasMeter::commitCostBlock(llvm::Value* _additionalCost) -{ - assert(!_additionalCost || m_checkCall); // _additionalCost => m_checkCall; Must be inside cost-block - - // If any uncommited block - if (m_checkCall) - { - if (m_blockCost == 0) // Do not check 0 - { - m_checkCall->eraseFromParent(); // Remove the gas check call - m_checkCall = nullptr; - return; - } - - m_checkCall->setArgOperand(0, Constant::get(m_blockCost)); // Update block cost in gas check call - m_checkCall = nullptr; // End cost-block - m_blockCost = 0; - - if (_additionalCost) - { - m_builder.CreateCall(m_gasCheckFunc, _additionalCost); - } - } - assert(m_blockCost == 0); -} - -void GasMeter::checkMemory(llvm::Value* _additionalMemoryInWords) -{ - auto cost = m_builder.CreateNUWMul(_additionalMemoryInWords, Constant::get(static_cast(c_memoryGas)), "memcost"); - m_builder.CreateCall(m_gasCheckFunc, cost); -} - -} -} -} - diff --git a/libevmjit/GasMeter.h b/libevmjit/GasMeter.h deleted file mode 100644 index dfb4fb548..000000000 --- a/libevmjit/GasMeter.h +++ /dev/null @@ -1,54 +0,0 @@ - -#pragma once - -#include - -#include "CompilerHelper.h" - -namespace dev -{ -namespace eth -{ -namespace jit -{ -class RuntimeManager; - -class GasMeter : public CompilerHelper // TODO: Use RuntimeHelper -{ -public: - GasMeter(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager); - - /// Count step cost of instruction - void count(Instruction _inst); - - /// Calculate & count gas cost for SSTORE instruction - void countSStore(class Ext& _ext, llvm::Value* _index, llvm::Value* _newValue); - - /// Count gas cost of LOG data - void countLogData(llvm::Value* _dataLength); - - /// Finalize cost-block by checking gas needed for the block before the block - /// @param _additionalCost adds additional cost to cost-block before commit - void commitCostBlock(llvm::Value* _additionalCost = nullptr); - - /// Give back an amount of gas not used by a call - void giveBack(llvm::Value* _gas); - - /// Generate code that checks the cost of additional memory used by program - void checkMemory(llvm::Value* _additionalMemoryInWords); - -private: - /// Cumulative gas cost of a block of instructions - /// @TODO Handle overflow - uint64_t m_blockCost = 0; - - llvm::CallInst* m_checkCall = nullptr; - llvm::Function* m_gasCheckFunc = nullptr; - - RuntimeManager& m_runtimeManager; -}; - -} -} -} - diff --git a/libevmjit/Memory.cpp b/libevmjit/Memory.cpp deleted file mode 100644 index 53cccf92b..000000000 --- a/libevmjit/Memory.cpp +++ /dev/null @@ -1,218 +0,0 @@ -#include "Memory.h" - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include "Type.h" -#include "Runtime.h" -#include "GasMeter.h" -#include "Endianness.h" -#include "Runtime.h" - -namespace dev -{ -namespace eth -{ -namespace jit -{ - -Memory::Memory(RuntimeManager& _runtimeManager, GasMeter& _gasMeter): - RuntimeHelper(_runtimeManager) -{ - auto module = getModule(); - llvm::Type* argTypes[] = {Type::Word, Type::Word}; - auto dumpTy = llvm::FunctionType::get(m_builder.getVoidTy(), llvm::ArrayRef(argTypes), false); - m_memDump = llvm::Function::Create(dumpTy, llvm::GlobalValue::LinkageTypes::ExternalLinkage, - "evmccrt_memory_dump", module); - - m_data = new llvm::GlobalVariable(*module, Type::BytePtr, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::BytePtr), "mem.data"); - m_data->setUnnamedAddr(true); // Address is not important - - m_size = new llvm::GlobalVariable(*module, Type::Word, false, llvm::GlobalVariable::PrivateLinkage, Constant::get(0), "mem.size"); - m_size->setUnnamedAddr(true); // Address is not important - - llvm::Type* resizeArgs[] = {Type::RuntimePtr, Type::WordPtr}; - m_resize = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, resizeArgs, false), llvm::Function::ExternalLinkage, "mem_resize", module); - llvm::AttrBuilder attrBuilder; - attrBuilder.addAttribute(llvm::Attribute::NoAlias).addAttribute(llvm::Attribute::NoCapture).addAttribute(llvm::Attribute::NonNull).addAttribute(llvm::Attribute::ReadOnly); - m_resize->setAttributes(llvm::AttributeSet::get(m_resize->getContext(), 1, attrBuilder)); - - m_require = createRequireFunc(_gasMeter, _runtimeManager); - m_loadWord = createFunc(false, Type::Word, _gasMeter); - m_storeWord = createFunc(true, Type::Word, _gasMeter); - m_storeByte = createFunc(true, Type::Byte, _gasMeter); -} - -llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _runtimeManager) -{ - llvm::Type* argTypes[] = {Type::Word, Type::Word}; - auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, argTypes, false), llvm::Function::PrivateLinkage, "mem.require", getModule()); - auto offset = func->arg_begin(); - offset->setName("offset"); - auto size = offset->getNextNode(); - size->setName("size"); - - auto checkBB = llvm::BasicBlock::Create(func->getContext(), "Check", func); - auto resizeBB = llvm::BasicBlock::Create(func->getContext(), "Resize", func); - auto returnBB = llvm::BasicBlock::Create(func->getContext(), "Return", func); - - InsertPointGuard guard(m_builder); // Restores insert point at function exit - - // BB "Check" - m_builder.SetInsertPoint(checkBB); - auto uaddWO = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::uadd_with_overflow, Type::Word); - auto uaddRes = m_builder.CreateCall2(uaddWO, offset, size, "res"); - auto sizeRequired = m_builder.CreateExtractValue(uaddRes, 0, "sizeReq"); - auto overflow1 = m_builder.CreateExtractValue(uaddRes, 1, "overflow1"); - auto currSize = m_builder.CreateLoad(m_size, "currSize"); - auto tooSmall = m_builder.CreateICmpULE(currSize, sizeRequired, "tooSmall"); - auto resizeNeeded = m_builder.CreateOr(tooSmall, overflow1, "resizeNeeded"); - m_builder.CreateCondBr(resizeNeeded, resizeBB, returnBB); // OPT branch weights? - - // BB "Resize" - m_builder.SetInsertPoint(resizeBB); - // Check gas first - uaddRes = m_builder.CreateCall2(uaddWO, sizeRequired, Constant::get(31), "res"); - auto wordsRequired = m_builder.CreateExtractValue(uaddRes, 0); - auto overflow2 = m_builder.CreateExtractValue(uaddRes, 1, "overflow2"); - auto overflow = m_builder.CreateOr(overflow1, overflow2, "overflow"); - wordsRequired = m_builder.CreateSelect(overflow, Constant::get(-1), wordsRequired); - wordsRequired = m_builder.CreateUDiv(wordsRequired, Constant::get(32), "wordsReq"); - sizeRequired = m_builder.CreateMul(wordsRequired, Constant::get(32), "roundedSizeReq"); - auto words = m_builder.CreateUDiv(currSize, Constant::get(32), "words"); // size is always 32*k - auto newWords = m_builder.CreateSub(wordsRequired, words, "addtionalWords"); - _gasMeter.checkMemory(newWords); - // Resize - m_builder.CreateStore(sizeRequired, m_size); - auto newData = m_builder.CreateCall2(m_resize, _runtimeManager.getRuntimePtr(), m_size, "newData"); - m_builder.CreateStore(newData, m_data); - m_builder.CreateBr(returnBB); - - // BB "Return" - m_builder.SetInsertPoint(returnBB); - m_builder.CreateRetVoid(); - return func; -} - -llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, GasMeter&) -{ - auto isWord = _valueType == Type::Word; - - llvm::Type* storeArgs[] = {Type::Word, _valueType}; - auto name = _isStore ? isWord ? "mstore" : "mstore8" : "mload"; - auto funcType = _isStore ? llvm::FunctionType::get(Type::Void, storeArgs, false) : llvm::FunctionType::get(Type::Word, Type::Word, false); - auto func = llvm::Function::Create(funcType, llvm::Function::PrivateLinkage, name, getModule()); - - InsertPointGuard guard(m_builder); // Restores insert point at function exit - - m_builder.SetInsertPoint(llvm::BasicBlock::Create(func->getContext(), {}, func)); - llvm::Value* index = func->arg_begin(); - index->setName("index"); - - auto valueSize = _valueType->getPrimitiveSizeInBits() / 8; - this->require(index, Constant::get(valueSize)); - auto data = m_builder.CreateLoad(m_data, "data"); - auto ptr = m_builder.CreateGEP(data, index, "ptr"); - if (isWord) - ptr = m_builder.CreateBitCast(ptr, Type::WordPtr, "wordPtr"); - if (_isStore) - { - llvm::Value* value = ++func->arg_begin(); - value->setName("value"); - if (isWord) - value = Endianness::toBE(m_builder, value); - m_builder.CreateStore(value, ptr); - m_builder.CreateRetVoid(); - } - else - { - llvm::Value* ret = m_builder.CreateLoad(ptr); - ret = Endianness::toNative(m_builder, ret); - m_builder.CreateRet(ret); - } - - return func; -} - - -llvm::Value* Memory::loadWord(llvm::Value* _addr) -{ - auto value = m_builder.CreateCall(m_loadWord, _addr); - return value; -} - -void Memory::storeWord(llvm::Value* _addr, llvm::Value* _word) -{ - m_builder.CreateCall2(m_storeWord, _addr, _word); -} - -void Memory::storeByte(llvm::Value* _addr, llvm::Value* _word) -{ - auto byte = m_builder.CreateTrunc(_word, Type::Byte, "byte"); - m_builder.CreateCall2(m_storeByte, _addr, byte); -} - -llvm::Value* Memory::getData() -{ - return m_builder.CreateLoad(m_data); -} - -llvm::Value* Memory::getSize() -{ - return m_builder.CreateLoad(m_size); -} - -void Memory::require(llvm::Value* _offset, llvm::Value* _size) -{ - m_builder.CreateCall2(m_require, _offset, _size); -} - -void Memory::copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value* _srcIdx, - llvm::Value* _destMemIdx, llvm::Value* _reqBytes) -{ - auto zero256 = llvm::ConstantInt::get(Type::Word, 0); - - require(_destMemIdx, _reqBytes); - - auto srcPtr = m_builder.CreateGEP(_srcPtr, _srcIdx, "src_idx"); - - auto memPtr = getData(); - auto destPtr = m_builder.CreateGEP(memPtr, _destMemIdx, "dest_mem_ptr"); - - // remaining source bytes: - auto remSrcSize = m_builder.CreateSub(_srcSize, _srcIdx); - auto remSizeNegative = m_builder.CreateICmpSLT(remSrcSize, zero256); - auto remSrcBytes = m_builder.CreateSelect(remSizeNegative, zero256, remSrcSize, "rem_src_bytes"); - - auto tooFewSrcBytes = m_builder.CreateICmpULT(remSrcBytes, _reqBytes); - auto bytesToCopy = m_builder.CreateSelect(tooFewSrcBytes, remSrcBytes, _reqBytes, "bytes_to_copy"); - - m_builder.CreateMemCpy(destPtr, srcPtr, bytesToCopy, 0); -} - -} -} -} - - -extern "C" -{ - using namespace dev::eth::jit; - - EXPORT uint8_t* mem_resize(Runtime* _rt, i256* _size) - { - auto size = _size->a; // Trunc to 64-bit - auto& memory = _rt->getMemory(); - memory.resize(size); - return memory.data(); - } -} diff --git a/libevmjit/Memory.h b/libevmjit/Memory.h deleted file mode 100644 index c6ba02a54..000000000 --- a/libevmjit/Memory.h +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -#include - -#include "CompilerHelper.h" - -namespace dev -{ -namespace eth -{ -namespace jit -{ - -class Memory : public RuntimeHelper -{ -public: - Memory(RuntimeManager& _runtimeManager, class GasMeter& _gasMeter); - - llvm::Value* loadWord(llvm::Value* _addr); - void storeWord(llvm::Value* _addr, llvm::Value* _word); - void storeByte(llvm::Value* _addr, llvm::Value* _byte); - llvm::Value* getData(); - llvm::Value* getSize(); - void copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value* _srcIndex, - llvm::Value* _destMemIdx, llvm::Value* _byteCount); - - /// Requires the amount of memory to for data defined by offset and size. And counts gas fee for that memory. - void require(llvm::Value* _offset, llvm::Value* _size); - -private: - llvm::Function* createFunc(bool _isStore, llvm::Type* _type, GasMeter& _gasMeter); - llvm::Function* createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _runtimeManager); - - llvm::GlobalVariable* m_data; - llvm::GlobalVariable* m_size; - - llvm::Function* m_resize; - llvm::Function* m_require; - llvm::Function* m_loadWord; - llvm::Function* m_storeWord; - llvm::Function* m_storeByte; - - llvm::Function* m_memDump; -}; - -} -} -} - diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp deleted file mode 100644 index 8e52b648a..000000000 --- a/libevmjit/Runtime.cpp +++ /dev/null @@ -1,210 +0,0 @@ - -#include "Runtime.h" - -#include -#include -#include - -#include - -#include "Type.h" - -namespace dev -{ -namespace eth -{ -namespace jit -{ - -llvm::StructType* RuntimeData::getType() -{ - static llvm::StructType* type = nullptr; - if (!type) - { - llvm::Type* elems[] = - { - llvm::ArrayType::get(Type::Word, _size), - Type::BytePtr, - Type::BytePtr, - Type::BytePtr - }; - type = llvm::StructType::create(elems, "Runtime"); - } - return type; -} - -namespace -{ -llvm::Twine getName(RuntimeData::Index _index) -{ - switch (_index) - { - default: return "data"; - case RuntimeData::Gas: return "gas"; - case RuntimeData::Address: return "address"; - case RuntimeData::Caller: return "caller"; - case RuntimeData::Origin: return "origin"; - case RuntimeData::CallValue: return "callvalue"; - case RuntimeData::CallDataSize: return "calldatasize"; - case RuntimeData::GasPrice: return "gasprice"; - case RuntimeData::PrevHash: return "prevhash"; - case RuntimeData::CoinBase: return "coinbase"; - case RuntimeData::TimeStamp: return "timestamp"; - case RuntimeData::Number: return "number"; - case RuntimeData::Difficulty: return "difficulty"; - case RuntimeData::GasLimit: return "gaslimit"; - case RuntimeData::CodeSize: return "codesize"; - } -} -} - -Runtime::Runtime(u256 _gas, ExtVMFace& _ext, jmp_buf _jmpBuf, bool _outputLogs): - m_ext(_ext), - m_outputLogs(_outputLogs) -{ - set(RuntimeData::Gas, _gas); - set(RuntimeData::Address, fromAddress(_ext.myAddress)); - set(RuntimeData::Caller, fromAddress(_ext.caller)); - set(RuntimeData::Origin, fromAddress(_ext.origin)); - set(RuntimeData::CallValue, _ext.value); - set(RuntimeData::CallDataSize, _ext.data.size()); - set(RuntimeData::GasPrice, _ext.gasPrice); - set(RuntimeData::PrevHash, _ext.previousBlock.hash); - set(RuntimeData::CoinBase, fromAddress(_ext.currentBlock.coinbaseAddress)); - set(RuntimeData::TimeStamp, _ext.currentBlock.timestamp); - set(RuntimeData::Number, _ext.currentBlock.number); - set(RuntimeData::Difficulty, _ext.currentBlock.difficulty); - set(RuntimeData::GasLimit, _ext.currentBlock.gasLimit); - set(RuntimeData::CodeSize, _ext.code.size()); // TODO: Use constant - m_data.callData = _ext.data.data(); - m_data.code = _ext.code.data(); - m_data.jmpBuf = _jmpBuf; -} - -void Runtime::set(RuntimeData::Index _index, u256 _value) -{ - m_data.elems[_index] = eth2llvm(_value); -} - -u256 Runtime::getGas() const -{ - return llvm2eth(m_data.elems[RuntimeData::Gas]); -} - -bytesConstRef 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])); - - assert(offset + size <= m_memory.size()); - // TODO: Handle invalid data access by returning empty ref - return {m_memory.data() + offset, size}; -} - -bool Runtime::outputLogs() const -{ - return m_outputLogs; -} - - -RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder): CompilerHelper(_builder) -{ - m_dataPtr = new llvm::GlobalVariable(*getModule(), Type::RuntimePtr, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::RuntimePtr), "rt"); - m_longjmp = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::longjmp); - - // Export data - auto mainFunc = getMainFunction(); - llvm::Value* dataPtr = &mainFunc->getArgumentList().back(); - m_builder.CreateStore(dataPtr, m_dataPtr); -} - -llvm::Value* RuntimeManager::getRuntimePtr() -{ - if (auto mainFunc = getMainFunction()) - return mainFunc->arg_begin()->getNextNode(); // Runtime is the second parameter of main function - return m_builder.CreateLoad(m_dataPtr, "rt"); -} - -llvm::Value* RuntimeManager::getPtr(RuntimeData::Index _index) -{ - llvm::Value* idxList[] = {m_builder.getInt32(0), m_builder.getInt32(0), m_builder.getInt32(_index)}; - return m_builder.CreateInBoundsGEP(getRuntimePtr(), idxList, getName(_index) + "Ptr"); -} - -llvm::Value* RuntimeManager::get(RuntimeData::Index _index) -{ - return m_builder.CreateLoad(getPtr(_index), getName(_index)); -} - -void RuntimeManager::set(RuntimeData::Index _index, llvm::Value* _value) -{ - m_builder.CreateStore(_value, getPtr(_index)); -} - -void RuntimeManager::registerReturnData(llvm::Value* _offset, llvm::Value* _size) -{ - set(RuntimeData::ReturnDataOffset, _offset); - set(RuntimeData::ReturnDataSize, _size); -} - -void RuntimeManager::raiseException(ReturnCode _returnCode) -{ - m_builder.CreateCall2(m_longjmp, getJmpBuf(), Constant::get(_returnCode)); -} - -llvm::Value* RuntimeManager::get(Instruction _inst) -{ - switch (_inst) - { - default: assert(false); return nullptr; - case Instruction::GAS: return get(RuntimeData::Gas); - case Instruction::ADDRESS: return get(RuntimeData::Address); - case Instruction::CALLER: return get(RuntimeData::Caller); - case Instruction::ORIGIN: return get(RuntimeData::Origin); - case Instruction::CALLVALUE: return get(RuntimeData::CallValue); - case Instruction::CALLDATASIZE: return get(RuntimeData::CallDataSize); - case Instruction::GASPRICE: return get(RuntimeData::GasPrice); - case Instruction::PREVHASH: return get(RuntimeData::PrevHash); - case Instruction::COINBASE: return get(RuntimeData::CoinBase); - case Instruction::TIMESTAMP: return get(RuntimeData::TimeStamp); - case Instruction::NUMBER: return get(RuntimeData::Number); - case Instruction::DIFFICULTY: return get(RuntimeData::Difficulty); - case Instruction::GASLIMIT: return get(RuntimeData::GasLimit); - case Instruction::CODESIZE: return get(RuntimeData::CodeSize); - } -} - -llvm::Value* RuntimeManager::getCallData() -{ - auto ptr = getBuilder().CreateStructGEP(getRuntimePtr(), 1, "calldataPtr"); - return getBuilder().CreateLoad(ptr, "calldata"); -} - -llvm::Value* RuntimeManager::getCode() -{ - auto ptr = getBuilder().CreateStructGEP(getRuntimePtr(), 2, "codePtr"); - return getBuilder().CreateLoad(ptr, "code"); -} - -llvm::Value* RuntimeManager::getJmpBuf() -{ - auto ptr = getBuilder().CreateStructGEP(getRuntimePtr(), 3, "jmpbufPtr"); - return getBuilder().CreateLoad(ptr, "jmpbuf"); -} - -llvm::Value* RuntimeManager::getGas() -{ - return get(RuntimeData::Gas); -} - -void RuntimeManager::setGas(llvm::Value* _gas) -{ - llvm::Value* idxList[] = {m_builder.getInt32(0), m_builder.getInt32(0), m_builder.getInt32(RuntimeData::Gas)}; - auto ptr = m_builder.CreateInBoundsGEP(getRuntimePtr(), idxList, "gasPtr"); - m_builder.CreateStore(_gas, ptr); -} - -} -} -} diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h deleted file mode 100644 index 8f485794a..000000000 --- a/libevmjit/Runtime.h +++ /dev/null @@ -1,122 +0,0 @@ - -#pragma once - -#include -#include - -#include - -#include "CompilerHelper.h" -#include "Utils.h" -#include "Type.h" - - -#ifdef _MSC_VER - #define EXPORT __declspec(dllexport) -#else - #define EXPORT -#endif - -namespace dev -{ -namespace eth -{ -namespace jit -{ - -struct RuntimeData -{ - enum Index: unsigned - { - Gas, - Address, - Caller, - Origin, - CallValue, - CallDataSize, - GasPrice, - PrevHash, - CoinBase, - TimeStamp, - Number, - Difficulty, - GasLimit, - CodeSize, - - _size, - - ReturnDataOffset = CallValue, // Reuse 2 fields for return data reference - ReturnDataSize = CallDataSize - }; - - i256 elems[_size]; - byte const* callData; - byte const* code; - decltype(&jmp_buf{}[0]) jmpBuf; - - static llvm::StructType* getType(); -}; - -using StackImpl = std::vector; -using MemoryImpl = bytes; - -class Runtime -{ -public: - Runtime(u256 _gas, ExtVMFace& _ext, jmp_buf _jmpBuf, bool _outputLogs); - - Runtime(const Runtime&) = delete; - void operator=(const Runtime&) = delete; - - RuntimeData* getDataPtr() { return &m_data; } - - StackImpl& getStack() { return m_stack; } - MemoryImpl& getMemory() { return m_memory; } - ExtVMFace& getExt() { return m_ext; } - - u256 getGas() const; - bytesConstRef getReturnData() const; - decltype(&jmp_buf{}[0]) getJmpBuf() { return m_data.jmpBuf; } - bool outputLogs() const; - -private: - void set(RuntimeData::Index _index, u256 _value); - - /// @internal Must be the first element to asure Runtime* === RuntimeData* - RuntimeData m_data; - StackImpl m_stack; - MemoryImpl m_memory; - ExtVMFace& m_ext; - bool m_outputLogs; ///< write LOG statements to console -}; - -class RuntimeManager: public CompilerHelper -{ -public: - RuntimeManager(llvm::IRBuilder<>& _builder); - - llvm::Value* getRuntimePtr(); - - llvm::Value* get(RuntimeData::Index _index); - llvm::Value* get(Instruction _inst); - llvm::Value* getGas(); // TODO: Remove - llvm::Value* getCallData(); - llvm::Value* getCode(); - void setGas(llvm::Value* _gas); - - void registerReturnData(llvm::Value* _index, llvm::Value* _size); - - void raiseException(ReturnCode _returnCode); - -private: - llvm::Value* getPtr(RuntimeData::Index _index); - void set(RuntimeData::Index _index, llvm::Value* _value); - llvm::Value* getJmpBuf(); - - llvm::GlobalVariable* m_dataPtr = nullptr; - llvm::Function* m_longjmp = nullptr; -}; - -} -} -} diff --git a/libevmjit/Stack.cpp b/libevmjit/Stack.cpp deleted file mode 100644 index 494750b43..000000000 --- a/libevmjit/Stack.cpp +++ /dev/null @@ -1,112 +0,0 @@ -#include "Stack.h" -#include "Runtime.h" -#include "Type.h" - -#include - -#include -#include - -namespace dev -{ -namespace eth -{ -namespace jit -{ - -Stack::Stack(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager): - CompilerHelper(_builder), - m_runtimeManager(_runtimeManager) -{ - m_arg = m_builder.CreateAlloca(Type::Word, nullptr, "stack.arg"); - - using namespace llvm; - using Linkage = GlobalValue::LinkageTypes; - - auto module = getModule(); - - llvm::Type* pushArgTypes[] = {Type::RuntimePtr, Type::WordPtr}; - m_push = Function::Create(FunctionType::get(Type::Void, pushArgTypes, false), Linkage::ExternalLinkage, "stack_push", module); - - llvm::Type* popArgTypes[] = {Type::RuntimePtr, Type::Size}; - m_pop = Function::Create(FunctionType::get(Type::Void, popArgTypes, false), Linkage::ExternalLinkage, "stack_pop", module); - - llvm::Type* getSetArgTypes[] = {Type::RuntimePtr, Type::Size, Type::WordPtr}; - m_get = Function::Create(FunctionType::get(Type::Void, getSetArgTypes, false), Linkage::ExternalLinkage, "stack_get", module); - m_set = Function::Create(FunctionType::get(Type::Void, getSetArgTypes, false), Linkage::ExternalLinkage, "stack_set", module); -} - -llvm::Value* Stack::get(size_t _index) -{ - m_builder.CreateCall3(m_get, m_runtimeManager.getRuntimePtr(), llvm::ConstantInt::get(Type::Size, _index, false), m_arg); - return m_builder.CreateLoad(m_arg); -} - -void Stack::set(size_t _index, llvm::Value* _value) -{ - m_builder.CreateStore(_value, m_arg); - m_builder.CreateCall3(m_set, m_runtimeManager.getRuntimePtr(), llvm::ConstantInt::get(Type::Size, _index, false), m_arg); -} - -void Stack::pop(size_t _count) -{ - m_builder.CreateCall2(m_pop, m_runtimeManager.getRuntimePtr(), llvm::ConstantInt::get(Type::Size, _count, false)); -} - -void Stack::push(llvm::Value* _value) -{ - m_builder.CreateStore(_value, m_arg); - m_builder.CreateCall2(m_push, m_runtimeManager.getRuntimePtr(), m_arg); -} - - -size_t Stack::maxStackSize = 0; - -} -} -} - -extern "C" -{ - using namespace dev::eth::jit; - - EXPORT void stack_pop(Runtime* _rt, uint64_t _count) - { - auto& stack = _rt->getStack(); - if (stack.size() < _count) - longjmp(_rt->getJmpBuf(), static_cast(ReturnCode::StackTooSmall)); - - stack.erase(stack.end() - _count, stack.end()); - } - - EXPORT void stack_push(Runtime* _rt, i256 const* _word) - { - auto& stack = _rt->getStack(); - stack.push_back(*_word); - - if (stack.size() > Stack::maxStackSize) - Stack::maxStackSize = stack.size(); - } - - EXPORT void stack_get(Runtime* _rt, uint64_t _index, i256* o_ret) - { - auto& stack = _rt->getStack(); - // TODO: encode _index and stack size in the return code - if (stack.size() <= _index) - longjmp(_rt->getJmpBuf(), static_cast(ReturnCode::StackTooSmall)); - - *o_ret = *(stack.rbegin() + _index); - } - - EXPORT void stack_set(Runtime* _rt, uint64_t _index, i256 const* _word) - { - auto& stack = _rt->getStack(); - // TODO: encode _index and stack size in the return code - if (stack.size() <= _index) - longjmp(_rt->getJmpBuf(), static_cast(ReturnCode::StackTooSmall)); - - *(stack.rbegin() + _index) = *_word; - } - -} // extern "C" - diff --git a/libevmjit/Stack.h b/libevmjit/Stack.h deleted file mode 100644 index 3e8881e4f..000000000 --- a/libevmjit/Stack.h +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include "CompilerHelper.h" - -#include - -namespace dev -{ -namespace eth -{ -namespace jit -{ -class RuntimeManager; - -class Stack : public CompilerHelper -{ -public: - Stack(llvm::IRBuilder<>& builder, RuntimeManager& runtimeManager); - - llvm::Value* get(size_t _index); - void set(size_t _index, llvm::Value* _value); - void pop(size_t _count); - void push(llvm::Value* _value); - - static size_t maxStackSize; - -private: - RuntimeManager& m_runtimeManager; - - llvm::Function* m_push; - llvm::Function* m_pop; - llvm::Function* m_get; - llvm::Function* m_set; - - llvm::Value* m_arg; -}; - - -} -} -} - - diff --git a/libevmjit/Type.cpp b/libevmjit/Type.cpp deleted file mode 100644 index a72ec0eda..000000000 --- a/libevmjit/Type.cpp +++ /dev/null @@ -1,59 +0,0 @@ - -#include "Type.h" - -#include - -#include "Runtime.h" - -namespace dev -{ -namespace eth -{ -namespace jit -{ - -llvm::IntegerType* Type::Word; -llvm::PointerType* Type::WordPtr; -llvm::IntegerType* Type::lowPrecision; -llvm::IntegerType* Type::Size; -llvm::IntegerType* Type::Byte; -llvm::PointerType* Type::BytePtr; -llvm::Type* Type::Void; -llvm::IntegerType* Type::MainReturn; -llvm::PointerType* Type::RuntimePtr; - -void Type::init(llvm::LLVMContext& _context) -{ - Word = llvm::Type::getIntNTy(_context, 256); - WordPtr = Word->getPointerTo(); - lowPrecision = llvm::Type::getInt64Ty(_context); - // TODO: Size should be architecture-dependent - Size = llvm::Type::getInt64Ty(_context); - Byte = llvm::Type::getInt8Ty(_context); - BytePtr = Byte->getPointerTo(); - Void = llvm::Type::getVoidTy(_context); - MainReturn = llvm::Type::getInt32Ty(_context); - RuntimePtr = RuntimeData::getType()->getPointerTo(); -} - -llvm::ConstantInt* Constant::get(int64_t _n) -{ - return llvm::ConstantInt::getSigned(Type::Word, _n); -} - -llvm::ConstantInt* Constant::get(u256 _n) -{ - llvm::APInt n(256, _n.str(0, std::ios_base::hex), 16); - assert(n.toString(10, false) == _n.str()); - return static_cast(llvm::ConstantInt::get(Type::Word, n)); -} - -llvm::ConstantInt* Constant::get(ReturnCode _returnCode) -{ - return llvm::ConstantInt::get(Type::MainReturn, static_cast(_returnCode)); -} - -} -} -} - diff --git a/libevmjit/Type.h b/libevmjit/Type.h deleted file mode 100644 index 0d8c6c530..000000000 --- a/libevmjit/Type.h +++ /dev/null @@ -1,63 +0,0 @@ - -#pragma once - -#include -#include -#include - -namespace dev -{ -namespace eth -{ -namespace jit -{ - -struct Type -{ - static llvm::IntegerType* Word; - static llvm::PointerType* WordPtr; - - /// Type for doing low precision arithmetics where 256-bit precision is not supported by native target - /// @TODO: Use 64-bit for now. In 128-bit compiler-rt library functions are required - static llvm::IntegerType* lowPrecision; - - static llvm::IntegerType* Size; - - static llvm::IntegerType* Byte; - static llvm::PointerType* BytePtr; - - static llvm::Type* Void; - - /// Main function return type - static llvm::IntegerType* MainReturn; - - static llvm::PointerType* RuntimePtr; - - 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 - static llvm::ConstantInt* get(int64_t _n); - static llvm::ConstantInt* get(u256 _n); - - static llvm::ConstantInt* get(ReturnCode _returnCode); -}; - -} -} -} - diff --git a/libevmjit/Utils.cpp b/libevmjit/Utils.cpp deleted file mode 100644 index 548ee0e1f..000000000 --- a/libevmjit/Utils.cpp +++ /dev/null @@ -1,57 +0,0 @@ - -#include "Utils.h" - -namespace dev -{ -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; -} - -u256 readPushData(bytes::const_iterator& _curr, bytes::const_iterator _end) -{ - auto pushInst = *_curr; - assert(Instruction(pushInst) >= Instruction::PUSH1 && Instruction(pushInst) <= Instruction::PUSH32); - auto numBytes = pushInst - static_cast(Instruction::PUSH1) + 1; - u256 value; - ++_curr; // Point the data - for (decltype(numBytes) i = 0; i < numBytes; ++i) - { - byte b = (_curr != _end) ? *_curr++ : 0; - value <<= 8; - value |= b; - } - --_curr; // Point the last real byte read - return value; -} - -} -} -} diff --git a/libevmjit/Utils.h b/libevmjit/Utils.h deleted file mode 100644 index 54291f3e0..000000000 --- a/libevmjit/Utils.h +++ /dev/null @@ -1,107 +0,0 @@ - -#pragma once - -#include - -#include -#include -#include - -namespace dev -{ -namespace eth -{ -namespace jit -{ - -struct JIT: public NoteChannel { static const char* name() { return "JIT"; } }; - -/// 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); - -/// Reads PUSH data from pointed fragment of bytecode and constructs number out of it -/// Reading out of bytecode means reading 0 -/// @param _curr is updates and points the last real byte read -u256 readPushData(bytes::const_iterator& _curr, bytes::const_iterator _end); - -#define ANY_PUSH PUSH1: \ - case Instruction::PUSH2: \ - case Instruction::PUSH3: \ - case Instruction::PUSH4: \ - case Instruction::PUSH5: \ - case Instruction::PUSH6: \ - case Instruction::PUSH7: \ - case Instruction::PUSH8: \ - case Instruction::PUSH9: \ - case Instruction::PUSH10: \ - case Instruction::PUSH11: \ - case Instruction::PUSH12: \ - case Instruction::PUSH13: \ - case Instruction::PUSH14: \ - case Instruction::PUSH15: \ - case Instruction::PUSH16: \ - case Instruction::PUSH17: \ - case Instruction::PUSH18: \ - case Instruction::PUSH19: \ - case Instruction::PUSH20: \ - case Instruction::PUSH21: \ - case Instruction::PUSH22: \ - case Instruction::PUSH23: \ - case Instruction::PUSH24: \ - case Instruction::PUSH25: \ - case Instruction::PUSH26: \ - case Instruction::PUSH27: \ - case Instruction::PUSH28: \ - case Instruction::PUSH29: \ - case Instruction::PUSH30: \ - case Instruction::PUSH31: \ - case Instruction::PUSH32 - -#define ANY_DUP DUP1: \ - case Instruction::DUP2: \ - case Instruction::DUP3: \ - case Instruction::DUP4: \ - case Instruction::DUP5: \ - case Instruction::DUP6: \ - case Instruction::DUP7: \ - case Instruction::DUP8: \ - case Instruction::DUP9: \ - case Instruction::DUP10: \ - case Instruction::DUP11: \ - case Instruction::DUP12: \ - case Instruction::DUP13: \ - case Instruction::DUP14: \ - case Instruction::DUP15: \ - case Instruction::DUP16 - -#define ANY_SWAP SWAP1: \ - case Instruction::SWAP2: \ - case Instruction::SWAP3: \ - case Instruction::SWAP4: \ - case Instruction::SWAP5: \ - case Instruction::SWAP6: \ - case Instruction::SWAP7: \ - case Instruction::SWAP8: \ - case Instruction::SWAP9: \ - case Instruction::SWAP10: \ - case Instruction::SWAP11: \ - case Instruction::SWAP12: \ - case Instruction::SWAP13: \ - case Instruction::SWAP14: \ - case Instruction::SWAP15: \ - case Instruction::SWAP16 - -} -} -} diff --git a/libevmjit/VM.cpp b/libevmjit/VM.cpp deleted file mode 100644 index b968008aa..000000000 --- a/libevmjit/VM.cpp +++ /dev/null @@ -1,46 +0,0 @@ - -#include "VM.h" - -#include -#include - -#include "ExecutionEngine.h" -#include "Compiler.h" -#include "Type.h" - -namespace dev -{ -namespace eth -{ -namespace jit -{ - -bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const&, uint64_t) -{ - Compiler::Options defaultOptions; - auto module = Compiler(defaultOptions).compile(_ext.code); - - ExecutionEngine engine; - auto exitCode = engine.run(std::move(module), m_gas, false, _ext); - - switch (static_cast(exitCode)) - { - case ReturnCode::BadJumpDestination: - BOOST_THROW_EXCEPTION(BadJumpDestination()); - case ReturnCode::OutOfGas: - BOOST_THROW_EXCEPTION(OutOfGas()); - case ReturnCode::StackTooSmall: - BOOST_THROW_EXCEPTION(StackTooSmall()); - case ReturnCode::BadInstruction: - BOOST_THROW_EXCEPTION(BadInstruction()); - default: - break; - } - - m_output = std::move(engine.returnData); - return {m_output.data(), m_output.size()}; // TODO: This all bytesConstRef stuff sucks -} - -} -} -} diff --git a/libevmjit/VM.h b/libevmjit/VM.h deleted file mode 100644 index 1c6c71181..000000000 --- a/libevmjit/VM.h +++ /dev/null @@ -1,34 +0,0 @@ - -#pragma once - -#include -#include -#include - -namespace dev -{ -namespace eth -{ - -class VMFactory; - -namespace jit -{ - -class VM: public VMFace -{ - virtual bytesConstRef go(ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) override final; - - enum Kind: bool { Interpreter, JIT }; - static std::unique_ptr create(Kind, u256 _gas = 0); - -private: - friend VMFactory; - explicit VM(u256 _gas = 0): VMFace(_gas) {} - - bytes m_output; -}; - -} -} -} diff --git a/libevmjit/interface.c b/libevmjit/interface.c deleted file mode 100644 index 47589578b..000000000 --- a/libevmjit/interface.c +++ /dev/null @@ -1,30 +0,0 @@ -#include - -// 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; - -// 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); From cc7578249631bf48aa1f27f09cb36138e1e66c89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 5 Dec 2014 09:17:20 +0100 Subject: [PATCH 409/641] Update evmjit submodule --- evmjit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evmjit b/evmjit index 6f84f3d1a..c6fcdbc7d 160000 --- a/evmjit +++ b/evmjit @@ -1 +1 @@ -Subproject commit 6f84f3d1ade42bcacc99533d4807b9b759a5938b +Subproject commit c6fcdbc7d650054c4ed597e735633a45144dc3df From 72552c4936db8bef2d31ae2d301bfff1db395d4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 5 Dec 2014 09:26:07 +0100 Subject: [PATCH 410/641] Move helper functions back to VM --- libevm/VM.h | 19 +++++++++++++------ libevm/VMFace.h | 15 --------------- 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/libevm/VM.h b/libevm/VM.h index b4a0664ec..c95242dfa 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -38,6 +38,13 @@ namespace eth class VMFactory; +// Convert from a 256-bit integer stack/memory entry into a 160-bit Address hash. +// Currently we just pull out the right (low-order in BE) 160-bits. +inline Address asAddress(u256 _item) +{ + return right160(h256(_item)); +} + inline u256 fromAddress(Address _a) { return (u160)_a; @@ -151,7 +158,7 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con case Instruction::SLOAD: require(1); - runGas = c_sloadGas; + runGas = c_sloadGas; break; // These all operate on memory and therefore potentially expand it: @@ -223,7 +230,7 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con u256 inOff = m_stack[m_stack.size() - 2]; u256 inSize = m_stack[m_stack.size() - 3]; newTempSize = (bigint)inOff + inSize; - runGas = c_createGas; + runGas = c_createGas; break; } case Instruction::EXP: @@ -399,7 +406,7 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con m_stack.pop_back(); break; case Instruction::SDIV: - m_stack[m_stack.size() - 2] = m_stack[m_stack.size() - 2] ? s2u(u2s(m_stack.back()) / u2s(m_stack[m_stack.size() - 2])) : 0; + m_stack[m_stack.size() - 2] = m_stack[m_stack.size() - 2] ? s2u(u2s(m_stack.back()) / u2s(m_stack[m_stack.size() - 2])) : 0; m_stack.pop_back(); break; case Instruction::MOD: @@ -407,7 +414,7 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con m_stack.pop_back(); break; case Instruction::SMOD: - m_stack[m_stack.size() - 2] = m_stack[m_stack.size() - 2] ? s2u(u2s(m_stack.back()) % u2s(m_stack[m_stack.size() - 2])) : 0; + m_stack[m_stack.size() - 2] = m_stack[m_stack.size() - 2] ? s2u(u2s(m_stack.back()) % u2s(m_stack[m_stack.size() - 2])) : 0; m_stack.pop_back(); break; case Instruction::EXP: @@ -430,11 +437,11 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con m_stack.pop_back(); break; case Instruction::SLT: - m_stack[m_stack.size() - 2] = u2s(m_stack.back()) < u2s(m_stack[m_stack.size() - 2]) ? 1 : 0; + m_stack[m_stack.size() - 2] = u2s(m_stack.back()) < u2s(m_stack[m_stack.size() - 2]) ? 1 : 0; m_stack.pop_back(); break; case Instruction::SGT: - m_stack[m_stack.size() - 2] = u2s(m_stack.back()) > u2s(m_stack[m_stack.size() - 2]) ? 1 : 0; + m_stack[m_stack.size() - 2] = u2s(m_stack.back()) > u2s(m_stack[m_stack.size() - 2]) ? 1 : 0; m_stack.pop_back(); break; case Instruction::EQ: diff --git a/libevm/VMFace.h b/libevm/VMFace.h index 6617db1da..f4dd3096e 100644 --- a/libevm/VMFace.h +++ b/libevm/VMFace.h @@ -34,21 +34,6 @@ struct BadJumpDestination: virtual VMException {}; struct OutOfGas: virtual VMException {}; struct StackTooSmall: virtual public VMException {}; -// Convert from a 256-bit integer stack/memory entry into a 160-bit Address hash. -// Currently we just pull out the right (low-order in BE) 160-bits. -inline Address asAddress(u256 _item) -{ - return right160(h256(_item)); -} - -inline u256 fromAddress(Address _a) -{ - return (u160)_a; - // h256 ret; - // memcpy(&ret, &_a, sizeof(_a)); - // return ret; -} - /** */ class VMFace From 31c3d111ada2285805114cb8b6aa3f487e52c0c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 5 Dec 2014 09:43:29 +0100 Subject: [PATCH 411/641] Windows fix & used code removed --- libevm/ExtVMFace.h | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h index 9e6601d0a..9d107a4b6 100644 --- a/libevm/ExtVMFace.h +++ b/libevm/ExtVMFace.h @@ -36,20 +36,12 @@ namespace dev namespace eth { -template inline std::set toSet(std::vector const& _ts) -{ - std::set ret; - for (auto const& t: _ts) - ret.insert(t); - return ret; -} - using LogBloom = h512; struct LogEntry { LogEntry() {} - LogEntry(RLP const& _r) { address = (Address)_r[0]; topics = (h256s)_r[1]; data = _r[2].toBytes(); } + LogEntry(RLP const& _r) { address = (Address)_r[0]; topics = _r[1].toVector(); data = _r[2].toBytes(); } LogEntry(Address const& _address, h256s const& _ts, bytes&& _d): address(_address), topics(_ts), data(std::move(_d)) {} void streamRLP(RLPStream& _s) const { _s.appendList(3) << address << topics << data; } From 312ee43aa2ff2d09c5d37a73e940bcadaab9a9f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 5 Dec 2014 10:13:14 +0100 Subject: [PATCH 412/641] Cleanups --- evmjit | 2 +- libethereum/VMFactory.cpp | 4 ++-- windows/LibEvmJitCpp.vcxproj | 4 ++-- windows/LibEvmJitCpp.vcxproj.filters | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/evmjit b/evmjit index c6fcdbc7d..2b9b53024 160000 --- a/evmjit +++ b/evmjit @@ -1 +1 @@ -Subproject commit c6fcdbc7d650054c4ed597e735633a45144dc3df +Subproject commit 2b9b53024dfa62b62a322909a43154f65f29d4ce diff --git a/libethereum/VMFactory.cpp b/libethereum/VMFactory.cpp index a5910ed15..3077ed546 100644 --- a/libethereum/VMFactory.cpp +++ b/libethereum/VMFactory.cpp @@ -1,7 +1,7 @@ #include #if ETH_EVMJIT - #include + #include #endif #include "VMFactory.h" @@ -14,7 +14,7 @@ namespace eth std::unique_ptr VMFactory::create(VMFactory::Kind _kind, u256 _gas) { #if ETH_EVMJIT - auto vm = _kind == Kind::JIT ? static_cast(new jit::VM) + auto vm = _kind == Kind::JIT ? static_cast(new JitVM) : static_cast(new VM); #else VMFace* vm = new VM; diff --git a/windows/LibEvmJitCpp.vcxproj b/windows/LibEvmJitCpp.vcxproj index a5094e49c..d72bcd981 100644 --- a/windows/LibEvmJitCpp.vcxproj +++ b/windows/LibEvmJitCpp.vcxproj @@ -127,10 +127,10 @@ - + - + diff --git a/windows/LibEvmJitCpp.vcxproj.filters b/windows/LibEvmJitCpp.vcxproj.filters index 0c37264b0..4bf360cbe 100644 --- a/windows/LibEvmJitCpp.vcxproj.filters +++ b/windows/LibEvmJitCpp.vcxproj.filters @@ -4,10 +4,10 @@ - + - + \ No newline at end of file From f990a1ac632d6ff0067e8e14cdd234f49f0a54db Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 5 Dec 2014 10:17:42 +0100 Subject: [PATCH 413/641] mix IDE M1 first commit --- mix/ApplicationCtx.cpp | 62 +++++++- mix/ApplicationCtx.h | 19 ++- mix/AssemblyDebuggerCtrl.cpp | 84 +++++++++++ mix/AssemblyDebuggerCtrl.h | 55 +++++++ mix/AssemblyDebuggerModel.cpp | 111 ++++++++++++++ mix/AssemblyDebuggerModel.h | 49 ++++++ mix/CodeEditorExtensionManager.cpp | 22 ++- mix/CodeEditorExtensionManager.h | 3 +- mix/ConstantCompilationCtrl.cpp | 4 +- mix/ConstantCompilationModel.cpp | 1 + mix/ConstantCompilationModel.h | 2 + mix/DebuggingStateWrapper.cpp | 189 +++++++++++++++++++++++ mix/DebuggingStateWrapper.h | 133 +++++++++++++++++ mix/Extension.cpp | 29 +++- mix/Extension.h | 14 +- mix/KeyEventManager.cpp | 43 ++++++ mix/KeyEventManager.h | 42 ++++++ mix/TransactionBuilder.cpp | 92 ++++++++++++ mix/TransactionBuilder.h | 48 ++++++ mix/main.cpp | 3 + mix/qml.qrc | 3 + mix/qml/BasicMessage.qml | 20 +++ mix/qml/Debugger.qml | 231 +++++++++++++++++++++++++++++ mix/qml/MainContent.qml | 24 ++- mix/qml/js/Debugger.js | 63 ++++++++ mix/qml/main.qml | 40 ++++- 26 files changed, 1353 insertions(+), 33 deletions(-) create mode 100644 mix/AssemblyDebuggerCtrl.cpp create mode 100644 mix/AssemblyDebuggerCtrl.h create mode 100644 mix/AssemblyDebuggerModel.cpp create mode 100644 mix/AssemblyDebuggerModel.h create mode 100644 mix/DebuggingStateWrapper.cpp create mode 100644 mix/DebuggingStateWrapper.h create mode 100644 mix/KeyEventManager.cpp create mode 100644 mix/KeyEventManager.h create mode 100644 mix/TransactionBuilder.cpp create mode 100644 mix/TransactionBuilder.h create mode 100644 mix/qml/BasicMessage.qml create mode 100644 mix/qml/Debugger.qml create mode 100644 mix/qml/js/Debugger.js diff --git a/mix/ApplicationCtx.cpp b/mix/ApplicationCtx.cpp index f97478f3c..52e66dab7 100644 --- a/mix/ApplicationCtx.cpp +++ b/mix/ApplicationCtx.cpp @@ -14,23 +14,83 @@ /** @file ApplicationCtx.cpp * @author Yann yann@ethdev.com * @date 2014 - * Provide an access to the current QQmlApplicationEngine which is used to add QML file on the fly. + * Provides an access to the current QQmlApplicationEngine which is used to add QML file on the fly. * In the future this class can be extended to add more variable related to the context of the application. + * For now ApplicationCtx provides reference to: + * - QQmlApplicationEngine + * - dev::WebThreeDirect (and dev::eth::Client) + * - KeyEventManager */ +#include +#include +#include #include +#include "libdevcrypto/FileSystem.h" +#include "KeyEventManager.h" #include "ApplicationCtx.h" +using namespace dev; using namespace dev::mix; +using namespace dev::eth; ApplicationCtx* ApplicationCtx::Instance = nullptr; +ApplicationCtx::ApplicationCtx(QQmlApplicationEngine* _engine) +{ + m_applicationEngine = _engine; + m_keyEventManager = std::unique_ptr(); + m_webThree = std::unique_ptr(); + m_webThree.reset(new WebThreeDirect(std::string("Mix/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir() + "/Mix", false, {"eth", "shh"})); + m_keyEventManager.reset(new KeyEventManager()); +} + +ApplicationCtx::~ApplicationCtx() +{ + delete m_applicationEngine; +} + QQmlApplicationEngine* ApplicationCtx::appEngine() { return m_applicationEngine; } +dev::eth::Client* ApplicationCtx::getEthereumClient() +{ + return m_webThree.get()->ethereum(); +} + +void ApplicationCtx::initKeyEventManager() +{ + QObject* mainContent = m_applicationEngine->rootObjects().at(0)->findChild("mainContent", Qt::FindChildrenRecursively); + if (mainContent) + { + QObject::connect(mainContent, SIGNAL(keyPressed(QVariant)), m_keyEventManager.get(), SLOT(keyPressed(QVariant))); + } + else + qDebug() << "Unable to find QObject of mainContent.qml. KeyEvent will not be handled!"; +} + +KeyEventManager* ApplicationCtx::getKeyEventManager() +{ + return m_keyEventManager.get(); +} + void ApplicationCtx::setApplicationContext(QQmlApplicationEngine* _engine) { if (Instance == nullptr) Instance = new ApplicationCtx(_engine); } + +void ApplicationCtx::displayMessageDialog(QString _title, QString _message) +{ + QQmlComponent component(m_applicationEngine, QUrl("qrc:/qml/BasicMessage.qml")); + QObject* dialog = component.create(); + dialog->findChild("messageContent", Qt::FindChildrenRecursively)->setProperty("text", _message); + QObject* dialogWin = ApplicationCtx::getInstance()->appEngine()->rootObjects().at(0)->findChild("messageDialog", Qt::FindChildrenRecursively); + QMetaObject::invokeMethod(dialogWin, "close"); + dialogWin->setProperty("contentItem", QVariant::fromValue(dialog)); + dialogWin->setProperty("title", _title); + dialogWin->setProperty("width", "250"); + dialogWin->setProperty("height", "100"); + QMetaObject::invokeMethod(dialogWin, "open"); +} diff --git a/mix/ApplicationCtx.h b/mix/ApplicationCtx.h index 37166ea05..05e4f3bb3 100644 --- a/mix/ApplicationCtx.h +++ b/mix/ApplicationCtx.h @@ -16,14 +16,19 @@ */ /** @file ApplicationCtx.h * @author Yann yann@ethdev.com - * @date 2014 - * Provide an access to the current QQmlApplicationEngine which is used to add QML file on the fly. + * Provides an access to the current QQmlApplicationEngine which is used to add QML file on the fly. * In the future this class can be extended to add more variable related to the context of the application. + * For now ApplicationCtx provides reference to: + * - QQmlApplicationEngine + * - dev::WebThreeDirect (and dev::eth::Client) + * - KeyEventManager */ #pragma once #include +#include "libwebthree/WebThree.h" +#include "KeyEventManager.h" namespace dev { @@ -36,15 +41,21 @@ class ApplicationCtx: public QObject Q_OBJECT public: - ApplicationCtx(QQmlApplicationEngine* _engine) { m_applicationEngine = _engine; } - ~ApplicationCtx() { delete m_applicationEngine; } + ApplicationCtx(QQmlApplicationEngine* _engine); + ~ApplicationCtx(); static ApplicationCtx* getInstance() { return Instance; } static void setApplicationContext(QQmlApplicationEngine* _engine); QQmlApplicationEngine* appEngine(); + dev::eth::Client* getEthereumClient(); + void initKeyEventManager(); + KeyEventManager* getKeyEventManager(); + void displayMessageDialog(QString _title, QString _message); private: static ApplicationCtx* Instance; QQmlApplicationEngine* m_applicationEngine; + std::unique_ptr m_webThree; + std::unique_ptr m_keyEventManager; public slots: void quitApplication() { delete Instance; } diff --git a/mix/AssemblyDebuggerCtrl.cpp b/mix/AssemblyDebuggerCtrl.cpp new file mode 100644 index 000000000..e8b0391d8 --- /dev/null +++ b/mix/AssemblyDebuggerCtrl.cpp @@ -0,0 +1,84 @@ +/* + This file is part of cpp-ethereum. + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file AssemblyDebuggerCtrl.h + * @author Yann yann@ethdev.com + * @date 2014 + * display opcode debugging. + */ + +#include +#include +#include +#include "libethereum/Transaction.h" +#include "AssemblyDebuggerModel.h" +#include "AssemblyDebuggerCtrl.h" +#include "TransactionBuilder.h" +#include "KeyEventManager.h" +#include "ApplicationCtx.h" +#include "DebuggingStateWrapper.h" +using namespace dev::mix; + +AssemblyDebuggerCtrl::AssemblyDebuggerCtrl(QTextDocument* _doc): Extension(ExtensionDisplayBehavior::ModalDialog) +{ + m_modelDebugger = std::unique_ptr(new AssemblyDebuggerModel); + m_doc = _doc; +} + +QString AssemblyDebuggerCtrl::contentUrl() const +{ + return QStringLiteral("qrc:/qml/Debugger.qml"); +} + +QString AssemblyDebuggerCtrl::title() const +{ + return "debugger"; +} + +void AssemblyDebuggerCtrl::start() const +{ + //start to listen on F5 + ApplicationCtx::getInstance()->getKeyEventManager()->registerEvent(this, SLOT(keyPressed(int))); +} + +void AssemblyDebuggerCtrl::keyPressed(int _key) +{ + if (_key == Qt::Key_F5) + { + if (!m_modelDebugger->compile(m_doc->toPlainText())) + { + ApplicationCtx::getInstance()->displayMessageDialog("debugger","compilation failed"); + return; + } + + KeyPair ad = KeyPair::create(); + u256 gasPrice = 10000000000000; + u256 gas = 1000000; + u256 amount = 100; + DebuggingContent debuggingContent = m_modelDebugger->getContractInitiationDebugStates(amount, gasPrice, gas, m_doc->toPlainText(), ad); + + //we need to wrap states in a QObject before sending to QML. + QList wStates; + for(int i = 0; i < debuggingContent.states.size(); i++) + { + DebuggingStateWrapper* s = new DebuggingStateWrapper(debuggingContent.executionCode, debuggingContent.executionData.toBytes()); + s->setState(debuggingContent.states.at(i)); + wStates.append(s); + } + std::tuple, QQMLMap*> code = DebuggingStateWrapper::getHumanReadableCode(debuggingContent.executionCode); + ApplicationCtx::getInstance()->appEngine()->rootContext()->setContextProperty("debugStates", QVariant::fromValue(wStates)); + ApplicationCtx::getInstance()->appEngine()->rootContext()->setContextProperty("humanReadableExecutionCode", QVariant::fromValue(std::get<0>(code))); + ApplicationCtx::getInstance()->appEngine()->rootContext()->setContextProperty("bytesCodeMapping", QVariant::fromValue(std::get<1>(code))); + this->addContentOn(this); + }; +} diff --git a/mix/AssemblyDebuggerCtrl.h b/mix/AssemblyDebuggerCtrl.h new file mode 100644 index 000000000..a1642cc14 --- /dev/null +++ b/mix/AssemblyDebuggerCtrl.h @@ -0,0 +1,55 @@ +/* + This file is part of cpp-ethereum. + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file AssemblyDebuggerCtrl.h + * @author Yann yann@ethdev.com + * @date 2014 + * Ethereum IDE client. + */ + +#pragma once + +#include +#include "QTextDocument" +#include "Extension.h" +#include "ConstantCompilationModel.h" +#include "AssemblyDebuggerModel.h" + +namespace dev +{ + +namespace mix +{ + +class AssemblyDebuggerCtrl: public Extension +{ + Q_OBJECT + +public: + AssemblyDebuggerCtrl(QTextDocument*); + ~AssemblyDebuggerCtrl() {} + void start() const override; + QString title() const override; + QString contentUrl() const override; + +private: + std::unique_ptr m_modelDebugger; + QTextDocument* m_doc; + +public Q_SLOTS: + void keyPressed(int); +}; + +} + +} diff --git a/mix/AssemblyDebuggerModel.cpp b/mix/AssemblyDebuggerModel.cpp new file mode 100644 index 000000000..c65beac7d --- /dev/null +++ b/mix/AssemblyDebuggerModel.cpp @@ -0,0 +1,111 @@ +/* + This file is part of cpp-ethereum. + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file AssemblyDebuggerModel.h + * @author Yann yann@ethdev.com + * @date 2014 + * used as a model to debug contract assembly code. + */ + +#include "libethereum/Executive.h" +#include "libethereum/Transaction.h" +#include "libethereum/ExtVM.h" +#include "libevm/VM.h" +#include "libdevcore/Common.h" +#include "ApplicationCtx.h" +#include "TransactionBuilder.h" +#include "AssemblyDebuggerModel.h" +#include "ConstantCompilationModel.h" +#include "DebuggingStateWrapper.h" +using namespace dev; +using namespace dev::eth; +using namespace dev::mix; + +AssemblyDebuggerModel::AssemblyDebuggerModel() +{ + m_currentExecution = std::unique_ptr(new Executive(m_executiveState)); +} + +DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::bytesConstRef _rawTransaction) +{ + QList states; + Transaction tr(_rawTransaction); + m_currentExecution.get()->create(tr.sender(), tr.value(), tr.gasPrice(), tr.gas(), &tr.data(), tr.sender()); + std::vector levels; + bytes code; + bytesConstRef data; + bool firstIteration = true; + auto onOp = [&](uint64_t steps, Instruction inst, dev::bigint newMemSize, dev::bigint gasCost, void* voidVM, void const* voidExt) + { + VM& vm = *(VM*)voidVM; + ExtVM const& ext = *(ExtVM const*)voidExt; + + if (firstIteration) + { + code = ext.code; + data = ext.data; + firstIteration = false; + } + + if (levels.size() < ext.depth) + levels.push_back(&states.back()); + else + levels.resize(ext.depth); + + states.append(DebuggingState({steps, ext.myAddress, vm.curPC(), inst, newMemSize, vm.gas(), + vm.stack(), vm.memory(), gasCost, ext.state().storage(ext.myAddress), levels})); + }; + + m_currentExecution.get()->go(onOp); + m_currentExecution.get()->finalize(onOp); + + DebuggingContent d; + d.states = states; + d.executionCode = code; + d.executionData = data; + d.contentAvailable = true; + d.message = "ok"; + return d; +} + + +DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::u256 _value, + dev::u256 _gasPrice, + dev::u256 _gas, + QString code, + KeyPair _key) +{ + ConstantCompilationModel compiler; + CompilerResult res = compiler.compile(code); + if (!res.success) + { + DebuggingContent r; + r.contentAvailable = false; + r.message = "compile failed"; + return r; + } + + TransactionBuilder trBuild; + Transaction tr = trBuild.getCreationTransaction(_value, _gasPrice, _gas, res.bytes, + m_executiveState.transactionsFrom(dev::toAddress(_key.secret())), _key.secret()); + bytes b = tr.rlp(); + dev::bytesConstRef bytesRef = &b; + return getContractInitiationDebugStates(bytesRef); +} + +bool AssemblyDebuggerModel::compile(QString code) +{ + ConstantCompilationModel compiler; + CompilerResult res = compiler.compile(code); + return res.success; +} diff --git a/mix/AssemblyDebuggerModel.h b/mix/AssemblyDebuggerModel.h new file mode 100644 index 000000000..3cac98db0 --- /dev/null +++ b/mix/AssemblyDebuggerModel.h @@ -0,0 +1,49 @@ +/* + This file is part of cpp-ethereum. + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file AssemblyDebuggerModel.h + * @author Yann yann@ethdev.com + * @date 2014 + * serves as a model to debug contract assembly code. + */ + +#pragma once + +#include +#include +#include "libethereum/State.h" +#include "libethereum/Executive.h" +#include "libdevcore/Common.h" +#include "DebuggingStateWrapper.h" +namespace dev +{ + +namespace mix +{ + +class AssemblyDebuggerModel +{ +public: + AssemblyDebuggerModel(); + DebuggingContent getContractInitiationDebugStates(dev::u256, dev::u256, dev::u256, QString, KeyPair); + DebuggingContent getContractInitiationDebugStates(dev::bytesConstRef); + bool compile(QString code); + +private: + std::unique_ptr m_currentExecution; + dev::eth::State m_executiveState; +}; + +} + +} diff --git a/mix/CodeEditorExtensionManager.cpp b/mix/CodeEditorExtensionManager.cpp index 596aea165..c85292f2b 100644 --- a/mix/CodeEditorExtensionManager.cpp +++ b/mix/CodeEditorExtensionManager.cpp @@ -27,6 +27,7 @@ #include #include #include "ConstantCompilationCtrl.h" +#include "AssemblyDebuggerCtrl.h" #include "features.h" #include "ApplicationCtx.h" #include "CodeEditorExtensionManager.h" @@ -59,22 +60,29 @@ void CodeEditorExtensionManager::loadEditor(QQuickItem* _editor) void CodeEditorExtensionManager::initExtensions() { - //only one for now - std::shared_ptr constantCompilation = std::make_shared(m_doc); - if (constantCompilation.get()->contentUrl() != "") + initExtension(std::make_shared(m_doc)); + initExtension(std::make_shared(m_doc)); +} + +void CodeEditorExtensionManager::initExtension(std::shared_ptr ext) +{ + if (!ext.get()->contentUrl().isEmpty()) { try { - constantCompilation.get()->addContentOn(m_tabView); + if (ext.get()->getDisplayBehavior() == ExtensionDisplayBehavior::Tab) + { + ext.get()->addTabOn(m_tabView); + } } catch (...) { - qDebug() << "Exception when adding content into view."; + qDebug() << "Exception when adding tab into view."; return; } } - constantCompilation.get()->start(); - m_features.append(constantCompilation); + ext.get()->start(); + m_features.append(ext); } void CodeEditorExtensionManager::setEditor(QQuickItem* _editor) diff --git a/mix/CodeEditorExtensionManager.h b/mix/CodeEditorExtensionManager.h index 2b8402bf2..8e8501bc9 100644 --- a/mix/CodeEditorExtensionManager.h +++ b/mix/CodeEditorExtensionManager.h @@ -45,12 +45,13 @@ public: CodeEditorExtensionManager() {} ~CodeEditorExtensionManager(); void initExtensions(); + void initExtension(std::shared_ptr); void setEditor(QQuickItem*); void setTabView(QQuickItem*); private: QQuickItem* m_editor; - QVector> m_features; + QVector> m_features; QQuickItem* m_tabView; QTextDocument* m_doc; void loadEditor(QQuickItem*); diff --git a/mix/ConstantCompilationCtrl.cpp b/mix/ConstantCompilationCtrl.cpp index 06b9c0284..a703e6686 100644 --- a/mix/ConstantCompilationCtrl.cpp +++ b/mix/ConstantCompilationCtrl.cpp @@ -30,7 +30,7 @@ #include "ConstantCompilationModel.h" using namespace dev::mix; -ConstantCompilationCtrl::ConstantCompilationCtrl(QTextDocument* _doc) +ConstantCompilationCtrl::ConstantCompilationCtrl(QTextDocument* _doc): Extension(ExtensionDisplayBehavior::Tab) { m_editor = _doc; m_compilationModel = new ConstantCompilationModel(); @@ -64,7 +64,7 @@ void ConstantCompilationCtrl::compile() resetOutPut(); return; } - CompilerResult res = m_compilationModel->compile(m_editor->toPlainText()); + CompilerResult res = m_compilationModel->compile(m_editor->toPlainText().replace("\t", " ")); writeOutPut(res); } diff --git a/mix/ConstantCompilationModel.cpp b/mix/ConstantCompilationModel.cpp index e06734f59..a6b2f2741 100644 --- a/mix/ConstantCompilationModel.cpp +++ b/mix/ConstantCompilationModel.cpp @@ -42,6 +42,7 @@ CompilerResult ConstantCompilationModel::compile(QString _code) res.success = true; res.comment = "ok"; res.hexCode = QString::fromStdString(dev::eth::disassemble(m_data)); + res.bytes = m_data; } catch (dev::Exception const& _exception) { diff --git a/mix/ConstantCompilationModel.h b/mix/ConstantCompilationModel.h index 4a17853f6..01ad32224 100644 --- a/mix/ConstantCompilationModel.h +++ b/mix/ConstantCompilationModel.h @@ -22,6 +22,7 @@ #pragma once +#include #include namespace dev @@ -34,6 +35,7 @@ struct CompilerResult { QString hexCode; QString comment; + dev::bytes bytes; bool success; }; diff --git a/mix/DebuggingStateWrapper.cpp b/mix/DebuggingStateWrapper.cpp new file mode 100644 index 000000000..877598ca5 --- /dev/null +++ b/mix/DebuggingStateWrapper.cpp @@ -0,0 +1,189 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file DebuggingState.h + * @author Yann yann@ethdev.com + * @date 2014 + * Used to translate c++ type (u256, bytes, ...) into friendly value (to be used by QML). + */ + +#include +#include +#include +#include "libdevcrypto/Common.h" +#include "libevmcore/Instruction.h" +#include "libdevcore/Common.h" +#include "DebuggingStateWrapper.h" +using namespace dev; +using namespace dev::eth; +using namespace dev::mix; + +std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCode(const bytes& code) +{ + QList codeStr; + QMap codeMapping; + for (unsigned i = 0; i <= code.size(); ++i) + { + byte b = i < code.size() ? code[i] : 0; + try + { + QString s = QString::fromStdString(instructionInfo((Instruction)b).name); + std::ostringstream out; + out << hex << std::setw(4) << std::setfill('0') << i; + codeMapping[i] = codeStr.size(); + int line = i; + if (b >= (byte)Instruction::PUSH1 && b <= (byte)Instruction::PUSH32) + { + unsigned bc = b - (byte)Instruction::PUSH1 + 1; + s = "PUSH 0x" + QString::fromStdString(toHex(bytesConstRef(&code[i + 1], bc))); + i += bc; + } + HumanReadableCode* humanCode = new HumanReadableCode(QString::fromStdString(out.str()) + " " + s, line); + codeStr.append(humanCode); + } + catch (...) + { + qDebug() << QString("Unhandled exception!") << endl << + QString::fromStdString(boost::current_exception_diagnostic_information()); + break; // probably hit data segment + } + } + return std::make_tuple(codeStr, new QQMLMap(codeMapping)); +} + +QString DebuggingStateWrapper::debugStack() +{ + QString stack; + for (auto i: m_state.stack) + stack.prepend(prettyU256(i) + "\n"); + + return stack; +} + +QString DebuggingStateWrapper::debugStorage() +{ + std::stringstream s; + for (auto const& i: m_state.storage) + s << "@" << prettyU256(i.first).toStdString() << "    " << prettyU256(i.second).toStdString(); + + return QString::fromStdString(s.str()); +} + +QString DebuggingStateWrapper::debugMemory() +{ + return QString::fromStdString(memDump(m_state.memory, 16, false)); +} + +QString DebuggingStateWrapper::debugCallData() +{ + + return QString::fromStdString(memDump(m_data, 16, false)); +} + +QStringList DebuggingStateWrapper::levels() +{ + QStringList levelsStr; + for (unsigned i = 0; i <= m_state.levels.size(); ++i) + { + DebuggingState const& s = i ? *m_state.levels[m_state.levels.size() - i] : m_state; + std::ostringstream out; + out << m_state.cur.abridged(); + if (i) + out << " " << instructionInfo(m_state.inst).name << " @0x" << hex << m_state.curPC; + levelsStr.append(QString::fromStdString(out.str())); + } + return levelsStr; +} + +QString DebuggingStateWrapper::headerInfo() +{ + std::ostringstream ss; + ss << dec << " STEP: " << m_state.steps << " | PC: 0x" << hex << m_state.curPC << " : " << dev::eth::instructionInfo(m_state.inst).name << " | ADDMEM: " << dec << m_state.newMemSize << " words | COST: " << dec << m_state.gasCost << " | GAS: " << dec << m_state.gas; + return QString::fromStdString(ss.str()); +} + +QString DebuggingStateWrapper::endOfDebug() +{ + if (m_state.gasCost > m_state.gas) + return "OUT-OF-GAS"; + else if (m_state.inst == Instruction::RETURN && m_state.stack.size() >= 2) + { + unsigned from = (unsigned)m_state.stack.back(); + unsigned size = (unsigned)m_state.stack[m_state.stack.size() - 2]; + unsigned o = 0; + bytes out(size, 0); + for (; o < size && from + o < m_state.memory.size(); ++o) + out[o] = m_state.memory[from + o]; + return "RETURN " + QString::fromStdString(dev::memDump(out, 16, false)); + } + else if (m_state.inst == Instruction::STOP) + return "STOP"; + else if (m_state.inst == Instruction::SUICIDE && m_state.stack.size() >= 1) + return "SUICIDE 0x" + QString::fromStdString(toString(right160(m_state.stack.back()))); + else + return "EXCEPTION"; +} + +QString DebuggingStateWrapper::prettyU256(u256 _n) +{ + unsigned inc = 0; + QString raw; + std::ostringstream s; + if (!(_n >> 64)) + s << " " << (uint64_t)_n << " (0x" << hex << (uint64_t)_n << ")"; + else if (!~(_n >> 64)) + s << " " << (int64_t)_n << " (0x" << hex << (int64_t)_n << ")"; + else if ((_n >> 160) == 0) + { + Address a = right160(_n); + + QString n = QString::fromStdString(a.abridged());//pretty(a); + if (n.isNull()) + s << "0x" << a; + else + s << n.toHtmlEscaped().toStdString() << "(0x" << a.abridged() << ")"; + } + else if ((raw = fromRaw((h256)_n, &inc)).size()) + return "\"" + raw.toHtmlEscaped() + "\"" + (inc ? " + " + QString::number(inc) : ""); + else + s << "" << (h256)_n; + return QString::fromStdString(s.str()); +} + +QString DebuggingStateWrapper::fromRaw(h256 _n, unsigned* _inc) +{ + if (_n) + { + std::string s((char const*)_n.data(), 32); + auto l = s.find_first_of('\0'); + if (!l) + return QString(); + if (l != std::string::npos) + { + auto p = s.find_first_not_of('\0', l); + if (!(p == std::string::npos || (_inc && p == 31))) + return QString(); + if (_inc) + *_inc = (byte)s[31]; + s.resize(l); + } + for (auto i: s) + if (i < 32) + return QString(); + return QString::fromStdString(s); + } + return QString(); +} diff --git a/mix/DebuggingStateWrapper.h b/mix/DebuggingStateWrapper.h new file mode 100644 index 000000000..07716e9ad --- /dev/null +++ b/mix/DebuggingStateWrapper.h @@ -0,0 +1,133 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file DebuggingState.h + * @author Yann yann@ethdev.com + * @date 2014 + * Ethereum IDE client. + */ + +#pragma once + +#include +#include "libethereum/State.h" +#include "libethereum/Executive.h" +#include "libdevcore/Common.h" + +namespace dev +{ + +namespace mix +{ + +struct DebuggingState +{ + uint64_t steps; + dev::Address cur; + dev::u256 curPC; + dev::eth::Instruction inst; + dev::bigint newMemSize; + dev::u256 gas; + dev::u256s stack; + dev::bytes memory; + dev::bigint gasCost; + std::map storage; + std::vector levels; +}; + +struct DebuggingContent +{ + QList states; + bytes executionCode; + bytesConstRef executionData; + bool contentAvailable; + QString message; +}; + +/* contains the line nb of the assembly code and the corresponding index in the code bytes array */ +class HumanReadableCode: public QObject +{ + Q_OBJECT + Q_PROPERTY(QString line READ line) + Q_PROPERTY(int processIndex READ processIndex) + +public: + HumanReadableCode(QString _line, int _processIndex) : m_line(_line), m_processIndex(_processIndex) {} + QString line() { return m_line; } + int processIndex() { return m_processIndex; } + +private: + QString m_line; + int m_processIndex; +}; + +/* used to publish QMap type to QML */ +class QQMLMap : public QObject +{ + Q_OBJECT + +public: + QQMLMap(QMap _map) : m_map(_map) { } + Q_INVOKABLE int getValue(int _key) { return m_map.value(_key); } + +private: + QMap m_map; +}; + +/* used to publish DebuggingState struct to QML */ +class DebuggingStateWrapper : public QObject +{ + Q_OBJECT + Q_PROPERTY(int step READ step) + Q_PROPERTY(int curPC READ curPC) + Q_PROPERTY(int gasCost READ gasCost) + Q_PROPERTY(int gas READ gas) + Q_PROPERTY(QString debugStack READ debugStack) + Q_PROPERTY(QString debugStorage READ debugStorage) + Q_PROPERTY(QString debugMemory READ debugMemory) + Q_PROPERTY(QString debugCallData READ debugCallData) + Q_PROPERTY(QString headerInfo READ headerInfo) + Q_PROPERTY(QString endOfDebug READ endOfDebug) + Q_PROPERTY(QStringList levels READ levels) + +public: + DebuggingStateWrapper(bytes _code, bytes _data) : m_code(_code), m_data(_data) {} + int step() { return (int)m_state.steps; } + int curPC() { return (int)m_state.curPC; } + int gasCost() { return (int)m_state.gasCost; } + int gas() { return (int)m_state.gas; } + QString debugStack(); + QString debugStorage(); + QString debugMemory(); + QString debugCallData(); + QString headerInfo(); + QString endOfDebug(); + QStringList levels(); + DebuggingState state() { return m_state; } + void setState(DebuggingState _state) { m_state = _state; } + static std::tuple, QQMLMap*> getHumanReadableCode(bytes const& code); + +private: + DebuggingState m_state; + bytes m_code; + bytes m_data; + QString prettyU256(u256 _n); + QString fromRaw(h256 _n, unsigned* _inc = nullptr); +}; + +} + +} diff --git a/mix/Extension.cpp b/mix/Extension.cpp index 5aeb0cc17..24cc19aba 100644 --- a/mix/Extension.cpp +++ b/mix/Extension.cpp @@ -25,7 +25,7 @@ using namespace dev; using namespace dev::mix; -void Extension::addContentOn(QObject* _tabView) +void Extension::addTabOn(QObject* _view) { if (contentUrl() == "") return; @@ -33,12 +33,29 @@ void Extension::addContentOn(QObject* _tabView) QVariant returnValue; QQmlComponent* component = new QQmlComponent( ApplicationCtx::getInstance()->appEngine(), - QUrl(this->contentUrl()), _tabView); + QUrl(contentUrl()), _view); - QMetaObject::invokeMethod(_tabView, "addTab", - Q_RETURN_ARG(QVariant, returnValue), - Q_ARG(QVariant, this->title()), - Q_ARG(QVariant, QVariant::fromValue(component))); + QMetaObject::invokeMethod(_view, "addTab", + Q_RETURN_ARG(QVariant, returnValue), + Q_ARG(QVariant, this->title()), + Q_ARG(QVariant, QVariant::fromValue(component))); m_view = qvariant_cast(returnValue); } + +void Extension::addContentOn(QObject* _view) +{ + Q_UNUSED(_view); + if (m_displayBehavior == ExtensionDisplayBehavior::ModalDialog) + { + QQmlComponent component(ApplicationCtx::getInstance()->appEngine(), QUrl(contentUrl())); + QObject* dialog = component.create(); + QObject* dialogWin = ApplicationCtx::getInstance()->appEngine()->rootObjects().at(0)->findChild("dialog", Qt::FindChildrenRecursively); + QMetaObject::invokeMethod(dialogWin, "close"); + dialogWin->setProperty("contentItem", QVariant::fromValue(dialog)); + dialogWin->setProperty("title", title()); + QMetaObject::invokeMethod(dialogWin, "open"); + } + //TODO add more view type. +} + diff --git a/mix/Extension.h b/mix/Extension.h index f8fef0aa6..b697af58b 100644 --- a/mix/Extension.h +++ b/mix/Extension.h @@ -28,19 +28,31 @@ namespace dev namespace mix { +enum ExtensionDisplayBehavior +{ + Tab, + ModalDialog +}; + + class Extension: public QObject { Q_OBJECT public: Extension() {} + Extension(ExtensionDisplayBehavior _displayBehavior) { m_displayBehavior = _displayBehavior; } virtual QString contentUrl() const { return ""; } virtual QString title() const { return ""; } virtual void start() const {} - void addContentOn(QObject* tabView); + void addContentOn(QObject* _tabView); + void addTabOn(QObject* _view); + void setDisplayBehavior(ExtensionDisplayBehavior _displayBehavior) { m_displayBehavior = _displayBehavior; } + ExtensionDisplayBehavior getDisplayBehavior() { return m_displayBehavior; } protected: QObject* m_view; + ExtensionDisplayBehavior m_displayBehavior; }; } diff --git a/mix/KeyEventManager.cpp b/mix/KeyEventManager.cpp new file mode 100644 index 000000000..f5d638869 --- /dev/null +++ b/mix/KeyEventManager.cpp @@ -0,0 +1,43 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file KeyEventManager.cpp + * @author Yann yann@ethdev.com + * @date 2014 + * Used as an event handler for all classes which need keyboard interactions. + * Can be improve by adding the possibility to register to a specific key. + */ + +#include +#include +#include "KeyEventManager.h" + +void KeyEventManager::registerEvent(const QObject* _receiver, const char* _slot) +{ + QObject::connect(this, SIGNAL(onKeyPressed(int)), _receiver, _slot); +} + +void KeyEventManager::unRegisterEvent(QObject* _receiver) +{ + QObject::disconnect(_receiver); +} + +void KeyEventManager::keyPressed(QVariant _event) +{ + emit onKeyPressed(_event.toInt()); +} + + diff --git a/mix/KeyEventManager.h b/mix/KeyEventManager.h new file mode 100644 index 000000000..ecd768c4c --- /dev/null +++ b/mix/KeyEventManager.h @@ -0,0 +1,42 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file KeyEventManager.h + * @author Yann yann@ethdev.com + * @date 2014 + * use as an event handler for all classes which need keyboard interactions + */ + +#pragma once + +#include + +class KeyEventManager: public QObject +{ + Q_OBJECT + +public: + KeyEventManager() {} + void registerEvent(const QObject* receiver, const char* slot); + void unRegisterEvent(QObject* receiver); + +signals: + void onKeyPressed(int); + +public Q_SLOTS: + void keyPressed(QVariant event); +}; + diff --git a/mix/TransactionBuilder.cpp b/mix/TransactionBuilder.cpp new file mode 100644 index 000000000..ce274fa00 --- /dev/null +++ b/mix/TransactionBuilder.cpp @@ -0,0 +1,92 @@ +/* + This file is part of cpp-ethereum. + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file TransactionBuilder.cpp + * @author Yann yann@ethdev.com + * @date 2014 + * Ethereum IDE client. + */ + +#include "libethereum/Executive.h" +#include "libdevcore/Common.h" +#include "ApplicationCtx.h" +#include "TransactionBuilder.h" +using namespace dev::mix; +using namespace dev::eth; +using namespace dev; + +Transaction TransactionBuilder::getCreationTransaction(u256 _value, u256 _gasPrice, u256 _gas, + bytes _data, u256 _nonce, Secret _secret) const +{ + return Transaction(_value, _gasPrice, _gas, _data, _nonce, _secret); +} + +Transaction TransactionBuilder::getBasicTransaction(u256 _value, u256 _gasPrice, u256 _gas, + QString address, bytes _data, u256 _nonce, Secret _secret) const +{ + return Transaction(_value, _gasPrice, _gas, fromString(address), _data, _nonce, _secret); +} + +int TransactionBuilder::fromHex(char _i) const +{ + if (_i >= '0' && _i <= '9') + return _i - '0'; + if (_i >= 'a' && _i <= 'f') + return _i - 'a' + 10; + if (_i >= 'A' && _i <= 'F') + return _i - 'A' + 10; + BOOST_THROW_EXCEPTION(BadHexCharacter() << errinfo_invalidSymbol(_i)); +} + +bytes TransactionBuilder::fromHex(std::string const& _s) const +{ + unsigned s = (_s[0] == '0' && _s[1] == 'x') ? 2 : 0; + std::vector ret; + ret.reserve((_s.size() - s + 1) / 2); + + if (_s.size() % 2) + try + { + ret.push_back(fromHex(_s[s++])); + } + catch (...){ ret.push_back(0); cwarn << boost::current_exception_diagnostic_information(); } + for (unsigned i = s; i < _s.size(); i += 2) + try + { + ret.push_back((byte)(fromHex(_s[i]) * 16 + fromHex(_s[i + 1]))); + } + catch (...){ ret.push_back(0); cwarn << boost::current_exception_diagnostic_information(); } + return ret; +} + +Address TransactionBuilder::fromString(QString const& _a) const +{ + Client* ethClient = ApplicationCtx::getInstance()->getEthereumClient(); + std::string sn = _a.toStdString(); + if (sn.size() > 32) + sn.resize(32); + h256 n; + memcpy(n.data(), sn.data(), sn.size()); + memset(n.data() + sn.size(), 0, 32 - sn.size()); + if (_a.size() == 40) + return Address(fromHex(_a.toStdString())); + else + { + //we try to resolve the recipient adress using nameReg contract state + const Address c_config = Address("661005d2720d855f1d9976f88bb10c1a3398c77f"); //NameReg contract + if (h160 nameReg = (u160)ethClient->stateAt(c_config, 0)) + if (h256 a = ethClient->stateAt(nameReg, n)) + return right160(a); + } + return Address(); // should maybe throws exception instead of returning blank address. +} diff --git a/mix/TransactionBuilder.h b/mix/TransactionBuilder.h new file mode 100644 index 000000000..261d3060f --- /dev/null +++ b/mix/TransactionBuilder.h @@ -0,0 +1,48 @@ +/* + This file is part of cpp-ethereum. + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file TransactionBuilder.h + * @author Yann yann@ethdev.com + * @date 2014 + * Ethereum IDE client. + */ + +#pragma once + +#include +#include "libdevcore/Common.h" +#include "libethereum/Transaction.h" + +namespace dev +{ + +namespace mix +{ + +class TransactionBuilder +{ +public: + TransactionBuilder() {} + dev::eth::Transaction getBasicTransaction(dev::u256 _value, dev::u256 _gasPrice, dev::u256 _gas, + QString address, bytes _data, dev::u256 _nonce, Secret _secret) const; + dev::eth::Transaction getCreationTransaction(dev::u256 _value, dev::u256 _gasPrice, dev::u256 _gas, + dev::bytes _data, dev::u256 _nonce, Secret _secret) const; +private: + bytes fromHex(std::string const& _s) const; + int fromHex(char _i) const; + Address fromString(QString const& _a) const; +}; + +} + +} diff --git a/mix/main.cpp b/mix/main.cpp index 537941290..4f707f47a 100644 --- a/mix/main.cpp +++ b/mix/main.cpp @@ -35,6 +35,9 @@ int main(int _argc, char *_argv[]) QQmlApplicationEngine* engine = new QQmlApplicationEngine(); ApplicationCtx::setApplicationContext(engine); QObject::connect(&app, SIGNAL(lastWindowClosed()), ApplicationCtx::getInstance(), SLOT(quitApplication())); //use to kill ApplicationContext and other stuff + engine->load(QUrl(QStringLiteral("qrc:/qml/main.qml"))); + + ApplicationCtx::getInstance()->initKeyEventManager(); //has to be called after the loading of the main view. return app.exec(); } diff --git a/mix/qml.qrc b/mix/qml.qrc index 267427ce5..2fa92d661 100644 --- a/mix/qml.qrc +++ b/mix/qml.qrc @@ -4,5 +4,8 @@ qml/main.qml qml/MainContent.qml qml/TabStyle.qml + qml/Debugger.qml + qml/js/Debugger.js + qml/BasicMessage.qml diff --git a/mix/qml/BasicMessage.qml b/mix/qml/BasicMessage.qml new file mode 100644 index 000000000..14ddbcf0d --- /dev/null +++ b/mix/qml/BasicMessage.qml @@ -0,0 +1,20 @@ +import QtQuick 2.3 +import QtQuick.Controls.Styles 1.2 +import QtQuick.Controls 1.2 +import QtQuick.Dialogs 1.2 +import QtQuick.Layouts 1.1 + +Rectangle { + anchors.fill: parent + color: "lightgrey" + Label + { + width: parent.width + height: parent.height + horizontalAlignment: "AlignHCenter" + verticalAlignment: "AlignVCenter" + objectName: "messageContent" + id: messageTxt + text: "" + } +} diff --git a/mix/qml/Debugger.qml b/mix/qml/Debugger.qml new file mode 100644 index 000000000..1c79e43ce --- /dev/null +++ b/mix/qml/Debugger.qml @@ -0,0 +1,231 @@ +import QtQuick 2.3 +import QtQuick.Controls.Styles 1.2 +import QtQuick.Controls 1.2 +import QtQuick.Dialogs 1.2 +import QtQuick.Layouts 1.1 +import "js/Debugger.js" as Debugger + +Rectangle { + anchors.fill: parent; + Rectangle { + id: headerInfo + width: parent.width + height: 30 + anchors.top: parent.top + Label { + anchors.centerIn: parent + font.family: "Verdana" + font.pointSize: 9 + font.italic: true + id: headerInfoLabel + } + + } + + Keys.onPressed: { + if (event.key === Qt.Key_F10) + Debugger.moveSelection(1); + else if (event.key === Qt.Key_F9) + Debugger.moveSelection(-1); + } + + Rectangle { + id: stateListContainer + focus: true + anchors.top: headerInfo.bottom + anchors.left: parent.left + height: parent.height - 30 + width: parent.width * 0.5 + + ListView { + anchors.top: parent.top + height: parent.height * 0.55 + width: 200 + anchors.horizontalCenter: parent.horizontalCenter + id: statesList + Component.onCompleted: Debugger.init(); + model: humanReadableExecutionCode + delegate: renderDelegate + highlight: highlightBar + highlightFollowsCurrentItem: true + } + + Component { + id: highlightBar + Rectangle { + height: statesList.currentItem.height + width: statesList.currentItem.width + border.color: "orange" + border.width: 1 + Behavior on y { SpringAnimation { spring: 2; damping: 0.1 } } + } + } + + Component { + id: renderDelegate + Item { + id: wrapperItem + height:20 + width: parent.width + Text { + anchors.centerIn: parent + text: line + font.pointSize: 9 + } + } + } + + Rectangle { + anchors.top: statesList.bottom + height: parent.height * 0.30 + width: parent.width + + Label { + id: callStackLabel + anchors.top: statesList.bottom + anchors.bottomMargin: 10 + horizontalAlignment: "AlignHCenter" + font.family: "Verdana" + font.pointSize: 8 + font.letterSpacing: 2 + width: parent.width + height: 15 + text: "callstack" + } + + ListView { + height: parent.height - 15 + width: 200 + anchors.top: callStackLabel.bottom + anchors.horizontalCenter: parent.horizontalCenter + id: levelList + delegate: Component { + Item { + Text { + font.family: "Verdana" + font.pointSize: 8 + text: modelData + } + } + } + } + } + } + + Rectangle { + anchors.topMargin: 5 + anchors.bottomMargin: 10 + anchors.rightMargin: 10 + height: parent.height - 30 + width: parent.width * 0.5 + anchors.right: parent.right + anchors.top: headerInfo.bottom + anchors.bottom: parent.bottom + + Rectangle { + id: debugStack + anchors.top: parent.top + width: parent.width + height: parent.height * 0.25 + + Label { + horizontalAlignment: "AlignHCenter" + font.family: "Verdana" + font.pointSize: 8 + font.letterSpacing: 2 + width: parent.width + height: 15 + anchors.top : parent.top + text: "debug stack" + } + TextArea { + anchors.bottom: parent.bottom + width: parent.width + font.family: "Verdana" + font.pointSize: 8 + font.letterSpacing: 2 + height: parent.height - 15 + id:debugStackTxt + readOnly: true; + } + } + + Rectangle { + id: debugMemory + anchors.top: debugStack.bottom + width: parent.width + height: parent.height * 0.25 + Label { + horizontalAlignment: "AlignHCenter" + font.family: "Verdana" + font.pointSize: 8 + font.letterSpacing: 2 + width: parent.width + height: 15 + anchors.top : parent.top + text: "debug memory" + } + TextArea { + anchors.bottom: parent.bottom + width: parent.width + font.family: "Verdana" + font.pointSize: 8 + font.letterSpacing: 2 + height: parent.height - 15 + id: debugMemoryTxt + readOnly: true; + } + } + + Rectangle { + id: debugStorage + anchors.top: debugMemory.bottom + width: parent.width + height: parent.height * 0.25 + Label { + horizontalAlignment: "AlignHCenter" + font.family: "Verdana" + font.pointSize: 8 + font.letterSpacing: 2 + width: parent.width + height: 15 + anchors.top : parent.top + text: "debug storage" + } + TextArea { + anchors.bottom: parent.bottom + width: parent.width + font.family: "Verdana" + font.pointSize: 8 + font.letterSpacing: 2 + height: parent.height - 15 + id:debugStorageTxt + readOnly: true; + } + } + + Rectangle { + id: debugCallData + anchors.top: debugStorage.bottom + width: parent.width + height: parent.height * 0.25 + Label { + horizontalAlignment: "AlignHCenter" + font.family: "Verdana" + font.pointSize: 8 + font.letterSpacing: 2 + width: parent.width + height: 15 + anchors.top : parent.top + text: "debug calldata" + } + TextArea { + anchors.bottom: parent.bottom + width: parent.width + height: parent.height - 15 + id: debugCallDataTxt + readOnly: true; + } + } + } +} diff --git a/mix/qml/MainContent.qml b/mix/qml/MainContent.qml index bd4737c3b..821b48913 100644 --- a/mix/qml/MainContent.qml +++ b/mix/qml/MainContent.qml @@ -1,10 +1,18 @@ -import QtQuick 2.2 -import QtQuick.Controls 1.1 +import QtQuick 2.3 +import QtQuick.Controls 1.2 import QtQuick.Layouts 1.0 -import QtQuick.Controls.Styles 1.1 +import QtQuick.Controls.Styles 1.2 import CodeEditorExtensionManager 1.0 Rectangle { + objectName: "mainContent" + signal keyPressed(variant event) + focus: true + Keys.enabled: true + Keys.onPressed: + { + root.keyPressed(event.key); + } anchors.fill: parent height: parent.height width: parent.width; @@ -26,11 +34,11 @@ Rectangle { anchors.centerIn: parent tabChangesFocus: false Keys.onPressed: { - if (event.key === Qt.Key_Tab) { - codeEditor.insert(codeEditor.cursorPosition, "\t"); - event.accepted = true; + if (event.key === Qt.Key_Tab) { + codeEditor.insert(codeEditor.cursorPosition, "\t"); + event.accepted = true; + } } - } } } Rectangle { @@ -46,7 +54,7 @@ Rectangle { style: TabStyle {} } } - CodeEditorExtensionManager{ + CodeEditorExtensionManager { tabView: contextualTabs editor: codeEditor } diff --git a/mix/qml/js/Debugger.js b/mix/qml/js/Debugger.js new file mode 100644 index 000000000..ddaa362a6 --- /dev/null +++ b/mix/qml/js/Debugger.js @@ -0,0 +1,63 @@ +//humanReadableExecutionCode => contain human readable code. +//debugStates => contain all debug states. +//bytesCodeMapping => mapping between humanReadableExecutionCode and bytesCode. +//statesList => ListView + +var currentSelectedState = null; +function init() +{ + currentSelectedState = 0; + select(currentSelectedState); +} + +function moveSelection(incr) +{ + if (currentSelectedState + incr >= 0) + { + if (currentSelectedState + incr < debugStates.length) + { + select(currentSelectedState + incr); + } + else + { + endOfDebug(); + } + } +} + +function select(stateIndex) +{ + var state = debugStates[stateIndex]; + var codeStr = bytesCodeMapping.getValue(state.curPC); + highlightSelection(codeStr); + currentSelectedState = codeStr; + completeCtxInformation(state); + levelList.model = state.levels; + levelList.update(); +} + +function highlightSelection(index) +{ + console.log(index); + statesList.currentIndex = index; +} + +function completeCtxInformation(state) +{ + debugStackTxt.text = state.debugStack; + debugStorageTxt.text = state.debugStorage; + debugMemoryTxt.text = state.debugMemory; + debugCallDataTxt.text = state.debugCallData; + headerInfoLabel.text = state.headerInfo +} + +function endOfDebug() +{ + var state = debugStates[debugStates.length - 1]; + debugStorageTxt.text = ""; + debugCallDataTxt.text = ""; + debugStackTxt.text = ""; + debugMemoryTxt.text = state.endOfDebug + var gascost = state.gas - state.gasCost; + headerInfoLabel.text = "EXIT | GAS: " + gascost; +} diff --git a/mix/qml/main.qml b/mix/qml/main.qml index 3553f7710..05b29eb62 100644 --- a/mix/qml/main.qml +++ b/mix/qml/main.qml @@ -1,15 +1,22 @@ import QtQuick 2.2 import QtQuick.Controls 1.1 import QtQuick.Controls.Styles 1.1 +import QtQuick.Dialogs 1.2 +import QtQuick.Layouts 1.1 +import QtQuick.Window 2.0 import CodeEditorExtensionManager 1.0 ApplicationWindow { + id: mainApplication visible: true - width: 1000 - height: 480 + x: Screen.width / 2 - width / 2 + y: Screen.height / 2 - height / 2 + width: 1200 + height: 600 minimumWidth: 400 minimumHeight: 300 title: qsTr("mix") + menuBar: MenuBar { Menu { title: qsTr("File") @@ -19,6 +26,33 @@ ApplicationWindow { } } } - MainContent{ + + MainContent { + } + + Dialog { + x: mainApplication.x + (mainApplication.width - width) / 2 + y: mainApplication.y + (mainApplication.height - height) / 2 + objectName: "dialog" + id: dialog + height: 400 + width: 700 + modality: Qt.WindowModal + contentItem: Rectangle { + objectName: "dialogContent" + } + } + + Dialog { + x: mainApplication.x + (mainApplication.width - width) / 2 + y: mainApplication.y + (mainApplication.height - height) / 2 + objectName: "messageDialog" + id: messageDialog + height: 150 + width: 200 + modality: Qt.WindowModal + contentItem: Rectangle { + objectName: "messageContent" + } } } From 803b47161ec05acea00129d4afa6dd93c6c943f0 Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 5 Dec 2014 11:27:09 +0100 Subject: [PATCH 414/641] debug modal dialog UI correction --- mix/qml/Debugger.qml | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/mix/qml/Debugger.qml b/mix/qml/Debugger.qml index 1c79e43ce..490f49f61 100644 --- a/mix/qml/Debugger.qml +++ b/mix/qml/Debugger.qml @@ -7,7 +7,9 @@ import "js/Debugger.js" as Debugger Rectangle { anchors.fill: parent; + color: "lightgrey" Rectangle { + color: "transparent" id: headerInfo width: parent.width height: 30 @@ -30,8 +32,10 @@ Rectangle { } Rectangle { + color: "transparent" id: stateListContainer focus: true + anchors.topMargin: 10 anchors.top: headerInfo.bottom anchors.left: parent.left height: parent.height - 30 @@ -39,7 +43,7 @@ Rectangle { ListView { anchors.top: parent.top - height: parent.height * 0.55 + height: parent.height * 0.60 width: 200 anchors.horizontalCenter: parent.horizontalCenter id: statesList @@ -65,7 +69,7 @@ Rectangle { id: renderDelegate Item { id: wrapperItem - height:20 + height: 20 width: parent.width Text { anchors.centerIn: parent @@ -76,13 +80,14 @@ Rectangle { } Rectangle { + id: callStackPanel anchors.top: statesList.bottom - height: parent.height * 0.30 + height: parent.height * 0.35 width: parent.width - + anchors.topMargin: 13 + color: "transparent" Label { id: callStackLabel - anchors.top: statesList.bottom anchors.bottomMargin: 10 horizontalAlignment: "AlignHCenter" font.family: "Verdana" @@ -113,6 +118,7 @@ Rectangle { } Rectangle { + color: "transparent" anchors.topMargin: 5 anchors.bottomMargin: 10 anchors.rightMargin: 10 @@ -127,7 +133,7 @@ Rectangle { anchors.top: parent.top width: parent.width height: parent.height * 0.25 - + color: "transparent" Label { horizontalAlignment: "AlignHCenter" font.family: "Verdana" @@ -155,6 +161,7 @@ Rectangle { anchors.top: debugStack.bottom width: parent.width height: parent.height * 0.25 + color: "transparent" Label { horizontalAlignment: "AlignHCenter" font.family: "Verdana" @@ -182,6 +189,7 @@ Rectangle { anchors.top: debugMemory.bottom width: parent.width height: parent.height * 0.25 + color: "transparent" Label { horizontalAlignment: "AlignHCenter" font.family: "Verdana" @@ -209,6 +217,7 @@ Rectangle { anchors.top: debugStorage.bottom width: parent.width height: parent.height * 0.25 + color: "transparent" Label { horizontalAlignment: "AlignHCenter" font.family: "Verdana" From b5323f75e6b6945e0ac36aae4fb2da84bf1fa64c Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 5 Dec 2014 12:48:34 +0100 Subject: [PATCH 415/641] common changes in windows build --- cmake/EthCompilerSettings.cmake | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index 8530a54b7..2757eb9ad 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -3,15 +3,16 @@ # C++11 check and activation if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") + set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wno-unknown-pragmas -Wextra -DSHAREDLIB") execute_process( COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION) if (NOT (GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7)) message(FATAL_ERROR "${PROJECT_NAME} requires g++ 4.7 or greater.") endif () elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") + set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wno-unknown-pragmas -Wextra -DSHAREDLIB") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") + set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -DSHAREDLIB") else () message(FATAL_ERROR "Your C++ compiler does not support C++11. You have ${CMAKE_CXX_COMPILER_ID}") endif () @@ -19,7 +20,7 @@ endif () # Initialize CXXFLAGS -set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wno-unknown-pragmas -Wextra -DSHAREDLIB") +# CMAKE_CXX_FLAGS was set before set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DETH_DEBUG") set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG -DETH_RELEASE") set(CMAKE_CXX_FLAGS_RELEASE "-O4 -DNDEBUG -DETH_RELEASE") From dbc5201e98c1fdc1e09f1fe3108a6c10f6b20fc1 Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 5 Dec 2014 12:57:09 +0100 Subject: [PATCH 416/641] - coding standards. - set 'parent' on QObject custom class to ensure object deletion. --- mix/ApplicationCtx.cpp | 6 ++---- mix/AssemblyDebuggerCtrl.cpp | 2 +- mix/AssemblyDebuggerModel.cpp | 1 - mix/AssemblyDebuggerModel.h | 1 + mix/CodeEditorExtensionManager.cpp | 12 ++++++------ mix/ConstantCompilationModel.h | 2 +- mix/DebuggingStateWrapper.cpp | 6 +++--- mix/DebuggingStateWrapper.h | 6 +++--- mix/qml/Debugger.qml | 2 +- 9 files changed, 18 insertions(+), 20 deletions(-) diff --git a/mix/ApplicationCtx.cpp b/mix/ApplicationCtx.cpp index 52e66dab7..99d9bee4c 100644 --- a/mix/ApplicationCtx.cpp +++ b/mix/ApplicationCtx.cpp @@ -38,10 +38,8 @@ ApplicationCtx* ApplicationCtx::Instance = nullptr; ApplicationCtx::ApplicationCtx(QQmlApplicationEngine* _engine) { m_applicationEngine = _engine; - m_keyEventManager = std::unique_ptr(); - m_webThree = std::unique_ptr(); - m_webThree.reset(new WebThreeDirect(std::string("Mix/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir() + "/Mix", false, {"eth", "shh"})); - m_keyEventManager.reset(new KeyEventManager()); + m_keyEventManager = std::unique_ptr(new KeyEventManager()); + m_webThree = std::unique_ptr(new WebThreeDirect(std::string("Mix/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir() + "/Mix", false, {"eth", "shh"})); } ApplicationCtx::~ApplicationCtx() diff --git a/mix/AssemblyDebuggerCtrl.cpp b/mix/AssemblyDebuggerCtrl.cpp index e8b0391d8..94d8bf6cb 100644 --- a/mix/AssemblyDebuggerCtrl.cpp +++ b/mix/AssemblyDebuggerCtrl.cpp @@ -75,7 +75,7 @@ void AssemblyDebuggerCtrl::keyPressed(int _key) s->setState(debuggingContent.states.at(i)); wStates.append(s); } - std::tuple, QQMLMap*> code = DebuggingStateWrapper::getHumanReadableCode(debuggingContent.executionCode); + std::tuple, QQMLMap*> code = DebuggingStateWrapper::getHumanReadableCode(debuggingContent.executionCode, this); ApplicationCtx::getInstance()->appEngine()->rootContext()->setContextProperty("debugStates", QVariant::fromValue(wStates)); ApplicationCtx::getInstance()->appEngine()->rootContext()->setContextProperty("humanReadableExecutionCode", QVariant::fromValue(std::get<0>(code))); ApplicationCtx::getInstance()->appEngine()->rootContext()->setContextProperty("bytesCodeMapping", QVariant::fromValue(std::get<1>(code))); diff --git a/mix/AssemblyDebuggerModel.cpp b/mix/AssemblyDebuggerModel.cpp index c65beac7d..df027acf7 100644 --- a/mix/AssemblyDebuggerModel.cpp +++ b/mix/AssemblyDebuggerModel.cpp @@ -78,7 +78,6 @@ DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::by return d; } - DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::u256 _value, dev::u256 _gasPrice, dev::u256 _gas, diff --git a/mix/AssemblyDebuggerModel.h b/mix/AssemblyDebuggerModel.h index 3cac98db0..378f238e6 100644 --- a/mix/AssemblyDebuggerModel.h +++ b/mix/AssemblyDebuggerModel.h @@ -25,6 +25,7 @@ #include "libethereum/Executive.h" #include "libdevcore/Common.h" #include "DebuggingStateWrapper.h" + namespace dev { diff --git a/mix/CodeEditorExtensionManager.cpp b/mix/CodeEditorExtensionManager.cpp index c85292f2b..503e07447 100644 --- a/mix/CodeEditorExtensionManager.cpp +++ b/mix/CodeEditorExtensionManager.cpp @@ -64,15 +64,15 @@ void CodeEditorExtensionManager::initExtensions() initExtension(std::make_shared(m_doc)); } -void CodeEditorExtensionManager::initExtension(std::shared_ptr ext) +void CodeEditorExtensionManager::initExtension(std::shared_ptr _ext) { - if (!ext.get()->contentUrl().isEmpty()) + if (!_ext.get()->contentUrl().isEmpty()) { try { - if (ext.get()->getDisplayBehavior() == ExtensionDisplayBehavior::Tab) + if (_ext.get()->getDisplayBehavior() == ExtensionDisplayBehavior::Tab) { - ext.get()->addTabOn(m_tabView); + _ext.get()->addTabOn(m_tabView); } } catch (...) @@ -81,8 +81,8 @@ void CodeEditorExtensionManager::initExtension(std::shared_ptr ext) return; } } - ext.get()->start(); - m_features.append(ext); + _ext.get()->start(); + m_features.append(_ext); } void CodeEditorExtensionManager::setEditor(QQuickItem* _editor) diff --git a/mix/ConstantCompilationModel.h b/mix/ConstantCompilationModel.h index 01ad32224..713c9e950 100644 --- a/mix/ConstantCompilationModel.h +++ b/mix/ConstantCompilationModel.h @@ -45,7 +45,7 @@ class ConstantCompilationModel public: ConstantCompilationModel() {} ~ConstantCompilationModel() {} - CompilerResult compile(QString code); + CompilerResult compile(QString); }; } diff --git a/mix/DebuggingStateWrapper.cpp b/mix/DebuggingStateWrapper.cpp index 877598ca5..3bce8658b 100644 --- a/mix/DebuggingStateWrapper.cpp +++ b/mix/DebuggingStateWrapper.cpp @@ -31,7 +31,7 @@ using namespace dev; using namespace dev::eth; using namespace dev::mix; -std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCode(const bytes& code) +std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCode(const bytes& code, QObject* _objUsedAsParent) { QList codeStr; QMap codeMapping; @@ -51,7 +51,7 @@ std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCod s = "PUSH 0x" + QString::fromStdString(toHex(bytesConstRef(&code[i + 1], bc))); i += bc; } - HumanReadableCode* humanCode = new HumanReadableCode(QString::fromStdString(out.str()) + " " + s, line); + HumanReadableCode* humanCode = new HumanReadableCode(QString::fromStdString(out.str()) + " " + s, line, _objUsedAsParent); codeStr.append(humanCode); } catch (...) @@ -61,7 +61,7 @@ std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCod break; // probably hit data segment } } - return std::make_tuple(codeStr, new QQMLMap(codeMapping)); + return std::make_tuple(codeStr, new QQMLMap(codeMapping, _objUsedAsParent)); } QString DebuggingStateWrapper::debugStack() diff --git a/mix/DebuggingStateWrapper.h b/mix/DebuggingStateWrapper.h index 07716e9ad..0285a4693 100644 --- a/mix/DebuggingStateWrapper.h +++ b/mix/DebuggingStateWrapper.h @@ -65,7 +65,7 @@ class HumanReadableCode: public QObject Q_PROPERTY(int processIndex READ processIndex) public: - HumanReadableCode(QString _line, int _processIndex) : m_line(_line), m_processIndex(_processIndex) {} + HumanReadableCode(QString _line, int _processIndex, QObject* _parent) : m_line(_line), m_processIndex(_processIndex), QObject(_parent) {} QString line() { return m_line; } int processIndex() { return m_processIndex; } @@ -80,7 +80,7 @@ class QQMLMap : public QObject Q_OBJECT public: - QQMLMap(QMap _map) : m_map(_map) { } + QQMLMap(QMap _map, QObject* _parent) : m_map(_map), QObject(_parent) { } Q_INVOKABLE int getValue(int _key) { return m_map.value(_key); } private: @@ -118,7 +118,7 @@ public: QStringList levels(); DebuggingState state() { return m_state; } void setState(DebuggingState _state) { m_state = _state; } - static std::tuple, QQMLMap*> getHumanReadableCode(bytes const& code); + static std::tuple, QQMLMap*> getHumanReadableCode(bytes const& code, QObject* _objUsedAsParent); private: DebuggingState m_state; diff --git a/mix/qml/Debugger.qml b/mix/qml/Debugger.qml index 490f49f61..6802f57df 100644 --- a/mix/qml/Debugger.qml +++ b/mix/qml/Debugger.qml @@ -84,7 +84,7 @@ Rectangle { anchors.top: statesList.bottom height: parent.height * 0.35 width: parent.width - anchors.topMargin: 13 + anchors.topMargin: 15 color: "transparent" Label { id: callStackLabel From 827de531b9f2f6d68c7ebbb40ed201d1f46a713b Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 5 Dec 2014 13:07:42 +0100 Subject: [PATCH 417/641] - Coding standards --- mix/AssemblyDebuggerModel.cpp | 4 ++-- mix/AssemblyDebuggerModel.h | 2 +- mix/CodeEditorExtensionManager.cpp | 1 - mix/DebuggingStateWrapper.cpp | 8 ++++---- mix/MixApplication.cpp | 2 +- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/mix/AssemblyDebuggerModel.cpp b/mix/AssemblyDebuggerModel.cpp index df027acf7..e4c2396ca 100644 --- a/mix/AssemblyDebuggerModel.cpp +++ b/mix/AssemblyDebuggerModel.cpp @@ -102,9 +102,9 @@ DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::u2 return getContractInitiationDebugStates(bytesRef); } -bool AssemblyDebuggerModel::compile(QString code) +bool AssemblyDebuggerModel::compile(QString _code) { ConstantCompilationModel compiler; - CompilerResult res = compiler.compile(code); + CompilerResult res = compiler.compile(_code); return res.success; } diff --git a/mix/AssemblyDebuggerModel.h b/mix/AssemblyDebuggerModel.h index 378f238e6..c0941dc8f 100644 --- a/mix/AssemblyDebuggerModel.h +++ b/mix/AssemblyDebuggerModel.h @@ -38,7 +38,7 @@ public: AssemblyDebuggerModel(); DebuggingContent getContractInitiationDebugStates(dev::u256, dev::u256, dev::u256, QString, KeyPair); DebuggingContent getContractInitiationDebugStates(dev::bytesConstRef); - bool compile(QString code); + bool compile(QString); private: std::unique_ptr m_currentExecution; diff --git a/mix/CodeEditorExtensionManager.cpp b/mix/CodeEditorExtensionManager.cpp index 503e07447..3bef1a828 100644 --- a/mix/CodeEditorExtensionManager.cpp +++ b/mix/CodeEditorExtensionManager.cpp @@ -28,7 +28,6 @@ #include #include "ConstantCompilationCtrl.h" #include "AssemblyDebuggerCtrl.h" -#include "features.h" #include "ApplicationCtx.h" #include "CodeEditorExtensionManager.h" using namespace dev::mix; diff --git a/mix/DebuggingStateWrapper.cpp b/mix/DebuggingStateWrapper.cpp index 3bce8658b..d96c975cd 100644 --- a/mix/DebuggingStateWrapper.cpp +++ b/mix/DebuggingStateWrapper.cpp @@ -31,13 +31,13 @@ using namespace dev; using namespace dev::eth; using namespace dev::mix; -std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCode(const bytes& code, QObject* _objUsedAsParent) +std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCode(const bytes& _code, QObject* _objUsedAsParent) { QList codeStr; QMap codeMapping; - for (unsigned i = 0; i <= code.size(); ++i) + for (unsigned i = 0; i <= _code.size(); ++i) { - byte b = i < code.size() ? code[i] : 0; + byte b = i < _code.size() ? _code[i] : 0; try { QString s = QString::fromStdString(instructionInfo((Instruction)b).name); @@ -48,7 +48,7 @@ std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCod if (b >= (byte)Instruction::PUSH1 && b <= (byte)Instruction::PUSH32) { unsigned bc = b - (byte)Instruction::PUSH1 + 1; - s = "PUSH 0x" + QString::fromStdString(toHex(bytesConstRef(&code[i + 1], bc))); + s = "PUSH 0x" + QString::fromStdString(toHex(bytesConstRef(&_code[i + 1], bc))); i += bc; } HumanReadableCode* humanCode = new HumanReadableCode(QString::fromStdString(out.str()) + " " + s, line, _objUsedAsParent); diff --git a/mix/MixApplication.cpp b/mix/MixApplication.cpp index e67ca1b12..86507329c 100644 --- a/mix/MixApplication.cpp +++ b/mix/MixApplication.cpp @@ -23,7 +23,7 @@ #include "MixApplication.h" using namespace dev::mix; -MixApplication::MixApplication(int _argc, char *_argv[]): QApplication(_argc, _argv) +MixApplication::MixApplication(int _argc, char* _argv[]): QApplication(_argc, _argv) { } From 85fa520d1b8b9487a28b176cd774d404ccee3b56 Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 5 Dec 2014 13:17:37 +0100 Subject: [PATCH 418/641] - Coding Standards --- mix/DebuggingStateWrapper.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mix/DebuggingStateWrapper.h b/mix/DebuggingStateWrapper.h index 0285a4693..3f03004b8 100644 --- a/mix/DebuggingStateWrapper.h +++ b/mix/DebuggingStateWrapper.h @@ -65,7 +65,7 @@ class HumanReadableCode: public QObject Q_PROPERTY(int processIndex READ processIndex) public: - HumanReadableCode(QString _line, int _processIndex, QObject* _parent) : m_line(_line), m_processIndex(_processIndex), QObject(_parent) {} + HumanReadableCode(QString _line, int _processIndex, QObject* _parent): QObject(_parent), m_line(_line), m_processIndex(_processIndex) {} QString line() { return m_line; } int processIndex() { return m_processIndex; } @@ -75,12 +75,12 @@ private: }; /* used to publish QMap type to QML */ -class QQMLMap : public QObject +class QQMLMap: public QObject { Q_OBJECT public: - QQMLMap(QMap _map, QObject* _parent) : m_map(_map), QObject(_parent) { } + QQMLMap(QMap _map, QObject* _parent): QObject(_parent), m_map(_map) { } Q_INVOKABLE int getValue(int _key) { return m_map.value(_key); } private: @@ -88,7 +88,7 @@ private: }; /* used to publish DebuggingState struct to QML */ -class DebuggingStateWrapper : public QObject +class DebuggingStateWrapper: public QObject { Q_OBJECT Q_PROPERTY(int step READ step) From fc8cb6d7af537e6e858ff3fa34f2dc5afc03f57b Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 5 Dec 2014 13:54:30 +0100 Subject: [PATCH 419/641] boost compatibility changes in msvc --- cmake/EthDependencies.cmake | 17 +++++++++++++++++ libdevcore/CMakeLists.txt | 12 +++++------- libdevcore/CommonData.cpp | 16 ++++++++++++++-- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index ae2483cda..223c14ce3 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -53,6 +53,23 @@ set(Boost_COMPILER -vc120) find_package(Boost 1.55.0 REQUIRED COMPONENTS thread date_time system regex) +if (Boost_FOUND) + message(" - boost header: ${Boost_INCLUDE_DIRS}") + message(" - boost lib : ${Boost_LIBRARIES}") +endif() + + + + + + + + + + + + + diff --git a/libdevcore/CMakeLists.txt b/libdevcore/CMakeLists.txt index 3ff0733b4..5bcff1ead 100644 --- a/libdevcore/CMakeLists.txt +++ b/libdevcore/CMakeLists.txt @@ -5,8 +5,9 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) -include_directories(${LEVELDB_INCLUDE_DIR}) include_directories(..) +include_directories(${LEVELDB_INCLUDE_DIR}) +include_directories(${Boost_INCLUDE_DIRS}) set(EXECUTABLE devcore) @@ -18,16 +19,13 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() +target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARY}) + if (APPLE) - # Latest mavericks boost libraries only come with -mt - target_link_libraries(${EXECUTABLE} boost_system-mt) - target_link_libraries(${EXECUTABLE} boost_filesystem-mt) - target_link_libraries(${EXECUTABLE} boost_thread-mt) find_package(Threads REQUIRED) target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) elseif (UNIX) - find_package(Boost 1.53 REQUIRED COMPONENTS thread system) - target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY} ${Boost_SYSTEM_LIBRARY}) find_package(Threads REQUIRED) target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) endif() diff --git a/libdevcore/CommonData.cpp b/libdevcore/CommonData.cpp index d34b565eb..215f9c4b3 100644 --- a/libdevcore/CommonData.cpp +++ b/libdevcore/CommonData.cpp @@ -89,13 +89,25 @@ bytes dev::fromHex(std::string const& _s) { ret.push_back(fromHex(_s[s++])); } - catch (...){ ret.push_back(0); cwarn << boost::current_exception_diagnostic_information(); } + catch (...) + { + ret.push_back(0); + // msvc does not support it +#ifndef BOOST_NO_EXCEPTIONS + cwarn << boost::current_exception_diagnostic_information(); +#endif + } for (unsigned i = s; i < _s.size(); i += 2) try { ret.push_back((byte)(fromHex(_s[i]) * 16 + fromHex(_s[i + 1]))); } - catch (...){ ret.push_back(0); cwarn << boost::current_exception_diagnostic_information(); } + catch (...){ + ret.push_back(0); +#ifndef BOOST_NO_EXCEPTIONS + cwarn << boost::current_exception_diagnostic_information(); +#endif + } return ret; } From 6c5a84cbc13d77780847c0fdb72356f8bf855e0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 5 Dec 2014 14:39:24 +0100 Subject: [PATCH 420/641] Fix random test generator --- test/createRandomTest.cpp | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/test/createRandomTest.cpp b/test/createRandomTest.cpp index 1647ce810..a01eec65c 100644 --- a/test/createRandomTest.cpp +++ b/test/createRandomTest.cpp @@ -1,18 +1,18 @@ /* - This file is part of cpp-ethereum. + This file is part of cpp-ethereum. - cpp-ethereum is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - cpp-ethereum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with cpp-ethereum. If not, see . + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . */ /** @file createRandomTest.cpp * @author Christoph Jentzsch @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include "vm.h" @@ -128,6 +129,9 @@ void doMyTests(json_spirit::mValue& v) assert(o.count("pre") > 0); assert(o.count("exec") > 0); + + auto vmObj = eth::VMFactory::create(eth::VMFactory::Interpreter); + auto& vm = *vmObj; dev::test::FakeExtVM fev; fev.importEnv(o["env"].get_obj()); fev.importState(o["pre"].get_obj()); @@ -141,9 +145,8 @@ void doMyTests(json_spirit::mValue& v) fev.code = fev.thisTxCode; } + vm.reset(fev.gas); bytes output; - eth::VM vm(fev.gas); - u256 gas; bool vmExceptionOccured = false; try From fab154454d52a60634172e1acf584be577c03b8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zaw=C5=82ocki?= Date: Fri, 5 Dec 2014 15:21:54 +0100 Subject: [PATCH 421/641] jit-related CMakeLists.txt fixes --- CMakeLists.txt | 3 +-- eth/CMakeLists.txt | 3 +-- exp/CMakeLists.txt | 2 +- libethereum/CMakeLists.txt | 1 + neth/CMakeLists.txt | 3 +-- test/CMakeLists.txt | 6 ++---- 6 files changed, 7 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9918b4ee1..ec2c90cc7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -176,8 +176,7 @@ if (NOT LANGUAGES) endif() if (EVMJIT) - add_subdirectory(libevmjit) - add_subdirectory(evmcc) + add_subdirectory(evmjit) endif() diff --git a/eth/CMakeLists.txt b/eth/CMakeLists.txt index 9239e79ac..918e8d047 100644 --- a/eth/CMakeLists.txt +++ b/eth/CMakeLists.txt @@ -14,8 +14,7 @@ target_link_libraries(${EXECUTABLE} secp256k1) target_link_libraries(${EXECUTABLE} gmp) if(EVMJIT) - target_link_libraries(${EXECUTABLE} evm) - target_link_libraries(${EXECUTABLE} evmjit) + target_link_libraries(${EXECUTABLE} evmjit-cpp) endif() if(MINIUPNPC_LS) diff --git a/exp/CMakeLists.txt b/exp/CMakeLists.txt index fce739007..a5e1cefea 100644 --- a/exp/CMakeLists.txt +++ b/exp/CMakeLists.txt @@ -18,7 +18,7 @@ endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) if(EVMJIT) - target_link_libraries(${EXECUTABLE} evmjit) + target_link_libraries(${EXECUTABLE} evmjit-cpp) endif() if ("${TARGET_PLATFORM}" STREQUAL "w64") diff --git a/libethereum/CMakeLists.txt b/libethereum/CMakeLists.txt index 6088525fb..973a59ae3 100644 --- a/libethereum/CMakeLists.txt +++ b/libethereum/CMakeLists.txt @@ -30,6 +30,7 @@ target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS}) target_link_libraries(${EXECUTABLE} gmp) if (EVMJIT) target_link_libraries(${EXECUTABLE} evmjit) + target_link_libraries(${EXECUTABLE} evmjit-cpp) endif() if("${TARGET_PLATFORM}" STREQUAL "w64") diff --git a/neth/CMakeLists.txt b/neth/CMakeLists.txt index c3d14c983..e65db71fe 100644 --- a/neth/CMakeLists.txt +++ b/neth/CMakeLists.txt @@ -23,8 +23,7 @@ target_link_libraries(${EXECUTABLE} web3jsonrpc) endif() if(EVMJIT) - target_link_libraries(${EXECUTABLE} evm) - target_link_libraries(${EXECUTABLE} evmjit) + target_link_libraries(${EXECUTABLE} evmjit-cpp) endif() if ("${TARGET_PLATFORM}" STREQUAL "w64") diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8d8430b5c..3336b4289 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -21,8 +21,7 @@ if(JSONRPC_LS) target_link_libraries(testeth web3jsonrpc) endif() if (EVMJIT) - target_link_libraries(testeth evm) - target_link_libraries(testeth evmjit) + target_link_libraries(testeth evmjit-cpp) endif() target_link_libraries(createRandomTest ethereum) @@ -30,8 +29,7 @@ target_link_libraries(createRandomTest ethcore) target_link_libraries(createRandomTest boost_chrono) target_link_libraries(createRandomTest boost_unit_test_framework) if (EVMJIT) - target_link_libraries(createRandomTest evm) - target_link_libraries(createRandomTest evmjit) + target_link_libraries(createRandomTest evmjit-cpp) endif() if ("${TARGET_PLATFORM}" STREQUAL "w64") From bb3a0bc0e43d83fc71bcc44721e561ac98cdfc27 Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 5 Dec 2014 15:25:31 +0100 Subject: [PATCH 422/641] devcore, evmcore, jsqrc compiling on windows --- cmake/EthCompilerSettings.cmake | 63 +++++++++++++++++---------------- libdevcore/CMakeLists.txt | 2 +- libdevcore/RLP.h | 8 ++--- libevmcore/CMakeLists.txt | 5 +-- libevmcore/Instruction.cpp | 4 +++ libjsqrc/CMakeLists.txt | 16 --------- 6 files changed, 44 insertions(+), 54 deletions(-) diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index 2757eb9ad..60ea3c90f 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -12,7 +12,8 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wno-unknown-pragmas -Wextra -DSHAREDLIB") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") - set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -DSHAREDLIB") + set(CMAKE_CXX_FLAGS "") + set(ETH_STATIC 1) else () message(FATAL_ERROR "Your C++ compiler does not support C++11. You have ${CMAKE_CXX_COMPILER_ID}") endif () @@ -27,36 +28,36 @@ set(CMAKE_CXX_FLAGS_RELEASE "-O4 -DNDEBUG -DETH_RELEASE") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -DETH_DEBUG") # Windows -if ("${TARGET_PLATFORM}" STREQUAL "w64") - set(CMAKE_SYSTEM_NAME Windows) - - set(CMAKE_CXX_LIBRARY_ARCHITECTURE x86_64-w64-mingw32) - set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) - set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) - set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres) - set(CMAKE_AR x86_64-w64-mingw32-ar) - set(CMAKE_RANLIB x86_64-w64-mingw32-ranlib) - - set(CMAKE_EXECUTABLE_SUFFIX .exe) - - set(CMAKE_FIND_ROOT_PATH - /usr/x86_64-w64-mingw32 - ) - - include_directories(/usr/x86_64-w64-mingw32/include/cryptopp) - - set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) - set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) - set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) - - set(CMAKE_INSTALL_PREFIX /usr/x86_64-w64-mingw32) - set(ETH_BUILD_PLATFORM "windows") - set(ETH_STATIC 1) -else () - set(ETH_BUILD_PLATFORM ${CMAKE_SYSTEM_NAME}) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") - set(ETH_SHARED 1) -endif() +#if ("${TARGET_PLATFORM}" STREQUAL "w64") +# set(CMAKE_SYSTEM_NAME Windows) +# +# set(CMAKE_CXX_LIBRARY_ARCHITECTURE x86_64-w64-mingw32) +# set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) +# set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) +# set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres) +# set(CMAKE_AR x86_64-w64-mingw32-ar) +# set(CMAKE_RANLIB x86_64-w64-mingw32-ranlib) +# +# set(CMAKE_EXECUTABLE_SUFFIX .exe) +# +# set(CMAKE_FIND_ROOT_PATH +# /usr/x86_64-w64-mingw32 +# ) +# +# include_directories(/usr/x86_64-w64-mingw32/include/cryptopp) +# +# set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +# set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +# set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +# +# set(CMAKE_INSTALL_PREFIX /usr/x86_64-w64-mingw32) +# set(ETH_BUILD_PLATFORM "windows") +# set(ETH_STATIC 1) +#else () +# set(ETH_BUILD_PLATFORM ${CMAKE_SYSTEM_NAME}) +# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") +# set(ETH_SHARED 1) +#endif() diff --git a/libdevcore/CMakeLists.txt b/libdevcore/CMakeLists.txt index 5bcff1ead..c6f3b735d 100644 --- a/libdevcore/CMakeLists.txt +++ b/libdevcore/CMakeLists.txt @@ -19,8 +19,8 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY}) target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY}) if (APPLE) find_package(Threads REQUIRED) diff --git a/libdevcore/RLP.h b/libdevcore/RLP.h index 3101f63d6..2eedbaba2 100644 --- a/libdevcore/RLP.h +++ b/libdevcore/RLP.h @@ -28,10 +28,10 @@ #include #include #include -#include -#include -#include -#include +#include "vector_ref.h" +#include "Common.h" +#include "Exceptions.h" +#include "FixedHash.h" namespace dev { diff --git a/libevmcore/CMakeLists.txt b/libevmcore/CMakeLists.txt index b889e7163..472e112a1 100644 --- a/libevmcore/CMakeLists.txt +++ b/libevmcore/CMakeLists.txt @@ -5,6 +5,9 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) +include_directories(..) +include_directories(${Boost_INCLUDE_DIRS}) + set(EXECUTABLE evmcore) file(GLOB HEADERS "*.h") @@ -14,8 +17,6 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -include_directories(..) - target_link_libraries(${EXECUTABLE} devcore) install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) diff --git a/libevmcore/Instruction.cpp b/libevmcore/Instruction.cpp index 9062fd8ed..b4a4d9f3b 100644 --- a/libevmcore/Instruction.cpp +++ b/libevmcore/Instruction.cpp @@ -326,7 +326,11 @@ InstructionInfo dev::eth::instructionInfo(Instruction _inst) } catch (...) { +#ifndef BOOST_NO_EXCEPTIONS cwarn << "\n" << boost::current_exception_diagnostic_information(); +#else + cwarn << "\n"; +#endif return InstructionInfo({"", 0, 0, 0, false}); } } diff --git a/libjsqrc/CMakeLists.txt b/libjsqrc/CMakeLists.txt index 9c505df2b..b8beec2ff 100644 --- a/libjsqrc/CMakeLists.txt +++ b/libjsqrc/CMakeLists.txt @@ -1,20 +1,4 @@ cmake_policy(SET CMP0015 NEW) - -# Find Qt5 for Apple and update src_list for windows -if (APPLE) - # homebrew defaults to qt4 and installs qt5 as 'keg-only' - # which places it into /usr/local/opt insteadof /usr/local. - - set(CMAKE_PREFIX_PATH /usr/local/opt/qt5) - include_directories(/usr/local/opt/qt5/include /usr/local/include) -elseif ("${TARGET_PLATFORM}" STREQUAL "w64") - set(SRC_LIST ${SRC_LIST} ../windows/qt_plugin_import.cpp) -elseif (UNIX) - set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ";$ENV{QTDIR}/lib/cmake") -endif () - -find_package(Qt5Core) - set(CMAKE_AUTOMOC OFF) qt5_add_resources(JSQRC js.qrc) From 1d6f52fc4a2969adf55c5f3c79991e5c1e350800 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 5 Dec 2014 15:26:55 +0100 Subject: [PATCH 423/641] evmjit submodule update --- evmjit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evmjit b/evmjit index 2b9b53024..c9f5694a2 160000 --- a/evmjit +++ b/evmjit @@ -1 +1 @@ -Subproject commit 2b9b53024dfa62b62a322909a43154f65f29d4ce +Subproject commit c9f5694a285412f693b160cf83e6258b0c41c504 From eb3e005dee2b03a2fa43b4d806338996a4586d97 Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 5 Dec 2014 16:20:00 +0100 Subject: [PATCH 424/641] use unique_ptr for QQMLApplicationEngine --- mix/ApplicationCtx.cpp | 11 +++-------- mix/ApplicationCtx.h | 4 ++-- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/mix/ApplicationCtx.cpp b/mix/ApplicationCtx.cpp index 99d9bee4c..0130f2dfb 100644 --- a/mix/ApplicationCtx.cpp +++ b/mix/ApplicationCtx.cpp @@ -37,19 +37,14 @@ ApplicationCtx* ApplicationCtx::Instance = nullptr; ApplicationCtx::ApplicationCtx(QQmlApplicationEngine* _engine) { - m_applicationEngine = _engine; + m_applicationEngine = std::unique_ptr(_engine); m_keyEventManager = std::unique_ptr(new KeyEventManager()); m_webThree = std::unique_ptr(new WebThreeDirect(std::string("Mix/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir() + "/Mix", false, {"eth", "shh"})); } -ApplicationCtx::~ApplicationCtx() -{ - delete m_applicationEngine; -} - QQmlApplicationEngine* ApplicationCtx::appEngine() { - return m_applicationEngine; + return m_applicationEngine.get(); } dev::eth::Client* ApplicationCtx::getEthereumClient() @@ -81,7 +76,7 @@ void ApplicationCtx::setApplicationContext(QQmlApplicationEngine* _engine) void ApplicationCtx::displayMessageDialog(QString _title, QString _message) { - QQmlComponent component(m_applicationEngine, QUrl("qrc:/qml/BasicMessage.qml")); + QQmlComponent component(m_applicationEngine.get(), QUrl("qrc:/qml/BasicMessage.qml")); QObject* dialog = component.create(); dialog->findChild("messageContent", Qt::FindChildrenRecursively)->setProperty("text", _message); QObject* dialogWin = ApplicationCtx::getInstance()->appEngine()->rootObjects().at(0)->findChild("messageDialog", Qt::FindChildrenRecursively); diff --git a/mix/ApplicationCtx.h b/mix/ApplicationCtx.h index 05e4f3bb3..5680c860e 100644 --- a/mix/ApplicationCtx.h +++ b/mix/ApplicationCtx.h @@ -42,7 +42,7 @@ class ApplicationCtx: public QObject public: ApplicationCtx(QQmlApplicationEngine* _engine); - ~ApplicationCtx(); + ~ApplicationCtx() {} static ApplicationCtx* getInstance() { return Instance; } static void setApplicationContext(QQmlApplicationEngine* _engine); QQmlApplicationEngine* appEngine(); @@ -53,7 +53,7 @@ public: private: static ApplicationCtx* Instance; - QQmlApplicationEngine* m_applicationEngine; + std::unique_ptr m_applicationEngine; std::unique_ptr m_webThree; std::unique_ptr m_keyEventManager; From 9d59ee4aa18597f8b02381f03f6f1429b9c2dc3d Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 5 Dec 2014 16:40:41 +0100 Subject: [PATCH 425/641] lll, buildinfo.h and llc compiling on windows --- CMakeLists.txt | 11 +++++++++-- libdevcore/CMakeLists.txt | 2 +- libevmcore/CMakeLists.txt | 2 +- liblll/CMakeLists.txt | 30 +++--------------------------- lllc/CMakeLists.txt | 25 ++++++++----------------- 5 files changed, 22 insertions(+), 48 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8fc718297..d4be26923 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,7 +51,7 @@ function(createBuildInfo) set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/msys") elseif (CMAKE_COMPILER_IS_GNUCXX) set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/g++") - elseif (CMAKE_COMPILER_IS_MSVC) + elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/msvc") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/clang") @@ -59,8 +59,15 @@ function(createBuildInfo) set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/unknown") endif () + #cmake build type may be not specified when using msvc + if (${CMAKE_BUILD_TYPE}) + set(_cmake_build_type ${CMAKE_BUILD_TYPE}) + else() + set(_cmake_build_type "undefined") + endif() + # Generate header file containing useful build information - add_custom_target(BuildInfo.h ALL COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/BuildInfo.sh ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_BUILD_TYPE} ${ETH_BUILD_PLATFORM}) + add_custom_target(BuildInfo.h ALL COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/BuildInfo.sh ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${_cmake_build_type} ${ETH_BUILD_PLATFORM}) include_directories(${CMAKE_CURRENT_BINARY_DIR}) set(CMAKE_INCLUDE_CURRENT_DIR ON) diff --git a/libdevcore/CMakeLists.txt b/libdevcore/CMakeLists.txt index c6f3b735d..3d103160c 100644 --- a/libdevcore/CMakeLists.txt +++ b/libdevcore/CMakeLists.txt @@ -5,9 +5,9 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) -include_directories(..) include_directories(${LEVELDB_INCLUDE_DIR}) include_directories(${Boost_INCLUDE_DIRS}) +include_directories(..) set(EXECUTABLE devcore) diff --git a/libevmcore/CMakeLists.txt b/libevmcore/CMakeLists.txt index 472e112a1..0f71dcd40 100644 --- a/libevmcore/CMakeLists.txt +++ b/libevmcore/CMakeLists.txt @@ -5,8 +5,8 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) -include_directories(..) include_directories(${Boost_INCLUDE_DIRS}) +include_directories(..) set(EXECUTABLE evmcore) diff --git a/liblll/CMakeLists.txt b/liblll/CMakeLists.txt index 4e6941359..e2c000010 100644 --- a/liblll/CMakeLists.txt +++ b/liblll/CMakeLists.txt @@ -5,6 +5,9 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) +include_directories(${Boost_INCLUDE_DIRS}) +include_directories(..) + set(EXECUTABLE lll) file(GLOB HEADERS "*.h") @@ -14,36 +17,9 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -include_directories(..) - target_link_libraries(${EXECUTABLE} evmcore) target_link_libraries(${EXECUTABLE} devcore) - -if("${TARGET_PLATFORM}" STREQUAL "w64") - target_link_libraries(${EXECUTABLE} boost_system-mt-s) - target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) - target_link_libraries(${EXECUTABLE} iphlpapi) - target_link_libraries(${EXECUTABLE} ws2_32) - target_link_libraries(${EXECUTABLE} mswsock) - target_link_libraries(${EXECUTABLE} shlwapi) -elseif (APPLE) - # Latest mavericks boost libraries only come with -mt - target_link_libraries(${EXECUTABLE} boost_system-mt) - target_link_libraries(${EXECUTABLE} boost_thread-mt) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -elseif (UNIX) - target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -else () - target_link_libraries(${EXECUTABLE} boost_system) - target_link_libraries(${EXECUTABLE} boost_thread) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -endif () - install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/lllc/CMakeLists.txt b/lllc/CMakeLists.txt index 3310354fb..0ca19fab9 100644 --- a/lllc/CMakeLists.txt +++ b/lllc/CMakeLists.txt @@ -3,31 +3,22 @@ set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) +include_directories(${Boost_INCLUDE_DIRS}) include_directories(..) set(EXECUTABLE lllc) -add_executable(${EXECUTABLE} ${SRC_LIST}) +if(ETH_STATIC) + add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) +else() + add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) +endif() + +add_dependencies(${EXECUTABLE} BuildInfo.h) target_link_libraries(${EXECUTABLE} lll) target_link_libraries(${EXECUTABLE} evmcore) target_link_libraries(${EXECUTABLE} devcore) -if ("${TARGET_PLATFORM}" STREQUAL "w64") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") - target_link_libraries(${EXECUTABLE} gcc) - target_link_libraries(${EXECUTABLE} gdi32) - target_link_libraries(${EXECUTABLE} ws2_32) - target_link_libraries(${EXECUTABLE} mswsock) - target_link_libraries(${EXECUTABLE} shlwapi) - target_link_libraries(${EXECUTABLE} iphlpapi) - target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) - set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) -elseif (UNIX) -else () - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -endif () - install( TARGETS ${EXECUTABLE} DESTINATION bin ) From 5063433df42fca47566a78625334cf3ff9f03114 Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 5 Dec 2014 17:00:26 +0100 Subject: [PATCH 426/641] solidity compiling on windows, fixed Compiler Error C2797 --- libsolidity/CMakeLists.txt | 5 +++-- libsolidity/GlobalContext.cpp | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index 260493b0e..8522130ee 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -5,6 +5,9 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) +include_directories(${Boost_INCLUDE_DIRS}) +include_directories(..) + set(EXECUTABLE solidity) file(GLOB HEADERS "*.h") @@ -14,8 +17,6 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -include_directories(..) - target_link_libraries(${EXECUTABLE} evmcore devcore) install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) diff --git a/libsolidity/GlobalContext.cpp b/libsolidity/GlobalContext.cpp index d8b637076..b54b93c03 100644 --- a/libsolidity/GlobalContext.cpp +++ b/libsolidity/GlobalContext.cpp @@ -33,7 +33,7 @@ namespace solidity { GlobalContext::GlobalContext(): - m_magicVariables{make_shared("block", make_shared(MagicType::Kind::BLOCK)), +m_magicVariables(vector>{make_shared("block", make_shared(MagicType::Kind::BLOCK)), make_shared("msg", make_shared(MagicType::Kind::MSG)), make_shared("tx", make_shared(MagicType::Kind::TX)), make_shared("suicide", @@ -59,7 +59,7 @@ GlobalContext::GlobalContext(): make_shared("ripemd160", make_shared(TypePointers({std::make_shared(256, IntegerType::Modifier::HASH)}), TypePointers({std::make_shared(160, IntegerType::Modifier::HASH)}), - FunctionType::Location::RIPEMD160))} + FunctionType::Location::RIPEMD160))}) { } From 548dda844a1dcb798ce708700571ff7423034ae5 Mon Sep 17 00:00:00 2001 From: debris Date: Sun, 7 Dec 2014 11:29:38 +0100 Subject: [PATCH 427/641] solidity compiling under msvc && boosts cmake file fixed --- extdep/CMakeLists.txt | 22 +++---- extdep/compile/boost.cmake | 19 ++++++ extdep/compile/configure.bat | 111 +++++++++++++++++++++++++++++++++ libsolidity/CMakeLists.txt | 9 ++- libsolidity/CompilerStack.h | 16 +++++ libsolidity/InterfaceHandler.h | 2 +- lllc/CMakeLists.txt | 8 +-- solc/CMakeLists.txt | 4 +- 8 files changed, 167 insertions(+), 24 deletions(-) create mode 100644 extdep/compile/boost.cmake create mode 100644 extdep/compile/configure.bat diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index cea32c80f..f57d6eac8 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -6,7 +6,7 @@ include(eth_download.cmake) # all dependencies will be installed into this directory, separated by platform string(TOLOWER ${CMAKE_SYSTEM_NAME} _system_name) -set(ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/install/${_system_name}") +set(ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/install2/${_system_name}") set(ETH_DEPENDENCY_SERVER "http://poc-7.ethdev.com/precompiled/${_system_name}") file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/lib) file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/include) @@ -14,22 +14,22 @@ file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/bin) if (ETH_COMPILE) # json-rpc-cpp and its dependencies - include(compile/jsoncpp.cmake) - include(compile/argtable2.cmake) - include(compile/curl.cmake) - include(compile/json-rpc-cpp.cmake) + #include(compile/jsoncpp.cmake) + #include(compile/argtable2.cmake) + #include(compile/curl.cmake) + #include(compile/json-rpc-cpp.cmake) # qt at its dependencies - include(compile/icu.cmake) - include(compile/jom.cmake) - include(compile/qt.cmake) + #include(compile/icu.cmake) + #include(compile/jom.cmake) + #include(compile/qt.cmake) # leveldb and its dependencies - include(compile/snappy.cmake) - include(compile/leveldb.cmake) + #include(compile/snappy.cmake) + #include(compile/leveldb.cmake) # cryptopp - include(compile/cryptopp.cmake) + #include(compile/cryptopp.cmake) # boost include(compile/boost.cmake) diff --git a/extdep/compile/boost.cmake b/extdep/compile/boost.cmake new file mode 100644 index 000000000..aaf892cc9 --- /dev/null +++ b/extdep/compile/boost.cmake @@ -0,0 +1,19 @@ +if(APPLE) + +elseif(WIN32) +set(boost_address_model) +# on windows 64: +# set(boost_address_model address-model=64) + +set(boost_targets --with-filesystem --with-system --with-thread --with-date_time --with-regex --with-test) +ExternalProject_Add(boost + URL http://downloads.sourceforge.net/project/boost/boost/1.55.0/boost_1_55_0.tar.gz + BINARY_DIR boost-prefix/src/boost + CONFIGURE_COMMAND ./bootstrap.bat + BUILD_COMMAND ./b2.exe -j4 --build-type=complete link=static runtime-link=shared variant=debug,release threading=multi ${boost_addressModel} ${boost_targets} install --prefix=${ETH_DEPENDENCY_INSTALL_DIR} + INSTALL_COMMAND cmake -E rename ${ETH_DEPENDENCY_INSTALL_DIR}/include/boost-1_55/boost ${ETH_DEPENDENCY_INSTALL_DIR}/include/boost + ) +else() + +endif() + diff --git a/extdep/compile/configure.bat b/extdep/compile/configure.bat new file mode 100644 index 000000000..bd810938a --- /dev/null +++ b/extdep/compile/configure.bat @@ -0,0 +1,111 @@ +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:: +:: Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +:: Contact: http://www.qt-project.org/legal +:: +:: This file is part of the tools applications of the Qt Toolkit. +:: +:: $QT_BEGIN_LICENSE:LGPL$ +:: Commercial License Usage +:: Licensees holding valid commercial Qt licenses may use this file in +:: accordance with the commercial license agreement provided with the +:: Software or, alternatively, in accordance with the terms contained in +:: a written agreement between you and Digia. For licensing terms and +:: conditions see http://qt.digia.com/licensing. For further information +:: use the contact form at http://qt.digia.com/contact-us. +:: +:: GNU Lesser General Public License Usage +:: Alternatively, this file may be used under the terms of the GNU Lesser +:: General Public License version 2.1 as published by the Free Software +:: Foundation and appearing in the file LICENSE.LGPL included in the +:: packaging of this file. Please review the following information to +:: ensure the GNU Lesser General Public License version 2.1 requirements +:: will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +:: +:: In addition, as a special exception, Digia gives you certain additional +:: rights. These rights are described in the Digia Qt LGPL Exception +:: version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +:: +:: GNU General Public License Usage +:: Alternatively, this file may be used under the terms of the GNU +:: General Public License version 3.0 as published by the Free Software +:: Foundation and appearing in the file LICENSE.GPL included in the +:: packaging of this file. Please review the following information to +:: ensure the GNU General Public License version 3.0 requirements will be +:: met: http://www.gnu.org/copyleft/gpl.html. +:: +:: +:: $QT_END_LICENSE$ +:: +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + +@echo off +set QTSRC=%~dp0 +set QTDIR=%CD% +::if not exist %QTSRC%\.gitignore goto sconf +echo Please wait while bootstrapping configure ... + +for %%C in (cl.exe icl.exe g++.exe perl.exe) do set %%C=%%~$PATH:C + +if "%perl.exe%" == "" ( + echo Perl not found in PATH. Aborting. >&2 + exit /b 1 +) +if not exist mkspecs ( + md mkspecs + if errorlevel 1 goto exit +) +perl %QTSRC%bin\syncqt.pl -minimal -module QtCore -outdir %QTDIR% %QTSRC% +if errorlevel 1 goto exit + +if not exist tools\configure ( + md tools\configure + if errorlevel 1 goto exit +) +cd tools\configure +if errorlevel 1 goto exit + +echo #### Generated by configure.bat - DO NOT EDIT! ####> Makefile +echo/>> Makefile +for /f "tokens=3 usebackq" %%V in (`findstr QT_VERSION_STR %QTSRC%\src\corelib\global\qglobal.h`) do @echo QTVERSION = %%~V>> Makefile +if not "%cl.exe%" == "" ( + echo CXX = cl>>Makefile + echo EXTRA_CXXFLAGS =>>Makefile + rem This must have a trailing space. + echo QTSRC = %QTSRC% >> Makefile + set tmpl=win32 + set make=nmake +) else if not "%icl.exe%" == "" ( + echo CXX = icl>>Makefile + echo EXTRA_CXXFLAGS = /Zc:forScope>>Makefile + rem This must have a trailing space. + echo QTSRC = %QTSRC% >> Makefile + set tmpl=win32 + set make=nmake +) else if not "%g++.exe%" == "" ( + echo CXX = g++>>Makefile + echo EXTRA_CXXFLAGS =>>Makefile + rem This must NOT have a trailing space. + echo QTSRC = %QTSRC:\=/%>> Makefile + set tmpl=mingw + set make=mingw32-make +) else ( + echo No suitable compiler found in PATH. Aborting. >&2 + cd ..\.. + exit /b 1 +) +echo/>> Makefile +type %QTSRC%tools\configure\Makefile.%tmpl% >> Makefile + +%make% +if errorlevel 1 (cd ..\.. & exit /b 1) + +cd ..\.. + +:conf +configure.exe -srcdir %QTSRC% %* +goto exit + +:sconf +%QTSRC%\configure.exe %* +:exit diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index 0f2dbbcd4..895b22ae0 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -6,6 +6,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) include_directories(${Boost_INCLUDE_DIRS}) +include_directories(${JSONCPP_INCLUDE_DIRS}) include_directories(..) set(EXECUTABLE solidity) @@ -17,11 +18,9 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -target_link_libraries(${EXECUTABLE} evmcore devcore) -# TODO: Temporary until PR 532 https://github.com/ethereum/cpp-ethereum/pull/532 -# gets accepted. Then we can simply add jsoncpp as a dependency and not the -# whole of JSONRPC as we are doing right here -target_link_libraries(${EXECUTABLE} ${JSONRPC_LS}) +target_link_libraries(${EXECUTABLE} evmcore) +target_link_libraries(${EXECUTABLE} devcore) +target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libsolidity/CompilerStack.h b/libsolidity/CompilerStack.h index 928815cc5..6286eb7ff 100644 --- a/libsolidity/CompilerStack.h +++ b/libsolidity/CompilerStack.h @@ -84,6 +84,22 @@ public: /// scanning the source code - this is useful for printing exception information. static bytes staticCompile(std::string const& _sourceCode, bool _optimize = false); + /// Compile under msvc results in error CC2280 + CompilerStack& operator=(const CompilerStack& _other) + { + m_scanner = _other.m_scanner; + m_globalContext = _other.m_globalContext; + m_contractASTNode = _other.m_contractASTNode; + m_parseSuccessful = _other.m_parseSuccessful; + m_interface.reset(_other.m_interface.get()); + m_userDocumentation.reset(_other.m_userDocumentation.get()); + m_devDocumentation.reset(_other.m_devDocumentation.get()); + m_compiler = _other.m_compiler; + m_interfaceHandler = _other.m_interfaceHandler; + m_bytecode = m_bytecode; + return *this; + } + private: std::shared_ptr m_scanner; std::shared_ptr m_globalContext; diff --git a/libsolidity/InterfaceHandler.h b/libsolidity/InterfaceHandler.h index 524e2903c..a31cd5c11 100644 --- a/libsolidity/InterfaceHandler.h +++ b/libsolidity/InterfaceHandler.h @@ -28,7 +28,7 @@ #include #include -#include +#include namespace dev { diff --git a/lllc/CMakeLists.txt b/lllc/CMakeLists.txt index 0ca19fab9..9549f89e5 100644 --- a/lllc/CMakeLists.txt +++ b/lllc/CMakeLists.txt @@ -3,16 +3,12 @@ set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) -include_directories(${Boost_INCLUDE_DIRS}) include_directories(..) set(EXECUTABLE lllc) -if(ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) -else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) -endif() +file(GLOB HEADERS "*.h") +add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) add_dependencies(${EXECUTABLE} BuildInfo.h) diff --git a/solc/CMakeLists.txt b/solc/CMakeLists.txt index ab402ed8e..203a616b4 100644 --- a/solc/CMakeLists.txt +++ b/solc/CMakeLists.txt @@ -3,11 +3,13 @@ set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) +include_directories(${Boost_INCLUDE_DIRS}) include_directories(..) set(EXECUTABLE solc) -add_executable(${EXECUTABLE} ${SRC_LIST}) +file(GLOB HEADERS "*.h") +add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) target_link_libraries(${EXECUTABLE} solidity) From 96441cbe9a887065d8af7f3e29367a7e7db8bf3b Mon Sep 17 00:00:00 2001 From: debris Date: Sun, 7 Dec 2014 19:07:51 +0100 Subject: [PATCH 428/641] solc working --- cmake/EthCompilerSettings.cmake | 2 +- cmake/EthDependencies.cmake | 2 +- extdep/compile/boost.cmake | 2 +- libdevcore/CMakeLists.txt | 4 ---- solc/CMakeLists.txt | 4 ++++ 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index 60ea3c90f..69a420333 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -12,7 +12,7 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wno-unknown-pragmas -Wextra -DSHAREDLIB") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") - set(CMAKE_CXX_FLAGS "") + set(CMAKE_CXX_FLAGS "/EHsc") set(ETH_STATIC 1) else () message(FATAL_ERROR "Your C++ compiler does not support C++11. You have ${CMAKE_CXX_COMPILER_ID}") diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 223c14ce3..743968dcb 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -51,7 +51,7 @@ set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_COMPILER -vc120) -find_package(Boost 1.55.0 REQUIRED COMPONENTS thread date_time system regex) +find_package(Boost 1.55.0 REQUIRED COMPONENTS thread date_time system regex chrono) if (Boost_FOUND) message(" - boost header: ${Boost_INCLUDE_DIRS}") diff --git a/extdep/compile/boost.cmake b/extdep/compile/boost.cmake index aaf892cc9..c87c907b7 100644 --- a/extdep/compile/boost.cmake +++ b/extdep/compile/boost.cmake @@ -5,7 +5,7 @@ set(boost_address_model) # on windows 64: # set(boost_address_model address-model=64) -set(boost_targets --with-filesystem --with-system --with-thread --with-date_time --with-regex --with-test) +set(boost_targets --with-filesystem --with-system --with-thread --with-date_time --with-regex --with-test --with-chrono) ExternalProject_Add(boost URL http://downloads.sourceforge.net/project/boost/boost/1.55.0/boost_1_55_0.tar.gz BINARY_DIR boost-prefix/src/boost diff --git a/libdevcore/CMakeLists.txt b/libdevcore/CMakeLists.txt index 3d103160c..37e6f4c89 100644 --- a/libdevcore/CMakeLists.txt +++ b/libdevcore/CMakeLists.txt @@ -5,7 +5,6 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) -include_directories(${LEVELDB_INCLUDE_DIR}) include_directories(${Boost_INCLUDE_DIRS}) include_directories(..) @@ -19,9 +18,6 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARY}) -target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY}) - if (APPLE) find_package(Threads REQUIRED) target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) diff --git a/solc/CMakeLists.txt b/solc/CMakeLists.txt index 203a616b4..303318502 100644 --- a/solc/CMakeLists.txt +++ b/solc/CMakeLists.txt @@ -11,6 +11,10 @@ set(EXECUTABLE solc) file(GLOB HEADERS "*.h") add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) +target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY_RELEASE}) +target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARY_RELEASE}) +target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARY_RELEASE}) +target_link_libraries(${EXECUTABLE} ${Boost_CHRONO_LIBRARY_RELEASE}) target_link_libraries(${EXECUTABLE} solidity) install( TARGETS ${EXECUTABLE} DESTINATION bin ) From cd0a5381380c9ae95074a79e5169d6fbd2fb3b6a Mon Sep 17 00:00:00 2001 From: debris Date: Sun, 7 Dec 2014 19:55:40 +0100 Subject: [PATCH 429/641] serpent compiling under msvc --- extdep/CMakeLists.txt | 22 +++++++++++----------- libdevcore/CMakeLists.txt | 5 +++++ libserpent/CMakeLists.txt | 24 ++---------------------- libserpent/rewriter.cpp | 1 + libserpent/util.cpp | 1 + lllc/CMakeLists.txt | 1 + solc/CMakeLists.txt | 4 ---- 7 files changed, 21 insertions(+), 37 deletions(-) diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index f57d6eac8..cea32c80f 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -6,7 +6,7 @@ include(eth_download.cmake) # all dependencies will be installed into this directory, separated by platform string(TOLOWER ${CMAKE_SYSTEM_NAME} _system_name) -set(ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/install2/${_system_name}") +set(ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/install/${_system_name}") set(ETH_DEPENDENCY_SERVER "http://poc-7.ethdev.com/precompiled/${_system_name}") file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/lib) file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/include) @@ -14,22 +14,22 @@ file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/bin) if (ETH_COMPILE) # json-rpc-cpp and its dependencies - #include(compile/jsoncpp.cmake) - #include(compile/argtable2.cmake) - #include(compile/curl.cmake) - #include(compile/json-rpc-cpp.cmake) + include(compile/jsoncpp.cmake) + include(compile/argtable2.cmake) + include(compile/curl.cmake) + include(compile/json-rpc-cpp.cmake) # qt at its dependencies - #include(compile/icu.cmake) - #include(compile/jom.cmake) - #include(compile/qt.cmake) + include(compile/icu.cmake) + include(compile/jom.cmake) + include(compile/qt.cmake) # leveldb and its dependencies - #include(compile/snappy.cmake) - #include(compile/leveldb.cmake) + include(compile/snappy.cmake) + include(compile/leveldb.cmake) # cryptopp - #include(compile/cryptopp.cmake) + include(compile/cryptopp.cmake) # boost include(compile/boost.cmake) diff --git a/libdevcore/CMakeLists.txt b/libdevcore/CMakeLists.txt index 37e6f4c89..06cbe850c 100644 --- a/libdevcore/CMakeLists.txt +++ b/libdevcore/CMakeLists.txt @@ -18,6 +18,11 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() +target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY_RELEASE}) +target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARY_RELEASE}) +target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARY_RELEASE}) +target_link_libraries(${EXECUTABLE} ${Boost_CHRONO_LIBRARY_RELEASE}) + if (APPLE) find_package(Threads REQUIRED) target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) diff --git a/libserpent/CMakeLists.txt b/libserpent/CMakeLists.txt index 315970a7a..365b1bc9e 100644 --- a/libserpent/CMakeLists.txt +++ b/libserpent/CMakeLists.txt @@ -5,6 +5,8 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) +include_directories(..) + set(EXECUTABLE serpent) file(GLOB HEADERS "*.h") @@ -14,32 +16,10 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -include_directories(..) - target_link_libraries(${EXECUTABLE} lll) target_link_libraries(${EXECUTABLE} evmcore) target_link_libraries(${EXECUTABLE} devcore) -if("${TARGET_PLATFORM}" STREQUAL "w64") - target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) - target_link_libraries(${EXECUTABLE} iphlpapi) - target_link_libraries(${EXECUTABLE} ws2_32) - target_link_libraries(${EXECUTABLE} mswsock) - target_link_libraries(${EXECUTABLE} shlwapi) -elseif (APPLE) - # Latest mavericks boost libraries only come with -mt - target_link_libraries(${EXECUTABLE} boost_thread-mt) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -elseif (UNIX) - target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -else () - target_link_libraries(${EXECUTABLE} boost_thread) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -endif () - install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libserpent/rewriter.cpp b/libserpent/rewriter.cpp index 3042eeb45..443457acf 100644 --- a/libserpent/rewriter.cpp +++ b/libserpent/rewriter.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include "util.h" #include "lllparser.h" #include "bignum.h" diff --git a/libserpent/util.cpp b/libserpent/util.cpp index 39eeb20be..fbce5e8b5 100644 --- a/libserpent/util.cpp +++ b/libserpent/util.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include "util.h" #include "bignum.h" #include diff --git a/lllc/CMakeLists.txt b/lllc/CMakeLists.txt index 9549f89e5..2e76aa6ff 100644 --- a/lllc/CMakeLists.txt +++ b/lllc/CMakeLists.txt @@ -3,6 +3,7 @@ set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) +include_directories(${Boost_INCLUDE_DIRS}) include_directories(..) set(EXECUTABLE lllc) diff --git a/solc/CMakeLists.txt b/solc/CMakeLists.txt index 303318502..203a616b4 100644 --- a/solc/CMakeLists.txt +++ b/solc/CMakeLists.txt @@ -11,10 +11,6 @@ set(EXECUTABLE solc) file(GLOB HEADERS "*.h") add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) -target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY_RELEASE}) -target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARY_RELEASE}) -target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARY_RELEASE}) -target_link_libraries(${EXECUTABLE} ${Boost_CHRONO_LIBRARY_RELEASE}) target_link_libraries(${EXECUTABLE} solidity) install( TARGETS ${EXECUTABLE} DESTINATION bin ) From 74115e23c580f5cdcca17d8b96686eb9eb94fa3a Mon Sep 17 00:00:00 2001 From: debris Date: Sun, 7 Dec 2014 21:53:25 +0100 Subject: [PATCH 430/641] secp256k1 building under msvc --- secp256k1/CMakeLists.txt | 42 +++++++--------------------------------- 1 file changed, 7 insertions(+), 35 deletions(-) diff --git a/secp256k1/CMakeLists.txt b/secp256k1/CMakeLists.txt index cdfadb265..baa58e7e8 100644 --- a/secp256k1/CMakeLists.txt +++ b/secp256k1/CMakeLists.txt @@ -3,47 +3,19 @@ set(CMAKE_AUTOMOC OFF) set(CMAKE_ASM_COMPILER "yasm") +include_directories(${Boost_INCLUDE_DIRS}) + set(EXECUTABLE secp256k1) file(GLOB HEADERS "*.h") - -if ("${TARGET_PLATFORM}" STREQUAL "w64") - add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/field_5x52_asm.o - COMMAND yasm -f win64 -o ${CMAKE_CURRENT_BINARY_DIR}/field_5x52_asm.o ${CMAKE_CURRENT_SOURCE_DIR}/field_5x52_asm.asm - ) - add_custom_target( - asmOut ALL - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/field_5x52_asm.o - ) - if(ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${EXECUTABLE}.c ${CMAKE_CURRENT_BINARY_DIR}/field_5x52_asm.o) - else() - add_library(${EXECUTABLE} SHARED ${EXECUTABLE}.c ${CMAKE_CURRENT_BINARY_DIR}/field_5x52_asm.o) - endif() - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -DUSE_FIELD_5X52 -DUSE_FIELD_5X52_ASM -DUSE_NUM_GMP -DUSE_FIELD_INV_NUM") -elseif(APPLE) - if(ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${EXECUTABLE}.c field_5x52_asm.asm) - else() - find_library(GMP_LS gmp /usr/local/lib) - add_library(${EXECUTABLE} SHARED ${EXECUTABLE}.c field_5x52_asm.asm) - endif() - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -DUSE_FIELD_GMP -DUSE_NUM_GMP -DUSE_FIELD_INV_NUM") +if(ETH_STATIC) + add_library(${EXECUTABLE} STATIC ${EXECUTABLE}.c) else() - if(ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${EXECUTABLE}.c field_5x52_asm.asm) - else() - add_library(${EXECUTABLE} SHARED ${EXECUTABLE}.c field_5x52_asm.asm) - endif() - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -DUSE_FIELD_GMP -DUSE_NUM_GMP -DUSE_FIELD_INV_NUM") + add_library(${EXECUTABLE} SHARED ${EXECUTABLE}.c) endif() -if (NOT GMP_LS) - set(GMP_LS gmp) -endif () - -target_link_libraries(${EXECUTABLE} ${GMP_LS}) +set_target_properties(${EXECUTABLE} PROPERTIES COMPILE_FLAGS "/TP") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSE_NUM_BOOST -DUSE_FIELD_10X26 -DUSE_FIELD_INV_BUILTIN") install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) From d00c595a74e59cacb155da03aeb58c2ce21cea01 Mon Sep 17 00:00:00 2001 From: debris Date: Sun, 7 Dec 2014 22:13:05 +0100 Subject: [PATCH 431/641] sc and devcrypto working on windows --- cmake/EthDependencies.cmake | 2 +- libdevcrypto/CMakeLists.txt | 18 ++++---------- libp2p/CMakeLists.txt | 47 ++++++------------------------------- sc/CMakeLists.txt | 16 ------------- 4 files changed, 13 insertions(+), 70 deletions(-) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 743968dcb..fb367ef7b 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -51,7 +51,7 @@ set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_COMPILER -vc120) -find_package(Boost 1.55.0 REQUIRED COMPONENTS thread date_time system regex chrono) +find_package(Boost 1.55.0 REQUIRED COMPONENTS thread date_time system regex chrono filesystem) if (Boost_FOUND) message(" - boost header: ${Boost_INCLUDE_DIRS}") diff --git a/libdevcrypto/CMakeLists.txt b/libdevcrypto/CMakeLists.txt index 423a9ccc6..bf564e915 100644 --- a/libdevcrypto/CMakeLists.txt +++ b/libdevcrypto/CMakeLists.txt @@ -3,6 +3,10 @@ set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) +include_directories(${CRYPTOPP_INCLUDE_DIR}) +include_directories(${LEVELDB_INCLUDE_DIR}) +include_directories(..) + set(EXECUTABLE devcrypto) file(GLOB HEADERS "*.h") @@ -12,23 +16,11 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -include_directories(${CRYPTOPP_INCLUDE_DIR}) -include_directories(${LEVELDB_INCLUDE_DIR}) -include_directories(..) - +target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARY_RELEASE}) target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LIBRARIES}) target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} secp256k1) -target_link_libraries(${EXECUTABLE} gmp) - -if (APPLE) - # Latest mavericks boost libraries only come with -mt - target_link_libraries(${EXECUTABLE} boost_filesystem-mt) -elseif (UNIX) - find_package(Boost 1.53 REQUIRED COMPONENTS filesystem) - target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARY}) -endif () install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libp2p/CMakeLists.txt b/libp2p/CMakeLists.txt index bae400caf..fa7ff6a54 100644 --- a/libp2p/CMakeLists.txt +++ b/libp2p/CMakeLists.txt @@ -5,6 +5,9 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) +include_directories(..) +include_directories(${LEVELDB_INCLUDE_DIR}) + set(EXECUTABLE p2p) file(GLOB HEADERS "*.h") @@ -14,50 +17,14 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -include_directories(..) -include_directories(${LEVELDB_INCLUDE_DIR}) - -target_link_libraries(${EXECUTABLE} devcrypto) -target_link_libraries(${EXECUTABLE} devcore) -target_link_libraries(${EXECUTABLE} secp256k1) +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() -target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) -target_link_libraries(${EXECUTABLE} gmp) -if("${TARGET_PLATFORM}" STREQUAL "w64") - target_link_libraries(${EXECUTABLE} boost_system-mt-s) - target_link_libraries(${EXECUTABLE} boost_regex-mt-s) - target_link_libraries(${EXECUTABLE} boost_filesystem-mt-s) - target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) - target_link_libraries(${EXECUTABLE} iphlpapi) - target_link_libraries(${EXECUTABLE} ws2_32) - target_link_libraries(${EXECUTABLE} mswsock) - target_link_libraries(${EXECUTABLE} shlwapi) -elseif (APPLE) - # Latest mavericks boost libraries only come with -mt - target_link_libraries(${EXECUTABLE} boost_system-mt) - target_link_libraries(${EXECUTABLE} boost_regex-mt) - target_link_libraries(${EXECUTABLE} boost_filesystem-mt) - target_link_libraries(${EXECUTABLE} boost_thread-mt) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -elseif (UNIX) - target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -else () - target_link_libraries(${EXECUTABLE} boost_system) - target_link_libraries(${EXECUTABLE} boost_regex) - target_link_libraries(${EXECUTABLE} boost_filesystem) - target_link_libraries(${EXECUTABLE} boost_thread) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -endif () +target_link_libraries(${EXECUTABLE} devcrypto) +target_link_libraries(${EXECUTABLE} devcore) +target_link_libraries(${EXECUTABLE} secp256k1) install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/sc/CMakeLists.txt b/sc/CMakeLists.txt index d977ee967..2adde060e 100644 --- a/sc/CMakeLists.txt +++ b/sc/CMakeLists.txt @@ -13,21 +13,5 @@ target_link_libraries(${EXECUTABLE} lll) target_link_libraries(${EXECUTABLE} evmcore) target_link_libraries(${EXECUTABLE} devcore) -if ("${TARGET_PLATFORM}" STREQUAL "w64") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") - target_link_libraries(${EXECUTABLE} gcc) - target_link_libraries(${EXECUTABLE} gdi32) - target_link_libraries(${EXECUTABLE} ws2_32) - target_link_libraries(${EXECUTABLE} mswsock) - target_link_libraries(${EXECUTABLE} shlwapi) - target_link_libraries(${EXECUTABLE} iphlpapi) - target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) - set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) -elseif (UNIX) -else () - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -endif () - install( TARGETS ${EXECUTABLE} DESTINATION bin ) From b4251aac130785f0a9793d8fe2ea409207e12927 Mon Sep 17 00:00:00 2001 From: debris Date: Sun, 7 Dec 2014 22:21:45 +0100 Subject: [PATCH 432/641] evm && ethcore working on windows --- libethcore/CMakeLists.txt | 10 +--------- libevm/CMakeLists.txt | 24 ++++-------------------- 2 files changed, 5 insertions(+), 29 deletions(-) diff --git a/libethcore/CMakeLists.txt b/libethcore/CMakeLists.txt index 99ae26776..869b6092b 100644 --- a/libethcore/CMakeLists.txt +++ b/libethcore/CMakeLists.txt @@ -14,21 +14,13 @@ file(GLOB HEADERS "*.h") if(ETH_STATIC) add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) + add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} secp256k1) -target_link_libraries(${EXECUTABLE} gmp) - -if (APPLE) - target_link_libraries(${EXECUTABLE} boost_system-mt) -elseif (UNIX) - find_package(Boost 1.53 REQUIRED COMPONENTS system) - target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARY}) -endif() install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libevm/CMakeLists.txt b/libevm/CMakeLists.txt index 8815d123c..778bce8d9 100644 --- a/libevm/CMakeLists.txt +++ b/libevm/CMakeLists.txt @@ -5,6 +5,9 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) +include_directories(..) +include_directories(${LEVELDB_INCLUDE_DIR}) + set(EXECUTABLE evm) file(GLOB HEADERS "*.h") @@ -14,36 +17,17 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -include_directories(${LEVELDB_INCLUDE_DIR}) -include_directories(..) +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() -target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) - target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} evmcore) target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} secp256k1) -target_link_libraries(${EXECUTABLE} gmp) - -if (APPLE) - # Latest mavericks boost libraries only come with -mt - target_link_libraries(${EXECUTABLE} boost_system-mt) - target_link_libraries(${EXECUTABLE} boost_filesystem-mt) - target_link_libraries(${EXECUTABLE} boost_thread-mt) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -elseif (UNIX) - target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -endif () install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) From f2a6a21ccab2558f1d35953e969ba28698c77ac2 Mon Sep 17 00:00:00 2001 From: debris Date: Sun, 7 Dec 2014 22:39:01 +0100 Subject: [PATCH 433/641] whisper && webthree working on windows --- libwebthree/CMakeLists.txt | 50 +++++++------------------------------- libwhisper/CMakeLists.txt | 49 ++++++------------------------------- libwhisper/_libwhisper.cpp | 8 ------ 3 files changed, 17 insertions(+), 90 deletions(-) delete mode 100644 libwhisper/_libwhisper.cpp diff --git a/libwebthree/CMakeLists.txt b/libwebthree/CMakeLists.txt index dc623a2fa..2e305a5be 100644 --- a/libwebthree/CMakeLists.txt +++ b/libwebthree/CMakeLists.txt @@ -1,10 +1,13 @@ -cmake_policy(SET CMP0015 NEW) +cmake_policy(SET CMP0015 OLD) set(CMAKE_AUTOMOC OFF) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) +include_directories(${LEVELDB_INCLUDE_DIR}) +include_directories(..) + set(EXECUTABLE webthree) file(GLOB HEADERS "*.h") @@ -14,8 +17,11 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -include_directories(..) -include_directories(${LEVELDB_INCLUDE_DIR}) +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) + +if(MINIUPNPC_LS) +target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) +endif() target_link_libraries(${EXECUTABLE} ethereum) target_link_libraries(${EXECUTABLE} evm) @@ -25,44 +31,6 @@ target_link_libraries(${EXECUTABLE} p2p) target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} secp256k1) -if(MINIUPNPC_LS) -target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) -endif() -target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) -target_link_libraries(${EXECUTABLE} gmp) - -if("${TARGET_PLATFORM}" STREQUAL "w64") - target_link_libraries(${EXECUTABLE} boost_system-mt-s) - target_link_libraries(${EXECUTABLE} boost_regex-mt-s) - target_link_libraries(${EXECUTABLE} boost_filesystem-mt-s) - target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) - target_link_libraries(${EXECUTABLE} iphlpapi) - target_link_libraries(${EXECUTABLE} ws2_32) - target_link_libraries(${EXECUTABLE} mswsock) - target_link_libraries(${EXECUTABLE} shlwapi) -elseif (APPLE) - # Latest mavericks boost libraries only come with -mt - target_link_libraries(${EXECUTABLE} boost_system-mt) - target_link_libraries(${EXECUTABLE} boost_regex-mt) - target_link_libraries(${EXECUTABLE} boost_filesystem-mt) - target_link_libraries(${EXECUTABLE} boost_thread-mt) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -elseif (UNIX) - target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -else () - target_link_libraries(${EXECUTABLE} boost_system) - target_link_libraries(${EXECUTABLE} boost_regex) - target_link_libraries(${EXECUTABLE} boost_filesystem) - target_link_libraries(${EXECUTABLE} boost_thread) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -endif () install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libwhisper/CMakeLists.txt b/libwhisper/CMakeLists.txt index 080c24c05..51908ffcf 100644 --- a/libwhisper/CMakeLists.txt +++ b/libwhisper/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_policy(SET CMP0015 NEW) +cmake_policy(SET CMP0015 OLD) set(CMAKE_AUTOMOC OFF) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") @@ -17,50 +17,17 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) + +if(MINIUPNPC_LS) +target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) +endif() + target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} p2p) target_link_libraries(${EXECUTABLE} secp256k1) -if(MINIUPNPC_LS) -target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) -endif() -target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) -target_link_libraries(${EXECUTABLE} gmp) - -if("${TARGET_PLATFORM}" STREQUAL "w64") - target_link_libraries(${EXECUTABLE} boost_system-mt-s) - target_link_libraries(${EXECUTABLE} boost_regex-mt-s) - target_link_libraries(${EXECUTABLE} boost_filesystem-mt-s) - target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) - target_link_libraries(${EXECUTABLE} iphlpapi) - target_link_libraries(${EXECUTABLE} ws2_32) - target_link_libraries(${EXECUTABLE} mswsock) - target_link_libraries(${EXECUTABLE} shlwapi) -elseif (APPLE) - # Latest mavericks boost libraries only come with -mt - target_link_libraries(${EXECUTABLE} boost_system-mt) - target_link_libraries(${EXECUTABLE} boost_regex-mt) - target_link_libraries(${EXECUTABLE} boost_filesystem-mt) - target_link_libraries(${EXECUTABLE} boost_thread-mt) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -elseif (UNIX) - target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -else () - target_link_libraries(${EXECUTABLE} boost_system) - target_link_libraries(${EXECUTABLE} boost_regex) - target_link_libraries(${EXECUTABLE} boost_filesystem) - target_link_libraries(${EXECUTABLE} boost_thread) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -endif () install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) -install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) - +install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) \ No newline at end of file diff --git a/libwhisper/_libwhisper.cpp b/libwhisper/_libwhisper.cpp deleted file mode 100644 index 813c6a657..000000000 --- a/libwhisper/_libwhisper.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#ifdef _MSC_VER -#include "All.h" -#include "Common.cpp" -#include "WhisperPeer.cpp" -#include "WhisperHost.cpp" -#include "Message.cpp" -#include "Interface.cpp" -#endif From 6f24e77588b9b7252136143a1f28c26ceed6cacf Mon Sep 17 00:00:00 2001 From: debris Date: Mon, 8 Dec 2014 11:17:38 +0100 Subject: [PATCH 434/641] web3jsonrpc, ethereum, qethereum, mix compiling on windows --- eth/CMakeLists.txt | 28 ++++----------------- eth/main.cpp | 3 +-- libethereum/CMakeLists.txt | 18 -------------- libweb3jsonrpc/CMakeLists.txt | 3 +-- libweb3jsonrpc/WebThreeStubServer.cpp | 6 ++--- mix/CMakeLists.txt | 36 ++++----------------------- 6 files changed, 15 insertions(+), 79 deletions(-) diff --git a/eth/CMakeLists.txt b/eth/CMakeLists.txt index 2b88efbc2..575c045d8 100644 --- a/eth/CMakeLists.txt +++ b/eth/CMakeLists.txt @@ -4,7 +4,6 @@ set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) -include_directories(${LEVELDB_INCLUDE_DIR}) include_directories(..) set(EXECUTABLE eth) @@ -12,7 +11,11 @@ set(EXECUTABLE eth) file(GLOB HEADERS "*.h") add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) -target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) + +add_dependencies(${EXECUTABLE} BuildInfo.h) + +target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARY_RELEASE}) +target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARY_RELEASE}) if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) @@ -28,27 +31,6 @@ endif() target_link_libraries(${EXECUTABLE} webthree) target_link_libraries(${EXECUTABLE} secp256k1) -target_link_libraries(${EXECUTABLE} gmp) - -if ("${TARGET_PLATFORM}" STREQUAL "w64") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") - target_link_libraries(${EXECUTABLE} boost_system-mt-s) - target_link_libraries(${EXECUTABLE} boost_filesystem-mt-s) - target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) - target_link_libraries(${EXECUTABLE} gcc) - target_link_libraries(${EXECUTABLE} gdi32) - target_link_libraries(${EXECUTABLE} ws2_32) - target_link_libraries(${EXECUTABLE} mswsock) - target_link_libraries(${EXECUTABLE} shlwapi) - target_link_libraries(${EXECUTABLE} iphlpapi) - set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) -elseif (UNIX) -else () - #target_link_libraries(${EXECUTABLE} boost_system) - #target_link_libraries(${EXECUTABLE} boost_filesystem) - #find_package(Threads REQUIRED) - #target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -endif () install( TARGETS ${EXECUTABLE} DESTINATION bin ) diff --git a/eth/main.cpp b/eth/main.cpp index abfc1bfa0..8c370fcef 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -427,8 +427,7 @@ int main(int argc, char** argv) { if (jsonrpc < 0) jsonrpc = 8080; - - jsonrpcConnector = unique_ptr(new jsonrpc::CorsHttpServer(jsonrpc)); + jsonrpcConnector = unique_ptr(new jsonrpc::HttpServer(jsonrpc)); jsonrpcServer = shared_ptr(new WebThreeStubServer(*jsonrpcConnector.get(), web3, vector({us}))); jsonrpcServer->setIdentities({us}); jsonrpcServer->StartListening(); diff --git a/libethereum/CMakeLists.txt b/libethereum/CMakeLists.txt index ce1b830f5..de750fdb8 100644 --- a/libethereum/CMakeLists.txt +++ b/libethereum/CMakeLists.txt @@ -31,24 +31,6 @@ target_link_libraries(${EXECUTABLE} p2p) target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} secp256k1) -target_link_libraries(${EXECUTABLE} gmp) - -if (APPLE) - # Latest mavericks boost libraries only come with -mt - target_link_libraries(${EXECUTABLE} boost_system-mt) - target_link_libraries(${EXECUTABLE} boost_regex-mt) - target_link_libraries(${EXECUTABLE} boost_filesystem-mt) - target_link_libraries(${EXECUTABLE} boost_thread-mt) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -elseif (UNIX) - target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -endif () install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libweb3jsonrpc/CMakeLists.txt b/libweb3jsonrpc/CMakeLists.txt index fcc9f0ee9..9925b9026 100644 --- a/libweb3jsonrpc/CMakeLists.txt +++ b/libweb3jsonrpc/CMakeLists.txt @@ -3,9 +3,9 @@ set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) +include_directories(..) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) include_directories(${LEVELDB_INCLUDE_DIR}) -include_directories(..) set(EXECUTABLE web3jsonrpc) @@ -28,7 +28,6 @@ endif() target_link_libraries(${EXECUTABLE} webthree) target_link_libraries(${EXECUTABLE} secp256k1) -target_link_libraries(${EXECUTABLE} gmp) target_link_libraries(${EXECUTABLE} solidity) target_link_libraries(${EXECUTABLE} serpent) diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index 1247c5143..c777ab66a 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -21,6 +21,9 @@ * @date 2014 */ +#include +#include +#include #include "WebThreeStubServer.h" #include #include @@ -31,9 +34,6 @@ #include #include #include -#include -#include -#include #include using namespace std; diff --git a/mix/CMakeLists.txt b/mix/CMakeLists.txt index 0252b5226..c08e1cbd2 100644 --- a/mix/CMakeLists.txt +++ b/mix/CMakeLists.txt @@ -2,27 +2,6 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) aux_source_directory(. SRC_LIST) include_directories(..) - -if (APPLE) - # Add homebrew path for qt5 - set(CMAKE_PREFIX_PATH /usr/local/opt/qt5) - include_directories(/usr/local/opt/qt5/include /usr/local/include) -elseif ("${TARGET_PLATFORM}" STREQUAL "w64") - set(SRC_LIST ${SRC_LIST} ../windows/qt_plugin_import.cpp) - include_directories(/usr/x86_64-w64-mingw32/include /usr/x86_64-w64-mingw32/include/QtCore /usr/x86_64-w64-mingw32/include/QtGui /usr/x86_64-w64-mingw32/include/QtQuick /usr/x86_64-w64-mingw32/include/QtQml /usr/x86_64-w64-mingw32/include/QtNetwork /usr/x86_64-w64-mingw32/include/QtWidgets /usr/x86_64-w64-mingw32/include/QtWebKit /usr/x86_64-w64-mingw32/include/QtWebKitWidgets) -elseif (UNIX) - set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ";$ENV{QTDIR}/lib/cmake") -endif () - -find_package(Qt5Core REQUIRED) -find_package(Qt5Gui REQUIRED) -find_package(Qt5Quick REQUIRED) -find_package(Qt5Qml REQUIRED) -find_package(Qt5Network REQUIRED) -find_package(Qt5Widgets REQUIRED) -find_package(Qt5WebKit REQUIRED) -find_package(Qt5WebKitWidgets REQUIRED) - #qt5_wrap_ui(ui_Main.h Main.ui) qt5_add_resources(UI_RESOURCES qml.qrc) @@ -55,8 +34,10 @@ else () add_executable(${EXECUTEABLE} ${SRC_LIST} ${HEADERS} ${UI_RESOURCES}) endif () -qt5_use_modules(${EXECUTEABLE} Core)# Gui Widgets Network WebKit WebKitWidgets) -target_link_libraries(${EXECUTEABLE} webthree qethereum ethereum evm ethcore devcrypto secp256k1 gmp ${CRYPTOPP_LS} serpent lll solidity evmcore devcore web3jsonrpc jsqrc) +#qt5_use_modules(${EXECUTEABLE} Core Gui Widgets Network WebKit WebKitWidgets) +target_link_libraries(${EXECUTEABLE} Qt5::Core) +target_link_libraries(${EXECUTEABLE} Qt5::Gui) +target_link_libraries(${EXECUTEABLE} webthree qethereum ethereum evm ethcore devcrypto secp256k1 ${CRYPTOPP_LS} serpent lll solidity evmcore devcore web3jsonrpc jsqrc) if (APPLE) # First have qt5 install plugins and frameworks @@ -82,13 +63,6 @@ if (APPLE) file(REMOVE \${LINGER_RM}) endif () ") -elseif (UNIX) -else () - target_link_libraries(${EXECUTEABLE} boost_system) - target_link_libraries(${EXECUTEABLE} boost_filesystem) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTEABLE} ${CMAKE_THREAD_LIBS_INIT}) +else() install( TARGETS ${EXECUTEABLE} RUNTIME DESTINATION bin ) endif () - -qt5_use_modules(${EXECUTEABLE} Core Gui) From ad2b462b5db02d5d91e35ca5e3cee5ad3ec027ba Mon Sep 17 00:00:00 2001 From: debris Date: Mon, 8 Dec 2014 12:23:10 +0100 Subject: [PATCH 435/641] common improvements --- alethzero/CMakeLists.txt | 17 ++--------------- cmake/EthDependencies.cmake | 3 ++- libsolidity/Token.h | 3 +++ mix/CMakeLists.txt | 4 ++-- 4 files changed, 9 insertions(+), 18 deletions(-) diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index 5b6c5c3c4..a1177a0a3 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_policy(SET CMP0015 NEW) +cmake_policy(SET CMP0015 OLD) set(CMAKE_INCLUDE_CURRENT_DIR ON) aux_source_directory(. SRC_LIST) @@ -46,7 +46,6 @@ target_link_libraries(${EXECUTABLE} evm) target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} secp256k1) -target_link_libraries(${EXECUTABLE} gmp) target_link_libraries(${EXECUTABLE} serpent) target_link_libraries(${EXECUTABLE} lll) target_link_libraries(${EXECUTABLE} solidity) @@ -80,19 +79,7 @@ if (APPLE) file(REMOVE \${LINGER_RM}) endif () ") -elseif ("${TARGET_PLATFORM}" STREQUAL "w64") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-keep-inline-dllexport -static-libgcc -static-libstdc++ -static") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-s -Wl,-subsystem,windows -mthreads -L/usr/x86_64-w64-mingw32/plugins/platforms") - target_link_libraries(${EXECUTABLE} gcc) - target_link_libraries(${EXECUTABLE} mingw32 qtmain mswsock iphlpapi qwindows shlwapi Qt5PlatformSupport opengl32 gdi32 comdlg32 oleaut32 imm32 winmm ole32 uuid ws2_32) - target_link_libraries(${EXECUTABLE} boost_system-mt-s) - target_link_libraries(${EXECUTABLE} boost_filesystem-mt-s) - target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) - target_link_libraries(${EXECUTABLE} crypt32) - target_link_libraries(${EXECUTABLE} Qt5PlatformSupport) - set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) -elseif (UNIX) else () - message(ERROR "platform not supported") + install( TARGETS ${EXECUTEABLE} RUNTIME DESTINATION bin) endif () diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index fb367ef7b..d7542e364 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -4,7 +4,8 @@ # by defining this variable, cmake will look for dependencies first in our own repository before looking in system paths like /usr/local/ ... # this must be set to point to the same directory as $ETH_DEPENDENCY_INSTALL_DIR in /extdep directory string(TOLOWER ${CMAKE_SYSTEM_NAME} _system_name) -set (CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}/extdep/install/${_system_name}") +set (CMAKE_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/extdep/install/${_system_name}") +set (CMAKE_PREFIX_PATH ${CMAKE_DEPENDENCY_INSTALL_DIR}) if (WIN32) set (CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "C:/Program Files/Windows Kits/8.1/Lib/winv6.3/um/x86") #set (CMAKE_PREFIX_PATH "C:/Program Files/Windows Kits/8.1/Lib/winv6.3/um/x64") diff --git a/libsolidity/Token.h b/libsolidity/Token.h index f1a94af35..eb9b4d426 100644 --- a/libsolidity/Token.h +++ b/libsolidity/Token.h @@ -296,6 +296,9 @@ class Token { public: // All token values. + // attention! msvc issue: + // http://stackoverflow.com/questions/9567868/compile-errors-after-adding-v8-to-my-project-c2143-c2059 + // @todo: avoid TOKEN_LIST macro #define T(name, string, precedence) name, enum Value { diff --git a/mix/CMakeLists.txt b/mix/CMakeLists.txt index c08e1cbd2..aa1f8cc02 100644 --- a/mix/CMakeLists.txt +++ b/mix/CMakeLists.txt @@ -31,7 +31,7 @@ if (APPLE) else () set(EXECUTEABLE mix) - add_executable(${EXECUTEABLE} ${SRC_LIST} ${HEADERS} ${UI_RESOURCES}) + add_executable(${EXECUTEABLE} ${SRC_LIST} ${HEADERS} ${UI_RESOURCES}) endif () #qt5_use_modules(${EXECUTEABLE} Core Gui Widgets Network WebKit WebKitWidgets) @@ -64,5 +64,5 @@ if (APPLE) endif () ") else() - install( TARGETS ${EXECUTEABLE} RUNTIME DESTINATION bin ) + install( TARGETS ${EXECUTEABLE} RUNTIME DESTINATION bin) endif () From de72fa0edd2ed8a6bbbf283607014244adcc4138 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 8 Dec 2014 13:45:57 +0100 Subject: [PATCH 436/641] - fromRaw, fromString, prettyU256 moved to CommonJS.cpp. - ApplicationCtx => AppContext. - Smart pointer direct method call (instead of calling get() before). - ConstantCompilationModel instanciate as smart pointer. - Bug fix https://github.com/ethereum/cpp-ethereum/issues/557 - Add comments on DebuggingStateWrapper - Coding Standards --- alethzero/MainWin.cpp | 16 ++--- alethzero/MainWin.h | 8 ++- libdevcore/CommonJS.cpp | 70 ++++++++++++++++++++++ libdevcore/CommonJS.h | 7 ++- mix/{ApplicationCtx.cpp => AppContext.cpp} | 32 +++++----- mix/{ApplicationCtx.h => AppContext.h} | 17 +++--- mix/AssemblyDebuggerCtrl.cpp | 15 ++--- mix/AssemblyDebuggerModel.cpp | 8 +-- mix/CodeEditorExtensionManager.cpp | 10 ++-- mix/ConstantCompilationCtrl.cpp | 7 +-- mix/ConstantCompilationCtrl.h | 4 +- mix/ConstantCompilationModel.cpp | 4 +- mix/ConstantCompilationModel.h | 4 +- mix/DebuggingStateWrapper.cpp | 62 ++----------------- mix/DebuggingStateWrapper.h | 23 ++++--- mix/Extension.cpp | 8 +-- mix/TransactionBuilder.cpp | 58 +----------------- mix/TransactionBuilder.h | 36 +++++------ mix/main.cpp | 8 +-- 19 files changed, 183 insertions(+), 214 deletions(-) rename mix/{ApplicationCtx.cpp => AppContext.cpp} (73%) rename mix/{ApplicationCtx.h => AppContext.h} (80%) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 4a32f66b2..0fe55d320 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -64,7 +64,7 @@ static void initUnits(QComboBox* _b) _b->addItem(QString::fromStdString(units()[n].second), n); } -static QString fromRaw(dev::h256 _n, unsigned* _inc = nullptr) +QString Main::fromRaw(dev::h256 _n, unsigned* _inc) { if (_n) { @@ -148,7 +148,7 @@ Main::Main(QWidget *parent) : statusBar()->addPermanentWidget(ui->peerCount); statusBar()->addPermanentWidget(ui->mineStatus); statusBar()->addPermanentWidget(ui->blockCount); - + connect(ui->ourAccounts->model(), SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)), SLOT(ourAccountsRowsMoved())); m_webThree.reset(new WebThreeDirect(string("AlethZero/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir() + "/AlethZero", false, {"eth", "shh"})); @@ -173,17 +173,17 @@ Main::Main(QWidget *parent) : connect(f, &QWebFrame::javaScriptWindowObjectCleared, QETH_INSTALL_JS_NAMESPACE(f, this, qweb)); connect(m_qweb, SIGNAL(onNewId(QString)), this, SLOT(addNewId(QString))); }); - + connect(ui->webView, &QWebView::loadFinished, [=]() { m_qweb->poll(); }); - + connect(ui->webView, &QWebView::titleChanged, [=]() { ui->tabWidget->setTabText(0, ui->webView->title()); }); - + readSettings(); installWatches(); startTimer(100); @@ -1067,7 +1067,7 @@ void Main::timerEvent(QTimerEvent*) // 7/18, Alex: aggregating timers, prelude to better threading? // Runs much faster on slower dual-core processors static int interval = 100; - + // refresh mining every 200ms if (interval / 100 % 2 == 0) refreshMining(); @@ -1093,7 +1093,7 @@ void Main::timerEvent(QTimerEvent*) } else interval += 100; - + if (m_qweb) m_qweb->poll(); @@ -1759,7 +1759,7 @@ void Main::on_net_triggered() { ui->port->setEnabled(!ui->net->isChecked()); ui->clientName->setEnabled(!ui->net->isChecked()); - string n = string("AlethZero/v") + dev::Version; + string n = string("AlethZero/v") + dev::Version; if (ui->clientName->text().size()) n += "/" + ui->clientName->text().toStdString(); n += "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM); diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index 50b9df413..e4b40dd81 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -69,7 +69,7 @@ struct WorldState class Main : public QMainWindow { Q_OBJECT - + public: explicit Main(QWidget *parent = 0); ~Main(); @@ -79,7 +79,7 @@ public: std::shared_ptr whisper() const { return m_webThree->whisper(); } QList owned() const { return m_myIdentities + m_myKeys; } - + public slots: void load(QString _file); void note(QString _entry); @@ -146,7 +146,7 @@ private slots: void on_debugDumpState_triggered(int _add = 1); void on_debugDumpStatePre_triggered(); void on_refresh_triggered(); - void on_usePrivate_triggered(); + void on_usePrivate_triggered(); void on_enableOptimizer_triggered(); void on_turboMining_triggered(); void on_go_triggered(); @@ -259,4 +259,6 @@ private: QWebThreeConnector* m_qwebConnector; std::unique_ptr m_server; QWebThree* m_qweb = nullptr; + + static QString fromRaw(dev::h256 _n, unsigned* _inc = nullptr); }; diff --git a/libdevcore/CommonJS.cpp b/libdevcore/CommonJS.cpp index c09a5b565..800bd06c8 100644 --- a/libdevcore/CommonJS.cpp +++ b/libdevcore/CommonJS.cpp @@ -54,4 +54,74 @@ bytes unpadded(bytes _b) return _b; } +std::string prettyU256(u256 _n) +{ + unsigned inc = 0; + std::string raw; + std::ostringstream s; + if (!(_n >> 64)) + s << " " << (uint64_t)_n << " (0x" << (uint64_t)_n << ")"; + else if (!~(_n >> 64)) + s << " " << (int64_t)_n << " (0x" << (int64_t)_n << ")"; + else if ((_n >> 160) == 0) + { + Address a = right160(_n); + + std::string n = a.abridged(); + if (n.empty()) + s << "0x" << a; + else + s << n << "(0x" << a.abridged() << ")"; + } + else if ((raw = fromRaw((h256)_n, &inc)).size()) + return "\"" + raw + "\"" + (inc ? " + " + std::to_string(inc) : ""); + else + s << "" << (h256)_n; + return s.str(); +} + +std::string fromRaw(h256 _n, unsigned* _inc) +{ + if (_n) + { + std::string s((char const*)_n.data(), 32); + auto l = s.find_first_of('\0'); + if (!l) + return NULL; + if (l != std::string::npos) + { + auto p = s.find_first_not_of('\0', l); + if (!(p == std::string::npos || (_inc && p == 31))) + return NULL; + if (_inc) + *_inc = (byte)s[31]; + s.resize(l); + } + for (auto i: s) + if (i < 32) + return NULL; + return s; + } + return NULL; +} + +Address fromString(std::string _sn) +{ + if (_sn.size() > 32) + _sn.resize(32); + h256 n; + memcpy(n.data(), _sn.data(), _sn.size()); + memset(n.data() + _sn.size(), 0, 32 - _sn.size()); + if (_sn.size() == 40) + return Address(fromHex(_sn)); + else + return Address(); + //we try to resolve the recipient adress using nameReg contract state + /*const Address c_config = Address("661005d2720d855f1d9976f88bb10c1a3398c77f"); //NameReg contract + if (h160 nameReg = (u160)ethClient->stateAt(c_config, 0)) + if (h256 a = ethClient->stateAt(nameReg, n)) + return right160(a);*/ +} + + } diff --git a/libdevcore/CommonJS.h b/libdevcore/CommonJS.h index 80e1a9ca1..0fb087f72 100644 --- a/libdevcore/CommonJS.h +++ b/libdevcore/CommonJS.h @@ -35,12 +35,12 @@ template std::string toJS(FixedHash const& _h) { return "0x" + toHex(_h.ref()); } - + template std::string toJS(boost::multiprecision::number> const& _n) { return "0x" + toHex(toCompactBigEndian(_n)); } - + inline std::string toJS(dev::bytes const& _n) { return "0x" + dev::toHex(_n); @@ -49,6 +49,9 @@ inline std::string toJS(dev::bytes const& _n) bytes jsToBytes(std::string const& _s); bytes padded(bytes _b, unsigned _l); bytes unpadded(bytes _s); +std::string prettyU256(u256 _n); +std::string fromRaw(h256 _n, unsigned* _inc = nullptr); +Address fromString(std::string _a); template FixedHash jsToFixed(std::string const& _s) { diff --git a/mix/ApplicationCtx.cpp b/mix/AppContext.cpp similarity index 73% rename from mix/ApplicationCtx.cpp rename to mix/AppContext.cpp index 0130f2dfb..5b8b76139 100644 --- a/mix/ApplicationCtx.cpp +++ b/mix/AppContext.cpp @@ -11,12 +11,12 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file ApplicationCtx.cpp +/** @file AppContext.cpp * @author Yann yann@ethdev.com * @date 2014 - * Provides an access to the current QQmlApplicationEngine which is used to add QML file on the fly. + * Provides access to the current QQmlApplicationEngine which is used to add QML file on the fly. * In the future this class can be extended to add more variable related to the context of the application. - * For now ApplicationCtx provides reference to: + * For now AppContext provides reference to: * - QQmlApplicationEngine * - dev::WebThreeDirect (and dev::eth::Client) * - KeyEventManager @@ -28,58 +28,56 @@ #include #include "libdevcrypto/FileSystem.h" #include "KeyEventManager.h" -#include "ApplicationCtx.h" +#include "AppContext.h" using namespace dev; using namespace dev::mix; using namespace dev::eth; -ApplicationCtx* ApplicationCtx::Instance = nullptr; +AppContext* AppContext::Instance = nullptr; -ApplicationCtx::ApplicationCtx(QQmlApplicationEngine* _engine) +AppContext::AppContext(QQmlApplicationEngine* _engine) { m_applicationEngine = std::unique_ptr(_engine); m_keyEventManager = std::unique_ptr(new KeyEventManager()); m_webThree = std::unique_ptr(new WebThreeDirect(std::string("Mix/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir() + "/Mix", false, {"eth", "shh"})); } -QQmlApplicationEngine* ApplicationCtx::appEngine() +QQmlApplicationEngine* AppContext::appEngine() { return m_applicationEngine.get(); } -dev::eth::Client* ApplicationCtx::getEthereumClient() +dev::eth::Client* AppContext::getEthereumClient() { - return m_webThree.get()->ethereum(); + return m_webThree->ethereum(); } -void ApplicationCtx::initKeyEventManager() +void AppContext::initKeyEventManager() { QObject* mainContent = m_applicationEngine->rootObjects().at(0)->findChild("mainContent", Qt::FindChildrenRecursively); if (mainContent) - { QObject::connect(mainContent, SIGNAL(keyPressed(QVariant)), m_keyEventManager.get(), SLOT(keyPressed(QVariant))); - } else qDebug() << "Unable to find QObject of mainContent.qml. KeyEvent will not be handled!"; } -KeyEventManager* ApplicationCtx::getKeyEventManager() +KeyEventManager* AppContext::getKeyEventManager() { return m_keyEventManager.get(); } -void ApplicationCtx::setApplicationContext(QQmlApplicationEngine* _engine) +void AppContext::setApplicationContext(QQmlApplicationEngine* _engine) { if (Instance == nullptr) - Instance = new ApplicationCtx(_engine); + Instance = new AppContext(_engine); } -void ApplicationCtx::displayMessageDialog(QString _title, QString _message) +void AppContext::displayMessageDialog(QString _title, QString _message) { QQmlComponent component(m_applicationEngine.get(), QUrl("qrc:/qml/BasicMessage.qml")); QObject* dialog = component.create(); dialog->findChild("messageContent", Qt::FindChildrenRecursively)->setProperty("text", _message); - QObject* dialogWin = ApplicationCtx::getInstance()->appEngine()->rootObjects().at(0)->findChild("messageDialog", Qt::FindChildrenRecursively); + QObject* dialogWin = AppContext::getInstance()->appEngine()->rootObjects().at(0)->findChild("messageDialog", Qt::FindChildrenRecursively); QMetaObject::invokeMethod(dialogWin, "close"); dialogWin->setProperty("contentItem", QVariant::fromValue(dialog)); dialogWin->setProperty("title", _title); diff --git a/mix/ApplicationCtx.h b/mix/AppContext.h similarity index 80% rename from mix/ApplicationCtx.h rename to mix/AppContext.h index 5680c860e..da7bf9a8d 100644 --- a/mix/ApplicationCtx.h +++ b/mix/AppContext.h @@ -14,11 +14,12 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file ApplicationCtx.h +/** @file AppContext.h * @author Yann yann@ethdev.com - * Provides an access to the current QQmlApplicationEngine which is used to add QML file on the fly. + * @date 2014 + * Provides access to the current QQmlApplicationEngine which is used to add QML file on the fly. * In the future this class can be extended to add more variable related to the context of the application. - * For now ApplicationCtx provides reference to: + * For now AppContext provides reference to: * - QQmlApplicationEngine * - dev::WebThreeDirect (and dev::eth::Client) * - KeyEventManager @@ -36,14 +37,14 @@ namespace dev namespace mix { -class ApplicationCtx: public QObject +class AppContext: public QObject { Q_OBJECT public: - ApplicationCtx(QQmlApplicationEngine* _engine); - ~ApplicationCtx() {} - static ApplicationCtx* getInstance() { return Instance; } + AppContext(QQmlApplicationEngine* _engine); + ~AppContext() {} + static AppContext* getInstance() { return Instance; } static void setApplicationContext(QQmlApplicationEngine* _engine); QQmlApplicationEngine* appEngine(); dev::eth::Client* getEthereumClient(); @@ -52,7 +53,7 @@ public: void displayMessageDialog(QString _title, QString _message); private: - static ApplicationCtx* Instance; + static AppContext* Instance; std::unique_ptr m_applicationEngine; std::unique_ptr m_webThree; std::unique_ptr m_keyEventManager; diff --git a/mix/AssemblyDebuggerCtrl.cpp b/mix/AssemblyDebuggerCtrl.cpp index 94d8bf6cb..6e2b11e70 100644 --- a/mix/AssemblyDebuggerCtrl.cpp +++ b/mix/AssemblyDebuggerCtrl.cpp @@ -25,7 +25,7 @@ #include "AssemblyDebuggerCtrl.h" #include "TransactionBuilder.h" #include "KeyEventManager.h" -#include "ApplicationCtx.h" +#include "AppContext.h" #include "DebuggingStateWrapper.h" using namespace dev::mix; @@ -48,16 +48,17 @@ QString AssemblyDebuggerCtrl::title() const void AssemblyDebuggerCtrl::start() const { //start to listen on F5 - ApplicationCtx::getInstance()->getKeyEventManager()->registerEvent(this, SLOT(keyPressed(int))); + AppContext::getInstance()->getKeyEventManager()->registerEvent(this, SLOT(keyPressed(int))); } void AssemblyDebuggerCtrl::keyPressed(int _key) { + if (_key == Qt::Key_F5) { if (!m_modelDebugger->compile(m_doc->toPlainText())) { - ApplicationCtx::getInstance()->displayMessageDialog("debugger","compilation failed"); + AppContext::getInstance()->displayMessageDialog("debugger","compilation failed"); return; } @@ -71,14 +72,14 @@ void AssemblyDebuggerCtrl::keyPressed(int _key) QList wStates; for(int i = 0; i < debuggingContent.states.size(); i++) { - DebuggingStateWrapper* s = new DebuggingStateWrapper(debuggingContent.executionCode, debuggingContent.executionData.toBytes()); + DebuggingStateWrapper* s = new DebuggingStateWrapper(debuggingContent.executionCode, debuggingContent.executionData.toBytes(), this); s->setState(debuggingContent.states.at(i)); wStates.append(s); } std::tuple, QQMLMap*> code = DebuggingStateWrapper::getHumanReadableCode(debuggingContent.executionCode, this); - ApplicationCtx::getInstance()->appEngine()->rootContext()->setContextProperty("debugStates", QVariant::fromValue(wStates)); - ApplicationCtx::getInstance()->appEngine()->rootContext()->setContextProperty("humanReadableExecutionCode", QVariant::fromValue(std::get<0>(code))); - ApplicationCtx::getInstance()->appEngine()->rootContext()->setContextProperty("bytesCodeMapping", QVariant::fromValue(std::get<1>(code))); + AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("debugStates", QVariant::fromValue(wStates)); + AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("humanReadableExecutionCode", QVariant::fromValue(std::get<0>(code))); + AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("bytesCodeMapping", QVariant::fromValue(std::get<1>(code))); this->addContentOn(this); }; } diff --git a/mix/AssemblyDebuggerModel.cpp b/mix/AssemblyDebuggerModel.cpp index e4c2396ca..aa9795d53 100644 --- a/mix/AssemblyDebuggerModel.cpp +++ b/mix/AssemblyDebuggerModel.cpp @@ -22,7 +22,7 @@ #include "libethereum/ExtVM.h" #include "libevm/VM.h" #include "libdevcore/Common.h" -#include "ApplicationCtx.h" +#include "AppContext.h" #include "TransactionBuilder.h" #include "AssemblyDebuggerModel.h" #include "ConstantCompilationModel.h" @@ -40,7 +40,7 @@ DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::by { QList states; Transaction tr(_rawTransaction); - m_currentExecution.get()->create(tr.sender(), tr.value(), tr.gasPrice(), tr.gas(), &tr.data(), tr.sender()); + m_currentExecution->create(tr.sender(), tr.value(), tr.gasPrice(), tr.gas(), &tr.data(), tr.sender()); std::vector levels; bytes code; bytesConstRef data; @@ -66,8 +66,8 @@ DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::by vm.stack(), vm.memory(), gasCost, ext.state().storage(ext.myAddress), levels})); }; - m_currentExecution.get()->go(onOp); - m_currentExecution.get()->finalize(onOp); + m_currentExecution->go(onOp); + m_currentExecution->finalize(onOp); DebuggingContent d; d.states = states; diff --git a/mix/CodeEditorExtensionManager.cpp b/mix/CodeEditorExtensionManager.cpp index 3bef1a828..78b0f0a7f 100644 --- a/mix/CodeEditorExtensionManager.cpp +++ b/mix/CodeEditorExtensionManager.cpp @@ -28,7 +28,7 @@ #include #include "ConstantCompilationCtrl.h" #include "AssemblyDebuggerCtrl.h" -#include "ApplicationCtx.h" +#include "AppContext.h" #include "CodeEditorExtensionManager.h" using namespace dev::mix; @@ -65,13 +65,13 @@ void CodeEditorExtensionManager::initExtensions() void CodeEditorExtensionManager::initExtension(std::shared_ptr _ext) { - if (!_ext.get()->contentUrl().isEmpty()) + if (!_ext->contentUrl().isEmpty()) { try { - if (_ext.get()->getDisplayBehavior() == ExtensionDisplayBehavior::Tab) + if (_ext->getDisplayBehavior() == ExtensionDisplayBehavior::Tab) { - _ext.get()->addTabOn(m_tabView); + _ext->addTabOn(m_tabView); } } catch (...) @@ -80,7 +80,7 @@ void CodeEditorExtensionManager::initExtension(std::shared_ptr _ext) return; } } - _ext.get()->start(); + _ext->start(); m_features.append(_ext); } diff --git a/mix/ConstantCompilationCtrl.cpp b/mix/ConstantCompilationCtrl.cpp index a703e6686..771387656 100644 --- a/mix/ConstantCompilationCtrl.cpp +++ b/mix/ConstantCompilationCtrl.cpp @@ -33,12 +33,7 @@ using namespace dev::mix; ConstantCompilationCtrl::ConstantCompilationCtrl(QTextDocument* _doc): Extension(ExtensionDisplayBehavior::Tab) { m_editor = _doc; - m_compilationModel = new ConstantCompilationModel(); -} - -ConstantCompilationCtrl::~ConstantCompilationCtrl() -{ - delete m_compilationModel; + m_compilationModel = std::unique_ptr(new ConstantCompilationModel()); } QString ConstantCompilationCtrl::contentUrl() const diff --git a/mix/ConstantCompilationCtrl.h b/mix/ConstantCompilationCtrl.h index e4661c800..446838d39 100644 --- a/mix/ConstantCompilationCtrl.h +++ b/mix/ConstantCompilationCtrl.h @@ -35,14 +35,14 @@ class ConstantCompilationCtrl: public Extension public: ConstantCompilationCtrl(QTextDocument*); - ~ConstantCompilationCtrl(); + ~ConstantCompilationCtrl() {} void start() const override; QString title() const override; QString contentUrl() const override; private: QTextDocument* m_editor; - ConstantCompilationModel* m_compilationModel; + std::unique_ptr m_compilationModel; void writeOutPut(CompilerResult const&); void resetOutPut(); diff --git a/mix/ConstantCompilationModel.cpp b/mix/ConstantCompilationModel.cpp index a6b2f2741..f50ac805b 100644 --- a/mix/ConstantCompilationModel.cpp +++ b/mix/ConstantCompilationModel.cpp @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file ApplicationCtx.h +/** @file ConstantCompilationModel.h * @author Yann yann@ethdev.com * @date 2014 * Ethereum IDE client. @@ -49,7 +49,7 @@ CompilerResult ConstantCompilationModel::compile(QString _code) ostringstream error; solidity::SourceReferenceFormatter::printExceptionInformation(error, _exception, "Error", compiler.getScanner()); res.success = false; - res.comment = QString::fromStdString(error.str()).toHtmlEscaped(); + res.comment = QString::fromStdString(error.str()); res.hexCode = ""; } catch (...) diff --git a/mix/ConstantCompilationModel.h b/mix/ConstantCompilationModel.h index 713c9e950..465cba285 100644 --- a/mix/ConstantCompilationModel.h +++ b/mix/ConstantCompilationModel.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file ApplicationCtx.h +/** @file ConstantCompilationModel.h * @author Yann yann@ethdev.com * @date 2014 * Ethereum IDE client. @@ -45,7 +45,7 @@ class ConstantCompilationModel public: ConstantCompilationModel() {} ~ConstantCompilationModel() {} - CompilerResult compile(QString); + CompilerResult compile(QString _code); }; } diff --git a/mix/DebuggingStateWrapper.cpp b/mix/DebuggingStateWrapper.cpp index d96c975cd..2dde93520 100644 --- a/mix/DebuggingStateWrapper.cpp +++ b/mix/DebuggingStateWrapper.cpp @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file DebuggingState.h +/** @file DebuggingStateWrapper.h * @author Yann yann@ethdev.com * @date 2014 * Used to translate c++ type (u256, bytes, ...) into friendly value (to be used by QML). @@ -23,6 +23,7 @@ #include #include #include +#include "libdevcore/CommonJS.h" #include "libdevcrypto/Common.h" #include "libevmcore/Instruction.h" #include "libdevcore/Common.h" @@ -68,7 +69,7 @@ QString DebuggingStateWrapper::debugStack() { QString stack; for (auto i: m_state.stack) - stack.prepend(prettyU256(i) + "\n"); + stack.prepend(QString::fromStdString(prettyU256(i)) + "\n"); return stack; } @@ -77,7 +78,7 @@ QString DebuggingStateWrapper::debugStorage() { std::stringstream s; for (auto const& i: m_state.storage) - s << "@" << prettyU256(i.first).toStdString() << "    " << prettyU256(i.second).toStdString(); + s << "@" << prettyU256(i.first) << "    " << prettyU256(i.second); return QString::fromStdString(s.str()); } @@ -130,60 +131,9 @@ QString DebuggingStateWrapper::endOfDebug() return "RETURN " + QString::fromStdString(dev::memDump(out, 16, false)); } else if (m_state.inst == Instruction::STOP) - return "STOP"; + return "STOP"; else if (m_state.inst == Instruction::SUICIDE && m_state.stack.size() >= 1) - return "SUICIDE 0x" + QString::fromStdString(toString(right160(m_state.stack.back()))); + return "SUICIDE 0x" + QString::fromStdString(toString(right160(m_state.stack.back()))); else return "EXCEPTION"; } - -QString DebuggingStateWrapper::prettyU256(u256 _n) -{ - unsigned inc = 0; - QString raw; - std::ostringstream s; - if (!(_n >> 64)) - s << " " << (uint64_t)_n << " (0x" << hex << (uint64_t)_n << ")"; - else if (!~(_n >> 64)) - s << " " << (int64_t)_n << " (0x" << hex << (int64_t)_n << ")"; - else if ((_n >> 160) == 0) - { - Address a = right160(_n); - - QString n = QString::fromStdString(a.abridged());//pretty(a); - if (n.isNull()) - s << "0x" << a; - else - s << n.toHtmlEscaped().toStdString() << "(0x" << a.abridged() << ")"; - } - else if ((raw = fromRaw((h256)_n, &inc)).size()) - return "\"" + raw.toHtmlEscaped() + "\"" + (inc ? " + " + QString::number(inc) : ""); - else - s << "" << (h256)_n; - return QString::fromStdString(s.str()); -} - -QString DebuggingStateWrapper::fromRaw(h256 _n, unsigned* _inc) -{ - if (_n) - { - std::string s((char const*)_n.data(), 32); - auto l = s.find_first_of('\0'); - if (!l) - return QString(); - if (l != std::string::npos) - { - auto p = s.find_first_not_of('\0', l); - if (!(p == std::string::npos || (_inc && p == 31))) - return QString(); - if (_inc) - *_inc = (byte)s[31]; - s.resize(l); - } - for (auto i: s) - if (i < 32) - return QString(); - return QString::fromStdString(s); - } - return QString(); -} diff --git a/mix/DebuggingStateWrapper.h b/mix/DebuggingStateWrapper.h index 3f03004b8..df3b8ccce 100644 --- a/mix/DebuggingStateWrapper.h +++ b/mix/DebuggingStateWrapper.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file DebuggingState.h +/** @file DebuggingStateWrapper.h * @author Yann yann@ethdev.com * @date 2014 * Ethereum IDE client. @@ -57,7 +57,9 @@ struct DebuggingContent QString message; }; -/* contains the line nb of the assembly code and the corresponding index in the code bytes array */ +/** + * @brief Contains the line nb of the assembly code and the corresponding index in the code bytes array. + */ class HumanReadableCode: public QObject { Q_OBJECT @@ -74,20 +76,25 @@ private: int m_processIndex; }; -/* used to publish QMap type to QML */ + +/** + * @brief Publish QMap type to QML. + */ class QQMLMap: public QObject { Q_OBJECT public: - QQMLMap(QMap _map, QObject* _parent): QObject(_parent), m_map(_map) { } - Q_INVOKABLE int getValue(int _key) { return m_map.value(_key); } + QQMLMap(QMap _map, QObject* _parent): QObject(_parent), m_map(_map) { } + Q_INVOKABLE int getValue(int _key) { return m_map.value(_key); } private: QMap m_map; }; -/* used to publish DebuggingState struct to QML */ +/** + * @brief Wrap DebuggingState in QObject + */ class DebuggingStateWrapper: public QObject { Q_OBJECT @@ -104,7 +111,7 @@ class DebuggingStateWrapper: public QObject Q_PROPERTY(QStringList levels READ levels) public: - DebuggingStateWrapper(bytes _code, bytes _data) : m_code(_code), m_data(_data) {} + DebuggingStateWrapper(bytes _code, bytes _data, QObject* parent): QObject(parent), m_code(_code), m_data(_data) {} int step() { return (int)m_state.steps; } int curPC() { return (int)m_state.curPC; } int gasCost() { return (int)m_state.gasCost; } @@ -124,8 +131,6 @@ private: DebuggingState m_state; bytes m_code; bytes m_data; - QString prettyU256(u256 _n); - QString fromRaw(h256 _n, unsigned* _inc = nullptr); }; } diff --git a/mix/Extension.cpp b/mix/Extension.cpp index 24cc19aba..410fe85ec 100644 --- a/mix/Extension.cpp +++ b/mix/Extension.cpp @@ -21,7 +21,7 @@ #include #include #include "Extension.h" -#include "ApplicationCtx.h" +#include "AppContext.h" using namespace dev; using namespace dev::mix; @@ -32,7 +32,7 @@ void Extension::addTabOn(QObject* _view) QVariant returnValue; QQmlComponent* component = new QQmlComponent( - ApplicationCtx::getInstance()->appEngine(), + AppContext::getInstance()->appEngine(), QUrl(contentUrl()), _view); QMetaObject::invokeMethod(_view, "addTab", @@ -48,9 +48,9 @@ void Extension::addContentOn(QObject* _view) Q_UNUSED(_view); if (m_displayBehavior == ExtensionDisplayBehavior::ModalDialog) { - QQmlComponent component(ApplicationCtx::getInstance()->appEngine(), QUrl(contentUrl())); + QQmlComponent component(AppContext::getInstance()->appEngine(), QUrl(contentUrl())); QObject* dialog = component.create(); - QObject* dialogWin = ApplicationCtx::getInstance()->appEngine()->rootObjects().at(0)->findChild("dialog", Qt::FindChildrenRecursively); + QObject* dialogWin = AppContext::getInstance()->appEngine()->rootObjects().at(0)->findChild("dialog", Qt::FindChildrenRecursively); QMetaObject::invokeMethod(dialogWin, "close"); dialogWin->setProperty("contentItem", QVariant::fromValue(dialog)); dialogWin->setProperty("title", title()); diff --git a/mix/TransactionBuilder.cpp b/mix/TransactionBuilder.cpp index ce274fa00..bb7cda939 100644 --- a/mix/TransactionBuilder.cpp +++ b/mix/TransactionBuilder.cpp @@ -18,8 +18,9 @@ */ #include "libethereum/Executive.h" +#include "libdevcore/CommonJS.h" #include "libdevcore/Common.h" -#include "ApplicationCtx.h" +#include "AppContext.h" #include "TransactionBuilder.h" using namespace dev::mix; using namespace dev::eth; @@ -34,59 +35,6 @@ Transaction TransactionBuilder::getCreationTransaction(u256 _value, u256 _gasPri Transaction TransactionBuilder::getBasicTransaction(u256 _value, u256 _gasPrice, u256 _gas, QString address, bytes _data, u256 _nonce, Secret _secret) const { - return Transaction(_value, _gasPrice, _gas, fromString(address), _data, _nonce, _secret); + return Transaction(_value, _gasPrice, _gas, dev::fromString(address.toStdString()), _data, _nonce, _secret); } -int TransactionBuilder::fromHex(char _i) const -{ - if (_i >= '0' && _i <= '9') - return _i - '0'; - if (_i >= 'a' && _i <= 'f') - return _i - 'a' + 10; - if (_i >= 'A' && _i <= 'F') - return _i - 'A' + 10; - BOOST_THROW_EXCEPTION(BadHexCharacter() << errinfo_invalidSymbol(_i)); -} - -bytes TransactionBuilder::fromHex(std::string const& _s) const -{ - unsigned s = (_s[0] == '0' && _s[1] == 'x') ? 2 : 0; - std::vector ret; - ret.reserve((_s.size() - s + 1) / 2); - - if (_s.size() % 2) - try - { - ret.push_back(fromHex(_s[s++])); - } - catch (...){ ret.push_back(0); cwarn << boost::current_exception_diagnostic_information(); } - for (unsigned i = s; i < _s.size(); i += 2) - try - { - ret.push_back((byte)(fromHex(_s[i]) * 16 + fromHex(_s[i + 1]))); - } - catch (...){ ret.push_back(0); cwarn << boost::current_exception_diagnostic_information(); } - return ret; -} - -Address TransactionBuilder::fromString(QString const& _a) const -{ - Client* ethClient = ApplicationCtx::getInstance()->getEthereumClient(); - std::string sn = _a.toStdString(); - if (sn.size() > 32) - sn.resize(32); - h256 n; - memcpy(n.data(), sn.data(), sn.size()); - memset(n.data() + sn.size(), 0, 32 - sn.size()); - if (_a.size() == 40) - return Address(fromHex(_a.toStdString())); - else - { - //we try to resolve the recipient adress using nameReg contract state - const Address c_config = Address("661005d2720d855f1d9976f88bb10c1a3398c77f"); //NameReg contract - if (h160 nameReg = (u160)ethClient->stateAt(c_config, 0)) - if (h256 a = ethClient->stateAt(nameReg, n)) - return right160(a); - } - return Address(); // should maybe throws exception instead of returning blank address. -} diff --git a/mix/TransactionBuilder.h b/mix/TransactionBuilder.h index 261d3060f..99f65b024 100644 --- a/mix/TransactionBuilder.h +++ b/mix/TransactionBuilder.h @@ -1,15 +1,15 @@ /* - This file is part of cpp-ethereum. - cpp-ethereum is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - cpp-ethereum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with cpp-ethereum. If not, see . + This file is part of cpp-ethereum. + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . */ /** @file TransactionBuilder.h * @author Yann yann@ethdev.com @@ -32,15 +32,11 @@ namespace mix class TransactionBuilder { public: - TransactionBuilder() {} - dev::eth::Transaction getBasicTransaction(dev::u256 _value, dev::u256 _gasPrice, dev::u256 _gas, - QString address, bytes _data, dev::u256 _nonce, Secret _secret) const; - dev::eth::Transaction getCreationTransaction(dev::u256 _value, dev::u256 _gasPrice, dev::u256 _gas, - dev::bytes _data, dev::u256 _nonce, Secret _secret) const; -private: - bytes fromHex(std::string const& _s) const; - int fromHex(char _i) const; - Address fromString(QString const& _a) const; + TransactionBuilder() {} + dev::eth::Transaction getBasicTransaction(dev::u256 _value, dev::u256 _gasPrice, dev::u256 _gas, + QString address, bytes _data, dev::u256 _nonce, Secret _secret) const; + dev::eth::Transaction getCreationTransaction(dev::u256 _value, dev::u256 _gasPrice, dev::u256 _gas, + dev::bytes _data, dev::u256 _nonce, Secret _secret) const; }; } diff --git a/mix/main.cpp b/mix/main.cpp index 4f707f47a..33a139f85 100644 --- a/mix/main.cpp +++ b/mix/main.cpp @@ -24,7 +24,7 @@ #include #include #include "CodeEditorExtensionManager.h" -#include "ApplicationCtx.h" +#include "AppContext.h" #include "MixApplication.h" using namespace dev::mix; @@ -33,11 +33,11 @@ int main(int _argc, char *_argv[]) QApplication app(_argc, _argv); qmlRegisterType("CodeEditorExtensionManager", 1, 0, "CodeEditorExtensionManager"); QQmlApplicationEngine* engine = new QQmlApplicationEngine(); - ApplicationCtx::setApplicationContext(engine); - QObject::connect(&app, SIGNAL(lastWindowClosed()), ApplicationCtx::getInstance(), SLOT(quitApplication())); //use to kill ApplicationContext and other stuff + AppContext::setApplicationContext(engine); + QObject::connect(&app, SIGNAL(lastWindowClosed()), AppContext::getInstance(), SLOT(quitApplication())); //use to kill ApplicationContext and other stuff engine->load(QUrl(QStringLiteral("qrc:/qml/main.qml"))); - ApplicationCtx::getInstance()->initKeyEventManager(); //has to be called after the loading of the main view. + AppContext::getInstance()->initKeyEventManager(); //has to be called after the loading of the main view. return app.exec(); } From f7c44f38661a16dde03e5831a5ecc192bfefbf6a Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 8 Dec 2014 13:55:54 +0100 Subject: [PATCH 437/641] project working on mac, FindGmp.cmake && couple of todos --- cmake/EthDependencies.cmake | 29 +++++++++++++++++++++-------- cmake/FindGmp.cmake | 32 ++++++++++++++++++++++++++++++++ cmake/FindLevelDB.cmake | 2 +- libethereum/CMakeLists.txt | 7 ++++--- secp256k1/CMakeLists.txt | 33 +++++++++++++++++++++++---------- 5 files changed, 81 insertions(+), 22 deletions(-) create mode 100644 cmake/FindGmp.cmake diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index d7542e364..7b756c3d5 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -6,7 +6,12 @@ string(TOLOWER ${CMAKE_SYSTEM_NAME} _system_name) set (CMAKE_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/extdep/install/${_system_name}") set (CMAKE_PREFIX_PATH ${CMAKE_DEPENDENCY_INSTALL_DIR}) -if (WIN32) + +# Qt5 requires opengl +# TODO use proper version of windows SDK (32 vs 64) +# TODO make it possible to use older versions of windows SDK (7.0+ should also work) +# TODO it windows SDK is NOT FOUND, throw ERROR +if (${CMAKE_CXX_COMPILER_ID} MATCHES "MSVC") set (CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "C:/Program Files/Windows Kits/8.1/Lib/winv6.3/um/x86") #set (CMAKE_PREFIX_PATH "C:/Program Files/Windows Kits/8.1/Lib/winv6.3/um/x64") endif() @@ -28,6 +33,7 @@ message(" - Jsoncpp lib : ${JSONCPP_LIBRARIES}") # TODO the JsonRpcCpp package does not yet check for correct version number # json-rpc-cpp support is currently not mandatory +# TODO make headless client optional find_package (JsonRpcCpp 0.3.2) if (${JSON_RPC_CPP_FOUND}) message (" - json-rpc-cpp header: ${JSON_RPC_CPP_INCLUDE_DIRS}") @@ -35,6 +41,13 @@ if (${JSON_RPC_CPP_FOUND}) add_definitions(-DETH_JSONRPC) endif() +# TODO gmp package does not yet check for correct version number +# TODO it is also not required in msvc build +find_package (Gmp 6.0.0) +message(" - Gmp Header: ${GMP_INCLUDE_DIR}") +message(" - Gmp lib : ${GMP_LIBRARY}") + +# TODO make headless client optional find_package (QT5Core REQUIRED) find_package (QT5Gui REQUIRED) find_package (Qt5Quick REQUIRED) @@ -46,18 +59,18 @@ find_package (Qt5WebKitWidgets REQUIRED) # we have to specify here if we want static and boost version, that is really important - -# win32 msvc 2013 boost set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) -set(Boost_COMPILER -vc120) + +# TODO hanlde other msvc versions or it will fail find them +if (${CMAKE_CXX_COMPILER_ID} MATCHES "MSVC") + set(Boost_COMPILER -vc120) +endif() find_package(Boost 1.55.0 REQUIRED COMPONENTS thread date_time system regex chrono filesystem) -if (Boost_FOUND) - message(" - boost header: ${Boost_INCLUDE_DIRS}") - message(" - boost lib : ${Boost_LIBRARIES}") -endif() +message(" - boost header: ${Boost_INCLUDE_DIRS}") +message(" - boost lib : ${Boost_LIBRARIES}") diff --git a/cmake/FindGmp.cmake b/cmake/FindGmp.cmake new file mode 100644 index 000000000..908499865 --- /dev/null +++ b/cmake/FindGmp.cmake @@ -0,0 +1,32 @@ +# Find gmp +# +# Find the gmp includes and library +# +# if you nee to add a custom library search path, do it via via CMAKE_FIND_ROOT_PATH +# +# This module defines +# GMP_INCLUDE_DIR, where to find header, etc. +# GMP_LIBRARY, the libraries needed to use leveldb. +# GMP_FOUND, If false, do not try to use leveldb. + +# only look in default directories +find_path( + GMP_INCLUDE_DIR + NAMES gmp.h + DOC "gmp include dir" + ) + +find_library( + GMP_LIBRARY + NAMES gmp + DOC "gmp library" + ) + + +# handle the QUIETLY and REQUIRED arguments and set GMP_FOUND to TRUE +# if all listed variables are TRUE, hide their existence from configuration view +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(gmp DEFAULT_MSG + GMP_INCLUDE_DIR GMP_LIBRARY) +mark_as_advanced (GMP_INCLUDE_DIR GMP_LIBRARY) + diff --git a/cmake/FindLevelDB.cmake b/cmake/FindLevelDB.cmake index 770c9e65f..26629d35f 100644 --- a/cmake/FindLevelDB.cmake +++ b/cmake/FindLevelDB.cmake @@ -26,7 +26,7 @@ find_library( # message (" - leveldb lib : ${LEVELDB_LIBRARY}") -# handle the QUIETLY and REQUIRED arguments and set JSON_RPC_CPP_FOUND to TRUE +# handle the QUIETLY and REQUIRED arguments and set LEVELDB_FOUND to TRUE # if all listed variables are TRUE, hide their existence from configuration view include(FindPackageHandleStandardArgs) find_package_handle_standard_args(leveldb DEFAULT_MSG diff --git a/libethereum/CMakeLists.txt b/libethereum/CMakeLists.txt index de750fdb8..e9904e9a8 100644 --- a/libethereum/CMakeLists.txt +++ b/libethereum/CMakeLists.txt @@ -5,6 +5,9 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) +include_directories(${LEVELDB_INCLUDE_DIR}) +include_directories(..) + set(EXECUTABLE ethereum) file(GLOB HEADERS "*.h") @@ -15,10 +18,8 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -include_directories(${LEVELDB_INCLUDE_DIR}) -include_directories(..) - target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARY_RELEASE}) if (MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) diff --git a/secp256k1/CMakeLists.txt b/secp256k1/CMakeLists.txt index baa58e7e8..f02bba238 100644 --- a/secp256k1/CMakeLists.txt +++ b/secp256k1/CMakeLists.txt @@ -3,19 +3,32 @@ set(CMAKE_AUTOMOC OFF) set(CMAKE_ASM_COMPILER "yasm") -include_directories(${Boost_INCLUDE_DIRS}) - set(EXECUTABLE secp256k1) - file(GLOB HEADERS "*.h") -if(ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${EXECUTABLE}.c) -else() - add_library(${EXECUTABLE} SHARED ${EXECUTABLE}.c) -endif() -set_target_properties(${EXECUTABLE} PROPERTIES COMPILE_FLAGS "/TP") -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSE_NUM_BOOST -DUSE_FIELD_10X26 -DUSE_FIELD_INV_BUILTIN") +if (${CMAKE_CXX_COMPILER_ID} MATCHES "MSVC") + + include_directories(${Boost_INCLUDE_DIRS}) + if(ETH_STATIC) + add_library(${EXECUTABLE} STATIC ${EXECUTABLE}.c) + else() + add_library(${EXECUTABLE} SHARED ${EXECUTABLE}.c) + endif() + # /TP - compile project as cpp project + set_target_properties(${EXECUTABLE} PROPERTIES COMPILE_FLAGS "/TP") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSE_NUM_BOOST -DUSE_FIELD_10X26 -DUSE_FIELD_INV_BUILTIN") + +elseif (APPLE OR UNIX) + + if (ETH_STATIC) + add_library(${EXECUTABLE} STATIC ${EXECUTABLE}.c field_5x52_asm.asm) + else() + add_library(${EXECUTABLE} SHARED ${EXECUTABLE}.c field_5x52_asm.asm) + endif() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -DUSE_FIELD_GMP -DUSE_NUM_GMP -DUSE_FIELD_INV_NUM") + target_link_libraries(${EXECUTABLE} ${GMP_LIBRARY}) + +endif() install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) From d5b343994a5f86aee9cad7556f4a15877d0d2f8b Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 8 Dec 2014 14:12:28 +0100 Subject: [PATCH 438/641] removed few unused lines from cmakes --- cmake/EthCompilerSettings.cmake | 51 ++++++++------------------------- libsolidity/CompilerStack.h | 16 ----------- 2 files changed, 12 insertions(+), 55 deletions(-) diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index 69a420333..ba24b62e2 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -1,25 +1,32 @@ # Set necessary compile and link flags - # C++11 check and activation if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") - set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wno-unknown-pragmas -Wextra -DSHAREDLIB") + + set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wno-unknown-pragmas -Wextra -DSHAREDLIB -fPIC") + set(ETH_SHARED 1) execute_process( COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION) if (NOT (GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7)) message(FATAL_ERROR "${PROJECT_NAME} requires g++ 4.7 or greater.") endif () + elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") - set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wno-unknown-pragmas -Wextra -DSHAREDLIB") + + set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wno-unknown-pragmas -Wextra -DSHAREDLIB -fPIC") + set(ETH_SHARED 1) + elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + + # specify Exception Handling Model in msvc set(CMAKE_CXX_FLAGS "/EHsc") + # windows likes static set(ETH_STATIC 1) + else () message(FATAL_ERROR "Your C++ compiler does not support C++11. You have ${CMAKE_CXX_COMPILER_ID}") endif () - - # Initialize CXXFLAGS # CMAKE_CXX_FLAGS was set before set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DETH_DEBUG") @@ -27,37 +34,3 @@ set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG -DETH_RELEASE") set(CMAKE_CXX_FLAGS_RELEASE "-O4 -DNDEBUG -DETH_RELEASE") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -DETH_DEBUG") -# Windows -#if ("${TARGET_PLATFORM}" STREQUAL "w64") -# set(CMAKE_SYSTEM_NAME Windows) -# -# set(CMAKE_CXX_LIBRARY_ARCHITECTURE x86_64-w64-mingw32) -# set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) -# set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) -# set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres) -# set(CMAKE_AR x86_64-w64-mingw32-ar) -# set(CMAKE_RANLIB x86_64-w64-mingw32-ranlib) -# -# set(CMAKE_EXECUTABLE_SUFFIX .exe) -# -# set(CMAKE_FIND_ROOT_PATH -# /usr/x86_64-w64-mingw32 -# ) -# -# include_directories(/usr/x86_64-w64-mingw32/include/cryptopp) -# -# set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) -# set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -# set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -# -# set(CMAKE_INSTALL_PREFIX /usr/x86_64-w64-mingw32) -# set(ETH_BUILD_PLATFORM "windows") -# set(ETH_STATIC 1) -#else () -# set(ETH_BUILD_PLATFORM ${CMAKE_SYSTEM_NAME}) -# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") -# set(ETH_SHARED 1) -#endif() - - - diff --git a/libsolidity/CompilerStack.h b/libsolidity/CompilerStack.h index 6f036d3f3..82d275498 100644 --- a/libsolidity/CompilerStack.h +++ b/libsolidity/CompilerStack.h @@ -94,22 +94,6 @@ public: /// scanning the source code - this is useful for printing exception information. static bytes staticCompile(std::string const& _sourceCode, bool _optimize = false); - /// Compile under msvc results in error CC2280 - CompilerStack& operator=(const CompilerStack& _other) - { - m_scanner = _other.m_scanner; - m_globalContext = _other.m_globalContext; - m_contractASTNode = _other.m_contractASTNode; - m_parseSuccessful = _other.m_parseSuccessful; - m_interface.reset(_other.m_interface.get()); - m_userDocumentation.reset(_other.m_userDocumentation.get()); - m_devDocumentation.reset(_other.m_devDocumentation.get()); - m_compiler = _other.m_compiler; - m_interfaceHandler = _other.m_interfaceHandler; - m_bytecode = m_bytecode; - return *this; - } - private: /** * Information pertaining to one source unit, filled gradually during parsing and compilation. From 5a874b4abb001afde8ad70f78aa638213b0ed0e5 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 8 Dec 2014 14:48:42 +0100 Subject: [PATCH 439/641] removed EthDependenciesDeprecated --- CMakeLists.txt | 4 - cmake/EthDependencies.cmake | 47 ++++++----- cmake/EthDependenciesDeprecated.cmake | 110 -------------------------- cmake/FindGmp.cmake | 5 +- cmake/FindMiniupnpc.cmake | 31 ++++++++ cmake/FindReadline.cmake | 31 ++++++++ eth/CMakeLists.txt | 8 +- exp/CMakeLists.txt | 4 +- libethereum/CMakeLists.txt | 4 +- libevm/CMakeLists.txt | 4 +- libp2p/CMakeLists.txt | 4 +- libweb3jsonrpc/CMakeLists.txt | 4 +- libwebthree/CMakeLists.txt | 4 +- libwhisper/CMakeLists.txt | 4 +- neth/CMakeLists.txt | 4 +- 15 files changed, 112 insertions(+), 156 deletions(-) delete mode 100644 cmake/EthDependenciesDeprecated.cmake create mode 100644 cmake/FindMiniupnpc.cmake create mode 100644 cmake/FindReadline.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index d4be26923..d070ccc1e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,10 +105,6 @@ message("-- CXXFLAGS: ${CMAKE_CXX_FLAGS}") # this must be an include, as a function it would messs up with variable scope! include(EthDependencies) - -# TODO this will go away soon! -include(EthDependenciesDeprecated) - createBuildInfo() add_subdirectory(libdevcore) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 7b756c3d5..77cd3bfe7 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -34,18 +34,39 @@ message(" - Jsoncpp lib : ${JSONCPP_LIBRARIES}") # TODO the JsonRpcCpp package does not yet check for correct version number # json-rpc-cpp support is currently not mandatory # TODO make headless client optional +# TODO get rid of -DETH_JSONRPC find_package (JsonRpcCpp 0.3.2) -if (${JSON_RPC_CPP_FOUND}) +if (JSON_RPC_CPP_FOUND) message (" - json-rpc-cpp header: ${JSON_RPC_CPP_INCLUDE_DIRS}") message (" - json-rpc-cpp lib : ${JSON_RPC_CPP_LIBRARIES}") add_definitions(-DETH_JSONRPC) endif() +# TODO readline package does not yet check for correct version number +# TODO make readline package dependent on cmake options +# TODO get rid of -DETH_READLINE +find_package (Readline 6.3.8) +if (READLINE_FOUND) + message (" - readline header: ${READLINE_INCLUDE_DIR}") + message (" - readline lib : ${READLINE_LIBRARY}") + add_definitions(-DETH_READLINE) +endif () + +# TODO miniupnpc package does not yet check for correct version number +# TODO make miniupnpc package dependent on cmake options +# TODO get rid of -DMINIUPNPC +find_package (Miniupnpc 1.8.2013) +if (MINIUPNPC_FOUND) + message (" - miniupnpc header: ${MINIUPNPC_INCLUDE_DIR}") + message (" - miniupnpc lib : ${MINIUPNPC_LIBRARY}") + add_definitions(-DETH_MINIUPNPC) +endif() + # TODO gmp package does not yet check for correct version number # TODO it is also not required in msvc build find_package (Gmp 6.0.0) -message(" - Gmp Header: ${GMP_INCLUDE_DIR}") -message(" - Gmp lib : ${GMP_LIBRARY}") +message(" - gmp Header: ${GMP_INCLUDE_DIR}") +message(" - gmp lib : ${GMP_LIBRARY}") # TODO make headless client optional find_package (QT5Core REQUIRED) @@ -57,7 +78,6 @@ find_package (Qt5Widgets REQUIRED) find_package (Qt5WebKit REQUIRED) find_package (Qt5WebKitWidgets REQUIRED) - # we have to specify here if we want static and boost version, that is really important set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) @@ -72,19 +92,8 @@ find_package(Boost 1.55.0 REQUIRED COMPONENTS thread date_time system regex chro message(" - boost header: ${Boost_INCLUDE_DIRS}") message(" - boost lib : ${Boost_LIBRARIES}") - - - - - - - - - - - - - - - +if (APPLE) + link_directories(/usr/local/lib) + include_directories(/usr/local/include) +endif() diff --git a/cmake/EthDependenciesDeprecated.cmake b/cmake/EthDependenciesDeprecated.cmake deleted file mode 100644 index 72ad9c769..000000000 --- a/cmake/EthDependenciesDeprecated.cmake +++ /dev/null @@ -1,110 +0,0 @@ -# search for and configure dependencies - -# deprecated. DO NOT ADD any new stuff here. Proper dependency fetching is done in EthDependencies.cmake - - -if("${TARGET_PLATFORM}" STREQUAL "w64") -# set(MINIUPNPC_LS /usr/x86_64-w64-mingw32/lib/libminiupnpc.a) -else() - - find_path( PYTHON_ID pyconfig.h - ${PYTHON_INCLUDE_DIR} - /usr/include/python2.7 - /usr/local/include/python2.7 - ) - if ( PYTHON_ID STREQUAL "PYTHON_ID-NOTFOUND" ) - message(STATUS "Failed to find the Python-2.7 headers") - else () - message(STATUS "Found Python-2.7 Headers: ${PYTHON_ID}") - - # Check for accessory dev libraries leveldb and miniupnpc - find_library( PYTHON_LS NAMES python2.7 - PATHS - /usr/lib - /usr/local/lib - /opt/local/lib - /usr/lib/*/ - ) - if ( PYTHON_LS STREQUAL "PYTHON_LS-NOTFOUND" ) - message(STATUS "Failed to find the Python-2.7 Library!") - set(PYTHON_ID) - set(PYTHON_LS) - else () - message(STATUS "Found Python-2.7 Library: ${PYTHON_LS}") - add_definitions(-DETH_PYTHON) - endif () - endif () - - find_path( MINIUPNPC_ID miniupnpc/miniwget.h - /usr/include - /usr/local/include - ) - if ( MINIUPNPC_ID ) - message(STATUS "Found miniupnpc headers") - - find_library( MINIUPNPC_LS NAMES miniupnpc - PATHS - /usr/lib - /usr/local/lib - /opt/local/lib - /usr/lib/*/ - ) - if ( MINIUPNPC_LS ) - message(STATUS "Found miniupnpc library: ${MINIUPNPC_LS}") - add_definitions(-DETH_MINIUPNPC) - else () - message(STATUS "Failed to find the miniupnpc library!") - endif () - else () - message(STATUS "Failed to find the miniupnpc headers!") - endif () - - find_path( READLINE_ID readline/readline.h - /usr/include - /usr/local/include - ) - if ( READLINE_ID ) - message(STATUS "Found readline headers") - find_library( READLINE_LS NAMES readline - PATHS - /usr/lib - /usr/local/lib - /opt/local/lib - /usr/lib/*/ - ) - if ( READLINE_LS ) - message(STATUS "Found readline library: ${READLINE_LS}") - add_definitions(-DETH_READLINE) - else () - message(STATUS "Failed to find the readline library!") - endif () - else () - message(STATUS "Failed to find the readline headers!") - endif () - - #if (LANGUAGES) - # find_package(Boost 1.53 REQUIRED COMPONENTS thread date_time) - #else() - # find_package(Boost 1.53 REQUIRED COMPONENTS thread date_time system regex) - #endif() - - set(QTQML 1) -endif() - -if(PYTHON_ID) - include_directories(${PYTHON_ID}) -endif() -if(MINIUPNPC_ID) - include_directories(${MINIUPNPC_ID}) -endif() -if(READLINE_ID) - include_directories(${READLINE_ID}) -endif() - - - - -if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - link_directories(/usr/local/lib) - include_directories(/usr/local/include) -endif() diff --git a/cmake/FindGmp.cmake b/cmake/FindGmp.cmake index 908499865..4d7a3a04c 100644 --- a/cmake/FindGmp.cmake +++ b/cmake/FindGmp.cmake @@ -6,8 +6,8 @@ # # This module defines # GMP_INCLUDE_DIR, where to find header, etc. -# GMP_LIBRARY, the libraries needed to use leveldb. -# GMP_FOUND, If false, do not try to use leveldb. +# GMP_LIBRARY, the libraries needed to use gmp. +# GMP_FOUND, If false, do not try to use gmp. # only look in default directories find_path( @@ -22,7 +22,6 @@ find_library( DOC "gmp library" ) - # handle the QUIETLY and REQUIRED arguments and set GMP_FOUND to TRUE # if all listed variables are TRUE, hide their existence from configuration view include(FindPackageHandleStandardArgs) diff --git a/cmake/FindMiniupnpc.cmake b/cmake/FindMiniupnpc.cmake new file mode 100644 index 000000000..90a202dce --- /dev/null +++ b/cmake/FindMiniupnpc.cmake @@ -0,0 +1,31 @@ +# Find miniupnpc +# +# Find the miniupnpc includes and library +# +# if you nee to add a custom library search path, do it via via CMAKE_FIND_ROOT_PATH +# +# This module defines +# MINIUPNPC_INCLUDE_DIR, where to find header, etc. +# MINIUPNPC_LIBRARY, the libraries needed to use gmp. +# MINIUPNPC_FOUND, If false, do not try to use gmp. + +# only look in default directories +find_path( + MINIUPNPC_INCLUDE_DIR + NAMES miniupnpc/miniupnpc.h + DOC "miniupnpc include dir" + ) + +find_library( + MINIUPNPC_LIBRARY + NAMES miniupnpc + DOC "miniupnpc library" + ) + +# handle the QUIETLY and REQUIRED arguments and set MINIUPNPC_FOUND to TRUE +# if all listed variables are TRUE, hide their existence from configuration view +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(miniupnpc DEFAULT_MSG + MINIUPNPC_INCLUDE_DIR MINIUPNPC_LIBRARY) +mark_as_advanced (MINIUPNPC_INCLUDE_DIR MINIUPNPC_LIBRARY) + diff --git a/cmake/FindReadline.cmake b/cmake/FindReadline.cmake new file mode 100644 index 000000000..16eb483ee --- /dev/null +++ b/cmake/FindReadline.cmake @@ -0,0 +1,31 @@ +# Find readline +# +# Find the readline includes and library +# +# if you nee to add a custom library search path, do it via via CMAKE_FIND_ROOT_PATH +# +# This module defines +# READLINE_INCLUDE_DIR, where to find header, etc. +# READLINE_LIBRARY, the libraries needed to use readline. +# READLINE_FOUND, If false, do not try to use readline. + +# only look in default directories +find_path( + READLINE_INCLUDE_DIR + NAMES readline/readline.h + DOC "readling include dir" + ) + +find_library( + READLINE_LIBRARY + NAMES readline + DOC "readline library" + ) + +# handle the QUIETLY and REQUIRED arguments and set READLINE_FOUND to TRUE +# if all listed variables are TRUE, hide their existence from configuration view +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(readline DEFAULT_MSG + READLINE_INCLUDE_DIR READLINE_LIBRARY) +mark_as_advanced (READLINE_INCLUDE_DIR READLINE_LIBRARY) + diff --git a/eth/CMakeLists.txt b/eth/CMakeLists.txt index 575c045d8..fe5571f60 100644 --- a/eth/CMakeLists.txt +++ b/eth/CMakeLists.txt @@ -17,16 +17,16 @@ add_dependencies(${EXECUTABLE} BuildInfo.h) target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARY_RELEASE}) target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARY_RELEASE}) -if(MINIUPNPC_LS) - target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) +if(MINIUPNPC_FOUND) + target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) endif() if(JSON_RPC_CPP_FOUND) target_link_libraries(${EXECUTABLE} web3jsonrpc) endif() -if(READLINE_LS) -target_link_libraries(${EXECUTABLE} ${READLINE_LS}) +if (READLINE_FOUND) +target_link_libraries(${EXECUTABLE} ${READLINE_LIBRARY}) endif() target_link_libraries(${EXECUTABLE} webthree) diff --git a/exp/CMakeLists.txt b/exp/CMakeLists.txt index 6fcea5341..1cd5218e2 100644 --- a/exp/CMakeLists.txt +++ b/exp/CMakeLists.txt @@ -12,8 +12,8 @@ add_executable(${EXECUTABLE} ${SRC_LIST}) target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) -if(MINIUPNPC_LS) -target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) +if(MINIUPNPC_FOUND) +target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) endif() target_link_libraries(${EXECUTABLE} ethereum) diff --git a/libethereum/CMakeLists.txt b/libethereum/CMakeLists.txt index e9904e9a8..ac5bd7136 100644 --- a/libethereum/CMakeLists.txt +++ b/libethereum/CMakeLists.txt @@ -21,8 +21,8 @@ endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARY_RELEASE}) -if (MINIUPNPC_LS) -target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) +if (MINIUPNPC_FOUND) +target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) endif() target_link_libraries(${EXECUTABLE} evm) diff --git a/libevm/CMakeLists.txt b/libevm/CMakeLists.txt index 778bce8d9..717904912 100644 --- a/libevm/CMakeLists.txt +++ b/libevm/CMakeLists.txt @@ -19,8 +19,8 @@ endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) -if(MINIUPNPC_LS) -target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) +if(MINIUPNPC_FOUND) +target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) endif() target_link_libraries(${EXECUTABLE} ethcore) diff --git a/libp2p/CMakeLists.txt b/libp2p/CMakeLists.txt index fa7ff6a54..e354a1c65 100644 --- a/libp2p/CMakeLists.txt +++ b/libp2p/CMakeLists.txt @@ -18,8 +18,8 @@ else() endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) -if(MINIUPNPC_LS) -target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) +if(MINIUPNPC_FOUND) +target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) endif() target_link_libraries(${EXECUTABLE} devcrypto) diff --git a/libweb3jsonrpc/CMakeLists.txt b/libweb3jsonrpc/CMakeLists.txt index 9925b9026..133471d18 100644 --- a/libweb3jsonrpc/CMakeLists.txt +++ b/libweb3jsonrpc/CMakeLists.txt @@ -22,8 +22,8 @@ target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_COMMON_LIBRARY}) target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_SERVER_LIBRARY}) -if (MINIUPNPC_LS) - target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) +if (MINIUPNPC_FOUND) + target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) endif() target_link_libraries(${EXECUTABLE} webthree) diff --git a/libwebthree/CMakeLists.txt b/libwebthree/CMakeLists.txt index 2e305a5be..09fe7f736 100644 --- a/libwebthree/CMakeLists.txt +++ b/libwebthree/CMakeLists.txt @@ -19,8 +19,8 @@ endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) -if(MINIUPNPC_LS) -target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) +if(MINIUPNPC_FOUND) +target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) endif() target_link_libraries(${EXECUTABLE} ethereum) diff --git a/libwhisper/CMakeLists.txt b/libwhisper/CMakeLists.txt index 51908ffcf..3ab2f6097 100644 --- a/libwhisper/CMakeLists.txt +++ b/libwhisper/CMakeLists.txt @@ -19,8 +19,8 @@ endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) -if(MINIUPNPC_LS) -target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) +if(MINIUPNPC_FOUND) +target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) endif() target_link_libraries(${EXECUTABLE} ethcore) diff --git a/neth/CMakeLists.txt b/neth/CMakeLists.txt index 46195a1eb..4dd49874d 100644 --- a/neth/CMakeLists.txt +++ b/neth/CMakeLists.txt @@ -14,8 +14,8 @@ target_link_libraries(${EXECUTABLE} webthree) target_link_libraries(${EXECUTABLE} ethereum) target_link_libraries(${EXECUTABLE} secp256k1) target_link_libraries(${EXECUTABLE} gmp) -if(MINIUPNPC_LS) -target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) +if(MINIUPNPC_FOUND) +target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) if(JSON_RPC_CPP_FOUND) From d2344f5b36a4553558d24bb90d7ef2ff2e70a7a9 Mon Sep 17 00:00:00 2001 From: debris Date: Mon, 8 Dec 2014 15:03:40 +0100 Subject: [PATCH 440/641] common changes on windows --- cmake/EthDependencies.cmake | 9 ++++++--- secp256k1/CMakeLists.txt | 23 +++++++++++------------ 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 77cd3bfe7..8a86e7095 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -11,8 +11,9 @@ set (CMAKE_PREFIX_PATH ${CMAKE_DEPENDENCY_INSTALL_DIR}) # TODO use proper version of windows SDK (32 vs 64) # TODO make it possible to use older versions of windows SDK (7.0+ should also work) # TODO it windows SDK is NOT FOUND, throw ERROR -if (${CMAKE_CXX_COMPILER_ID} MATCHES "MSVC") +if (WIN32) set (CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "C:/Program Files/Windows Kits/8.1/Lib/winv6.3/um/x86") + message(" - Found windows 8.1 SDK") #set (CMAKE_PREFIX_PATH "C:/Program Files/Windows Kits/8.1/Lib/winv6.3/um/x64") endif() @@ -65,8 +66,10 @@ endif() # TODO gmp package does not yet check for correct version number # TODO it is also not required in msvc build find_package (Gmp 6.0.0) -message(" - gmp Header: ${GMP_INCLUDE_DIR}") -message(" - gmp lib : ${GMP_LIBRARY}") +if (GMP_FOUND) + message(" - gmp Header: ${GMP_INCLUDE_DIR}") + message(" - gmp lib : ${GMP_LIBRARY}") +endif() # TODO make headless client optional find_package (QT5Core REQUIRED) diff --git a/secp256k1/CMakeLists.txt b/secp256k1/CMakeLists.txt index f02bba238..230bf76b9 100644 --- a/secp256k1/CMakeLists.txt +++ b/secp256k1/CMakeLists.txt @@ -6,7 +6,16 @@ set(CMAKE_ASM_COMPILER "yasm") set(EXECUTABLE secp256k1) file(GLOB HEADERS "*.h") -if (${CMAKE_CXX_COMPILER_ID} MATCHES "MSVC") +if (APPLE OR UNIX) + + if (ETH_STATIC) + add_library(${EXECUTABLE} STATIC ${EXECUTABLE}.c field_5x52_asm.asm) + else() + add_library(${EXECUTABLE} SHARED ${EXECUTABLE}.c field_5x52_asm.asm) + endif() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -DUSE_FIELD_GMP -DUSE_NUM_GMP -DUSE_FIELD_INV_NUM") + target_link_libraries(${EXECUTABLE} ${GMP_LIBRARY}) +else() include_directories(${Boost_INCLUDE_DIRS}) if(ETH_STATIC) @@ -17,17 +26,7 @@ if (${CMAKE_CXX_COMPILER_ID} MATCHES "MSVC") # /TP - compile project as cpp project set_target_properties(${EXECUTABLE} PROPERTIES COMPILE_FLAGS "/TP") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSE_NUM_BOOST -DUSE_FIELD_10X26 -DUSE_FIELD_INV_BUILTIN") - -elseif (APPLE OR UNIX) - - if (ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${EXECUTABLE}.c field_5x52_asm.asm) - else() - add_library(${EXECUTABLE} SHARED ${EXECUTABLE}.c field_5x52_asm.asm) - endif() - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -DUSE_FIELD_GMP -DUSE_NUM_GMP -DUSE_FIELD_INV_NUM") - target_link_libraries(${EXECUTABLE} ${GMP_LIBRARY}) - + endif() install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) From 7e44c34491a62cba5ecef5253404e0a25241a74b Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 8 Dec 2014 15:41:22 +0100 Subject: [PATCH 441/641] - manage Debugger states calculation in a separate thread (avoid blocking the UI) --- mix/AssemblyDebuggerCtrl.cpp | 25 +++++++++++++++++++------ mix/AssemblyDebuggerCtrl.h | 8 ++++++++ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/mix/AssemblyDebuggerCtrl.cpp b/mix/AssemblyDebuggerCtrl.cpp index 6e2b11e70..4d293cd8d 100644 --- a/mix/AssemblyDebuggerCtrl.cpp +++ b/mix/AssemblyDebuggerCtrl.cpp @@ -17,6 +17,7 @@ * display opcode debugging. */ +#include #include #include #include @@ -31,6 +32,9 @@ using namespace dev::mix; AssemblyDebuggerCtrl::AssemblyDebuggerCtrl(QTextDocument* _doc): Extension(ExtensionDisplayBehavior::ModalDialog) { + qRegisterMetaType(); + connect(this, SIGNAL(dataAvailable(QList, AssemblyDebuggerData)), + this, SLOT(updateGUI(QList, AssemblyDebuggerData)), Qt::QueuedConnection); m_modelDebugger = std::unique_ptr(new AssemblyDebuggerModel); m_doc = _doc; } @@ -56,6 +60,9 @@ void AssemblyDebuggerCtrl::keyPressed(int _key) if (_key == Qt::Key_F5) { + QString code = m_doc->toPlainText(); + QtConcurrent::run([this, code](){ + if (!m_modelDebugger->compile(m_doc->toPlainText())) { AppContext::getInstance()->displayMessageDialog("debugger","compilation failed"); @@ -76,10 +83,16 @@ void AssemblyDebuggerCtrl::keyPressed(int _key) s->setState(debuggingContent.states.at(i)); wStates.append(s); } - std::tuple, QQMLMap*> code = DebuggingStateWrapper::getHumanReadableCode(debuggingContent.executionCode, this); - AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("debugStates", QVariant::fromValue(wStates)); - AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("humanReadableExecutionCode", QVariant::fromValue(std::get<0>(code))); - AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("bytesCodeMapping", QVariant::fromValue(std::get<1>(code))); - this->addContentOn(this); - }; + AssemblyDebuggerData code = DebuggingStateWrapper::getHumanReadableCode(debuggingContent.executionCode, this); + emit dataAvailable(wStates, code); + }); + } +} + +void AssemblyDebuggerCtrl::updateGUI(QList _wStates, AssemblyDebuggerData _code) +{ + AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("debugStates", QVariant::fromValue(_wStates)); + AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("humanReadableExecutionCode", QVariant::fromValue(std::get<0>(_code))); + AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("bytesCodeMapping", QVariant::fromValue(std::get<1>(_code))); + this->addContentOn(this); } diff --git a/mix/AssemblyDebuggerCtrl.h b/mix/AssemblyDebuggerCtrl.h index a1642cc14..66256e472 100644 --- a/mix/AssemblyDebuggerCtrl.h +++ b/mix/AssemblyDebuggerCtrl.h @@ -25,6 +25,9 @@ #include "ConstantCompilationModel.h" #include "AssemblyDebuggerModel.h" +using AssemblyDebuggerData = std::tuple, dev::mix::QQMLMap*>; +Q_DECLARE_METATYPE(AssemblyDebuggerData) + namespace dev { @@ -48,6 +51,11 @@ private: public Q_SLOTS: void keyPressed(int); + void updateGUI(QList _wStates, AssemblyDebuggerData _code); + +signals: + void dataAvailable(QList _wStates, AssemblyDebuggerData _code); + }; } From 0d58c2b664d880253d93a1ec0b10c36f3ee03f6b Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 8 Dec 2014 16:53:07 +0100 Subject: [PATCH 442/641] - delete code comment (code used to resolve name using NameReg contract) --- libdevcore/CommonJS.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libdevcore/CommonJS.cpp b/libdevcore/CommonJS.cpp index 800bd06c8..8d8638da5 100644 --- a/libdevcore/CommonJS.cpp +++ b/libdevcore/CommonJS.cpp @@ -116,11 +116,6 @@ Address fromString(std::string _sn) return Address(fromHex(_sn)); else return Address(); - //we try to resolve the recipient adress using nameReg contract state - /*const Address c_config = Address("661005d2720d855f1d9976f88bb10c1a3398c77f"); //NameReg contract - if (h160 nameReg = (u160)ethClient->stateAt(c_config, 0)) - if (h256 a = ethClient->stateAt(nameReg, n)) - return right160(a);*/ } From 6030db73f771bc6edb8dcb4837464ffa5456df7b Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 8 Dec 2014 17:42:47 +0100 Subject: [PATCH 443/641] - Bug fix (failed compilation alert was loaded in a separate thread). - Coding Standards. - Add DebuggingStatusResult in AssemblyDebuggerCtrl --- mix/AssemblyDebuggerCtrl.cpp | 25 ++++++++++++++++--------- mix/AssemblyDebuggerCtrl.h | 11 +++++++++-- mix/AssemblyDebuggerModel.cpp | 4 ++-- mix/DebuggingStateWrapper.h | 4 ++-- mix/KeyEventManager.h | 6 +++--- mix/TransactionBuilder.cpp | 4 ++-- 6 files changed, 34 insertions(+), 20 deletions(-) diff --git a/mix/AssemblyDebuggerCtrl.cpp b/mix/AssemblyDebuggerCtrl.cpp index 4d293cd8d..e48aa9138 100644 --- a/mix/AssemblyDebuggerCtrl.cpp +++ b/mix/AssemblyDebuggerCtrl.cpp @@ -33,8 +33,9 @@ using namespace dev::mix; AssemblyDebuggerCtrl::AssemblyDebuggerCtrl(QTextDocument* _doc): Extension(ExtensionDisplayBehavior::ModalDialog) { qRegisterMetaType(); - connect(this, SIGNAL(dataAvailable(QList, AssemblyDebuggerData)), - this, SLOT(updateGUI(QList, AssemblyDebuggerData)), Qt::QueuedConnection); + qRegisterMetaType(); + connect(this, SIGNAL(dataAvailable(bool, DebuggingStatusResult, QList, AssemblyDebuggerData)), + this, SLOT(updateGUI(bool, DebuggingStatusResult, QList, AssemblyDebuggerData)), Qt::QueuedConnection); m_modelDebugger = std::unique_ptr(new AssemblyDebuggerModel); m_doc = _doc; } @@ -65,7 +66,7 @@ void AssemblyDebuggerCtrl::keyPressed(int _key) if (!m_modelDebugger->compile(m_doc->toPlainText())) { - AppContext::getInstance()->displayMessageDialog("debugger","compilation failed"); + emit dataAvailable(false, DebuggingStatusResult::Compilationfailed); return; } @@ -84,15 +85,21 @@ void AssemblyDebuggerCtrl::keyPressed(int _key) wStates.append(s); } AssemblyDebuggerData code = DebuggingStateWrapper::getHumanReadableCode(debuggingContent.executionCode, this); - emit dataAvailable(wStates, code); + emit dataAvailable(true, DebuggingStatusResult::Ok, wStates, code); }); } } -void AssemblyDebuggerCtrl::updateGUI(QList _wStates, AssemblyDebuggerData _code) +void AssemblyDebuggerCtrl::updateGUI(bool success, DebuggingStatusResult reason, QList _wStates, AssemblyDebuggerData _code) { - AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("debugStates", QVariant::fromValue(_wStates)); - AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("humanReadableExecutionCode", QVariant::fromValue(std::get<0>(_code))); - AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("bytesCodeMapping", QVariant::fromValue(std::get<1>(_code))); - this->addContentOn(this); + Q_UNUSED(reason); + if (success) + { + AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("debugStates", QVariant::fromValue(_wStates)); + AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("humanReadableExecutionCode", QVariant::fromValue(std::get<0>(_code))); + AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("bytesCodeMapping", QVariant::fromValue(std::get<1>(_code))); + this->addContentOn(this); + } + else + AppContext::getInstance()->displayMessageDialog("debugger","compilation failed"); } diff --git a/mix/AssemblyDebuggerCtrl.h b/mix/AssemblyDebuggerCtrl.h index 66256e472..0c092c46d 100644 --- a/mix/AssemblyDebuggerCtrl.h +++ b/mix/AssemblyDebuggerCtrl.h @@ -26,7 +26,14 @@ #include "AssemblyDebuggerModel.h" using AssemblyDebuggerData = std::tuple, dev::mix::QQMLMap*>; +enum DebuggingStatusResult +{ + Ok, + Compilationfailed +}; + Q_DECLARE_METATYPE(AssemblyDebuggerData) +Q_DECLARE_METATYPE(DebuggingStatusResult) namespace dev { @@ -51,10 +58,10 @@ private: public Q_SLOTS: void keyPressed(int); - void updateGUI(QList _wStates, AssemblyDebuggerData _code); + void updateGUI(bool success, DebuggingStatusResult reason, QList _wStates = QList(), AssemblyDebuggerData _code = AssemblyDebuggerData()); signals: - void dataAvailable(QList _wStates, AssemblyDebuggerData _code); + void dataAvailable(bool success, DebuggingStatusResult reason, QList _wStates = QList(), AssemblyDebuggerData _code = AssemblyDebuggerData()); }; diff --git a/mix/AssemblyDebuggerModel.cpp b/mix/AssemblyDebuggerModel.cpp index aa9795d53..bcf58835c 100644 --- a/mix/AssemblyDebuggerModel.cpp +++ b/mix/AssemblyDebuggerModel.cpp @@ -81,11 +81,11 @@ DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::by DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::u256 _value, dev::u256 _gasPrice, dev::u256 _gas, - QString code, + QString _code, KeyPair _key) { ConstantCompilationModel compiler; - CompilerResult res = compiler.compile(code); + CompilerResult res = compiler.compile(_code); if (!res.success) { DebuggingContent r; diff --git a/mix/DebuggingStateWrapper.h b/mix/DebuggingStateWrapper.h index df3b8ccce..89f90bfbd 100644 --- a/mix/DebuggingStateWrapper.h +++ b/mix/DebuggingStateWrapper.h @@ -111,7 +111,7 @@ class DebuggingStateWrapper: public QObject Q_PROPERTY(QStringList levels READ levels) public: - DebuggingStateWrapper(bytes _code, bytes _data, QObject* parent): QObject(parent), m_code(_code), m_data(_data) {} + DebuggingStateWrapper(bytes _code, bytes _data, QObject* _parent): QObject(_parent), m_code(_code), m_data(_data) {} int step() { return (int)m_state.steps; } int curPC() { return (int)m_state.curPC; } int gasCost() { return (int)m_state.gasCost; } @@ -125,7 +125,7 @@ public: QStringList levels(); DebuggingState state() { return m_state; } void setState(DebuggingState _state) { m_state = _state; } - static std::tuple, QQMLMap*> getHumanReadableCode(bytes const& code, QObject* _objUsedAsParent); + static std::tuple, QQMLMap*> getHumanReadableCode(bytes const& _code, QObject* _objUsedAsParent); private: DebuggingState m_state; diff --git a/mix/KeyEventManager.h b/mix/KeyEventManager.h index ecd768c4c..32ee5e867 100644 --- a/mix/KeyEventManager.h +++ b/mix/KeyEventManager.h @@ -30,13 +30,13 @@ class KeyEventManager: public QObject public: KeyEventManager() {} - void registerEvent(const QObject* receiver, const char* slot); - void unRegisterEvent(QObject* receiver); + void registerEvent(const QObject* _receiver, const char* _slot); + void unRegisterEvent(QObject* _receiver); signals: void onKeyPressed(int); public Q_SLOTS: - void keyPressed(QVariant event); + void keyPressed(QVariant _event); }; diff --git a/mix/TransactionBuilder.cpp b/mix/TransactionBuilder.cpp index bb7cda939..68eecf10b 100644 --- a/mix/TransactionBuilder.cpp +++ b/mix/TransactionBuilder.cpp @@ -33,8 +33,8 @@ Transaction TransactionBuilder::getCreationTransaction(u256 _value, u256 _gasPri } Transaction TransactionBuilder::getBasicTransaction(u256 _value, u256 _gasPrice, u256 _gas, - QString address, bytes _data, u256 _nonce, Secret _secret) const + QString _address, bytes _data, u256 _nonce, Secret _secret) const { - return Transaction(_value, _gasPrice, _gas, dev::fromString(address.toStdString()), _data, _nonce, _secret); + return Transaction(_value, _gasPrice, _gas, dev::fromString(_address.toStdString()), _data, _nonce, _secret); } From c014442517775c96350058d510b6c1f3d78ba9da Mon Sep 17 00:00:00 2001 From: debris Date: Mon, 8 Dec 2014 18:27:01 +0100 Subject: [PATCH 444/641] alethzero working on windows! --- alethzero/CMakeLists.txt | 5 ++--- alethzero/MainWin.cpp | 15 --------------- cmake/EthCompilerSettings.cmake | 1 + libdevcrypto/CMakeLists.txt | 2 +- mix/CMakeLists.txt | 3 +-- 5 files changed, 5 insertions(+), 21 deletions(-) diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index a1177a0a3..07500390b 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -34,11 +34,10 @@ else () add_executable(${EXECUTABLE} Main.ui ${SRC_LIST} ${HEADERS}) endif () +add_dependencies(${EXECUTABLE} BuildInfo.h) + qt5_use_modules(${EXECUTABLE} Core) target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) -#target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) -#target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_COMMON_LIBRARY}) -#target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_SERVER_LIBRARY}) target_link_libraries(${EXECUTABLE} webthree) target_link_libraries(${EXECUTABLE} qethereum) target_link_libraries(${EXECUTABLE} ethereum) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index f7ae09498..f6ecf40a1 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -2240,18 +2240,3 @@ void Main::refreshWhispers() ui->whispers->addItem(item); } } - -// extra bits needed to link on VS -#ifdef _MSC_VER - -// include moc file, ofuscated to hide from automoc -#include\ -"moc_MainWin.cpp" - -#include\ -"moc_MiningView.cpp" - -#include\ -"moc_DownloadView.cpp" - -#endif diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index ba24b62e2..d821067a8 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -19,6 +19,7 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") # specify Exception Handling Model in msvc + set(CMAKE_C_FLAGS "/EHsc") set(CMAKE_CXX_FLAGS "/EHsc") # windows likes static set(ETH_STATIC 1) diff --git a/libdevcrypto/CMakeLists.txt b/libdevcrypto/CMakeLists.txt index bf564e915..d2db758af 100644 --- a/libdevcrypto/CMakeLists.txt +++ b/libdevcrypto/CMakeLists.txt @@ -18,7 +18,7 @@ endif() target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARY_RELEASE}) target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) -target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LIBRARIES}) +target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LIBRARY}) target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} secp256k1) diff --git a/mix/CMakeLists.txt b/mix/CMakeLists.txt index aa1f8cc02..f700b0dec 100644 --- a/mix/CMakeLists.txt +++ b/mix/CMakeLists.txt @@ -34,10 +34,9 @@ else () add_executable(${EXECUTEABLE} ${SRC_LIST} ${HEADERS} ${UI_RESOURCES}) endif () -#qt5_use_modules(${EXECUTEABLE} Core Gui Widgets Network WebKit WebKitWidgets) target_link_libraries(${EXECUTEABLE} Qt5::Core) target_link_libraries(${EXECUTEABLE} Qt5::Gui) -target_link_libraries(${EXECUTEABLE} webthree qethereum ethereum evm ethcore devcrypto secp256k1 ${CRYPTOPP_LS} serpent lll solidity evmcore devcore web3jsonrpc jsqrc) +target_link_libraries(${EXECUTEABLE} webthree qethereum ethereum evm ethcore devcrypto secp256k1 serpent lll solidity evmcore devcore web3jsonrpc jsqrc) if (APPLE) # First have qt5 install plugins and frameworks From 421506a8695b39ab50743eb386c7f160f8bcf360 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 8 Dec 2014 19:49:44 +0100 Subject: [PATCH 445/641] - Coding Standards. - Q_SLOTS => slots. - https://github.com/ethereum/cpp-ethereum/issues/557 => replace by 8 spaces instead of 4. - ref to QtQuick 2.2 instead of 2.3 --- mix/AppContext.h | 1 - mix/AssemblyDebuggerCtrl.cpp | 4 ++-- mix/AssemblyDebuggerCtrl.h | 3 +-- mix/AssemblyDebuggerModel.h | 1 - mix/CodeEditorExtensionManager.cpp | 2 -- mix/CodeEditorExtensionManager.h | 1 - mix/ConstantCompilationCtrl.cpp | 2 +- mix/ConstantCompilationCtrl.h | 3 +-- mix/ConstantCompilationModel.h | 1 - mix/DebuggingStateWrapper.cpp | 1 - mix/DebuggingStateWrapper.h | 1 - mix/Extension.h | 1 - mix/KeyEventManager.h | 2 +- mix/MixApplication.h | 1 - mix/TransactionBuilder.h | 1 - mix/qml/BasicMessage.qml | 2 +- mix/qml/Debugger.qml | 2 +- mix/qml/MainContent.qml | 2 +- 18 files changed, 9 insertions(+), 22 deletions(-) diff --git a/mix/AppContext.h b/mix/AppContext.h index da7bf9a8d..0016ab3be 100644 --- a/mix/AppContext.h +++ b/mix/AppContext.h @@ -33,7 +33,6 @@ namespace dev { - namespace mix { diff --git a/mix/AssemblyDebuggerCtrl.cpp b/mix/AssemblyDebuggerCtrl.cpp index e48aa9138..18e5802af 100644 --- a/mix/AssemblyDebuggerCtrl.cpp +++ b/mix/AssemblyDebuggerCtrl.cpp @@ -58,11 +58,11 @@ void AssemblyDebuggerCtrl::start() const void AssemblyDebuggerCtrl::keyPressed(int _key) { - if (_key == Qt::Key_F5) { QString code = m_doc->toPlainText(); - QtConcurrent::run([this, code](){ + QtConcurrent::run([this, code]() + { if (!m_modelDebugger->compile(m_doc->toPlainText())) { diff --git a/mix/AssemblyDebuggerCtrl.h b/mix/AssemblyDebuggerCtrl.h index 0c092c46d..1976b2d64 100644 --- a/mix/AssemblyDebuggerCtrl.h +++ b/mix/AssemblyDebuggerCtrl.h @@ -37,7 +37,6 @@ Q_DECLARE_METATYPE(DebuggingStatusResult) namespace dev { - namespace mix { @@ -56,7 +55,7 @@ private: std::unique_ptr m_modelDebugger; QTextDocument* m_doc; -public Q_SLOTS: +public slots: void keyPressed(int); void updateGUI(bool success, DebuggingStatusResult reason, QList _wStates = QList(), AssemblyDebuggerData _code = AssemblyDebuggerData()); diff --git a/mix/AssemblyDebuggerModel.h b/mix/AssemblyDebuggerModel.h index c0941dc8f..3ed6818bc 100644 --- a/mix/AssemblyDebuggerModel.h +++ b/mix/AssemblyDebuggerModel.h @@ -28,7 +28,6 @@ namespace dev { - namespace mix { diff --git a/mix/CodeEditorExtensionManager.cpp b/mix/CodeEditorExtensionManager.cpp index 78b0f0a7f..1b2a9cc3c 100644 --- a/mix/CodeEditorExtensionManager.cpp +++ b/mix/CodeEditorExtensionManager.cpp @@ -70,9 +70,7 @@ void CodeEditorExtensionManager::initExtension(std::shared_ptr _ext) try { if (_ext->getDisplayBehavior() == ExtensionDisplayBehavior::Tab) - { _ext->addTabOn(m_tabView); - } } catch (...) { diff --git a/mix/CodeEditorExtensionManager.h b/mix/CodeEditorExtensionManager.h index 8e8501bc9..84ce9af92 100644 --- a/mix/CodeEditorExtensionManager.h +++ b/mix/CodeEditorExtensionManager.h @@ -30,7 +30,6 @@ namespace dev { - namespace mix { diff --git a/mix/ConstantCompilationCtrl.cpp b/mix/ConstantCompilationCtrl.cpp index 771387656..8b0577d93 100644 --- a/mix/ConstantCompilationCtrl.cpp +++ b/mix/ConstantCompilationCtrl.cpp @@ -59,7 +59,7 @@ void ConstantCompilationCtrl::compile() resetOutPut(); return; } - CompilerResult res = m_compilationModel->compile(m_editor->toPlainText().replace("\t", " ")); + CompilerResult res = m_compilationModel->compile(m_editor->toPlainText().replace("\t", " ")); writeOutPut(res); } diff --git a/mix/ConstantCompilationCtrl.h b/mix/ConstantCompilationCtrl.h index 446838d39..7cde63a05 100644 --- a/mix/ConstantCompilationCtrl.h +++ b/mix/ConstantCompilationCtrl.h @@ -25,7 +25,6 @@ namespace dev { - namespace mix { @@ -46,7 +45,7 @@ private: void writeOutPut(CompilerResult const&); void resetOutPut(); -public Q_SLOTS: +public slots: void compile(); }; diff --git a/mix/ConstantCompilationModel.h b/mix/ConstantCompilationModel.h index 465cba285..4c161ec09 100644 --- a/mix/ConstantCompilationModel.h +++ b/mix/ConstantCompilationModel.h @@ -27,7 +27,6 @@ namespace dev { - namespace mix { diff --git a/mix/DebuggingStateWrapper.cpp b/mix/DebuggingStateWrapper.cpp index 2dde93520..89d9892ac 100644 --- a/mix/DebuggingStateWrapper.cpp +++ b/mix/DebuggingStateWrapper.cpp @@ -90,7 +90,6 @@ QString DebuggingStateWrapper::debugMemory() QString DebuggingStateWrapper::debugCallData() { - return QString::fromStdString(memDump(m_data, 16, false)); } diff --git a/mix/DebuggingStateWrapper.h b/mix/DebuggingStateWrapper.h index 89f90bfbd..09089fe58 100644 --- a/mix/DebuggingStateWrapper.h +++ b/mix/DebuggingStateWrapper.h @@ -29,7 +29,6 @@ namespace dev { - namespace mix { diff --git a/mix/Extension.h b/mix/Extension.h index b697af58b..b6a65bb5f 100644 --- a/mix/Extension.h +++ b/mix/Extension.h @@ -24,7 +24,6 @@ namespace dev { - namespace mix { diff --git a/mix/KeyEventManager.h b/mix/KeyEventManager.h index 32ee5e867..f3343cc45 100644 --- a/mix/KeyEventManager.h +++ b/mix/KeyEventManager.h @@ -36,7 +36,7 @@ public: signals: void onKeyPressed(int); -public Q_SLOTS: +public slots: void keyPressed(QVariant _event); }; diff --git a/mix/MixApplication.h b/mix/MixApplication.h index fdc506268..d927f2e07 100644 --- a/mix/MixApplication.h +++ b/mix/MixApplication.h @@ -27,7 +27,6 @@ namespace dev { - namespace mix { diff --git a/mix/TransactionBuilder.h b/mix/TransactionBuilder.h index 99f65b024..9ad929d38 100644 --- a/mix/TransactionBuilder.h +++ b/mix/TransactionBuilder.h @@ -25,7 +25,6 @@ namespace dev { - namespace mix { diff --git a/mix/qml/BasicMessage.qml b/mix/qml/BasicMessage.qml index 14ddbcf0d..0678c9b54 100644 --- a/mix/qml/BasicMessage.qml +++ b/mix/qml/BasicMessage.qml @@ -1,4 +1,4 @@ -import QtQuick 2.3 +import QtQuick 2.2 import QtQuick.Controls.Styles 1.2 import QtQuick.Controls 1.2 import QtQuick.Dialogs 1.2 diff --git a/mix/qml/Debugger.qml b/mix/qml/Debugger.qml index 6802f57df..e895d1ada 100644 --- a/mix/qml/Debugger.qml +++ b/mix/qml/Debugger.qml @@ -1,4 +1,4 @@ -import QtQuick 2.3 +import QtQuick 2.2 import QtQuick.Controls.Styles 1.2 import QtQuick.Controls 1.2 import QtQuick.Dialogs 1.2 diff --git a/mix/qml/MainContent.qml b/mix/qml/MainContent.qml index 821b48913..1da48a1c8 100644 --- a/mix/qml/MainContent.qml +++ b/mix/qml/MainContent.qml @@ -1,4 +1,4 @@ -import QtQuick 2.3 +import QtQuick 2.2 import QtQuick.Controls 1.2 import QtQuick.Layouts 1.0 import QtQuick.Controls.Styles 1.2 From c9bf5fcd7c6fef8fba3982f853c429cbf16403cf Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 8 Dec 2014 21:32:05 +0100 Subject: [PATCH 446/641] - Instruction.h: add functions "getInstructionNumber" - AssemblyDebuggerCtrl add members AppContext, QQMLApplicationEngine --- libevmcore/Instruction.h | 18 ++++++++++++++++++ mix/AssemblyDebuggerCtrl.cpp | 12 +++++++----- mix/AssemblyDebuggerCtrl.h | 3 +++ mix/DebuggingStateWrapper.cpp | 3 ++- 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/libevmcore/Instruction.h b/libevmcore/Instruction.h index f8a0478f1..555dbf0ea 100644 --- a/libevmcore/Instruction.h +++ b/libevmcore/Instruction.h @@ -173,6 +173,24 @@ enum class Instruction: uint8_t SUICIDE = 0xff ///< halt execution and register account for later deletion }; +/// @returns the number of PUSH Instruction _inst +inline unsigned getPushNumber(Instruction _inst) +{ + return (byte)_inst - unsigned(Instruction::PUSH1) + 1; +} + +/// @returns the number of DUP Instruction _inst +inline unsigned getDupNumber(Instruction _inst) +{ + return (byte)_inst - unsigned(Instruction::DUP1) + 1; +} + +/// @returns the number of SWAP Instruction _inst +inline unsigned getSwapNumber(Instruction _inst) +{ + return (byte)_inst - unsigned(Instruction::SWAP1) + 1; +} + /// @returns the PUSH<_number> instruction inline Instruction pushInstruction(unsigned _number) { diff --git a/mix/AssemblyDebuggerCtrl.cpp b/mix/AssemblyDebuggerCtrl.cpp index 18e5802af..1fdb9403e 100644 --- a/mix/AssemblyDebuggerCtrl.cpp +++ b/mix/AssemblyDebuggerCtrl.cpp @@ -32,6 +32,8 @@ using namespace dev::mix; AssemblyDebuggerCtrl::AssemblyDebuggerCtrl(QTextDocument* _doc): Extension(ExtensionDisplayBehavior::ModalDialog) { + m_ctx = AppContext::getInstance(); + m_appEngine = m_ctx->appEngine(); qRegisterMetaType(); qRegisterMetaType(); connect(this, SIGNAL(dataAvailable(bool, DebuggingStatusResult, QList, AssemblyDebuggerData)), @@ -53,7 +55,7 @@ QString AssemblyDebuggerCtrl::title() const void AssemblyDebuggerCtrl::start() const { //start to listen on F5 - AppContext::getInstance()->getKeyEventManager()->registerEvent(this, SLOT(keyPressed(int))); + m_ctx->getKeyEventManager()->registerEvent(this, SLOT(keyPressed(int))); } void AssemblyDebuggerCtrl::keyPressed(int _key) @@ -95,11 +97,11 @@ void AssemblyDebuggerCtrl::updateGUI(bool success, DebuggingStatusResult reason, Q_UNUSED(reason); if (success) { - AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("debugStates", QVariant::fromValue(_wStates)); - AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("humanReadableExecutionCode", QVariant::fromValue(std::get<0>(_code))); - AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("bytesCodeMapping", QVariant::fromValue(std::get<1>(_code))); + m_appEngine->rootContext()->setContextProperty("debugStates", QVariant::fromValue(_wStates)); + m_appEngine->rootContext()->setContextProperty("humanReadableExecutionCode", QVariant::fromValue(std::get<0>(_code))); + m_appEngine->rootContext()->setContextProperty("bytesCodeMapping", QVariant::fromValue(std::get<1>(_code))); this->addContentOn(this); } else - AppContext::getInstance()->displayMessageDialog("debugger","compilation failed"); + m_ctx->displayMessageDialog("debugger","compilation failed"); } diff --git a/mix/AssemblyDebuggerCtrl.h b/mix/AssemblyDebuggerCtrl.h index 1976b2d64..b4957ed85 100644 --- a/mix/AssemblyDebuggerCtrl.h +++ b/mix/AssemblyDebuggerCtrl.h @@ -24,6 +24,7 @@ #include "Extension.h" #include "ConstantCompilationModel.h" #include "AssemblyDebuggerModel.h" +#include "AppContext.h" using AssemblyDebuggerData = std::tuple, dev::mix::QQMLMap*>; enum DebuggingStatusResult @@ -54,6 +55,8 @@ public: private: std::unique_ptr m_modelDebugger; QTextDocument* m_doc; + AppContext* m_ctx; + QQmlApplicationEngine* m_appEngine; public slots: void keyPressed(int); diff --git a/mix/DebuggingStateWrapper.cpp b/mix/DebuggingStateWrapper.cpp index 89d9892ac..6328cce6b 100644 --- a/mix/DebuggingStateWrapper.cpp +++ b/mix/DebuggingStateWrapper.cpp @@ -23,6 +23,7 @@ #include #include #include +#include "libevmcore/Instruction.h" #include "libdevcore/CommonJS.h" #include "libdevcrypto/Common.h" #include "libevmcore/Instruction.h" @@ -48,7 +49,7 @@ std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCod int line = i; if (b >= (byte)Instruction::PUSH1 && b <= (byte)Instruction::PUSH32) { - unsigned bc = b - (byte)Instruction::PUSH1 + 1; + unsigned bc = getPushNumber((Instruction)b); s = "PUSH 0x" + QString::fromStdString(toHex(bytesConstRef(&_code[i + 1], bc))); i += bc; } From dee70471980d59b3a8b97b677a1bd0051839984f Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 8 Dec 2014 21:56:17 +0100 Subject: [PATCH 447/641] - QQMLApplicationEngine and AppContext moved to Extension.h --- mix/AssemblyDebuggerCtrl.cpp | 2 -- mix/AssemblyDebuggerCtrl.h | 2 -- mix/DebuggingStateWrapper.cpp | 2 +- mix/Extension.cpp | 17 +++++++++++++++++ mix/Extension.h | 10 ++++++++-- 5 files changed, 26 insertions(+), 7 deletions(-) diff --git a/mix/AssemblyDebuggerCtrl.cpp b/mix/AssemblyDebuggerCtrl.cpp index 1fdb9403e..36318ccb7 100644 --- a/mix/AssemblyDebuggerCtrl.cpp +++ b/mix/AssemblyDebuggerCtrl.cpp @@ -32,8 +32,6 @@ using namespace dev::mix; AssemblyDebuggerCtrl::AssemblyDebuggerCtrl(QTextDocument* _doc): Extension(ExtensionDisplayBehavior::ModalDialog) { - m_ctx = AppContext::getInstance(); - m_appEngine = m_ctx->appEngine(); qRegisterMetaType(); qRegisterMetaType(); connect(this, SIGNAL(dataAvailable(bool, DebuggingStatusResult, QList, AssemblyDebuggerData)), diff --git a/mix/AssemblyDebuggerCtrl.h b/mix/AssemblyDebuggerCtrl.h index b4957ed85..e94cc4ce9 100644 --- a/mix/AssemblyDebuggerCtrl.h +++ b/mix/AssemblyDebuggerCtrl.h @@ -55,8 +55,6 @@ public: private: std::unique_ptr m_modelDebugger; QTextDocument* m_doc; - AppContext* m_ctx; - QQmlApplicationEngine* m_appEngine; public slots: void keyPressed(int); diff --git a/mix/DebuggingStateWrapper.cpp b/mix/DebuggingStateWrapper.cpp index 6328cce6b..2315cd5a8 100644 --- a/mix/DebuggingStateWrapper.cpp +++ b/mix/DebuggingStateWrapper.cpp @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file DebuggingStateWrapper.h +/** @file DebuggingStateWrapper.cpp * @author Yann yann@ethdev.com * @date 2014 * Used to translate c++ type (u256, bytes, ...) into friendly value (to be used by QML). diff --git a/mix/Extension.cpp b/mix/Extension.cpp index 410fe85ec..f9a8ad94d 100644 --- a/mix/Extension.cpp +++ b/mix/Extension.cpp @@ -25,6 +25,23 @@ using namespace dev; using namespace dev::mix; +Extension::Extension() +{ + init(); +} + +Extension::Extension(ExtensionDisplayBehavior _displayBehavior) +{ + init(); + m_displayBehavior = _displayBehavior; +} + +void Extension::init() +{ + m_ctx = AppContext::getInstance(); + m_appEngine = m_ctx->appEngine(); +} + void Extension::addTabOn(QObject* _view) { if (contentUrl() == "") diff --git a/mix/Extension.h b/mix/Extension.h index b6a65bb5f..4d6f4f084 100644 --- a/mix/Extension.h +++ b/mix/Extension.h @@ -21,6 +21,7 @@ #include #include +#include "AppContext.h" namespace dev { @@ -39,8 +40,8 @@ class Extension: public QObject Q_OBJECT public: - Extension() {} - Extension(ExtensionDisplayBehavior _displayBehavior) { m_displayBehavior = _displayBehavior; } + Extension(); + Extension(ExtensionDisplayBehavior _displayBehavior); virtual QString contentUrl() const { return ""; } virtual QString title() const { return ""; } virtual void start() const {} @@ -52,6 +53,11 @@ public: protected: QObject* m_view; ExtensionDisplayBehavior m_displayBehavior; + AppContext* m_ctx; + QQmlApplicationEngine* m_appEngine; + +private: + void init(); }; } From 5071446c6861757b592d54fa176b6f7497086072 Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 9 Dec 2014 00:58:02 +0100 Subject: [PATCH 448/641] msvc changes in tests, but tests not yet working there --- cmake/EthDependencies.cmake | 2 +- test/CMakeLists.txt | 36 ++++------------------------- test/jsonrpc.cpp | 5 +++- test/solidityEndToEndTest.cpp | 35 ++++++++++++++-------------- test/solidityExpressionCompiler.cpp | 3 +++ test/solidityJSONInterfaceTest.cpp | 2 +- test/solidityNatspecJSON.cpp | 2 +- 7 files changed, 33 insertions(+), 52 deletions(-) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 8a86e7095..fb2aafd47 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -90,7 +90,7 @@ if (${CMAKE_CXX_COMPILER_ID} MATCHES "MSVC") set(Boost_COMPILER -vc120) endif() -find_package(Boost 1.55.0 REQUIRED COMPONENTS thread date_time system regex chrono filesystem) +find_package(Boost 1.55.0 REQUIRED COMPONENTS thread date_time system regex chrono filesystem unit_test_framework) message(" - boost header: ${Boost_INCLUDE_DIRS}") message(" - boost lib : ${Boost_LIBRARIES}") diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 59eb34bc8..e27e0949d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -3,53 +3,27 @@ cmake_policy(SET CMP0015 NEW) aux_source_directory(. SRC_LIST) list(REMOVE_ITEM SRC_LIST "./createRandomTest.cpp") -include_directories(..) include_directories(${CRYPTOPP_INCLUDE_DIRS}) include_directories(${JSONCPP_INCLUDE_DIRS}) +include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) +include_directories(..) file(GLOB HEADERS "*.h") add_executable(testeth ${SRC_LIST} ${HEADERS}) add_executable(createRandomTest createRandomTest.cpp vm.cpp TestHelper.cpp) - target_link_libraries(testeth ethereum) target_link_libraries(testeth ethcore) target_link_libraries(testeth secp256k1) -target_link_libraries(testeth gmp) target_link_libraries(testeth solidity) target_link_libraries(testeth webthree) +target_link_libraries(testeth ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY_RELEASE}) -target_link_libraries(testeth ${CRYPTOPP_LIBRARIES}) - -if(JSON_RPC_CPP_FOUND) - target_link_libraries(testeth ${JSONCPP_LIBRARIES}) +if (JSON_RPC_CPP_FOUND) target_link_libraries(testeth web3jsonrpc) target_link_libraries(testeth ${JSON_RPC_CPP_CLIENT_LIBRARY}) endif() target_link_libraries(createRandomTest ethereum) target_link_libraries(createRandomTest ethcore) -target_link_libraries(createRandomTest boost_chrono) -target_link_libraries(createRandomTest boost_unit_test_framework) -target_link_libraries(createRandomTest ${CRYPTOPP_LIBRARIES}) - -if ("${TARGET_PLATFORM}" STREQUAL "w64") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") - target_link_libraries(testeth boost_system-mt-s) - target_link_libraries(testeth boost_filesystem-mt-s) - target_link_libraries(testeth boost_thread_win32-mt-s) - target_link_libraries(testeth gcc) - target_link_libraries(testeth gdi32) - target_link_libraries(testeth ws2_32) - target_link_libraries(testeth mswsock) - target_link_libraries(testeth shlwapi) - target_link_libraries(testeth iphlpapi) - set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) -elseif (UNIX) - find_package(Boost 1.53 REQUIRED COMPONENTS unit_test_framework) -else () - target_link_libraries(testeth boost_system) - target_link_libraries(testeth boost_filesystem) - find_package(Threads REQUIRED) - target_link_libraries(testeth ${CMAKE_THREAD_LIBS_INIT}) -endif () +target_link_libraries(createRandomTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY_RELEASE}) diff --git a/test/jsonrpc.cpp b/test/jsonrpc.cpp index 3c1725388..5a9b94ebc 100644 --- a/test/jsonrpc.cpp +++ b/test/jsonrpc.cpp @@ -62,7 +62,7 @@ struct Setup web3->setIdealPeerCount(5); web3->ethereum()->setForceMining(true); - auto server = new jsonrpc::CorsHttpServer(8080); + auto server = new jsonrpc::HttpServer(8080); jsonrpcServer = unique_ptr(new WebThreeStubServer(*server, *web3, {})); jsonrpcServer->setIdentities({}); jsonrpcServer->StartListening(); @@ -302,8 +302,11 @@ BOOST_AUTO_TEST_CASE(contract_storage) Json::Value storage = jsonrpcClient->eth_storageAt(contractAddress); BOOST_CHECK_EQUAL(storage.getMemberNames().size(), 1); + // bracers are required, cause msvc couldnt handle this macro in for statement for (auto name: storage.getMemberNames()) + { BOOST_CHECK_EQUAL(storage[name].asString(), "0x03"); + } } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/solidityEndToEndTest.cpp b/test/solidityEndToEndTest.cpp index 9e02438e8..1ea9fe351 100644 --- a/test/solidityEndToEndTest.cpp +++ b/test/solidityEndToEndTest.cpp @@ -519,22 +519,23 @@ BOOST_AUTO_TEST_CASE(simple_mapping) " }\n" "}"; compileAndRun(sourceCode); - - BOOST_CHECK(callContractFunction(0, bytes({0x00})) == bytes({0x00})); - BOOST_CHECK(callContractFunction(0, bytes({0x01})) == bytes({0x00})); - BOOST_CHECK(callContractFunction(0, bytes({0xa7})) == bytes({0x00})); + + // msvc seems to have problems with initializer-list, when there is only 1 param in the list + BOOST_CHECK(callContractFunction(0, bytes(1, 0x00)) == bytes(1, 0x00)); + BOOST_CHECK(callContractFunction(0, bytes(1, 0x01)) == bytes(1, 0x00)); + BOOST_CHECK(callContractFunction(0, bytes(1, 0xa7)) == bytes(1, 0x00)); callContractFunction(1, bytes({0x01, 0xa1})); - BOOST_CHECK(callContractFunction(0, bytes({0x00})) == bytes({0x00})); - BOOST_CHECK(callContractFunction(0, bytes({0x01})) == bytes({0xa1})); - BOOST_CHECK(callContractFunction(0, bytes({0xa7})) == bytes({0x00})); + BOOST_CHECK(callContractFunction(0, bytes(1, 0x00)) == bytes(1, 0x00)); + BOOST_CHECK(callContractFunction(0, bytes(1, 0x01)) == bytes(1, 0xa1)); + BOOST_CHECK(callContractFunction(0, bytes(1, 0xa7)) == bytes(1, 0x00)); callContractFunction(1, bytes({0x00, 0xef})); - BOOST_CHECK(callContractFunction(0, bytes({0x00})) == bytes({0xef})); - BOOST_CHECK(callContractFunction(0, bytes({0x01})) == bytes({0xa1})); - BOOST_CHECK(callContractFunction(0, bytes({0xa7})) == bytes({0x00})); + BOOST_CHECK(callContractFunction(0, bytes(1, 0x00)) == bytes(1, 0xef)); + BOOST_CHECK(callContractFunction(0, bytes(1, 0x01)) == bytes(1, 0xa1)); + BOOST_CHECK(callContractFunction(0, bytes(1, 0xa7)) == bytes(1, 0x00)); callContractFunction(1, bytes({0x01, 0x05})); - BOOST_CHECK(callContractFunction(0, bytes({0x00})) == bytes({0xef})); - BOOST_CHECK(callContractFunction(0, bytes({0x01})) == bytes({0x05})); - BOOST_CHECK(callContractFunction(0, bytes({0xa7})) == bytes({0x00})); + BOOST_CHECK(callContractFunction(0, bytes(1, 0x00)) == bytes(1, 0xef)); + BOOST_CHECK(callContractFunction(0, bytes(1, 0x01)) == bytes(1, 0x05)); + BOOST_CHECK(callContractFunction(0, bytes(1, 0xa7)) == bytes(1, 0x00)); } BOOST_AUTO_TEST_CASE(mapping_state) @@ -702,9 +703,9 @@ BOOST_AUTO_TEST_CASE(structs) " }\n" "}\n"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction(0) == bytes({0x00})); + BOOST_CHECK(callContractFunction(0) == bytes(1, 0x00)); BOOST_CHECK(callContractFunction(1) == bytes()); - BOOST_CHECK(callContractFunction(0) == bytes({0x01})); + BOOST_CHECK(callContractFunction(0) == bytes(1, 0x01)); } BOOST_AUTO_TEST_CASE(struct_reference) @@ -730,9 +731,9 @@ BOOST_AUTO_TEST_CASE(struct_reference) " }\n" "}\n"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction(0) == bytes({0x00})); + BOOST_CHECK(callContractFunction(0) == bytes(1, 0x00)); BOOST_CHECK(callContractFunction(1) == bytes()); - BOOST_CHECK(callContractFunction(0) == bytes({0x01})); + BOOST_CHECK(callContractFunction(0) == bytes(1, 0x01)); } BOOST_AUTO_TEST_CASE(constructor) diff --git a/test/solidityExpressionCompiler.cpp b/test/solidityExpressionCompiler.cpp index 486b46ebb..c05db25d4 100644 --- a/test/solidityExpressionCompiler.cpp +++ b/test/solidityExpressionCompiler.cpp @@ -76,8 +76,11 @@ Declaration const& resolveDeclaration(vector const& _namespacedName, NameAndTypeResolver const& _resolver) { Declaration const* declaration = nullptr; + // bracers are required, cause msvc couldnt handle this macro in for statement for (string const& namePart: _namespacedName) + { BOOST_REQUIRE(declaration = _resolver.resolveName(namePart, declaration)); + } BOOST_REQUIRE(declaration); return *declaration; } diff --git a/test/solidityJSONInterfaceTest.cpp b/test/solidityJSONInterfaceTest.cpp index 487508bb9..c734009c3 100644 --- a/test/solidityJSONInterfaceTest.cpp +++ b/test/solidityJSONInterfaceTest.cpp @@ -22,7 +22,7 @@ #include #include -#include +#include #include namespace dev diff --git a/test/solidityNatspecJSON.cpp b/test/solidityNatspecJSON.cpp index f1795fe1c..d66d1294f 100644 --- a/test/solidityNatspecJSON.cpp +++ b/test/solidityNatspecJSON.cpp @@ -22,7 +22,7 @@ #include #include -#include +#include #include namespace dev From 49063af0494cc34dfe7393b1620f24b04061ef5a Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 9 Dec 2014 01:03:55 +0100 Subject: [PATCH 449/641] common changes in mix --- mix/CMakeLists.txt | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/mix/CMakeLists.txt b/mix/CMakeLists.txt index f700b0dec..bdb682a09 100644 --- a/mix/CMakeLists.txt +++ b/mix/CMakeLists.txt @@ -36,7 +36,20 @@ endif () target_link_libraries(${EXECUTEABLE} Qt5::Core) target_link_libraries(${EXECUTEABLE} Qt5::Gui) -target_link_libraries(${EXECUTEABLE} webthree qethereum ethereum evm ethcore devcrypto secp256k1 serpent lll solidity evmcore devcore web3jsonrpc jsqrc) +target_link_libraries(${EXECUTEABLE} webthree) +target_link_libraries(${EXECUTEABLE} qethereum) +target_link_libraries(${EXECUTEABLE} ethereum) +target_link_libraries(${EXECUTEABLE} evm) +target_link_libraries(${EXECUTEABLE} ethcore) +target_link_libraries(${EXECUTEABLE} devcrypto) +target_link_libraries(${EXECUTEABLE} secp256k1) +target_link_libraries(${EXECUTEABLE} serpent) +target_link_libraries(${EXECUTEABLE} lll) +target_link_libraries(${EXECUTEABLE} solidity) +target_link_libraries(${EXECUTEABLE} evmcore) +target_link_libraries(${EXECUTEABLE} devcore) +target_link_libraries(${EXECUTEABLE} web3jsonrpc) +target_link_libraries(${EXECUTEABLE} jsqrc) if (APPLE) # First have qt5 install plugins and frameworks From dbb724da9f331a9539427a93f4c055abcafcc887 Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 9 Dec 2014 01:05:37 +0100 Subject: [PATCH 450/641] removed windows dir --- windows/.gitattributes | 2 - windows/Alethzero.vcxproj | 311 --- windows/Alethzero.vcxproj.filters | 37 - windows/BuildInfo.lua | 25 - windows/Eth.vcxproj | 195 -- windows/Ethereum.sln | 191 -- windows/Ethereum.vcxproj.filters | 16 - windows/Exp.vcxproj | 195 -- windows/LibCryptoPP.vcxproj | 414 --- windows/LibEthereum.props | 35 - windows/LibEthereum.vcxproj | 571 ----- windows/LibEthereum.vcxproj.filters | 477 ---- windows/LibEthereum_Debug.props | 18 - windows/LibEthereum_Release.props | 14 - windows/LibLevelDB.vcxproj | 221 -- windows/LibLevelDB.vcxproj.filters | 246 -- windows/LibMiniUPnPc.vcxproj | 182 -- windows/LibQEthereum.props | 70 - windows/LibQEthereum.vcxproj | 204 -- windows/LibQEthereum.vcxproj.filters | 24 - windows/LibSecp256k1.vcxproj | 183 -- windows/LibSecp256k1.vcxproj.filters | 71 - windows/LibSerpent.vcxproj | 187 -- windows/LibSerpent.vcxproj.filters | 18 - windows/Lllc.vcxproj | 195 -- windows/Neth.vcxproj | 213 -- windows/Sc.vcxproj | 198 -- windows/TestEthereum.vcxproj | 194 -- windows/TestEthereum.vcxproj.filters | 38 - windows/TestSecp256k1.vcxproj | 171 -- windows/Walleth.vcxproj | 315 --- windows/Walleth.vcxproj.filters | 34 - windows/WinMain.cpp | 72 - windows/bootstrap.sh | 233 -- windows/compile_ethereum.bat | 14 - windows/compile_icu.bat | 11 - windows/compile_qt.bat | 51 - windows/include/LibLevelDB/port/port.h | 23 - windows/include/LibLevelDB/unistd.h | 0 .../include/LibMiniUPnPc/miniupnpcstrings.h | 14 - windows/moc.lua | 38 - windows/ncurses/include/ncurses/curses.h | 1675 ------------ windows/ncurses/include/ncurses/cursesapp.h | 176 -- windows/ncurses/include/ncurses/cursesf.h | 967 ------- windows/ncurses/include/ncurses/cursesm.h | 672 ----- windows/ncurses/include/ncurses/cursesp.h | 268 -- windows/ncurses/include/ncurses/cursesw.h | 1556 ----------- windows/ncurses/include/ncurses/cursslk.h | 238 -- windows/ncurses/include/ncurses/eti.h | 54 - windows/ncurses/include/ncurses/etip.h | 378 --- windows/ncurses/include/ncurses/form.h | 422 --- windows/ncurses/include/ncurses/menu.h | 260 -- windows/ncurses/include/ncurses/nc_tparm.h | 73 - windows/ncurses/include/ncurses/ncurses.h | 1675 ------------ windows/ncurses/include/ncurses/ncurses_dll.h | 86 - windows/ncurses/include/ncurses/panel.h | 85 - windows/ncurses/include/ncurses/term.h | 834 ------ windows/ncurses/include/ncurses/term_entry.h | 174 -- windows/ncurses/include/ncurses/termcap.h | 75 - windows/ncurses/include/ncurses/tic.h | 346 --- windows/ncurses/include/ncurses/unctrl.h | 67 - windows/ncurses/lib/Win32/libgcc_s_sjlj-1.dll | Bin 88085 -> 0 bytes windows/ncurses/lib/Win32/wform.dll | Bin 150757 -> 0 bytes windows/ncurses/lib/Win32/wform.lib | Bin 20764 -> 0 bytes windows/ncurses/lib/Win32/wmenu.dll | Bin 59968 -> 0 bytes windows/ncurses/lib/Win32/wmenu.lib | Bin 17014 -> 0 bytes windows/ncurses/lib/Win32/wncurses.dll | Bin 432882 -> 0 bytes windows/ncurses/lib/Win32/wncurses.lib | Bin 123366 -> 0 bytes windows/ncurses/lib/Win32/wpanel.dll | Bin 40517 -> 0 bytes windows/ncurses/lib/Win32/wpanel.lib | Bin 5050 -> 0 bytes windows/ncurses/lib/x64/wform.dll | Bin 164906 -> 0 bytes windows/ncurses/lib/x64/wform.lib | Bin 20002 -> 0 bytes windows/ncurses/lib/x64/wmenu.dll | Bin 67812 -> 0 bytes windows/ncurses/lib/x64/wmenu.lib | Bin 16184 -> 0 bytes windows/ncurses/lib/x64/wncurses.dll | Bin 470191 -> 0 bytes windows/ncurses/lib/x64/wncurses.lib | Bin 120128 -> 0 bytes windows/ncurses/lib/x64/wpanel.dll | Bin 45915 -> 0 bytes windows/ncurses/lib/x64/wpanel.lib | Bin 4828 -> 0 bytes .../icu/0001-Upgrade-projects-to-VS2013.patch | 2279 ----------------- ...0002-Qt-requires-U_CHARSET_IS_UTF8-1.patch | 26 - .../icu/0003-Add-minimal-icu.sln.patch | 71 - windows/qt_plugin_import.cpp | 4 - windows/stdafx.cpp | 21 - windows/stdafx.h | 60 - 84 files changed, 18263 deletions(-) delete mode 100644 windows/.gitattributes delete mode 100644 windows/Alethzero.vcxproj delete mode 100644 windows/Alethzero.vcxproj.filters delete mode 100644 windows/BuildInfo.lua delete mode 100644 windows/Eth.vcxproj delete mode 100644 windows/Ethereum.sln delete mode 100644 windows/Ethereum.vcxproj.filters delete mode 100644 windows/Exp.vcxproj delete mode 100644 windows/LibCryptoPP.vcxproj delete mode 100644 windows/LibEthereum.props delete mode 100644 windows/LibEthereum.vcxproj delete mode 100644 windows/LibEthereum.vcxproj.filters delete mode 100644 windows/LibEthereum_Debug.props delete mode 100644 windows/LibEthereum_Release.props delete mode 100644 windows/LibLevelDB.vcxproj delete mode 100644 windows/LibLevelDB.vcxproj.filters delete mode 100644 windows/LibMiniUPnPc.vcxproj delete mode 100644 windows/LibQEthereum.props delete mode 100644 windows/LibQEthereum.vcxproj delete mode 100644 windows/LibQEthereum.vcxproj.filters delete mode 100644 windows/LibSecp256k1.vcxproj delete mode 100644 windows/LibSecp256k1.vcxproj.filters delete mode 100644 windows/LibSerpent.vcxproj delete mode 100644 windows/LibSerpent.vcxproj.filters delete mode 100644 windows/Lllc.vcxproj delete mode 100644 windows/Neth.vcxproj delete mode 100644 windows/Sc.vcxproj delete mode 100644 windows/TestEthereum.vcxproj delete mode 100644 windows/TestEthereum.vcxproj.filters delete mode 100644 windows/TestSecp256k1.vcxproj delete mode 100644 windows/Walleth.vcxproj delete mode 100644 windows/Walleth.vcxproj.filters delete mode 100644 windows/WinMain.cpp delete mode 100644 windows/bootstrap.sh delete mode 100644 windows/compile_ethereum.bat delete mode 100644 windows/compile_icu.bat delete mode 100644 windows/compile_qt.bat delete mode 100644 windows/include/LibLevelDB/port/port.h delete mode 100644 windows/include/LibLevelDB/unistd.h delete mode 100644 windows/include/LibMiniUPnPc/miniupnpcstrings.h delete mode 100644 windows/moc.lua delete mode 100644 windows/ncurses/include/ncurses/curses.h delete mode 100644 windows/ncurses/include/ncurses/cursesapp.h delete mode 100644 windows/ncurses/include/ncurses/cursesf.h delete mode 100644 windows/ncurses/include/ncurses/cursesm.h delete mode 100644 windows/ncurses/include/ncurses/cursesp.h delete mode 100644 windows/ncurses/include/ncurses/cursesw.h delete mode 100644 windows/ncurses/include/ncurses/cursslk.h delete mode 100644 windows/ncurses/include/ncurses/eti.h delete mode 100644 windows/ncurses/include/ncurses/etip.h delete mode 100644 windows/ncurses/include/ncurses/form.h delete mode 100644 windows/ncurses/include/ncurses/menu.h delete mode 100644 windows/ncurses/include/ncurses/nc_tparm.h delete mode 100644 windows/ncurses/include/ncurses/ncurses.h delete mode 100644 windows/ncurses/include/ncurses/ncurses_dll.h delete mode 100644 windows/ncurses/include/ncurses/panel.h delete mode 100644 windows/ncurses/include/ncurses/term.h delete mode 100644 windows/ncurses/include/ncurses/term_entry.h delete mode 100644 windows/ncurses/include/ncurses/termcap.h delete mode 100644 windows/ncurses/include/ncurses/tic.h delete mode 100644 windows/ncurses/include/ncurses/unctrl.h delete mode 100644 windows/ncurses/lib/Win32/libgcc_s_sjlj-1.dll delete mode 100644 windows/ncurses/lib/Win32/wform.dll delete mode 100644 windows/ncurses/lib/Win32/wform.lib delete mode 100644 windows/ncurses/lib/Win32/wmenu.dll delete mode 100644 windows/ncurses/lib/Win32/wmenu.lib delete mode 100644 windows/ncurses/lib/Win32/wncurses.dll delete mode 100644 windows/ncurses/lib/Win32/wncurses.lib delete mode 100644 windows/ncurses/lib/Win32/wpanel.dll delete mode 100644 windows/ncurses/lib/Win32/wpanel.lib delete mode 100644 windows/ncurses/lib/x64/wform.dll delete mode 100644 windows/ncurses/lib/x64/wform.lib delete mode 100644 windows/ncurses/lib/x64/wmenu.dll delete mode 100644 windows/ncurses/lib/x64/wmenu.lib delete mode 100644 windows/ncurses/lib/x64/wncurses.dll delete mode 100644 windows/ncurses/lib/x64/wncurses.lib delete mode 100644 windows/ncurses/lib/x64/wpanel.dll delete mode 100644 windows/ncurses/lib/x64/wpanel.lib delete mode 100644 windows/patches/icu/0001-Upgrade-projects-to-VS2013.patch delete mode 100644 windows/patches/icu/0002-Qt-requires-U_CHARSET_IS_UTF8-1.patch delete mode 100644 windows/patches/icu/0003-Add-minimal-icu.sln.patch delete mode 100644 windows/qt_plugin_import.cpp delete mode 100644 windows/stdafx.cpp delete mode 100644 windows/stdafx.h diff --git a/windows/.gitattributes b/windows/.gitattributes deleted file mode 100644 index 48910107d..000000000 --- a/windows/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -*.vcxproj eol=crlf -*.props eol=crlf diff --git a/windows/Alethzero.vcxproj b/windows/Alethzero.vcxproj deleted file mode 100644 index 38dbd6265..000000000 --- a/windows/Alethzero.vcxproj +++ /dev/null @@ -1,311 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - Win32Proj - AlethZero - AlethZero - {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD} - - - - Application - true - v120 - - - Application - true - v120 - - - Application - false - v120 - - - Application - false - v120 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - - - - false - - - false - - - - Use - Disabled - WIN32;_WINSOCK_DEPRECATED_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - true - stdafx.h - - - Windows - true - true - - - - - - - - - Use - Disabled - WIN32;_DEBUG;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - true - stdafx.h - - - Windows - true - - - - - - - - - Use - MaxSpeed - true - true - WIN32;_WINSOCK_DEPRECATED_NO_WARNINGS;NDEBUG;%(PreprocessorDefinitions) - MultiThreadedDLL - true - AnySuitable - stdafx.h - - - Windows - true - true - true - true - - - - - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;%(PreprocessorDefinitions) - MultiThreadedDLL - true - AnySuitable - stdafx.h - - - Windows - true - true - true - - - - - - - - - {df3c5b07-a1a2-4f16-b37f-a27333622cdd} - - - {f174e81a-2a66-4693-b917-11bb42d3658c} - - - - - - - - - - Create - Create - Create - Create - - - - - - $(Lua) moc.lua "$(QtBin)/moc" "$(IntDir)moc_%(FileName).cpp" "@(ClCompile->'%(AdditionalIncludeDirectories)');$(IncludePath)" "@(ClCompile->'%(PreprocessorDefinitions)');_MSC_VER=1800" "%(FullPath)" - $(IntDir)moc_%(FileName).cpp - - - $(Lua) moc.lua "$(QtBin)/moc" "$(IntDir)moc_%(FileName).cpp" "@(ClCompile->'%(AdditionalIncludeDirectories)');$(IncludePath)" "@(ClCompile->'%(PreprocessorDefinitions)');_MSC_VER=1800" "%(FullPath)" - - - $(Lua) moc.lua "$(QtBin)/moc" "$(IntDir)moc_%(FileName).cpp" "@(ClCompile->'%(AdditionalIncludeDirectories)');$(IncludePath)" "@(ClCompile->'%(PreprocessorDefinitions)');_MSC_VER=1800" "%(FullPath)" - - - $(Lua) moc.lua "$(QtBin)/moc" "$(IntDir)moc_%(FileName).cpp" "@(ClCompile->'%(AdditionalIncludeDirectories)');$(IncludePath)" "@(ClCompile->'%(PreprocessorDefinitions)');_MSC_VER=1800" "%(FullPath)" - - - $(IntDir)moc_%(FileName).cpp - $(IntDir)moc_%(FileName).cpp - $(IntDir)moc_%(FileName).cpp - - - - - $(Lua) moc.lua "$(QtBin)/moc" "$(IntDir)moc_%(FileName).cpp" "@(ClCompile->'%(AdditionalIncludeDirectories)');$(IncludePath)" "@(ClCompile->'%(PreprocessorDefinitions)');_MSC_VER=1800" "%(FullPath)" - - - $(Lua) moc.lua "$(QtBin)/moc" "$(IntDir)moc_%(FileName).cpp" "@(ClCompile->'%(AdditionalIncludeDirectories)');$(IncludePath)" "@(ClCompile->'%(PreprocessorDefinitions)');_MSC_VER=1800" "%(FullPath)" - - - $(Lua) moc.lua "$(QtBin)/moc" "$(IntDir)moc_%(FileName).cpp" "@(ClCompile->'%(AdditionalIncludeDirectories)');$(IncludePath)" "@(ClCompile->'%(PreprocessorDefinitions)');_MSC_VER=1800" "%(FullPath)" - - - $(Lua) moc.lua "$(QtBin)/moc" "$(IntDir)moc_%(FileName).cpp" "@(ClCompile->'%(AdditionalIncludeDirectories)');$(IncludePath)" "@(ClCompile->'%(PreprocessorDefinitions)');_MSC_VER=1800" "%(FullPath)" - - - $(IntDir)moc_%(FileName).cpp - $(IntDir)moc_%(FileName).cpp - $(IntDir)moc_%(FileName).cpp - $(IntDir)moc_%(FileName).cpp - - - $(Lua) moc.lua "$(QtBin)/moc" "$(IntDir)moc_%(FileName).cpp" "@(ClCompile->'%(AdditionalIncludeDirectories)');$(IncludePath)" "@(ClCompile->'%(PreprocessorDefinitions)');_MSC_VER=1800" "%(FullPath)" - - - $(Lua) moc.lua "$(QtBin)/moc" "$(IntDir)moc_%(FileName).cpp" "@(ClCompile->'%(AdditionalIncludeDirectories)');$(IncludePath)" "@(ClCompile->'%(PreprocessorDefinitions)');_MSC_VER=1800" "%(FullPath)" - - - $(Lua) moc.lua "$(QtBin)/moc" "$(IntDir)moc_%(FileName).cpp" "@(ClCompile->'%(AdditionalIncludeDirectories)');$(IncludePath)" "@(ClCompile->'%(PreprocessorDefinitions)');_MSC_VER=1800" "%(FullPath)" - - - $(Lua) moc.lua "$(QtBin)/moc" "$(IntDir)moc_%(FileName).cpp" "@(ClCompile->'%(AdditionalIncludeDirectories)');$(IncludePath)" "@(ClCompile->'%(PreprocessorDefinitions)');_MSC_VER=1800" "%(FullPath)" - - - $(IntDir)moc_%(FileName).cpp - $(IntDir)moc_%(FileName).cpp - $(IntDir)moc_%(FileName).cpp - $(IntDir)moc_%(FileName).cpp - - - - - - Document - "$(QtBin)/uic" -o "$(IntDir)ui_%(FileName).h" "%(FullPath)" - "$(QtBin)/uic" -o "$(IntDir)ui_%(FileName).h" "%(FullPath)" - $(IntDir)ui_%(FileName).h - "$(QtBin)/uic" -o "$(IntDir)ui_%(FileName).h" "%(FullPath)" - "$(QtBin)/uic" -o "$(IntDir)ui_%(FileName).h" "%(FullPath)" - $(IntDir)ui_%(FileName).h - "$(QtBin)/uic" -o "$(IntDir)ui_%(FileName).h" "%(FullPath)" - "$(QtBin)/uic" -o "$(IntDir)ui_%(FileName).h" "%(FullPath)" - $(IntDir)ui_%(FileName).h - "$(QtBin)/uic" -o "$(IntDir)ui_%(FileName).h" "%(FullPath)" - "$(QtBin)/uic" -o "$(IntDir)ui_%(FileName).h" "%(FullPath)" - $(IntDir)ui_%(FileName).h - - - - - Document - $(Lua) "%(FullPath)" "$(IntDir)%(FileName).h" - - - $(Lua) "%(FullPath)" "$(IntDir)%(FileName).h" - - - $(Lua) "%(FullPath)" "$(IntDir)%(FileName).h" - - - $(Lua) "%(FullPath)" "$(IntDir)%(FileName).h" - - - $(IntDir)%(FileName).h - $(IntDir)%(FileName).h - $(IntDir)%(FileName).h - $(IntDir)%(FileName).h - ../.git/index - ../.git/index - ../.git/index - ../.git/index - - - - - - - - - - - - - $(BuildDependsOn);FinalCopy - - - - - - - - \ No newline at end of file diff --git a/windows/Alethzero.vcxproj.filters b/windows/Alethzero.vcxproj.filters deleted file mode 100644 index ef47bdba0..000000000 --- a/windows/Alethzero.vcxproj.filters +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - Windows - - - Windows - - - - - - - - Windows - - - - - - - {049fb46c-1677-45cb-95ae-3a2d9e3090be} - - - - - - - Windows - - - - - \ No newline at end of file diff --git a/windows/BuildInfo.lua b/windows/BuildInfo.lua deleted file mode 100644 index 47b23a795..000000000 --- a/windows/BuildInfo.lua +++ /dev/null @@ -1,25 +0,0 @@ - -function os.capture(cmd) - local f = io.popen(cmd, 'r') - if (f) then - local s = f:read('*a') - if (f:close()) then - return s - end - end - return nil -end - -hash = (os.capture("git rev-parse HEAD") or "UnknownRevision"):gsub("\n$", "") -clean = ((os.capture("git diff --name-only") or "0"):gsub("\n$", "") == "") and "1" or "0" - -local output = io.open(arg[1], "w") -if (output) then - output:write("// This file was automatically generated by buildinfo.lua\n#pragma once\n\n") - output:write("#define ETH_COMMIT_HASH "..hash.."\n") - output:write("#define ETH_CLEAN_REPO "..clean.."\n") - output:close() -end - - - diff --git a/windows/Eth.vcxproj b/windows/Eth.vcxproj deleted file mode 100644 index 9b2d47727..000000000 --- a/windows/Eth.vcxproj +++ /dev/null @@ -1,195 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - Win32Proj - Ethereum - eth - {C60C065C-2135-4B2B-AFD4-35FD7AC56B40} - - - - Application - true - v120 - - - Application - true - v120 - - - Application - false - v120 - - - Application - false - v120 - - - - - - - - - - - - - - - - - - - - - - - - - - - true - - - - false - - - false - - - - - - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - true - - - Console - true - true - - - - - - - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - true - - - Console - true - - - - - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true - AnySuitable - - - Console - true - true - true - true - - - - - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true - AnySuitable - - - Console - true - true - true - - - - - {826e68cb-d3ee-4a8a-b540-59a8c3f38d4f} - - - - - - - - Document - $(Lua) "%(FullPath)" "$(IntDir)%(FileName).h" - - - $(IntDir)%(FileName).h - $(Lua) "%(FullPath)" "$(IntDir)%(FileName).h" - - - $(IntDir)%(FileName).h - $(Lua) "%(FullPath)" "$(IntDir)%(FileName).h" - - - $(IntDir)%(FileName).h - $(Lua) "%(FullPath)" "$(IntDir)%(FileName).h" - - - $(IntDir)%(FileName).h - ../.git/index - ../.git/index - ../.git/index - ../.git/index - - - - - - - $(BuildDependsOn);FinalCopy - - - - - - - - \ No newline at end of file diff --git a/windows/Ethereum.sln b/windows/Ethereum.sln deleted file mode 100644 index 26fe794c2..000000000 --- a/windows/Ethereum.sln +++ /dev/null @@ -1,191 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Express 2013 for Windows Desktop -VisualStudioVersion = 12.0.21005.1 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libs", "Libs", "{988F2383-FA1D-408B-BCF6-C0EE7AB0A560}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{6838FA95-01BF-4FF7-914C-FC209B81406E}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibEthereum", "LibEthereum.vcxproj", "{826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibLevelDB", "LibLevelDB.vcxproj", "{27014763-955D-486B-9BA7-69872192E6F4}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibSecp256k1", "LibSecp256k1.vcxproj", "{1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestSecp256k1", "TestSecp256k1.vcxproj", "{3BF049F8-AF7E-4E1C-9627-3E94C887AF24}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestEthereum", "TestEthereum.vcxproj", "{3F3E389B-88DE-41D5-A73B-4F6036E18B36}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibCryptoPP", "LibCryptoPP.vcxproj", "{1CC213A4-3482-4211-B47B-172E90DAC7DE}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibMiniUPnPc", "LibMiniUPnPc.vcxproj", "{1B1CA20E-39C3-4D9B-AC37-3783048E6672}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AlethZero", "Alethzero.vcxproj", "{BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibQEthereum", "LibQEthereum.vcxproj", "{DF3C5B07-A1A2-4F16-B37F-A27333622CDD}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "eth", "Eth.vcxproj", "{C60C065C-2135-4B2B-AFD4-35FD7AC56B40}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "neth", "Neth.vcxproj", "{90C70663-7181-4E99-9079-54188CEB8954}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibSerpent", "LibSerpent.vcxproj", "{F174E81A-2A66-4693-B917-11BB42D3658C}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "exp", "Exp.vcxproj", "{9AA5CF66-1150-4A02-B40E-3B89740DADB8}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sc", "Sc.vcxproj", "{90068D1B-070E-4C41-88B0-1E243E1E5BFF}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lllc", "Lllc.vcxproj", "{255BDC68-B8DB-465F-8220-981E77684189}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|Win32.ActiveCfg = Debug|Win32 - {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|Win32.Build.0 = Debug|Win32 - {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|x64.ActiveCfg = Debug|x64 - {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|x64.Build.0 = Debug|x64 - {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|Win32.ActiveCfg = Release|Win32 - {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|Win32.Build.0 = Release|Win32 - {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|x64.ActiveCfg = Release|x64 - {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|x64.Build.0 = Release|x64 - {27014763-955D-486B-9BA7-69872192E6F4}.Debug|Win32.ActiveCfg = Debug|Win32 - {27014763-955D-486B-9BA7-69872192E6F4}.Debug|Win32.Build.0 = Debug|Win32 - {27014763-955D-486B-9BA7-69872192E6F4}.Debug|x64.ActiveCfg = Debug|x64 - {27014763-955D-486B-9BA7-69872192E6F4}.Debug|x64.Build.0 = Debug|x64 - {27014763-955D-486B-9BA7-69872192E6F4}.Release|Win32.ActiveCfg = Release|Win32 - {27014763-955D-486B-9BA7-69872192E6F4}.Release|Win32.Build.0 = Release|Win32 - {27014763-955D-486B-9BA7-69872192E6F4}.Release|x64.ActiveCfg = Release|x64 - {27014763-955D-486B-9BA7-69872192E6F4}.Release|x64.Build.0 = Release|x64 - {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|Win32.ActiveCfg = Debug|Win32 - {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|Win32.Build.0 = Debug|Win32 - {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|x64.ActiveCfg = Debug|x64 - {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|x64.Build.0 = Debug|x64 - {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|Win32.ActiveCfg = Release|Win32 - {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|Win32.Build.0 = Release|Win32 - {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|x64.ActiveCfg = Release|x64 - {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|x64.Build.0 = Release|x64 - {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|Win32.ActiveCfg = Debug|Win32 - {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|Win32.Build.0 = Debug|Win32 - {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|x64.ActiveCfg = Debug|x64 - {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|x64.Build.0 = Debug|x64 - {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|Win32.ActiveCfg = Release|Win32 - {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|Win32.Build.0 = Release|Win32 - {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|x64.ActiveCfg = Release|x64 - {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|x64.Build.0 = Release|x64 - {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|Win32.ActiveCfg = Debug|Win32 - {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|Win32.Build.0 = Debug|Win32 - {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|x64.ActiveCfg = Debug|x64 - {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|x64.Build.0 = Debug|x64 - {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|Win32.ActiveCfg = Release|Win32 - {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|Win32.Build.0 = Release|Win32 - {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|x64.ActiveCfg = Release|x64 - {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|x64.Build.0 = Release|x64 - {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|Win32.ActiveCfg = Debug|Win32 - {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|Win32.Build.0 = Debug|Win32 - {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|x64.ActiveCfg = Debug|x64 - {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|x64.Build.0 = Debug|x64 - {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|Win32.ActiveCfg = Release|Win32 - {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|Win32.Build.0 = Release|Win32 - {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|x64.ActiveCfg = Release|x64 - {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|x64.Build.0 = Release|x64 - {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|Win32.ActiveCfg = Debug|Win32 - {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|Win32.Build.0 = Debug|Win32 - {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|x64.ActiveCfg = Debug|x64 - {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|x64.Build.0 = Debug|x64 - {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|Win32.ActiveCfg = Release|Win32 - {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|Win32.Build.0 = Release|Win32 - {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|x64.ActiveCfg = Release|x64 - {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|x64.Build.0 = Release|x64 - {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Debug|Win32.ActiveCfg = Debug|Win32 - {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Debug|Win32.Build.0 = Debug|Win32 - {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Debug|x64.ActiveCfg = Debug|x64 - {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Debug|x64.Build.0 = Debug|x64 - {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Release|Win32.ActiveCfg = Release|Win32 - {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Release|Win32.Build.0 = Release|Win32 - {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Release|x64.ActiveCfg = Release|x64 - {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Release|x64.Build.0 = Release|x64 - {326EF470-463F-4751-A22A-48BBAAD8B143}.Debug|Win32.ActiveCfg = Debug|Win32 - {326EF470-463F-4751-A22A-48BBAAD8B143}.Debug|Win32.Build.0 = Debug|Win32 - {326EF470-463F-4751-A22A-48BBAAD8B143}.Debug|x64.ActiveCfg = Debug|x64 - {326EF470-463F-4751-A22A-48BBAAD8B143}.Debug|x64.Build.0 = Debug|x64 - {326EF470-463F-4751-A22A-48BBAAD8B143}.Release|Win32.ActiveCfg = Release|Win32 - {326EF470-463F-4751-A22A-48BBAAD8B143}.Release|Win32.Build.0 = Release|Win32 - {326EF470-463F-4751-A22A-48BBAAD8B143}.Release|x64.ActiveCfg = Release|x64 - {326EF470-463F-4751-A22A-48BBAAD8B143}.Release|x64.Build.0 = Release|x64 - {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Debug|Win32.ActiveCfg = Debug|Win32 - {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Debug|Win32.Build.0 = Debug|Win32 - {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Debug|x64.ActiveCfg = Debug|x64 - {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Debug|x64.Build.0 = Debug|x64 - {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Release|Win32.ActiveCfg = Release|Win32 - {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Release|Win32.Build.0 = Release|Win32 - {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Release|x64.ActiveCfg = Release|x64 - {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Release|x64.Build.0 = Release|x64 - {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|Win32.ActiveCfg = Debug|Win32 - {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|Win32.Build.0 = Debug|Win32 - {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|x64.ActiveCfg = Debug|x64 - {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|x64.Build.0 = Debug|x64 - {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|Win32.ActiveCfg = Release|Win32 - {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|Win32.Build.0 = Release|Win32 - {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|x64.ActiveCfg = Release|x64 - {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|x64.Build.0 = Release|x64 - {90C70663-7181-4E99-9079-54188CEB8954}.Debug|Win32.ActiveCfg = Debug|Win32 - {90C70663-7181-4E99-9079-54188CEB8954}.Debug|Win32.Build.0 = Debug|Win32 - {90C70663-7181-4E99-9079-54188CEB8954}.Debug|x64.ActiveCfg = Debug|x64 - {90C70663-7181-4E99-9079-54188CEB8954}.Debug|x64.Build.0 = Debug|x64 - {90C70663-7181-4E99-9079-54188CEB8954}.Release|Win32.ActiveCfg = Release|Win32 - {90C70663-7181-4E99-9079-54188CEB8954}.Release|Win32.Build.0 = Release|Win32 - {90C70663-7181-4E99-9079-54188CEB8954}.Release|x64.ActiveCfg = Release|x64 - {90C70663-7181-4E99-9079-54188CEB8954}.Release|x64.Build.0 = Release|x64 - {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|Win32.ActiveCfg = Debug|Win32 - {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|Win32.Build.0 = Debug|Win32 - {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|x64.ActiveCfg = Debug|x64 - {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|x64.Build.0 = Debug|x64 - {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|Win32.ActiveCfg = Release|Win32 - {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|Win32.Build.0 = Release|Win32 - {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|x64.ActiveCfg = Release|x64 - {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|x64.Build.0 = Release|x64 - {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|Win32.ActiveCfg = Debug|Win32 - {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|Win32.Build.0 = Debug|Win32 - {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|x64.ActiveCfg = Debug|x64 - {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|x64.Build.0 = Debug|x64 - {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|Win32.ActiveCfg = Release|Win32 - {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|Win32.Build.0 = Release|Win32 - {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|x64.ActiveCfg = Release|x64 - {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|x64.Build.0 = Release|x64 - {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|Win32.ActiveCfg = Debug|Win32 - {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|Win32.Build.0 = Debug|Win32 - {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|x64.ActiveCfg = Debug|x64 - {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|x64.Build.0 = Debug|x64 - {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|Win32.ActiveCfg = Release|Win32 - {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|Win32.Build.0 = Release|Win32 - {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|x64.ActiveCfg = Release|x64 - {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|x64.Build.0 = Release|x64 - {255BDC68-B8DB-465F-8220-981E77684189}.Debug|Win32.ActiveCfg = Debug|Win32 - {255BDC68-B8DB-465F-8220-981E77684189}.Debug|Win32.Build.0 = Debug|Win32 - {255BDC68-B8DB-465F-8220-981E77684189}.Debug|x64.ActiveCfg = Debug|x64 - {255BDC68-B8DB-465F-8220-981E77684189}.Debug|x64.Build.0 = Debug|x64 - {255BDC68-B8DB-465F-8220-981E77684189}.Release|Win32.ActiveCfg = Release|Win32 - {255BDC68-B8DB-465F-8220-981E77684189}.Release|Win32.Build.0 = Release|Win32 - {255BDC68-B8DB-465F-8220-981E77684189}.Release|x64.ActiveCfg = Release|x64 - {255BDC68-B8DB-465F-8220-981E77684189}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F} = {988F2383-FA1D-408B-BCF6-C0EE7AB0A560} - {27014763-955D-486B-9BA7-69872192E6F4} = {988F2383-FA1D-408B-BCF6-C0EE7AB0A560} - {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA} = {988F2383-FA1D-408B-BCF6-C0EE7AB0A560} - {1CC213A4-3482-4211-B47B-172E90DAC7DE} = {988F2383-FA1D-408B-BCF6-C0EE7AB0A560} - {1B1CA20E-39C3-4D9B-AC37-3783048E6672} = {988F2383-FA1D-408B-BCF6-C0EE7AB0A560} - {DF3C5B07-A1A2-4F16-B37F-A27333622CDD} = {988F2383-FA1D-408B-BCF6-C0EE7AB0A560} - {F174E81A-2A66-4693-B917-11BB42D3658C} = {988F2383-FA1D-408B-BCF6-C0EE7AB0A560} - {3BF049F8-AF7E-4E1C-9627-3E94C887AF24} = {6838FA95-01BF-4FF7-914C-FC209B81406E} - {3F3E389B-88DE-41D5-A73B-4F6036E18B36} = {6838FA95-01BF-4FF7-914C-FC209B81406E} - EndGlobalSection -EndGlobal diff --git a/windows/Ethereum.vcxproj.filters b/windows/Ethereum.vcxproj.filters deleted file mode 100644 index 0bee64924..000000000 --- a/windows/Ethereum.vcxproj.filters +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - {ed0eafbf-bbfb-4700-b7c0-9b58049cc681} - - - - - Windows - - - \ No newline at end of file diff --git a/windows/Exp.vcxproj b/windows/Exp.vcxproj deleted file mode 100644 index cf4eb5d2e..000000000 --- a/windows/Exp.vcxproj +++ /dev/null @@ -1,195 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - Win32Proj - Ethereum - exp - {9AA5CF66-1150-4A02-B40E-3B89740DADB8} - - - - Application - true - v120 - - - Application - true - v120 - - - Application - false - v120 - - - Application - false - v120 - - - - - - - - - - - - - - - - - - - - - - - - - - - true - - - - false - - - false - - - - - - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - true - - - Console - true - true - - - - - - - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - true - - - Console - true - - - - - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true - AnySuitable - - - Console - true - true - true - true - - - - - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true - AnySuitable - - - Console - true - true - true - - - - - {826e68cb-d3ee-4a8a-b540-59a8c3f38d4f} - - - - - Document - $(Lua) "%(FullPath)" "$(IntDir)%(FileName).h" - - - $(IntDir)%(FileName).h - $(Lua) "%(FullPath)" "$(IntDir)%(FileName).h" - - - $(IntDir)%(FileName).h - $(Lua) "%(FullPath)" "$(IntDir)%(FileName).h" - - - $(IntDir)%(FileName).h - $(Lua) "%(FullPath)" "$(IntDir)%(FileName).h" - - - $(IntDir)%(FileName).h - ../.git/index - ../.git/index - ../.git/index - ../.git/index - - - - - - - - - - $(BuildDependsOn);FinalCopy - - - - - - - - \ No newline at end of file diff --git a/windows/LibCryptoPP.vcxproj b/windows/LibCryptoPP.vcxproj deleted file mode 100644 index 032ae5fa6..000000000 --- a/windows/LibCryptoPP.vcxproj +++ /dev/null @@ -1,414 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Document - ml64.exe /c /nologo /Fo"$(IntDir)x64dll.obj" /Zi "%(FullPath)" - ml64.exe /c /nologo /Fo"$(IntDir)x64dll.obj" /Zi "%(FullPath)" - $(IntDir)x64dll.obj - $(IntDir)x64dll.obj - - - - Win32Proj - LibCryptoPP - {1CC213A4-3482-4211-B47B-172E90DAC7DE} - - - - StaticLibrary - true - v120 - - - StaticLibrary - true - v120 - - - StaticLibrary - false - v120 - - - StaticLibrary - false - v120 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Disabled - MultiThreadedDebugDLL - 4100;4189;4244;%(DisableSpecificWarnings) - - - Windows - true - - - - - - - Disabled - MultiThreadedDebugDLL - 4100;4189;4244;%(DisableSpecificWarnings) - - - Windows - true - - - - - - - MaxSpeed - true - true - MultiThreadedDLL - 4100;4189;4244;%(DisableSpecificWarnings) - - - Windows - true - true - true - - - - - - - MaxSpeed - true - true - MultiThreadedDLL - 4100;4189;4244;%(DisableSpecificWarnings) - - - Windows - true - true - true - - - - - - \ No newline at end of file diff --git a/windows/LibEthereum.props b/windows/LibEthereum.props deleted file mode 100644 index 8c0bcac90..000000000 --- a/windows/LibEthereum.props +++ /dev/null @@ -1,35 +0,0 @@ - - - - - ../../boost - "../../lua/lua" - - - ..\..\_build\$(ProjectName)\$(Platform)_$(Configuration)\ - ..\..\_build\$(ProjectName)\$(Platform)_$(Configuration)\ - - - - 4068;4244;4267 - true - false - include/$(ProjectName);$(IntDir);../../cryptopp;..;../libethcore;../libethereum;../libethsupport;$(BoostDir);../../leveldb/include;../secp256k1;../../miniupnp - ETH_BUILD_PLATFORM=Windows/VS2013;ETH_BUILD_TYPE=$(Configuration)-$(Platform);ETH_MINIUPNPC=1;STATICLIB;LEVELDB_PLATFORM_WINDOWS;USE_NUM_BOOST;USE_FIELD_10X26;USE_FIELD_INV_BUILTIN;_WIN32_WINNT=0x0501;WIN32;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - true - Level3 - - - $(BoostDir)/stage/$(Platform) - - - - - $(BoostDir) - - - $(Lua) - - - \ No newline at end of file diff --git a/windows/LibEthereum.vcxproj b/windows/LibEthereum.vcxproj deleted file mode 100644 index 06f868023..000000000 --- a/windows/LibEthereum.vcxproj +++ /dev/null @@ -1,571 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - - - - - - - - - - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - - - - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - - - true - true - true - true - - - - stdafx.h - Create - Create - Create - Create - - - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - - - - - - - - - - - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - - - - - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - - true - true - true - true - - - true - true - true - true - - - - - - {1cc213a4-3482-4211-b47b-172e90dac7de} - - - {27014763-955d-486b-9ba7-69872192e6f4} - - - {1b1ca20e-39c3-4d9b-ac37-3783048e6672} - - - {1e1175bb-c4a9-41d8-b2d1-9022f71d3cea} - - - - {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F} - Win32Proj - LibEthereum - - - - StaticLibrary - true - v120 - - - StaticLibrary - true - v120 - - - StaticLibrary - false - v120 - - - StaticLibrary - false - v120 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - false - MultiThreadedDebugDLL - Use - stdafx.h - - - Windows - true - - - - - Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - false - MultiThreadedDebugDLL - stdafx.h - Use - - - Windows - true - - - - - - - MaxSpeed - true - true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - true - MultiThreadedDLL - Use - stdafx.h - - - Windows - true - true - true - - - - - MaxSpeed - true - true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - true - MultiThreadedDLL - Use - stdafx.h - - - Windows - true - true - true - - - - - - diff --git a/windows/LibEthereum.vcxproj.filters b/windows/LibEthereum.vcxproj.filters deleted file mode 100644 index 114364008..000000000 --- a/windows/LibEthereum.vcxproj.filters +++ /dev/null @@ -1,477 +0,0 @@ - - - - - Windows - - - libethereum - - - libethereum - - - libethereum - - - libethereum - - - libethereum - - - libethereum - - - libethereum - - - libethereum - - - libevm - - - libevm - - - libevm - - - libevmcore - - - liblll - - - liblll - - - liblll - - - liblll - - - libethereum - - - libethereum - - - libethereum - - - libethereum - - - libethereum - - - libethereum - - - libethereum - - - libdevcrypto - - - libdevcrypto - - - libdevcrypto - - - libdevcrypto - - - libdevcrypto - - - libdevcrypto - - - libdevcrypto - - - libethcore - - - libethcore - - - libethcore - - - libdevcore - - - libdevcore - - - libdevcore - - - libdevcore - - - libdevcore - - - libdevcore - - - libdevcore - - - libethcore - - - libevm - - - libethereum - - - libethereum - - - libethereum - - - libethereum - - - libethereum - - - libp2p - - - libp2p - - - libp2p - - - libp2p - - - libp2p - - - libp2p - - - libwhisper - - - libwhisper - - - libethereum - - - libdevcore - - - libdevcore - - - libethereum - - - libwebthree - - - libethcore - - - libdevcrypto - - - libdevcrypto - - - libdevcrypto - - - libethereum - - - libevmcore - - - - - Windows - - - libethereum - - - libethereum - - - libethereum - - - libethereum - - - libethereum - - - libethereum - - - libethereum - - - libethereum - - - libevm - - - libevm - - - libevm - - - libevm - - - libevmcore - - - liblll - - - liblll - - - liblll - - - liblll - - - liblll - - - liblll - - - libethereum - - - libethereum - - - libethereum - - - libethereum - - - libethereum - - - libethereum - - - libethereum - - - libdevcrypto - - - libdevcrypto - - - libdevcrypto - - - libdevcrypto - - - libdevcrypto - - - libdevcrypto - - - libdevcrypto - - - libdevcrypto - - - libdevcrypto - - - libethcore - - - libethcore - - - libethcore - - - libethcore - - - libethcore - - - libethcore - - - libdevcore - - - libdevcore - - - libdevcore - - - libdevcore - - - libdevcore - - - libdevcore - - - libdevcore - - - libdevcore - - - libdevcore - - - libdevcore - - - libethereum - - - libethereum - - - libethereum - - - libethereum - - - libethereum - - - libethereum - - - libp2p - - - libp2p - - - libp2p - - - libp2p - - - libp2p - - - libp2p - - - libp2p - - - libwhisper - - - libwhisper - - - libethereum - - - libdevcore - - - libdevcore - - - libethereum - - - libwebthree - - - libdevcrypto - - - libdevcrypto - - - libdevcrypto - - - libethereum - - - libevmcore - - - libevmcore - - - - - {2d571d8f-bacf-4c49-a0d0-c9036f5c0cc9} - - - {8275e3be-c870-44a2-8185-5a9992af8f8e} - - - {b246b3d7-af02-4125-a254-2b377214c288} - - - {37c37803-1515-47c1-b7e6-3879f4429ab3} - - - {ed9ad1b3-700c-47f9-8548-a90b5ef179ac} - - - {e6332606-e0ca-48aa-8a6b-303971ba7a93} - - - {fae2102b-d574-40fc-9f90-1b9ed0d117ac} - - - {35c32f6c-3f19-4603-8084-1b88ec9ae498} - - - {fc2cb618-ab0c-45b6-8eb9-6d88e0336fa9} - - - {36748e80-c977-4fee-84e6-699c039dff87} - - - {d838fece-fc20-42f6-bff5-97c236159b80} - - - \ No newline at end of file diff --git a/windows/LibEthereum_Debug.props b/windows/LibEthereum_Debug.props deleted file mode 100644 index 6d322078a..000000000 --- a/windows/LibEthereum_Debug.props +++ /dev/null @@ -1,18 +0,0 @@ - - - - - d - d - - - - - - $(DebugSuffix) - - - $(d) - - - \ No newline at end of file diff --git a/windows/LibEthereum_Release.props b/windows/LibEthereum_Release.props deleted file mode 100644 index 8f0436f61..000000000 --- a/windows/LibEthereum_Release.props +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - $(DebugSuffix) - - - \ No newline at end of file diff --git a/windows/LibLevelDB.vcxproj b/windows/LibLevelDB.vcxproj deleted file mode 100644 index 3e2407da6..000000000 --- a/windows/LibLevelDB.vcxproj +++ /dev/null @@ -1,221 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {27014763-955D-486B-9BA7-69872192E6F4} - Win32Proj - LibLevelDB - - - - StaticLibrary - true - v120 - - - StaticLibrary - true - v120 - - - StaticLibrary - false - v120 - - - StaticLibrary - false - v120 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Disabled - MultiThreadedDebugDLL - %(AdditionalIncludeDirectories);../../leveldb - _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - 4018;4100;4244;4267;4389;4702;4722;4800;4996;%(DisableSpecificWarnings) - - - Windows - true - - - - - - - Disabled - MultiThreadedDebugDLL - %(AdditionalIncludeDirectories);../../leveldb - _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - 4018;4100;4244;4267;4389;4702;4722;4800;4996;%(DisableSpecificWarnings) - - - Windows - true - - - - - - - MaxSpeed - true - true - MultiThreadedDLL - %(AdditionalIncludeDirectories);../../leveldb - _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - 4018;4100;4244;4267;4389;4702;4722;4800;4996;%(DisableSpecificWarnings) - - - Windows - true - true - true - - - - - - - MaxSpeed - true - true - MultiThreadedDLL - %(AdditionalIncludeDirectories);../../leveldb - _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - 4018;4100;4244;4267;4389;4702;4722;4800;4996;%(DisableSpecificWarnings) - - - Windows - true - true - true - - - - - - \ No newline at end of file diff --git a/windows/LibLevelDB.vcxproj.filters b/windows/LibLevelDB.vcxproj.filters deleted file mode 100644 index bc3306f56..000000000 --- a/windows/LibLevelDB.vcxproj.filters +++ /dev/null @@ -1,246 +0,0 @@ - - - - - {d83904b1-b5d1-4c5b-b476-96f08300d103} - - - {72573022-b7fd-4b7a-a92e-a68c06bd6366} - - - {7f821e9e-4ebf-4d18-8fb4-898bd3d81376} - - - {f285a595-6c39-4350-8d30-6f696a3a7c4c} - - - - - db - - - db - - - db - - - db - - - db - - - db - - - db - - - db - - - db - - - db - - - db - - - db - - - db - - - db - - - db - - - table - - - table - - - table - - - table - - - table - - - table - - - util - - - util - - - util - - - util - - - util - - - util - - - util - - - util - - - util - - - util - - - util - - - util - - - port - - - port - - - port - - - - - db - - - db - - - db - - - db - - - db - - - db - - - db - - - db - - - db - - - db - - - db - - - db - - - db - - - db - - - db - - - table - - - table - - - table - - - table - - - table - - - table - - - table - - - table - - - util - - - util - - - util - - - util - - - util - - - util - - - util - - - util - - - util - - - util - - - util - - - util - - - util - - - util - - - util - - - port - - - \ No newline at end of file diff --git a/windows/LibMiniUPnPc.vcxproj b/windows/LibMiniUPnPc.vcxproj deleted file mode 100644 index 07489d0e8..000000000 --- a/windows/LibMiniUPnPc.vcxproj +++ /dev/null @@ -1,182 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Win32Proj - LibMiniUPnPc - {1B1CA20E-39C3-4D9B-AC37-3783048E6672} - LibMiniUPnPc - - - - StaticLibrary - true - v120 - - - StaticLibrary - true - v120 - - - StaticLibrary - false - v120 - - - StaticLibrary - false - v120 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Disabled - MultiThreadedDebugDLL - _CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;MINIUPNP_STATICLIB;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions) - 4100;4244;4245;4267;4389;%(DisableSpecificWarnings) - - - Windows - true - - - Iphlpapi.lib - - - - - - - Disabled - MultiThreadedDebugDLL - _CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;MINIUPNP_STATICLIB;%(PreprocessorDefinitions) - 4100;4244;4245;4267;4389;%(DisableSpecificWarnings) - - - Windows - true - - - Iphlpapi.lib - - - - - - - MaxSpeed - true - true - MultiThreadedDLL - _CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;MINIUPNP_STATICLIB;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions) - 4100;4244;4245;4267;4389;%(DisableSpecificWarnings) - - - Windows - true - true - true - - - Iphlpapi.lib - - - - - - - MaxSpeed - true - true - MultiThreadedDLL - _CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;MINIUPNP_STATICLIB;%(PreprocessorDefinitions) - 4100;4244;4245;4267;4389;%(DisableSpecificWarnings) - - - Windows - true - true - true - - - Iphlpapi.lib - - - - - - \ No newline at end of file diff --git a/windows/LibQEthereum.props b/windows/LibQEthereum.props deleted file mode 100644 index 08ba05c69..000000000 --- a/windows/LibQEthereum.props +++ /dev/null @@ -1,70 +0,0 @@ - - - - - ../../Qt/$(Platform) - $(QtDir)/qtbase - $(QtBase)/bin - $(QtBase)/include;../../Qt/Src/qtbase/include;../../Qt/Src/qtbase/include/QtCore;../../Qt/Src/qtbase/include/QtWidgets;../../Qt/Src/qtbase/include/QtQml;../../Qt/Src/qtbase/include/QtGui;../../Qt/Src/qtdeclarative/include;../../Qt/Src/qtwebkit/include - $(QtBase)/lib;$(QtBase)/plugins/platforms;../../icu/lib64 - ..\..\icu\bin_$(Platform)\icu*52.dll;$(QtBase)\lib\Qt5Core$(d).dll;$(QtBase)\lib\Qt5Gui$(d).dll;$(QtBase)\lib\Qt5Multimedia$(d).dll;$(QtBase)\lib\Qt5MultimediaWidgets$(d).dll;$(QtBase)\lib\Qt5OpenGL$(d).dll;$(QtBase)\lib\Qt5Positioning$(d).dll;$(QtBase)\lib\Qt5PrintSupport$(d).dll;$(QtBase)\lib\Qt5Network$(d).dll;$(QtBase)\lib\Qt5Qml$(d).dll;$(QtBase)\lib\Qt5Quick$(d).dll;$(QtBase)\lib\Qt5Sensors$(d).dll;$(QtBase)\lib\Qt5Sql$(d).dll;$(QtBase)\lib\Qt5Webkit$(d).dll;$(QtBase)\lib\Qt5WebkitWidgets$(d).dll;$(QtBase)\lib\Qt5Widgets$(d).dll;$(QtBase)\plugins\**\qwindows$(d).dll;$(QtBase)\plugins\**\qgenericbearer$(d).dll;$(QtBase)\plugins\**\qnativewifibearer$(d).dll;$(QtBase)\plugins\**\qgif$(d).dll;$(QtBase)\plugins\**\qico$(d).dll;$(QtBase)\plugins\**\qjpeg$(d).dll;$(QtBase)\plugins\**\qsvg$(d).dll;$(QtBase)\plugins\**\qtsensors_dummy$(d).dll - - - <_PropertySheetDisplayName>LibQEthereum - - - - - ..;$(QtInclude);%(AdditionalIncludeDirectories) - 4718;%(DisableSpecificWarnings) - ETH_QTQML=1;%(PreprocessorDefinitions) - - - - - - - - - $(QtLib);%(AdditionalLibraryDirectories) - Qt5PlatformSupport$(d).lib;Qt5Core$(d).lib;Qt5GUI$(d).lib;Qt5Network$(d).lib;Qt5Quick$(d).lib;Qt5Qml$(d).lib;Qt5Webkit$(d).lib;Qt5WebkitWidgets$(d).lib;Qt5Widgets$(d).lib;%(AdditionalDependencies) - - - - - $(QtDir) - - - $(QtBase) - - - $(QtBin) - - - $(QtInclude) - - - $(QtLib) - - - $(CopyDlls) - - - - - - - - - - \ No newline at end of file diff --git a/windows/LibQEthereum.vcxproj b/windows/LibQEthereum.vcxproj deleted file mode 100644 index 20b29e06e..000000000 --- a/windows/LibQEthereum.vcxproj +++ /dev/null @@ -1,204 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - {826e68cb-d3ee-4a8a-b540-59a8c3f38d4f} - - - - - - - Create - Create - Create - Create - - - - - $(Lua) moc.lua "$(QtBin)/moc" "$(IntDir)moc_%(FileName).cpp" "@(ClCompile->'%(AdditionalIncludeDirectories)');$(IncludePath)" "@(ClCompile->'%(PreprocessorDefinitions)');_MSC_VER=1800" "%(FullPath)" - $(Lua) moc.lua "$(QtBin)/moc" "$(IntDir)moc_%(FileName).cpp" "@(ClCompile->'%(AdditionalIncludeDirectories)');$(IncludePath)" "@(ClCompile->'%(PreprocessorDefinitions)');_MSC_VER=1800" "%(FullPath)" - $(Lua) moc.lua "$(QtBin)/moc" "$(IntDir)moc_%(FileName).cpp" "@(ClCompile->'%(AdditionalIncludeDirectories)');$(IncludePath)" "@(ClCompile->'%(PreprocessorDefinitions)');_MSC_VER=1800" "%(FullPath)" - $(Lua) moc.lua "$(QtBin)/moc" "$(IntDir)moc_%(FileName).cpp" "@(ClCompile->'%(AdditionalIncludeDirectories)');$(IncludePath)" "@(ClCompile->'%(PreprocessorDefinitions)');_MSC_VER=1800" "%(FullPath)" - - - $(IntDir)moc_%(FileName).cpp - - - $(IntDir)moc_%(FileName).cpp - - - $(IntDir)moc_%(FileName).cpp - - - $(IntDir)moc_%(FileName).cpp - - - - - $(Lua) moc.lua "$(QtBin)/moc" "$(IntDir)moc_%(FileName).cpp" "@(ClCompile->'%(AdditionalIncludeDirectories)');$(IncludePath)" "@(ClCompile->'%(PreprocessorDefinitions)');_MSC_VER=1800" "%(FullPath)" - - - $(Lua) moc.lua "$(QtBin)/moc" "$(IntDir)moc_%(FileName).cpp" "@(ClCompile->'%(AdditionalIncludeDirectories)');$(IncludePath)" "@(ClCompile->'%(PreprocessorDefinitions)');_MSC_VER=1800" "%(FullPath)" - - - $(Lua) moc.lua "$(QtBin)/moc" "$(IntDir)moc_%(FileName).cpp" "@(ClCompile->'%(AdditionalIncludeDirectories)');$(IncludePath)" "@(ClCompile->'%(PreprocessorDefinitions)');_MSC_VER=1800" "%(FullPath)" - - - $(Lua) moc.lua "$(QtBin)/moc" "$(IntDir)moc_%(FileName).cpp" "@(ClCompile->'%(AdditionalIncludeDirectories)');$(IncludePath)" "@(ClCompile->'%(PreprocessorDefinitions)');_MSC_VER=1800" "%(FullPath)" - - - $(IntDir)moc_%(FileName).cpp - $(IntDir)moc_%(FileName).cpp - $(IntDir)moc_%(FileName).cpp - $(IntDir)moc_%(FileName).cpp - - - - - Win32Proj - LibQEthereum - {DF3C5B07-A1A2-4F16-B37F-A27333622CDD} - - - - StaticLibrary - true - v120 - - - StaticLibrary - true - v120 - - - StaticLibrary - false - v120 - - - StaticLibrary - false - v120 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - false - MultiThreadedDebugDLL - Use - stdafx.h - - - Windows - true - - - - - Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - false - MultiThreadedDebugDLL - stdafx.h - Use - - - Windows - true - - - - - - - MaxSpeed - true - true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - true - MultiThreadedDLL - Use - stdafx.h - - - Windows - true - true - true - - - - - MaxSpeed - true - true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - true - MultiThreadedDLL - Use - stdafx.h - - - Windows - true - true - true - - - - - - \ No newline at end of file diff --git a/windows/LibQEthereum.vcxproj.filters b/windows/LibQEthereum.vcxproj.filters deleted file mode 100644 index e38730504..000000000 --- a/windows/LibQEthereum.vcxproj.filters +++ /dev/null @@ -1,24 +0,0 @@ - - - - - {516a3655-70df-49f7-af1f-008cf4acf934} - - - - - Windows - - - - - - - Windows - - - - - - - \ No newline at end of file diff --git a/windows/LibSecp256k1.vcxproj b/windows/LibSecp256k1.vcxproj deleted file mode 100644 index 37df3b3b6..000000000 --- a/windows/LibSecp256k1.vcxproj +++ /dev/null @@ -1,183 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CompileAsCpp - CompileAsCpp - CompileAsCpp - CompileAsCpp - - - - - - - Win32Proj - LibSecp256k1 - {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA} - LibSecp256k1 - - - - StaticLibrary - true - v120 - - - StaticLibrary - true - v120 - - - StaticLibrary - false - v120 - - - StaticLibrary - false - v120 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - 4189;4244;4267;%(DisableSpecificWarnings) - - - Windows - true - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - 4189;4244;4267;%(DisableSpecificWarnings) - - - Windows - true - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - MultiThreadedDLL - 4189;4244;4267;%(DisableSpecificWarnings) - - - Windows - true - true - true - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - MultiThreadedDLL - 4189;4244;4267;%(DisableSpecificWarnings) - - - Windows - true - true - true - - - - - - \ No newline at end of file diff --git a/windows/LibSecp256k1.vcxproj.filters b/windows/LibSecp256k1.vcxproj.filters deleted file mode 100644 index aa4e5b9cb..000000000 --- a/windows/LibSecp256k1.vcxproj.filters +++ /dev/null @@ -1,71 +0,0 @@ - - - - - {7d4db365-bce7-45c1-861c-f5f86beca992} - - - - - impl - - - impl - - - impl - - - impl - - - impl - - - impl - - - impl - - - impl - - - impl - - - impl - - - impl - - - impl - - - impl - - - impl - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/windows/LibSerpent.vcxproj b/windows/LibSerpent.vcxproj deleted file mode 100644 index 925d4915b..000000000 --- a/windows/LibSerpent.vcxproj +++ /dev/null @@ -1,187 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - {1cc213a4-3482-4211-b47b-172e90dac7de} - - - {27014763-955d-486b-9ba7-69872192e6f4} - - - {1b1ca20e-39c3-4d9b-ac37-3783048e6672} - - - {1e1175bb-c4a9-41d8-b2d1-9022f71d3cea} - - - - - - - - - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - - - - Win32Proj - LibSerpent - {F174E81A-2A66-4693-B917-11BB42D3658C} - - - - StaticLibrary - true - v120 - - - StaticLibrary - true - v120 - - - StaticLibrary - false - v120 - - - StaticLibrary - false - v120 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - false - MultiThreadedDebugDLL - Use - stdafx.h - - - Windows - true - - - - - Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - false - MultiThreadedDebugDLL - stdafx.h - Use - - - Windows - true - - - - - - - MaxSpeed - true - true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - true - MultiThreadedDLL - Use - stdafx.h - - - Windows - true - true - true - - - - - MaxSpeed - true - true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - true - MultiThreadedDLL - Use - stdafx.h - - - Windows - true - true - true - - - - - - \ No newline at end of file diff --git a/windows/LibSerpent.vcxproj.filters b/windows/LibSerpent.vcxproj.filters deleted file mode 100644 index 65df02da3..000000000 --- a/windows/LibSerpent.vcxproj.filters +++ /dev/null @@ -1,18 +0,0 @@ - - - - - {20ea55ad-2a66-41df-a64e-9fed221f544f} - - - - - Windows - - - - - Windows - - - \ No newline at end of file diff --git a/windows/Lllc.vcxproj b/windows/Lllc.vcxproj deleted file mode 100644 index 70306d656..000000000 --- a/windows/Lllc.vcxproj +++ /dev/null @@ -1,195 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - Win32Proj - Ethereum - lllc - {255BDC68-B8DB-465F-8220-981E77684189} - - - - Application - true - v120 - - - Application - true - v120 - - - Application - false - v120 - - - Application - false - v120 - - - - - - - - - - - - - - - - - - - - - - - - - - - true - - - - false - - - false - - - - - - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - true - - - Console - true - true - - - - - - - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - true - - - Console - true - - - - - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true - AnySuitable - - - Console - true - true - true - true - - - - - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true - AnySuitable - - - Console - true - true - true - - - - - {826e68cb-d3ee-4a8a-b540-59a8c3f38d4f} - - - - - Document - $(Lua) "%(FullPath)" "$(IntDir)%(FileName).h" - - - $(IntDir)%(FileName).h - $(Lua) "%(FullPath)" "$(IntDir)%(FileName).h" - - - $(IntDir)%(FileName).h - $(Lua) "%(FullPath)" "$(IntDir)%(FileName).h" - - - $(IntDir)%(FileName).h - $(Lua) "%(FullPath)" "$(IntDir)%(FileName).h" - - - $(IntDir)%(FileName).h - ../.git/index - ../.git/index - ../.git/index - ../.git/index - - - - - - - - - - $(BuildDependsOn);FinalCopy - - - - - - - - \ No newline at end of file diff --git a/windows/Neth.vcxproj b/windows/Neth.vcxproj deleted file mode 100644 index a778b78d8..000000000 --- a/windows/Neth.vcxproj +++ /dev/null @@ -1,213 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - Win32Proj - Nethereum - neth - {90C70663-7181-4E99-9079-54188CEB8954} - - - - Application - true - v120 - - - Application - true - v120 - - - Application - false - v120 - - - Application - false - v120 - - - - - - - - - - - - - - - - - - - - - - - - - - - true - - - - false - - - false - - - - - - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - true - ncurses/include;ncurses/include/ncurses;%(AdditionalIncludeDirectories) - - - Console - true - true - $(BoostDir)/stage/$(Platform);ncurses/lib/$(Platform) - wncurses.lib;wform.lib;wmenu.lib;wpanel.lib;%(AdditionalDependencies) - - - - - - - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - true - ncurses/include;ncurses/include/ncurses;ncurses/include/ncurses;%(AdditionalIncludeDirectories) - - - Console - true - $(BoostDir)/stage/$(Platform);ncurses/lib/$(Platform) - wncurses.lib;wform.lib;wmenu.lib;wpanel.lib;%(AdditionalDependencies) - - - - - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true - AnySuitable - ncurses/include;ncurses/include/ncurses;%(AdditionalIncludeDirectories) - - - Console - true - true - true - true - $(BoostDir)/stage/$(Platform);ncurses/lib/$(Platform) - wncurses.lib;wform.lib;wmenu.lib;wpanel.lib;%(AdditionalDependencies) - - - - - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true - AnySuitable - ncurses/include;ncurses/include/ncurses;%(AdditionalIncludeDirectories) - - - Console - true - true - true - $(BoostDir)/stage/$(Platform);ncurses/lib/$(Platform) - wncurses.lib;wform.lib;wmenu.lib;wpanel.lib;%(AdditionalDependencies) - - - - - {826e68cb-d3ee-4a8a-b540-59a8c3f38d4f} - - - - - Document - $(Lua) "%(FullPath)" "$(IntDir)%(FileName).h" - - - $(IntDir)%(FileName).h - $(Lua) "%(FullPath)" "$(IntDir)%(FileName).h" - - - $(IntDir)%(FileName).h - $(Lua) "%(FullPath)" "$(IntDir)%(FileName).h" - - - $(IntDir)%(FileName).h - $(Lua) "%(FullPath)" "$(IntDir)%(FileName).h" - - - $(IntDir)%(FileName).h - ../.git/index - ../.git/index - ../.git/index - ../.git/index - - - - - - - - - - $(BuildDependsOn);FinalCopy - - - - - - - - - - - - - - \ No newline at end of file diff --git a/windows/Sc.vcxproj b/windows/Sc.vcxproj deleted file mode 100644 index 8dc0e1dee..000000000 --- a/windows/Sc.vcxproj +++ /dev/null @@ -1,198 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - Win32Proj - Ethereum - sc - {90068D1B-070E-4C41-88B0-1E243E1E5BFF} - - - - Application - true - v120 - - - Application - true - v120 - - - Application - false - v120 - - - Application - false - v120 - - - - - - - - - - - - - - - - - - - - - - - - - - - true - - - - false - - - false - - - - - - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - true - - - Console - true - true - - - - - - - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - true - - - Console - true - - - - - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true - AnySuitable - - - Console - true - true - true - true - - - - - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true - AnySuitable - - - Console - true - true - true - - - - - {826e68cb-d3ee-4a8a-b540-59a8c3f38d4f} - - - {f174e81a-2a66-4693-b917-11bb42d3658c} - - - - - Document - $(Lua) "%(FullPath)" "$(IntDir)%(FileName).h" - - - $(IntDir)%(FileName).h - $(Lua) "%(FullPath)" "$(IntDir)%(FileName).h" - - - $(IntDir)%(FileName).h - $(Lua) "%(FullPath)" "$(IntDir)%(FileName).h" - - - $(IntDir)%(FileName).h - $(Lua) "%(FullPath)" "$(IntDir)%(FileName).h" - - - $(IntDir)%(FileName).h - ../.git/index - ../.git/index - ../.git/index - ../.git/index - - - - - - - - - - $(BuildDependsOn);FinalCopy - - - - - - - - \ No newline at end of file diff --git a/windows/TestEthereum.vcxproj b/windows/TestEthereum.vcxproj deleted file mode 100644 index 172e6be86..000000000 --- a/windows/TestEthereum.vcxproj +++ /dev/null @@ -1,194 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - Win32Proj - TestEthereum - TestEthereum - {3F3E389B-88DE-41D5-A73B-4F6036E18B36} - - - - Application - true - v120 - - - Application - true - v120 - - - Application - false - v120 - - - Application - false - v120 - - - - - - - - - - - - - - - - - - - - - - - true - - - true - - - false - - - false - - - - Use - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - true - true - stdafx.h - Async - - - Console - true - true - - - - - Use - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - true - stdafx.h - Async - - - Console - true - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true - AnySuitable - true - stdafx.h - Async - - - Console - true - true - true - true - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true - AnySuitable - true - stdafx.h - Async - - - Console - true - true - true - - - - - {826e68cb-d3ee-4a8a-b540-59a8c3f38d4f} - - - - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - - - - - - - - - - - - - \ No newline at end of file diff --git a/windows/TestEthereum.vcxproj.filters b/windows/TestEthereum.vcxproj.filters deleted file mode 100644 index 4be707aec..000000000 --- a/windows/TestEthereum.vcxproj.filters +++ /dev/null @@ -1,38 +0,0 @@ - - - - - Windows - - - - - - - - - - - - - - - - - - - - - {0acd7e2f-2594-4c13-94cb-3247045bdbfd} - - - - - Windows - - - - - - - \ No newline at end of file diff --git a/windows/TestSecp256k1.vcxproj b/windows/TestSecp256k1.vcxproj deleted file mode 100644 index d2c113d4c..000000000 --- a/windows/TestSecp256k1.vcxproj +++ /dev/null @@ -1,171 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - CompileAsCpp - CompileAsCpp - CompileAsCpp - CompileAsCpp - - - - - {1e1175bb-c4a9-41d8-b2d1-9022f71d3cea} - - - - Win32Proj - TestSecp256k1 - TestSecp256k1 - {3BF049F8-AF7E-4E1C-9627-3E94C887AF24} - - - - Application - true - v120 - - - Application - true - v120 - - - Application - false - v120 - - - Application - false - v120 - - - - - - - - - - - - - - - - - - - - - - - true - - - true - - - false - - - false - - - - - - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - true - true - 4189;4244;4267;%(DisableSpecificWarnings) - - - Console - true - true - - - - - - - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - true - 4189;4244;4267;%(DisableSpecificWarnings) - - - Console - true - - - - - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true - AnySuitable - true - 4189;4244;4267;%(DisableSpecificWarnings) - - - Console - true - true - true - true - - - - - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true - AnySuitable - true - 4189;4244;4267;%(DisableSpecificWarnings) - - - Console - true - true - true - - - - - - \ No newline at end of file diff --git a/windows/Walleth.vcxproj b/windows/Walleth.vcxproj deleted file mode 100644 index ad76f0f01..000000000 --- a/windows/Walleth.vcxproj +++ /dev/null @@ -1,315 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - Win32Proj - Walleth - Walleth - {326EF470-463F-4751-A22A-48BBAAD8B143} - - - - Application - true - v120 - - - Application - true - v120 - - - Application - false - v120 - - - Application - false - v120 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - - - - false - - - false - - - - Use - Disabled - WIN32;_DEBUG;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - true - stdafx.h - - - Windows - true - true - - - - - - - - - - - - - - - Use - Disabled - WIN32;_DEBUG;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - true - stdafx.h - - - Windows - true - - - - - - - - - - - - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;%(PreprocessorDefinitions) - MultiThreadedDLL - true - AnySuitable - stdafx.h - - - Windows - true - true - true - true - - - - - - - - - - - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;%(PreprocessorDefinitions) - MultiThreadedDLL - true - AnySuitable - stdafx.h - - - Windows - true - true - true - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - - - - - - $(Lua) moc.lua "$(QtBin)/moc" "$(IntDir)moc_%(FileName).cpp" "@(ClCompile->'%(AdditionalIncludeDirectories)');$(IncludePath)" "@(ClCompile->'%(PreprocessorDefinitions)');_MSC_VER=1800" "%(FullPath)" - $(IntDir)moc_%(FileName).cpp - - - $(Lua) moc.lua "$(QtBin)/moc" "$(IntDir)moc_%(FileName).cpp" "@(ClCompile->'%(AdditionalIncludeDirectories)');$(IncludePath)" "@(ClCompile->'%(PreprocessorDefinitions)');_MSC_VER=1800" "%(FullPath)" - - - $(Lua) moc.lua "$(QtBin)/moc" "$(IntDir)moc_%(FileName).cpp" "@(ClCompile->'%(AdditionalIncludeDirectories)');$(IncludePath)" "@(ClCompile->'%(PreprocessorDefinitions)');_MSC_VER=1800" "%(FullPath)" - - - $(Lua) moc.lua "$(QtBin)/moc" "$(IntDir)moc_%(FileName).cpp" "@(ClCompile->'%(AdditionalIncludeDirectories)');$(IncludePath)" "@(ClCompile->'%(PreprocessorDefinitions)');_MSC_VER=1800" "%(FullPath)" - - - $(IntDir)moc_%(FileName).cpp - $(IntDir)moc_%(FileName).cpp - $(IntDir)moc_%(FileName).cpp - - - - - - Document - "$(QtBin)/uic" -o "$(IntDir)ui_%(FileName).h" "%(FullPath)" - "$(QtBin)/uic" -o "$(IntDir)ui_%(FileName).h" "%(FullPath)" - $(IntDir)ui_%(FileName).h - "$(QtBin)/uic" -o "$(IntDir)ui_%(FileName).h" "%(FullPath)" - "$(QtBin)/uic" -o "$(IntDir)ui_%(FileName).h" "%(FullPath)" - $(IntDir)ui_%(FileName).h - "$(QtBin)/uic" -o "$(IntDir)ui_%(FileName).h" "%(FullPath)" - "$(QtBin)/uic" -o "$(IntDir)ui_%(FileName).h" "%(FullPath)" - $(IntDir)ui_%(FileName).h - "$(QtBin)/uic" -o "$(IntDir)ui_%(FileName).h" "%(FullPath)" - "$(QtBin)/uic" -o "$(IntDir)ui_%(FileName).h" "%(FullPath)" - $(IntDir)ui_%(FileName).h - - - - - Document - $(Lua) "%(FullPath)" "$(IntDir)%(FileName).h" - - - $(Lua) "%(FullPath)" "$(IntDir)%(FileName).h" - - - $(Lua) "%(FullPath)" "$(IntDir)%(FileName).h" - - - $(Lua) "%(FullPath)" "$(IntDir)%(FileName).h" - - - $(IntDir)%(FileName).h - $(IntDir)%(FileName).h - $(IntDir)%(FileName).h - $(IntDir)%(FileName).h - ../.git/index - ../.git/index - ../.git/index - ../.git/index - - - - - {df3c5b07-a1a2-4f16-b37f-a27333622cdd} - - - - - Document - "$(QtBin)/rcc" -o "$(IntDir)qrc_%(FileName).cpp" "%(FullPath)" - "$(QtBin)/rcc" -o "$(IntDir)qrc_%(FileName).cpp" "%(FullPath)" - "$(QtBin)/rcc" -o "$(IntDir)qrc_%(FileName).cpp" "%(FullPath)" - "$(QtBin)/rcc" -o "$(IntDir)qrc_%(FileName).cpp" "%(FullPath)" - "$(QtBin)/rcc" -o "$(IntDir)qrc_%(FileName).cpp" "%(FullPath)" - "$(QtBin)/rcc" -o "$(IntDir)qrc_%(FileName).cpp" "%(FullPath)" - "$(QtBin)/rcc" -o "$(IntDir)qrc_%(FileName).cpp" "%(FullPath)" - "$(QtBin)/rcc" -o "$(IntDir)qrc_%(FileName).cpp" "%(FullPath)" - $(IntDir)qrc_%(FileName).cpp - $(IntDir)qrc_%(FileName).cpp - $(IntDir)qrc_%(FileName).cpp - $(IntDir)qrc_%(FileName).cpp - ../Walleth/Simple.qml - ../Walleth/Simple.qml - ../Walleth/Simple.qml - ../Walleth/Simple.qml - - - - - - - - - - - - - - $(BuildDependsOn);FinalCopy - - - - - - - - \ No newline at end of file diff --git a/windows/Walleth.vcxproj.filters b/windows/Walleth.vcxproj.filters deleted file mode 100644 index 804248d9f..000000000 --- a/windows/Walleth.vcxproj.filters +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - Windows - - - Windows - - - - - - - Windows - - - - - - {37f5b48c-b602-474b-8683-041898e328b5} - - - - - Windows - - - - - - \ No newline at end of file diff --git a/windows/WinMain.cpp b/windows/WinMain.cpp deleted file mode 100644 index d2fc147ca..000000000 --- a/windows/WinMain.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// http://www.flipcode.com/archives/WinMain_Command_Line_Parser.shtml -// COTD Entry submitted by Max McGuire [amcguire@andrew.cmu.edu] - -#include - -extern int main(int argc, char* argv[]); - -int WINAPI WinMain(HINSTANCE /*instance*/, HINSTANCE /*prev_instance*/, char* command_line, int /*show_command*/) -{ - int argc; - char** argv; - char* arg; - int index; - int result; - - // count the arguments - argc = 1; - arg = command_line; - - while (arg[0] != 0) - { - while (arg[0] != 0 && arg[0] == ' ') - { - arg++; - } - if (arg[0] != 0) - { - argc++; - while (arg[0] != 0 && arg[0] != ' ') - { - arg++; - } - } - } - - // tokenize the arguments - argv = (char**)malloc(argc * sizeof(char*)); - arg = command_line; - index = 1; - - while (arg[0] != 0) - { - while (arg[0] != 0 && arg[0] == ' ') - { - arg++; - } - if (arg[0] != 0) - { - argv[index] = arg; - index++; - while (arg[0] != 0 && arg[0] != ' ') - { - arg++; - } - if (arg[0] != 0) - { - arg[0] = 0; - arg++; - } - } - } - - // put the program name into argv[0] - char filename[_MAX_PATH]; - GetModuleFileName(NULL, filename, _MAX_PATH); - argv[0] = filename; - - // call the user specified main function - result = main(argc, argv); - free(argv); - return result; -} diff --git a/windows/bootstrap.sh b/windows/bootstrap.sh deleted file mode 100644 index 642c3f5c8..000000000 --- a/windows/bootstrap.sh +++ /dev/null @@ -1,233 +0,0 @@ -#!/bin/bash -# @file bootstrap.sh -# @author Tim Hughes -# @date 2014 -# Script to fetch and compile depdencies for building Ethereum using Visual Studio Express 2013. -# Prerequisites: -# - Visual Studio Express 2013 for Desktop -# - On PATH: bash, git, git-svn, curl, 7z, perl, ruby, python - -error_exit() -{ - echo $1 1>&2 - exit 1 -} - -# check for existance of basic tools -for i in gawk sed curl git 7z; do - which $i &>/dev/null || error_exit "Could not find $i on PATH" -done - -# get commands before they are removed from the path -sed=`which sed` -awk=`which gawk` -which=`which which` - -path_remove() -{ - export PATH=`echo -n $PATH | "$awk" -v RS=: -v ORS=: '$0 != "'$1'"' | "$sed" 's/:$//'` -} - -path_remove_bin() -{ - path_remove "/bin" - path_remove "/usr/bin" - path_remove "/usr/local/bin" -} - -# check for native perl, python and ruby installations (needed by Qt) -( - path_remove_bin; - for i in ruby python perl; do - "$which" $i &>/dev/null || error_exit "Could not find $i on PATH" - done -) - -if [ ! -d "$VS120COMNTOOLS" ]; then - error_exit "Couldn't find Visual Studio 2013" -fi - -if [[ ! $@ ]] || [ $1 == "fetch" ]; then - # fetch ethereum (develop branch) - if [ ! -d cpp-ethereum ]; then - (set -x; git clone https://github.com/ethereum/cpp-ethereum.git) - cd cpp-ethereum - (set -x; git checkout -b develop origin/develop) - cd .. - echo - fi - - # fetch CryptoPP-5.6.2 - if [ ! -d cryptopp ]; then - (set -x; git svn clone -r 541:541 http://svn.code.sf.net/p/cryptopp/code/trunk/c5 cryptopp) - echo - fi - - # fetch MiniUPnP-1.8 - if [ ! -d miniupnp ]; then - (set -x; git clone https://github.com/miniupnp/miniupnp.git) - cd miniupnp - (set -x; git checkout tags/miniupnpd_1_8) - cd .. - echo - fi - - # fetch LevelDB (windows branch) - if [ ! -d leveldb ]; then - (set -x; git clone https://code.google.com/p/leveldb/) - cd leveldb - (set -x; git checkout origin/windows) - cd .. - echo - fi - - # fetch and unpack boost-1.55 source - if [ ! -d boost ]; then - if [ ! -f _download/boost_1_55_0.7z ]; then - (set -x; mkdir -p _download) - (set -x; curl -o _download/boost_1_55_0.7z -L http://sourceforge.net/projects/boost/files/boost/1.55.0/boost_1_55_0.7z/download) - fi - (set -x; 7z x _download/boost_1_55_0.7z) - (set -x; mv boost_1_55_0 boost) - echo - fi - - # fetch and unpack icu - if [ ! -d icu ]; then - git svn clone -rHEAD http://source.icu-project.org/repos/icu/icu/tags/release-52-1 icu - cd icu - # patch for VS2013 and Windows Qt build - git am --3way --ignore-space-change -s ../cpp-ethereum/windows/patches/icu/0*.patch - cd .. - fi - - # fetch and unpack Qt 5.1.2 source - if [ ! -d Qt ]; then - if [ ! -f _download/qt-everywhere-opensource-src-5.2.1.zip ]; then - (set -x; mkdir -p _download) - (set -x; curl -o _download/qt-everywhere-opensource-src-5.2.1.zip -L http://download.qt-project.org/official_releases/qt/5.2/5.2.1/single/qt-everywhere-opensource-src-5.2.1.zip) - fi - (set -x; mkdir Qt) - cd Qt - (set -x; 7z x ../_download/qt-everywhere-opensource-src-5.2.1.zip) - (set -x; mv qt-everywhere-opensource-src-5.2.1 Src) - cd .. - echo - fi - - # fetch jom - if [ ! -f "Qt/jom/jom.exe" ]; then - if [ ! -f "_download/jom.zip" ]; then - (set -x; mkdir -p _download) - (set -x; curl -o "_download/jom.zip" -L http://download.qt-project.org/official_releases/jom/jom.zip) - fi - (set -x; mkdir -p Qt/jom) - cd Qt/jom - (set -x; 7z x ../../_download/jom.zip) - cd ../.. - echo - fi - - # fetch and unpack Lua binaries - if [ ! -d lua ]; then - if [ ! -f _download/lua-5.2.1_Win32_bin.zip ]; then - (set -x; mkdir -p _download) - (set -x; curl -o _download/lua-5.2.1_Win32_bin.zip -L http://sourceforge.net/projects/luabinaries/files/5.2.1/Executables/lua-5.2.1_Win32_bin.zip/download) - fi - (set -x; mkdir lua) - cd lua - (set -x; 7z x ../_download/lua-5.2.1_Win32_bin.zip lua52.exe lua52.dll) - (set -x; mv lua52.exe lua.exe) - cd .. - echo - fi -fi - -compile_boost() -{ - if [ $platform == "x64" ]; then - addressModel="address-model=64" - else - addressModel="" - fi - - if [ ! -d "stage/$platform" ]; then - targets="--with-filesystem --with-system --with-thread --with-date_time --with-regex --with-test" - (set -x; ./b2 -j4 --build-type=complete link=static runtime-link=shared variant=debug,release threading=multi $addressModel $targets stage) - (set -x; mv stage/lib stage/$platform) - fi -} - -if [[ ! $@ ]] || [ $1 == "compile-boost" ]; then - # bootstrap if b2 is missing - cd boost - if [ ! -f "b2.exe" ]; then - (set -x; cmd.exe /c bootstrap.bat) - fi - - # compile boost for x86 and x64 - platform="x64"; compile_boost - platform="Win32"; compile_boost - cd .. - echo -fi - -compile_icu() -{ - if [ ! -d lib_$platform ] || [ ! -d bin_$platform ]; then - (set -x; cmd.exe /c "..\\cpp-ethereum\\windows\\compile_icu.bat $platform") - if [ $platform == "x64" ]; then - icu_suff="64" - else - icu_suff="" - fi - rm -rf lib_$platform - rm -rf bin_$platform - mv lib$icu_suff lib_$platform - mv bin$icu_suff bin_$platform - fi -} - -if [[ ! $@ ]] || [ $1 == "compile-icu" ]; then - cd icu - platform="x64"; compile_icu - platform="Win32"; compile_icu - cd .. -fi - -compile_qt() -{ - if [ ! -d $platform ]; then - ( - set -x - - # copy icu dlls to Qt bin folder (this is so the Qt tools work without global adjustment to PATH) - mkdir -p $platform/qtbase/bin - cp -a ../icu/bin_$platform/*.dll $platform/qtbase/bin/ - - ( - # remove bash paths - set +x - path_remove_bin - set -x - - # compile qt - cmd.exe /c "..\\cpp-ethereum\\windows\\compile_qt.bat $platform" - ) - ) - fi -} - -if [[ ! $@ ]] || [ $1 == "compile-qt" ]; then - # compile Qt for x86 and x64 - cd Qt - platform="x64"; compile_qt - platform="Win32"; compile_qt - cd .. - echo -fi - -# finally run MS build -cd cpp-ethereum/windows -cmd.exe /c "compile_ethereum.bat" -cd .. \ No newline at end of file diff --git a/windows/compile_ethereum.bat b/windows/compile_ethereum.bat deleted file mode 100644 index 6aa93b155..000000000 --- a/windows/compile_ethereum.bat +++ /dev/null @@ -1,14 +0,0 @@ -@echo off -rem @file compile_ethereum.bat -rem @author Tim Hughes -rem @date 2014 -echo on - -rem : import VC environment -call "%VS120COMNTOOLS%\VsDevCmd.bat" - -rem : build for x64 -msbuild /maxcpucount /p:Configuration=Release;Platform=x64 Ethereum.sln - -rem : build for Win32 -msbuild /maxcpucount /p:Configuration=Release;Platform=Win32 Ethereum.sln diff --git a/windows/compile_icu.bat b/windows/compile_icu.bat deleted file mode 100644 index 93bd21976..000000000 --- a/windows/compile_icu.bat +++ /dev/null @@ -1,11 +0,0 @@ -@echo off -rem @file compile_icu.bat -rem @author Tim Hughes -rem @date 2014 -echo on - -rem : import VC environment -call "%VS120COMNTOOLS%\VsDevCmd.bat" - -rem : build for platform -msbuild /maxcpucount /p:Configuration=Release;Platform=%1% source/allinone/icu.sln diff --git a/windows/compile_qt.bat b/windows/compile_qt.bat deleted file mode 100644 index b11fd42d5..000000000 --- a/windows/compile_qt.bat +++ /dev/null @@ -1,51 +0,0 @@ -@echo off -rem @file compileqt.bat -rem @author Tim Hughes -rem @date 2014 - -rem : enable use prefix if we want to produce standalone Qt binaries -rem : off by default since this takes longer and duplicates all the headers -set USE_PREFIX=0 - -rem : echo commands so we can see what's going on -echo on - -rem : select platform and toolset from first argument -IF %1%==x64 (set PLATFORM=x64&set TOOLSET=x86_amd64&set) ELSE (set PLATFORM=Win32&set TOOLSET=x86=) - -rem : import VC environment vars -call "%VS120COMNTOOLS%\..\..\VC\vcvarsall.bat" %TOOLSET% - -rem : assume our root Qt dir is the current dir -set QT=%CD% - -set PATH=%QT%\Src\gnuwin32\bin;%PATH% - -rem : create the build folder and add the qtbase/bin folder to the PATH -if not exist %QT%\%PLATFORM%\Makefile ( - set DO_CONFIGURE=1 - mkdir %QT%\%PLATFORM% -) else ( - set DO_CONFIGURE=0 -) -if %USE_PREFIX%==1 ( - if not exist %QT%\%PLATFORM%-Build mkdir %QT%\%PLATFORM%-Build - if not exist %QT%\%PLATFORM%\qtbase mkdir %QT%\%PLATFORM%\qtbase - cd %QT%\%PLATFORM%-Build - set QT_PREFIX=-prefix %Qt%\%PLATFORM%\qtbase - set QT_TARGETS=install -) else ( - cd %QT%\%PLATFORM% - set QT_PREFIX= - set QT_TARGETS= -) -set PATH=%CD%\qtbase\bin;%PATH% - -rem : run Qt configure with desired settings -if %DO_CONFIGURE%==1 ( - call %QT%\Src\configure.bat %QT_PREFIX% -opensource -confirm-license -debug-and-release -opengl desktop -platform win32-msvc2013 -icu -I "%QT%\..\icu\include" -L "%QT%\..\icu\lib_%PLATFORM%" -nomake tests -nomake examples -) - -rem : compile and install module-qtbase -%QT%\jom\jom - diff --git a/windows/include/LibLevelDB/port/port.h b/windows/include/LibLevelDB/port/port.h deleted file mode 100644 index ce7ae19c4..000000000 --- a/windows/include/LibLevelDB/port/port.h +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_PORT_PORT_H_ -#define STORAGE_LEVELDB_PORT_PORT_H_ - -#include - -// Include the appropriate platform specific file below. If you are -// porting to a new platform, see "port_example.h" for documentation -// of what the new port_.h file must provide. -#if defined(LEVELDB_PLATFORM_POSIX) -# include "port/port_posix.h" -#elif defined(LEVELDB_PLATFORM_CHROMIUM) -# include "port/port_chromium.h" -#elif defined(LEVELDB_PLATFORM_ANDROID) -# include "port/port_android.h" -#elif defined(LEVELDB_PLATFORM_WINDOWS) -# include "port/port_win.h" -#endif - -#endif // STORAGE_LEVELDB_PORT_PORT_H_ diff --git a/windows/include/LibLevelDB/unistd.h b/windows/include/LibLevelDB/unistd.h deleted file mode 100644 index e69de29bb..000000000 diff --git a/windows/include/LibMiniUPnPc/miniupnpcstrings.h b/windows/include/LibMiniUPnPc/miniupnpcstrings.h deleted file mode 100644 index 364342ecf..000000000 --- a/windows/include/LibMiniUPnPc/miniupnpcstrings.h +++ /dev/null @@ -1,14 +0,0 @@ -/* $Id: miniupnpcstrings.h.in,v 1.4 2011/01/04 11:41:53 nanard Exp $ */ -/* Project: miniupnp - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * Author: Thomas Bernard - * Copyright (c) 2005-2011 Thomas Bernard - * This software is subjects to the conditions detailed - * in the LICENCE file provided within this distribution */ -#ifndef MINIUPNPCSTRINGS_H_INCLUDED -#define MINIUPNPCSTRINGS_H_INCLUDED - -#define OS_STRING "Windows" -#define MINIUPNPC_VERSION_STRING "1.9" - -#endif diff --git a/windows/moc.lua b/windows/moc.lua deleted file mode 100644 index 8a129eeae..000000000 --- a/windows/moc.lua +++ /dev/null @@ -1,38 +0,0 @@ - -local function quote(x) - return '"' .. x .. '"' -end - -local function toForward(x) - return x:gsub('\\', '/') -end - --- arguments are in this order -local cmd = arg[1] -local outFile = arg[2] -local includes = toForward(arg[3]) -local defines = arg[4] -local inFile = arg[5] - --- build list of includes -local includes2 = "" -for i in string.gmatch(includes, "[^;]+") do - includes2 = includes2.." -I "..quote(i) -end -includes = includes2; - --- build list of defines -local defines2 = "" -for i in string.gmatch(defines, "[^;]+") do - defines2 = defines2.." -D"..i -end -defines = defines2 - --- moc doesn't compile boost correctly, so skip those headers -workarounds=' -DBOOST_MP_CPP_INT_HPP -DBOOST_THREAD_WEK01082003_HPP' - --- build command -cmd = quote(cmd).." -o "..quote(outFile)..includes..defines..workarounds..' '..quote(inFile) -print(cmd) -os.execute(quote(cmd)) - diff --git a/windows/ncurses/include/ncurses/curses.h b/windows/ncurses/include/ncurses/curses.h deleted file mode 100644 index ff375d525..000000000 --- a/windows/ncurses/include/ncurses/curses.h +++ /dev/null @@ -1,1675 +0,0 @@ -/**************************************************************************** - * Copyright (c) 1998-2010,2011 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/**************************************************************************** - * Author: Zeyd M. Ben-Halim 1992,1995 * - * and: Eric S. Raymond * - * and: Thomas E. Dickey 1996-on * - ****************************************************************************/ - -/* $Id: curses.h.in,v 1.220 2011/01/22 19:47:20 tom Exp $ */ - -#ifndef __NCURSES_H -#define __NCURSES_H - -#define CURSES 1 -#define CURSES_H 1 - -/* These are defined only in curses.h, and are used for conditional compiles */ -#define NCURSES_VERSION_MAJOR 5 -#define NCURSES_VERSION_MINOR 9 -#define NCURSES_VERSION_PATCH 20110404 - -/* This is defined in more than one ncurses header, for identification */ -#undef NCURSES_VERSION -#define NCURSES_VERSION "5.9" - -/* - * Identify the mouse encoding version. - */ -#define NCURSES_MOUSE_VERSION 1 - -/* - * Definitions to facilitate DLL's. - */ -#include - -/* - * User-definable tweak to disable the include of . - */ -#ifndef NCURSES_ENABLE_STDBOOL_H -#define NCURSES_ENABLE_STDBOOL_H 1 -#endif - -/* - * NCURSES_ATTR_T is used to quiet compiler warnings when building ncurses - * configured using --disable-macros. - */ -#ifdef NCURSES_NOMACROS -#ifndef NCURSES_ATTR_T -#define NCURSES_ATTR_T attr_t -#endif -#endif /* NCURSES_NOMACROS */ - -#ifndef NCURSES_ATTR_T -#define NCURSES_ATTR_T int -#endif - -/* - * Expands to 'const' if ncurses is configured using --enable-const. Note that - * doing so makes it incompatible with other implementations of X/Open Curses. - */ -#undef NCURSES_CONST -#define NCURSES_CONST /*nothing*/ - -#undef NCURSES_INLINE -#define NCURSES_INLINE inline - -/* - * The internal type used for color values - */ -#undef NCURSES_COLOR_T -#define NCURSES_COLOR_T short - -/* - * Definition used to make WINDOW and similar structs opaque. - */ -#ifndef NCURSES_OPAQUE -#define NCURSES_OPAQUE 0 -#endif - -/* - * The reentrant code relies on the opaque setting, but adds features. - */ -#ifndef NCURSES_REENTRANT -#define NCURSES_REENTRANT 0 -#endif - -/* - * Control whether bindings for interop support are added. - */ -#undef NCURSES_INTEROP_FUNCS -#define NCURSES_INTEROP_FUNCS 0 - -/* - * The internal type used for window dimensions. - */ -#undef NCURSES_SIZE_T -#define NCURSES_SIZE_T short - -/* - * Control whether tparm() supports varargs or fixed-parameter list. - */ -#undef NCURSES_TPARM_VARARGS -#define NCURSES_TPARM_VARARGS 1 - -/* - * NCURSES_CH_T is used in building the library, but not used otherwise in - * this header file, since that would make the normal/wide-character versions - * of the header incompatible. - */ -#undef NCURSES_CH_T -#define NCURSES_CH_T chtype - -#if 0 && defined(_LP64) -typedef unsigned chtype; -typedef unsigned mmask_t; -#else -typedef unsigned long chtype; -typedef unsigned long mmask_t; -#endif - -/* - * We need FILE, etc. Include this before checking any feature symbols. - */ -#include - -/* - * With XPG4, you must define _XOPEN_SOURCE_EXTENDED, it is redundant (or - * conflicting) when _XOPEN_SOURCE is 500 or greater. - */ -#undef NCURSES_WIDECHAR -#if defined(_XOPEN_SOURCE_EXTENDED) || defined(_XPG5) -#define NCURSES_WIDECHAR -#endif - -#include /* we need va_list */ -#ifdef NCURSES_WIDECHAR -#include /* we want wchar_t */ -#endif - -/* X/Open and SVr4 specify that curses implements 'bool'. However, C++ may also - * implement it. If so, we must use the C++ compiler's type to avoid conflict - * with other interfaces. - * - * A further complication is that may declare 'bool' to be a - * different type, such as an enum which is not necessarily compatible with - * C++. If we have , make 'bool' a macro, so users may #undef it. - * Otherwise, let it remain a typedef to avoid conflicts with other #define's. - * In either case, make a typedef for NCURSES_BOOL which can be used if needed - * from either C or C++. - */ - -#undef TRUE -#define TRUE 1 - -#undef FALSE -#define FALSE 0 - -typedef unsigned char NCURSES_BOOL; - -#if defined(__cplusplus) /* __cplusplus, etc. */ - -/* use the C++ compiler's bool type */ -#define NCURSES_BOOL bool - -#else /* c89, c99, etc. */ - -#if NCURSES_ENABLE_STDBOOL_H -#include -/* use whatever the C compiler decides bool really is */ -#define NCURSES_BOOL bool -#else -/* there is no predefined bool - use our own */ -#undef bool -#define bool NCURSES_BOOL -#endif - -#endif /* !__cplusplus, etc. */ - -#ifdef __cplusplus -extern "C" { -#define NCURSES_CAST(type,value) static_cast(value) -#else -#define NCURSES_CAST(type,value) (type)(value) -#endif - -/* - * X/Open attributes. In the ncurses implementation, they are identical to the - * A_ attributes. - */ -#define WA_ATTRIBUTES A_ATTRIBUTES -#define WA_NORMAL A_NORMAL -#define WA_STANDOUT A_STANDOUT -#define WA_UNDERLINE A_UNDERLINE -#define WA_REVERSE A_REVERSE -#define WA_BLINK A_BLINK -#define WA_DIM A_DIM -#define WA_BOLD A_BOLD -#define WA_ALTCHARSET A_ALTCHARSET -#define WA_INVIS A_INVIS -#define WA_PROTECT A_PROTECT -#define WA_HORIZONTAL A_HORIZONTAL -#define WA_LEFT A_LEFT -#define WA_LOW A_LOW -#define WA_RIGHT A_RIGHT -#define WA_TOP A_TOP -#define WA_VERTICAL A_VERTICAL - -/* colors */ -#define COLOR_BLACK 0 -#define COLOR_RED 1 -#define COLOR_GREEN 2 -#define COLOR_YELLOW 3 -#define COLOR_BLUE 4 -#define COLOR_MAGENTA 5 -#define COLOR_CYAN 6 -#define COLOR_WHITE 7 - -/* line graphics */ - -#if 0 || NCURSES_REENTRANT -NCURSES_WRAPPED_VAR(chtype*, acs_map); -#define acs_map NCURSES_PUBLIC_VAR(acs_map()) -#else -extern NCURSES_EXPORT_VAR(chtype) acs_map[]; -#endif - -#define NCURSES_ACS(c) (acs_map[NCURSES_CAST(unsigned char,c)]) - -/* VT100 symbols begin here */ -#define ACS_ULCORNER NCURSES_ACS('l') /* upper left corner */ -#define ACS_LLCORNER NCURSES_ACS('m') /* lower left corner */ -#define ACS_URCORNER NCURSES_ACS('k') /* upper right corner */ -#define ACS_LRCORNER NCURSES_ACS('j') /* lower right corner */ -#define ACS_LTEE NCURSES_ACS('t') /* tee pointing right */ -#define ACS_RTEE NCURSES_ACS('u') /* tee pointing left */ -#define ACS_BTEE NCURSES_ACS('v') /* tee pointing up */ -#define ACS_TTEE NCURSES_ACS('w') /* tee pointing down */ -#define ACS_HLINE NCURSES_ACS('q') /* horizontal line */ -#define ACS_VLINE NCURSES_ACS('x') /* vertical line */ -#define ACS_PLUS NCURSES_ACS('n') /* large plus or crossover */ -#define ACS_S1 NCURSES_ACS('o') /* scan line 1 */ -#define ACS_S9 NCURSES_ACS('s') /* scan line 9 */ -#define ACS_DIAMOND NCURSES_ACS('`') /* diamond */ -#define ACS_CKBOARD NCURSES_ACS('a') /* checker board (stipple) */ -#define ACS_DEGREE NCURSES_ACS('f') /* degree symbol */ -#define ACS_PLMINUS NCURSES_ACS('g') /* plus/minus */ -#define ACS_BULLET NCURSES_ACS('~') /* bullet */ -/* Teletype 5410v1 symbols begin here */ -#define ACS_LARROW NCURSES_ACS(',') /* arrow pointing left */ -#define ACS_RARROW NCURSES_ACS('+') /* arrow pointing right */ -#define ACS_DARROW NCURSES_ACS('.') /* arrow pointing down */ -#define ACS_UARROW NCURSES_ACS('-') /* arrow pointing up */ -#define ACS_BOARD NCURSES_ACS('h') /* board of squares */ -#define ACS_LANTERN NCURSES_ACS('i') /* lantern symbol */ -#define ACS_BLOCK NCURSES_ACS('0') /* solid square block */ -/* - * These aren't documented, but a lot of System Vs have them anyway - * (you can spot pprryyzz{{||}} in a lot of AT&T terminfo strings). - * The ACS_names may not match AT&T's, our source didn't know them. - */ -#define ACS_S3 NCURSES_ACS('p') /* scan line 3 */ -#define ACS_S7 NCURSES_ACS('r') /* scan line 7 */ -#define ACS_LEQUAL NCURSES_ACS('y') /* less/equal */ -#define ACS_GEQUAL NCURSES_ACS('z') /* greater/equal */ -#define ACS_PI NCURSES_ACS('{') /* Pi */ -#define ACS_NEQUAL NCURSES_ACS('|') /* not equal */ -#define ACS_STERLING NCURSES_ACS('}') /* UK pound sign */ - -/* - * Line drawing ACS names are of the form ACS_trbl, where t is the top, r - * is the right, b is the bottom, and l is the left. t, r, b, and l might - * be B (blank), S (single), D (double), or T (thick). The subset defined - * here only uses B and S. - */ -#define ACS_BSSB ACS_ULCORNER -#define ACS_SSBB ACS_LLCORNER -#define ACS_BBSS ACS_URCORNER -#define ACS_SBBS ACS_LRCORNER -#define ACS_SBSS ACS_RTEE -#define ACS_SSSB ACS_LTEE -#define ACS_SSBS ACS_BTEE -#define ACS_BSSS ACS_TTEE -#define ACS_BSBS ACS_HLINE -#define ACS_SBSB ACS_VLINE -#define ACS_SSSS ACS_PLUS - -#undef ERR -#define ERR (-1) - -#undef OK -#define OK (0) - -/* values for the _flags member */ -#define _SUBWIN 0x01 /* is this a sub-window? */ -#define _ENDLINE 0x02 /* is the window flush right? */ -#define _FULLWIN 0x04 /* is the window full-screen? */ -#define _SCROLLWIN 0x08 /* bottom edge is at screen bottom? */ -#define _ISPAD 0x10 /* is this window a pad? */ -#define _HASMOVED 0x20 /* has cursor moved since last refresh? */ -#define _WRAPPED 0x40 /* cursor was just wrappped */ - -/* - * this value is used in the firstchar and lastchar fields to mark - * unchanged lines - */ -#define _NOCHANGE -1 - -/* - * this value is used in the oldindex field to mark lines created by insertions - * and scrolls. - */ -#define _NEWINDEX -1 - -typedef struct screen SCREEN; -typedef struct _win_st WINDOW; - -typedef chtype attr_t; /* ...must be at least as wide as chtype */ - -#ifdef NCURSES_WIDECHAR - -#if 0 -#ifdef mblen /* libutf8.h defines it w/o undefining first */ -#undef mblen -#endif -#include -#endif - -#if 0 -#include /* ...to get mbstate_t, etc. */ -#endif - -#if 0 -typedef unsigned short wchar_t; -#endif - -#if 0 -typedef unsigned int wint_t; -#endif - -/* - * cchar_t stores an array of CCHARW_MAX wide characters. The first is - * normally a spacing character. The others are non-spacing. If those - * (spacing and nonspacing) do not fill the array, a null L'\0' follows. - * Otherwise, a null is assumed to follow when extracting via getcchar(). - */ -#define CCHARW_MAX 5 -typedef struct -{ - attr_t attr; - wchar_t chars[CCHARW_MAX]; -#if 0 -#undef NCURSES_EXT_COLORS -#define NCURSES_EXT_COLORS 20110404 - int ext_color; /* color pair, must be more than 16-bits */ -#endif -} -cchar_t; - -#endif /* NCURSES_WIDECHAR */ - -#if !NCURSES_OPAQUE -struct ldat; - -struct _win_st -{ - NCURSES_SIZE_T _cury, _curx; /* current cursor position */ - - /* window location and size */ - NCURSES_SIZE_T _maxy, _maxx; /* maximums of x and y, NOT window size */ - NCURSES_SIZE_T _begy, _begx; /* screen coords of upper-left-hand corner */ - - short _flags; /* window state flags */ - - /* attribute tracking */ - attr_t _attrs; /* current attribute for non-space character */ - chtype _bkgd; /* current background char/attribute pair */ - - /* option values set by user */ - bool _notimeout; /* no time out on function-key entry? */ - bool _clear; /* consider all data in the window invalid? */ - bool _leaveok; /* OK to not reset cursor on exit? */ - bool _scroll; /* OK to scroll this window? */ - bool _idlok; /* OK to use insert/delete line? */ - bool _idcok; /* OK to use insert/delete char? */ - bool _immed; /* window in immed mode? (not yet used) */ - bool _sync; /* window in sync mode? */ - bool _use_keypad; /* process function keys into KEY_ symbols? */ - int _delay; /* 0 = nodelay, <0 = blocking, >0 = delay */ - - struct ldat *_line; /* the actual line data */ - - /* global screen state */ - NCURSES_SIZE_T _regtop; /* top line of scrolling region */ - NCURSES_SIZE_T _regbottom; /* bottom line of scrolling region */ - - /* these are used only if this is a sub-window */ - int _parx; /* x coordinate of this window in parent */ - int _pary; /* y coordinate of this window in parent */ - WINDOW *_parent; /* pointer to parent if a sub-window */ - - /* these are used only if this is a pad */ - struct pdat - { - NCURSES_SIZE_T _pad_y, _pad_x; - NCURSES_SIZE_T _pad_top, _pad_left; - NCURSES_SIZE_T _pad_bottom, _pad_right; - } _pad; - - NCURSES_SIZE_T _yoffset; /* real begy is _begy + _yoffset */ - -#ifdef NCURSES_WIDECHAR - cchar_t _bkgrnd; /* current background char/attribute pair */ -#if 0 - int _color; /* current color-pair for non-space character */ -#endif -#endif -}; -#endif /* NCURSES_OPAQUE */ - -/* - * This is an extension to support events... - */ -#if 1 -#ifdef NCURSES_WGETCH_EVENTS -#if !defined(__BEOS__) || defined(__HAIKU__) - /* Fix _nc_timed_wait() on BEOS... */ -# define NCURSES_EVENT_VERSION 1 -#endif /* !defined(__BEOS__) */ - -/* - * Bits to set in _nc_event.data.flags - */ -# define _NC_EVENT_TIMEOUT_MSEC 1 -# define _NC_EVENT_FILE 2 -# define _NC_EVENT_FILE_READABLE 2 -# if 0 /* Not supported yet... */ -# define _NC_EVENT_FILE_WRITABLE 4 -# define _NC_EVENT_FILE_EXCEPTION 8 -# endif - -typedef struct -{ - int type; - union - { - long timeout_msec; /* _NC_EVENT_TIMEOUT_MSEC */ - struct - { - unsigned int flags; - int fd; - unsigned int result; - } fev; /* _NC_EVENT_FILE */ - } data; -} _nc_event; - -typedef struct -{ - int count; - int result_flags; /* _NC_EVENT_TIMEOUT_MSEC or _NC_EVENT_FILE_READABLE */ - _nc_event *events[1]; -} _nc_eventlist; - -extern NCURSES_EXPORT(int) wgetch_events (WINDOW *, _nc_eventlist *); /* experimental */ -extern NCURSES_EXPORT(int) wgetnstr_events (WINDOW *,char *,int,_nc_eventlist *);/* experimental */ - -#endif /* NCURSES_WGETCH_EVENTS */ -#endif /* NCURSES_EXT_FUNCS */ - -/* - * GCC (and some other compilers) define '__attribute__'; we're using this - * macro to alert the compiler to flag inconsistencies in printf/scanf-like - * function calls. Just in case '__attribute__' isn't defined, make a dummy. - * Old versions of G++ do not accept it anyway, at least not consistently with - * GCC. - */ -#if !(defined(__GNUC__) || defined(__GNUG__) || defined(__attribute__)) -#define __attribute__(p) /* nothing */ -#endif - -/* - * We cannot define these in ncurses_cfg.h, since they require parameters to be - * passed (that is non-portable). If you happen to be using gcc with warnings - * enabled, define - * GCC_PRINTF - * GCC_SCANF - * to improve checking of calls to printw(), etc. - */ -#ifndef GCC_PRINTFLIKE -#if defined(GCC_PRINTF) && !defined(printf) -#define GCC_PRINTFLIKE(fmt,var) __attribute__((format(printf,fmt,var))) -#else -#define GCC_PRINTFLIKE(fmt,var) /*nothing*/ -#endif -#endif - -#ifndef GCC_SCANFLIKE -#if defined(GCC_SCANF) && !defined(scanf) -#define GCC_SCANFLIKE(fmt,var) __attribute__((format(scanf,fmt,var))) -#else -#define GCC_SCANFLIKE(fmt,var) /*nothing*/ -#endif -#endif - -#ifndef GCC_NORETURN -#define GCC_NORETURN /* nothing */ -#endif - -#ifndef GCC_UNUSED -#define GCC_UNUSED /* nothing */ -#endif - -/* - * Curses uses a helper function. Define our type for this to simplify - * extending it for the sp-funcs feature. - */ -typedef int (*NCURSES_OUTC)(int); - -/* - * Function prototypes. This is the complete X/Open Curses list of required - * functions. Those marked `generated' will have sources generated from the - * macro definitions later in this file, in order to satisfy XPG4.2 - * requirements. - */ - -extern NCURSES_EXPORT(int) addch (const chtype); /* generated */ -extern NCURSES_EXPORT(int) addchnstr (const chtype *, int); /* generated */ -extern NCURSES_EXPORT(int) addchstr (const chtype *); /* generated */ -extern NCURSES_EXPORT(int) addnstr (const char *, int); /* generated */ -extern NCURSES_EXPORT(int) addstr (const char *); /* generated */ -extern NCURSES_EXPORT(int) attroff (NCURSES_ATTR_T); /* generated */ -extern NCURSES_EXPORT(int) attron (NCURSES_ATTR_T); /* generated */ -extern NCURSES_EXPORT(int) attrset (NCURSES_ATTR_T); /* generated */ -extern NCURSES_EXPORT(int) attr_get (attr_t *, short *, void *); /* generated */ -extern NCURSES_EXPORT(int) attr_off (attr_t, void *); /* generated */ -extern NCURSES_EXPORT(int) attr_on (attr_t, void *); /* generated */ -extern NCURSES_EXPORT(int) attr_set (attr_t, short, void *); /* generated */ -extern NCURSES_EXPORT(int) baudrate (void); /* implemented */ -extern NCURSES_EXPORT(int) beep (void); /* implemented */ -extern NCURSES_EXPORT(int) bkgd (chtype); /* generated */ -extern NCURSES_EXPORT(void) bkgdset (chtype); /* generated */ -extern NCURSES_EXPORT(int) border (chtype,chtype,chtype,chtype,chtype,chtype,chtype,chtype); /* generated */ -extern NCURSES_EXPORT(int) box (WINDOW *, chtype, chtype); /* generated */ -extern NCURSES_EXPORT(bool) can_change_color (void); /* implemented */ -extern NCURSES_EXPORT(int) cbreak (void); /* implemented */ -extern NCURSES_EXPORT(int) chgat (int, attr_t, short, const void *); /* generated */ -extern NCURSES_EXPORT(int) clear (void); /* generated */ -extern NCURSES_EXPORT(int) clearok (WINDOW *,bool); /* implemented */ -extern NCURSES_EXPORT(int) clrtobot (void); /* generated */ -extern NCURSES_EXPORT(int) clrtoeol (void); /* generated */ -extern NCURSES_EXPORT(int) color_content (short,short*,short*,short*); /* implemented */ -extern NCURSES_EXPORT(int) color_set (short,void*); /* generated */ -extern NCURSES_EXPORT(int) COLOR_PAIR (int); /* generated */ -extern NCURSES_EXPORT(int) copywin (const WINDOW*,WINDOW*,int,int,int,int,int,int,int); /* implemented */ -extern NCURSES_EXPORT(int) curs_set (int); /* implemented */ -extern NCURSES_EXPORT(int) def_prog_mode (void); /* implemented */ -extern NCURSES_EXPORT(int) def_shell_mode (void); /* implemented */ -extern NCURSES_EXPORT(int) delay_output (int); /* implemented */ -extern NCURSES_EXPORT(int) delch (void); /* generated */ -extern NCURSES_EXPORT(void) delscreen (SCREEN *); /* implemented */ -extern NCURSES_EXPORT(int) delwin (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) deleteln (void); /* generated */ -extern NCURSES_EXPORT(WINDOW *) derwin (WINDOW *,int,int,int,int); /* implemented */ -extern NCURSES_EXPORT(int) doupdate (void); /* implemented */ -extern NCURSES_EXPORT(WINDOW *) dupwin (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) echo (void); /* implemented */ -extern NCURSES_EXPORT(int) echochar (const chtype); /* generated */ -extern NCURSES_EXPORT(int) erase (void); /* generated */ -extern NCURSES_EXPORT(int) endwin (void); /* implemented */ -extern NCURSES_EXPORT(char) erasechar (void); /* implemented */ -extern NCURSES_EXPORT(void) filter (void); /* implemented */ -extern NCURSES_EXPORT(int) flash (void); /* implemented */ -extern NCURSES_EXPORT(int) flushinp (void); /* implemented */ -extern NCURSES_EXPORT(chtype) getbkgd (WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) getch (void); /* generated */ -extern NCURSES_EXPORT(int) getnstr (char *, int); /* generated */ -extern NCURSES_EXPORT(int) getstr (char *); /* generated */ -extern NCURSES_EXPORT(WINDOW *) getwin (FILE *); /* implemented */ -extern NCURSES_EXPORT(int) halfdelay (int); /* implemented */ -extern NCURSES_EXPORT(bool) has_colors (void); /* implemented */ -extern NCURSES_EXPORT(bool) has_ic (void); /* implemented */ -extern NCURSES_EXPORT(bool) has_il (void); /* implemented */ -extern NCURSES_EXPORT(int) hline (chtype, int); /* generated */ -extern NCURSES_EXPORT(void) idcok (WINDOW *, bool); /* implemented */ -extern NCURSES_EXPORT(int) idlok (WINDOW *, bool); /* implemented */ -extern NCURSES_EXPORT(void) immedok (WINDOW *, bool); /* implemented */ -extern NCURSES_EXPORT(chtype) inch (void); /* generated */ -extern NCURSES_EXPORT(int) inchnstr (chtype *, int); /* generated */ -extern NCURSES_EXPORT(int) inchstr (chtype *); /* generated */ -extern NCURSES_EXPORT(WINDOW *) initscr (void); /* implemented */ -extern NCURSES_EXPORT(int) init_color (short,short,short,short); /* implemented */ -extern NCURSES_EXPORT(int) init_pair (short,short,short); /* implemented */ -extern NCURSES_EXPORT(int) innstr (char *, int); /* generated */ -extern NCURSES_EXPORT(int) insch (chtype); /* generated */ -extern NCURSES_EXPORT(int) insdelln (int); /* generated */ -extern NCURSES_EXPORT(int) insertln (void); /* generated */ -extern NCURSES_EXPORT(int) insnstr (const char *, int); /* generated */ -extern NCURSES_EXPORT(int) insstr (const char *); /* generated */ -extern NCURSES_EXPORT(int) instr (char *); /* generated */ -extern NCURSES_EXPORT(int) intrflush (WINDOW *,bool); /* implemented */ -extern NCURSES_EXPORT(bool) isendwin (void); /* implemented */ -extern NCURSES_EXPORT(bool) is_linetouched (WINDOW *,int); /* implemented */ -extern NCURSES_EXPORT(bool) is_wintouched (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(NCURSES_CONST char *) keyname (int); /* implemented */ -extern NCURSES_EXPORT(int) keypad (WINDOW *,bool); /* implemented */ -extern NCURSES_EXPORT(char) killchar (void); /* implemented */ -extern NCURSES_EXPORT(int) leaveok (WINDOW *,bool); /* implemented */ -extern NCURSES_EXPORT(char *) longname (void); /* implemented */ -extern NCURSES_EXPORT(int) meta (WINDOW *,bool); /* implemented */ -extern NCURSES_EXPORT(int) move (int, int); /* generated */ -extern NCURSES_EXPORT(int) mvaddch (int, int, const chtype); /* generated */ -extern NCURSES_EXPORT(int) mvaddchnstr (int, int, const chtype *, int); /* generated */ -extern NCURSES_EXPORT(int) mvaddchstr (int, int, const chtype *); /* generated */ -extern NCURSES_EXPORT(int) mvaddnstr (int, int, const char *, int); /* generated */ -extern NCURSES_EXPORT(int) mvaddstr (int, int, const char *); /* generated */ -extern NCURSES_EXPORT(int) mvchgat (int, int, int, attr_t, short, const void *); /* generated */ -extern NCURSES_EXPORT(int) mvcur (int,int,int,int); /* implemented */ -extern NCURSES_EXPORT(int) mvdelch (int, int); /* generated */ -extern NCURSES_EXPORT(int) mvderwin (WINDOW *, int, int); /* implemented */ -extern NCURSES_EXPORT(int) mvgetch (int, int); /* generated */ -extern NCURSES_EXPORT(int) mvgetnstr (int, int, char *, int); /* generated */ -extern NCURSES_EXPORT(int) mvgetstr (int, int, char *); /* generated */ -extern NCURSES_EXPORT(int) mvhline (int, int, chtype, int); /* generated */ -extern NCURSES_EXPORT(chtype) mvinch (int, int); /* generated */ -extern NCURSES_EXPORT(int) mvinchnstr (int, int, chtype *, int); /* generated */ -extern NCURSES_EXPORT(int) mvinchstr (int, int, chtype *); /* generated */ -extern NCURSES_EXPORT(int) mvinnstr (int, int, char *, int); /* generated */ -extern NCURSES_EXPORT(int) mvinsch (int, int, chtype); /* generated */ -extern NCURSES_EXPORT(int) mvinsnstr (int, int, const char *, int); /* generated */ -extern NCURSES_EXPORT(int) mvinsstr (int, int, const char *); /* generated */ -extern NCURSES_EXPORT(int) mvinstr (int, int, char *); /* generated */ -extern NCURSES_EXPORT(int) mvprintw (int,int, const char *,...) /* implemented */ - GCC_PRINTFLIKE(3,4); -extern NCURSES_EXPORT(int) mvscanw (int,int, NCURSES_CONST char *,...) /* implemented */ - GCC_SCANFLIKE(3,4); -extern NCURSES_EXPORT(int) mvvline (int, int, chtype, int); /* generated */ -extern NCURSES_EXPORT(int) mvwaddch (WINDOW *, int, int, const chtype); /* generated */ -extern NCURSES_EXPORT(int) mvwaddchnstr (WINDOW *, int, int, const chtype *, int);/* generated */ -extern NCURSES_EXPORT(int) mvwaddchstr (WINDOW *, int, int, const chtype *); /* generated */ -extern NCURSES_EXPORT(int) mvwaddnstr (WINDOW *, int, int, const char *, int); /* generated */ -extern NCURSES_EXPORT(int) mvwaddstr (WINDOW *, int, int, const char *); /* generated */ -extern NCURSES_EXPORT(int) mvwchgat (WINDOW *, int, int, int, attr_t, short, const void *);/* generated */ -extern NCURSES_EXPORT(int) mvwdelch (WINDOW *, int, int); /* generated */ -extern NCURSES_EXPORT(int) mvwgetch (WINDOW *, int, int); /* generated */ -extern NCURSES_EXPORT(int) mvwgetnstr (WINDOW *, int, int, char *, int); /* generated */ -extern NCURSES_EXPORT(int) mvwgetstr (WINDOW *, int, int, char *); /* generated */ -extern NCURSES_EXPORT(int) mvwhline (WINDOW *, int, int, chtype, int); /* generated */ -extern NCURSES_EXPORT(int) mvwin (WINDOW *,int,int); /* implemented */ -extern NCURSES_EXPORT(chtype) mvwinch (WINDOW *, int, int); /* generated */ -extern NCURSES_EXPORT(int) mvwinchnstr (WINDOW *, int, int, chtype *, int); /* generated */ -extern NCURSES_EXPORT(int) mvwinchstr (WINDOW *, int, int, chtype *); /* generated */ -extern NCURSES_EXPORT(int) mvwinnstr (WINDOW *, int, int, char *, int); /* generated */ -extern NCURSES_EXPORT(int) mvwinsch (WINDOW *, int, int, chtype); /* generated */ -extern NCURSES_EXPORT(int) mvwinsnstr (WINDOW *, int, int, const char *, int); /* generated */ -extern NCURSES_EXPORT(int) mvwinsstr (WINDOW *, int, int, const char *); /* generated */ -extern NCURSES_EXPORT(int) mvwinstr (WINDOW *, int, int, char *); /* generated */ -extern NCURSES_EXPORT(int) mvwprintw (WINDOW*,int,int, const char *,...) /* implemented */ - GCC_PRINTFLIKE(4,5); -extern NCURSES_EXPORT(int) mvwscanw (WINDOW *,int,int, NCURSES_CONST char *,...) /* implemented */ - GCC_SCANFLIKE(4,5); -extern NCURSES_EXPORT(int) mvwvline (WINDOW *,int, int, chtype, int); /* generated */ -extern NCURSES_EXPORT(int) napms (int); /* implemented */ -extern NCURSES_EXPORT(WINDOW *) newpad (int,int); /* implemented */ -extern NCURSES_EXPORT(SCREEN *) newterm (NCURSES_CONST char *,FILE *,FILE *); /* implemented */ -extern NCURSES_EXPORT(WINDOW *) newwin (int,int,int,int); /* implemented */ -extern NCURSES_EXPORT(int) nl (void); /* implemented */ -extern NCURSES_EXPORT(int) nocbreak (void); /* implemented */ -extern NCURSES_EXPORT(int) nodelay (WINDOW *,bool); /* implemented */ -extern NCURSES_EXPORT(int) noecho (void); /* implemented */ -extern NCURSES_EXPORT(int) nonl (void); /* implemented */ -extern NCURSES_EXPORT(void) noqiflush (void); /* implemented */ -extern NCURSES_EXPORT(int) noraw (void); /* implemented */ -extern NCURSES_EXPORT(int) notimeout (WINDOW *,bool); /* implemented */ -extern NCURSES_EXPORT(int) overlay (const WINDOW*,WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) overwrite (const WINDOW*,WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) pair_content (short,short*,short*); /* implemented */ -extern NCURSES_EXPORT(int) PAIR_NUMBER (int); /* generated */ -extern NCURSES_EXPORT(int) pechochar (WINDOW *, const chtype); /* implemented */ -extern NCURSES_EXPORT(int) pnoutrefresh (WINDOW*,int,int,int,int,int,int);/* implemented */ -extern NCURSES_EXPORT(int) prefresh (WINDOW *,int,int,int,int,int,int); /* implemented */ -extern NCURSES_EXPORT(int) printw (const char *,...) /* implemented */ - GCC_PRINTFLIKE(1,2); -extern NCURSES_EXPORT(int) putwin (WINDOW *, FILE *); /* implemented */ -extern NCURSES_EXPORT(void) qiflush (void); /* implemented */ -extern NCURSES_EXPORT(int) raw (void); /* implemented */ -extern NCURSES_EXPORT(int) redrawwin (WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) refresh (void); /* generated */ -extern NCURSES_EXPORT(int) resetty (void); /* implemented */ -extern NCURSES_EXPORT(int) reset_prog_mode (void); /* implemented */ -extern NCURSES_EXPORT(int) reset_shell_mode (void); /* implemented */ -extern NCURSES_EXPORT(int) ripoffline (int, int (*)(WINDOW *, int)); /* implemented */ -extern NCURSES_EXPORT(int) savetty (void); /* implemented */ -extern NCURSES_EXPORT(int) scanw (NCURSES_CONST char *,...) /* implemented */ - GCC_SCANFLIKE(1,2); -extern NCURSES_EXPORT(int) scr_dump (const char *); /* implemented */ -extern NCURSES_EXPORT(int) scr_init (const char *); /* implemented */ -extern NCURSES_EXPORT(int) scrl (int); /* generated */ -extern NCURSES_EXPORT(int) scroll (WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) scrollok (WINDOW *,bool); /* implemented */ -extern NCURSES_EXPORT(int) scr_restore (const char *); /* implemented */ -extern NCURSES_EXPORT(int) scr_set (const char *); /* implemented */ -extern NCURSES_EXPORT(int) setscrreg (int,int); /* generated */ -extern NCURSES_EXPORT(SCREEN *) set_term (SCREEN *); /* implemented */ -extern NCURSES_EXPORT(int) slk_attroff (const chtype); /* implemented */ -extern NCURSES_EXPORT(int) slk_attr_off (const attr_t, void *); /* generated:WIDEC */ -extern NCURSES_EXPORT(int) slk_attron (const chtype); /* implemented */ -extern NCURSES_EXPORT(int) slk_attr_on (attr_t,void*); /* generated:WIDEC */ -extern NCURSES_EXPORT(int) slk_attrset (const chtype); /* implemented */ -extern NCURSES_EXPORT(attr_t) slk_attr (void); /* implemented */ -extern NCURSES_EXPORT(int) slk_attr_set (const attr_t,short,void*); /* implemented */ -extern NCURSES_EXPORT(int) slk_clear (void); /* implemented */ -extern NCURSES_EXPORT(int) slk_color (short); /* implemented */ -extern NCURSES_EXPORT(int) slk_init (int); /* implemented */ -extern NCURSES_EXPORT(char *) slk_label (int); /* implemented */ -extern NCURSES_EXPORT(int) slk_noutrefresh (void); /* implemented */ -extern NCURSES_EXPORT(int) slk_refresh (void); /* implemented */ -extern NCURSES_EXPORT(int) slk_restore (void); /* implemented */ -extern NCURSES_EXPORT(int) slk_set (int,const char *,int); /* implemented */ -extern NCURSES_EXPORT(int) slk_touch (void); /* implemented */ -extern NCURSES_EXPORT(int) standout (void); /* generated */ -extern NCURSES_EXPORT(int) standend (void); /* generated */ -extern NCURSES_EXPORT(int) start_color (void); /* implemented */ -extern NCURSES_EXPORT(WINDOW *) subpad (WINDOW *, int, int, int, int); /* implemented */ -extern NCURSES_EXPORT(WINDOW *) subwin (WINDOW *, int, int, int, int); /* implemented */ -extern NCURSES_EXPORT(int) syncok (WINDOW *, bool); /* implemented */ -extern NCURSES_EXPORT(chtype) termattrs (void); /* implemented */ -extern NCURSES_EXPORT(char *) termname (void); /* implemented */ -extern NCURSES_EXPORT(void) timeout (int); /* generated */ -extern NCURSES_EXPORT(int) touchline (WINDOW *, int, int); /* generated */ -extern NCURSES_EXPORT(int) touchwin (WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) typeahead (int); /* implemented */ -extern NCURSES_EXPORT(int) ungetch (int); /* implemented */ -extern NCURSES_EXPORT(int) untouchwin (WINDOW *); /* generated */ -extern NCURSES_EXPORT(void) use_env (bool); /* implemented */ -extern NCURSES_EXPORT(int) vidattr (chtype); /* implemented */ -extern NCURSES_EXPORT(int) vidputs (chtype, NCURSES_OUTC); /* implemented */ -extern NCURSES_EXPORT(int) vline (chtype, int); /* generated */ -extern NCURSES_EXPORT(int) vwprintw (WINDOW *, const char *,va_list); /* implemented */ -extern NCURSES_EXPORT(int) vw_printw (WINDOW *, const char *,va_list); /* generated */ -extern NCURSES_EXPORT(int) vwscanw (WINDOW *, NCURSES_CONST char *,va_list); /* implemented */ -extern NCURSES_EXPORT(int) vw_scanw (WINDOW *, NCURSES_CONST char *,va_list); /* generated */ -extern NCURSES_EXPORT(int) waddch (WINDOW *, const chtype); /* implemented */ -extern NCURSES_EXPORT(int) waddchnstr (WINDOW *,const chtype *,int); /* implemented */ -extern NCURSES_EXPORT(int) waddchstr (WINDOW *,const chtype *); /* generated */ -extern NCURSES_EXPORT(int) waddnstr (WINDOW *,const char *,int); /* implemented */ -extern NCURSES_EXPORT(int) waddstr (WINDOW *,const char *); /* generated */ -extern NCURSES_EXPORT(int) wattron (WINDOW *, int); /* generated */ -extern NCURSES_EXPORT(int) wattroff (WINDOW *, int); /* generated */ -extern NCURSES_EXPORT(int) wattrset (WINDOW *, int); /* generated */ -extern NCURSES_EXPORT(int) wattr_get (WINDOW *, attr_t *, short *, void *); /* generated */ -extern NCURSES_EXPORT(int) wattr_on (WINDOW *, attr_t, void *); /* implemented */ -extern NCURSES_EXPORT(int) wattr_off (WINDOW *, attr_t, void *); /* implemented */ -extern NCURSES_EXPORT(int) wattr_set (WINDOW *, attr_t, short, void *); /* generated */ -extern NCURSES_EXPORT(int) wbkgd (WINDOW *, chtype); /* implemented */ -extern NCURSES_EXPORT(void) wbkgdset (WINDOW *,chtype); /* implemented */ -extern NCURSES_EXPORT(int) wborder (WINDOW *,chtype,chtype,chtype,chtype,chtype,chtype,chtype,chtype); /* implemented */ -extern NCURSES_EXPORT(int) wchgat (WINDOW *, int, attr_t, short, const void *);/* implemented */ -extern NCURSES_EXPORT(int) wclear (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) wclrtobot (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) wclrtoeol (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) wcolor_set (WINDOW*,short,void*); /* implemented */ -extern NCURSES_EXPORT(void) wcursyncup (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) wdelch (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) wdeleteln (WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) wechochar (WINDOW *, const chtype); /* implemented */ -extern NCURSES_EXPORT(int) werase (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) wgetch (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) wgetnstr (WINDOW *,char *,int); /* implemented */ -extern NCURSES_EXPORT(int) wgetstr (WINDOW *, char *); /* generated */ -extern NCURSES_EXPORT(int) whline (WINDOW *, chtype, int); /* implemented */ -extern NCURSES_EXPORT(chtype) winch (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) winchnstr (WINDOW *, chtype *, int); /* implemented */ -extern NCURSES_EXPORT(int) winchstr (WINDOW *, chtype *); /* generated */ -extern NCURSES_EXPORT(int) winnstr (WINDOW *, char *, int); /* implemented */ -extern NCURSES_EXPORT(int) winsch (WINDOW *, chtype); /* implemented */ -extern NCURSES_EXPORT(int) winsdelln (WINDOW *,int); /* implemented */ -extern NCURSES_EXPORT(int) winsertln (WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) winsnstr (WINDOW *, const char *,int); /* implemented */ -extern NCURSES_EXPORT(int) winsstr (WINDOW *, const char *); /* generated */ -extern NCURSES_EXPORT(int) winstr (WINDOW *, char *); /* generated */ -extern NCURSES_EXPORT(int) wmove (WINDOW *,int,int); /* implemented */ -extern NCURSES_EXPORT(int) wnoutrefresh (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) wprintw (WINDOW *, const char *,...) /* implemented */ - GCC_PRINTFLIKE(2,3); -extern NCURSES_EXPORT(int) wredrawln (WINDOW *,int,int); /* implemented */ -extern NCURSES_EXPORT(int) wrefresh (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) wscanw (WINDOW *, NCURSES_CONST char *,...) /* implemented */ - GCC_SCANFLIKE(2,3); -extern NCURSES_EXPORT(int) wscrl (WINDOW *,int); /* implemented */ -extern NCURSES_EXPORT(int) wsetscrreg (WINDOW *,int,int); /* implemented */ -extern NCURSES_EXPORT(int) wstandout (WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) wstandend (WINDOW *); /* generated */ -extern NCURSES_EXPORT(void) wsyncdown (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(void) wsyncup (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(void) wtimeout (WINDOW *,int); /* implemented */ -extern NCURSES_EXPORT(int) wtouchln (WINDOW *,int,int,int); /* implemented */ -extern NCURSES_EXPORT(int) wvline (WINDOW *,chtype,int); /* implemented */ - -/* - * These are also declared in : - */ -extern NCURSES_EXPORT(int) tigetflag (NCURSES_CONST char *); /* implemented */ -extern NCURSES_EXPORT(int) tigetnum (NCURSES_CONST char *); /* implemented */ -extern NCURSES_EXPORT(char *) tigetstr (NCURSES_CONST char *); /* implemented */ -extern NCURSES_EXPORT(int) putp (const char *); /* implemented */ - -#if NCURSES_TPARM_VARARGS -extern NCURSES_EXPORT(char *) tparm (NCURSES_CONST char *, ...); /* special */ -#else -extern NCURSES_EXPORT(char *) tparm (NCURSES_CONST char *, long,long,long,long,long,long,long,long,long); /* special */ -extern NCURSES_EXPORT(char *) tparm_varargs (NCURSES_CONST char *, ...); /* special */ -#endif - -extern NCURSES_EXPORT(char *) tiparm (const char *, ...); /* special */ - -/* - * These functions are not in X/Open, but we use them in macro definitions: - */ -extern NCURSES_EXPORT(int) getattrs (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) getcurx (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) getcury (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) getbegx (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) getbegy (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) getmaxx (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) getmaxy (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) getparx (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) getpary (const WINDOW *); /* generated */ - -/* - * vid_attr() was implemented originally based on a draft of X/Open curses. - */ -#ifndef NCURSES_WIDECHAR -#define vid_attr(a,pair,opts) vidattr(a) -#endif - -/* - * These functions are extensions - not in X/Open Curses. - */ -#if 1 -#undef NCURSES_EXT_FUNCS -#define NCURSES_EXT_FUNCS 20110404 -typedef int (*NCURSES_WINDOW_CB)(WINDOW *, void *); -typedef int (*NCURSES_SCREEN_CB)(SCREEN *, void *); -extern NCURSES_EXPORT(bool) is_term_resized (int, int); -extern NCURSES_EXPORT(char *) keybound (int, int); -extern NCURSES_EXPORT(const char *) curses_version (void); -extern NCURSES_EXPORT(int) assume_default_colors (int, int); -extern NCURSES_EXPORT(int) define_key (const char *, int); -extern NCURSES_EXPORT(int) get_escdelay (void); -extern NCURSES_EXPORT(int) key_defined (const char *); -extern NCURSES_EXPORT(int) keyok (int, bool); -extern NCURSES_EXPORT(int) resize_term (int, int); -extern NCURSES_EXPORT(int) resizeterm (int, int); -extern NCURSES_EXPORT(int) set_escdelay (int); -extern NCURSES_EXPORT(int) set_tabsize (int); -extern NCURSES_EXPORT(int) use_default_colors (void); -extern NCURSES_EXPORT(int) use_extended_names (bool); -extern NCURSES_EXPORT(int) use_legacy_coding (int); -extern NCURSES_EXPORT(int) use_screen (SCREEN *, NCURSES_SCREEN_CB, void *); -extern NCURSES_EXPORT(int) use_window (WINDOW *, NCURSES_WINDOW_CB, void *); -extern NCURSES_EXPORT(int) wresize (WINDOW *, int, int); -extern NCURSES_EXPORT(void) nofilter(void); - -/* - * These extensions provide access to information stored in the WINDOW even - * when NCURSES_OPAQUE is set: - */ -extern NCURSES_EXPORT(WINDOW *) wgetparent (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(bool) is_cleared (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(bool) is_idcok (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(bool) is_idlok (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(bool) is_immedok (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(bool) is_keypad (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(bool) is_leaveok (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(bool) is_nodelay (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(bool) is_notimeout (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(bool) is_pad (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(bool) is_scrollok (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(bool) is_subwin (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(bool) is_syncok (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) wgetscrreg (const WINDOW *, int *, int *); /* generated */ - -#else -#define curses_version() NCURSES_VERSION -#endif - -/* - * Extra extension-functions, which pass a SCREEN pointer rather than using - * a global variable SP. - */ -#if 1 -#undef NCURSES_SP_FUNCS -#define NCURSES_SP_FUNCS 20110404 -#define NCURSES_SP_NAME(name) name##_sp - -/* Define the sp-funcs helper function */ -#define NCURSES_SP_OUTC NCURSES_SP_NAME(NCURSES_OUTC) -typedef int (*NCURSES_SP_OUTC)(SCREEN*, int); - -extern NCURSES_EXPORT(SCREEN *) new_prescr (void); /* implemented:SP_FUNC */ - -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(baudrate) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(beep) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(bool) NCURSES_SP_NAME(can_change_color) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(cbreak) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(curs_set) (SCREEN*, int); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(color_content) (SCREEN*, short, short*, short*, short*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(def_prog_mode) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(def_shell_mode) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(delay_output) (SCREEN*, int); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(doupdate) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(echo) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(endwin) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(char) NCURSES_SP_NAME(erasechar) (SCREEN*);/* implemented:SP_FUNC */ -extern NCURSES_EXPORT(void) NCURSES_SP_NAME(filter) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(flash) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(flushinp) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(WINDOW *) NCURSES_SP_NAME(getwin) (SCREEN*, FILE *); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(halfdelay) (SCREEN*, int); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(bool) NCURSES_SP_NAME(has_colors) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(bool) NCURSES_SP_NAME(has_ic) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(bool) NCURSES_SP_NAME(has_il) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(init_color) (SCREEN*, short, short, short, short); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(init_pair) (SCREEN*, short, short, short); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(intrflush) (SCREEN*, WINDOW*, bool); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(bool) NCURSES_SP_NAME(isendwin) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(NCURSES_CONST char *) NCURSES_SP_NAME(keyname) (SCREEN*, int); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(char) NCURSES_SP_NAME(killchar) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(longname) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(mvcur) (SCREEN*, int, int, int, int); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(napms) (SCREEN*, int); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(WINDOW *) NCURSES_SP_NAME(newpad) (SCREEN*, int, int); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(SCREEN *) NCURSES_SP_NAME(newterm) (SCREEN*, NCURSES_CONST char *, FILE *, FILE *); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(WINDOW *) NCURSES_SP_NAME(newwin) (SCREEN*, int, int, int, int); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(nl) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(nocbreak) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(noecho) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(nonl) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(void) NCURSES_SP_NAME(noqiflush) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(noraw) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(pair_content) (SCREEN*, short, short*, short*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(void) NCURSES_SP_NAME(qiflush) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(raw) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(reset_prog_mode) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(reset_shell_mode) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(resetty) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(ripoffline) (SCREEN*, int, int (*)(WINDOW *, int)); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(savetty) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(scr_init) (SCREEN*, const char *); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(scr_restore) (SCREEN*, const char *); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(scr_set) (SCREEN*, const char *); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_attroff) (SCREEN*, const chtype); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_attron) (SCREEN*, const chtype); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_attrset) (SCREEN*, const chtype); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(attr_t) NCURSES_SP_NAME(slk_attr) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_attr_set) (SCREEN*, const attr_t, short, void*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_clear) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_color) (SCREEN*, short); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_init) (SCREEN*, int); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(slk_label) (SCREEN*, int); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_noutrefresh) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_refresh) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_restore) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_set) (SCREEN*, int, const char *, int); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_touch) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(start_color) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(chtype) NCURSES_SP_NAME(termattrs) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(termname) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(typeahead) (SCREEN*, int); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(ungetch) (SCREEN*, int); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(void) NCURSES_SP_NAME(use_env) (SCREEN*, bool); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(vidattr) (SCREEN*, chtype); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(vidputs) (SCREEN*, chtype, NCURSES_SP_OUTC); /* implemented:SP_FUNC */ -#if 1 -extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(keybound) (SCREEN*, int, int); /* implemented:EXT_SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(assume_default_colors) (SCREEN*, int, int); /* implemented:EXT_SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(define_key) (SCREEN*, const char *, int); /* implemented:EXT_SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(get_escdelay) (SCREEN*); /* implemented:EXT_SP_FUNC */ -extern NCURSES_EXPORT(bool) NCURSES_SP_NAME(is_term_resized) (SCREEN*, int, int); /* implemented:EXT_SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(key_defined) (SCREEN*, const char *); /* implemented:EXT_SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(keyok) (SCREEN*, int, bool); /* implemented:EXT_SP_FUNC */ -extern NCURSES_EXPORT(void) NCURSES_SP_NAME(nofilter) (SCREEN*); /* implemented */ /* implemented:EXT_SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(resize_term) (SCREEN*, int, int); /* implemented:EXT_SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(resizeterm) (SCREEN*, int, int); /* implemented:EXT_SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(set_escdelay) (SCREEN*, int); /* implemented:EXT_SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(set_tabsize) (SCREEN*, int); /* implemented:EXT_SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(use_default_colors) (SCREEN*); /* implemented:EXT_SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(use_legacy_coding) (SCREEN*, int); /* implemented:EXT_SP_FUNC */ -#endif -#else -#undef NCURSES_SP_FUNCS -#define NCURSES_SP_FUNCS 0 -#define NCURSES_SP_NAME(name) name -#define NCURSES_SP_OUTC NCURSES_OUTC -#endif - -/* attributes */ - -#define NCURSES_ATTR_SHIFT 8 -#define NCURSES_BITS(mask,shift) ((mask) << ((shift) + NCURSES_ATTR_SHIFT)) - -#define A_NORMAL (1UL - 1UL) -#define A_ATTRIBUTES NCURSES_BITS(~(1UL - 1UL),0) -#define A_CHARTEXT (NCURSES_BITS(1UL,0) - 1UL) -#define A_COLOR NCURSES_BITS(((1UL) << 8) - 1UL,0) -#define A_STANDOUT NCURSES_BITS(1UL,8) -#define A_UNDERLINE NCURSES_BITS(1UL,9) -#define A_REVERSE NCURSES_BITS(1UL,10) -#define A_BLINK NCURSES_BITS(1UL,11) -#define A_DIM NCURSES_BITS(1UL,12) -#define A_BOLD NCURSES_BITS(1UL,13) -#define A_ALTCHARSET NCURSES_BITS(1UL,14) -#define A_INVIS NCURSES_BITS(1UL,15) -#define A_PROTECT NCURSES_BITS(1UL,16) -#define A_HORIZONTAL NCURSES_BITS(1UL,17) -#define A_LEFT NCURSES_BITS(1UL,18) -#define A_LOW NCURSES_BITS(1UL,19) -#define A_RIGHT NCURSES_BITS(1UL,20) -#define A_TOP NCURSES_BITS(1UL,21) -#define A_VERTICAL NCURSES_BITS(1UL,22) - -/* - * Most of the pseudo functions are macros that either provide compatibility - * with older versions of curses, or provide inline functionality to improve - * performance. - */ - -/* - * These pseudo functions are always implemented as macros: - */ - -#define getyx(win,y,x) (y = getcury(win), x = getcurx(win)) -#define getbegyx(win,y,x) (y = getbegy(win), x = getbegx(win)) -#define getmaxyx(win,y,x) (y = getmaxy(win), x = getmaxx(win)) -#define getparyx(win,y,x) (y = getpary(win), x = getparx(win)) - -#define getsyx(y,x) do { if (newscr) { \ - if (is_leaveok(newscr)) \ - (y) = (x) = -1; \ - else \ - getyx(newscr,(y), (x)); \ - } \ - } while(0) - -#define setsyx(y,x) do { if (newscr) { \ - if ((y) == -1 && (x) == -1) \ - leaveok(newscr, TRUE); \ - else { \ - leaveok(newscr, FALSE); \ - wmove(newscr, (y), (x)); \ - } \ - } \ - } while(0) - -#ifndef NCURSES_NOMACROS - -/* - * These miscellaneous pseudo functions are provided for compatibility: - */ - -#define wgetstr(w, s) wgetnstr(w, s, -1) -#define getnstr(s, n) wgetnstr(stdscr, s, n) - -#define setterm(term) setupterm(term, 1, (int *)0) - -#define fixterm() reset_prog_mode() -#define resetterm() reset_shell_mode() -#define saveterm() def_prog_mode() -#define crmode() cbreak() -#define nocrmode() nocbreak() -#define gettmode() - -/* It seems older SYSV curses versions define these */ -#if !NCURSES_OPAQUE -#define getattrs(win) NCURSES_CAST(int, (win) ? (win)->_attrs : A_NORMAL) -#define getcurx(win) ((win) ? (win)->_curx : ERR) -#define getcury(win) ((win) ? (win)->_cury : ERR) -#define getbegx(win) ((win) ? (win)->_begx : ERR) -#define getbegy(win) ((win) ? (win)->_begy : ERR) -#define getmaxx(win) ((win) ? ((win)->_maxx + 1) : ERR) -#define getmaxy(win) ((win) ? ((win)->_maxy + 1) : ERR) -#define getparx(win) ((win) ? (win)->_parx : ERR) -#define getpary(win) ((win) ? (win)->_pary : ERR) -#endif /* NCURSES_OPAQUE */ - -#define wstandout(win) (wattrset(win,A_STANDOUT)) -#define wstandend(win) (wattrset(win,A_NORMAL)) - -#define wattron(win,at) wattr_on(win, NCURSES_CAST(attr_t, at), NULL) -#define wattroff(win,at) wattr_off(win, NCURSES_CAST(attr_t, at), NULL) - -#if !NCURSES_OPAQUE -#if defined(NCURSES_WIDECHAR) && 0 -#define wattrset(win,at) ((win) \ - ? ((win)->_color = PAIR_NUMBER(at), \ - (win)->_attrs = NCURSES_CAST(attr_t, at), \ - OK) \ - : ERR) -#else -#define wattrset(win,at) ((win) \ - ? ((win)->_attrs = NCURSES_CAST(attr_t, at), \ - OK) \ - : ERR) -#endif -#endif /* NCURSES_OPAQUE */ - -#define scroll(win) wscrl(win,1) - -#define touchwin(win) wtouchln((win), 0, getmaxy(win), 1) -#define touchline(win, s, c) wtouchln((win), s, c, 1) -#define untouchwin(win) wtouchln((win), 0, getmaxy(win), 0) - -#define box(win, v, h) wborder(win, v, v, h, h, 0, 0, 0, 0) -#define border(ls, rs, ts, bs, tl, tr, bl, br) wborder(stdscr, ls, rs, ts, bs, tl, tr, bl, br) -#define hline(ch, n) whline(stdscr, ch, n) -#define vline(ch, n) wvline(stdscr, ch, n) - -#define winstr(w, s) winnstr(w, s, -1) -#define winchstr(w, s) winchnstr(w, s, -1) -#define winsstr(w, s) winsnstr(w, s, -1) - -#if !NCURSES_OPAQUE -#define redrawwin(win) wredrawln(win, 0, (win)->_maxy+1) -#endif /* NCURSES_OPAQUE */ - -#define waddstr(win,str) waddnstr(win,str,-1) -#define waddchstr(win,str) waddchnstr(win,str,-1) - -/* - * These apply to the first 256 color pairs. - */ -#define COLOR_PAIR(n) NCURSES_BITS(n, 0) -#define PAIR_NUMBER(a) (NCURSES_CAST(int,((NCURSES_CAST(unsigned long,a) & A_COLOR) >> NCURSES_ATTR_SHIFT))) - -/* - * pseudo functions for standard screen - */ - -#define addch(ch) waddch(stdscr,ch) -#define addchnstr(str,n) waddchnstr(stdscr,str,n) -#define addchstr(str) waddchstr(stdscr,str) -#define addnstr(str,n) waddnstr(stdscr,str,n) -#define addstr(str) waddnstr(stdscr,str,-1) -#define attroff(at) wattroff(stdscr,at) -#define attron(at) wattron(stdscr,at) -#define attrset(at) wattrset(stdscr,at) -#define attr_get(ap,cp,o) wattr_get(stdscr,ap,cp,o) -#define attr_off(a,o) wattr_off(stdscr,a,o) -#define attr_on(a,o) wattr_on(stdscr,a,o) -#define attr_set(a,c,o) wattr_set(stdscr,a,c,o) -#define bkgd(ch) wbkgd(stdscr,ch) -#define bkgdset(ch) wbkgdset(stdscr,ch) -#define chgat(n,a,c,o) wchgat(stdscr,n,a,c,o) -#define clear() wclear(stdscr) -#define clrtobot() wclrtobot(stdscr) -#define clrtoeol() wclrtoeol(stdscr) -#define color_set(c,o) wcolor_set(stdscr,c,o) -#define delch() wdelch(stdscr) -#define deleteln() winsdelln(stdscr,-1) -#define echochar(c) wechochar(stdscr,c) -#define erase() werase(stdscr) -#define getch() wgetch(stdscr) -#define getstr(str) wgetstr(stdscr,str) -#define inch() winch(stdscr) -#define inchnstr(s,n) winchnstr(stdscr,s,n) -#define inchstr(s) winchstr(stdscr,s) -#define innstr(s,n) winnstr(stdscr,s,n) -#define insch(c) winsch(stdscr,c) -#define insdelln(n) winsdelln(stdscr,n) -#define insertln() winsdelln(stdscr,1) -#define insnstr(s,n) winsnstr(stdscr,s,n) -#define insstr(s) winsstr(stdscr,s) -#define instr(s) winstr(stdscr,s) -#define move(y,x) wmove(stdscr,y,x) -#define refresh() wrefresh(stdscr) -#define scrl(n) wscrl(stdscr,n) -#define setscrreg(t,b) wsetscrreg(stdscr,t,b) -#define standend() wstandend(stdscr) -#define standout() wstandout(stdscr) -#define timeout(delay) wtimeout(stdscr,delay) -#define wdeleteln(win) winsdelln(win,-1) -#define winsertln(win) winsdelln(win,1) - -/* - * mv functions - */ - -#define mvwaddch(win,y,x,ch) (wmove(win,y,x) == ERR ? ERR : waddch(win,ch)) -#define mvwaddchnstr(win,y,x,str,n) (wmove(win,y,x) == ERR ? ERR : waddchnstr(win,str,n)) -#define mvwaddchstr(win,y,x,str) (wmove(win,y,x) == ERR ? ERR : waddchnstr(win,str,-1)) -#define mvwaddnstr(win,y,x,str,n) (wmove(win,y,x) == ERR ? ERR : waddnstr(win,str,n)) -#define mvwaddstr(win,y,x,str) (wmove(win,y,x) == ERR ? ERR : waddnstr(win,str,-1)) -#define mvwdelch(win,y,x) (wmove(win,y,x) == ERR ? ERR : wdelch(win)) -#define mvwchgat(win,y,x,n,a,c,o) (wmove(win,y,x) == ERR ? ERR : wchgat(win,n,a,c,o)) -#define mvwgetch(win,y,x) (wmove(win,y,x) == ERR ? ERR : wgetch(win)) -#define mvwgetnstr(win,y,x,str,n) (wmove(win,y,x) == ERR ? ERR : wgetnstr(win,str,n)) -#define mvwgetstr(win,y,x,str) (wmove(win,y,x) == ERR ? ERR : wgetstr(win,str)) -#define mvwhline(win,y,x,c,n) (wmove(win,y,x) == ERR ? ERR : whline(win,c,n)) -#define mvwinch(win,y,x) (wmove(win,y,x) == ERR ? NCURSES_CAST(chtype, ERR) : winch(win)) -#define mvwinchnstr(win,y,x,s,n) (wmove(win,y,x) == ERR ? ERR : winchnstr(win,s,n)) -#define mvwinchstr(win,y,x,s) (wmove(win,y,x) == ERR ? ERR : winchstr(win,s)) -#define mvwinnstr(win,y,x,s,n) (wmove(win,y,x) == ERR ? ERR : winnstr(win,s,n)) -#define mvwinsch(win,y,x,c) (wmove(win,y,x) == ERR ? ERR : winsch(win,c)) -#define mvwinsnstr(win,y,x,s,n) (wmove(win,y,x) == ERR ? ERR : winsnstr(win,s,n)) -#define mvwinsstr(win,y,x,s) (wmove(win,y,x) == ERR ? ERR : winsstr(win,s)) -#define mvwinstr(win,y,x,s) (wmove(win,y,x) == ERR ? ERR : winstr(win,s)) -#define mvwvline(win,y,x,c,n) (wmove(win,y,x) == ERR ? ERR : wvline(win,c,n)) - -#define mvaddch(y,x,ch) mvwaddch(stdscr,y,x,ch) -#define mvaddchnstr(y,x,str,n) mvwaddchnstr(stdscr,y,x,str,n) -#define mvaddchstr(y,x,str) mvwaddchstr(stdscr,y,x,str) -#define mvaddnstr(y,x,str,n) mvwaddnstr(stdscr,y,x,str,n) -#define mvaddstr(y,x,str) mvwaddstr(stdscr,y,x,str) -#define mvchgat(y,x,n,a,c,o) mvwchgat(stdscr,y,x,n,a,c,o) -#define mvdelch(y,x) mvwdelch(stdscr,y,x) -#define mvgetch(y,x) mvwgetch(stdscr,y,x) -#define mvgetnstr(y,x,str,n) mvwgetnstr(stdscr,y,x,str,n) -#define mvgetstr(y,x,str) mvwgetstr(stdscr,y,x,str) -#define mvhline(y,x,c,n) mvwhline(stdscr,y,x,c,n) -#define mvinch(y,x) mvwinch(stdscr,y,x) -#define mvinchnstr(y,x,s,n) mvwinchnstr(stdscr,y,x,s,n) -#define mvinchstr(y,x,s) mvwinchstr(stdscr,y,x,s) -#define mvinnstr(y,x,s,n) mvwinnstr(stdscr,y,x,s,n) -#define mvinsch(y,x,c) mvwinsch(stdscr,y,x,c) -#define mvinsnstr(y,x,s,n) mvwinsnstr(stdscr,y,x,s,n) -#define mvinsstr(y,x,s) mvwinsstr(stdscr,y,x,s) -#define mvinstr(y,x,s) mvwinstr(stdscr,y,x,s) -#define mvvline(y,x,c,n) mvwvline(stdscr,y,x,c,n) - -/* - * Some wide-character functions can be implemented without the extensions. - */ -#if !NCURSES_OPAQUE -#define getbkgd(win) ((win)->_bkgd) -#endif /* NCURSES_OPAQUE */ - -#define slk_attr_off(a,v) ((v) ? ERR : slk_attroff(a)) -#define slk_attr_on(a,v) ((v) ? ERR : slk_attron(a)) - -#if !NCURSES_OPAQUE -#if defined(NCURSES_WIDECHAR) && 0 -#define wattr_set(win,a,p,opts) ((win)->_attrs = ((a) & ~A_COLOR), \ - (win)->_color = (p), \ - OK) -#define wattr_get(win,a,p,opts) ((void)((a) != (void *)0 && (*(a) = (win)->_attrs)), \ - (void)((p) != (void *)0 && (*(p) = (short)(win)->_color)), \ - OK) -#else -#define wattr_set(win,a,p,opts) ((win)->_attrs = (((a) & ~A_COLOR) | (attr_t)COLOR_PAIR(p)), OK) -#define wattr_get(win,a,p,opts) ((void)((a) != (void *)0 && (*(a) = (win)->_attrs)), \ - (void)((p) != (void *)0 && (*(p) = (short)PAIR_NUMBER((win)->_attrs))), \ - OK) -#endif -#endif /* NCURSES_OPAQUE */ - -/* - * X/Open curses deprecates SVr4 vwprintw/vwscanw, which are supposed to use - * varargs.h. It adds new calls vw_printw/vw_scanw, which are supposed to - * use POSIX stdarg.h. The ncurses versions of vwprintw/vwscanw already - * use stdarg.h, so... - */ -#define vw_printw vwprintw -#define vw_scanw vwscanw - -/* - * Export fallback function for use in C++ binding. - */ -#if !1 -#define vsscanf(a,b,c) _nc_vsscanf(a,b,c) -NCURSES_EXPORT(int) vsscanf(const char *, const char *, va_list); -#endif - -/* - * These macros are extensions - not in X/Open Curses. - */ -#if 1 -#if !NCURSES_OPAQUE -#define is_cleared(win) ((win) ? (win)->_clear : FALSE) -#define is_idcok(win) ((win) ? (win)->_idcok : FALSE) -#define is_idlok(win) ((win) ? (win)->_idlok : FALSE) -#define is_immedok(win) ((win) ? (win)->_immed : FALSE) -#define is_keypad(win) ((win) ? (win)->_use_keypad : FALSE) -#define is_leaveok(win) ((win) ? (win)->_leaveok : FALSE) -#define is_nodelay(win) ((win) ? ((win)->_delay == 0) : FALSE) -#define is_notimeout(win) ((win) ? (win)->_notimeout : FALSE) -#define is_pad(win) ((win) ? ((win)->_flags & _ISPAD) != 0 : FALSE) -#define is_scrollok(win) ((win) ? (win)->_scroll : FALSE) -#define is_subwin(win) ((win) ? ((win)->_flags & _SUBWIN) != 0 : FALSE) -#define is_syncok(win) ((win) ? (win)->_sync : FALSE) -#define wgetparent(win) ((win) ? (win)->_parent : 0) -#define wgetscrreg(win,t,b) ((win) ? (*(t) = (win)->_regtop, *(b) = (win)->_regbottom, OK) : ERR) -#endif -#endif - -#endif /* NCURSES_NOMACROS */ - -/* - * Public variables. - * - * Notes: - * a. ESCDELAY was an undocumented feature under AIX curses. - * It gives the ESC expire time in milliseconds. - * b. ttytype is needed for backward compatibility - */ -#if NCURSES_REENTRANT - -NCURSES_WRAPPED_VAR(WINDOW *, curscr); -NCURSES_WRAPPED_VAR(WINDOW *, newscr); -NCURSES_WRAPPED_VAR(WINDOW *, stdscr); -NCURSES_WRAPPED_VAR(char *, ttytype); -NCURSES_WRAPPED_VAR(int, COLORS); -NCURSES_WRAPPED_VAR(int, COLOR_PAIRS); -NCURSES_WRAPPED_VAR(int, COLS); -NCURSES_WRAPPED_VAR(int, ESCDELAY); -NCURSES_WRAPPED_VAR(int, LINES); -NCURSES_WRAPPED_VAR(int, TABSIZE); - -#define curscr NCURSES_PUBLIC_VAR(curscr()) -#define newscr NCURSES_PUBLIC_VAR(newscr()) -#define stdscr NCURSES_PUBLIC_VAR(stdscr()) -#define ttytype NCURSES_PUBLIC_VAR(ttytype()) -#define COLORS NCURSES_PUBLIC_VAR(COLORS()) -#define COLOR_PAIRS NCURSES_PUBLIC_VAR(COLOR_PAIRS()) -#define COLS NCURSES_PUBLIC_VAR(COLS()) -#define ESCDELAY NCURSES_PUBLIC_VAR(ESCDELAY()) -#define LINES NCURSES_PUBLIC_VAR(LINES()) -#define TABSIZE NCURSES_PUBLIC_VAR(TABSIZE()) - -#else - -extern NCURSES_EXPORT_VAR(WINDOW *) curscr; -extern NCURSES_EXPORT_VAR(WINDOW *) newscr; -extern NCURSES_EXPORT_VAR(WINDOW *) stdscr; -extern NCURSES_EXPORT_VAR(char) ttytype[]; -extern NCURSES_EXPORT_VAR(int) COLORS; -extern NCURSES_EXPORT_VAR(int) COLOR_PAIRS; -extern NCURSES_EXPORT_VAR(int) COLS; -extern NCURSES_EXPORT_VAR(int) ESCDELAY; -extern NCURSES_EXPORT_VAR(int) LINES; -extern NCURSES_EXPORT_VAR(int) TABSIZE; - -#endif - -/* - * Pseudo-character tokens outside ASCII range. The curses wgetch() function - * will return any given one of these only if the corresponding k- capability - * is defined in your terminal's terminfo entry. - * - * Some keys (KEY_A1, etc) are arranged like this: - * a1 up a3 - * left b2 right - * c1 down c3 - * - * A few key codes do not depend upon the terminfo entry. - */ -#define KEY_CODE_YES 0400 /* A wchar_t contains a key code */ -#define KEY_MIN 0401 /* Minimum curses key */ -#define KEY_BREAK 0401 /* Break key (unreliable) */ -#define KEY_SRESET 0530 /* Soft (partial) reset (unreliable) */ -#define KEY_RESET 0531 /* Reset or hard reset (unreliable) */ -/* - * These definitions were generated by ./MKkey_defs.sh ./Caps - */ -#define KEY_DOWN 0402 /* down-arrow key */ -#define KEY_UP 0403 /* up-arrow key */ -#define KEY_LEFT 0404 /* left-arrow key */ -#define KEY_RIGHT 0405 /* right-arrow key */ -#define KEY_HOME 0406 /* home key */ -#define KEY_BACKSPACE 0407 /* backspace key */ -#define KEY_F0 0410 /* Function keys. Space for 64 */ -#define KEY_F(n) (KEY_F0+(n)) /* Value of function key n */ -#define KEY_DL 0510 /* delete-line key */ -#define KEY_IL 0511 /* insert-line key */ -#define KEY_DC 0512 /* delete-character key */ -#define KEY_IC 0513 /* insert-character key */ -#define KEY_EIC 0514 /* sent by rmir or smir in insert mode */ -#define KEY_CLEAR 0515 /* clear-screen or erase key */ -#define KEY_EOS 0516 /* clear-to-end-of-screen key */ -#define KEY_EOL 0517 /* clear-to-end-of-line key */ -#define KEY_SF 0520 /* scroll-forward key */ -#define KEY_SR 0521 /* scroll-backward key */ -#define KEY_NPAGE 0522 /* next-page key */ -#define KEY_PPAGE 0523 /* previous-page key */ -#define KEY_STAB 0524 /* set-tab key */ -#define KEY_CTAB 0525 /* clear-tab key */ -#define KEY_CATAB 0526 /* clear-all-tabs key */ -#define KEY_ENTER 0527 /* enter/send key */ -#define KEY_PRINT 0532 /* print key */ -#define KEY_LL 0533 /* lower-left key (home down) */ -#define KEY_A1 0534 /* upper left of keypad */ -#define KEY_A3 0535 /* upper right of keypad */ -#define KEY_B2 0536 /* center of keypad */ -#define KEY_C1 0537 /* lower left of keypad */ -#define KEY_C3 0540 /* lower right of keypad */ -#define KEY_BTAB 0541 /* back-tab key */ -#define KEY_BEG 0542 /* begin key */ -#define KEY_CANCEL 0543 /* cancel key */ -#define KEY_CLOSE 0544 /* close key */ -#define KEY_COMMAND 0545 /* command key */ -#define KEY_COPY 0546 /* copy key */ -#define KEY_CREATE 0547 /* create key */ -#define KEY_END 0550 /* end key */ -#define KEY_EXIT 0551 /* exit key */ -#define KEY_FIND 0552 /* find key */ -#define KEY_HELP 0553 /* help key */ -#define KEY_MARK 0554 /* mark key */ -#define KEY_MESSAGE 0555 /* message key */ -#define KEY_MOVE 0556 /* move key */ -#define KEY_NEXT 0557 /* next key */ -#define KEY_OPEN 0560 /* open key */ -#define KEY_OPTIONS 0561 /* options key */ -#define KEY_PREVIOUS 0562 /* previous key */ -#define KEY_REDO 0563 /* redo key */ -#define KEY_REFERENCE 0564 /* reference key */ -#define KEY_REFRESH 0565 /* refresh key */ -#define KEY_REPLACE 0566 /* replace key */ -#define KEY_RESTART 0567 /* restart key */ -#define KEY_RESUME 0570 /* resume key */ -#define KEY_SAVE 0571 /* save key */ -#define KEY_SBEG 0572 /* shifted begin key */ -#define KEY_SCANCEL 0573 /* shifted cancel key */ -#define KEY_SCOMMAND 0574 /* shifted command key */ -#define KEY_SCOPY 0575 /* shifted copy key */ -#define KEY_SCREATE 0576 /* shifted create key */ -#define KEY_SDC 0577 /* shifted delete-character key */ -#define KEY_SDL 0600 /* shifted delete-line key */ -#define KEY_SELECT 0601 /* select key */ -#define KEY_SEND 0602 /* shifted end key */ -#define KEY_SEOL 0603 /* shifted clear-to-end-of-line key */ -#define KEY_SEXIT 0604 /* shifted exit key */ -#define KEY_SFIND 0605 /* shifted find key */ -#define KEY_SHELP 0606 /* shifted help key */ -#define KEY_SHOME 0607 /* shifted home key */ -#define KEY_SIC 0610 /* shifted insert-character key */ -#define KEY_SLEFT 0611 /* shifted left-arrow key */ -#define KEY_SMESSAGE 0612 /* shifted message key */ -#define KEY_SMOVE 0613 /* shifted move key */ -#define KEY_SNEXT 0614 /* shifted next key */ -#define KEY_SOPTIONS 0615 /* shifted options key */ -#define KEY_SPREVIOUS 0616 /* shifted previous key */ -#define KEY_SPRINT 0617 /* shifted print key */ -#define KEY_SREDO 0620 /* shifted redo key */ -#define KEY_SREPLACE 0621 /* shifted replace key */ -#define KEY_SRIGHT 0622 /* shifted right-arrow key */ -#define KEY_SRSUME 0623 /* shifted resume key */ -#define KEY_SSAVE 0624 /* shifted save key */ -#define KEY_SSUSPEND 0625 /* shifted suspend key */ -#define KEY_SUNDO 0626 /* shifted undo key */ -#define KEY_SUSPEND 0627 /* suspend key */ -#define KEY_UNDO 0630 /* undo key */ -#define KEY_MOUSE 0631 /* Mouse event has occurred */ -#define KEY_RESIZE 0632 /* Terminal resize event */ -#define KEY_EVENT 0633 /* We were interrupted by an event */ - -#define KEY_MAX 0777 /* Maximum key value is 0633 */ -/* $Id: curses.tail,v 1.20 2010/03/28 19:10:55 tom Exp $ */ -/* - * vile:cmode: - * This file is part of ncurses, designed to be appended after curses.h.in - * (see that file for the relevant copyright). - */ - -/* mouse interface */ - -#if NCURSES_MOUSE_VERSION > 1 -#define NCURSES_MOUSE_MASK(b,m) ((m) << (((b) - 1) * 5)) -#else -#define NCURSES_MOUSE_MASK(b,m) ((m) << (((b) - 1) * 6)) -#endif - -#define NCURSES_BUTTON_RELEASED 001L -#define NCURSES_BUTTON_PRESSED 002L -#define NCURSES_BUTTON_CLICKED 004L -#define NCURSES_DOUBLE_CLICKED 010L -#define NCURSES_TRIPLE_CLICKED 020L -#define NCURSES_RESERVED_EVENT 040L - -/* event masks */ -#define BUTTON1_RELEASED NCURSES_MOUSE_MASK(1, NCURSES_BUTTON_RELEASED) -#define BUTTON1_PRESSED NCURSES_MOUSE_MASK(1, NCURSES_BUTTON_PRESSED) -#define BUTTON1_CLICKED NCURSES_MOUSE_MASK(1, NCURSES_BUTTON_CLICKED) -#define BUTTON1_DOUBLE_CLICKED NCURSES_MOUSE_MASK(1, NCURSES_DOUBLE_CLICKED) -#define BUTTON1_TRIPLE_CLICKED NCURSES_MOUSE_MASK(1, NCURSES_TRIPLE_CLICKED) - -#define BUTTON2_RELEASED NCURSES_MOUSE_MASK(2, NCURSES_BUTTON_RELEASED) -#define BUTTON2_PRESSED NCURSES_MOUSE_MASK(2, NCURSES_BUTTON_PRESSED) -#define BUTTON2_CLICKED NCURSES_MOUSE_MASK(2, NCURSES_BUTTON_CLICKED) -#define BUTTON2_DOUBLE_CLICKED NCURSES_MOUSE_MASK(2, NCURSES_DOUBLE_CLICKED) -#define BUTTON2_TRIPLE_CLICKED NCURSES_MOUSE_MASK(2, NCURSES_TRIPLE_CLICKED) - -#define BUTTON3_RELEASED NCURSES_MOUSE_MASK(3, NCURSES_BUTTON_RELEASED) -#define BUTTON3_PRESSED NCURSES_MOUSE_MASK(3, NCURSES_BUTTON_PRESSED) -#define BUTTON3_CLICKED NCURSES_MOUSE_MASK(3, NCURSES_BUTTON_CLICKED) -#define BUTTON3_DOUBLE_CLICKED NCURSES_MOUSE_MASK(3, NCURSES_DOUBLE_CLICKED) -#define BUTTON3_TRIPLE_CLICKED NCURSES_MOUSE_MASK(3, NCURSES_TRIPLE_CLICKED) - -#define BUTTON4_RELEASED NCURSES_MOUSE_MASK(4, NCURSES_BUTTON_RELEASED) -#define BUTTON4_PRESSED NCURSES_MOUSE_MASK(4, NCURSES_BUTTON_PRESSED) -#define BUTTON4_CLICKED NCURSES_MOUSE_MASK(4, NCURSES_BUTTON_CLICKED) -#define BUTTON4_DOUBLE_CLICKED NCURSES_MOUSE_MASK(4, NCURSES_DOUBLE_CLICKED) -#define BUTTON4_TRIPLE_CLICKED NCURSES_MOUSE_MASK(4, NCURSES_TRIPLE_CLICKED) - -/* - * In 32 bits the version-1 scheme does not provide enough space for a 5th - * button, unless we choose to change the ABI by omitting the reserved-events. - */ -#if NCURSES_MOUSE_VERSION > 1 - -#define BUTTON5_RELEASED NCURSES_MOUSE_MASK(5, NCURSES_BUTTON_RELEASED) -#define BUTTON5_PRESSED NCURSES_MOUSE_MASK(5, NCURSES_BUTTON_PRESSED) -#define BUTTON5_CLICKED NCURSES_MOUSE_MASK(5, NCURSES_BUTTON_CLICKED) -#define BUTTON5_DOUBLE_CLICKED NCURSES_MOUSE_MASK(5, NCURSES_DOUBLE_CLICKED) -#define BUTTON5_TRIPLE_CLICKED NCURSES_MOUSE_MASK(5, NCURSES_TRIPLE_CLICKED) - -#define BUTTON_CTRL NCURSES_MOUSE_MASK(6, 0001L) -#define BUTTON_SHIFT NCURSES_MOUSE_MASK(6, 0002L) -#define BUTTON_ALT NCURSES_MOUSE_MASK(6, 0004L) -#define REPORT_MOUSE_POSITION NCURSES_MOUSE_MASK(6, 0010L) - -#else - -#define BUTTON1_RESERVED_EVENT NCURSES_MOUSE_MASK(1, NCURSES_RESERVED_EVENT) -#define BUTTON2_RESERVED_EVENT NCURSES_MOUSE_MASK(2, NCURSES_RESERVED_EVENT) -#define BUTTON3_RESERVED_EVENT NCURSES_MOUSE_MASK(3, NCURSES_RESERVED_EVENT) -#define BUTTON4_RESERVED_EVENT NCURSES_MOUSE_MASK(4, NCURSES_RESERVED_EVENT) - -#define BUTTON_CTRL NCURSES_MOUSE_MASK(5, 0001L) -#define BUTTON_SHIFT NCURSES_MOUSE_MASK(5, 0002L) -#define BUTTON_ALT NCURSES_MOUSE_MASK(5, 0004L) -#define REPORT_MOUSE_POSITION NCURSES_MOUSE_MASK(5, 0010L) - -#endif - -#define ALL_MOUSE_EVENTS (REPORT_MOUSE_POSITION - 1) - -/* macros to extract single event-bits from masks */ -#define BUTTON_RELEASE(e, x) ((e) & NCURSES_MOUSE_MASK(x, 001)) -#define BUTTON_PRESS(e, x) ((e) & NCURSES_MOUSE_MASK(x, 002)) -#define BUTTON_CLICK(e, x) ((e) & NCURSES_MOUSE_MASK(x, 004)) -#define BUTTON_DOUBLE_CLICK(e, x) ((e) & NCURSES_MOUSE_MASK(x, 010)) -#define BUTTON_TRIPLE_CLICK(e, x) ((e) & NCURSES_MOUSE_MASK(x, 020)) -#define BUTTON_RESERVED_EVENT(e, x) ((e) & NCURSES_MOUSE_MASK(x, 040)) - -typedef struct -{ - short id; /* ID to distinguish multiple devices */ - int x, y, z; /* event coordinates (character-cell) */ - mmask_t bstate; /* button state bits */ -} -MEVENT; - -extern NCURSES_EXPORT(bool) has_mouse(void); -extern NCURSES_EXPORT(int) getmouse (MEVENT *); -extern NCURSES_EXPORT(int) ungetmouse (MEVENT *); -extern NCURSES_EXPORT(mmask_t) mousemask (mmask_t, mmask_t *); -extern NCURSES_EXPORT(bool) wenclose (const WINDOW *, int, int); -extern NCURSES_EXPORT(int) mouseinterval (int); -extern NCURSES_EXPORT(bool) wmouse_trafo (const WINDOW*, int*, int*, bool); -extern NCURSES_EXPORT(bool) mouse_trafo (int*, int*, bool); /* generated */ - -#if NCURSES_SP_FUNCS -extern NCURSES_EXPORT(bool) NCURSES_SP_NAME(has_mouse) (SCREEN*); -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(getmouse) (SCREEN*, MEVENT *); -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(ungetmouse) (SCREEN*,MEVENT *); -extern NCURSES_EXPORT(mmask_t) NCURSES_SP_NAME(mousemask) (SCREEN*, mmask_t, mmask_t *); -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(mouseinterval) (SCREEN*, int); -#endif - -#define mouse_trafo(y,x,to_screen) wmouse_trafo(stdscr,y,x,to_screen) - -/* other non-XSI functions */ - -extern NCURSES_EXPORT(int) mcprint (char *, int); /* direct data to printer */ -extern NCURSES_EXPORT(int) has_key (int); /* do we have given key? */ - -#if NCURSES_SP_FUNCS -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(has_key) (SCREEN*, int); /* do we have given key? */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(mcprint) (SCREEN*, char *, int); /* direct data to printer */ -#endif - -/* Debugging : use with libncurses_g.a */ - -extern NCURSES_EXPORT(void) _tracef (const char *, ...) GCC_PRINTFLIKE(1,2); -extern NCURSES_EXPORT(void) _tracedump (const char *, WINDOW *); -extern NCURSES_EXPORT(char *) _traceattr (attr_t); -extern NCURSES_EXPORT(char *) _traceattr2 (int, chtype); -extern NCURSES_EXPORT(char *) _nc_tracebits (void); -extern NCURSES_EXPORT(char *) _tracechar (int); -extern NCURSES_EXPORT(char *) _tracechtype (chtype); -extern NCURSES_EXPORT(char *) _tracechtype2 (int, chtype); -#ifdef NCURSES_WIDECHAR -#define _tracech_t _tracecchar_t -extern NCURSES_EXPORT(char *) _tracecchar_t (const cchar_t *); -#define _tracech_t2 _tracecchar_t2 -extern NCURSES_EXPORT(char *) _tracecchar_t2 (int, const cchar_t *); -#else -#define _tracech_t _tracechtype -#define _tracech_t2 _tracechtype2 -#endif -extern NCURSES_EXPORT(char *) _tracemouse (const MEVENT *); -extern NCURSES_EXPORT(void) trace (const unsigned int); - -/* trace masks */ -#define TRACE_DISABLE 0x0000 /* turn off tracing */ -#define TRACE_TIMES 0x0001 /* trace user and system times of updates */ -#define TRACE_TPUTS 0x0002 /* trace tputs calls */ -#define TRACE_UPDATE 0x0004 /* trace update actions, old & new screens */ -#define TRACE_MOVE 0x0008 /* trace cursor moves and scrolls */ -#define TRACE_CHARPUT 0x0010 /* trace all character outputs */ -#define TRACE_ORDINARY 0x001F /* trace all update actions */ -#define TRACE_CALLS 0x0020 /* trace all curses calls */ -#define TRACE_VIRTPUT 0x0040 /* trace virtual character puts */ -#define TRACE_IEVENT 0x0080 /* trace low-level input processing */ -#define TRACE_BITS 0x0100 /* trace state of TTY control bits */ -#define TRACE_ICALLS 0x0200 /* trace internal/nested calls */ -#define TRACE_CCALLS 0x0400 /* trace per-character calls */ -#define TRACE_DATABASE 0x0800 /* trace read/write of terminfo/termcap data */ -#define TRACE_ATTRS 0x1000 /* trace attribute updates */ - -#define TRACE_SHIFT 13 /* number of bits in the trace masks */ -#define TRACE_MAXIMUM ((1 << TRACE_SHIFT) - 1) /* maximum trace level */ - -#if defined(TRACE) || defined(NCURSES_TEST) -extern NCURSES_EXPORT_VAR(int) _nc_optimize_enable; /* enable optimizations */ -extern NCURSES_EXPORT(const char *) _nc_visbuf (const char *); -#define OPTIMIZE_MVCUR 0x01 /* cursor movement optimization */ -#define OPTIMIZE_HASHMAP 0x02 /* diff hashing to detect scrolls */ -#define OPTIMIZE_SCROLL 0x04 /* scroll optimization */ -#define OPTIMIZE_ALL 0xff /* enable all optimizations (dflt) */ -#endif - -#include - -#ifdef __cplusplus - -#ifndef NCURSES_NOMACROS - -/* these names conflict with STL */ -#undef box -#undef clear -#undef erase -#undef move -#undef refresh - -#endif /* NCURSES_NOMACROS */ - -} -#endif - -#endif /* __NCURSES_H */ diff --git a/windows/ncurses/include/ncurses/cursesapp.h b/windows/ncurses/include/ncurses/cursesapp.h deleted file mode 100644 index f619c1f04..000000000 --- a/windows/ncurses/include/ncurses/cursesapp.h +++ /dev/null @@ -1,176 +0,0 @@ -// * This makes emacs happy -*-Mode: C++;-*- -/**************************************************************************** - * Copyright (c) 1998-2003,2005 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/**************************************************************************** - * Author: Juergen Pfeifer, 1997 * - ****************************************************************************/ - -// $Id: cursesapp.h,v 1.11 2005/05/28 21:57:44 tom Exp $ - -#ifndef NCURSES_CURSESAPP_H_incl -#define NCURSES_CURSESAPP_H_incl - -#include - -class NCURSES_IMPEXP NCursesApplication { -public: - typedef struct _slk_link { // This structure is used to maintain - struct _slk_link* prev; // a stack of SLKs - Soft_Label_Key_Set* SLKs; - } SLK_Link; -private: - static int rinit(NCursesWindow& w); // Internal Init function for title - static NCursesApplication* theApp; // Global ref. to the application - - static SLK_Link* slk_stack; - -protected: - static NCursesWindow* titleWindow; // The Title Window (if any) - - bool b_Colors; // Is this a color application? - NCursesWindow* Root_Window; // This is the stdscr equiv. - - // Initialization of attributes; - // Rewrite this in your derived class if you prefer other settings - virtual void init(bool bColors); - - // The number of lines for the title window. Default is no title window - // You may rewrite this in your derived class - virtual int titlesize() const { - return 0; - } - - // This method is called to put something into the title window initially - // You may rewrite this in your derived class - virtual void title() { - } - - // The layout used for the Soft Label Keys. Default is to have no SLKs. - // You may rewrite this in your derived class - virtual Soft_Label_Key_Set::Label_Layout useSLKs() const { - return Soft_Label_Key_Set::None; - } - - // This method is called to initialize the SLKs. Default is nothing. - // You may rewrite this in your derived class - virtual void init_labels(Soft_Label_Key_Set& S) const { - } - - // Your derived class must implement this method. The return value must - // be the exit value of your application. - virtual int run() = 0; - - // The constructor is protected, so you may use it in your derived - // class constructor. The argument tells whether or not you want colors. - NCursesApplication(bool wantColors = FALSE); - - NCursesApplication& operator=(const NCursesApplication& rhs) - { - if (this != &rhs) { - *this = rhs; - } - return *this; - } - - NCursesApplication(const NCursesApplication& rhs) - : b_Colors(rhs.b_Colors), - Root_Window(rhs.Root_Window) - { - } - -public: - virtual ~NCursesApplication(); - - // Get a pointer to the current application object - static NCursesApplication* getApplication() { - return theApp; - } - - // This method runs the application and returns its exit value - int operator()(void); - - // Process the commandline arguments. The default implementation simply - // ignores them. Your derived class may rewrite this. - virtual void handleArgs(int argc, char* argv[]) { - } - - // Does this application use colors? - inline bool useColors() const { - return b_Colors; - } - - // Push the Key Set S onto the SLK Stack. S then becomes the current set - // of Soft Labelled Keys. - void push(Soft_Label_Key_Set& S); - - // Throw away the current set of SLKs and make the previous one the - // new current set. - bool pop(); - - // Retrieve the current set of Soft Labelled Keys. - Soft_Label_Key_Set* top() const; - - // Attributes to use for menu and forms foregrounds - virtual chtype foregrounds() const { - return b_Colors ? COLOR_PAIR(1) : A_BOLD; - } - - // Attributes to use for menu and forms backgrounds - virtual chtype backgrounds() const { - return b_Colors ? COLOR_PAIR(2) : A_NORMAL; - } - - // Attributes to use for inactive (menu) elements - virtual chtype inactives() const { - return b_Colors ? (COLOR_PAIR(3)|A_DIM) : A_DIM; - } - - // Attributes to use for (form) labels and SLKs - virtual chtype labels() const { - return b_Colors ? COLOR_PAIR(4) : A_NORMAL; - } - - // Attributes to use for form backgrounds - virtual chtype dialog_backgrounds() const { - return b_Colors ? COLOR_PAIR(4) : A_NORMAL; - } - - // Attributes to use as default for (form) window backgrounds - virtual chtype window_backgrounds() const { - return b_Colors ? COLOR_PAIR(5) : A_NORMAL; - } - - // Attributes to use for the title window - virtual chtype screen_titles() const { - return b_Colors ? COLOR_PAIR(6) : A_BOLD; - } - -}; - -#endif /* NCURSES_CURSESAPP_H_incl */ diff --git a/windows/ncurses/include/ncurses/cursesf.h b/windows/ncurses/include/ncurses/cursesf.h deleted file mode 100644 index 215eb295d..000000000 --- a/windows/ncurses/include/ncurses/cursesf.h +++ /dev/null @@ -1,967 +0,0 @@ -// * This makes emacs happy -*-Mode: C++;-*- -/**************************************************************************** - * Copyright (c) 1998-2004,2005 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/**************************************************************************** - * Author: Juergen Pfeifer, 1997 * - ****************************************************************************/ - -// $Id: cursesf.h,v 1.28 2005/08/13 18:08:24 tom Exp $ - -#ifndef NCURSES_CURSESF_H_incl -#define NCURSES_CURSESF_H_incl 1 - -#include - -#ifndef __EXT_QNX -#include -#endif - -extern "C" { -# include -} -// -// ------------------------------------------------------------------------- -// The abstract base class for buitin and user defined Fieldtypes. -// ------------------------------------------------------------------------- -// -class NCURSES_IMPEXP NCursesFormField; // forward declaration - -// Class to represent builtin field types as well as C++ written new -// fieldtypes (see classes UserDefineFieldType... -class NCURSES_IMPEXP NCursesFieldType -{ - friend class NCursesFormField; - -protected: - FIELDTYPE* fieldtype; - - inline void OnError(int err) const THROWS(NCursesFormException) { - if (err!=E_OK) - THROW(new NCursesFormException (err)); - } - - NCursesFieldType(FIELDTYPE *f) : fieldtype(f) { - } - - virtual ~NCursesFieldType() {} - - // Set the fields f fieldtype to this one. - virtual void set(NCursesFormField& f) = 0; - -public: - NCursesFieldType() - : fieldtype(STATIC_CAST(FIELDTYPE*)(0)) - { - } - - NCursesFieldType& operator=(const NCursesFieldType& rhs) - { - if (this != &rhs) { - *this = rhs; - } - return *this; - } - - NCursesFieldType(const NCursesFieldType& rhs) - : fieldtype(rhs.fieldtype) - { - } - -}; - -// -// ------------------------------------------------------------------------- -// The class representing a forms field, wrapping the lowlevel FIELD struct -// ------------------------------------------------------------------------- -// -class NCURSES_IMPEXP NCursesFormField -{ - friend class NCursesForm; - -protected: - FIELD *field; // lowlevel structure - NCursesFieldType* ftype; // Associated field type - - // Error handler - inline void OnError (int err) const THROWS(NCursesFormException) { - if (err != E_OK) - THROW(new NCursesFormException (err)); - } - -public: - // Create a 'Null' field. Can be used to delimit a field list - NCursesFormField() - : field(STATIC_CAST(FIELD*)(0)), - ftype(STATIC_CAST(NCursesFieldType*)(0)) - { - } - - // Create a new field - NCursesFormField (int rows, - int ncols, - int first_row = 0, - int first_col = 0, - int offscreen_rows = 0, - int additional_buffers = 0) - : field(0), - ftype(STATIC_CAST(NCursesFieldType*)(0)) - { - field = ::new_field(rows, ncols, first_row, first_col, - offscreen_rows, additional_buffers); - if (!field) - OnError(errno); - } - - NCursesFormField& operator=(const NCursesFormField& rhs) - { - if (this != &rhs) { - *this = rhs; - } - return *this; - } - - NCursesFormField(const NCursesFormField& rhs) - : field(rhs.field), ftype(rhs.ftype) - { - } - - virtual ~NCursesFormField (); - - // Duplicate the field at a new position - inline NCursesFormField* dup(int first_row, int first_col) - { - NCursesFormField* f = new NCursesFormField(); - if (!f) - OnError(E_SYSTEM_ERROR); - else { - f->ftype = ftype; - f->field = ::dup_field(field,first_row,first_col); - if (!f->field) - OnError(errno); - } - return f; - } - - // Link the field to a new location - inline NCursesFormField* link(int first_row, int first_col) { - NCursesFormField* f = new NCursesFormField(); - if (!f) - OnError(E_SYSTEM_ERROR); - else { - f->ftype = ftype; - f->field = ::link_field(field,first_row,first_col); - if (!f->field) - OnError(errno); - } - return f; - } - - // Get the lowlevel field representation - inline FIELD* get_field() const { - return field; - } - - // Retrieve info about the field - inline void info(int& rows, int& ncols, - int& first_row, int& first_col, - int& offscreen_rows, int& additional_buffers) const { - OnError(::field_info(field, &rows, &ncols, - &first_row, &first_col, - &offscreen_rows, &additional_buffers)); - } - - // Retrieve info about the fields dynamic properties. - inline void dynamic_info(int& dynamic_rows, int& dynamic_cols, - int& max_growth) const { - OnError(::dynamic_field_info(field, &dynamic_rows, &dynamic_cols, - &max_growth)); - } - - // For a dynamic field you may set the maximum growth limit. - // A zero means unlimited growth. - inline void set_maximum_growth(int growth = 0) { - OnError(::set_max_field(field,growth)); - } - - // Move the field to a new position - inline void move(int row, int col) { - OnError(::move_field(field,row,col)); - } - - // Mark the field to start a new page - inline void new_page(bool pageFlag = FALSE) { - OnError(::set_new_page(field,pageFlag)); - } - - // Retrieve whether or not the field starts a new page. - inline bool is_new_page() const { - return ::new_page(field); - } - - // Set the justification for the field - inline void set_justification(int just) { - OnError(::set_field_just(field,just)); - } - - // Retrieve the fields justification - inline int justification() const { - return ::field_just(field); - } - // Set the foreground attribute for the field - inline void set_foreground(chtype foreground) { - OnError(::set_field_fore(field,foreground)); - } - - // Retrieve the fields foreground attribute - inline chtype fore() const { - return ::field_fore(field); - } - - // Set the background attribute for the field - inline void set_background(chtype background) { - OnError(::set_field_back(field,background)); - } - - // Retrieve the fields background attribute - inline chtype back() const { - return ::field_back(field); - } - - // Set the padding character for the field - inline void set_pad_character(int padding) { - OnError(::set_field_pad(field, padding)); - } - - // Retrieve the fields padding character - inline int pad() const { - return ::field_pad(field); - } - - // Switch on the fields options - inline void options_on (Field_Options opts) { - OnError (::field_opts_on (field, opts)); - } - - // Switch off the fields options - inline void options_off (Field_Options opts) { - OnError (::field_opts_off (field, opts)); - } - - // Retrieve the fields options - inline Field_Options options () const { - return ::field_opts (field); - } - - // Set the fields options - inline void set_options (Field_Options opts) { - OnError (::set_field_opts (field, opts)); - } - - // Mark the field as changed - inline void set_changed(bool changeFlag = TRUE) { - OnError(::set_field_status(field,changeFlag)); - } - - // Test whether or not the field is marked as changed - inline bool changed() const { - return ::field_status(field); - } - - // Return the index of the field in the field array of a form - // or -1 if the field is not associated to a form - inline int (index)() const { - return ::field_index(field); - } - - // Store a value in a fields buffer. The default buffer is nr. 0 - inline void set_value(const char *val, int buffer = 0) { - OnError(::set_field_buffer(field,buffer,val)); - } - - // Retrieve the value of a fields buffer. The default buffer is nr. 0 - inline char* value(int buffer = 0) const { - return ::field_buffer(field,buffer); - } - - // Set the validation type of the field. - inline void set_fieldtype(NCursesFieldType& f) { - ftype = &f; - f.set(*this); // A good friend may do that... - } - - // Retrieve the validation type of the field. - inline NCursesFieldType* fieldtype() const { - return ftype; - } - -}; - - // This are the built-in hook functions in this C++ binding. In C++ we use - // virtual member functions (see below On_..._Init and On_..._Termination) - // to provide this functionality in an object oriented manner. -extern "C" { - void _nc_xx_frm_init(FORM *); - void _nc_xx_frm_term(FORM *); - void _nc_xx_fld_init(FORM *); - void _nc_xx_fld_term(FORM *); -} - -// -// ------------------------------------------------------------------------- -// The class representing a form, wrapping the lowlevel FORM struct -// ------------------------------------------------------------------------- -// -class NCURSES_IMPEXP NCursesForm : public NCursesPanel -{ -protected: - FORM* form; // the lowlevel structure - -private: - NCursesWindow* sub; // the subwindow object - bool b_sub_owner; // is this our own subwindow? - bool b_framed; // has the form a border? - bool b_autoDelete; // Delete fields when deleting form? - - NCursesFormField** my_fields; // The array of fields for this form - - // This structure is used for the form's user data field to link the - // FORM* to the C++ object and to provide extra space for a user pointer. - typedef struct { - void* m_user; // the pointer for the user's data - const NCursesForm* m_back; // backward pointer to C++ object - const FORM* m_owner; - } UserHook; - - // Get the backward pointer to the C++ object from a FORM - static inline NCursesForm* getHook(const FORM *f) { - UserHook* hook = reinterpret_cast(::form_userptr(f)); - assert(hook != 0 && hook->m_owner==f); - return const_cast(hook->m_back); - } - - friend void _nc_xx_frm_init(FORM *); - friend void _nc_xx_frm_term(FORM *); - friend void _nc_xx_fld_init(FORM *); - friend void _nc_xx_fld_term(FORM *); - - // Calculate FIELD* array for the menu - FIELD** mapFields(NCursesFormField* nfields[]); - -protected: - // internal routines - inline void set_user(void *user) { - UserHook* uptr = reinterpret_cast(::form_userptr (form)); - assert (uptr != 0 && uptr->m_back==this && uptr->m_owner==form); - uptr->m_user = user; - } - - inline void *get_user() { - UserHook* uptr = reinterpret_cast(::form_userptr (form)); - assert (uptr != 0 && uptr->m_back==this && uptr->m_owner==form); - return uptr->m_user; - } - - void InitForm (NCursesFormField* Fields[], - bool with_frame, - bool autoDeleteFields); - - inline void OnError (int err) const THROWS(NCursesFormException) { - if (err != E_OK) - THROW(new NCursesFormException (err)); - } - - // this wraps the form_driver call. - virtual int driver (int c) ; - - // 'Internal' constructor, builds an object without association to a - // field array. - NCursesForm( int nlines, - int ncols, - int begin_y = 0, - int begin_x = 0) - : NCursesPanel(nlines, ncols, begin_y, begin_x), - form (STATIC_CAST(FORM*)(0)), - sub(0), - b_sub_owner(0), - b_framed(0), - b_autoDelete(0), - my_fields(0) - { - } - -public: - // Create form for the default panel. - NCursesForm (NCursesFormField* Fields[], - bool with_frame=FALSE, // reserve space for a frame? - bool autoDelete_Fields=FALSE) // do automatic cleanup? - : NCursesPanel(), - form(0), - sub(0), - b_sub_owner(0), - b_framed(0), - b_autoDelete(0), - my_fields(0) - { - InitForm(Fields, with_frame, autoDelete_Fields); - } - - // Create a form in a panel with the given position and size. - NCursesForm (NCursesFormField* Fields[], - int nlines, - int ncols, - int begin_y, - int begin_x, - bool with_frame=FALSE, // reserve space for a frame? - bool autoDelete_Fields=FALSE) // do automatic cleanup? - : NCursesPanel(nlines, ncols, begin_y, begin_x), - form(0), - sub(0), - b_sub_owner(0), - b_framed(0), - b_autoDelete(0), - my_fields(0) - { - InitForm(Fields, with_frame, autoDelete_Fields); - } - - NCursesForm& operator=(const NCursesForm& rhs) - { - if (this != &rhs) { - *this = rhs; - NCursesPanel::operator=(rhs); - } - return *this; - } - - NCursesForm(const NCursesForm& rhs) - : NCursesPanel(rhs), - form(rhs.form), - sub(rhs.sub), - b_sub_owner(rhs.b_sub_owner), - b_framed(rhs.b_framed), - b_autoDelete(rhs.b_autoDelete), - my_fields(rhs.my_fields) - { - } - - virtual ~NCursesForm(); - - // Set the default attributes for the form - virtual void setDefaultAttributes(); - - // Retrieve current field of the form. - inline NCursesFormField* current_field() const { - return my_fields[::field_index(::current_field(form))]; - } - - // Set the forms subwindow - void setSubWindow(NCursesWindow& sub); - - // Set these fields for the form - inline void setFields(NCursesFormField* Fields[]) { - OnError(::set_form_fields(form,mapFields(Fields))); - } - - // Remove the form from the screen - inline void unpost (void) { - OnError (::unpost_form (form)); - } - - // Post the form to the screen if flag is true, unpost it otherwise - inline void post(bool flag = TRUE) { - OnError (flag ? ::post_form(form) : ::unpost_form (form)); - } - - // Decorations - inline void frame(const char *title=NULL, const char* btitle=NULL) { - if (b_framed) - NCursesPanel::frame(title,btitle); - else - OnError(E_SYSTEM_ERROR); - } - - inline void boldframe(const char *title=NULL, const char* btitle=NULL) { - if (b_framed) - NCursesPanel::boldframe(title,btitle); - else - OnError(E_SYSTEM_ERROR); - } - - inline void label(const char *topLabel, const char *bottomLabel) { - if (b_framed) - NCursesPanel::label(topLabel,bottomLabel); - else - OnError(E_SYSTEM_ERROR); - } - - // ----- - // Hooks - // ----- - - // Called after the form gets repositioned in its window. - // This is especially true if the form is posted. - virtual void On_Form_Init(); - - // Called before the form gets repositioned in its window. - // This is especially true if the form is unposted. - virtual void On_Form_Termination(); - - // Called after the field became the current field - virtual void On_Field_Init(NCursesFormField& field); - - // Called before this field is left as current field. - virtual void On_Field_Termination(NCursesFormField& field); - - // Calculate required window size for the form. - void scale(int& rows, int& ncols) const { - OnError(::scale_form(form,&rows,&ncols)); - } - - // Retrieve number of fields in the form. - int count() const { - return ::field_count(form); - } - - // Make the page the current page of the form. - void set_page(int pageNum) { - OnError(::set_form_page(form, pageNum)); - } - - // Retrieve current page number - int page() const { - return ::form_page(form); - } - - // Switch on the forms options - inline void options_on (Form_Options opts) { - OnError (::form_opts_on (form, opts)); - } - - // Switch off the forms options - inline void options_off (Form_Options opts) { - OnError (::form_opts_off (form, opts)); - } - - // Retrieve the forms options - inline Form_Options options () const { - return ::form_opts (form); - } - - // Set the forms options - inline void set_options (Form_Options opts) { - OnError (::set_form_opts (form, opts)); - } - - // Are there more data in the current field after the data shown - inline bool data_ahead() const { - return ::data_ahead(form); - } - - // Are there more data in the current field before the data shown - inline bool data_behind() const { - return ::data_behind(form); - } - - // Position the cursor to the current field - inline void position_cursor () { - OnError (::pos_form_cursor (form)); - } - // Set the current field - inline void set_current(NCursesFormField& F) { - OnError (::set_current_field(form, F.field)); - } - - // Provide a default key virtualization. Translate the keyboard - // code c into a form request code. - // The default implementation provides a hopefully straightforward - // mapping for the most common keystrokes and form requests. - virtual int virtualize(int c); - - // Operators - inline NCursesFormField* operator[](int i) const { - if ( (i < 0) || (i >= ::field_count (form)) ) - OnError (E_BAD_ARGUMENT); - return my_fields[i]; - } - - // Perform the menu's operation - // Return the field where you left the form. - virtual NCursesFormField* operator()(void); - - // Exception handlers. The default is a Beep. - virtual void On_Request_Denied(int c) const; - virtual void On_Invalid_Field(int c) const; - virtual void On_Unknown_Command(int c) const; - -}; - -// -// ------------------------------------------------------------------------- -// This is the typical C++ typesafe way to allow to attach -// user data to a field of a form. Its assumed that the user -// data belongs to some class T. Use T as template argument -// to create a UserField. -// ------------------------------------------------------------------------- -template class NCURSES_IMPEXP NCursesUserField : public NCursesFormField -{ -public: - NCursesUserField (int rows, - int ncols, - int first_row = 0, - int first_col = 0, - const T* p_UserData = STATIC_CAST(T*)(0), - int offscreen_rows = 0, - int additional_buffers = 0) - : NCursesFormField (rows, ncols, - first_row, first_col, - offscreen_rows, additional_buffers) { - if (field) - OnError(::set_field_userptr(field, STATIC_CAST(void *)(p_UserData))); - } - - virtual ~NCursesUserField() {}; - - inline const T* UserData (void) const { - return reinterpret_cast(::field_userptr (field)); - } - - inline virtual void setUserData(const T* p_UserData) { - if (field) - OnError (::set_field_userptr (field, STATIC_CAST(void *)(p_UserData))); - } -}; -// -// ------------------------------------------------------------------------- -// The same mechanism is used to attach user data to a form -// ------------------------------------------------------------------------- -// -template class NCURSES_IMPEXP NCursesUserForm : public NCursesForm -{ -protected: - // 'Internal' constructor, builds an object without association to a - // field array. - NCursesUserForm( int nlines, - int ncols, - int begin_y = 0, - int begin_x = 0, - const T* p_UserData = STATIC_CAST(T*)(0)) - : NCursesForm(nlines,ncols,begin_y,begin_x) { - if (form) - set_user (const_cast(p_UserData)); - } - -public: - NCursesUserForm (NCursesFormField Fields[], - const T* p_UserData = STATIC_CAST(T*)(0), - bool with_frame=FALSE, - bool autoDelete_Fields=FALSE) - : NCursesForm (Fields, with_frame, autoDelete_Fields) { - if (form) - set_user (const_cast(p_UserData)); - }; - - NCursesUserForm (NCursesFormField Fields[], - int nlines, - int ncols, - int begin_y = 0, - int begin_x = 0, - const T* p_UserData = STATIC_CAST(T*)(0), - bool with_frame=FALSE, - bool autoDelete_Fields=FALSE) - : NCursesForm (Fields, nlines, ncols, begin_y, begin_x, - with_frame, autoDelete_Fields) { - if (form) - set_user (const_cast(p_UserData)); - }; - - virtual ~NCursesUserForm() { - }; - - inline T* UserData (void) const { - return reinterpret_cast(get_user ()); - }; - - inline virtual void setUserData (const T* p_UserData) { - if (form) - set_user (const_cast(p_UserData)); - } - -}; -// -// ------------------------------------------------------------------------- -// Builtin Fieldtypes -// ------------------------------------------------------------------------- -// -class NCURSES_IMPEXP Alpha_Field : public NCursesFieldType -{ -private: - int min_field_width; - - void set(NCursesFormField& f) { - OnError(::set_field_type(f.get_field(),fieldtype,min_field_width)); - } - -public: - Alpha_Field(int width) - : NCursesFieldType(TYPE_ALPHA), - min_field_width(width) { - } -}; - -class NCURSES_IMPEXP Alphanumeric_Field : public NCursesFieldType -{ -private: - int min_field_width; - - void set(NCursesFormField& f) { - OnError(::set_field_type(f.get_field(),fieldtype,min_field_width)); - } - -public: - Alphanumeric_Field(int width) - : NCursesFieldType(TYPE_ALNUM), - min_field_width(width) { - } -}; - -class NCURSES_IMPEXP Integer_Field : public NCursesFieldType -{ -private: - int precision; - long lower_limit, upper_limit; - - void set(NCursesFormField& f) { - OnError(::set_field_type(f.get_field(),fieldtype, - precision,lower_limit,upper_limit)); - } - -public: - Integer_Field(int prec, long low=0L, long high=0L) - : NCursesFieldType(TYPE_INTEGER), - precision(prec), lower_limit(low), upper_limit(high) { - } -}; - -class NCURSES_IMPEXP Numeric_Field : public NCursesFieldType -{ -private: - int precision; - double lower_limit, upper_limit; - - void set(NCursesFormField& f) { - OnError(::set_field_type(f.get_field(),fieldtype, - precision,lower_limit,upper_limit)); - } - -public: - Numeric_Field(int prec, double low=0.0, double high=0.0) - : NCursesFieldType(TYPE_NUMERIC), - precision(prec), lower_limit(low), upper_limit(high) { - } -}; - -class NCURSES_IMPEXP Regular_Expression_Field : public NCursesFieldType -{ -private: - char* regex; - - void set(NCursesFormField& f) { - OnError(::set_field_type(f.get_field(),fieldtype,regex)); - } - - void copy_regex(const char *source) - { - regex = new char[1 + ::strlen(source)]; - (::strcpy)(regex, source); - } - -public: - Regular_Expression_Field(const char *expr) - : NCursesFieldType(TYPE_REGEXP), - regex(NULL) - { - copy_regex(expr); - } - - Regular_Expression_Field& operator=(const Regular_Expression_Field& rhs) - { - if (this != &rhs) { - *this = rhs; - copy_regex(rhs.regex); - NCursesFieldType::operator=(rhs); - } - return *this; - } - - Regular_Expression_Field(const Regular_Expression_Field& rhs) - : NCursesFieldType(rhs), - regex(NULL) - { - copy_regex(rhs.regex); - } - - ~Regular_Expression_Field() { - delete[] regex; - } -}; - -class NCURSES_IMPEXP Enumeration_Field : public NCursesFieldType -{ -private: - const char** list; - int case_sensitive; - int non_unique_matches; - - void set(NCursesFormField& f) { - OnError(::set_field_type(f.get_field(),fieldtype, - list,case_sensitive,non_unique_matches)); - } -public: - Enumeration_Field(const char* enums[], - bool case_sens=FALSE, - bool non_unique=FALSE) - : NCursesFieldType(TYPE_ENUM), - list(enums), - case_sensitive(case_sens ? -1 : 0), - non_unique_matches(non_unique ? -1 : 0) { - } - - Enumeration_Field& operator=(const Enumeration_Field& rhs) - { - if (this != &rhs) { - *this = rhs; - NCursesFieldType::operator=(rhs); - } - return *this; - } - - Enumeration_Field(const Enumeration_Field& rhs) - : NCursesFieldType(rhs), - list(rhs.list), - case_sensitive(rhs.case_sensitive), - non_unique_matches(rhs.non_unique_matches) - { - } -}; - -class NCURSES_IMPEXP IPV4_Address_Field : public NCursesFieldType -{ -private: - void set(NCursesFormField& f) { - OnError(::set_field_type(f.get_field(),fieldtype)); - } - -public: - IPV4_Address_Field() : NCursesFieldType(TYPE_IPV4) { - } -}; - -extern "C" { - bool _nc_xx_fld_fcheck(FIELD *, const void*); - bool _nc_xx_fld_ccheck(int c, const void *); - void* _nc_xx_fld_makearg(va_list*); -} - -// -// ------------------------------------------------------------------------- -// Abstract base class for User-Defined Fieldtypes -// ------------------------------------------------------------------------- -// -class NCURSES_IMPEXP UserDefinedFieldType : public NCursesFieldType -{ - friend class UDF_Init; // Internal helper to set up statics -private: - // For all C++ defined fieldtypes we need only one generic lowlevel - // FIELDTYPE* element. - static FIELDTYPE* generic_fieldtype; - -protected: - // This are the functions required by the low level libforms functions - // to construct a fieldtype. - friend bool _nc_xx_fld_fcheck(FIELD *, const void*); - friend bool _nc_xx_fld_ccheck(int c, const void *); - friend void* _nc_xx_fld_makearg(va_list*); - - void set(NCursesFormField& f) { - OnError(::set_field_type(f.get_field(),fieldtype,&f)); - } - -protected: - // Redefine this function to do a field validation. The argument - // is a reference to the field you should validate. - virtual bool field_check(NCursesFormField& f) = 0; - - // Redefine this function to do a character validation. The argument - // is the character to be validated. - virtual bool char_check (int c) = 0; - -public: - UserDefinedFieldType() : NCursesFieldType(generic_fieldtype) { - } -}; - -extern "C" { - bool _nc_xx_next_choice(FIELD*, const void *); - bool _nc_xx_prev_choice(FIELD*, const void *); -} - -// -// ------------------------------------------------------------------------- -// Abstract base class for User-Defined Fieldtypes with Choice functions -// ------------------------------------------------------------------------- -// -class NCURSES_IMPEXP UserDefinedFieldType_With_Choice : public UserDefinedFieldType -{ - friend class UDF_Init; // Internal helper to set up statics -private: - // For all C++ defined fieldtypes with choice functions we need only one - // generic lowlevel FIELDTYPE* element. - static FIELDTYPE* generic_fieldtype_with_choice; - - // This are the functions required by the low level libforms functions - // to construct a fieldtype with choice functions. - friend bool _nc_xx_next_choice(FIELD*, const void *); - friend bool _nc_xx_prev_choice(FIELD*, const void *); - -protected: - // Redefine this function to do the retrieval of the next choice value. - // The argument is a reference to the field tobe examined. - virtual bool next (NCursesFormField& f) = 0; - - // Redefine this function to do the retrieval of the previous choice value. - // The argument is a reference to the field tobe examined. - virtual bool previous(NCursesFormField& f) = 0; - -public: - UserDefinedFieldType_With_Choice() { - fieldtype = generic_fieldtype_with_choice; - } -}; - -#endif /* NCURSES_CURSESF_H_incl */ diff --git a/windows/ncurses/include/ncurses/cursesm.h b/windows/ncurses/include/ncurses/cursesm.h deleted file mode 100644 index 8e0e2c66c..000000000 --- a/windows/ncurses/include/ncurses/cursesm.h +++ /dev/null @@ -1,672 +0,0 @@ -// * This makes emacs happy -*-Mode: C++;-*- -/**************************************************************************** - * Copyright (c) 1998-2003,2005 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/**************************************************************************** - * Author: Juergen Pfeifer, 1997 * - ****************************************************************************/ - -// $Id: cursesm.h,v 1.25 2005/08/13 18:10:36 tom Exp $ - -#ifndef NCURSES_CURSESM_H_incl -#define NCURSES_CURSESM_H_incl 1 - -#include - -extern "C" { -# include -} -// -// ------------------------------------------------------------------------- -// This wraps the ITEM type of -// ------------------------------------------------------------------------- -// -class NCURSES_IMPEXP NCursesMenuItem -{ - friend class NCursesMenu; - -protected: - ITEM *item; - - inline void OnError (int err) const THROWS(NCursesMenuException) { - if (err != E_OK) - THROW(new NCursesMenuException (err)); - } - -public: - NCursesMenuItem (const char* p_name = NULL, - const char* p_descript = NULL) - : item(0) - { - item = p_name ? ::new_item (p_name, p_descript) : STATIC_CAST(ITEM*)(0); - if (p_name && !item) - OnError (E_SYSTEM_ERROR); - } - // Create an item. If you pass both parameters as NULL, a delimiting - // item is constructed which can be used to terminate a list of - // NCursesMenu objects. - - NCursesMenuItem& operator=(const NCursesMenuItem& rhs) - { - if (this != &rhs) { - *this = rhs; - } - return *this; - } - - NCursesMenuItem(const NCursesMenuItem& rhs) - : item(0) - { - } - - virtual ~NCursesMenuItem (); - // Release the items memory - - inline const char* name () const { - return ::item_name (item); - } - // Name of the item - - inline const char* description () const { - return ::item_description (item); - } - // Description of the item - - inline int (index) (void) const { - return ::item_index (item); - } - // Index of the item in an item array (or -1) - - inline void options_on (Item_Options opts) { - OnError (::item_opts_on (item, opts)); - } - // Switch on the items options - - inline void options_off (Item_Options opts) { - OnError (::item_opts_off (item, opts)); - } - // Switch off the item's option - - inline Item_Options options () const { - return ::item_opts (item); - } - // Retrieve the items options - - inline void set_options (Item_Options opts) { - OnError (::set_item_opts (item, opts)); - } - // Set the items options - - inline void set_value (bool f) { - OnError (::set_item_value (item,f)); - } - // Set/Reset the items selection state - - inline bool value () const { - return ::item_value (item); - } - // Retrieve the items selection state - - inline bool visible () const { - return ::item_visible (item); - } - // Retrieve visibility of the item - - virtual bool action(); - // Perform an action associated with this item; you may use this in an - // user supplied driver for a menu; you may derive from this class and - // overload action() to supply items with different actions. - // If an action returns true, the menu will be exited. The default action - // is to do nothing. -}; - -// Prototype for an items callback function. -typedef bool ITEMCALLBACK(NCursesMenuItem&); - -// If you don't like to create a child class for individual items to -// overload action(), you may use this class and provide a callback -// function pointer for items. -class NCURSES_IMPEXP NCursesMenuCallbackItem : public NCursesMenuItem -{ -private: - ITEMCALLBACK* p_fct; - -public: - NCursesMenuCallbackItem(ITEMCALLBACK* fct = NULL, - const char* p_name = NULL, - const char* p_descript = NULL ) - : NCursesMenuItem (p_name, p_descript), - p_fct (fct) { - } - - NCursesMenuCallbackItem& operator=(const NCursesMenuCallbackItem& rhs) - { - if (this != &rhs) { - *this = rhs; - } - return *this; - } - - NCursesMenuCallbackItem(const NCursesMenuCallbackItem& rhs) - : NCursesMenuItem(rhs), - p_fct(0) - { - } - - virtual ~NCursesMenuCallbackItem(); - - bool action(); -}; - - // This are the built-in hook functions in this C++ binding. In C++ we use - // virtual member functions (see below On_..._Init and On_..._Termination) - // to provide this functionality in an object oriented manner. -extern "C" { - void _nc_xx_mnu_init(MENU *); - void _nc_xx_mnu_term(MENU *); - void _nc_xx_itm_init(MENU *); - void _nc_xx_itm_term(MENU *); -} - -// -// ------------------------------------------------------------------------- -// This wraps the MENU type of -// ------------------------------------------------------------------------- -// -class NCURSES_IMPEXP NCursesMenu : public NCursesPanel -{ -protected: - MENU *menu; - -private: - NCursesWindow* sub; // the subwindow object - bool b_sub_owner; // is this our own subwindow? - bool b_framed; // has the menu a border? - bool b_autoDelete; // Delete items when deleting menu? - - NCursesMenuItem** my_items; // The array of items for this menu - - // This structure is used for the menu's user data field to link the - // MENU* to the C++ object and to provide extra space for a user pointer. - typedef struct { - void* m_user; // the pointer for the user's data - const NCursesMenu* m_back; // backward pointer to C++ object - const MENU* m_owner; - } UserHook; - - // Get the backward pointer to the C++ object from a MENU - static inline NCursesMenu* getHook(const MENU *m) { - UserHook* hook = STATIC_CAST(UserHook*)(::menu_userptr(m)); - assert(hook != 0 && hook->m_owner==m); - return const_cast(hook->m_back); - } - - friend void _nc_xx_mnu_init(MENU *); - friend void _nc_xx_mnu_term(MENU *); - friend void _nc_xx_itm_init(MENU *); - friend void _nc_xx_itm_term(MENU *); - - // Calculate ITEM* array for the menu - ITEM** mapItems(NCursesMenuItem* nitems[]); - -protected: - // internal routines - inline void set_user(void *user) { - UserHook* uptr = STATIC_CAST(UserHook*)(::menu_userptr (menu)); - assert (uptr != 0 && uptr->m_back==this && uptr->m_owner==menu); - uptr->m_user = user; - } - - inline void *get_user() { - UserHook* uptr = STATIC_CAST(UserHook*)(::menu_userptr (menu)); - assert (uptr != 0 && uptr->m_back==this && uptr->m_owner==menu); - return uptr->m_user; - } - - void InitMenu (NCursesMenuItem* menu[], - bool with_frame, - bool autoDeleteItems); - - inline void OnError (int err) const THROWS(NCursesMenuException) { - if (err != E_OK) - THROW(new NCursesMenuException (this, err)); - } - - // this wraps the menu_driver call. - virtual int driver (int c) ; - - // 'Internal' constructor to create a menu without association to - // an array of items. - NCursesMenu( int nlines, - int ncols, - int begin_y = 0, - int begin_x = 0) - : NCursesPanel(nlines,ncols,begin_y,begin_x), - menu (STATIC_CAST(MENU*)(0)), - sub(0), - b_sub_owner(0), - b_framed(0), - b_autoDelete(0), - my_items(0) - { - } - -public: - // Make a full window size menu - NCursesMenu (NCursesMenuItem* Items[], - bool with_frame=FALSE, // Reserve space for a frame? - bool autoDelete_Items=FALSE) // Autocleanup of Items? - : NCursesPanel(), - menu(0), - sub(0), - b_sub_owner(0), - b_framed(0), - b_autoDelete(0), - my_items(0) - { - InitMenu(Items, with_frame, autoDelete_Items); - } - - // Make a menu with a window of this size. - NCursesMenu (NCursesMenuItem* Items[], - int nlines, - int ncols, - int begin_y = 0, - int begin_x = 0, - bool with_frame=FALSE, // Reserve space for a frame? - bool autoDelete_Items=FALSE) // Autocleanup of Items? - : NCursesPanel(nlines, ncols, begin_y, begin_x), - menu(0), - sub(0), - b_sub_owner(0), - b_framed(0), - b_autoDelete(0), - my_items(0) - { - InitMenu(Items, with_frame, autoDelete_Items); - } - - NCursesMenu& operator=(const NCursesMenu& rhs) - { - if (this != &rhs) { - *this = rhs; - NCursesPanel::operator=(rhs); - } - return *this; - } - - NCursesMenu(const NCursesMenu& rhs) - : NCursesPanel(rhs), - menu(rhs.menu), - sub(rhs.sub), - b_sub_owner(rhs.b_sub_owner), - b_framed(rhs.b_framed), - b_autoDelete(rhs.b_autoDelete), - my_items(rhs.my_items) - { - } - - virtual ~NCursesMenu (); - - // Retrieve the menus subwindow - inline NCursesWindow& subWindow() const { - assert(sub!=NULL); - return *sub; - } - - // Set the menus subwindow - void setSubWindow(NCursesWindow& sub); - - // Set these items for the menu - inline void setItems(NCursesMenuItem* Items[]) { - OnError(::set_menu_items(menu,mapItems(Items))); - } - - // Remove the menu from the screen - inline void unpost (void) { - OnError (::unpost_menu (menu)); - } - - // Post the menu to the screen if flag is true, unpost it otherwise - inline void post(bool flag = TRUE) { - flag ? OnError (::post_menu(menu)) : OnError (::unpost_menu (menu)); - } - - // Get the numer of rows and columns for this menu - inline void scale (int& mrows, int& mcols) const { - OnError (::scale_menu (menu, &mrows, &mcols)); - } - - // Set the format of this menu - inline void set_format(int mrows, int mcols) { - OnError (::set_menu_format(menu, mrows, mcols)); - } - - // Get the format of this menu - inline void menu_format(int& rows,int& ncols) { - ::menu_format(menu,&rows,&ncols); - } - - // Items of the menu - inline NCursesMenuItem* items() const { - return *my_items; - } - - // Get the number of items in this menu - inline int count() const { - return ::item_count(menu); - } - - // Get the current item (i.e. the one the cursor is located) - inline NCursesMenuItem* current_item() const { - return my_items[::item_index(::current_item(menu))]; - } - - // Get the marker string - inline const char* mark() const { - return ::menu_mark(menu); - } - - // Set the marker string - inline void set_mark(const char *marker) { - OnError (::set_menu_mark (menu, marker)); - } - - // Get the name of the request code c - inline static const char* request_name(int c) { - return ::menu_request_name(c); - } - - // Get the current pattern - inline char* pattern() const { - return ::menu_pattern(menu); - } - - // true if there is a pattern match, false otherwise. - bool set_pattern (const char *pat); - - // set the default attributes for the menu - // i.e. set fore, back and grey attribute - virtual void setDefaultAttributes(); - - // Get the menus background attributes - inline chtype back() const { - return ::menu_back(menu); - } - - // Get the menus foreground attributes - inline chtype fore() const { - return ::menu_fore(menu); - } - - // Get the menus grey attributes (used for unselectable items) - inline chtype grey() const { - return ::menu_grey(menu); - } - - // Set the menus background attributes - inline chtype set_background(chtype a) { - return ::set_menu_back(menu,a); - } - - // Set the menus foreground attributes - inline chtype set_foreground(chtype a) { - return ::set_menu_fore(menu,a); - } - - // Set the menus grey attributes (used for unselectable items) - inline chtype set_grey(chtype a) { - return ::set_menu_grey(menu,a); - } - - inline void options_on (Menu_Options opts) { - OnError (::menu_opts_on (menu,opts)); - } - - inline void options_off(Menu_Options opts) { - OnError (::menu_opts_off(menu,opts)); - } - - inline Menu_Options options() const { - return ::menu_opts(menu); - } - - inline void set_options (Menu_Options opts) { - OnError (::set_menu_opts (menu,opts)); - } - - inline int pad() const { - return ::menu_pad(menu); - } - - inline void set_pad (int padch) { - OnError (::set_menu_pad (menu, padch)); - } - - // Position the cursor to the current item - inline void position_cursor () const { - OnError (::pos_menu_cursor (menu)); - } - - // Set the current item - inline void set_current(NCursesMenuItem& I) { - OnError (::set_current_item(menu, I.item)); - } - - // Get the current top row of the menu - inline int top_row (void) const { - return ::top_row (menu); - } - - // Set the current top row of the menu - inline void set_top_row (int row) { - OnError (::set_top_row (menu, row)); - } - - // spacing control - // Set the spacing for the menu - inline void setSpacing(int spc_description, - int spc_rows, - int spc_columns) { - OnError(::set_menu_spacing(menu, - spc_description, - spc_rows, - spc_columns)); - } - - // Get the spacing info for the menu - inline void Spacing(int& spc_description, - int& spc_rows, - int& spc_columns) const { - OnError(::menu_spacing(menu, - &spc_description, - &spc_rows, - &spc_columns)); - } - - // Decorations - inline void frame(const char *title=NULL, const char* btitle=NULL) { - if (b_framed) - NCursesPanel::frame(title,btitle); - else - OnError(E_SYSTEM_ERROR); - } - - inline void boldframe(const char *title=NULL, const char* btitle=NULL) { - if (b_framed) - NCursesPanel::boldframe(title,btitle); - else - OnError(E_SYSTEM_ERROR); - } - - inline void label(const char *topLabel, const char *bottomLabel) { - if (b_framed) - NCursesPanel::label(topLabel,bottomLabel); - else - OnError(E_SYSTEM_ERROR); - } - - // ----- - // Hooks - // ----- - - // Called after the menu gets repositioned in its window. - // This is especially true if the menu is posted. - virtual void On_Menu_Init(); - - // Called before the menu gets repositioned in its window. - // This is especially true if the menu is unposted. - virtual void On_Menu_Termination(); - - // Called after the item became the current item - virtual void On_Item_Init(NCursesMenuItem& item); - - // Called before this item is left as current item. - virtual void On_Item_Termination(NCursesMenuItem& item); - - // Provide a default key virtualization. Translate the keyboard - // code c into a menu request code. - // The default implementation provides a hopefully straightforward - // mapping for the most common keystrokes and menu requests. - virtual int virtualize(int c); - - - // Operators - inline NCursesMenuItem* operator[](int i) const { - if ( (i < 0) || (i >= ::item_count (menu)) ) - OnError (E_BAD_ARGUMENT); - return (my_items[i]); - } - - // Perform the menu's operation - // Return the item where you left the selection mark for a single - // selection menu, or NULL for a multivalued menu. - virtual NCursesMenuItem* operator()(void); - - // -------------------- - // Exception handlers - // Called by operator() - // -------------------- - - // Called if the request is denied - virtual void On_Request_Denied(int c) const; - - // Called if the item is not selectable - virtual void On_Not_Selectable(int c) const; - - // Called if pattern doesn't match - virtual void On_No_Match(int c) const; - - // Called if the command is unknown - virtual void On_Unknown_Command(int c) const; - -}; -// -// ------------------------------------------------------------------------- -// This is the typical C++ typesafe way to allow to attach -// user data to an item of a menu. Its assumed that the user -// data belongs to some class T. Use T as template argument -// to create a UserItem. -// ------------------------------------------------------------------------- -// -template class NCURSES_IMPEXP NCursesUserItem : public NCursesMenuItem -{ -public: - NCursesUserItem (const char* p_name, - const char* p_descript = NULL, - const T* p_UserData = STATIC_CAST(T*)(0)) - : NCursesMenuItem (p_name, p_descript) { - if (item) - OnError (::set_item_userptr (item, const_cast(reinterpret_cast(p_UserData)))); - } - - virtual ~NCursesUserItem() {} - - inline const T* UserData (void) const { - return reinterpret_cast(::item_userptr (item)); - }; - - inline virtual void setUserData(const T* p_UserData) { - if (item) - OnError (::set_item_userptr (item, const_cast(reinterpret_cast(p_UserData)))); - } -}; -// -// ------------------------------------------------------------------------- -// The same mechanism is used to attach user data to a menu -// ------------------------------------------------------------------------- -// -template class NCURSES_IMPEXP NCursesUserMenu : public NCursesMenu -{ -protected: - NCursesUserMenu( int nlines, - int ncols, - int begin_y = 0, - int begin_x = 0, - const T* p_UserData = STATIC_CAST(T*)(0)) - : NCursesMenu(nlines,ncols,begin_y,begin_x) { - if (menu) - set_user (const_cast(p_UserData)); - } - -public: - NCursesUserMenu (NCursesMenuItem Items[], - const T* p_UserData = STATIC_CAST(T*)(0), - bool with_frame=FALSE, - bool autoDelete_Items=FALSE) - : NCursesMenu (Items, with_frame, autoDelete_Items) { - if (menu) - set_user (const_cast(p_UserData)); - }; - - NCursesUserMenu (NCursesMenuItem Items[], - int nlines, - int ncols, - int begin_y = 0, - int begin_x = 0, - const T* p_UserData = STATIC_CAST(T*)(0), - bool with_frame=FALSE) - : NCursesMenu (Items, nlines, ncols, begin_y, begin_x, with_frame) { - if (menu) - set_user (const_cast(p_UserData)); - }; - - virtual ~NCursesUserMenu() { - }; - - inline T* UserData (void) const { - return reinterpret_cast(get_user ()); - }; - - inline virtual void setUserData (const T* p_UserData) { - if (menu) - set_user (const_cast(p_UserData)); - } -}; - -#endif /* NCURSES_CURSESM_H_incl */ diff --git a/windows/ncurses/include/ncurses/cursesp.h b/windows/ncurses/include/ncurses/cursesp.h deleted file mode 100644 index 720f999d0..000000000 --- a/windows/ncurses/include/ncurses/cursesp.h +++ /dev/null @@ -1,268 +0,0 @@ -// * This makes emacs happy -*-Mode: C++;-*- -/**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/**************************************************************************** - * Author: Juergen Pfeifer, 1997 * - ****************************************************************************/ - -#ifndef NCURSES_CURSESP_H_incl -#define NCURSES_CURSESP_H_incl 1 - -// $Id: cursesp.h,v 1.29 2008/08/16 17:20:23 tom Exp $ - -#include - -extern "C" { -# include -} - -class NCURSES_IMPEXP NCursesPanel - : public NCursesWindow -{ -protected: - PANEL *p; - static NCursesPanel *dummy; - -private: - // This structure is used for the panel's user data field to link the - // PANEL* to the C++ object and to provide extra space for a user pointer. - typedef struct { - void* m_user; // the pointer for the user's data - const NCursesPanel* m_back; // backward pointer to C++ object - const PANEL* m_owner; // the panel itself - } UserHook; - - inline UserHook *UserPointer() - { - UserHook* uptr = reinterpret_cast( - const_cast(::panel_userptr (p))); - return uptr; - } - - void init(); // Initialize the panel object - -protected: - void set_user(void *user) - { - UserHook* uptr = UserPointer(); - if (uptr != 0 && uptr->m_back==this && uptr->m_owner==p) { - uptr->m_user = user; - } - } - // Set the user pointer of the panel. - - void *get_user() - { - UserHook* uptr = UserPointer(); - void *result = 0; - if (uptr != 0 && uptr->m_back==this && uptr->m_owner==p) - result = uptr->m_user; - return result; - } - - void OnError (int err) const THROWS(NCursesPanelException) - { - if (err==ERR) - THROW(new NCursesPanelException (this, err)); - } - // If err is equal to the curses error indicator ERR, an error handler - // is called. - - // Get a keystroke. Default implementation calls getch() - virtual int getKey(void); - -public: - NCursesPanel(int nlines, - int ncols, - int begin_y = 0, - int begin_x = 0) - : NCursesWindow(nlines,ncols,begin_y,begin_x), p(0) - { - init(); - } - // Create a panel with this size starting at the requested position. - - NCursesPanel() - : NCursesWindow(::stdscr), p(0) - { - init(); - } - // This constructor creates the default Panel associated with the - // ::stdscr window - - NCursesPanel& operator=(const NCursesPanel& rhs) - { - if (this != &rhs) { - *this = rhs; - NCursesWindow::operator=(rhs); - } - return *this; - } - - NCursesPanel(const NCursesPanel& rhs) - : NCursesWindow(rhs), - p(rhs.p) - { - } - - virtual ~NCursesPanel(); - - // basic manipulation - inline void hide() - { - OnError (::hide_panel(p)); - } - // Hide the panel. It stays in the stack but becomes invisible. - - inline void show() - { - OnError (::show_panel(p)); - } - // Show the panel, i.e. make it visible. - - inline void top() - { - OnError (::top_panel(p)); - } - // Make this panel the top panel in the stack. - - inline void bottom() - { - OnError (::bottom_panel(p)); - } - // Make this panel the bottom panel in the stack. - // N.B.: The panel associated with ::stdscr is always on the bottom. So - // actually bottom() makes the panel the first above ::stdscr. - - virtual int mvwin(int y, int x) - { - OnError(::move_panel(p, y, x)); - return OK; - } - - inline bool hidden() const - { - return (::panel_hidden (p) ? TRUE : FALSE); - } - // Return TRUE if the panel is hidden, FALSE otherwise. - -/* The functions panel_above() and panel_below() are not reflected in - the NCursesPanel class. The reason for this is, that we cannot - assume that a panel retrieved by those operations is one wrapped - by a C++ class. Although this situation might be handled, we also - need a reverse mapping from PANEL to NCursesPanel which needs some - redesign of the low level stuff. At the moment, we define them in the - interface but they will always produce an error. */ - inline NCursesPanel& above() const - { - OnError(ERR); - return *dummy; - } - - inline NCursesPanel& below() const - { - OnError(ERR); - return *dummy; - } - - // Those two are rewrites of the corresponding virtual members of - // NCursesWindow - virtual int refresh(); - // Propagate all panel changes to the virtual screen and update the - // physical screen. - - virtual int noutrefresh(); - // Propagate all panel changes to the virtual screen. - - static void redraw(); - // Redraw all panels. - - // decorations - virtual void frame(const char* title=NULL, - const char* btitle=NULL); - // Put a frame around the panel and put the title centered in the top line - // and btitle in the bottom line. - - virtual void boldframe(const char* title=NULL, - const char* btitle=NULL); - // Same as frame(), but use highlighted attributes. - - virtual void label(const char* topLabel, - const char* bottomLabel); - // Put the title centered in the top line and btitle in the bottom line. - - virtual void centertext(int row,const char* label); - // Put the label text centered in the specified row. -}; - -/* We use templates to provide a typesafe mechanism to associate - * user data with a panel. A NCursesUserPanel is a panel - * associated with some user data of type T. - */ -template class NCursesUserPanel : public NCursesPanel -{ -public: - NCursesUserPanel (int nlines, - int ncols, - int begin_y = 0, - int begin_x = 0, - const T* p_UserData = STATIC_CAST(T*)(0)) - : NCursesPanel (nlines, ncols, begin_y, begin_x) - { - if (p) - set_user (const_cast(p_UserData)); - }; - // This creates an user panel of the requested size with associated - // user data pointed to by p_UserData. - - NCursesUserPanel(const T* p_UserData = STATIC_CAST(T*)(0)) : NCursesPanel() - { - if (p) - set_user(const_cast(p_UserData)); - }; - // This creates an user panel associated with the ::stdscr and user data - // pointed to by p_UserData. - - virtual ~NCursesUserPanel() {}; - - T* UserData (void) const - { - return reinterpret_cast(get_user ()); - }; - // Retrieve the user data associated with the panel. - - virtual void setUserData (const T* p_UserData) - { - if (p) - set_user (const_cast(p_UserData)); - } - // Associate the user panel with the user data pointed to by p_UserData. -}; - -#endif /* NCURSES_CURSESP_H_incl */ diff --git a/windows/ncurses/include/ncurses/cursesw.h b/windows/ncurses/include/ncurses/cursesw.h deleted file mode 100644 index 95659f2fd..000000000 --- a/windows/ncurses/include/ncurses/cursesw.h +++ /dev/null @@ -1,1556 +0,0 @@ -// * This makes emacs happy -*-Mode: C++;-*- -// vile:cppmode -/**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -#ifndef NCURSES_CURSESW_H_incl -#define NCURSES_CURSESW_H_incl 1 - -// $Id: cursesw.h,v 1.48 2008/01/19 21:09:10 tom Exp $ - -#include - -extern "C" { -# include -} - -/* SCO 3.2v4 curses.h includes term.h, which defines lines as a macro. - Undefine it here, because NCursesWindow uses lines as a method. */ -#undef lines - -/* "Convert" macros to inlines. We'll define it as another symbol to avoid - * conflict with library symbols. - */ -#undef UNDEF -#define UNDEF(name) CUR_ ##name - -#ifdef addch -inline int UNDEF(addch)(chtype ch) { return addch(ch); } -#undef addch -#define addch UNDEF(addch) -#endif - -#ifdef addchstr -inline int UNDEF(addchstr)(chtype *at) { return addchstr(at); } -#undef addchstr -#define addchstr UNDEF(addchstr) -#endif - -#ifdef addnstr -inline int UNDEF(addnstr)(const char *str, int n) -{ return addnstr(str, n); } -#undef addnstr -#define addnstr UNDEF(addnstr) -#endif - -#ifdef addstr -inline int UNDEF(addstr)(const char * str) { return addstr(str); } -#undef addstr -#define addstr UNDEF(addstr) -#endif - -#ifdef attroff -inline int UNDEF(attroff)(chtype at) { return attroff(at); } -#undef attroff -#define attroff UNDEF(attroff) -#endif - -#ifdef attron -inline int UNDEF(attron)(chtype at) { return attron(at); } -#undef attron -#define attron UNDEF(attron) -#endif - -#ifdef attrset -inline chtype UNDEF(attrset)(chtype at) { return attrset(at); } -#undef attrset -#define attrset UNDEF(attrset) -#endif - -#ifdef bkgd -inline int UNDEF(bkgd)(chtype ch) { return bkgd(ch); } -#undef bkgd -#define bkgd UNDEF(bkgd) -#endif - -#ifdef bkgdset -inline void UNDEF(bkgdset)(chtype ch) { bkgdset(ch); } -#undef bkgdset -#define bkgdset UNDEF(bkgdset) -#endif - -#ifdef border -inline int UNDEF(border)(chtype ls, chtype rs, chtype ts, chtype bs, chtype tl, chtype tr, chtype bl, chtype br) -{ return border(ls, rs, ts, bs, tl, tr, bl, br); } -#undef border -#define border UNDEF(border) -#endif - -#ifdef box -inline int UNDEF(box)(WINDOW *win, int v, int h) { return box(win, v, h); } -#undef box -#define box UNDEF(box) -#endif - -#ifdef chgat -inline int UNDEF(chgat)(int n, attr_t attr, short color, const void *opts) { - return chgat(n, attr, color, opts); } -#undef chgat -#define chgat UNDEF(chgat) -#endif - -#ifdef clear -inline int UNDEF(clear)() { return clear(); } -#undef clear -#define clear UNDEF(clear) -#endif - -#ifdef clearok -inline int UNDEF(clearok)(WINDOW* win, bool bf) { return clearok(win, bf); } -#undef clearok -#define clearok UNDEF(clearok) -#else -extern "C" NCURSES_IMPEXP int NCURSES_API clearok(WINDOW*, bool); -#endif - -#ifdef clrtobot -inline int UNDEF(clrtobot)() { return clrtobot(); } -#undef clrtobot -#define clrtobot UNDEF(clrtobot) -#endif - -#ifdef clrtoeol -inline int UNDEF(clrtoeol)() { return clrtoeol(); } -#undef clrtoeol -#define clrtoeol UNDEF(clrtoeol) -#endif - -#ifdef color_set -inline chtype UNDEF(color_set)(short p, void* opts) { return color_set(p, opts); } -#undef color_set -#define color_set UNDEF(color_set) -#endif - -#ifdef crmode -inline int UNDEF(crmode)(void) { return crmode(); } -#undef crmode -#define crmode UNDEF(crmode) -#endif - -#ifdef delch -inline int UNDEF(delch)() { return delch(); } -#undef delch -#define delch UNDEF(delch) -#endif - -#ifdef deleteln -inline int UNDEF(deleteln)() { return deleteln(); } -#undef deleteln -#define deleteln UNDEF(deleteln) -#endif - -#ifdef echochar -inline int UNDEF(echochar)(chtype ch) { return echochar(ch); } -#undef echochar -#define echochar UNDEF(echochar) -#endif - -#ifdef erase -inline int UNDEF(erase)() { return erase(); } -#undef erase -#define erase UNDEF(erase) -#endif - -#ifdef fixterm -inline int UNDEF(fixterm)(void) { return fixterm(); } -#undef fixterm -#define fixterm UNDEF(fixterm) -#endif - -#ifdef flushok -inline int UNDEF(flushok)(WINDOW* _win, bool _bf) { - return flushok(_win, _bf); } -#undef flushok -#define flushok UNDEF(flushok) -#else -#define _no_flushok -#endif - -#ifdef getattrs -inline int UNDEF(getattrs)(WINDOW *win) { return getattrs(win); } -#undef getattrs -#define getattrs UNDEF(getattrs) -#endif - -#ifdef getbegyx -inline void UNDEF(getbegyx)(WINDOW* win, int& y, int& x) { getbegyx(win, y, x); } -#undef getbegyx -#define getbegyx UNDEF(getbegyx) -#endif - -#ifdef getbkgd -inline chtype UNDEF(getbkgd)(const WINDOW *win) { return getbkgd(win); } -#undef getbkgd -#define getbkgd UNDEF(getbkgd) -#endif - -#ifdef getch -inline int UNDEF(getch)() { return getch(); } -#undef getch -#define getch UNDEF(getch) -#endif - -#ifdef getmaxyx -inline void UNDEF(getmaxyx)(WINDOW* win, int& y, int& x) { getmaxyx(win, y, x); } -#undef getmaxyx -#define getmaxyx UNDEF(getmaxyx) -#endif - -#ifdef getnstr -inline int UNDEF(getnstr)(char *_str, int n) { return getnstr(_str, n); } -#undef getnstr -#define getnstr UNDEF(getnstr) -#endif - -#ifdef getparyx -inline void UNDEF(getparyx)(WINDOW* win, int& y, int& x) { getparyx(win, y, x); } -#undef getparyx -#define getparyx UNDEF(getparyx) -#endif - -#ifdef getstr -inline int UNDEF(getstr)(char *_str) { return getstr(_str); } -#undef getstr -#define getstr UNDEF(getstr) -#endif - -#ifdef getyx -inline void UNDEF(getyx)(const WINDOW* win, int& y, int& x) { - getyx(win, y, x); } -#undef getyx -#define getyx UNDEF(getyx) -#endif - -#ifdef hline -inline int UNDEF(hline)(chtype ch, int n) { return hline(ch, n); } -#undef hline -#define hline UNDEF(hline) -#endif - -#ifdef inch -inline chtype UNDEF(inch)() { return inch(); } -#undef inch -#define inch UNDEF(inch) -#endif - -#ifdef inchstr -inline int UNDEF(inchstr)(chtype *str) { return inchstr(str); } -#undef inchstr -#define inchstr UNDEF(inchstr) -#endif - -#ifdef innstr -inline int UNDEF(innstr)(char *_str, int n) { return innstr(_str, n); } -#undef innstr -#define innstr UNDEF(innstr) -#endif - -#ifdef insch -inline int UNDEF(insch)(chtype c) { return insch(c); } -#undef insch -#define insch UNDEF(insch) -#endif - -#ifdef insdelln -inline int UNDEF(insdelln)(int n) { return insdelln(n); } -#undef insdelln -#define insdelln UNDEF(insdelln) -#endif - -#ifdef insertln -inline int UNDEF(insertln)() { return insertln(); } -#undef insertln -#define insertln UNDEF(insertln) -#endif - -#ifdef insnstr -inline int UNDEF(insnstr)(const char *_str, int n) { - return insnstr(_str, n); } -#undef insnstr -#define insnstr UNDEF(insnstr) -#endif - -#ifdef insstr -inline int UNDEF(insstr)(const char *_str) { - return insstr(_str); } -#undef insstr -#define insstr UNDEF(insstr) -#endif - -#ifdef instr -inline int UNDEF(instr)(char *_str) { return instr(_str); } -#undef instr -#define instr UNDEF(instr) -#endif - -#ifdef intrflush -inline void UNDEF(intrflush)(WINDOW *win, bool bf) { intrflush(); } -#undef intrflush -#define intrflush UNDEF(intrflush) -#endif - -#ifdef leaveok -inline int UNDEF(leaveok)(WINDOW* win, bool bf) { return leaveok(win, bf); } -#undef leaveok -#define leaveok UNDEF(leaveok) -#else -extern "C" NCURSES_IMPEXP int NCURSES_API leaveok(WINDOW* win, bool bf); -#endif - -#ifdef move -inline int UNDEF(move)(int x, int y) { return move(x, y); } -#undef move -#define move UNDEF(move) -#endif - -#ifdef mvaddch -inline int UNDEF(mvaddch)(int y, int x, chtype ch) -{ return mvaddch(y, x, ch); } -#undef mvaddch -#define mvaddch UNDEF(mvaddch) -#endif - -#ifdef mvaddnstr -inline int UNDEF(mvaddnstr)(int y, int x, const char *str, int n) -{ return mvaddnstr(y, x, str, n); } -#undef mvaddnstr -#define mvaddnstr UNDEF(mvaddnstr) -#endif - -#ifdef mvaddstr -inline int UNDEF(mvaddstr)(int y, int x, const char * str) -{ return mvaddstr(y, x, str); } -#undef mvaddstr -#define mvaddstr UNDEF(mvaddstr) -#endif - -#ifdef mvchgat -inline int UNDEF(mvchgat)(int y, int x, int n, - attr_t attr, short color, const void *opts) { - return mvchgat(y, x, n, attr, color, opts); } -#undef mvchgat -#define mvchgat UNDEF(mvchgat) -#endif - -#ifdef mvdelch -inline int UNDEF(mvdelch)(int y, int x) { return mvdelch(y, x);} -#undef mvdelch -#define mvdelch UNDEF(mvdelch) -#endif - -#ifdef mvgetch -inline int UNDEF(mvgetch)(int y, int x) { return mvgetch(y, x);} -#undef mvgetch -#define mvgetch UNDEF(mvgetch) -#endif - -#ifdef mvgetnstr -inline int UNDEF(mvgetnstr)(int y, int x, char *str, int n) { - return mvgetnstr(y, x, str, n);} -#undef mvgetnstr -#define mvgetnstr UNDEF(mvgetnstr) -#endif - -#ifdef mvgetstr -inline int UNDEF(mvgetstr)(int y, int x, char *str) {return mvgetstr(y, x, str);} -#undef mvgetstr -#define mvgetstr UNDEF(mvgetstr) -#endif - -#ifdef mvinch -inline chtype UNDEF(mvinch)(int y, int x) { return mvinch(y, x);} -#undef mvinch -#define mvinch UNDEF(mvinch) -#endif - -#ifdef mvinnstr -inline int UNDEF(mvinnstr)(int y, int x, char *_str, int n) { - return mvinnstr(y, x, _str, n); } -#undef mvinnstr -#define mvinnstr UNDEF(mvinnstr) -#endif - -#ifdef mvinsch -inline int UNDEF(mvinsch)(int y, int x, chtype c) -{ return mvinsch(y, x, c); } -#undef mvinsch -#define mvinsch UNDEF(mvinsch) -#endif - -#ifdef mvinsnstr -inline int UNDEF(mvinsnstr)(int y, int x, const char *_str, int n) { - return mvinsnstr(y, x, _str, n); } -#undef mvinsnstr -#define mvinsnstr UNDEF(mvinsnstr) -#endif - -#ifdef mvinsstr -inline int UNDEF(mvinsstr)(int y, int x, const char *_str) { - return mvinsstr(y, x, _str); } -#undef mvinsstr -#define mvinsstr UNDEF(mvinsstr) -#endif - -#ifdef mvwaddch -inline int UNDEF(mvwaddch)(WINDOW *win, int y, int x, const chtype ch) -{ return mvwaddch(win, y, x, ch); } -#undef mvwaddch -#define mvwaddch UNDEF(mvwaddch) -#endif - -#ifdef mvwaddchnstr -inline int UNDEF(mvwaddchnstr)(WINDOW *win, int y, int x, const chtype *str, int n) -{ return mvwaddchnstr(win, y, x, str, n); } -#undef mvwaddchnstr -#define mvwaddchnstr UNDEF(mvwaddchnstr) -#endif - -#ifdef mvwaddchstr -inline int UNDEF(mvwaddchstr)(WINDOW *win, int y, int x, const chtype *str) -{ return mvwaddchstr(win, y, x, str); } -#undef mvwaddchstr -#define mvwaddchstr UNDEF(mvwaddchstr) -#endif - -#ifdef mvwaddnstr -inline int UNDEF(mvwaddnstr)(WINDOW *win, int y, int x, const char *str, int n) -{ return mvwaddnstr(win, y, x, str, n); } -#undef mvwaddnstr -#define mvwaddnstr UNDEF(mvwaddnstr) -#endif - -#ifdef mvwaddstr -inline int UNDEF(mvwaddstr)(WINDOW *win, int y, int x, const char * str) -{ return mvwaddstr(win, y, x, str); } -#undef mvwaddstr -#define mvwaddstr UNDEF(mvwaddstr) -#endif - -#ifdef mvwchgat -inline int UNDEF(mvwchgat)(WINDOW *win, int y, int x, int n, - attr_t attr, short color, const void *opts) { - return mvwchgat(win, y, x, n, attr, color, opts); } -#undef mvwchgat -#define mvwchgat UNDEF(mvwchgat) -#endif - -#ifdef mvwdelch -inline int UNDEF(mvwdelch)(WINDOW *win, int y, int x) -{ return mvwdelch(win, y, x); } -#undef mvwdelch -#define mvwdelch UNDEF(mvwdelch) -#endif - -#ifdef mvwgetch -inline int UNDEF(mvwgetch)(WINDOW *win, int y, int x) { return mvwgetch(win, y, x);} -#undef mvwgetch -#define mvwgetch UNDEF(mvwgetch) -#endif - -#ifdef mvwgetnstr -inline int UNDEF(mvwgetnstr)(WINDOW *win, int y, int x, char *str, int n) -{return mvwgetnstr(win, y, x, str, n);} -#undef mvwgetnstr -#define mvwgetnstr UNDEF(mvwgetnstr) -#endif - -#ifdef mvwgetstr -inline int UNDEF(mvwgetstr)(WINDOW *win, int y, int x, char *str) -{return mvwgetstr(win, y, x, str);} -#undef mvwgetstr -#define mvwgetstr UNDEF(mvwgetstr) -#endif - -#ifdef mvwhline -inline int UNDEF(mvwhline)(WINDOW *win, int y, int x, chtype c, int n) { - return mvwhline(win, y, x, c, n); } -#undef mvwhline -#define mvwhline UNDEF(mvwhline) -#endif - -#ifdef mvwinch -inline chtype UNDEF(mvwinch)(WINDOW *win, int y, int x) { - return mvwinch(win, y, x);} -#undef mvwinch -#define mvwinch UNDEF(mvwinch) -#endif - -#ifdef mvwinchnstr -inline int UNDEF(mvwinchnstr)(WINDOW *win, int y, int x, chtype *str, int n) { return mvwinchnstr(win, y, x, str, n); } -#undef mvwinchnstr -#define mvwinchnstr UNDEF(mvwinchnstr) -#endif - -#ifdef mvwinchstr -inline int UNDEF(mvwinchstr)(WINDOW *win, int y, int x, chtype *str) { return mvwinchstr(win, y, x, str); } -#undef mvwinchstr -#define mvwinchstr UNDEF(mvwinchstr) -#endif - -#ifdef mvwinnstr -inline int UNDEF(mvwinnstr)(WINDOW *win, int y, int x, char *_str, int n) { - return mvwinnstr(win, y, x, _str, n); } -#undef mvwinnstr -#define mvwinnstr UNDEF(mvwinnstr) -#endif - -#ifdef mvwinsch -inline int UNDEF(mvwinsch)(WINDOW *win, int y, int x, chtype c) -{ return mvwinsch(win, y, x, c); } -#undef mvwinsch -#define mvwinsch UNDEF(mvwinsch) -#endif - -#ifdef mvwinsnstr -inline int UNDEF(mvwinsnstr)(WINDOW *w, int y, int x, const char *_str, int n) { - return mvwinsnstr(w, y, x, _str, n); } -#undef mvwinsnstr -#define mvwinsnstr UNDEF(mvwinsnstr) -#endif - -#ifdef mvwinsstr -inline int UNDEF(mvwinsstr)(WINDOW *w, int y, int x, const char *_str) { - return mvwinsstr(w, y, x, _str); } -#undef mvwinsstr -#define mvwinsstr UNDEF(mvwinsstr) -#endif - -#ifdef mvwvline -inline int UNDEF(mvwvline)(WINDOW *win, int y, int x, chtype c, int n) { - return mvwvline(win, y, x, c, n); } -#undef mvwvline -#define mvwvline UNDEF(mvwvline) -#endif - -#ifdef napms -inline void UNDEF(napms)(unsigned long x) { napms(x); } -#undef napms -#define napms UNDEF(napms) -#endif - -#ifdef nocrmode -inline int UNDEF(nocrmode)(void) { return nocrmode(); } -#undef nocrmode -#define nocrmode UNDEF(nocrmode) -#endif - -#ifdef nodelay -inline void UNDEF(nodelay)() { nodelay(); } -#undef nodelay -#define nodelay UNDEF(nodelay) -#endif - -#ifdef redrawwin -inline int UNDEF(redrawwin)(WINDOW *win) { return redrawwin(win); } -#undef redrawwin -#define redrawwin UNDEF(redrawwin) -#endif - -#ifdef refresh -inline int UNDEF(refresh)() { return refresh(); } -#undef refresh -#define refresh UNDEF(refresh) -#endif - -#ifdef resetterm -inline int UNDEF(resetterm)(void) { return resetterm(); } -#undef resetterm -#define resetterm UNDEF(resetterm) -#endif - -#ifdef saveterm -inline int UNDEF(saveterm)(void) { return saveterm(); } -#undef saveterm -#define saveterm UNDEF(saveterm) -#endif - -#ifdef scrl -inline int UNDEF(scrl)(int l) { return scrl(l); } -#undef scrl -#define scrl UNDEF(scrl) -#endif - -#ifdef scroll -inline int UNDEF(scroll)(WINDOW *win) { return scroll(win); } -#undef scroll -#define scroll UNDEF(scroll) -#endif - -#ifdef scrollok -inline int UNDEF(scrollok)(WINDOW* win, bool bf) { return scrollok(win, bf); } -#undef scrollok -#define scrollok UNDEF(scrollok) -#else -#if defined(__NCURSES_H) -extern "C" NCURSES_IMPEXP int NCURSES_API scrollok(WINDOW*, bool); -#else -extern "C" NCURSES_IMPEXP int NCURSES_API scrollok(WINDOW*, char); -#endif -#endif - -#ifdef setscrreg -inline int UNDEF(setscrreg)(int t, int b) { return setscrreg(t, b); } -#undef setscrreg -#define setscrreg UNDEF(setscrreg) -#endif - -#ifdef standend -inline int UNDEF(standend)() { return standend(); } -#undef standend -#define standend UNDEF(standend) -#endif - -#ifdef standout -inline int UNDEF(standout)() { return standout(); } -#undef standout -#define standout UNDEF(standout) -#endif - -#ifdef subpad -inline WINDOW *UNDEF(subpad)(WINDOW *p, int l, int c, int y, int x) -{ return derwin(p, l, c, y, x); } -#undef subpad -#define subpad UNDEF(subpad) -#endif - -#ifdef timeout -inline void UNDEF(timeout)(int delay) { timeout(delay); } -#undef timeout -#define timeout UNDEF(timeout) -#endif - -#ifdef touchline -inline int UNDEF(touchline)(WINDOW *win, int s, int c) -{ return touchline(win, s, c); } -#undef touchline -#define touchline UNDEF(touchline) -#endif - -#ifdef touchwin -inline int UNDEF(touchwin)(WINDOW *win) { return touchwin(win); } -#undef touchwin -#define touchwin UNDEF(touchwin) -#endif - -#ifdef untouchwin -inline int UNDEF(untouchwin)(WINDOW *win) { return untouchwin(win); } -#undef untouchwin -#define untouchwin UNDEF(untouchwin) -#endif - -#ifdef vline -inline int UNDEF(vline)(chtype ch, int n) { return vline(ch, n); } -#undef vline -#define vline UNDEF(vline) -#endif - -#ifdef waddchstr -inline int UNDEF(waddchstr)(WINDOW *win, chtype *at) { return waddchstr(win, at); } -#undef waddchstr -#define waddchstr UNDEF(waddchstr) -#endif - -#ifdef waddstr -inline int UNDEF(waddstr)(WINDOW *win, char *str) { return waddstr(win, str); } -#undef waddstr -#define waddstr UNDEF(waddstr) -#endif - -#ifdef wattroff -inline int UNDEF(wattroff)(WINDOW *win, int att) { return wattroff(win, att); } -#undef wattroff -#define wattroff UNDEF(wattroff) -#endif - -#ifdef wattrset -inline int UNDEF(wattrset)(WINDOW *win, int att) { return wattrset(win, att); } -#undef wattrset -#define wattrset UNDEF(wattrset) -#endif - -#ifdef winch -inline chtype UNDEF(winch)(const WINDOW* win) { return winch(win); } -#undef winch -#define winch UNDEF(winch) -#endif - -#ifdef winchnstr -inline int UNDEF(winchnstr)(WINDOW *win, chtype *str, int n) { return winchnstr(win, str, n); } -#undef winchnstr -#define winchnstr UNDEF(winchnstr) -#endif - -#ifdef winchstr -inline int UNDEF(winchstr)(WINDOW *win, chtype *str) { return winchstr(win, str); } -#undef winchstr -#define winchstr UNDEF(winchstr) -#endif - -#ifdef winsstr -inline int UNDEF(winsstr)(WINDOW *w, const char *_str) { - return winsstr(w, _str); } -#undef winsstr -#define winsstr UNDEF(winsstr) -#endif - -#ifdef wstandend -inline int UNDEF(wstandend)(WINDOW *win) { return wstandend(win); } -#undef wstandend -#define wstandend UNDEF(wstandend) -#endif - -#ifdef wstandout -inline int UNDEF(wstandout)(WINDOW *win) { return wstandout(win); } -#undef wstandout -#define wstandout UNDEF(wstandout) -#endif - -/* - * - * C++ class for windows. - * - */ - -extern "C" int _nc_ripoffline(int, int (*init)(WINDOW*, int)); -extern "C" int _nc_xx_ripoff_init(WINDOW *, int); -extern "C" int _nc_has_mouse(void); - -class NCURSES_IMPEXP NCursesWindow -{ - friend class NCursesMenu; - friend class NCursesForm; - -private: - static bool b_initialized; - static void initialize(); - void constructing(); - friend int _nc_xx_ripoff_init(WINDOW *, int); - - void set_keyboard(); - - short getcolor(int getback) const; - short getPair() const; - - static int setpalette(short fore, short back, short pair); - static int colorInitialized; - - // This private constructor is only used during the initialization - // of windows generated by ripoffline() calls. - NCursesWindow(WINDOW* win, int ncols); - -protected: - virtual void err_handler(const char *) const THROWS(NCursesException); - // Signal an error with the given message text. - - static long count; // count of all active windows: - // We rely on the c++ promise that - // all otherwise uninitialized - // static class vars are set to 0 - - WINDOW* w; // the curses WINDOW - - bool alloced; // TRUE if we own the WINDOW - - NCursesWindow* par; // parent, if subwindow - NCursesWindow* subwins; // head of subwindows list - NCursesWindow* sib; // next subwindow of parent - - void kill_subwindows(); // disable all subwindows - // Destroy all subwindows. - - /* Only for use by derived classes. They are then in charge to - fill the member variables correctly. */ - NCursesWindow(); - -public: - NCursesWindow(WINDOW* window); // useful only for stdscr - - NCursesWindow(int nlines, // number of lines - int ncols, // number of columns - int begin_y, // line origin - int begin_x); // col origin - - NCursesWindow(NCursesWindow& par,// parent window - int nlines, // number of lines - int ncols, // number of columns - int begin_y, // absolute or relative - int begin_x, // origins: - char absrel = 'a');// if `a', begin_y & begin_x are - // absolute screen pos, else if `r', they are relative to par origin - - NCursesWindow(NCursesWindow& par,// parent window - bool do_box = TRUE); - // this is the very common case that we want to create the subwindow that - // is two lines and two columns smaller and begins at (1,1). - // We may automatically request the box around it. - - NCursesWindow& operator=(const NCursesWindow& rhs) - { - if (this != &rhs) - *this = rhs; - return *this; - } - - NCursesWindow(const NCursesWindow& rhs) - : w(rhs.w), alloced(rhs.alloced), par(rhs.par), subwins(rhs.subwins), sib(rhs.sib) - { - } - - virtual ~NCursesWindow(); - - NCursesWindow Clone(); - // Make an exact copy of the window. - - // Initialization. - static void useColors(void); - // Call this routine very early if you want to have colors. - - static int ripoffline(int ripoff_lines, - int (*init)(NCursesWindow& win)); - // This function is used to generate a window of ripped-of lines. - // If the argument is positive, lines are removed from the top, if it - // is negative lines are removed from the bottom. This enhances the - // lowlevel ripoffline() function because it uses the internal - // implementation that allows to remove more than just a single line. - // This function must be called before any other ncurses function. The - // creation of the window is deferred until ncurses gets initialized. - // The initialization function is then called. - - // ------------------------------------------------------------------------- - // terminal status - // ------------------------------------------------------------------------- - int lines() const { initialize(); return LINES; } - // Number of lines on terminal, *not* window - - int cols() const { initialize(); return COLS; } - // Number of cols on terminal, *not* window - - int tabsize() const { initialize(); return TABSIZE; } - // Size of a tab on terminal, *not* window - - static int NumberOfColors(); - // Number of available colors - - int colors() const { return NumberOfColors(); } - // Number of available colors - - // ------------------------------------------------------------------------- - // window status - // ------------------------------------------------------------------------- - int height() const { return maxy() + 1; } - // Number of lines in this window - - int width() const { return maxx() + 1; } - // Number of columns in this window - - int begx() const { return getbegx(w); } - // Column of top left corner relative to stdscr - - int begy() const { return getbegy(w); } - // Line of top left corner relative to stdscr - - int curx() const { return getcurx(w); } - // Column of top left corner relative to stdscr - - int cury() const { return getcury(w); } - // Line of top left corner relative to stdscr - - int maxx() const { return getmaxx(w) == ERR ? ERR : getmaxx(w)-1; } - // Largest x coord in window - - int maxy() const { return getmaxy(w) == ERR ? ERR : getmaxy(w)-1; } - // Largest y coord in window - - short getcolor() const; - // Actual color pair - - short foreground() const { return getcolor(0); } - // Actual foreground color - - short background() const { return getcolor(1); } - // Actual background color - - int setpalette(short fore, short back); - // Set color palette entry - - int setcolor(short pair); - // Set actually used palette entry - - // ------------------------------------------------------------------------- - // window positioning - // ------------------------------------------------------------------------- - virtual int mvwin(int begin_y, int begin_x) { - return ::mvwin(w, begin_y, begin_x); } - // Move window to new position with the new position as top left corner. - // This is virtual because it is redefined in NCursesPanel. - - // ------------------------------------------------------------------------- - // coordinate positioning - // ------------------------------------------------------------------------- - int move(int y, int x) { return ::wmove(w, y, x); } - // Move cursor the this position - - void getyx(int& y, int& x) const { ::getyx(w, y, x); } - // Get current position of the cursor - - void getbegyx(int& y, int& x) const { ::getbegyx(w, y, x); } - // Get beginning of the window - - void getmaxyx(int& y, int& x) const { ::getmaxyx(w, y, x); } - // Get size of the window - - void getparyx(int& y, int& x) const { ::getparyx(w, y, x); } - // Get parent's beginning of the window - - int mvcur(int oldrow, int oldcol, int newrow, int newcol) const { - return ::mvcur(oldrow, oldcol, newrow, newcol); } - // Perform lowlevel cursor motion that takes effect immediately. - - // ------------------------------------------------------------------------- - // input - // ------------------------------------------------------------------------- - int getch() { return ::wgetch(w); } - // Get a keystroke from the window. - - int getch(int y, int x) { return ::mvwgetch(w, y, x); } - // Move cursor to position and get a keystroke from the window - - int getstr(char* str, int n=-1) { - return ::wgetnstr(w, str, n); } - // Read a series of characters into str until a newline or carriage return - // is received. Read at most n characters. If n is negative, the limit is - // ignored. - - int getstr(int y, int x, char* str, int n=-1) { - return ::mvwgetnstr(w, y, x, str, n); } - // Move the cursor to the requested position and then perform the getstr() - // as described above. - - int instr(char *s, int n=-1) { return ::winnstr(w, s, n); } - // Get a string of characters from the window into the buffer s. Retrieve - // at most n characters, if n is negative retrieve all characters up to the - // end of the current line. Attributes are stripped from the characters. - - int instr(int y, int x, char *s, int n=-1) { - return ::mvwinnstr(w, y, x, s, n); } - // Move the cursor to the requested position and then perform the instr() - // as described above. - - int scanw(const char* fmt, ...) - // Perform a scanw function from the window. -#if __GNUG__ >= 2 - __attribute__ ((format (scanf, 2, 3))); -#else - ; -#endif - - int scanw(const char*, va_list); - // Perform a scanw function from the window. - - int scanw(int y, int x, const char* fmt, ...) - // Move the cursor to the requested position and then perform a scanw - // from the window. -#if __GNUG__ >= 2 - __attribute__ ((format (scanf, 4, 5))); -#else - ; -#endif - - int scanw(int y, int x, const char* fmt, va_list); - // Move the cursor to the requested position and then perform a scanw - // from the window. - - // ------------------------------------------------------------------------- - // output - // ------------------------------------------------------------------------- - int addch(const chtype ch) { return ::waddch(w, ch); } - // Put attributed character to the window. - - int addch(int y, int x, const chtype ch) { - return ::mvwaddch(w, y, x, ch); } - // Move cursor to the requested position and then put attributed character - // to the window. - - int echochar(const chtype ch) { return ::wechochar(w, ch); } - // Put attributed character to the window and refresh it immediately. - - int addstr(const char* str, int n=-1) { - return ::waddnstr(w, str, n); } - // Write the string str to the window, stop writing if the terminating - // NUL or the limit n is reached. If n is negative, it is ignored. - - int addstr(int y, int x, const char * str, int n=-1) { - return ::mvwaddnstr(w, y, x, str, n); } - // Move the cursor to the requested position and then perform the addchstr - // as described above. - - int addchstr(const chtype* str, int n=-1) { - return ::waddchnstr(w, str, n); } - // Write the string str to the window, stop writing if the terminating - // NUL or the limit n is reached. If n is negative, it is ignored. - - int addchstr(int y, int x, const chtype * str, int n=-1) { - return ::mvwaddchnstr(w, y, x, str, n); } - // Move the cursor to the requested position and then perform the addchstr - // as described above. - - int printw(const char* fmt, ...) - // Do a formatted print to the window. -#if (__GNUG__ >= 2) && !defined(printf) - __attribute__ ((format (printf, 2, 3))); -#else - ; -#endif - - int printw(int y, int x, const char * fmt, ...) - // Move the cursor and then do a formatted print to the window. -#if (__GNUG__ >= 2) && !defined(printf) - __attribute__ ((format (printf, 4, 5))); -#else - ; -#endif - - int printw(const char* fmt, va_list args); - // Do a formatted print to the window. - - int printw(int y, int x, const char * fmt, va_list args); - // Move the cursor and then do a formatted print to the window. - - chtype inch() const { return ::winch(w); } - // Retrieve attributed character under the current cursor position. - - chtype inch(int y, int x) { return ::mvwinch(w, y, x); } - // Move cursor to requested position and then retrieve attributed character - // at this position. - - int inchstr(chtype* str, int n=-1) { - return ::winchnstr(w, str, n); } - // Read the string str from the window, stop reading if the terminating - // NUL or the limit n is reached. If n is negative, it is ignored. - - int inchstr(int y, int x, chtype * str, int n=-1) { - return ::mvwinchnstr(w, y, x, str, n); } - // Move the cursor to the requested position and then perform the inchstr - // as described above. - - int insch(chtype ch) { return ::winsch(w, ch); } - // Insert attributed character into the window before current cursor - // position. - - int insch(int y, int x, chtype ch) { - return ::mvwinsch(w, y, x, ch); } - // Move cursor to requested position and then insert the attributed - // character before that position. - - int insertln() { return ::winsdelln(w, 1); } - // Insert an empty line above the current line. - - int insdelln(int n=1) { return ::winsdelln(w, n); } - // If n>0 insert that many lines above the current line. If n<0 delete - // that many lines beginning with the current line. - - int insstr(const char *s, int n=-1) { - return ::winsnstr(w, s, n); } - // Insert the string into the window before the current cursor position. - // Insert stops at end of string or when the limit n is reached. If n is - // negative, it is ignored. - - int insstr(int y, int x, const char *s, int n=-1) { - return ::mvwinsnstr(w, y, x, s, n); } - // Move the cursor to the requested position and then perform the insstr() - // as described above. - - int attron (chtype at) { return ::wattron (w, at); } - // Switch on the window attributes; - - int attroff(chtype at) { return ::wattroff(w, static_cast(at)); } - // Switch off the window attributes; - - int attrset(chtype at) { return ::wattrset(w, static_cast(at)); } - // Set the window attributes; - - chtype attrget() { return ::getattrs(w); } - // Get the window attributes; - - int color_set(short color_pair_number, void* opts=NULL) { - return ::wcolor_set(w, color_pair_number, opts); } - // Set the window color attribute; - - int chgat(int n, attr_t attr, short color, const void *opts=NULL) { - return ::wchgat(w, n, attr, color, opts); } - // Change the attributes of the next n characters in the current line. If - // n is negative or greater than the number of remaining characters in the - // line, the attributes will be changed up to the end of the line. - - int chgat(int y, int x, - int n, attr_t attr, short color, const void *opts=NULL) { - return ::mvwchgat(w, y, x, n, attr, color, opts); } - // Move the cursor to the requested position and then perform chgat() as - // described above. - - // ------------------------------------------------------------------------- - // background - // ------------------------------------------------------------------------- - chtype getbkgd() const { return ::getbkgd(w); } - // Get current background setting. - - int bkgd(const chtype ch) { return ::wbkgd(w, ch); } - // Set the background property and apply it to the window. - - void bkgdset(chtype ch) { ::wbkgdset(w, ch); } - // Set the background property. - - // ------------------------------------------------------------------------- - // borders - // ------------------------------------------------------------------------- - int box(chtype vert=0, chtype hor=0) { - return ::wborder(w, vert, vert, hor, hor, 0, 0, 0, 0); } - // Draw a box around the window with the given vertical and horizontal - // drawing characters. If you specify a zero as character, curses will try - // to find a "nice" character. - - int border(chtype left=0, chtype right=0, - chtype top =0, chtype bottom=0, - chtype top_left =0, chtype top_right=0, - chtype bottom_left =0, chtype bottom_right=0) { - return ::wborder(w, left, right, top, bottom, top_left, top_right, - bottom_left, bottom_right); } - // Draw a border around the window with the given characters for the - // various parts of the border. If you pass zero for a character, curses - // will try to find "nice" characters. - - // ------------------------------------------------------------------------- - // lines and boxes - // ------------------------------------------------------------------------- - int hline(int len, chtype ch=0) { return ::whline(w, ch, len); } - // Draw a horizontal line of len characters with the given character. If - // you pass zero for the character, curses will try to find a "nice" one. - - int hline(int y, int x, int len, chtype ch=0) { - return ::mvwhline(w, y, x, ch, len); } - // Move the cursor to the requested position and then draw a horizontal line. - - int vline(int len, chtype ch=0) { return ::wvline(w, ch, len); } - // Draw a vertical line of len characters with the given character. If - // you pass zero for the character, curses will try to find a "nice" one. - - int vline(int y, int x, int len, chtype ch=0) { - return ::mvwvline(w, y, x, ch, len); } - // Move the cursor to the requested position and then draw a vertical line. - - // ------------------------------------------------------------------------- - // erasure - // ------------------------------------------------------------------------- - int erase() { return ::werase(w); } - // Erase the window. - - int clear() { return ::wclear(w); } - // Clear the window. - - int clearok(bool bf) { return ::clearok(w, bf); } - // Set/Reset the clear flag. If set, the next refresh() will clear the - // screen. - - int clrtobot() { return ::wclrtobot(w); } - // Clear to the end of the window. - - int clrtoeol() { return ::wclrtoeol(w); } - // Clear to the end of the line. - - int delch() { return ::wdelch(w); } - // Delete character under the cursor. - - int delch(int y, int x) { return ::mvwdelch(w, y, x); } - // Move cursor to requested position and delete the character under the - // cursor. - - int deleteln() { return ::winsdelln(w, -1); } - // Delete the current line. - - // ------------------------------------------------------------------------- - // screen control - // ------------------------------------------------------------------------- - int scroll(int amount=1) { return ::wscrl(w, amount); } - // Scroll amount lines. If amount is positive, scroll up, otherwise - // scroll down. - - int scrollok(bool bf) { return ::scrollok(w, bf); } - // If bf is TRUE, window scrolls if cursor is moved off the bottom - // edge of the window or a scrolling region, otherwise the cursor is left - // at the bottom line. - - int setscrreg(int from, int to) { - return ::wsetscrreg(w, from, to); } - // Define a soft scrolling region. - - int idlok(bool bf) { return ::idlok(w, bf); } - // If bf is TRUE, use insert/delete line hardware support if possible. - // Otherwise do it in software. - - void idcok(bool bf) { ::idcok(w, bf); } - // If bf is TRUE, use insert/delete character hardware support if possible. - // Otherwise do it in software. - - int touchline(int s, int c) { return ::touchline(w, s, c); } - // Mark the given lines as modified. - - int touchwin() { return ::wtouchln(w, 0, height(), 1); } - // Mark the whole window as modified. - - int untouchwin() { return ::wtouchln(w, 0, height(), 0); } - // Mark the whole window as unmodified. - - int touchln(int s, int cnt, bool changed=TRUE) { - return ::wtouchln(w, s, cnt, static_cast(changed ? 1 : 0)); } - // Mark cnt lines beginning from line s as changed or unchanged, depending - // on the value of the changed flag. - - bool is_linetouched(int line) const { - return (::is_linetouched(w, line) ? TRUE:FALSE); } - // Return TRUE if line is marked as changed, FALSE otherwise - - bool is_wintouched() const { - return (::is_wintouched(w) ? TRUE:FALSE); } - // Return TRUE if window is marked as changed, FALSE otherwise - - int leaveok(bool bf) { return ::leaveok(w, bf); } - // If bf is TRUE, curses will leave the cursor after an update whereever - // it is after the update. - - int redrawln(int from, int n) { return ::wredrawln(w, from, n); } - // Redraw n lines starting from the requested line - - int redrawwin() { return ::wredrawln(w, 0, height()); } - // Redraw the whole window - - int doupdate() { return ::doupdate(); } - // Do all outputs to make the physical screen looking like the virtual one - - void syncdown() { ::wsyncdown(w); } - // Propagate the changes down to all descendant windows - - void syncup() { ::wsyncup(w); } - // Propagate the changes up in the hierarchy - - void cursyncup() { ::wcursyncup(w); } - // Position the cursor in all ancestor windows corresponding to our setting - - int syncok(bool bf) { return ::syncok(w, bf); } - // If called with bf=TRUE, syncup() is called whenever the window is changed - -#ifndef _no_flushok - int flushok(bool bf) { return ::flushok(w, bf); } -#endif - - void immedok(bool bf) { ::immedok(w, bf); } - // If called with bf=TRUE, any change in the window will cause an - // automatic immediate refresh() - - int intrflush(bool bf) { return ::intrflush(w, bf); } - - int keypad(bool bf) { return ::keypad(w, bf); } - // If called with bf=TRUE, the application will interpret function keys. - - int nodelay(bool bf) { return ::nodelay(w, bf); } - - int meta(bool bf) { return ::meta(w, bf); } - // If called with bf=TRUE, keys may generate 8-Bit characters. Otherwise - // 7-Bit characters are generated. - - int standout() { return ::wstandout(w); } - // Enable "standout" attributes - - int standend() { return ::wstandend(w); } - // Disable "standout" attributes - - // ------------------------------------------------------------------------- - // The next two are virtual, because we redefine them in the - // NCursesPanel class. - // ------------------------------------------------------------------------- - virtual int refresh() { return ::wrefresh(w); } - // Propagate the changes in this window to the virtual screen and call - // doupdate(). This is redefined in NCursesPanel. - - virtual int noutrefresh() { return ::wnoutrefresh(w); } - // Propagate the changes in this window to the virtual screen. This is - // redefined in NCursesPanel. - - // ------------------------------------------------------------------------- - // multiple window control - // ------------------------------------------------------------------------- - int overlay(NCursesWindow& win) { - return ::overlay(w, win.w); } - // Overlay this window over win. - - int overwrite(NCursesWindow& win) { - return ::overwrite(w, win.w); } - // Overwrite win with this window. - - int copywin(NCursesWindow& win, - int sminrow, int smincol, - int dminrow, int dmincol, - int dmaxrow, int dmaxcol, bool overlaywin=TRUE) { - return ::copywin(w, win.w, sminrow, smincol, dminrow, dmincol, - dmaxrow, dmaxcol, static_cast(overlaywin ? 1 : 0)); } - // Overlay or overwrite the rectangle in win given by dminrow,dmincol, - // dmaxrow,dmaxcol with the rectangle in this window beginning at - // sminrow,smincol. - - // ------------------------------------------------------------------------- - // Extended functions - // ------------------------------------------------------------------------- -#if defined(NCURSES_EXT_FUNCS) && (NCURSES_EXT_FUNCS != 0) - int wresize(int newLines, int newColumns) { - return ::wresize(w, newLines, newColumns); } -#endif - - // ------------------------------------------------------------------------- - // Mouse related - // ------------------------------------------------------------------------- - bool has_mouse() const; - // Return TRUE if terminal supports a mouse, FALSE otherwise - - // ------------------------------------------------------------------------- - // traversal support - // ------------------------------------------------------------------------- - NCursesWindow* child() { return subwins; } - // Get the first child window. - - NCursesWindow* sibling() { return sib; } - // Get the next child of my parent. - - NCursesWindow* parent() { return par; } - // Get my parent. - - bool isDescendant(NCursesWindow& win); - // Return TRUE if win is a descendant of this. -}; - -// ------------------------------------------------------------------------- -// We leave this here for compatibility reasons. -// ------------------------------------------------------------------------- -class NCURSES_IMPEXP NCursesColorWindow : public NCursesWindow -{ -public: - NCursesColorWindow(WINDOW* &window) // useful only for stdscr - : NCursesWindow(window) { - useColors(); } - - NCursesColorWindow(int nlines, // number of lines - int ncols, // number of columns - int begin_y, // line origin - int begin_x) // col origin - : NCursesWindow(nlines, ncols, begin_y, begin_x) { - useColors(); } - - NCursesColorWindow(NCursesWindow& parentWin,// parent window - int nlines, // number of lines - int ncols, // number of columns - int begin_y, // absolute or relative - int begin_x, // origins: - char absrel = 'a') // if `a', by & bx are - : NCursesWindow(parentWin, - nlines, ncols, // absolute screen pos, - begin_y, begin_x, // else if `r', they are - absrel ) { // relative to par origin - useColors(); } -}; - -// These enum definitions really belong inside the NCursesPad class, but only -// recent compilers support that feature. - - typedef enum { - REQ_PAD_REFRESH = KEY_MAX + 1, - REQ_PAD_UP, - REQ_PAD_DOWN, - REQ_PAD_LEFT, - REQ_PAD_RIGHT, - REQ_PAD_EXIT - } Pad_Request; - - const Pad_Request PAD_LOW = REQ_PAD_REFRESH; // lowest op-code - const Pad_Request PAD_HIGH = REQ_PAD_EXIT; // highest op-code - -// ------------------------------------------------------------------------- -// Pad Support. We allow an association of a pad with a "real" window -// through which the pad may be viewed. -// ------------------------------------------------------------------------- -class NCURSES_IMPEXP NCursesPad : public NCursesWindow -{ -private: - NCursesWindow* viewWin; // the "viewport" window - NCursesWindow* viewSub; // the "viewport" subwindow - - int h_gridsize, v_gridsize; - -protected: - int min_row, min_col; // top left row/col of the pads display area - - NCursesWindow* Win(void) const { - // Get the window into which the pad should be copied (if any) - return (viewSub?viewSub:(viewWin?viewWin:0)); - } - - NCursesWindow* getWindow(void) const { - return viewWin; - } - - NCursesWindow* getSubWindow(void) const { - return viewSub; - } - - virtual int driver (int key); // Virtualize keystroke key - // The driver translates the keystroke c into an Pad_Request - - virtual void OnUnknownOperation(int pad_req) { - ::beep(); - } - // This is called if the driver returns an unknown op-code - - virtual void OnNavigationError(int pad_req) { - ::beep(); - } - // This is called if a navigation request couldn't be satisfied - - virtual void OnOperation(int pad_req) { - }; - // OnOperation is called if a Pad_Operation was executed and just before - // the refresh() operation is done. - -public: - NCursesPad(int nlines, int ncols); - // create a pad with the given size - - NCursesPad& operator=(const NCursesPad& rhs) - { - if (this != &rhs) { - *this = rhs; - NCursesWindow::operator=(rhs); - } - return *this; - } - - NCursesPad(const NCursesPad& rhs) - : NCursesWindow(rhs), - viewWin(rhs.viewWin), - viewSub(rhs.viewSub), - h_gridsize(rhs.h_gridsize), - v_gridsize(rhs.v_gridsize), - min_row(rhs.min_row), - min_col(rhs.min_col) - { - } - - virtual ~NCursesPad() {} - - int echochar(const chtype ch) { return ::pechochar(w, ch); } - // Put the attributed character onto the pad and immediately do a - // prefresh(). - - int refresh(); - // If a viewport is defined the pad is displayed in this window, otherwise - // this is a noop. - - int refresh(int pminrow, int pmincol, - int sminrow, int smincol, - int smaxrow, int smaxcol) { - return ::prefresh(w, pminrow, pmincol, - sminrow, smincol, smaxrow, smaxcol); - } - // The coordinates sminrow,smincol,smaxrow,smaxcol describe a rectangle - // on the screen. refresh copies a rectangle of this size beginning - // with top left corner pminrow,pmincol onto the screen and calls doupdate(). - - int noutrefresh(); - // If a viewport is defined the pad is displayed in this window, otherwise - // this is a noop. - - int noutrefresh(int pminrow, int pmincol, - int sminrow, int smincol, - int smaxrow, int smaxcol) { - return ::pnoutrefresh(w, pminrow, pmincol, - sminrow, smincol, smaxrow, smaxcol); - } - // Does the same as refresh() but without calling doupdate(). - - virtual void setWindow(NCursesWindow& view, int v_grid = 1, int h_grid = 1); - // Add the window "view" as viewing window to the pad. - - virtual void setSubWindow(NCursesWindow& sub); - // Use the subwindow "sub" of the viewport window for the actual viewing. - // The full viewport window is usually used to provide some decorations - // like frames, titles etc. - - virtual void operator() (void); - // Perform Pad's operation -}; - -// A FramedPad is constructed always with a viewport window. This viewport -// will be framed (by a box() command) and the interior of the box is the -// viewport subwindow. On the frame we display scrollbar sliders. -class NCURSES_IMPEXP NCursesFramedPad : public NCursesPad -{ -protected: - virtual void OnOperation(int pad_req); - -public: - NCursesFramedPad(NCursesWindow& win, int nlines, int ncols, - int v_grid = 1, int h_grid = 1) - : NCursesPad(nlines, ncols) { - NCursesPad::setWindow(win, v_grid, h_grid); - NCursesPad::setSubWindow(*(new NCursesWindow(win))); - } - // Construct the FramedPad with the given Window win as viewport. - - virtual ~NCursesFramedPad() { - delete getSubWindow(); - } - - void setWindow(NCursesWindow& view, int v_grid = 1, int h_grid = 1) { - err_handler("Operation not allowed"); - } - // Disable this call; the viewport is already defined - - void setSubWindow(NCursesWindow& sub) { - err_handler("Operation not allowed"); - } - // Disable this call; the viewport subwindow is already defined - -}; - -#endif /* NCURSES_CURSESW_H_incl */ diff --git a/windows/ncurses/include/ncurses/cursslk.h b/windows/ncurses/include/ncurses/cursslk.h deleted file mode 100644 index 4c64f402e..000000000 --- a/windows/ncurses/include/ncurses/cursslk.h +++ /dev/null @@ -1,238 +0,0 @@ -// * this is for making emacs happy: -*-Mode: C++;-*- -/**************************************************************************** - * Copyright (c) 1998-2003,2005 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/**************************************************************************** - * Author: Juergen Pfeifer, 1997 * - ****************************************************************************/ - -// $Id: cursslk.h,v 1.13 2005/05/28 21:58:18 tom Exp $ - -#ifndef NCURSES_CURSSLK_H_incl -#define NCURSES_CURSSLK_H_incl - -#include - -class NCURSES_IMPEXP Soft_Label_Key_Set { -public: - // This inner class represents the attributes of a Soft Label Key (SLK) - class NCURSES_IMPEXP Soft_Label_Key { - friend class Soft_Label_Key_Set; - public: - typedef enum { Left=0, Center=1, Right=2 } Justification; - - private: - char *label; // The Text of the Label - Justification format; // The Justification - int num; // The number of the Label - - Soft_Label_Key() : label(NULL), format(Left), num(-1) { - } - - virtual ~Soft_Label_Key() { - delete[] label; - }; - - public: - // Set the text of the Label - Soft_Label_Key& operator=(char *text); - - // Set the Justification of the Label - Soft_Label_Key& operator=(Justification just) { - format = just; - return *this; - } - - // Retrieve the text of the label - inline char* operator()(void) const { - return label; - } - - Soft_Label_Key& operator=(const Soft_Label_Key& rhs) - { - if (this != &rhs) { - *this = rhs; - } - return *this; - } - - Soft_Label_Key(const Soft_Label_Key& rhs) - : label(NULL), - format(rhs.format), - num(rhs.num) - { - *this = rhs.label; - } - }; - -public: - typedef enum { - None = -1, - Three_Two_Three = 0, - Four_Four = 1, - PC_Style = 2, - PC_Style_With_Index = 3 - } Label_Layout; - -private: - static long NCURSES_IMPEXP count; // Number of Key Sets - static Label_Layout NCURSES_IMPEXP format; // Layout of the Key Sets - static int NCURSES_IMPEXP num_labels; // Number Of Labels in Key Sets - bool NCURSES_IMPEXP b_attrInit; // Are attributes initialized - - Soft_Label_Key *slk_array; // The array of SLK's - - // Init the Key Set - void init(); - - // Activate or Deactivate Label# i, Label counting starts with 1! - void activate_label(int i, bool bf=TRUE); - - // Activate of Deactivate all Labels - void activate_labels(bool bf); - -protected: - inline void Error (const char* msg) const THROWS(NCursesException) { - THROW(new NCursesException (msg)); - } - - // Remove SLK's from screen - void clear() { - if (ERR==::slk_clear()) - Error("slk_clear"); - } - - // Restore them - void restore() { - if (ERR==::slk_restore()) - Error("slk_restore"); - } - -public: - - // Construct a Key Set, use the most comfortable layout as default. - // You must create a Soft_Label_Key_Set before you create any object of - // the NCursesWindow, NCursesPanel or derived classes. (Actually before - // ::initscr() is called). - Soft_Label_Key_Set(Label_Layout fmt); - - // This constructor assumes, that you already constructed a Key Set - // with a layout by the constructor above. This layout will be reused. - NCURSES_IMPEXP Soft_Label_Key_Set(); - - Soft_Label_Key_Set& operator=(const Soft_Label_Key_Set& rhs) - { - if (this != &rhs) { - *this = rhs; - init(); // allocate a new slk_array[] - } - return *this; - } - - Soft_Label_Key_Set(const Soft_Label_Key_Set& rhs) - : b_attrInit(rhs.b_attrInit), - slk_array(NULL) - { - init(); // allocate a new slk_array[] - } - - virtual ~Soft_Label_Key_Set(); - - // Get Label# i. Label counting starts with 1! - NCURSES_IMPEXP Soft_Label_Key& operator[](int i); - - // Retrieve number of Labels - inline int labels() const { return num_labels; } - - // Refresh the SLK portion of the screen - inline void refresh() { - if (ERR==::slk_refresh()) - Error("slk_refresh"); - } - - // Mark the SLK portion of the screen for refresh, defer actual refresh - // until next update call. - inline void noutrefresh() { - if (ERR==::slk_noutrefresh()) - Error("slk_noutrefresh"); - } - - // Mark the whole SLK portion of the screen as modified - inline void touch() { - if (ERR==::slk_touch()) - Error("slk_touch"); - } - - // Activate Label# i - inline void show(int i) { - activate_label(i,FALSE); - activate_label(i,TRUE); - } - - // Hide Label# i - inline void hide(int i) { - activate_label(i,FALSE); - } - - // Show all Labels - inline void show() { - activate_labels(FALSE); - activate_labels(TRUE); - } - - // Hide all Labels - inline void hide() { - activate_labels(FALSE); - } - - inline void attron(attr_t attrs) { - if (ERR==::slk_attron(attrs)) - Error("slk_attron"); - } - - inline void attroff(attr_t attrs) { - if (ERR==::slk_attroff(attrs)) - Error("slk_attroff"); - } - - inline void attrset(attr_t attrs) { - if (ERR==::slk_attrset(attrs)) - Error("slk_attrset"); - } - - inline void color(short color_pair_number) { - if (ERR==::slk_color(color_pair_number)) - Error("slk_color"); - } - - inline attr_t attr() const { - return ::slk_attr(); - } -}; - -#endif /* NCURSES_CURSSLK_H_incl */ diff --git a/windows/ncurses/include/ncurses/eti.h b/windows/ncurses/include/ncurses/eti.h deleted file mode 100644 index baa6190d8..000000000 --- a/windows/ncurses/include/ncurses/eti.h +++ /dev/null @@ -1,54 +0,0 @@ -/**************************************************************************** - * Copyright (c) 1998-2002,2003 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/**************************************************************************** - * Author: Juergen Pfeifer, 1995,1997 * - ****************************************************************************/ - -/* $Id: eti.h,v 1.8 2003/10/25 15:24:29 tom Exp $ */ - -#ifndef NCURSES_ETI_H_incl -#define NCURSES_ETI_H_incl 1 - -#define E_OK (0) -#define E_SYSTEM_ERROR (-1) -#define E_BAD_ARGUMENT (-2) -#define E_POSTED (-3) -#define E_CONNECTED (-4) -#define E_BAD_STATE (-5) -#define E_NO_ROOM (-6) -#define E_NOT_POSTED (-7) -#define E_UNKNOWN_COMMAND (-8) -#define E_NO_MATCH (-9) -#define E_NOT_SELECTABLE (-10) -#define E_NOT_CONNECTED (-11) -#define E_REQUEST_DENIED (-12) -#define E_INVALID_FIELD (-13) -#define E_CURRENT (-14) - -#endif diff --git a/windows/ncurses/include/ncurses/etip.h b/windows/ncurses/include/ncurses/etip.h deleted file mode 100644 index 82e9409cf..000000000 --- a/windows/ncurses/include/ncurses/etip.h +++ /dev/null @@ -1,378 +0,0 @@ -// * This makes emacs happy -*-Mode: C++;-*- -/**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/**************************************************************************** - * Author: Juergen Pfeifer, 1997 * - ****************************************************************************/ - -// $Id: etip.h.in,v 1.37 2008/08/30 19:27:32 tom Exp $ - -#ifndef NCURSES_ETIP_H_incl -#define NCURSES_ETIP_H_incl 1 - -// These are substituted at configure/build time -#ifndef HAVE_BUILTIN_H -#define HAVE_BUILTIN_H 0 -#endif - -#ifndef HAVE_GXX_BUILTIN_H -#define HAVE_GXX_BUILTIN_H 0 -#endif - -#ifndef HAVE_GPP_BUILTIN_H -#define HAVE_GPP_BUILTIN_H 0 -#endif - -#ifndef HAVE_IOSTREAM -#define HAVE_IOSTREAM 1 -#endif - -#ifndef HAVE_TYPEINFO -#define HAVE_TYPEINFO 1 -#endif - -#ifndef HAVE_VALUES_H -#define HAVE_VALUES_H 0 -#endif - -#ifndef ETIP_NEEDS_MATH_H -#define ETIP_NEEDS_MATH_H 0 -#endif - -#ifndef ETIP_NEEDS_MATH_EXCEPTION -#define ETIP_NEEDS_MATH_EXCEPTION 0 -#endif - -#ifndef CPP_HAS_PARAM_INIT -#define CPP_HAS_PARAM_INIT 0 -#endif - -#ifndef CPP_HAS_STATIC_CAST -#define CPP_HAS_STATIC_CAST 1 -#endif - -#ifndef IOSTREAM_NAMESPACE -#define IOSTREAM_NAMESPACE 1 -#endif - -#ifdef __GNUG__ -# if ((__GNUG__ <= 2) && (__GNUC_MINOR__ < 8)) -# if HAVE_TYPEINFO -# include -# endif -# endif -#endif - -#if defined(__GNUG__) -# if HAVE_BUILTIN_H || HAVE_GXX_BUILTIN_H || HAVE_GPP_BUILTIN_H -# if ETIP_NEEDS_MATH_H -# if ETIP_NEEDS_MATH_EXCEPTION -# undef exception -# define exception math_exception -# endif -# include -# endif -# undef exception -# define exception builtin_exception -# if HAVE_GPP_BUILTIN_H -# include -# elif HAVE_GXX_BUILTIN_H -# include -# else -# include -# endif -# undef exception -# endif -#elif defined (__SUNPRO_CC) -# include -#endif - -#include - -extern "C" { -#if HAVE_VALUES_H -# include -#endif - -#include -#include -#include -} - -// Language features -#if CPP_HAS_PARAM_INIT -#define NCURSES_PARAM_INIT(value) = value -#else -#define NCURSES_PARAM_INIT(value) /*nothing*/ -#endif - -#if CPP_HAS_STATIC_CAST -#define STATIC_CAST(s) static_cast -#else -#define STATIC_CAST(s) (s) -#endif - -// Forward Declarations -class NCURSES_IMPEXP NCursesPanel; -class NCURSES_IMPEXP NCursesMenu; -class NCURSES_IMPEXP NCursesForm; - -class NCURSES_IMPEXP NCursesException -{ -public: - const char *message; - int errorno; - - NCursesException (const char* msg, int err) - : message(msg), errorno (err) - {}; - - NCursesException (const char* msg) - : message(msg), errorno (E_SYSTEM_ERROR) - {}; - - NCursesException& operator=(const NCursesException& rhs) - { - errorno = rhs.errorno; - return *this; - } - - NCursesException(const NCursesException& rhs) - : message(rhs.message), errorno(rhs.errorno) - { - } - - virtual const char *classname() const { - return "NCursesWindow"; - } - - virtual ~NCursesException() - { - } -}; - -class NCURSES_IMPEXP NCursesPanelException : public NCursesException -{ -public: - const NCursesPanel* p; - - NCursesPanelException (const char *msg, int err) : - NCursesException (msg, err), - p (NULL) - {}; - - NCursesPanelException (const NCursesPanel* panel, - const char *msg, - int err) : - NCursesException (msg, err), - p (panel) - {}; - - NCursesPanelException (int err) : - NCursesException ("panel library error", err), - p (NULL) - {}; - - NCursesPanelException (const NCursesPanel* panel, - int err) : - NCursesException ("panel library error", err), - p (panel) - {}; - - NCursesPanelException& operator=(const NCursesPanelException& rhs) - { - if (this != &rhs) { - NCursesException::operator=(rhs); - p = rhs.p; - } - return *this; - } - - NCursesPanelException(const NCursesPanelException& rhs) - : NCursesException(rhs), p(rhs.p) - { - } - - virtual const char *classname() const { - return "NCursesPanel"; - } - - virtual ~NCursesPanelException() - { - } -}; - -class NCURSES_IMPEXP NCursesMenuException : public NCursesException -{ -public: - const NCursesMenu* m; - - NCursesMenuException (const char *msg, int err) : - NCursesException (msg, err), - m (NULL) - {}; - - NCursesMenuException (const NCursesMenu* menu, - const char *msg, - int err) : - NCursesException (msg, err), - m (menu) - {}; - - NCursesMenuException (int err) : - NCursesException ("menu library error", err), - m (NULL) - {}; - - NCursesMenuException (const NCursesMenu* menu, - int err) : - NCursesException ("menu library error", err), - m (menu) - {}; - - NCursesMenuException& operator=(const NCursesMenuException& rhs) - { - if (this != &rhs) { - NCursesException::operator=(rhs); - m = rhs.m; - } - return *this; - } - - NCursesMenuException(const NCursesMenuException& rhs) - : NCursesException(rhs), m(rhs.m) - { - } - - virtual const char *classname() const { - return "NCursesMenu"; - } - - virtual ~NCursesMenuException() - { - } -}; - -class NCURSES_IMPEXP NCursesFormException : public NCursesException -{ -public: - const NCursesForm* f; - - NCursesFormException (const char *msg, int err) : - NCursesException (msg, err), - f (NULL) - {}; - - NCursesFormException (const NCursesForm* form, - const char *msg, - int err) : - NCursesException (msg, err), - f (form) - {}; - - NCursesFormException (int err) : - NCursesException ("form library error", err), - f (NULL) - {}; - - NCursesFormException (const NCursesForm* form, - int err) : - NCursesException ("form library error", err), - f (form) - {}; - - NCursesFormException& operator=(const NCursesFormException& rhs) - { - if (this != &rhs) { - NCursesException::operator=(rhs); - f = rhs.f; - } - return *this; - } - - NCursesFormException(const NCursesFormException& rhs) - : NCursesException(rhs), f(rhs.f) - { - } - - virtual const char *classname() const { - return "NCursesForm"; - } - - virtual ~NCursesFormException() - { - } -}; - -#if !((defined(__GNUG__) && defined(__EXCEPTIONS)) || defined(__SUNPRO_CC)) -# if HAVE_IOSTREAM -# include -# if IOSTREAM_NAMESPACE -using std::cerr; -using std::endl; -# endif -# else -# include -# endif - extern "C" void exit(int); -#endif - -inline void THROW(const NCursesException *e) { -#if defined(__GNUG__) && defined(__EXCEPTIONS) -# if ((__GNUG__ <= 2) && (__GNUC_MINOR__ < 8)) - (*lib_error_handler)(e ? e->classname() : "", e ? e->message : ""); -#else -#define CPP_HAS_TRY_CATCH 1 -#endif -#elif defined(__SUNPRO_CC) -# if !defined(__SUNPRO_CC_COMPAT) || (__SUNPRO_CC_COMPAT < 5) - genericerror(1, ((e != 0) ? (char *)(e->message) : "")); -#else -#define CPP_HAS_TRY_CATCH 1 -#endif -#else - if (e) - cerr << e->message << endl; - exit(0); -#endif - -#ifndef CPP_HAS_TRY_CATCH -#define CPP_HAS_TRY_CATCH 0 -#define NCURSES_CPP_TRY /* nothing */ -#define NCURSES_CPP_CATCH(e) if (false) -#define THROWS(s) /* nothing */ -#elif CPP_HAS_TRY_CATCH - throw *e; -#define NCURSES_CPP_TRY try -#define NCURSES_CPP_CATCH(e) catch(e) -#define THROWS(s) throw(s) -#endif -} - -#endif /* NCURSES_ETIP_H_incl */ diff --git a/windows/ncurses/include/ncurses/form.h b/windows/ncurses/include/ncurses/form.h deleted file mode 100644 index 80886ac3a..000000000 --- a/windows/ncurses/include/ncurses/form.h +++ /dev/null @@ -1,422 +0,0 @@ -/**************************************************************************** - * Copyright (c) 1998-2004,2009 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/**************************************************************************** - * Author: Juergen Pfeifer, 1995,1997 * - ****************************************************************************/ - -/* $Id: form.h,v 0.21 2009/11/07 19:31:11 tom Exp $ */ - -#ifndef FORM_H -#define FORM_H - -#include -#include - -#ifdef __cplusplus - extern "C" { -#endif - -#ifndef FORM_PRIV_H -typedef void *FIELD_CELL; -#endif - -#ifndef NCURSES_FIELD_INTERNALS -#define NCURSES_FIELD_INTERNALS /* nothing */ -#endif - -typedef int Form_Options; -typedef int Field_Options; - - /********** - * _PAGE * - **********/ - -typedef struct { - short pmin; /* index of first field on page */ - short pmax; /* index of last field on page */ - short smin; /* index of top leftmost field on page */ - short smax; /* index of bottom rightmost field on page */ -} _PAGE; - - /********** - * FIELD * - **********/ - -typedef struct fieldnode { - unsigned short status; /* flags */ - short rows; /* size in rows */ - short cols; /* size in cols */ - short frow; /* first row */ - short fcol; /* first col */ - int drows; /* dynamic rows */ - int dcols; /* dynamic cols */ - int maxgrow; /* maximum field growth */ - int nrow; /* off-screen rows */ - short nbuf; /* additional buffers */ - short just; /* justification */ - short page; /* page on form */ - short index; /* into form -> field */ - int pad; /* pad character */ - chtype fore; /* foreground attribute */ - chtype back; /* background attribute */ - Field_Options opts; /* options */ - struct fieldnode * snext; /* sorted order pointer */ - struct fieldnode * sprev; /* sorted order pointer */ - struct fieldnode * link; /* linked field chain */ - struct formnode * form; /* containing form */ - struct typenode * type; /* field type */ - void * arg; /* argument for type */ - FIELD_CELL * buf; /* field buffers */ - void * usrptr; /* user pointer */ - /* - * The wide-character configuration requires extra information. Because - * there are existing applications that manipulate the members of FIELD - * directly, we cannot make the struct opaque. Offsets of members up to - * this point are the same in the narrow- and wide-character configuration. - * But note that the type of buf depends on the configuration, and is made - * opaque for that reason. - */ - NCURSES_FIELD_INTERNALS -} FIELD; - - - /********* - * FORM * - *********/ - -typedef struct formnode { - unsigned short status; /* flags */ - short rows; /* size in rows */ - short cols; /* size in cols */ - int currow; /* current row in field window */ - int curcol; /* current col in field window */ - int toprow; /* in scrollable field window */ - int begincol; /* in horiz. scrollable field */ - short maxfield; /* number of fields */ - short maxpage; /* number of pages */ - short curpage; /* index into page */ - Form_Options opts; /* options */ - WINDOW * win; /* window */ - WINDOW * sub; /* subwindow */ - WINDOW * w; /* window for current field */ - FIELD ** field; /* field [maxfield] */ - FIELD * current; /* current field */ - _PAGE * page; /* page [maxpage] */ - void * usrptr; /* user pointer */ - - void (*forminit)(struct formnode *); - void (*formterm)(struct formnode *); - void (*fieldinit)(struct formnode *); - void (*fieldterm)(struct formnode *); - -} FORM; - - - /************** - * FIELDTYPE * - **************/ - -typedef struct typenode { - unsigned short status; /* flags */ - long ref; /* reference count */ - struct typenode * left; /* ptr to operand for | */ - struct typenode * right; /* ptr to operand for | */ - - void* (*makearg)(va_list *); /* make fieldtype arg */ - void* (*copyarg)(const void *); /* copy fieldtype arg */ - void (*freearg)(void *); /* free fieldtype arg */ - -#if NCURSES_INTEROP_FUNCS - union { - bool (*ofcheck)(FIELD *,const void *); /* field validation */ - bool (*gfcheck)(FORM*,FIELD *,const void*); /* generic field validation */ - } fieldcheck; - union { - bool (*occheck)(int,const void *); /* character validation */ - bool (*gccheck)(int,FORM*, - FIELD*,const void*); /* generic char validation */ - } charcheck; - union { - bool (*onext)(FIELD *,const void *); /* enumerate next value */ - bool (*gnext)(FORM*,FIELD*,const void*); /* generic enumerate next */ - } enum_next; - union { - bool (*oprev)(FIELD *,const void *); /* enumerate prev value */ - bool (*gprev)(FORM*,FIELD*,const void*); /* generic enumerate prev */ - } enum_prev; - void* (*genericarg)(void*); /* Alternate Arg method */ -#else - bool (*fcheck)(FIELD *,const void *); /* field validation */ - bool (*ccheck)(int,const void *); /* character validation */ - - bool (*next)(FIELD *,const void *); /* enumerate next value */ - bool (*prev)(FIELD *,const void *); /* enumerate prev value */ -#endif -} FIELDTYPE; - -typedef void (*Form_Hook)(FORM *); - - /*************************** - * miscellaneous #defines * - ***************************/ - -/* field justification */ -#define NO_JUSTIFICATION (0) -#define JUSTIFY_LEFT (1) -#define JUSTIFY_CENTER (2) -#define JUSTIFY_RIGHT (3) - -/* field options */ -#define O_VISIBLE (0x0001U) -#define O_ACTIVE (0x0002U) -#define O_PUBLIC (0x0004U) -#define O_EDIT (0x0008U) -#define O_WRAP (0x0010U) -#define O_BLANK (0x0020U) -#define O_AUTOSKIP (0x0040U) -#define O_NULLOK (0x0080U) -#define O_PASSOK (0x0100U) -#define O_STATIC (0x0200U) - -/* form options */ -#define O_NL_OVERLOAD (0x0001U) -#define O_BS_OVERLOAD (0x0002U) - -/* form driver commands */ -#define REQ_NEXT_PAGE (KEY_MAX + 1) /* move to next page */ -#define REQ_PREV_PAGE (KEY_MAX + 2) /* move to previous page */ -#define REQ_FIRST_PAGE (KEY_MAX + 3) /* move to first page */ -#define REQ_LAST_PAGE (KEY_MAX + 4) /* move to last page */ - -#define REQ_NEXT_FIELD (KEY_MAX + 5) /* move to next field */ -#define REQ_PREV_FIELD (KEY_MAX + 6) /* move to previous field */ -#define REQ_FIRST_FIELD (KEY_MAX + 7) /* move to first field */ -#define REQ_LAST_FIELD (KEY_MAX + 8) /* move to last field */ -#define REQ_SNEXT_FIELD (KEY_MAX + 9) /* move to sorted next field */ -#define REQ_SPREV_FIELD (KEY_MAX + 10) /* move to sorted prev field */ -#define REQ_SFIRST_FIELD (KEY_MAX + 11) /* move to sorted first field */ -#define REQ_SLAST_FIELD (KEY_MAX + 12) /* move to sorted last field */ -#define REQ_LEFT_FIELD (KEY_MAX + 13) /* move to left to field */ -#define REQ_RIGHT_FIELD (KEY_MAX + 14) /* move to right to field */ -#define REQ_UP_FIELD (KEY_MAX + 15) /* move to up to field */ -#define REQ_DOWN_FIELD (KEY_MAX + 16) /* move to down to field */ - -#define REQ_NEXT_CHAR (KEY_MAX + 17) /* move to next char in field */ -#define REQ_PREV_CHAR (KEY_MAX + 18) /* move to prev char in field */ -#define REQ_NEXT_LINE (KEY_MAX + 19) /* move to next line in field */ -#define REQ_PREV_LINE (KEY_MAX + 20) /* move to prev line in field */ -#define REQ_NEXT_WORD (KEY_MAX + 21) /* move to next word in field */ -#define REQ_PREV_WORD (KEY_MAX + 22) /* move to prev word in field */ -#define REQ_BEG_FIELD (KEY_MAX + 23) /* move to first char in field */ -#define REQ_END_FIELD (KEY_MAX + 24) /* move after last char in fld */ -#define REQ_BEG_LINE (KEY_MAX + 25) /* move to beginning of line */ -#define REQ_END_LINE (KEY_MAX + 26) /* move after last char in line */ -#define REQ_LEFT_CHAR (KEY_MAX + 27) /* move left in field */ -#define REQ_RIGHT_CHAR (KEY_MAX + 28) /* move right in field */ -#define REQ_UP_CHAR (KEY_MAX + 29) /* move up in field */ -#define REQ_DOWN_CHAR (KEY_MAX + 30) /* move down in field */ - -#define REQ_NEW_LINE (KEY_MAX + 31) /* insert/overlay new line */ -#define REQ_INS_CHAR (KEY_MAX + 32) /* insert blank char at cursor */ -#define REQ_INS_LINE (KEY_MAX + 33) /* insert blank line at cursor */ -#define REQ_DEL_CHAR (KEY_MAX + 34) /* delete char at cursor */ -#define REQ_DEL_PREV (KEY_MAX + 35) /* delete char before cursor */ -#define REQ_DEL_LINE (KEY_MAX + 36) /* delete line at cursor */ -#define REQ_DEL_WORD (KEY_MAX + 37) /* delete word at cursor */ -#define REQ_CLR_EOL (KEY_MAX + 38) /* clear to end of line */ -#define REQ_CLR_EOF (KEY_MAX + 39) /* clear to end of field */ -#define REQ_CLR_FIELD (KEY_MAX + 40) /* clear entire field */ -#define REQ_OVL_MODE (KEY_MAX + 41) /* begin overlay mode */ -#define REQ_INS_MODE (KEY_MAX + 42) /* begin insert mode */ -#define REQ_SCR_FLINE (KEY_MAX + 43) /* scroll field forward a line */ -#define REQ_SCR_BLINE (KEY_MAX + 44) /* scroll field backward a line */ -#define REQ_SCR_FPAGE (KEY_MAX + 45) /* scroll field forward a page */ -#define REQ_SCR_BPAGE (KEY_MAX + 46) /* scroll field backward a page */ -#define REQ_SCR_FHPAGE (KEY_MAX + 47) /* scroll field forward half page */ -#define REQ_SCR_BHPAGE (KEY_MAX + 48) /* scroll field backward half page */ -#define REQ_SCR_FCHAR (KEY_MAX + 49) /* horizontal scroll char */ -#define REQ_SCR_BCHAR (KEY_MAX + 50) /* horizontal scroll char */ -#define REQ_SCR_HFLINE (KEY_MAX + 51) /* horizontal scroll line */ -#define REQ_SCR_HBLINE (KEY_MAX + 52) /* horizontal scroll line */ -#define REQ_SCR_HFHALF (KEY_MAX + 53) /* horizontal scroll half line */ -#define REQ_SCR_HBHALF (KEY_MAX + 54) /* horizontal scroll half line */ - -#define REQ_VALIDATION (KEY_MAX + 55) /* validate field */ -#define REQ_NEXT_CHOICE (KEY_MAX + 56) /* display next field choice */ -#define REQ_PREV_CHOICE (KEY_MAX + 57) /* display prev field choice */ - -#define MIN_FORM_COMMAND (KEY_MAX + 1) /* used by form_driver */ -#define MAX_FORM_COMMAND (KEY_MAX + 57) /* used by form_driver */ - -#if defined(MAX_COMMAND) -# if (MAX_FORM_COMMAND > MAX_COMMAND) -# error Something is wrong -- MAX_FORM_COMMAND is greater than MAX_COMMAND -# elif (MAX_COMMAND != (KEY_MAX + 128)) -# error Something is wrong -- MAX_COMMAND is already inconsistently defined. -# endif -#else -# define MAX_COMMAND (KEY_MAX + 128) -#endif - - /************************* - * standard field types * - *************************/ -extern NCURSES_EXPORT_VAR(FIELDTYPE *) TYPE_ALPHA; -extern NCURSES_EXPORT_VAR(FIELDTYPE *) TYPE_ALNUM; -extern NCURSES_EXPORT_VAR(FIELDTYPE *) TYPE_ENUM; -extern NCURSES_EXPORT_VAR(FIELDTYPE *) TYPE_INTEGER; -extern NCURSES_EXPORT_VAR(FIELDTYPE *) TYPE_NUMERIC; -extern NCURSES_EXPORT_VAR(FIELDTYPE *) TYPE_REGEXP; - - /************************************ - * built-in additional field types * - * They are not defined in SVr4 * - ************************************/ -extern NCURSES_EXPORT_VAR(FIELDTYPE *) TYPE_IPV4; /* Internet IP Version 4 address */ - - /*********************** - * FIELDTYPE routines * - ***********************/ -extern NCURSES_EXPORT(FIELDTYPE *) new_fieldtype ( - bool (* const field_check)(FIELD *,const void *), - bool (* const char_check)(int,const void *)); -extern NCURSES_EXPORT(FIELDTYPE *) link_fieldtype( - FIELDTYPE *, FIELDTYPE *); - -extern NCURSES_EXPORT(int) free_fieldtype (FIELDTYPE *); -extern NCURSES_EXPORT(int) set_fieldtype_arg (FIELDTYPE *, - void * (* const make_arg)(va_list *), - void * (* const copy_arg)(const void *), - void (* const free_arg)(void *)); -extern NCURSES_EXPORT(int) set_fieldtype_choice (FIELDTYPE *, - bool (* const next_choice)(FIELD *,const void *), - bool (* const prev_choice)(FIELD *,const void *)); - - /******************* - * FIELD routines * - *******************/ -extern NCURSES_EXPORT(FIELD *) new_field (int,int,int,int,int,int); -extern NCURSES_EXPORT(FIELD *) dup_field (FIELD *,int,int); -extern NCURSES_EXPORT(FIELD *) link_field (FIELD *,int,int); - -extern NCURSES_EXPORT(int) free_field (FIELD *); -extern NCURSES_EXPORT(int) field_info (const FIELD *,int *,int *,int *,int *,int *,int *); -extern NCURSES_EXPORT(int) dynamic_field_info (const FIELD *,int *,int *,int *); -extern NCURSES_EXPORT(int) set_max_field ( FIELD *,int); -extern NCURSES_EXPORT(int) move_field (FIELD *,int,int); -extern NCURSES_EXPORT(int) set_field_type (FIELD *,FIELDTYPE *,...); -extern NCURSES_EXPORT(int) set_new_page (FIELD *,bool); -extern NCURSES_EXPORT(int) set_field_just (FIELD *,int); -extern NCURSES_EXPORT(int) field_just (const FIELD *); -extern NCURSES_EXPORT(int) set_field_fore (FIELD *,chtype); -extern NCURSES_EXPORT(int) set_field_back (FIELD *,chtype); -extern NCURSES_EXPORT(int) set_field_pad (FIELD *,int); -extern NCURSES_EXPORT(int) field_pad (const FIELD *); -extern NCURSES_EXPORT(int) set_field_buffer (FIELD *,int,const char *); -extern NCURSES_EXPORT(int) set_field_status (FIELD *,bool); -extern NCURSES_EXPORT(int) set_field_userptr (FIELD *, void *); -extern NCURSES_EXPORT(int) set_field_opts (FIELD *,Field_Options); -extern NCURSES_EXPORT(int) field_opts_on (FIELD *,Field_Options); -extern NCURSES_EXPORT(int) field_opts_off (FIELD *,Field_Options); - -extern NCURSES_EXPORT(chtype) field_fore (const FIELD *); -extern NCURSES_EXPORT(chtype) field_back (const FIELD *); - -extern NCURSES_EXPORT(bool) new_page (const FIELD *); -extern NCURSES_EXPORT(bool) field_status (const FIELD *); - -extern NCURSES_EXPORT(void *) field_arg (const FIELD *); - -extern NCURSES_EXPORT(void *) field_userptr (const FIELD *); - -extern NCURSES_EXPORT(FIELDTYPE *) field_type (const FIELD *); - -extern NCURSES_EXPORT(char *) field_buffer (const FIELD *,int); - -extern NCURSES_EXPORT(Field_Options) field_opts (const FIELD *); - - /****************** - * FORM routines * - ******************/ - -extern NCURSES_EXPORT(FORM *) new_form (FIELD **); - -extern NCURSES_EXPORT(FIELD **) form_fields (const FORM *); -extern NCURSES_EXPORT(FIELD *) current_field (const FORM *); - -extern NCURSES_EXPORT(WINDOW *) form_win (const FORM *); -extern NCURSES_EXPORT(WINDOW *) form_sub (const FORM *); - -extern NCURSES_EXPORT(Form_Hook) form_init (const FORM *); -extern NCURSES_EXPORT(Form_Hook) form_term (const FORM *); -extern NCURSES_EXPORT(Form_Hook) field_init (const FORM *); -extern NCURSES_EXPORT(Form_Hook) field_term (const FORM *); - -extern NCURSES_EXPORT(int) free_form (FORM *); -extern NCURSES_EXPORT(int) set_form_fields (FORM *,FIELD **); -extern NCURSES_EXPORT(int) field_count (const FORM *); -extern NCURSES_EXPORT(int) set_form_win (FORM *,WINDOW *); -extern NCURSES_EXPORT(int) set_form_sub (FORM *,WINDOW *); -extern NCURSES_EXPORT(int) set_current_field (FORM *,FIELD *); -extern NCURSES_EXPORT(int) field_index (const FIELD *); -extern NCURSES_EXPORT(int) set_form_page (FORM *,int); -extern NCURSES_EXPORT(int) form_page (const FORM *); -extern NCURSES_EXPORT(int) scale_form (const FORM *,int *,int *); -extern NCURSES_EXPORT(int) set_form_init (FORM *,Form_Hook); -extern NCURSES_EXPORT(int) set_form_term (FORM *,Form_Hook); -extern NCURSES_EXPORT(int) set_field_init (FORM *,Form_Hook); -extern NCURSES_EXPORT(int) set_field_term (FORM *,Form_Hook); -extern NCURSES_EXPORT(int) post_form (FORM *); -extern NCURSES_EXPORT(int) unpost_form (FORM *); -extern NCURSES_EXPORT(int) pos_form_cursor (FORM *); -extern NCURSES_EXPORT(int) form_driver (FORM *,int); -extern NCURSES_EXPORT(int) set_form_userptr (FORM *,void *); -extern NCURSES_EXPORT(int) set_form_opts (FORM *,Form_Options); -extern NCURSES_EXPORT(int) form_opts_on (FORM *,Form_Options); -extern NCURSES_EXPORT(int) form_opts_off (FORM *,Form_Options); -extern NCURSES_EXPORT(int) form_request_by_name (const char *); - -extern NCURSES_EXPORT(const char *) form_request_name (int); - -extern NCURSES_EXPORT(void *) form_userptr (const FORM *); - -extern NCURSES_EXPORT(Form_Options) form_opts (const FORM *); - -extern NCURSES_EXPORT(bool) data_ahead (const FORM *); -extern NCURSES_EXPORT(bool) data_behind (const FORM *); - -#if NCURSES_SP_FUNCS -extern NCURSES_EXPORT(FORM *) NCURSES_SP_NAME(new_form) (SCREEN*, FIELD **); -#endif - -#ifdef __cplusplus - } -#endif - -#endif /* FORM_H */ diff --git a/windows/ncurses/include/ncurses/menu.h b/windows/ncurses/include/ncurses/menu.h deleted file mode 100644 index 48eaa3f1d..000000000 --- a/windows/ncurses/include/ncurses/menu.h +++ /dev/null @@ -1,260 +0,0 @@ -/**************************************************************************** - * Copyright (c) 1998-2007,2009 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/**************************************************************************** - * Author: Juergen Pfeifer, 1995,1997 * - ****************************************************************************/ - -/* $Id: menu.h,v 1.20 2009/04/05 00:28:07 tom Exp $ */ - -#ifndef ETI_MENU -#define ETI_MENU - -#ifdef AMIGA -#define TEXT TEXT_ncurses -#endif - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef int Menu_Options; -typedef int Item_Options; - -/* Menu options: */ -#define O_ONEVALUE (0x01) -#define O_SHOWDESC (0x02) -#define O_ROWMAJOR (0x04) -#define O_IGNORECASE (0x08) -#define O_SHOWMATCH (0x10) -#define O_NONCYCLIC (0x20) - -/* Item options: */ -#define O_SELECTABLE (0x01) - -typedef struct -{ - const char* str; - unsigned short length; -} TEXT; - -typedef struct tagITEM -{ - TEXT name; /* name of menu item */ - TEXT description; /* description of item, optional in display */ - struct tagMENU *imenu; /* Pointer to parent menu */ - void *userptr; /* Pointer to user defined per item data */ - Item_Options opt; /* Item options */ - short index; /* Item number if connected to a menu */ - short y; /* y and x location of item in menu */ - short x; - bool value; /* Selection value */ - - struct tagITEM *left; /* neighbor items */ - struct tagITEM *right; - struct tagITEM *up; - struct tagITEM *down; - -} ITEM; - -typedef void (*Menu_Hook)(struct tagMENU *); - -typedef struct tagMENU -{ - short height; /* Nr. of chars high */ - short width; /* Nr. of chars wide */ - short rows; /* Nr. of items high */ - short cols; /* Nr. of items wide */ - short frows; /* Nr. of formatted items high */ - short fcols; /* Nr. of formatted items wide */ - short arows; /* Nr. of items high (actual) */ - short namelen; /* Max. name length */ - short desclen; /* Max. description length */ - short marklen; /* Length of mark, if any */ - short itemlen; /* Length of one item */ - short spc_desc; /* Spacing for descriptor */ - short spc_cols; /* Spacing for columns */ - short spc_rows; /* Spacing for rows */ - char *pattern; /* Buffer to store match chars */ - short pindex; /* Index into pattern buffer */ - WINDOW *win; /* Window containing menu */ - WINDOW *sub; /* Subwindow for menu display */ - WINDOW *userwin; /* User's window */ - WINDOW *usersub; /* User's subwindow */ - ITEM **items; /* array of items */ - short nitems; /* Nr. of items in menu */ - ITEM *curitem; /* Current item */ - short toprow; /* Top row of menu */ - chtype fore; /* Selection attribute */ - chtype back; /* Nonselection attribute */ - chtype grey; /* Inactive attribute */ - unsigned char pad; /* Pad character */ - - Menu_Hook menuinit; /* User hooks */ - Menu_Hook menuterm; - Menu_Hook iteminit; - Menu_Hook itemterm; - - void *userptr; /* Pointer to menus user data */ - char *mark; /* Pointer to marker string */ - - Menu_Options opt; /* Menu options */ - unsigned short status; /* Internal state of menu */ - -} MENU; - - -/* Define keys */ - -#define REQ_LEFT_ITEM (KEY_MAX + 1) -#define REQ_RIGHT_ITEM (KEY_MAX + 2) -#define REQ_UP_ITEM (KEY_MAX + 3) -#define REQ_DOWN_ITEM (KEY_MAX + 4) -#define REQ_SCR_ULINE (KEY_MAX + 5) -#define REQ_SCR_DLINE (KEY_MAX + 6) -#define REQ_SCR_DPAGE (KEY_MAX + 7) -#define REQ_SCR_UPAGE (KEY_MAX + 8) -#define REQ_FIRST_ITEM (KEY_MAX + 9) -#define REQ_LAST_ITEM (KEY_MAX + 10) -#define REQ_NEXT_ITEM (KEY_MAX + 11) -#define REQ_PREV_ITEM (KEY_MAX + 12) -#define REQ_TOGGLE_ITEM (KEY_MAX + 13) -#define REQ_CLEAR_PATTERN (KEY_MAX + 14) -#define REQ_BACK_PATTERN (KEY_MAX + 15) -#define REQ_NEXT_MATCH (KEY_MAX + 16) -#define REQ_PREV_MATCH (KEY_MAX + 17) - -#define MIN_MENU_COMMAND (KEY_MAX + 1) -#define MAX_MENU_COMMAND (KEY_MAX + 17) - -/* - * Some AT&T code expects MAX_COMMAND to be out-of-band not - * just for menu commands but for forms ones as well. - */ -#if defined(MAX_COMMAND) -# if (MAX_MENU_COMMAND > MAX_COMMAND) -# error Something is wrong -- MAX_MENU_COMMAND is greater than MAX_COMMAND -# elif (MAX_COMMAND != (KEY_MAX + 128)) -# error Something is wrong -- MAX_COMMAND is already inconsistently defined. -# endif -#else -# define MAX_COMMAND (KEY_MAX + 128) -#endif - - -/* --------- prototypes for libmenu functions ----------------------------- */ - -extern NCURSES_EXPORT(ITEM **) menu_items (const MENU *); -extern NCURSES_EXPORT(ITEM *) current_item (const MENU *); -extern NCURSES_EXPORT(ITEM *) new_item (const char *,const char *); - -extern NCURSES_EXPORT(MENU *) new_menu (ITEM **); - -extern NCURSES_EXPORT(Item_Options) item_opts (const ITEM *); -extern NCURSES_EXPORT(Menu_Options) menu_opts (const MENU *); - -extern NCURSES_EXPORT(Menu_Hook) item_init (const MENU *); -extern NCURSES_EXPORT(Menu_Hook) item_term (const MENU *); -extern NCURSES_EXPORT(Menu_Hook) menu_init (const MENU *); -extern NCURSES_EXPORT(Menu_Hook) menu_term (const MENU *); - -extern NCURSES_EXPORT(WINDOW *) menu_sub (const MENU *); -extern NCURSES_EXPORT(WINDOW *) menu_win (const MENU *); - -extern NCURSES_EXPORT(const char *) item_description (const ITEM *); -extern NCURSES_EXPORT(const char *) item_name (const ITEM *); -extern NCURSES_EXPORT(const char *) menu_mark (const MENU *); -extern NCURSES_EXPORT(const char *) menu_request_name (int); - -extern NCURSES_EXPORT(char *) menu_pattern (const MENU *); - -extern NCURSES_EXPORT(void *) menu_userptr (const MENU *); -extern NCURSES_EXPORT(void *) item_userptr (const ITEM *); - -extern NCURSES_EXPORT(chtype) menu_back (const MENU *); -extern NCURSES_EXPORT(chtype) menu_fore (const MENU *); -extern NCURSES_EXPORT(chtype) menu_grey (const MENU *); - -extern NCURSES_EXPORT(int) free_item (ITEM *); -extern NCURSES_EXPORT(int) free_menu (MENU *); -extern NCURSES_EXPORT(int) item_count (const MENU *); -extern NCURSES_EXPORT(int) item_index (const ITEM *); -extern NCURSES_EXPORT(int) item_opts_off (ITEM *,Item_Options); -extern NCURSES_EXPORT(int) item_opts_on (ITEM *,Item_Options); -extern NCURSES_EXPORT(int) menu_driver (MENU *,int); -extern NCURSES_EXPORT(int) menu_opts_off (MENU *,Menu_Options); -extern NCURSES_EXPORT(int) menu_opts_on (MENU *,Menu_Options); -extern NCURSES_EXPORT(int) menu_pad (const MENU *); -extern NCURSES_EXPORT(int) pos_menu_cursor (const MENU *); -extern NCURSES_EXPORT(int) post_menu (MENU *); -extern NCURSES_EXPORT(int) scale_menu (const MENU *,int *,int *); -extern NCURSES_EXPORT(int) set_current_item (MENU *menu,ITEM *item); -extern NCURSES_EXPORT(int) set_item_init (MENU *, Menu_Hook); -extern NCURSES_EXPORT(int) set_item_opts (ITEM *,Item_Options); -extern NCURSES_EXPORT(int) set_item_term (MENU *, Menu_Hook); -extern NCURSES_EXPORT(int) set_item_userptr (ITEM *, void *); -extern NCURSES_EXPORT(int) set_item_value (ITEM *,bool); -extern NCURSES_EXPORT(int) set_menu_back (MENU *,chtype); -extern NCURSES_EXPORT(int) set_menu_fore (MENU *,chtype); -extern NCURSES_EXPORT(int) set_menu_format (MENU *,int,int); -extern NCURSES_EXPORT(int) set_menu_grey (MENU *,chtype); -extern NCURSES_EXPORT(int) set_menu_init (MENU *, Menu_Hook); -extern NCURSES_EXPORT(int) set_menu_items (MENU *,ITEM **); -extern NCURSES_EXPORT(int) set_menu_mark (MENU *, const char *); -extern NCURSES_EXPORT(int) set_menu_opts (MENU *,Menu_Options); -extern NCURSES_EXPORT(int) set_menu_pad (MENU *,int); -extern NCURSES_EXPORT(int) set_menu_pattern (MENU *,const char *); -extern NCURSES_EXPORT(int) set_menu_sub (MENU *,WINDOW *); -extern NCURSES_EXPORT(int) set_menu_term (MENU *, Menu_Hook); -extern NCURSES_EXPORT(int) set_menu_userptr (MENU *,void *); -extern NCURSES_EXPORT(int) set_menu_win (MENU *,WINDOW *); -extern NCURSES_EXPORT(int) set_top_row (MENU *,int); -extern NCURSES_EXPORT(int) top_row (const MENU *); -extern NCURSES_EXPORT(int) unpost_menu (MENU *); -extern NCURSES_EXPORT(int) menu_request_by_name (const char *); -extern NCURSES_EXPORT(int) set_menu_spacing (MENU *,int,int,int); -extern NCURSES_EXPORT(int) menu_spacing (const MENU *,int *,int *,int *); - - -extern NCURSES_EXPORT(bool) item_value (const ITEM *); -extern NCURSES_EXPORT(bool) item_visible (const ITEM *); - -extern NCURSES_EXPORT(void) menu_format (const MENU *,int *,int *); - -#if NCURSES_SP_FUNCS -extern NCURSES_EXPORT(MENU *) NCURSES_SP_NAME(new_menu) (SCREEN*, ITEM **); -#endif - -#ifdef __cplusplus - } -#endif - -#endif /* ETI_MENU */ diff --git a/windows/ncurses/include/ncurses/nc_tparm.h b/windows/ncurses/include/ncurses/nc_tparm.h deleted file mode 100644 index a8dbcacb1..000000000 --- a/windows/ncurses/include/ncurses/nc_tparm.h +++ /dev/null @@ -1,73 +0,0 @@ -/**************************************************************************** - * Copyright (c) 2006,2010 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/**************************************************************************** - * Author: Thomas E. Dickey 2006 * - ****************************************************************************/ - -/* $Id: nc_tparm.h,v 1.5 2010/12/25 20:27:22 tom Exp $ */ - -#ifndef NC_TPARM_included -#define NC_TPARM_included 1 - -/* - * Cast parameters past the formatting-string for tparm() to match the - * assumption of the varargs code. - */ -#ifndef TPARM_ARG -#define TPARM_ARG long -#endif - -#define TPARM_N(n) (TPARM_ARG)(n) - -#define TPARM_9(a,b,c,d,e,f,g,h,i,j) tparm(a,TPARM_N(b),TPARM_N(c),TPARM_N(d),TPARM_N(e),TPARM_N(f),TPARM_N(g),TPARM_N(h),TPARM_N(i),TPARM_N(j)) - -#if NCURSES_TPARM_VARARGS -#define TPARM_8(a,b,c,d,e,f,g,h,i) tparm(a,TPARM_N(b),TPARM_N(c),TPARM_N(d),TPARM_N(e),TPARM_N(f),TPARM_N(g),TPARM_N(h),TPARM_N(i)) -#define TPARM_7(a,b,c,d,e,f,g,h) tparm(a,TPARM_N(b),TPARM_N(c),TPARM_N(d),TPARM_N(e),TPARM_N(f),TPARM_N(g),TPARM_N(h)) -#define TPARM_6(a,b,c,d,e,f,g) tparm(a,TPARM_N(b),TPARM_N(c),TPARM_N(d),TPARM_N(e),TPARM_N(f),TPARM_N(g)) -#define TPARM_5(a,b,c,d,e,f) tparm(a,TPARM_N(b),TPARM_N(c),TPARM_N(d),TPARM_N(e),TPARM_N(f)) -#define TPARM_4(a,b,c,d,e) tparm(a,TPARM_N(b),TPARM_N(c),TPARM_N(d),TPARM_N(e)) -#define TPARM_3(a,b,c,d) tparm(a,TPARM_N(b),TPARM_N(c),TPARM_N(d)) -#define TPARM_2(a,b,c) tparm(a,TPARM_N(b),TPARM_N(c)) -#define TPARM_1(a,b) tparm(a,TPARM_N(b)) -#define TPARM_0(a) tparm(a) -#else -#define TPARM_8(a,b,c,d,e,f,g,h,i) TPARM_9(a,b,c,d,e,f,g,h,i,0) -#define TPARM_7(a,b,c,d,e,f,g,h) TPARM_8(a,b,c,d,e,f,g,h,0) -#define TPARM_6(a,b,c,d,e,f,g) TPARM_7(a,b,c,d,e,f,g,0) -#define TPARM_5(a,b,c,d,e,f) TPARM_6(a,b,c,d,e,f,0) -#define TPARM_4(a,b,c,d,e) TPARM_5(a,b,c,d,e,0) -#define TPARM_3(a,b,c,d) TPARM_4(a,b,c,d,0) -#define TPARM_2(a,b,c) TPARM_3(a,b,c,0) -#define TPARM_1(a,b) TPARM_2(a,b,0) -#define TPARM_1(a,b) TPARM_2(a,b,0) -#define TPARM_0(a) TPARM_1(a,0) -#endif - -#endif /* NC_TPARM_included */ diff --git a/windows/ncurses/include/ncurses/ncurses.h b/windows/ncurses/include/ncurses/ncurses.h deleted file mode 100644 index ff375d525..000000000 --- a/windows/ncurses/include/ncurses/ncurses.h +++ /dev/null @@ -1,1675 +0,0 @@ -/**************************************************************************** - * Copyright (c) 1998-2010,2011 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/**************************************************************************** - * Author: Zeyd M. Ben-Halim 1992,1995 * - * and: Eric S. Raymond * - * and: Thomas E. Dickey 1996-on * - ****************************************************************************/ - -/* $Id: curses.h.in,v 1.220 2011/01/22 19:47:20 tom Exp $ */ - -#ifndef __NCURSES_H -#define __NCURSES_H - -#define CURSES 1 -#define CURSES_H 1 - -/* These are defined only in curses.h, and are used for conditional compiles */ -#define NCURSES_VERSION_MAJOR 5 -#define NCURSES_VERSION_MINOR 9 -#define NCURSES_VERSION_PATCH 20110404 - -/* This is defined in more than one ncurses header, for identification */ -#undef NCURSES_VERSION -#define NCURSES_VERSION "5.9" - -/* - * Identify the mouse encoding version. - */ -#define NCURSES_MOUSE_VERSION 1 - -/* - * Definitions to facilitate DLL's. - */ -#include - -/* - * User-definable tweak to disable the include of . - */ -#ifndef NCURSES_ENABLE_STDBOOL_H -#define NCURSES_ENABLE_STDBOOL_H 1 -#endif - -/* - * NCURSES_ATTR_T is used to quiet compiler warnings when building ncurses - * configured using --disable-macros. - */ -#ifdef NCURSES_NOMACROS -#ifndef NCURSES_ATTR_T -#define NCURSES_ATTR_T attr_t -#endif -#endif /* NCURSES_NOMACROS */ - -#ifndef NCURSES_ATTR_T -#define NCURSES_ATTR_T int -#endif - -/* - * Expands to 'const' if ncurses is configured using --enable-const. Note that - * doing so makes it incompatible with other implementations of X/Open Curses. - */ -#undef NCURSES_CONST -#define NCURSES_CONST /*nothing*/ - -#undef NCURSES_INLINE -#define NCURSES_INLINE inline - -/* - * The internal type used for color values - */ -#undef NCURSES_COLOR_T -#define NCURSES_COLOR_T short - -/* - * Definition used to make WINDOW and similar structs opaque. - */ -#ifndef NCURSES_OPAQUE -#define NCURSES_OPAQUE 0 -#endif - -/* - * The reentrant code relies on the opaque setting, but adds features. - */ -#ifndef NCURSES_REENTRANT -#define NCURSES_REENTRANT 0 -#endif - -/* - * Control whether bindings for interop support are added. - */ -#undef NCURSES_INTEROP_FUNCS -#define NCURSES_INTEROP_FUNCS 0 - -/* - * The internal type used for window dimensions. - */ -#undef NCURSES_SIZE_T -#define NCURSES_SIZE_T short - -/* - * Control whether tparm() supports varargs or fixed-parameter list. - */ -#undef NCURSES_TPARM_VARARGS -#define NCURSES_TPARM_VARARGS 1 - -/* - * NCURSES_CH_T is used in building the library, but not used otherwise in - * this header file, since that would make the normal/wide-character versions - * of the header incompatible. - */ -#undef NCURSES_CH_T -#define NCURSES_CH_T chtype - -#if 0 && defined(_LP64) -typedef unsigned chtype; -typedef unsigned mmask_t; -#else -typedef unsigned long chtype; -typedef unsigned long mmask_t; -#endif - -/* - * We need FILE, etc. Include this before checking any feature symbols. - */ -#include - -/* - * With XPG4, you must define _XOPEN_SOURCE_EXTENDED, it is redundant (or - * conflicting) when _XOPEN_SOURCE is 500 or greater. - */ -#undef NCURSES_WIDECHAR -#if defined(_XOPEN_SOURCE_EXTENDED) || defined(_XPG5) -#define NCURSES_WIDECHAR -#endif - -#include /* we need va_list */ -#ifdef NCURSES_WIDECHAR -#include /* we want wchar_t */ -#endif - -/* X/Open and SVr4 specify that curses implements 'bool'. However, C++ may also - * implement it. If so, we must use the C++ compiler's type to avoid conflict - * with other interfaces. - * - * A further complication is that may declare 'bool' to be a - * different type, such as an enum which is not necessarily compatible with - * C++. If we have , make 'bool' a macro, so users may #undef it. - * Otherwise, let it remain a typedef to avoid conflicts with other #define's. - * In either case, make a typedef for NCURSES_BOOL which can be used if needed - * from either C or C++. - */ - -#undef TRUE -#define TRUE 1 - -#undef FALSE -#define FALSE 0 - -typedef unsigned char NCURSES_BOOL; - -#if defined(__cplusplus) /* __cplusplus, etc. */ - -/* use the C++ compiler's bool type */ -#define NCURSES_BOOL bool - -#else /* c89, c99, etc. */ - -#if NCURSES_ENABLE_STDBOOL_H -#include -/* use whatever the C compiler decides bool really is */ -#define NCURSES_BOOL bool -#else -/* there is no predefined bool - use our own */ -#undef bool -#define bool NCURSES_BOOL -#endif - -#endif /* !__cplusplus, etc. */ - -#ifdef __cplusplus -extern "C" { -#define NCURSES_CAST(type,value) static_cast(value) -#else -#define NCURSES_CAST(type,value) (type)(value) -#endif - -/* - * X/Open attributes. In the ncurses implementation, they are identical to the - * A_ attributes. - */ -#define WA_ATTRIBUTES A_ATTRIBUTES -#define WA_NORMAL A_NORMAL -#define WA_STANDOUT A_STANDOUT -#define WA_UNDERLINE A_UNDERLINE -#define WA_REVERSE A_REVERSE -#define WA_BLINK A_BLINK -#define WA_DIM A_DIM -#define WA_BOLD A_BOLD -#define WA_ALTCHARSET A_ALTCHARSET -#define WA_INVIS A_INVIS -#define WA_PROTECT A_PROTECT -#define WA_HORIZONTAL A_HORIZONTAL -#define WA_LEFT A_LEFT -#define WA_LOW A_LOW -#define WA_RIGHT A_RIGHT -#define WA_TOP A_TOP -#define WA_VERTICAL A_VERTICAL - -/* colors */ -#define COLOR_BLACK 0 -#define COLOR_RED 1 -#define COLOR_GREEN 2 -#define COLOR_YELLOW 3 -#define COLOR_BLUE 4 -#define COLOR_MAGENTA 5 -#define COLOR_CYAN 6 -#define COLOR_WHITE 7 - -/* line graphics */ - -#if 0 || NCURSES_REENTRANT -NCURSES_WRAPPED_VAR(chtype*, acs_map); -#define acs_map NCURSES_PUBLIC_VAR(acs_map()) -#else -extern NCURSES_EXPORT_VAR(chtype) acs_map[]; -#endif - -#define NCURSES_ACS(c) (acs_map[NCURSES_CAST(unsigned char,c)]) - -/* VT100 symbols begin here */ -#define ACS_ULCORNER NCURSES_ACS('l') /* upper left corner */ -#define ACS_LLCORNER NCURSES_ACS('m') /* lower left corner */ -#define ACS_URCORNER NCURSES_ACS('k') /* upper right corner */ -#define ACS_LRCORNER NCURSES_ACS('j') /* lower right corner */ -#define ACS_LTEE NCURSES_ACS('t') /* tee pointing right */ -#define ACS_RTEE NCURSES_ACS('u') /* tee pointing left */ -#define ACS_BTEE NCURSES_ACS('v') /* tee pointing up */ -#define ACS_TTEE NCURSES_ACS('w') /* tee pointing down */ -#define ACS_HLINE NCURSES_ACS('q') /* horizontal line */ -#define ACS_VLINE NCURSES_ACS('x') /* vertical line */ -#define ACS_PLUS NCURSES_ACS('n') /* large plus or crossover */ -#define ACS_S1 NCURSES_ACS('o') /* scan line 1 */ -#define ACS_S9 NCURSES_ACS('s') /* scan line 9 */ -#define ACS_DIAMOND NCURSES_ACS('`') /* diamond */ -#define ACS_CKBOARD NCURSES_ACS('a') /* checker board (stipple) */ -#define ACS_DEGREE NCURSES_ACS('f') /* degree symbol */ -#define ACS_PLMINUS NCURSES_ACS('g') /* plus/minus */ -#define ACS_BULLET NCURSES_ACS('~') /* bullet */ -/* Teletype 5410v1 symbols begin here */ -#define ACS_LARROW NCURSES_ACS(',') /* arrow pointing left */ -#define ACS_RARROW NCURSES_ACS('+') /* arrow pointing right */ -#define ACS_DARROW NCURSES_ACS('.') /* arrow pointing down */ -#define ACS_UARROW NCURSES_ACS('-') /* arrow pointing up */ -#define ACS_BOARD NCURSES_ACS('h') /* board of squares */ -#define ACS_LANTERN NCURSES_ACS('i') /* lantern symbol */ -#define ACS_BLOCK NCURSES_ACS('0') /* solid square block */ -/* - * These aren't documented, but a lot of System Vs have them anyway - * (you can spot pprryyzz{{||}} in a lot of AT&T terminfo strings). - * The ACS_names may not match AT&T's, our source didn't know them. - */ -#define ACS_S3 NCURSES_ACS('p') /* scan line 3 */ -#define ACS_S7 NCURSES_ACS('r') /* scan line 7 */ -#define ACS_LEQUAL NCURSES_ACS('y') /* less/equal */ -#define ACS_GEQUAL NCURSES_ACS('z') /* greater/equal */ -#define ACS_PI NCURSES_ACS('{') /* Pi */ -#define ACS_NEQUAL NCURSES_ACS('|') /* not equal */ -#define ACS_STERLING NCURSES_ACS('}') /* UK pound sign */ - -/* - * Line drawing ACS names are of the form ACS_trbl, where t is the top, r - * is the right, b is the bottom, and l is the left. t, r, b, and l might - * be B (blank), S (single), D (double), or T (thick). The subset defined - * here only uses B and S. - */ -#define ACS_BSSB ACS_ULCORNER -#define ACS_SSBB ACS_LLCORNER -#define ACS_BBSS ACS_URCORNER -#define ACS_SBBS ACS_LRCORNER -#define ACS_SBSS ACS_RTEE -#define ACS_SSSB ACS_LTEE -#define ACS_SSBS ACS_BTEE -#define ACS_BSSS ACS_TTEE -#define ACS_BSBS ACS_HLINE -#define ACS_SBSB ACS_VLINE -#define ACS_SSSS ACS_PLUS - -#undef ERR -#define ERR (-1) - -#undef OK -#define OK (0) - -/* values for the _flags member */ -#define _SUBWIN 0x01 /* is this a sub-window? */ -#define _ENDLINE 0x02 /* is the window flush right? */ -#define _FULLWIN 0x04 /* is the window full-screen? */ -#define _SCROLLWIN 0x08 /* bottom edge is at screen bottom? */ -#define _ISPAD 0x10 /* is this window a pad? */ -#define _HASMOVED 0x20 /* has cursor moved since last refresh? */ -#define _WRAPPED 0x40 /* cursor was just wrappped */ - -/* - * this value is used in the firstchar and lastchar fields to mark - * unchanged lines - */ -#define _NOCHANGE -1 - -/* - * this value is used in the oldindex field to mark lines created by insertions - * and scrolls. - */ -#define _NEWINDEX -1 - -typedef struct screen SCREEN; -typedef struct _win_st WINDOW; - -typedef chtype attr_t; /* ...must be at least as wide as chtype */ - -#ifdef NCURSES_WIDECHAR - -#if 0 -#ifdef mblen /* libutf8.h defines it w/o undefining first */ -#undef mblen -#endif -#include -#endif - -#if 0 -#include /* ...to get mbstate_t, etc. */ -#endif - -#if 0 -typedef unsigned short wchar_t; -#endif - -#if 0 -typedef unsigned int wint_t; -#endif - -/* - * cchar_t stores an array of CCHARW_MAX wide characters. The first is - * normally a spacing character. The others are non-spacing. If those - * (spacing and nonspacing) do not fill the array, a null L'\0' follows. - * Otherwise, a null is assumed to follow when extracting via getcchar(). - */ -#define CCHARW_MAX 5 -typedef struct -{ - attr_t attr; - wchar_t chars[CCHARW_MAX]; -#if 0 -#undef NCURSES_EXT_COLORS -#define NCURSES_EXT_COLORS 20110404 - int ext_color; /* color pair, must be more than 16-bits */ -#endif -} -cchar_t; - -#endif /* NCURSES_WIDECHAR */ - -#if !NCURSES_OPAQUE -struct ldat; - -struct _win_st -{ - NCURSES_SIZE_T _cury, _curx; /* current cursor position */ - - /* window location and size */ - NCURSES_SIZE_T _maxy, _maxx; /* maximums of x and y, NOT window size */ - NCURSES_SIZE_T _begy, _begx; /* screen coords of upper-left-hand corner */ - - short _flags; /* window state flags */ - - /* attribute tracking */ - attr_t _attrs; /* current attribute for non-space character */ - chtype _bkgd; /* current background char/attribute pair */ - - /* option values set by user */ - bool _notimeout; /* no time out on function-key entry? */ - bool _clear; /* consider all data in the window invalid? */ - bool _leaveok; /* OK to not reset cursor on exit? */ - bool _scroll; /* OK to scroll this window? */ - bool _idlok; /* OK to use insert/delete line? */ - bool _idcok; /* OK to use insert/delete char? */ - bool _immed; /* window in immed mode? (not yet used) */ - bool _sync; /* window in sync mode? */ - bool _use_keypad; /* process function keys into KEY_ symbols? */ - int _delay; /* 0 = nodelay, <0 = blocking, >0 = delay */ - - struct ldat *_line; /* the actual line data */ - - /* global screen state */ - NCURSES_SIZE_T _regtop; /* top line of scrolling region */ - NCURSES_SIZE_T _regbottom; /* bottom line of scrolling region */ - - /* these are used only if this is a sub-window */ - int _parx; /* x coordinate of this window in parent */ - int _pary; /* y coordinate of this window in parent */ - WINDOW *_parent; /* pointer to parent if a sub-window */ - - /* these are used only if this is a pad */ - struct pdat - { - NCURSES_SIZE_T _pad_y, _pad_x; - NCURSES_SIZE_T _pad_top, _pad_left; - NCURSES_SIZE_T _pad_bottom, _pad_right; - } _pad; - - NCURSES_SIZE_T _yoffset; /* real begy is _begy + _yoffset */ - -#ifdef NCURSES_WIDECHAR - cchar_t _bkgrnd; /* current background char/attribute pair */ -#if 0 - int _color; /* current color-pair for non-space character */ -#endif -#endif -}; -#endif /* NCURSES_OPAQUE */ - -/* - * This is an extension to support events... - */ -#if 1 -#ifdef NCURSES_WGETCH_EVENTS -#if !defined(__BEOS__) || defined(__HAIKU__) - /* Fix _nc_timed_wait() on BEOS... */ -# define NCURSES_EVENT_VERSION 1 -#endif /* !defined(__BEOS__) */ - -/* - * Bits to set in _nc_event.data.flags - */ -# define _NC_EVENT_TIMEOUT_MSEC 1 -# define _NC_EVENT_FILE 2 -# define _NC_EVENT_FILE_READABLE 2 -# if 0 /* Not supported yet... */ -# define _NC_EVENT_FILE_WRITABLE 4 -# define _NC_EVENT_FILE_EXCEPTION 8 -# endif - -typedef struct -{ - int type; - union - { - long timeout_msec; /* _NC_EVENT_TIMEOUT_MSEC */ - struct - { - unsigned int flags; - int fd; - unsigned int result; - } fev; /* _NC_EVENT_FILE */ - } data; -} _nc_event; - -typedef struct -{ - int count; - int result_flags; /* _NC_EVENT_TIMEOUT_MSEC or _NC_EVENT_FILE_READABLE */ - _nc_event *events[1]; -} _nc_eventlist; - -extern NCURSES_EXPORT(int) wgetch_events (WINDOW *, _nc_eventlist *); /* experimental */ -extern NCURSES_EXPORT(int) wgetnstr_events (WINDOW *,char *,int,_nc_eventlist *);/* experimental */ - -#endif /* NCURSES_WGETCH_EVENTS */ -#endif /* NCURSES_EXT_FUNCS */ - -/* - * GCC (and some other compilers) define '__attribute__'; we're using this - * macro to alert the compiler to flag inconsistencies in printf/scanf-like - * function calls. Just in case '__attribute__' isn't defined, make a dummy. - * Old versions of G++ do not accept it anyway, at least not consistently with - * GCC. - */ -#if !(defined(__GNUC__) || defined(__GNUG__) || defined(__attribute__)) -#define __attribute__(p) /* nothing */ -#endif - -/* - * We cannot define these in ncurses_cfg.h, since they require parameters to be - * passed (that is non-portable). If you happen to be using gcc with warnings - * enabled, define - * GCC_PRINTF - * GCC_SCANF - * to improve checking of calls to printw(), etc. - */ -#ifndef GCC_PRINTFLIKE -#if defined(GCC_PRINTF) && !defined(printf) -#define GCC_PRINTFLIKE(fmt,var) __attribute__((format(printf,fmt,var))) -#else -#define GCC_PRINTFLIKE(fmt,var) /*nothing*/ -#endif -#endif - -#ifndef GCC_SCANFLIKE -#if defined(GCC_SCANF) && !defined(scanf) -#define GCC_SCANFLIKE(fmt,var) __attribute__((format(scanf,fmt,var))) -#else -#define GCC_SCANFLIKE(fmt,var) /*nothing*/ -#endif -#endif - -#ifndef GCC_NORETURN -#define GCC_NORETURN /* nothing */ -#endif - -#ifndef GCC_UNUSED -#define GCC_UNUSED /* nothing */ -#endif - -/* - * Curses uses a helper function. Define our type for this to simplify - * extending it for the sp-funcs feature. - */ -typedef int (*NCURSES_OUTC)(int); - -/* - * Function prototypes. This is the complete X/Open Curses list of required - * functions. Those marked `generated' will have sources generated from the - * macro definitions later in this file, in order to satisfy XPG4.2 - * requirements. - */ - -extern NCURSES_EXPORT(int) addch (const chtype); /* generated */ -extern NCURSES_EXPORT(int) addchnstr (const chtype *, int); /* generated */ -extern NCURSES_EXPORT(int) addchstr (const chtype *); /* generated */ -extern NCURSES_EXPORT(int) addnstr (const char *, int); /* generated */ -extern NCURSES_EXPORT(int) addstr (const char *); /* generated */ -extern NCURSES_EXPORT(int) attroff (NCURSES_ATTR_T); /* generated */ -extern NCURSES_EXPORT(int) attron (NCURSES_ATTR_T); /* generated */ -extern NCURSES_EXPORT(int) attrset (NCURSES_ATTR_T); /* generated */ -extern NCURSES_EXPORT(int) attr_get (attr_t *, short *, void *); /* generated */ -extern NCURSES_EXPORT(int) attr_off (attr_t, void *); /* generated */ -extern NCURSES_EXPORT(int) attr_on (attr_t, void *); /* generated */ -extern NCURSES_EXPORT(int) attr_set (attr_t, short, void *); /* generated */ -extern NCURSES_EXPORT(int) baudrate (void); /* implemented */ -extern NCURSES_EXPORT(int) beep (void); /* implemented */ -extern NCURSES_EXPORT(int) bkgd (chtype); /* generated */ -extern NCURSES_EXPORT(void) bkgdset (chtype); /* generated */ -extern NCURSES_EXPORT(int) border (chtype,chtype,chtype,chtype,chtype,chtype,chtype,chtype); /* generated */ -extern NCURSES_EXPORT(int) box (WINDOW *, chtype, chtype); /* generated */ -extern NCURSES_EXPORT(bool) can_change_color (void); /* implemented */ -extern NCURSES_EXPORT(int) cbreak (void); /* implemented */ -extern NCURSES_EXPORT(int) chgat (int, attr_t, short, const void *); /* generated */ -extern NCURSES_EXPORT(int) clear (void); /* generated */ -extern NCURSES_EXPORT(int) clearok (WINDOW *,bool); /* implemented */ -extern NCURSES_EXPORT(int) clrtobot (void); /* generated */ -extern NCURSES_EXPORT(int) clrtoeol (void); /* generated */ -extern NCURSES_EXPORT(int) color_content (short,short*,short*,short*); /* implemented */ -extern NCURSES_EXPORT(int) color_set (short,void*); /* generated */ -extern NCURSES_EXPORT(int) COLOR_PAIR (int); /* generated */ -extern NCURSES_EXPORT(int) copywin (const WINDOW*,WINDOW*,int,int,int,int,int,int,int); /* implemented */ -extern NCURSES_EXPORT(int) curs_set (int); /* implemented */ -extern NCURSES_EXPORT(int) def_prog_mode (void); /* implemented */ -extern NCURSES_EXPORT(int) def_shell_mode (void); /* implemented */ -extern NCURSES_EXPORT(int) delay_output (int); /* implemented */ -extern NCURSES_EXPORT(int) delch (void); /* generated */ -extern NCURSES_EXPORT(void) delscreen (SCREEN *); /* implemented */ -extern NCURSES_EXPORT(int) delwin (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) deleteln (void); /* generated */ -extern NCURSES_EXPORT(WINDOW *) derwin (WINDOW *,int,int,int,int); /* implemented */ -extern NCURSES_EXPORT(int) doupdate (void); /* implemented */ -extern NCURSES_EXPORT(WINDOW *) dupwin (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) echo (void); /* implemented */ -extern NCURSES_EXPORT(int) echochar (const chtype); /* generated */ -extern NCURSES_EXPORT(int) erase (void); /* generated */ -extern NCURSES_EXPORT(int) endwin (void); /* implemented */ -extern NCURSES_EXPORT(char) erasechar (void); /* implemented */ -extern NCURSES_EXPORT(void) filter (void); /* implemented */ -extern NCURSES_EXPORT(int) flash (void); /* implemented */ -extern NCURSES_EXPORT(int) flushinp (void); /* implemented */ -extern NCURSES_EXPORT(chtype) getbkgd (WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) getch (void); /* generated */ -extern NCURSES_EXPORT(int) getnstr (char *, int); /* generated */ -extern NCURSES_EXPORT(int) getstr (char *); /* generated */ -extern NCURSES_EXPORT(WINDOW *) getwin (FILE *); /* implemented */ -extern NCURSES_EXPORT(int) halfdelay (int); /* implemented */ -extern NCURSES_EXPORT(bool) has_colors (void); /* implemented */ -extern NCURSES_EXPORT(bool) has_ic (void); /* implemented */ -extern NCURSES_EXPORT(bool) has_il (void); /* implemented */ -extern NCURSES_EXPORT(int) hline (chtype, int); /* generated */ -extern NCURSES_EXPORT(void) idcok (WINDOW *, bool); /* implemented */ -extern NCURSES_EXPORT(int) idlok (WINDOW *, bool); /* implemented */ -extern NCURSES_EXPORT(void) immedok (WINDOW *, bool); /* implemented */ -extern NCURSES_EXPORT(chtype) inch (void); /* generated */ -extern NCURSES_EXPORT(int) inchnstr (chtype *, int); /* generated */ -extern NCURSES_EXPORT(int) inchstr (chtype *); /* generated */ -extern NCURSES_EXPORT(WINDOW *) initscr (void); /* implemented */ -extern NCURSES_EXPORT(int) init_color (short,short,short,short); /* implemented */ -extern NCURSES_EXPORT(int) init_pair (short,short,short); /* implemented */ -extern NCURSES_EXPORT(int) innstr (char *, int); /* generated */ -extern NCURSES_EXPORT(int) insch (chtype); /* generated */ -extern NCURSES_EXPORT(int) insdelln (int); /* generated */ -extern NCURSES_EXPORT(int) insertln (void); /* generated */ -extern NCURSES_EXPORT(int) insnstr (const char *, int); /* generated */ -extern NCURSES_EXPORT(int) insstr (const char *); /* generated */ -extern NCURSES_EXPORT(int) instr (char *); /* generated */ -extern NCURSES_EXPORT(int) intrflush (WINDOW *,bool); /* implemented */ -extern NCURSES_EXPORT(bool) isendwin (void); /* implemented */ -extern NCURSES_EXPORT(bool) is_linetouched (WINDOW *,int); /* implemented */ -extern NCURSES_EXPORT(bool) is_wintouched (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(NCURSES_CONST char *) keyname (int); /* implemented */ -extern NCURSES_EXPORT(int) keypad (WINDOW *,bool); /* implemented */ -extern NCURSES_EXPORT(char) killchar (void); /* implemented */ -extern NCURSES_EXPORT(int) leaveok (WINDOW *,bool); /* implemented */ -extern NCURSES_EXPORT(char *) longname (void); /* implemented */ -extern NCURSES_EXPORT(int) meta (WINDOW *,bool); /* implemented */ -extern NCURSES_EXPORT(int) move (int, int); /* generated */ -extern NCURSES_EXPORT(int) mvaddch (int, int, const chtype); /* generated */ -extern NCURSES_EXPORT(int) mvaddchnstr (int, int, const chtype *, int); /* generated */ -extern NCURSES_EXPORT(int) mvaddchstr (int, int, const chtype *); /* generated */ -extern NCURSES_EXPORT(int) mvaddnstr (int, int, const char *, int); /* generated */ -extern NCURSES_EXPORT(int) mvaddstr (int, int, const char *); /* generated */ -extern NCURSES_EXPORT(int) mvchgat (int, int, int, attr_t, short, const void *); /* generated */ -extern NCURSES_EXPORT(int) mvcur (int,int,int,int); /* implemented */ -extern NCURSES_EXPORT(int) mvdelch (int, int); /* generated */ -extern NCURSES_EXPORT(int) mvderwin (WINDOW *, int, int); /* implemented */ -extern NCURSES_EXPORT(int) mvgetch (int, int); /* generated */ -extern NCURSES_EXPORT(int) mvgetnstr (int, int, char *, int); /* generated */ -extern NCURSES_EXPORT(int) mvgetstr (int, int, char *); /* generated */ -extern NCURSES_EXPORT(int) mvhline (int, int, chtype, int); /* generated */ -extern NCURSES_EXPORT(chtype) mvinch (int, int); /* generated */ -extern NCURSES_EXPORT(int) mvinchnstr (int, int, chtype *, int); /* generated */ -extern NCURSES_EXPORT(int) mvinchstr (int, int, chtype *); /* generated */ -extern NCURSES_EXPORT(int) mvinnstr (int, int, char *, int); /* generated */ -extern NCURSES_EXPORT(int) mvinsch (int, int, chtype); /* generated */ -extern NCURSES_EXPORT(int) mvinsnstr (int, int, const char *, int); /* generated */ -extern NCURSES_EXPORT(int) mvinsstr (int, int, const char *); /* generated */ -extern NCURSES_EXPORT(int) mvinstr (int, int, char *); /* generated */ -extern NCURSES_EXPORT(int) mvprintw (int,int, const char *,...) /* implemented */ - GCC_PRINTFLIKE(3,4); -extern NCURSES_EXPORT(int) mvscanw (int,int, NCURSES_CONST char *,...) /* implemented */ - GCC_SCANFLIKE(3,4); -extern NCURSES_EXPORT(int) mvvline (int, int, chtype, int); /* generated */ -extern NCURSES_EXPORT(int) mvwaddch (WINDOW *, int, int, const chtype); /* generated */ -extern NCURSES_EXPORT(int) mvwaddchnstr (WINDOW *, int, int, const chtype *, int);/* generated */ -extern NCURSES_EXPORT(int) mvwaddchstr (WINDOW *, int, int, const chtype *); /* generated */ -extern NCURSES_EXPORT(int) mvwaddnstr (WINDOW *, int, int, const char *, int); /* generated */ -extern NCURSES_EXPORT(int) mvwaddstr (WINDOW *, int, int, const char *); /* generated */ -extern NCURSES_EXPORT(int) mvwchgat (WINDOW *, int, int, int, attr_t, short, const void *);/* generated */ -extern NCURSES_EXPORT(int) mvwdelch (WINDOW *, int, int); /* generated */ -extern NCURSES_EXPORT(int) mvwgetch (WINDOW *, int, int); /* generated */ -extern NCURSES_EXPORT(int) mvwgetnstr (WINDOW *, int, int, char *, int); /* generated */ -extern NCURSES_EXPORT(int) mvwgetstr (WINDOW *, int, int, char *); /* generated */ -extern NCURSES_EXPORT(int) mvwhline (WINDOW *, int, int, chtype, int); /* generated */ -extern NCURSES_EXPORT(int) mvwin (WINDOW *,int,int); /* implemented */ -extern NCURSES_EXPORT(chtype) mvwinch (WINDOW *, int, int); /* generated */ -extern NCURSES_EXPORT(int) mvwinchnstr (WINDOW *, int, int, chtype *, int); /* generated */ -extern NCURSES_EXPORT(int) mvwinchstr (WINDOW *, int, int, chtype *); /* generated */ -extern NCURSES_EXPORT(int) mvwinnstr (WINDOW *, int, int, char *, int); /* generated */ -extern NCURSES_EXPORT(int) mvwinsch (WINDOW *, int, int, chtype); /* generated */ -extern NCURSES_EXPORT(int) mvwinsnstr (WINDOW *, int, int, const char *, int); /* generated */ -extern NCURSES_EXPORT(int) mvwinsstr (WINDOW *, int, int, const char *); /* generated */ -extern NCURSES_EXPORT(int) mvwinstr (WINDOW *, int, int, char *); /* generated */ -extern NCURSES_EXPORT(int) mvwprintw (WINDOW*,int,int, const char *,...) /* implemented */ - GCC_PRINTFLIKE(4,5); -extern NCURSES_EXPORT(int) mvwscanw (WINDOW *,int,int, NCURSES_CONST char *,...) /* implemented */ - GCC_SCANFLIKE(4,5); -extern NCURSES_EXPORT(int) mvwvline (WINDOW *,int, int, chtype, int); /* generated */ -extern NCURSES_EXPORT(int) napms (int); /* implemented */ -extern NCURSES_EXPORT(WINDOW *) newpad (int,int); /* implemented */ -extern NCURSES_EXPORT(SCREEN *) newterm (NCURSES_CONST char *,FILE *,FILE *); /* implemented */ -extern NCURSES_EXPORT(WINDOW *) newwin (int,int,int,int); /* implemented */ -extern NCURSES_EXPORT(int) nl (void); /* implemented */ -extern NCURSES_EXPORT(int) nocbreak (void); /* implemented */ -extern NCURSES_EXPORT(int) nodelay (WINDOW *,bool); /* implemented */ -extern NCURSES_EXPORT(int) noecho (void); /* implemented */ -extern NCURSES_EXPORT(int) nonl (void); /* implemented */ -extern NCURSES_EXPORT(void) noqiflush (void); /* implemented */ -extern NCURSES_EXPORT(int) noraw (void); /* implemented */ -extern NCURSES_EXPORT(int) notimeout (WINDOW *,bool); /* implemented */ -extern NCURSES_EXPORT(int) overlay (const WINDOW*,WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) overwrite (const WINDOW*,WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) pair_content (short,short*,short*); /* implemented */ -extern NCURSES_EXPORT(int) PAIR_NUMBER (int); /* generated */ -extern NCURSES_EXPORT(int) pechochar (WINDOW *, const chtype); /* implemented */ -extern NCURSES_EXPORT(int) pnoutrefresh (WINDOW*,int,int,int,int,int,int);/* implemented */ -extern NCURSES_EXPORT(int) prefresh (WINDOW *,int,int,int,int,int,int); /* implemented */ -extern NCURSES_EXPORT(int) printw (const char *,...) /* implemented */ - GCC_PRINTFLIKE(1,2); -extern NCURSES_EXPORT(int) putwin (WINDOW *, FILE *); /* implemented */ -extern NCURSES_EXPORT(void) qiflush (void); /* implemented */ -extern NCURSES_EXPORT(int) raw (void); /* implemented */ -extern NCURSES_EXPORT(int) redrawwin (WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) refresh (void); /* generated */ -extern NCURSES_EXPORT(int) resetty (void); /* implemented */ -extern NCURSES_EXPORT(int) reset_prog_mode (void); /* implemented */ -extern NCURSES_EXPORT(int) reset_shell_mode (void); /* implemented */ -extern NCURSES_EXPORT(int) ripoffline (int, int (*)(WINDOW *, int)); /* implemented */ -extern NCURSES_EXPORT(int) savetty (void); /* implemented */ -extern NCURSES_EXPORT(int) scanw (NCURSES_CONST char *,...) /* implemented */ - GCC_SCANFLIKE(1,2); -extern NCURSES_EXPORT(int) scr_dump (const char *); /* implemented */ -extern NCURSES_EXPORT(int) scr_init (const char *); /* implemented */ -extern NCURSES_EXPORT(int) scrl (int); /* generated */ -extern NCURSES_EXPORT(int) scroll (WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) scrollok (WINDOW *,bool); /* implemented */ -extern NCURSES_EXPORT(int) scr_restore (const char *); /* implemented */ -extern NCURSES_EXPORT(int) scr_set (const char *); /* implemented */ -extern NCURSES_EXPORT(int) setscrreg (int,int); /* generated */ -extern NCURSES_EXPORT(SCREEN *) set_term (SCREEN *); /* implemented */ -extern NCURSES_EXPORT(int) slk_attroff (const chtype); /* implemented */ -extern NCURSES_EXPORT(int) slk_attr_off (const attr_t, void *); /* generated:WIDEC */ -extern NCURSES_EXPORT(int) slk_attron (const chtype); /* implemented */ -extern NCURSES_EXPORT(int) slk_attr_on (attr_t,void*); /* generated:WIDEC */ -extern NCURSES_EXPORT(int) slk_attrset (const chtype); /* implemented */ -extern NCURSES_EXPORT(attr_t) slk_attr (void); /* implemented */ -extern NCURSES_EXPORT(int) slk_attr_set (const attr_t,short,void*); /* implemented */ -extern NCURSES_EXPORT(int) slk_clear (void); /* implemented */ -extern NCURSES_EXPORT(int) slk_color (short); /* implemented */ -extern NCURSES_EXPORT(int) slk_init (int); /* implemented */ -extern NCURSES_EXPORT(char *) slk_label (int); /* implemented */ -extern NCURSES_EXPORT(int) slk_noutrefresh (void); /* implemented */ -extern NCURSES_EXPORT(int) slk_refresh (void); /* implemented */ -extern NCURSES_EXPORT(int) slk_restore (void); /* implemented */ -extern NCURSES_EXPORT(int) slk_set (int,const char *,int); /* implemented */ -extern NCURSES_EXPORT(int) slk_touch (void); /* implemented */ -extern NCURSES_EXPORT(int) standout (void); /* generated */ -extern NCURSES_EXPORT(int) standend (void); /* generated */ -extern NCURSES_EXPORT(int) start_color (void); /* implemented */ -extern NCURSES_EXPORT(WINDOW *) subpad (WINDOW *, int, int, int, int); /* implemented */ -extern NCURSES_EXPORT(WINDOW *) subwin (WINDOW *, int, int, int, int); /* implemented */ -extern NCURSES_EXPORT(int) syncok (WINDOW *, bool); /* implemented */ -extern NCURSES_EXPORT(chtype) termattrs (void); /* implemented */ -extern NCURSES_EXPORT(char *) termname (void); /* implemented */ -extern NCURSES_EXPORT(void) timeout (int); /* generated */ -extern NCURSES_EXPORT(int) touchline (WINDOW *, int, int); /* generated */ -extern NCURSES_EXPORT(int) touchwin (WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) typeahead (int); /* implemented */ -extern NCURSES_EXPORT(int) ungetch (int); /* implemented */ -extern NCURSES_EXPORT(int) untouchwin (WINDOW *); /* generated */ -extern NCURSES_EXPORT(void) use_env (bool); /* implemented */ -extern NCURSES_EXPORT(int) vidattr (chtype); /* implemented */ -extern NCURSES_EXPORT(int) vidputs (chtype, NCURSES_OUTC); /* implemented */ -extern NCURSES_EXPORT(int) vline (chtype, int); /* generated */ -extern NCURSES_EXPORT(int) vwprintw (WINDOW *, const char *,va_list); /* implemented */ -extern NCURSES_EXPORT(int) vw_printw (WINDOW *, const char *,va_list); /* generated */ -extern NCURSES_EXPORT(int) vwscanw (WINDOW *, NCURSES_CONST char *,va_list); /* implemented */ -extern NCURSES_EXPORT(int) vw_scanw (WINDOW *, NCURSES_CONST char *,va_list); /* generated */ -extern NCURSES_EXPORT(int) waddch (WINDOW *, const chtype); /* implemented */ -extern NCURSES_EXPORT(int) waddchnstr (WINDOW *,const chtype *,int); /* implemented */ -extern NCURSES_EXPORT(int) waddchstr (WINDOW *,const chtype *); /* generated */ -extern NCURSES_EXPORT(int) waddnstr (WINDOW *,const char *,int); /* implemented */ -extern NCURSES_EXPORT(int) waddstr (WINDOW *,const char *); /* generated */ -extern NCURSES_EXPORT(int) wattron (WINDOW *, int); /* generated */ -extern NCURSES_EXPORT(int) wattroff (WINDOW *, int); /* generated */ -extern NCURSES_EXPORT(int) wattrset (WINDOW *, int); /* generated */ -extern NCURSES_EXPORT(int) wattr_get (WINDOW *, attr_t *, short *, void *); /* generated */ -extern NCURSES_EXPORT(int) wattr_on (WINDOW *, attr_t, void *); /* implemented */ -extern NCURSES_EXPORT(int) wattr_off (WINDOW *, attr_t, void *); /* implemented */ -extern NCURSES_EXPORT(int) wattr_set (WINDOW *, attr_t, short, void *); /* generated */ -extern NCURSES_EXPORT(int) wbkgd (WINDOW *, chtype); /* implemented */ -extern NCURSES_EXPORT(void) wbkgdset (WINDOW *,chtype); /* implemented */ -extern NCURSES_EXPORT(int) wborder (WINDOW *,chtype,chtype,chtype,chtype,chtype,chtype,chtype,chtype); /* implemented */ -extern NCURSES_EXPORT(int) wchgat (WINDOW *, int, attr_t, short, const void *);/* implemented */ -extern NCURSES_EXPORT(int) wclear (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) wclrtobot (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) wclrtoeol (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) wcolor_set (WINDOW*,short,void*); /* implemented */ -extern NCURSES_EXPORT(void) wcursyncup (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) wdelch (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) wdeleteln (WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) wechochar (WINDOW *, const chtype); /* implemented */ -extern NCURSES_EXPORT(int) werase (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) wgetch (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) wgetnstr (WINDOW *,char *,int); /* implemented */ -extern NCURSES_EXPORT(int) wgetstr (WINDOW *, char *); /* generated */ -extern NCURSES_EXPORT(int) whline (WINDOW *, chtype, int); /* implemented */ -extern NCURSES_EXPORT(chtype) winch (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) winchnstr (WINDOW *, chtype *, int); /* implemented */ -extern NCURSES_EXPORT(int) winchstr (WINDOW *, chtype *); /* generated */ -extern NCURSES_EXPORT(int) winnstr (WINDOW *, char *, int); /* implemented */ -extern NCURSES_EXPORT(int) winsch (WINDOW *, chtype); /* implemented */ -extern NCURSES_EXPORT(int) winsdelln (WINDOW *,int); /* implemented */ -extern NCURSES_EXPORT(int) winsertln (WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) winsnstr (WINDOW *, const char *,int); /* implemented */ -extern NCURSES_EXPORT(int) winsstr (WINDOW *, const char *); /* generated */ -extern NCURSES_EXPORT(int) winstr (WINDOW *, char *); /* generated */ -extern NCURSES_EXPORT(int) wmove (WINDOW *,int,int); /* implemented */ -extern NCURSES_EXPORT(int) wnoutrefresh (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) wprintw (WINDOW *, const char *,...) /* implemented */ - GCC_PRINTFLIKE(2,3); -extern NCURSES_EXPORT(int) wredrawln (WINDOW *,int,int); /* implemented */ -extern NCURSES_EXPORT(int) wrefresh (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) wscanw (WINDOW *, NCURSES_CONST char *,...) /* implemented */ - GCC_SCANFLIKE(2,3); -extern NCURSES_EXPORT(int) wscrl (WINDOW *,int); /* implemented */ -extern NCURSES_EXPORT(int) wsetscrreg (WINDOW *,int,int); /* implemented */ -extern NCURSES_EXPORT(int) wstandout (WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) wstandend (WINDOW *); /* generated */ -extern NCURSES_EXPORT(void) wsyncdown (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(void) wsyncup (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(void) wtimeout (WINDOW *,int); /* implemented */ -extern NCURSES_EXPORT(int) wtouchln (WINDOW *,int,int,int); /* implemented */ -extern NCURSES_EXPORT(int) wvline (WINDOW *,chtype,int); /* implemented */ - -/* - * These are also declared in : - */ -extern NCURSES_EXPORT(int) tigetflag (NCURSES_CONST char *); /* implemented */ -extern NCURSES_EXPORT(int) tigetnum (NCURSES_CONST char *); /* implemented */ -extern NCURSES_EXPORT(char *) tigetstr (NCURSES_CONST char *); /* implemented */ -extern NCURSES_EXPORT(int) putp (const char *); /* implemented */ - -#if NCURSES_TPARM_VARARGS -extern NCURSES_EXPORT(char *) tparm (NCURSES_CONST char *, ...); /* special */ -#else -extern NCURSES_EXPORT(char *) tparm (NCURSES_CONST char *, long,long,long,long,long,long,long,long,long); /* special */ -extern NCURSES_EXPORT(char *) tparm_varargs (NCURSES_CONST char *, ...); /* special */ -#endif - -extern NCURSES_EXPORT(char *) tiparm (const char *, ...); /* special */ - -/* - * These functions are not in X/Open, but we use them in macro definitions: - */ -extern NCURSES_EXPORT(int) getattrs (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) getcurx (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) getcury (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) getbegx (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) getbegy (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) getmaxx (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) getmaxy (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) getparx (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) getpary (const WINDOW *); /* generated */ - -/* - * vid_attr() was implemented originally based on a draft of X/Open curses. - */ -#ifndef NCURSES_WIDECHAR -#define vid_attr(a,pair,opts) vidattr(a) -#endif - -/* - * These functions are extensions - not in X/Open Curses. - */ -#if 1 -#undef NCURSES_EXT_FUNCS -#define NCURSES_EXT_FUNCS 20110404 -typedef int (*NCURSES_WINDOW_CB)(WINDOW *, void *); -typedef int (*NCURSES_SCREEN_CB)(SCREEN *, void *); -extern NCURSES_EXPORT(bool) is_term_resized (int, int); -extern NCURSES_EXPORT(char *) keybound (int, int); -extern NCURSES_EXPORT(const char *) curses_version (void); -extern NCURSES_EXPORT(int) assume_default_colors (int, int); -extern NCURSES_EXPORT(int) define_key (const char *, int); -extern NCURSES_EXPORT(int) get_escdelay (void); -extern NCURSES_EXPORT(int) key_defined (const char *); -extern NCURSES_EXPORT(int) keyok (int, bool); -extern NCURSES_EXPORT(int) resize_term (int, int); -extern NCURSES_EXPORT(int) resizeterm (int, int); -extern NCURSES_EXPORT(int) set_escdelay (int); -extern NCURSES_EXPORT(int) set_tabsize (int); -extern NCURSES_EXPORT(int) use_default_colors (void); -extern NCURSES_EXPORT(int) use_extended_names (bool); -extern NCURSES_EXPORT(int) use_legacy_coding (int); -extern NCURSES_EXPORT(int) use_screen (SCREEN *, NCURSES_SCREEN_CB, void *); -extern NCURSES_EXPORT(int) use_window (WINDOW *, NCURSES_WINDOW_CB, void *); -extern NCURSES_EXPORT(int) wresize (WINDOW *, int, int); -extern NCURSES_EXPORT(void) nofilter(void); - -/* - * These extensions provide access to information stored in the WINDOW even - * when NCURSES_OPAQUE is set: - */ -extern NCURSES_EXPORT(WINDOW *) wgetparent (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(bool) is_cleared (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(bool) is_idcok (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(bool) is_idlok (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(bool) is_immedok (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(bool) is_keypad (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(bool) is_leaveok (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(bool) is_nodelay (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(bool) is_notimeout (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(bool) is_pad (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(bool) is_scrollok (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(bool) is_subwin (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(bool) is_syncok (const WINDOW *); /* generated */ -extern NCURSES_EXPORT(int) wgetscrreg (const WINDOW *, int *, int *); /* generated */ - -#else -#define curses_version() NCURSES_VERSION -#endif - -/* - * Extra extension-functions, which pass a SCREEN pointer rather than using - * a global variable SP. - */ -#if 1 -#undef NCURSES_SP_FUNCS -#define NCURSES_SP_FUNCS 20110404 -#define NCURSES_SP_NAME(name) name##_sp - -/* Define the sp-funcs helper function */ -#define NCURSES_SP_OUTC NCURSES_SP_NAME(NCURSES_OUTC) -typedef int (*NCURSES_SP_OUTC)(SCREEN*, int); - -extern NCURSES_EXPORT(SCREEN *) new_prescr (void); /* implemented:SP_FUNC */ - -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(baudrate) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(beep) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(bool) NCURSES_SP_NAME(can_change_color) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(cbreak) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(curs_set) (SCREEN*, int); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(color_content) (SCREEN*, short, short*, short*, short*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(def_prog_mode) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(def_shell_mode) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(delay_output) (SCREEN*, int); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(doupdate) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(echo) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(endwin) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(char) NCURSES_SP_NAME(erasechar) (SCREEN*);/* implemented:SP_FUNC */ -extern NCURSES_EXPORT(void) NCURSES_SP_NAME(filter) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(flash) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(flushinp) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(WINDOW *) NCURSES_SP_NAME(getwin) (SCREEN*, FILE *); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(halfdelay) (SCREEN*, int); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(bool) NCURSES_SP_NAME(has_colors) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(bool) NCURSES_SP_NAME(has_ic) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(bool) NCURSES_SP_NAME(has_il) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(init_color) (SCREEN*, short, short, short, short); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(init_pair) (SCREEN*, short, short, short); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(intrflush) (SCREEN*, WINDOW*, bool); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(bool) NCURSES_SP_NAME(isendwin) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(NCURSES_CONST char *) NCURSES_SP_NAME(keyname) (SCREEN*, int); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(char) NCURSES_SP_NAME(killchar) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(longname) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(mvcur) (SCREEN*, int, int, int, int); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(napms) (SCREEN*, int); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(WINDOW *) NCURSES_SP_NAME(newpad) (SCREEN*, int, int); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(SCREEN *) NCURSES_SP_NAME(newterm) (SCREEN*, NCURSES_CONST char *, FILE *, FILE *); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(WINDOW *) NCURSES_SP_NAME(newwin) (SCREEN*, int, int, int, int); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(nl) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(nocbreak) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(noecho) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(nonl) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(void) NCURSES_SP_NAME(noqiflush) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(noraw) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(pair_content) (SCREEN*, short, short*, short*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(void) NCURSES_SP_NAME(qiflush) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(raw) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(reset_prog_mode) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(reset_shell_mode) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(resetty) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(ripoffline) (SCREEN*, int, int (*)(WINDOW *, int)); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(savetty) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(scr_init) (SCREEN*, const char *); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(scr_restore) (SCREEN*, const char *); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(scr_set) (SCREEN*, const char *); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_attroff) (SCREEN*, const chtype); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_attron) (SCREEN*, const chtype); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_attrset) (SCREEN*, const chtype); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(attr_t) NCURSES_SP_NAME(slk_attr) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_attr_set) (SCREEN*, const attr_t, short, void*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_clear) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_color) (SCREEN*, short); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_init) (SCREEN*, int); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(slk_label) (SCREEN*, int); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_noutrefresh) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_refresh) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_restore) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_set) (SCREEN*, int, const char *, int); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_touch) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(start_color) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(chtype) NCURSES_SP_NAME(termattrs) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(termname) (SCREEN*); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(typeahead) (SCREEN*, int); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(ungetch) (SCREEN*, int); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(void) NCURSES_SP_NAME(use_env) (SCREEN*, bool); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(vidattr) (SCREEN*, chtype); /* implemented:SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(vidputs) (SCREEN*, chtype, NCURSES_SP_OUTC); /* implemented:SP_FUNC */ -#if 1 -extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(keybound) (SCREEN*, int, int); /* implemented:EXT_SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(assume_default_colors) (SCREEN*, int, int); /* implemented:EXT_SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(define_key) (SCREEN*, const char *, int); /* implemented:EXT_SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(get_escdelay) (SCREEN*); /* implemented:EXT_SP_FUNC */ -extern NCURSES_EXPORT(bool) NCURSES_SP_NAME(is_term_resized) (SCREEN*, int, int); /* implemented:EXT_SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(key_defined) (SCREEN*, const char *); /* implemented:EXT_SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(keyok) (SCREEN*, int, bool); /* implemented:EXT_SP_FUNC */ -extern NCURSES_EXPORT(void) NCURSES_SP_NAME(nofilter) (SCREEN*); /* implemented */ /* implemented:EXT_SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(resize_term) (SCREEN*, int, int); /* implemented:EXT_SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(resizeterm) (SCREEN*, int, int); /* implemented:EXT_SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(set_escdelay) (SCREEN*, int); /* implemented:EXT_SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(set_tabsize) (SCREEN*, int); /* implemented:EXT_SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(use_default_colors) (SCREEN*); /* implemented:EXT_SP_FUNC */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(use_legacy_coding) (SCREEN*, int); /* implemented:EXT_SP_FUNC */ -#endif -#else -#undef NCURSES_SP_FUNCS -#define NCURSES_SP_FUNCS 0 -#define NCURSES_SP_NAME(name) name -#define NCURSES_SP_OUTC NCURSES_OUTC -#endif - -/* attributes */ - -#define NCURSES_ATTR_SHIFT 8 -#define NCURSES_BITS(mask,shift) ((mask) << ((shift) + NCURSES_ATTR_SHIFT)) - -#define A_NORMAL (1UL - 1UL) -#define A_ATTRIBUTES NCURSES_BITS(~(1UL - 1UL),0) -#define A_CHARTEXT (NCURSES_BITS(1UL,0) - 1UL) -#define A_COLOR NCURSES_BITS(((1UL) << 8) - 1UL,0) -#define A_STANDOUT NCURSES_BITS(1UL,8) -#define A_UNDERLINE NCURSES_BITS(1UL,9) -#define A_REVERSE NCURSES_BITS(1UL,10) -#define A_BLINK NCURSES_BITS(1UL,11) -#define A_DIM NCURSES_BITS(1UL,12) -#define A_BOLD NCURSES_BITS(1UL,13) -#define A_ALTCHARSET NCURSES_BITS(1UL,14) -#define A_INVIS NCURSES_BITS(1UL,15) -#define A_PROTECT NCURSES_BITS(1UL,16) -#define A_HORIZONTAL NCURSES_BITS(1UL,17) -#define A_LEFT NCURSES_BITS(1UL,18) -#define A_LOW NCURSES_BITS(1UL,19) -#define A_RIGHT NCURSES_BITS(1UL,20) -#define A_TOP NCURSES_BITS(1UL,21) -#define A_VERTICAL NCURSES_BITS(1UL,22) - -/* - * Most of the pseudo functions are macros that either provide compatibility - * with older versions of curses, or provide inline functionality to improve - * performance. - */ - -/* - * These pseudo functions are always implemented as macros: - */ - -#define getyx(win,y,x) (y = getcury(win), x = getcurx(win)) -#define getbegyx(win,y,x) (y = getbegy(win), x = getbegx(win)) -#define getmaxyx(win,y,x) (y = getmaxy(win), x = getmaxx(win)) -#define getparyx(win,y,x) (y = getpary(win), x = getparx(win)) - -#define getsyx(y,x) do { if (newscr) { \ - if (is_leaveok(newscr)) \ - (y) = (x) = -1; \ - else \ - getyx(newscr,(y), (x)); \ - } \ - } while(0) - -#define setsyx(y,x) do { if (newscr) { \ - if ((y) == -1 && (x) == -1) \ - leaveok(newscr, TRUE); \ - else { \ - leaveok(newscr, FALSE); \ - wmove(newscr, (y), (x)); \ - } \ - } \ - } while(0) - -#ifndef NCURSES_NOMACROS - -/* - * These miscellaneous pseudo functions are provided for compatibility: - */ - -#define wgetstr(w, s) wgetnstr(w, s, -1) -#define getnstr(s, n) wgetnstr(stdscr, s, n) - -#define setterm(term) setupterm(term, 1, (int *)0) - -#define fixterm() reset_prog_mode() -#define resetterm() reset_shell_mode() -#define saveterm() def_prog_mode() -#define crmode() cbreak() -#define nocrmode() nocbreak() -#define gettmode() - -/* It seems older SYSV curses versions define these */ -#if !NCURSES_OPAQUE -#define getattrs(win) NCURSES_CAST(int, (win) ? (win)->_attrs : A_NORMAL) -#define getcurx(win) ((win) ? (win)->_curx : ERR) -#define getcury(win) ((win) ? (win)->_cury : ERR) -#define getbegx(win) ((win) ? (win)->_begx : ERR) -#define getbegy(win) ((win) ? (win)->_begy : ERR) -#define getmaxx(win) ((win) ? ((win)->_maxx + 1) : ERR) -#define getmaxy(win) ((win) ? ((win)->_maxy + 1) : ERR) -#define getparx(win) ((win) ? (win)->_parx : ERR) -#define getpary(win) ((win) ? (win)->_pary : ERR) -#endif /* NCURSES_OPAQUE */ - -#define wstandout(win) (wattrset(win,A_STANDOUT)) -#define wstandend(win) (wattrset(win,A_NORMAL)) - -#define wattron(win,at) wattr_on(win, NCURSES_CAST(attr_t, at), NULL) -#define wattroff(win,at) wattr_off(win, NCURSES_CAST(attr_t, at), NULL) - -#if !NCURSES_OPAQUE -#if defined(NCURSES_WIDECHAR) && 0 -#define wattrset(win,at) ((win) \ - ? ((win)->_color = PAIR_NUMBER(at), \ - (win)->_attrs = NCURSES_CAST(attr_t, at), \ - OK) \ - : ERR) -#else -#define wattrset(win,at) ((win) \ - ? ((win)->_attrs = NCURSES_CAST(attr_t, at), \ - OK) \ - : ERR) -#endif -#endif /* NCURSES_OPAQUE */ - -#define scroll(win) wscrl(win,1) - -#define touchwin(win) wtouchln((win), 0, getmaxy(win), 1) -#define touchline(win, s, c) wtouchln((win), s, c, 1) -#define untouchwin(win) wtouchln((win), 0, getmaxy(win), 0) - -#define box(win, v, h) wborder(win, v, v, h, h, 0, 0, 0, 0) -#define border(ls, rs, ts, bs, tl, tr, bl, br) wborder(stdscr, ls, rs, ts, bs, tl, tr, bl, br) -#define hline(ch, n) whline(stdscr, ch, n) -#define vline(ch, n) wvline(stdscr, ch, n) - -#define winstr(w, s) winnstr(w, s, -1) -#define winchstr(w, s) winchnstr(w, s, -1) -#define winsstr(w, s) winsnstr(w, s, -1) - -#if !NCURSES_OPAQUE -#define redrawwin(win) wredrawln(win, 0, (win)->_maxy+1) -#endif /* NCURSES_OPAQUE */ - -#define waddstr(win,str) waddnstr(win,str,-1) -#define waddchstr(win,str) waddchnstr(win,str,-1) - -/* - * These apply to the first 256 color pairs. - */ -#define COLOR_PAIR(n) NCURSES_BITS(n, 0) -#define PAIR_NUMBER(a) (NCURSES_CAST(int,((NCURSES_CAST(unsigned long,a) & A_COLOR) >> NCURSES_ATTR_SHIFT))) - -/* - * pseudo functions for standard screen - */ - -#define addch(ch) waddch(stdscr,ch) -#define addchnstr(str,n) waddchnstr(stdscr,str,n) -#define addchstr(str) waddchstr(stdscr,str) -#define addnstr(str,n) waddnstr(stdscr,str,n) -#define addstr(str) waddnstr(stdscr,str,-1) -#define attroff(at) wattroff(stdscr,at) -#define attron(at) wattron(stdscr,at) -#define attrset(at) wattrset(stdscr,at) -#define attr_get(ap,cp,o) wattr_get(stdscr,ap,cp,o) -#define attr_off(a,o) wattr_off(stdscr,a,o) -#define attr_on(a,o) wattr_on(stdscr,a,o) -#define attr_set(a,c,o) wattr_set(stdscr,a,c,o) -#define bkgd(ch) wbkgd(stdscr,ch) -#define bkgdset(ch) wbkgdset(stdscr,ch) -#define chgat(n,a,c,o) wchgat(stdscr,n,a,c,o) -#define clear() wclear(stdscr) -#define clrtobot() wclrtobot(stdscr) -#define clrtoeol() wclrtoeol(stdscr) -#define color_set(c,o) wcolor_set(stdscr,c,o) -#define delch() wdelch(stdscr) -#define deleteln() winsdelln(stdscr,-1) -#define echochar(c) wechochar(stdscr,c) -#define erase() werase(stdscr) -#define getch() wgetch(stdscr) -#define getstr(str) wgetstr(stdscr,str) -#define inch() winch(stdscr) -#define inchnstr(s,n) winchnstr(stdscr,s,n) -#define inchstr(s) winchstr(stdscr,s) -#define innstr(s,n) winnstr(stdscr,s,n) -#define insch(c) winsch(stdscr,c) -#define insdelln(n) winsdelln(stdscr,n) -#define insertln() winsdelln(stdscr,1) -#define insnstr(s,n) winsnstr(stdscr,s,n) -#define insstr(s) winsstr(stdscr,s) -#define instr(s) winstr(stdscr,s) -#define move(y,x) wmove(stdscr,y,x) -#define refresh() wrefresh(stdscr) -#define scrl(n) wscrl(stdscr,n) -#define setscrreg(t,b) wsetscrreg(stdscr,t,b) -#define standend() wstandend(stdscr) -#define standout() wstandout(stdscr) -#define timeout(delay) wtimeout(stdscr,delay) -#define wdeleteln(win) winsdelln(win,-1) -#define winsertln(win) winsdelln(win,1) - -/* - * mv functions - */ - -#define mvwaddch(win,y,x,ch) (wmove(win,y,x) == ERR ? ERR : waddch(win,ch)) -#define mvwaddchnstr(win,y,x,str,n) (wmove(win,y,x) == ERR ? ERR : waddchnstr(win,str,n)) -#define mvwaddchstr(win,y,x,str) (wmove(win,y,x) == ERR ? ERR : waddchnstr(win,str,-1)) -#define mvwaddnstr(win,y,x,str,n) (wmove(win,y,x) == ERR ? ERR : waddnstr(win,str,n)) -#define mvwaddstr(win,y,x,str) (wmove(win,y,x) == ERR ? ERR : waddnstr(win,str,-1)) -#define mvwdelch(win,y,x) (wmove(win,y,x) == ERR ? ERR : wdelch(win)) -#define mvwchgat(win,y,x,n,a,c,o) (wmove(win,y,x) == ERR ? ERR : wchgat(win,n,a,c,o)) -#define mvwgetch(win,y,x) (wmove(win,y,x) == ERR ? ERR : wgetch(win)) -#define mvwgetnstr(win,y,x,str,n) (wmove(win,y,x) == ERR ? ERR : wgetnstr(win,str,n)) -#define mvwgetstr(win,y,x,str) (wmove(win,y,x) == ERR ? ERR : wgetstr(win,str)) -#define mvwhline(win,y,x,c,n) (wmove(win,y,x) == ERR ? ERR : whline(win,c,n)) -#define mvwinch(win,y,x) (wmove(win,y,x) == ERR ? NCURSES_CAST(chtype, ERR) : winch(win)) -#define mvwinchnstr(win,y,x,s,n) (wmove(win,y,x) == ERR ? ERR : winchnstr(win,s,n)) -#define mvwinchstr(win,y,x,s) (wmove(win,y,x) == ERR ? ERR : winchstr(win,s)) -#define mvwinnstr(win,y,x,s,n) (wmove(win,y,x) == ERR ? ERR : winnstr(win,s,n)) -#define mvwinsch(win,y,x,c) (wmove(win,y,x) == ERR ? ERR : winsch(win,c)) -#define mvwinsnstr(win,y,x,s,n) (wmove(win,y,x) == ERR ? ERR : winsnstr(win,s,n)) -#define mvwinsstr(win,y,x,s) (wmove(win,y,x) == ERR ? ERR : winsstr(win,s)) -#define mvwinstr(win,y,x,s) (wmove(win,y,x) == ERR ? ERR : winstr(win,s)) -#define mvwvline(win,y,x,c,n) (wmove(win,y,x) == ERR ? ERR : wvline(win,c,n)) - -#define mvaddch(y,x,ch) mvwaddch(stdscr,y,x,ch) -#define mvaddchnstr(y,x,str,n) mvwaddchnstr(stdscr,y,x,str,n) -#define mvaddchstr(y,x,str) mvwaddchstr(stdscr,y,x,str) -#define mvaddnstr(y,x,str,n) mvwaddnstr(stdscr,y,x,str,n) -#define mvaddstr(y,x,str) mvwaddstr(stdscr,y,x,str) -#define mvchgat(y,x,n,a,c,o) mvwchgat(stdscr,y,x,n,a,c,o) -#define mvdelch(y,x) mvwdelch(stdscr,y,x) -#define mvgetch(y,x) mvwgetch(stdscr,y,x) -#define mvgetnstr(y,x,str,n) mvwgetnstr(stdscr,y,x,str,n) -#define mvgetstr(y,x,str) mvwgetstr(stdscr,y,x,str) -#define mvhline(y,x,c,n) mvwhline(stdscr,y,x,c,n) -#define mvinch(y,x) mvwinch(stdscr,y,x) -#define mvinchnstr(y,x,s,n) mvwinchnstr(stdscr,y,x,s,n) -#define mvinchstr(y,x,s) mvwinchstr(stdscr,y,x,s) -#define mvinnstr(y,x,s,n) mvwinnstr(stdscr,y,x,s,n) -#define mvinsch(y,x,c) mvwinsch(stdscr,y,x,c) -#define mvinsnstr(y,x,s,n) mvwinsnstr(stdscr,y,x,s,n) -#define mvinsstr(y,x,s) mvwinsstr(stdscr,y,x,s) -#define mvinstr(y,x,s) mvwinstr(stdscr,y,x,s) -#define mvvline(y,x,c,n) mvwvline(stdscr,y,x,c,n) - -/* - * Some wide-character functions can be implemented without the extensions. - */ -#if !NCURSES_OPAQUE -#define getbkgd(win) ((win)->_bkgd) -#endif /* NCURSES_OPAQUE */ - -#define slk_attr_off(a,v) ((v) ? ERR : slk_attroff(a)) -#define slk_attr_on(a,v) ((v) ? ERR : slk_attron(a)) - -#if !NCURSES_OPAQUE -#if defined(NCURSES_WIDECHAR) && 0 -#define wattr_set(win,a,p,opts) ((win)->_attrs = ((a) & ~A_COLOR), \ - (win)->_color = (p), \ - OK) -#define wattr_get(win,a,p,opts) ((void)((a) != (void *)0 && (*(a) = (win)->_attrs)), \ - (void)((p) != (void *)0 && (*(p) = (short)(win)->_color)), \ - OK) -#else -#define wattr_set(win,a,p,opts) ((win)->_attrs = (((a) & ~A_COLOR) | (attr_t)COLOR_PAIR(p)), OK) -#define wattr_get(win,a,p,opts) ((void)((a) != (void *)0 && (*(a) = (win)->_attrs)), \ - (void)((p) != (void *)0 && (*(p) = (short)PAIR_NUMBER((win)->_attrs))), \ - OK) -#endif -#endif /* NCURSES_OPAQUE */ - -/* - * X/Open curses deprecates SVr4 vwprintw/vwscanw, which are supposed to use - * varargs.h. It adds new calls vw_printw/vw_scanw, which are supposed to - * use POSIX stdarg.h. The ncurses versions of vwprintw/vwscanw already - * use stdarg.h, so... - */ -#define vw_printw vwprintw -#define vw_scanw vwscanw - -/* - * Export fallback function for use in C++ binding. - */ -#if !1 -#define vsscanf(a,b,c) _nc_vsscanf(a,b,c) -NCURSES_EXPORT(int) vsscanf(const char *, const char *, va_list); -#endif - -/* - * These macros are extensions - not in X/Open Curses. - */ -#if 1 -#if !NCURSES_OPAQUE -#define is_cleared(win) ((win) ? (win)->_clear : FALSE) -#define is_idcok(win) ((win) ? (win)->_idcok : FALSE) -#define is_idlok(win) ((win) ? (win)->_idlok : FALSE) -#define is_immedok(win) ((win) ? (win)->_immed : FALSE) -#define is_keypad(win) ((win) ? (win)->_use_keypad : FALSE) -#define is_leaveok(win) ((win) ? (win)->_leaveok : FALSE) -#define is_nodelay(win) ((win) ? ((win)->_delay == 0) : FALSE) -#define is_notimeout(win) ((win) ? (win)->_notimeout : FALSE) -#define is_pad(win) ((win) ? ((win)->_flags & _ISPAD) != 0 : FALSE) -#define is_scrollok(win) ((win) ? (win)->_scroll : FALSE) -#define is_subwin(win) ((win) ? ((win)->_flags & _SUBWIN) != 0 : FALSE) -#define is_syncok(win) ((win) ? (win)->_sync : FALSE) -#define wgetparent(win) ((win) ? (win)->_parent : 0) -#define wgetscrreg(win,t,b) ((win) ? (*(t) = (win)->_regtop, *(b) = (win)->_regbottom, OK) : ERR) -#endif -#endif - -#endif /* NCURSES_NOMACROS */ - -/* - * Public variables. - * - * Notes: - * a. ESCDELAY was an undocumented feature under AIX curses. - * It gives the ESC expire time in milliseconds. - * b. ttytype is needed for backward compatibility - */ -#if NCURSES_REENTRANT - -NCURSES_WRAPPED_VAR(WINDOW *, curscr); -NCURSES_WRAPPED_VAR(WINDOW *, newscr); -NCURSES_WRAPPED_VAR(WINDOW *, stdscr); -NCURSES_WRAPPED_VAR(char *, ttytype); -NCURSES_WRAPPED_VAR(int, COLORS); -NCURSES_WRAPPED_VAR(int, COLOR_PAIRS); -NCURSES_WRAPPED_VAR(int, COLS); -NCURSES_WRAPPED_VAR(int, ESCDELAY); -NCURSES_WRAPPED_VAR(int, LINES); -NCURSES_WRAPPED_VAR(int, TABSIZE); - -#define curscr NCURSES_PUBLIC_VAR(curscr()) -#define newscr NCURSES_PUBLIC_VAR(newscr()) -#define stdscr NCURSES_PUBLIC_VAR(stdscr()) -#define ttytype NCURSES_PUBLIC_VAR(ttytype()) -#define COLORS NCURSES_PUBLIC_VAR(COLORS()) -#define COLOR_PAIRS NCURSES_PUBLIC_VAR(COLOR_PAIRS()) -#define COLS NCURSES_PUBLIC_VAR(COLS()) -#define ESCDELAY NCURSES_PUBLIC_VAR(ESCDELAY()) -#define LINES NCURSES_PUBLIC_VAR(LINES()) -#define TABSIZE NCURSES_PUBLIC_VAR(TABSIZE()) - -#else - -extern NCURSES_EXPORT_VAR(WINDOW *) curscr; -extern NCURSES_EXPORT_VAR(WINDOW *) newscr; -extern NCURSES_EXPORT_VAR(WINDOW *) stdscr; -extern NCURSES_EXPORT_VAR(char) ttytype[]; -extern NCURSES_EXPORT_VAR(int) COLORS; -extern NCURSES_EXPORT_VAR(int) COLOR_PAIRS; -extern NCURSES_EXPORT_VAR(int) COLS; -extern NCURSES_EXPORT_VAR(int) ESCDELAY; -extern NCURSES_EXPORT_VAR(int) LINES; -extern NCURSES_EXPORT_VAR(int) TABSIZE; - -#endif - -/* - * Pseudo-character tokens outside ASCII range. The curses wgetch() function - * will return any given one of these only if the corresponding k- capability - * is defined in your terminal's terminfo entry. - * - * Some keys (KEY_A1, etc) are arranged like this: - * a1 up a3 - * left b2 right - * c1 down c3 - * - * A few key codes do not depend upon the terminfo entry. - */ -#define KEY_CODE_YES 0400 /* A wchar_t contains a key code */ -#define KEY_MIN 0401 /* Minimum curses key */ -#define KEY_BREAK 0401 /* Break key (unreliable) */ -#define KEY_SRESET 0530 /* Soft (partial) reset (unreliable) */ -#define KEY_RESET 0531 /* Reset or hard reset (unreliable) */ -/* - * These definitions were generated by ./MKkey_defs.sh ./Caps - */ -#define KEY_DOWN 0402 /* down-arrow key */ -#define KEY_UP 0403 /* up-arrow key */ -#define KEY_LEFT 0404 /* left-arrow key */ -#define KEY_RIGHT 0405 /* right-arrow key */ -#define KEY_HOME 0406 /* home key */ -#define KEY_BACKSPACE 0407 /* backspace key */ -#define KEY_F0 0410 /* Function keys. Space for 64 */ -#define KEY_F(n) (KEY_F0+(n)) /* Value of function key n */ -#define KEY_DL 0510 /* delete-line key */ -#define KEY_IL 0511 /* insert-line key */ -#define KEY_DC 0512 /* delete-character key */ -#define KEY_IC 0513 /* insert-character key */ -#define KEY_EIC 0514 /* sent by rmir or smir in insert mode */ -#define KEY_CLEAR 0515 /* clear-screen or erase key */ -#define KEY_EOS 0516 /* clear-to-end-of-screen key */ -#define KEY_EOL 0517 /* clear-to-end-of-line key */ -#define KEY_SF 0520 /* scroll-forward key */ -#define KEY_SR 0521 /* scroll-backward key */ -#define KEY_NPAGE 0522 /* next-page key */ -#define KEY_PPAGE 0523 /* previous-page key */ -#define KEY_STAB 0524 /* set-tab key */ -#define KEY_CTAB 0525 /* clear-tab key */ -#define KEY_CATAB 0526 /* clear-all-tabs key */ -#define KEY_ENTER 0527 /* enter/send key */ -#define KEY_PRINT 0532 /* print key */ -#define KEY_LL 0533 /* lower-left key (home down) */ -#define KEY_A1 0534 /* upper left of keypad */ -#define KEY_A3 0535 /* upper right of keypad */ -#define KEY_B2 0536 /* center of keypad */ -#define KEY_C1 0537 /* lower left of keypad */ -#define KEY_C3 0540 /* lower right of keypad */ -#define KEY_BTAB 0541 /* back-tab key */ -#define KEY_BEG 0542 /* begin key */ -#define KEY_CANCEL 0543 /* cancel key */ -#define KEY_CLOSE 0544 /* close key */ -#define KEY_COMMAND 0545 /* command key */ -#define KEY_COPY 0546 /* copy key */ -#define KEY_CREATE 0547 /* create key */ -#define KEY_END 0550 /* end key */ -#define KEY_EXIT 0551 /* exit key */ -#define KEY_FIND 0552 /* find key */ -#define KEY_HELP 0553 /* help key */ -#define KEY_MARK 0554 /* mark key */ -#define KEY_MESSAGE 0555 /* message key */ -#define KEY_MOVE 0556 /* move key */ -#define KEY_NEXT 0557 /* next key */ -#define KEY_OPEN 0560 /* open key */ -#define KEY_OPTIONS 0561 /* options key */ -#define KEY_PREVIOUS 0562 /* previous key */ -#define KEY_REDO 0563 /* redo key */ -#define KEY_REFERENCE 0564 /* reference key */ -#define KEY_REFRESH 0565 /* refresh key */ -#define KEY_REPLACE 0566 /* replace key */ -#define KEY_RESTART 0567 /* restart key */ -#define KEY_RESUME 0570 /* resume key */ -#define KEY_SAVE 0571 /* save key */ -#define KEY_SBEG 0572 /* shifted begin key */ -#define KEY_SCANCEL 0573 /* shifted cancel key */ -#define KEY_SCOMMAND 0574 /* shifted command key */ -#define KEY_SCOPY 0575 /* shifted copy key */ -#define KEY_SCREATE 0576 /* shifted create key */ -#define KEY_SDC 0577 /* shifted delete-character key */ -#define KEY_SDL 0600 /* shifted delete-line key */ -#define KEY_SELECT 0601 /* select key */ -#define KEY_SEND 0602 /* shifted end key */ -#define KEY_SEOL 0603 /* shifted clear-to-end-of-line key */ -#define KEY_SEXIT 0604 /* shifted exit key */ -#define KEY_SFIND 0605 /* shifted find key */ -#define KEY_SHELP 0606 /* shifted help key */ -#define KEY_SHOME 0607 /* shifted home key */ -#define KEY_SIC 0610 /* shifted insert-character key */ -#define KEY_SLEFT 0611 /* shifted left-arrow key */ -#define KEY_SMESSAGE 0612 /* shifted message key */ -#define KEY_SMOVE 0613 /* shifted move key */ -#define KEY_SNEXT 0614 /* shifted next key */ -#define KEY_SOPTIONS 0615 /* shifted options key */ -#define KEY_SPREVIOUS 0616 /* shifted previous key */ -#define KEY_SPRINT 0617 /* shifted print key */ -#define KEY_SREDO 0620 /* shifted redo key */ -#define KEY_SREPLACE 0621 /* shifted replace key */ -#define KEY_SRIGHT 0622 /* shifted right-arrow key */ -#define KEY_SRSUME 0623 /* shifted resume key */ -#define KEY_SSAVE 0624 /* shifted save key */ -#define KEY_SSUSPEND 0625 /* shifted suspend key */ -#define KEY_SUNDO 0626 /* shifted undo key */ -#define KEY_SUSPEND 0627 /* suspend key */ -#define KEY_UNDO 0630 /* undo key */ -#define KEY_MOUSE 0631 /* Mouse event has occurred */ -#define KEY_RESIZE 0632 /* Terminal resize event */ -#define KEY_EVENT 0633 /* We were interrupted by an event */ - -#define KEY_MAX 0777 /* Maximum key value is 0633 */ -/* $Id: curses.tail,v 1.20 2010/03/28 19:10:55 tom Exp $ */ -/* - * vile:cmode: - * This file is part of ncurses, designed to be appended after curses.h.in - * (see that file for the relevant copyright). - */ - -/* mouse interface */ - -#if NCURSES_MOUSE_VERSION > 1 -#define NCURSES_MOUSE_MASK(b,m) ((m) << (((b) - 1) * 5)) -#else -#define NCURSES_MOUSE_MASK(b,m) ((m) << (((b) - 1) * 6)) -#endif - -#define NCURSES_BUTTON_RELEASED 001L -#define NCURSES_BUTTON_PRESSED 002L -#define NCURSES_BUTTON_CLICKED 004L -#define NCURSES_DOUBLE_CLICKED 010L -#define NCURSES_TRIPLE_CLICKED 020L -#define NCURSES_RESERVED_EVENT 040L - -/* event masks */ -#define BUTTON1_RELEASED NCURSES_MOUSE_MASK(1, NCURSES_BUTTON_RELEASED) -#define BUTTON1_PRESSED NCURSES_MOUSE_MASK(1, NCURSES_BUTTON_PRESSED) -#define BUTTON1_CLICKED NCURSES_MOUSE_MASK(1, NCURSES_BUTTON_CLICKED) -#define BUTTON1_DOUBLE_CLICKED NCURSES_MOUSE_MASK(1, NCURSES_DOUBLE_CLICKED) -#define BUTTON1_TRIPLE_CLICKED NCURSES_MOUSE_MASK(1, NCURSES_TRIPLE_CLICKED) - -#define BUTTON2_RELEASED NCURSES_MOUSE_MASK(2, NCURSES_BUTTON_RELEASED) -#define BUTTON2_PRESSED NCURSES_MOUSE_MASK(2, NCURSES_BUTTON_PRESSED) -#define BUTTON2_CLICKED NCURSES_MOUSE_MASK(2, NCURSES_BUTTON_CLICKED) -#define BUTTON2_DOUBLE_CLICKED NCURSES_MOUSE_MASK(2, NCURSES_DOUBLE_CLICKED) -#define BUTTON2_TRIPLE_CLICKED NCURSES_MOUSE_MASK(2, NCURSES_TRIPLE_CLICKED) - -#define BUTTON3_RELEASED NCURSES_MOUSE_MASK(3, NCURSES_BUTTON_RELEASED) -#define BUTTON3_PRESSED NCURSES_MOUSE_MASK(3, NCURSES_BUTTON_PRESSED) -#define BUTTON3_CLICKED NCURSES_MOUSE_MASK(3, NCURSES_BUTTON_CLICKED) -#define BUTTON3_DOUBLE_CLICKED NCURSES_MOUSE_MASK(3, NCURSES_DOUBLE_CLICKED) -#define BUTTON3_TRIPLE_CLICKED NCURSES_MOUSE_MASK(3, NCURSES_TRIPLE_CLICKED) - -#define BUTTON4_RELEASED NCURSES_MOUSE_MASK(4, NCURSES_BUTTON_RELEASED) -#define BUTTON4_PRESSED NCURSES_MOUSE_MASK(4, NCURSES_BUTTON_PRESSED) -#define BUTTON4_CLICKED NCURSES_MOUSE_MASK(4, NCURSES_BUTTON_CLICKED) -#define BUTTON4_DOUBLE_CLICKED NCURSES_MOUSE_MASK(4, NCURSES_DOUBLE_CLICKED) -#define BUTTON4_TRIPLE_CLICKED NCURSES_MOUSE_MASK(4, NCURSES_TRIPLE_CLICKED) - -/* - * In 32 bits the version-1 scheme does not provide enough space for a 5th - * button, unless we choose to change the ABI by omitting the reserved-events. - */ -#if NCURSES_MOUSE_VERSION > 1 - -#define BUTTON5_RELEASED NCURSES_MOUSE_MASK(5, NCURSES_BUTTON_RELEASED) -#define BUTTON5_PRESSED NCURSES_MOUSE_MASK(5, NCURSES_BUTTON_PRESSED) -#define BUTTON5_CLICKED NCURSES_MOUSE_MASK(5, NCURSES_BUTTON_CLICKED) -#define BUTTON5_DOUBLE_CLICKED NCURSES_MOUSE_MASK(5, NCURSES_DOUBLE_CLICKED) -#define BUTTON5_TRIPLE_CLICKED NCURSES_MOUSE_MASK(5, NCURSES_TRIPLE_CLICKED) - -#define BUTTON_CTRL NCURSES_MOUSE_MASK(6, 0001L) -#define BUTTON_SHIFT NCURSES_MOUSE_MASK(6, 0002L) -#define BUTTON_ALT NCURSES_MOUSE_MASK(6, 0004L) -#define REPORT_MOUSE_POSITION NCURSES_MOUSE_MASK(6, 0010L) - -#else - -#define BUTTON1_RESERVED_EVENT NCURSES_MOUSE_MASK(1, NCURSES_RESERVED_EVENT) -#define BUTTON2_RESERVED_EVENT NCURSES_MOUSE_MASK(2, NCURSES_RESERVED_EVENT) -#define BUTTON3_RESERVED_EVENT NCURSES_MOUSE_MASK(3, NCURSES_RESERVED_EVENT) -#define BUTTON4_RESERVED_EVENT NCURSES_MOUSE_MASK(4, NCURSES_RESERVED_EVENT) - -#define BUTTON_CTRL NCURSES_MOUSE_MASK(5, 0001L) -#define BUTTON_SHIFT NCURSES_MOUSE_MASK(5, 0002L) -#define BUTTON_ALT NCURSES_MOUSE_MASK(5, 0004L) -#define REPORT_MOUSE_POSITION NCURSES_MOUSE_MASK(5, 0010L) - -#endif - -#define ALL_MOUSE_EVENTS (REPORT_MOUSE_POSITION - 1) - -/* macros to extract single event-bits from masks */ -#define BUTTON_RELEASE(e, x) ((e) & NCURSES_MOUSE_MASK(x, 001)) -#define BUTTON_PRESS(e, x) ((e) & NCURSES_MOUSE_MASK(x, 002)) -#define BUTTON_CLICK(e, x) ((e) & NCURSES_MOUSE_MASK(x, 004)) -#define BUTTON_DOUBLE_CLICK(e, x) ((e) & NCURSES_MOUSE_MASK(x, 010)) -#define BUTTON_TRIPLE_CLICK(e, x) ((e) & NCURSES_MOUSE_MASK(x, 020)) -#define BUTTON_RESERVED_EVENT(e, x) ((e) & NCURSES_MOUSE_MASK(x, 040)) - -typedef struct -{ - short id; /* ID to distinguish multiple devices */ - int x, y, z; /* event coordinates (character-cell) */ - mmask_t bstate; /* button state bits */ -} -MEVENT; - -extern NCURSES_EXPORT(bool) has_mouse(void); -extern NCURSES_EXPORT(int) getmouse (MEVENT *); -extern NCURSES_EXPORT(int) ungetmouse (MEVENT *); -extern NCURSES_EXPORT(mmask_t) mousemask (mmask_t, mmask_t *); -extern NCURSES_EXPORT(bool) wenclose (const WINDOW *, int, int); -extern NCURSES_EXPORT(int) mouseinterval (int); -extern NCURSES_EXPORT(bool) wmouse_trafo (const WINDOW*, int*, int*, bool); -extern NCURSES_EXPORT(bool) mouse_trafo (int*, int*, bool); /* generated */ - -#if NCURSES_SP_FUNCS -extern NCURSES_EXPORT(bool) NCURSES_SP_NAME(has_mouse) (SCREEN*); -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(getmouse) (SCREEN*, MEVENT *); -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(ungetmouse) (SCREEN*,MEVENT *); -extern NCURSES_EXPORT(mmask_t) NCURSES_SP_NAME(mousemask) (SCREEN*, mmask_t, mmask_t *); -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(mouseinterval) (SCREEN*, int); -#endif - -#define mouse_trafo(y,x,to_screen) wmouse_trafo(stdscr,y,x,to_screen) - -/* other non-XSI functions */ - -extern NCURSES_EXPORT(int) mcprint (char *, int); /* direct data to printer */ -extern NCURSES_EXPORT(int) has_key (int); /* do we have given key? */ - -#if NCURSES_SP_FUNCS -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(has_key) (SCREEN*, int); /* do we have given key? */ -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(mcprint) (SCREEN*, char *, int); /* direct data to printer */ -#endif - -/* Debugging : use with libncurses_g.a */ - -extern NCURSES_EXPORT(void) _tracef (const char *, ...) GCC_PRINTFLIKE(1,2); -extern NCURSES_EXPORT(void) _tracedump (const char *, WINDOW *); -extern NCURSES_EXPORT(char *) _traceattr (attr_t); -extern NCURSES_EXPORT(char *) _traceattr2 (int, chtype); -extern NCURSES_EXPORT(char *) _nc_tracebits (void); -extern NCURSES_EXPORT(char *) _tracechar (int); -extern NCURSES_EXPORT(char *) _tracechtype (chtype); -extern NCURSES_EXPORT(char *) _tracechtype2 (int, chtype); -#ifdef NCURSES_WIDECHAR -#define _tracech_t _tracecchar_t -extern NCURSES_EXPORT(char *) _tracecchar_t (const cchar_t *); -#define _tracech_t2 _tracecchar_t2 -extern NCURSES_EXPORT(char *) _tracecchar_t2 (int, const cchar_t *); -#else -#define _tracech_t _tracechtype -#define _tracech_t2 _tracechtype2 -#endif -extern NCURSES_EXPORT(char *) _tracemouse (const MEVENT *); -extern NCURSES_EXPORT(void) trace (const unsigned int); - -/* trace masks */ -#define TRACE_DISABLE 0x0000 /* turn off tracing */ -#define TRACE_TIMES 0x0001 /* trace user and system times of updates */ -#define TRACE_TPUTS 0x0002 /* trace tputs calls */ -#define TRACE_UPDATE 0x0004 /* trace update actions, old & new screens */ -#define TRACE_MOVE 0x0008 /* trace cursor moves and scrolls */ -#define TRACE_CHARPUT 0x0010 /* trace all character outputs */ -#define TRACE_ORDINARY 0x001F /* trace all update actions */ -#define TRACE_CALLS 0x0020 /* trace all curses calls */ -#define TRACE_VIRTPUT 0x0040 /* trace virtual character puts */ -#define TRACE_IEVENT 0x0080 /* trace low-level input processing */ -#define TRACE_BITS 0x0100 /* trace state of TTY control bits */ -#define TRACE_ICALLS 0x0200 /* trace internal/nested calls */ -#define TRACE_CCALLS 0x0400 /* trace per-character calls */ -#define TRACE_DATABASE 0x0800 /* trace read/write of terminfo/termcap data */ -#define TRACE_ATTRS 0x1000 /* trace attribute updates */ - -#define TRACE_SHIFT 13 /* number of bits in the trace masks */ -#define TRACE_MAXIMUM ((1 << TRACE_SHIFT) - 1) /* maximum trace level */ - -#if defined(TRACE) || defined(NCURSES_TEST) -extern NCURSES_EXPORT_VAR(int) _nc_optimize_enable; /* enable optimizations */ -extern NCURSES_EXPORT(const char *) _nc_visbuf (const char *); -#define OPTIMIZE_MVCUR 0x01 /* cursor movement optimization */ -#define OPTIMIZE_HASHMAP 0x02 /* diff hashing to detect scrolls */ -#define OPTIMIZE_SCROLL 0x04 /* scroll optimization */ -#define OPTIMIZE_ALL 0xff /* enable all optimizations (dflt) */ -#endif - -#include - -#ifdef __cplusplus - -#ifndef NCURSES_NOMACROS - -/* these names conflict with STL */ -#undef box -#undef clear -#undef erase -#undef move -#undef refresh - -#endif /* NCURSES_NOMACROS */ - -} -#endif - -#endif /* __NCURSES_H */ diff --git a/windows/ncurses/include/ncurses/ncurses_dll.h b/windows/ncurses/include/ncurses/ncurses_dll.h deleted file mode 100644 index 6974fcba0..000000000 --- a/windows/ncurses/include/ncurses/ncurses_dll.h +++ /dev/null @@ -1,86 +0,0 @@ -/**************************************************************************** - * Copyright (c) 1998-2007,2009 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ -/* $Id: ncurses_dll.h.in,v 1.8 2009/04/04 22:26:27 tom Exp $ */ - -#ifndef NCURSES_DLL_H_incl -#define NCURSES_DLL_H_incl 1 - -/* - * For reentrant code, we map the various global variables into SCREEN by - * using functions to access them. - */ -#define NCURSES_PUBLIC_VAR(name) _nc_##name -#define NCURSES_WRAPPED_VAR(type,name) extern type NCURSES_PUBLIC_VAR(name)(void) - -/* no longer needed on cygwin or mingw, thanks to auto-import */ -/* but this structure may be useful at some point for an MSVC build */ -/* so, for now unconditionally define the important flags */ -/* "the right way" for proper static and dll+auto-import behavior */ -#undef NCURSES_DLL -#define NCURSES_STATIC - -#if defined(__CYGWIN__) || defined(__MINGW32__) -# if defined(NCURSES_DLL) -# if defined(NCURSES_STATIC) -# undef NCURSES_STATIC -# endif -# endif -# undef NCURSES_IMPEXP -# undef NCURSES_API -# undef NCURSES_EXPORT -# undef NCURSES_EXPORT_VAR -# if defined(NCURSES_DLL) -/* building a DLL */ -# define NCURSES_IMPEXP __declspec(dllexport) -# elif defined(NCURSES_STATIC) -/* building or linking to a static library */ -# define NCURSES_IMPEXP /* nothing */ -# else -/* linking to the DLL */ -# define NCURSES_IMPEXP __declspec(dllimport) -# endif -# define NCURSES_API __cdecl -# define NCURSES_EXPORT(type) NCURSES_IMPEXP type NCURSES_API -# define NCURSES_EXPORT_VAR(type) NCURSES_IMPEXP type -#endif - -/* Take care of non-cygwin platforms */ -#if !defined(NCURSES_IMPEXP) -# define NCURSES_IMPEXP /* nothing */ -#endif -#if !defined(NCURSES_API) -# define NCURSES_API /* nothing */ -#endif -#if !defined(NCURSES_EXPORT) -# define NCURSES_EXPORT(type) NCURSES_IMPEXP type NCURSES_API -#endif -#if !defined(NCURSES_EXPORT_VAR) -# define NCURSES_EXPORT_VAR(type) __declspec(dllimport) type -#endif - -#endif /* NCURSES_DLL_H_incl */ diff --git a/windows/ncurses/include/ncurses/panel.h b/windows/ncurses/include/ncurses/panel.h deleted file mode 100644 index 4d5aca279..000000000 --- a/windows/ncurses/include/ncurses/panel.h +++ /dev/null @@ -1,85 +0,0 @@ -/**************************************************************************** - * Copyright (c) 1998-2006,2009 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/**************************************************************************** - * Author: Zeyd M. Ben-Halim 1995 * - * and: Eric S. Raymond * - * and: Juergen Pfeifer 1996-1999,2008 * - ****************************************************************************/ - -/* $Id: panel.h,v 1.11 2009/04/11 19:50:40 tom Exp $ */ - -/* panel.h -- interface file for panels library */ - -#ifndef NCURSES_PANEL_H_incl -#define NCURSES_PANEL_H_incl 1 - -#include - -typedef struct panel -{ - WINDOW *win; - struct panel *below; - struct panel *above; - NCURSES_CONST void *user; -} PANEL; - -#if defined(__cplusplus) -extern "C" { -#endif - -extern NCURSES_EXPORT(WINDOW*) panel_window (const PANEL *); -extern NCURSES_EXPORT(void) update_panels (void); -extern NCURSES_EXPORT(int) hide_panel (PANEL *); -extern NCURSES_EXPORT(int) show_panel (PANEL *); -extern NCURSES_EXPORT(int) del_panel (PANEL *); -extern NCURSES_EXPORT(int) top_panel (PANEL *); -extern NCURSES_EXPORT(int) bottom_panel (PANEL *); -extern NCURSES_EXPORT(PANEL*) new_panel (WINDOW *); -extern NCURSES_EXPORT(PANEL*) panel_above (const PANEL *); -extern NCURSES_EXPORT(PANEL*) panel_below (const PANEL *); -extern NCURSES_EXPORT(int) set_panel_userptr (PANEL *, NCURSES_CONST void *); -extern NCURSES_EXPORT(NCURSES_CONST void*) panel_userptr (const PANEL *); -extern NCURSES_EXPORT(int) move_panel (PANEL *, int, int); -extern NCURSES_EXPORT(int) replace_panel (PANEL *,WINDOW *); -extern NCURSES_EXPORT(int) panel_hidden (const PANEL *); - -#if NCURSES_SP_FUNCS -extern NCURSES_EXPORT(PANEL *) ground_panel(SCREEN *); -extern NCURSES_EXPORT(PANEL *) ceiling_panel(SCREEN *); - -extern NCURSES_EXPORT(void) NCURSES_SP_NAME(update_panels) (SCREEN*); -#endif - -#if defined(__cplusplus) -} -#endif - -#endif /* NCURSES_PANEL_H_incl */ - -/* end of panel.h */ diff --git a/windows/ncurses/include/ncurses/term.h b/windows/ncurses/include/ncurses/term.h deleted file mode 100644 index 543a18df8..000000000 --- a/windows/ncurses/include/ncurses/term.h +++ /dev/null @@ -1,834 +0,0 @@ -/**************************************************************************** - * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/****************************************************************************/ -/* Author: Zeyd M. Ben-Halim 1992,1995 */ -/* and: Eric S. Raymond */ -/* and: Thomas E. Dickey 1995-on */ -/****************************************************************************/ - -/* $Id: MKterm.h.awk.in,v 1.58 2010/01/09 19:53:26 tom Exp $ */ - -/* -** term.h -- Definition of struct term -*/ - -#ifndef NCURSES_TERM_H_incl -#define NCURSES_TERM_H_incl 1 - -#undef NCURSES_VERSION -#define NCURSES_VERSION "5.9" - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Make this file self-contained by providing defaults for the HAVE_TERMIO[S]_H - * definition (based on the system for which this was configured). - */ - -#undef NCURSES_CONST -#define NCURSES_CONST /*nothing*/ - -#undef NCURSES_SBOOL -#define NCURSES_SBOOL char - -#undef NCURSES_XNAMES -#define NCURSES_XNAMES 1 - -/* We will use these symbols to hide differences between - * termios/termio/sgttyb interfaces. - */ -#undef TTY -#undef SET_TTY -#undef GET_TTY - -/* Assume POSIX termio if we have the header and function */ -/* #if HAVE_TERMIOS_H && HAVE_TCGETATTR */ -#if 0 && 0 - -#undef TERMIOS -#define TERMIOS 1 - -#include -#define TTY struct termios - -#else /* !HAVE_TERMIOS_H */ - -/* #if HAVE_TERMIO_H */ -#if 0 - -#undef TERMIOS -#define TERMIOS 1 - -#include -#define TTY struct termio - -/* Add definitions to make termio look like termios. - * But ifdef it, since there are some implementations - * that try to do this for us in a fake . - */ -#ifndef TCSANOW -#define TCSANOW TCSETA -#endif -#ifndef TCSADRAIN -#define TCSADRAIN TCSETAW -#endif -#ifndef TCSAFLUSH -#define TCSAFLUSH TCSETAF -#endif -#ifndef tcsetattr -#define tcsetattr(fd, cmd, arg) ioctl(fd, cmd, arg) -#endif -#ifndef tcgetattr -#define tcgetattr(fd, arg) ioctl(fd, TCGETA, arg) -#endif -#ifndef cfgetospeed -#define cfgetospeed(t) ((t)->c_cflag & CBAUD) -#endif -#ifndef TCIFLUSH -#define TCIFLUSH 0 -#endif -#ifndef TCOFLUSH -#define TCOFLUSH 1 -#endif -#ifndef TCIOFLUSH -#define TCIOFLUSH 2 -#endif -#ifndef tcflush -#define tcflush(fd, arg) ioctl(fd, TCFLSH, arg) -#endif - -#else /* !HAVE_TERMIO_H */ - -#if __MINGW32__ -# include -# define TTY struct termios -#else -#undef TERMIOS -#include -#include -#define TTY struct sgttyb -#endif /* MINGW32 */ -#endif /* HAVE_TERMIO_H */ - -#endif /* HAVE_TERMIOS_H */ - -#ifdef TERMIOS -#define GET_TTY(fd, buf) tcgetattr(fd, buf) -#define SET_TTY(fd, buf) tcsetattr(fd, TCSADRAIN, buf) -#else -#define GET_TTY(fd, buf) gtty(fd, buf) -#define SET_TTY(fd, buf) stty(fd, buf) -#endif - -#define NAMESIZE 256 - -#define CUR cur_term->type. - -#define auto_left_margin CUR Booleans[0] -#define auto_right_margin CUR Booleans[1] -#define no_esc_ctlc CUR Booleans[2] -#define ceol_standout_glitch CUR Booleans[3] -#define eat_newline_glitch CUR Booleans[4] -#define erase_overstrike CUR Booleans[5] -#define generic_type CUR Booleans[6] -#define hard_copy CUR Booleans[7] -#define has_meta_key CUR Booleans[8] -#define has_status_line CUR Booleans[9] -#define insert_null_glitch CUR Booleans[10] -#define memory_above CUR Booleans[11] -#define memory_below CUR Booleans[12] -#define move_insert_mode CUR Booleans[13] -#define move_standout_mode CUR Booleans[14] -#define over_strike CUR Booleans[15] -#define status_line_esc_ok CUR Booleans[16] -#define dest_tabs_magic_smso CUR Booleans[17] -#define tilde_glitch CUR Booleans[18] -#define transparent_underline CUR Booleans[19] -#define xon_xoff CUR Booleans[20] -#define needs_xon_xoff CUR Booleans[21] -#define prtr_silent CUR Booleans[22] -#define hard_cursor CUR Booleans[23] -#define non_rev_rmcup CUR Booleans[24] -#define no_pad_char CUR Booleans[25] -#define non_dest_scroll_region CUR Booleans[26] -#define can_change CUR Booleans[27] -#define back_color_erase CUR Booleans[28] -#define hue_lightness_saturation CUR Booleans[29] -#define col_addr_glitch CUR Booleans[30] -#define cr_cancels_micro_mode CUR Booleans[31] -#define has_print_wheel CUR Booleans[32] -#define row_addr_glitch CUR Booleans[33] -#define semi_auto_right_margin CUR Booleans[34] -#define cpi_changes_res CUR Booleans[35] -#define lpi_changes_res CUR Booleans[36] -#define columns CUR Numbers[0] -#define init_tabs CUR Numbers[1] -#define lines CUR Numbers[2] -#define lines_of_memory CUR Numbers[3] -#define magic_cookie_glitch CUR Numbers[4] -#define padding_baud_rate CUR Numbers[5] -#define virtual_terminal CUR Numbers[6] -#define width_status_line CUR Numbers[7] -#define num_labels CUR Numbers[8] -#define label_height CUR Numbers[9] -#define label_width CUR Numbers[10] -#define max_attributes CUR Numbers[11] -#define maximum_windows CUR Numbers[12] -#define max_colors CUR Numbers[13] -#define max_pairs CUR Numbers[14] -#define no_color_video CUR Numbers[15] -#define buffer_capacity CUR Numbers[16] -#define dot_vert_spacing CUR Numbers[17] -#define dot_horz_spacing CUR Numbers[18] -#define max_micro_address CUR Numbers[19] -#define max_micro_jump CUR Numbers[20] -#define micro_col_size CUR Numbers[21] -#define micro_line_size CUR Numbers[22] -#define number_of_pins CUR Numbers[23] -#define output_res_char CUR Numbers[24] -#define output_res_line CUR Numbers[25] -#define output_res_horz_inch CUR Numbers[26] -#define output_res_vert_inch CUR Numbers[27] -#define print_rate CUR Numbers[28] -#define wide_char_size CUR Numbers[29] -#define buttons CUR Numbers[30] -#define bit_image_entwining CUR Numbers[31] -#define bit_image_type CUR Numbers[32] -#define back_tab CUR Strings[0] -#define bell CUR Strings[1] -#define carriage_return CUR Strings[2] -#define change_scroll_region CUR Strings[3] -#define clear_all_tabs CUR Strings[4] -#define clear_screen CUR Strings[5] -#define clr_eol CUR Strings[6] -#define clr_eos CUR Strings[7] -#define column_address CUR Strings[8] -#define command_character CUR Strings[9] -#define cursor_address CUR Strings[10] -#define cursor_down CUR Strings[11] -#define cursor_home CUR Strings[12] -#define cursor_invisible CUR Strings[13] -#define cursor_left CUR Strings[14] -#define cursor_mem_address CUR Strings[15] -#define cursor_normal CUR Strings[16] -#define cursor_right CUR Strings[17] -#define cursor_to_ll CUR Strings[18] -#define cursor_up CUR Strings[19] -#define cursor_visible CUR Strings[20] -#define delete_character CUR Strings[21] -#define delete_line CUR Strings[22] -#define dis_status_line CUR Strings[23] -#define down_half_line CUR Strings[24] -#define enter_alt_charset_mode CUR Strings[25] -#define enter_blink_mode CUR Strings[26] -#define enter_bold_mode CUR Strings[27] -#define enter_ca_mode CUR Strings[28] -#define enter_delete_mode CUR Strings[29] -#define enter_dim_mode CUR Strings[30] -#define enter_insert_mode CUR Strings[31] -#define enter_secure_mode CUR Strings[32] -#define enter_protected_mode CUR Strings[33] -#define enter_reverse_mode CUR Strings[34] -#define enter_standout_mode CUR Strings[35] -#define enter_underline_mode CUR Strings[36] -#define erase_chars CUR Strings[37] -#define exit_alt_charset_mode CUR Strings[38] -#define exit_attribute_mode CUR Strings[39] -#define exit_ca_mode CUR Strings[40] -#define exit_delete_mode CUR Strings[41] -#define exit_insert_mode CUR Strings[42] -#define exit_standout_mode CUR Strings[43] -#define exit_underline_mode CUR Strings[44] -#define flash_screen CUR Strings[45] -#define form_feed CUR Strings[46] -#define from_status_line CUR Strings[47] -#define init_1string CUR Strings[48] -#define init_2string CUR Strings[49] -#define init_3string CUR Strings[50] -#define init_file CUR Strings[51] -#define insert_character CUR Strings[52] -#define insert_line CUR Strings[53] -#define insert_padding CUR Strings[54] -#define key_backspace CUR Strings[55] -#define key_catab CUR Strings[56] -#define key_clear CUR Strings[57] -#define key_ctab CUR Strings[58] -#define key_dc CUR Strings[59] -#define key_dl CUR Strings[60] -#define key_down CUR Strings[61] -#define key_eic CUR Strings[62] -#define key_eol CUR Strings[63] -#define key_eos CUR Strings[64] -#define key_f0 CUR Strings[65] -#define key_f1 CUR Strings[66] -#define key_f10 CUR Strings[67] -#define key_f2 CUR Strings[68] -#define key_f3 CUR Strings[69] -#define key_f4 CUR Strings[70] -#define key_f5 CUR Strings[71] -#define key_f6 CUR Strings[72] -#define key_f7 CUR Strings[73] -#define key_f8 CUR Strings[74] -#define key_f9 CUR Strings[75] -#define key_home CUR Strings[76] -#define key_ic CUR Strings[77] -#define key_il CUR Strings[78] -#define key_left CUR Strings[79] -#define key_ll CUR Strings[80] -#define key_npage CUR Strings[81] -#define key_ppage CUR Strings[82] -#define key_right CUR Strings[83] -#define key_sf CUR Strings[84] -#define key_sr CUR Strings[85] -#define key_stab CUR Strings[86] -#define key_up CUR Strings[87] -#define keypad_local CUR Strings[88] -#define keypad_xmit CUR Strings[89] -#define lab_f0 CUR Strings[90] -#define lab_f1 CUR Strings[91] -#define lab_f10 CUR Strings[92] -#define lab_f2 CUR Strings[93] -#define lab_f3 CUR Strings[94] -#define lab_f4 CUR Strings[95] -#define lab_f5 CUR Strings[96] -#define lab_f6 CUR Strings[97] -#define lab_f7 CUR Strings[98] -#define lab_f8 CUR Strings[99] -#define lab_f9 CUR Strings[100] -#define meta_off CUR Strings[101] -#define meta_on CUR Strings[102] -#define newline CUR Strings[103] -#define pad_char CUR Strings[104] -#define parm_dch CUR Strings[105] -#define parm_delete_line CUR Strings[106] -#define parm_down_cursor CUR Strings[107] -#define parm_ich CUR Strings[108] -#define parm_index CUR Strings[109] -#define parm_insert_line CUR Strings[110] -#define parm_left_cursor CUR Strings[111] -#define parm_right_cursor CUR Strings[112] -#define parm_rindex CUR Strings[113] -#define parm_up_cursor CUR Strings[114] -#define pkey_key CUR Strings[115] -#define pkey_local CUR Strings[116] -#define pkey_xmit CUR Strings[117] -#define print_screen CUR Strings[118] -#define prtr_off CUR Strings[119] -#define prtr_on CUR Strings[120] -#define repeat_char CUR Strings[121] -#define reset_1string CUR Strings[122] -#define reset_2string CUR Strings[123] -#define reset_3string CUR Strings[124] -#define reset_file CUR Strings[125] -#define restore_cursor CUR Strings[126] -#define row_address CUR Strings[127] -#define save_cursor CUR Strings[128] -#define scroll_forward CUR Strings[129] -#define scroll_reverse CUR Strings[130] -#define set_attributes CUR Strings[131] -#define set_tab CUR Strings[132] -#define set_window CUR Strings[133] -#define tab CUR Strings[134] -#define to_status_line CUR Strings[135] -#define underline_char CUR Strings[136] -#define up_half_line CUR Strings[137] -#define init_prog CUR Strings[138] -#define key_a1 CUR Strings[139] -#define key_a3 CUR Strings[140] -#define key_b2 CUR Strings[141] -#define key_c1 CUR Strings[142] -#define key_c3 CUR Strings[143] -#define prtr_non CUR Strings[144] -#define char_padding CUR Strings[145] -#define acs_chars CUR Strings[146] -#define plab_norm CUR Strings[147] -#define key_btab CUR Strings[148] -#define enter_xon_mode CUR Strings[149] -#define exit_xon_mode CUR Strings[150] -#define enter_am_mode CUR Strings[151] -#define exit_am_mode CUR Strings[152] -#define xon_character CUR Strings[153] -#define xoff_character CUR Strings[154] -#define ena_acs CUR Strings[155] -#define label_on CUR Strings[156] -#define label_off CUR Strings[157] -#define key_beg CUR Strings[158] -#define key_cancel CUR Strings[159] -#define key_close CUR Strings[160] -#define key_command CUR Strings[161] -#define key_copy CUR Strings[162] -#define key_create CUR Strings[163] -#define key_end CUR Strings[164] -#define key_enter CUR Strings[165] -#define key_exit CUR Strings[166] -#define key_find CUR Strings[167] -#define key_help CUR Strings[168] -#define key_mark CUR Strings[169] -#define key_message CUR Strings[170] -#define key_move CUR Strings[171] -#define key_next CUR Strings[172] -#define key_open CUR Strings[173] -#define key_options CUR Strings[174] -#define key_previous CUR Strings[175] -#define key_print CUR Strings[176] -#define key_redo CUR Strings[177] -#define key_reference CUR Strings[178] -#define key_refresh CUR Strings[179] -#define key_replace CUR Strings[180] -#define key_restart CUR Strings[181] -#define key_resume CUR Strings[182] -#define key_save CUR Strings[183] -#define key_suspend CUR Strings[184] -#define key_undo CUR Strings[185] -#define key_sbeg CUR Strings[186] -#define key_scancel CUR Strings[187] -#define key_scommand CUR Strings[188] -#define key_scopy CUR Strings[189] -#define key_screate CUR Strings[190] -#define key_sdc CUR Strings[191] -#define key_sdl CUR Strings[192] -#define key_select CUR Strings[193] -#define key_send CUR Strings[194] -#define key_seol CUR Strings[195] -#define key_sexit CUR Strings[196] -#define key_sfind CUR Strings[197] -#define key_shelp CUR Strings[198] -#define key_shome CUR Strings[199] -#define key_sic CUR Strings[200] -#define key_sleft CUR Strings[201] -#define key_smessage CUR Strings[202] -#define key_smove CUR Strings[203] -#define key_snext CUR Strings[204] -#define key_soptions CUR Strings[205] -#define key_sprevious CUR Strings[206] -#define key_sprint CUR Strings[207] -#define key_sredo CUR Strings[208] -#define key_sreplace CUR Strings[209] -#define key_sright CUR Strings[210] -#define key_srsume CUR Strings[211] -#define key_ssave CUR Strings[212] -#define key_ssuspend CUR Strings[213] -#define key_sundo CUR Strings[214] -#define req_for_input CUR Strings[215] -#define key_f11 CUR Strings[216] -#define key_f12 CUR Strings[217] -#define key_f13 CUR Strings[218] -#define key_f14 CUR Strings[219] -#define key_f15 CUR Strings[220] -#define key_f16 CUR Strings[221] -#define key_f17 CUR Strings[222] -#define key_f18 CUR Strings[223] -#define key_f19 CUR Strings[224] -#define key_f20 CUR Strings[225] -#define key_f21 CUR Strings[226] -#define key_f22 CUR Strings[227] -#define key_f23 CUR Strings[228] -#define key_f24 CUR Strings[229] -#define key_f25 CUR Strings[230] -#define key_f26 CUR Strings[231] -#define key_f27 CUR Strings[232] -#define key_f28 CUR Strings[233] -#define key_f29 CUR Strings[234] -#define key_f30 CUR Strings[235] -#define key_f31 CUR Strings[236] -#define key_f32 CUR Strings[237] -#define key_f33 CUR Strings[238] -#define key_f34 CUR Strings[239] -#define key_f35 CUR Strings[240] -#define key_f36 CUR Strings[241] -#define key_f37 CUR Strings[242] -#define key_f38 CUR Strings[243] -#define key_f39 CUR Strings[244] -#define key_f40 CUR Strings[245] -#define key_f41 CUR Strings[246] -#define key_f42 CUR Strings[247] -#define key_f43 CUR Strings[248] -#define key_f44 CUR Strings[249] -#define key_f45 CUR Strings[250] -#define key_f46 CUR Strings[251] -#define key_f47 CUR Strings[252] -#define key_f48 CUR Strings[253] -#define key_f49 CUR Strings[254] -#define key_f50 CUR Strings[255] -#define key_f51 CUR Strings[256] -#define key_f52 CUR Strings[257] -#define key_f53 CUR Strings[258] -#define key_f54 CUR Strings[259] -#define key_f55 CUR Strings[260] -#define key_f56 CUR Strings[261] -#define key_f57 CUR Strings[262] -#define key_f58 CUR Strings[263] -#define key_f59 CUR Strings[264] -#define key_f60 CUR Strings[265] -#define key_f61 CUR Strings[266] -#define key_f62 CUR Strings[267] -#define key_f63 CUR Strings[268] -#define clr_bol CUR Strings[269] -#define clear_margins CUR Strings[270] -#define set_left_margin CUR Strings[271] -#define set_right_margin CUR Strings[272] -#define label_format CUR Strings[273] -#define set_clock CUR Strings[274] -#define display_clock CUR Strings[275] -#define remove_clock CUR Strings[276] -#define create_window CUR Strings[277] -#define goto_window CUR Strings[278] -#define hangup CUR Strings[279] -#define dial_phone CUR Strings[280] -#define quick_dial CUR Strings[281] -#define tone CUR Strings[282] -#define pulse CUR Strings[283] -#define flash_hook CUR Strings[284] -#define fixed_pause CUR Strings[285] -#define wait_tone CUR Strings[286] -#define user0 CUR Strings[287] -#define user1 CUR Strings[288] -#define user2 CUR Strings[289] -#define user3 CUR Strings[290] -#define user4 CUR Strings[291] -#define user5 CUR Strings[292] -#define user6 CUR Strings[293] -#define user7 CUR Strings[294] -#define user8 CUR Strings[295] -#define user9 CUR Strings[296] -#define orig_pair CUR Strings[297] -#define orig_colors CUR Strings[298] -#define initialize_color CUR Strings[299] -#define initialize_pair CUR Strings[300] -#define set_color_pair CUR Strings[301] -#define set_foreground CUR Strings[302] -#define set_background CUR Strings[303] -#define change_char_pitch CUR Strings[304] -#define change_line_pitch CUR Strings[305] -#define change_res_horz CUR Strings[306] -#define change_res_vert CUR Strings[307] -#define define_char CUR Strings[308] -#define enter_doublewide_mode CUR Strings[309] -#define enter_draft_quality CUR Strings[310] -#define enter_italics_mode CUR Strings[311] -#define enter_leftward_mode CUR Strings[312] -#define enter_micro_mode CUR Strings[313] -#define enter_near_letter_quality CUR Strings[314] -#define enter_normal_quality CUR Strings[315] -#define enter_shadow_mode CUR Strings[316] -#define enter_subscript_mode CUR Strings[317] -#define enter_superscript_mode CUR Strings[318] -#define enter_upward_mode CUR Strings[319] -#define exit_doublewide_mode CUR Strings[320] -#define exit_italics_mode CUR Strings[321] -#define exit_leftward_mode CUR Strings[322] -#define exit_micro_mode CUR Strings[323] -#define exit_shadow_mode CUR Strings[324] -#define exit_subscript_mode CUR Strings[325] -#define exit_superscript_mode CUR Strings[326] -#define exit_upward_mode CUR Strings[327] -#define micro_column_address CUR Strings[328] -#define micro_down CUR Strings[329] -#define micro_left CUR Strings[330] -#define micro_right CUR Strings[331] -#define micro_row_address CUR Strings[332] -#define micro_up CUR Strings[333] -#define order_of_pins CUR Strings[334] -#define parm_down_micro CUR Strings[335] -#define parm_left_micro CUR Strings[336] -#define parm_right_micro CUR Strings[337] -#define parm_up_micro CUR Strings[338] -#define select_char_set CUR Strings[339] -#define set_bottom_margin CUR Strings[340] -#define set_bottom_margin_parm CUR Strings[341] -#define set_left_margin_parm CUR Strings[342] -#define set_right_margin_parm CUR Strings[343] -#define set_top_margin CUR Strings[344] -#define set_top_margin_parm CUR Strings[345] -#define start_bit_image CUR Strings[346] -#define start_char_set_def CUR Strings[347] -#define stop_bit_image CUR Strings[348] -#define stop_char_set_def CUR Strings[349] -#define subscript_characters CUR Strings[350] -#define superscript_characters CUR Strings[351] -#define these_cause_cr CUR Strings[352] -#define zero_motion CUR Strings[353] -#define char_set_names CUR Strings[354] -#define key_mouse CUR Strings[355] -#define mouse_info CUR Strings[356] -#define req_mouse_pos CUR Strings[357] -#define get_mouse CUR Strings[358] -#define set_a_foreground CUR Strings[359] -#define set_a_background CUR Strings[360] -#define pkey_plab CUR Strings[361] -#define device_type CUR Strings[362] -#define code_set_init CUR Strings[363] -#define set0_des_seq CUR Strings[364] -#define set1_des_seq CUR Strings[365] -#define set2_des_seq CUR Strings[366] -#define set3_des_seq CUR Strings[367] -#define set_lr_margin CUR Strings[368] -#define set_tb_margin CUR Strings[369] -#define bit_image_repeat CUR Strings[370] -#define bit_image_newline CUR Strings[371] -#define bit_image_carriage_return CUR Strings[372] -#define color_names CUR Strings[373] -#define define_bit_image_region CUR Strings[374] -#define end_bit_image_region CUR Strings[375] -#define set_color_band CUR Strings[376] -#define set_page_length CUR Strings[377] -#define display_pc_char CUR Strings[378] -#define enter_pc_charset_mode CUR Strings[379] -#define exit_pc_charset_mode CUR Strings[380] -#define enter_scancode_mode CUR Strings[381] -#define exit_scancode_mode CUR Strings[382] -#define pc_term_options CUR Strings[383] -#define scancode_escape CUR Strings[384] -#define alt_scancode_esc CUR Strings[385] -#define enter_horizontal_hl_mode CUR Strings[386] -#define enter_left_hl_mode CUR Strings[387] -#define enter_low_hl_mode CUR Strings[388] -#define enter_right_hl_mode CUR Strings[389] -#define enter_top_hl_mode CUR Strings[390] -#define enter_vertical_hl_mode CUR Strings[391] -#define set_a_attributes CUR Strings[392] -#define set_pglen_inch CUR Strings[393] - -#define BOOLWRITE 37 -#define NUMWRITE 33 -#define STRWRITE 394 - -/* older synonyms for some capabilities */ -#define beehive_glitch no_esc_ctlc -#define teleray_glitch dest_tabs_magic_smso -#define micro_char_size micro_col_size - -#ifdef __INTERNAL_CAPS_VISIBLE -#define termcap_init2 CUR Strings[394] -#define termcap_reset CUR Strings[395] -#define magic_cookie_glitch_ul CUR Numbers[33] -#define backspaces_with_bs CUR Booleans[37] -#define crt_no_scrolling CUR Booleans[38] -#define no_correctly_working_cr CUR Booleans[39] -#define carriage_return_delay CUR Numbers[34] -#define new_line_delay CUR Numbers[35] -#define linefeed_if_not_lf CUR Strings[396] -#define backspace_if_not_bs CUR Strings[397] -#define gnu_has_meta_key CUR Booleans[40] -#define linefeed_is_newline CUR Booleans[41] -#define backspace_delay CUR Numbers[36] -#define horizontal_tab_delay CUR Numbers[37] -#define number_of_function_keys CUR Numbers[38] -#define other_non_function_keys CUR Strings[398] -#define arrow_key_map CUR Strings[399] -#define has_hardware_tabs CUR Booleans[42] -#define return_does_clr_eol CUR Booleans[43] -#define acs_ulcorner CUR Strings[400] -#define acs_llcorner CUR Strings[401] -#define acs_urcorner CUR Strings[402] -#define acs_lrcorner CUR Strings[403] -#define acs_ltee CUR Strings[404] -#define acs_rtee CUR Strings[405] -#define acs_btee CUR Strings[406] -#define acs_ttee CUR Strings[407] -#define acs_hline CUR Strings[408] -#define acs_vline CUR Strings[409] -#define acs_plus CUR Strings[410] -#define memory_lock CUR Strings[411] -#define memory_unlock CUR Strings[412] -#define box_chars_1 CUR Strings[413] -#endif /* __INTERNAL_CAPS_VISIBLE */ - - -/* - * Predefined terminfo array sizes - */ -#define BOOLCOUNT 44 -#define NUMCOUNT 39 -#define STRCOUNT 414 - -/* used by code for comparing entries */ -#define acs_chars_index 146 - -typedef struct termtype { /* in-core form of terminfo data */ - char *term_names; /* str_table offset of term names */ - char *str_table; /* pointer to string table */ - NCURSES_SBOOL *Booleans; /* array of boolean values */ - short *Numbers; /* array of integer values */ - char **Strings; /* array of string offsets */ - -#if NCURSES_XNAMES - char *ext_str_table; /* pointer to extended string table */ - char **ext_Names; /* corresponding names */ - - unsigned short num_Booleans;/* count total Booleans */ - unsigned short num_Numbers; /* count total Numbers */ - unsigned short num_Strings; /* count total Strings */ - - unsigned short ext_Booleans;/* count extensions to Booleans */ - unsigned short ext_Numbers; /* count extensions to Numbers */ - unsigned short ext_Strings; /* count extensions to Strings */ -#endif /* NCURSES_XNAMES */ - -} TERMTYPE; - -typedef struct term { /* describe an actual terminal */ - TERMTYPE type; /* terminal type description */ - short Filedes; /* file description being written to */ - TTY Ottyb, /* original state of the terminal */ - Nttyb; /* current state of the terminal */ - int _baudrate; /* used to compute padding */ - char * _termname; /* used for termname() */ -} TERMINAL; - -#if 0 && !0 -extern NCURSES_EXPORT_VAR(TERMINAL *) cur_term; -#elif 0 -NCURSES_WRAPPED_VAR(TERMINAL *, cur_term); -#define cur_term NCURSES_PUBLIC_VAR(cur_term()) -#else -extern NCURSES_EXPORT_VAR(TERMINAL *) cur_term; -#endif - -#if 0 || 0 -NCURSES_WRAPPED_VAR(NCURSES_CONST char * const *, boolnames); -NCURSES_WRAPPED_VAR(NCURSES_CONST char * const *, boolcodes); -NCURSES_WRAPPED_VAR(NCURSES_CONST char * const *, boolfnames); -NCURSES_WRAPPED_VAR(NCURSES_CONST char * const *, numnames); -NCURSES_WRAPPED_VAR(NCURSES_CONST char * const *, numcodes); -NCURSES_WRAPPED_VAR(NCURSES_CONST char * const *, numfnames); -NCURSES_WRAPPED_VAR(NCURSES_CONST char * const *, strnames); -NCURSES_WRAPPED_VAR(NCURSES_CONST char * const *, strcodes); -NCURSES_WRAPPED_VAR(NCURSES_CONST char * const *, strfnames); - -#define boolnames NCURSES_PUBLIC_VAR(boolnames()) -#define boolcodes NCURSES_PUBLIC_VAR(boolcodes()) -#define boolfnames NCURSES_PUBLIC_VAR(boolfnames()) -#define numnames NCURSES_PUBLIC_VAR(numnames()) -#define numcodes NCURSES_PUBLIC_VAR(numcodes()) -#define numfnames NCURSES_PUBLIC_VAR(numfnames()) -#define strnames NCURSES_PUBLIC_VAR(strnames()) -#define strcodes NCURSES_PUBLIC_VAR(strcodes()) -#define strfnames NCURSES_PUBLIC_VAR(strfnames()) - -#else - -extern NCURSES_EXPORT_VAR(NCURSES_CONST char * const ) boolnames[]; -extern NCURSES_EXPORT_VAR(NCURSES_CONST char * const ) boolcodes[]; -extern NCURSES_EXPORT_VAR(NCURSES_CONST char * const ) boolfnames[]; -extern NCURSES_EXPORT_VAR(NCURSES_CONST char * const ) numnames[]; -extern NCURSES_EXPORT_VAR(NCURSES_CONST char * const ) numcodes[]; -extern NCURSES_EXPORT_VAR(NCURSES_CONST char * const ) numfnames[]; -extern NCURSES_EXPORT_VAR(NCURSES_CONST char * const ) strnames[]; -extern NCURSES_EXPORT_VAR(NCURSES_CONST char * const ) strcodes[]; -extern NCURSES_EXPORT_VAR(NCURSES_CONST char * const ) strfnames[]; - -#endif - -/* internals */ -extern NCURSES_EXPORT(int) _nc_set_tty_mode (TTY *buf); -extern NCURSES_EXPORT(int) _nc_get_tty_mode (TTY *buf); -extern NCURSES_EXPORT(int) _nc_read_entry (const char * const, char * const, TERMTYPE *const); -extern NCURSES_EXPORT(int) _nc_read_file_entry (const char *const, TERMTYPE *); -extern NCURSES_EXPORT(int) _nc_read_termtype (TERMTYPE *, char *, int); -extern NCURSES_EXPORT(char *) _nc_first_name (const char *const); -extern NCURSES_EXPORT(int) _nc_name_match (const char *const, const char *const, const char *const); -extern NCURSES_EXPORT(const TERMTYPE *) _nc_fallback (const char *); - -/* entry points */ -extern NCURSES_EXPORT(TERMINAL *) set_curterm (TERMINAL *); -extern NCURSES_EXPORT(int) del_curterm (TERMINAL *); - -/* miscellaneous entry points */ -extern NCURSES_EXPORT(int) restartterm (NCURSES_CONST char *, int, int *); -extern NCURSES_EXPORT(int) setupterm (NCURSES_CONST char *,int,int *); - -/* terminfo entry points, also declared in curses.h */ -#if !defined(__NCURSES_H) -extern NCURSES_EXPORT(char *) tigetstr (NCURSES_CONST char *); -extern NCURSES_EXPORT_VAR(char) ttytype[]; -extern NCURSES_EXPORT(int) putp (const char *); -extern NCURSES_EXPORT(int) tigetflag (NCURSES_CONST char *); -extern NCURSES_EXPORT(int) tigetnum (NCURSES_CONST char *); - -#if 1 /* NCURSES_TPARM_VARARGS */ -extern NCURSES_EXPORT(char *) tparm (NCURSES_CONST char *, ...); /* special */ -#else -extern NCURSES_EXPORT(char *) tparm (NCURSES_CONST char *, long,long,long,long,long,long,long,long,long); /* special */ -extern NCURSES_EXPORT(char *) tparm_varargs (NCURSES_CONST char *, ...); /* special */ -#endif - -extern NCURSES_EXPORT(char *) tiparm (const char *, ...); /* special */ - -#endif /* __NCURSES_H */ - -/* termcap database emulation (XPG4 uses const only for 2nd param of tgetent) */ -#if !defined(NCURSES_TERMCAP_H_incl) -extern NCURSES_EXPORT(char *) tgetstr (NCURSES_CONST char *, char **); -extern NCURSES_EXPORT(char *) tgoto (const char *, int, int); -extern NCURSES_EXPORT(int) tgetent (char *, const char *); -extern NCURSES_EXPORT(int) tgetflag (NCURSES_CONST char *); -extern NCURSES_EXPORT(int) tgetnum (NCURSES_CONST char *); -extern NCURSES_EXPORT(int) tputs (const char *, int, int (*)(int)); -#endif /* NCURSES_TERMCAP_H_incl */ - -/* - * Include curses.h before term.h to enable these extensions. - */ -#if defined(NCURSES_SP_FUNCS) && (NCURSES_SP_FUNCS != 0) - -extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(tigetstr) (SCREEN*, NCURSES_CONST char *); -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(putp) (SCREEN*, const char *); -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(tigetflag) (SCREEN*, NCURSES_CONST char *); -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(tigetnum) (SCREEN*, NCURSES_CONST char *); - -#if 1 /* NCURSES_TPARM_VARARGS */ -extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(tparm) (SCREEN*, NCURSES_CONST char *, ...); /* special */ -#else -extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(tparm) (SCREEN*, NCURSES_CONST char *, long,long,long,long,long,long,long,long,long); /* special */ -extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(tparm_varargs) (SCREEN*, NCURSES_CONST char *, ...); /* special */ -#endif - -/* termcap database emulation (XPG4 uses const only for 2nd param of tgetent) */ -extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(tgetstr) (SCREEN*, NCURSES_CONST char *, char **); -extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(tgoto) (SCREEN*, const char *, int, int); -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(tgetent) (SCREEN*, char *, const char *); -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(tgetflag) (SCREEN*, NCURSES_CONST char *); -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(tgetnum) (SCREEN*, NCURSES_CONST char *); -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(tputs) (SCREEN*, const char *, int, NCURSES_SP_OUTC); - -extern NCURSES_EXPORT(TERMINAL *) NCURSES_SP_NAME(set_curterm) (SCREEN*, TERMINAL *); -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(del_curterm) (SCREEN*, TERMINAL *); - -extern NCURSES_EXPORT(int) NCURSES_SP_NAME(restartterm) (SCREEN*, NCURSES_CONST char *, int, int *); -#endif /* NCURSES_SP_FUNCS */ - -#ifdef __cplusplus -} -#endif - -#endif /* NCURSES_TERM_H_incl */ diff --git a/windows/ncurses/include/ncurses/term_entry.h b/windows/ncurses/include/ncurses/term_entry.h deleted file mode 100644 index 1610438e3..000000000 --- a/windows/ncurses/include/ncurses/term_entry.h +++ /dev/null @@ -1,174 +0,0 @@ -/**************************************************************************** - * Copyright (c) 1998-2008,2009 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/**************************************************************************** - * Author: Zeyd M. Ben-Halim 1992,1995 * - * and: Eric S. Raymond * - * and: Thomas E. Dickey 1998-on * - ****************************************************************************/ - -/* $Id: term_entry.h,v 1.37 2009/07/11 16:52:29 tom Exp $ */ - -/* - * term_entry.h -- interface to entry-manipulation code - */ - -#ifndef NCURSES_TERM_ENTRY_H_incl -#define NCURSES_TERM_ENTRY_H_incl 1 - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#define MAX_USES 32 -#define MAX_CROSSLINKS 16 - -typedef struct entry { - TERMTYPE tterm; - unsigned nuses; - struct - { - char *name; - struct entry *link; - long line; - } - uses[MAX_USES]; - int ncrosslinks; - struct entry *crosslinks[MAX_CROSSLINKS]; - long cstart, cend; - long startline; - struct entry *next; - struct entry *last; -} -ENTRY; - -#if NCURSES_XNAMES -#define NUM_BOOLEANS(tp) (tp)->num_Booleans -#define NUM_NUMBERS(tp) (tp)->num_Numbers -#define NUM_STRINGS(tp) (tp)->num_Strings -#define EXT_NAMES(tp,i,limit,index,table) (i >= limit) ? tp->ext_Names[index] : table[i] -#else -#define NUM_BOOLEANS(tp) BOOLCOUNT -#define NUM_NUMBERS(tp) NUMCOUNT -#define NUM_STRINGS(tp) STRCOUNT -#define EXT_NAMES(tp,i,limit,index,table) table[i] -#endif - -#define NUM_EXT_NAMES(tp) (unsigned) ((tp)->ext_Booleans + (tp)->ext_Numbers + (tp)->ext_Strings) - -#define for_each_boolean(n,tp) for(n = 0; n < NUM_BOOLEANS(tp); n++) -#define for_each_number(n,tp) for(n = 0; n < NUM_NUMBERS(tp); n++) -#define for_each_string(n,tp) for(n = 0; n < NUM_STRINGS(tp); n++) - -#if NCURSES_XNAMES -#define for_each_ext_boolean(n,tp) for(n = BOOLCOUNT; n < NUM_BOOLEANS(tp); n++) -#define for_each_ext_number(n,tp) for(n = NUMCOUNT; n < NUM_NUMBERS(tp); n++) -#define for_each_ext_string(n,tp) for(n = STRCOUNT; n < NUM_STRINGS(tp); n++) -#endif - -#define ExtBoolname(tp,i,names) EXT_NAMES(tp, i, BOOLCOUNT, (i - (tp->num_Booleans - tp->ext_Booleans)), names) -#define ExtNumname(tp,i,names) EXT_NAMES(tp, i, NUMCOUNT, (i - (tp->num_Numbers - tp->ext_Numbers)) + tp->ext_Booleans, names) -#define ExtStrname(tp,i,names) EXT_NAMES(tp, i, STRCOUNT, (i - (tp->num_Strings - tp->ext_Strings)) + (tp->ext_Numbers + tp->ext_Booleans), names) - -extern NCURSES_EXPORT_VAR(ENTRY *) _nc_head; -extern NCURSES_EXPORT_VAR(ENTRY *) _nc_tail; -#define for_entry_list(qp) for (qp = _nc_head; qp; qp = qp->next) - -#define MAX_LINE 132 - -#define NULLHOOK (bool(*)(ENTRY *))0 - -/* - * Note that WANTED and PRESENT are not simple inverses! If a capability - * has been explicitly cancelled, it's not considered WANTED. - */ -#define WANTED(s) ((s) == ABSENT_STRING) -#define PRESENT(s) (((s) != ABSENT_STRING) && ((s) != CANCELLED_STRING)) - -#define ANDMISSING(p,q) \ - {if (PRESENT(p) && !PRESENT(q)) _nc_warning(#p " but no " #q);} - -#define PAIRED(p,q) \ - { \ - if (PRESENT(q) && !PRESENT(p)) \ - _nc_warning(#q " but no " #p); \ - if (PRESENT(p) && !PRESENT(q)) \ - _nc_warning(#p " but no " #q); \ - } - -/* alloc_entry.c: elementary allocation code */ -extern NCURSES_EXPORT(ENTRY *) _nc_copy_entry (ENTRY *oldp); -extern NCURSES_EXPORT(char *) _nc_save_str (const char *const); -extern NCURSES_EXPORT(void) _nc_init_entry (TERMTYPE *const); -extern NCURSES_EXPORT(void) _nc_merge_entry (TERMTYPE *const, TERMTYPE *const); -extern NCURSES_EXPORT(void) _nc_wrap_entry (ENTRY *const, bool); - -/* alloc_ttype.c: elementary allocation code */ -extern NCURSES_EXPORT(void) _nc_align_termtype (TERMTYPE *, TERMTYPE *); -extern NCURSES_EXPORT(void) _nc_copy_termtype (TERMTYPE *, TERMTYPE *); - -/* free_ttype.c: elementary allocation code */ -extern NCURSES_EXPORT(void) _nc_free_termtype (TERMTYPE *); - -/* lib_acs.c */ -extern NCURSES_EXPORT(void) _nc_init_acs (void); /* corresponds to traditional 'init_acs()' */ - -/* lib_termcap.c: trim sgr0 string for termcap users */ -extern NCURSES_EXPORT(char *) _nc_trim_sgr0 (TERMTYPE *); - -/* parse_entry.c: entry-parsing code */ -#if NCURSES_XNAMES -extern NCURSES_EXPORT_VAR(bool) _nc_user_definable; -extern NCURSES_EXPORT_VAR(bool) _nc_disable_period; -#endif -extern NCURSES_EXPORT(int) _nc_parse_entry (ENTRY *, int, bool); -extern NCURSES_EXPORT(int) _nc_capcmp (const char *, const char *); - -/* write_entry.c: writing an entry to the file system */ -extern NCURSES_EXPORT(void) _nc_set_writedir (char *); -extern NCURSES_EXPORT(void) _nc_write_entry (TERMTYPE *const); - -/* comp_parse.c: entry list handling */ -extern NCURSES_EXPORT(void) _nc_read_entry_source (FILE*, char*, int, bool, bool (*)(ENTRY*)); -extern NCURSES_EXPORT(bool) _nc_entry_match (char *, char *); -extern NCURSES_EXPORT(int) _nc_resolve_uses (bool); /* obs 20040705 */ -extern NCURSES_EXPORT(int) _nc_resolve_uses2 (bool, bool); -extern NCURSES_EXPORT(void) _nc_free_entries (ENTRY *); -extern NCURSES_IMPEXP void NCURSES_API (*_nc_check_termtype)(TERMTYPE *); /* obs 20040705 */ -extern NCURSES_IMPEXP void NCURSES_API (*_nc_check_termtype2)(TERMTYPE *, bool); - -/* trace_xnames.c */ -extern NCURSES_EXPORT(void) _nc_trace_xnames (TERMTYPE *); - -#ifdef __cplusplus -} -#endif - -#endif /* NCURSES_TERM_ENTRY_H_incl */ diff --git a/windows/ncurses/include/ncurses/termcap.h b/windows/ncurses/include/ncurses/termcap.h deleted file mode 100644 index a1d81a154..000000000 --- a/windows/ncurses/include/ncurses/termcap.h +++ /dev/null @@ -1,75 +0,0 @@ -/**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/**************************************************************************** - * Author: Zeyd M. Ben-Halim 1992,1995 * - * and: Eric S. Raymond * - ****************************************************************************/ - -/* $Id: termcap.h.in,v 1.16 2001/03/24 21:53:27 tom Exp $ */ - -#ifndef NCURSES_TERMCAP_H_incl -#define NCURSES_TERMCAP_H_incl 1 - -#undef NCURSES_VERSION -#define NCURSES_VERSION "5.9" - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -#include - -#undef NCURSES_CONST -#define NCURSES_CONST /*nothing*/ - -#undef NCURSES_OSPEED -#define NCURSES_OSPEED short - -extern NCURSES_EXPORT_VAR(char) PC; -extern NCURSES_EXPORT_VAR(char *) UP; -extern NCURSES_EXPORT_VAR(char *) BC; -extern NCURSES_EXPORT_VAR(NCURSES_OSPEED) ospeed; - -#if !defined(NCURSES_TERM_H_incl) -extern NCURSES_EXPORT(char *) tgetstr (NCURSES_CONST char *, char **); -extern NCURSES_EXPORT(char *) tgoto (const char *, int, int); -extern NCURSES_EXPORT(int) tgetent (char *, const char *); -extern NCURSES_EXPORT(int) tgetflag (NCURSES_CONST char *); -extern NCURSES_EXPORT(int) tgetnum (NCURSES_CONST char *); -extern NCURSES_EXPORT(int) tputs (const char *, int, int (*)(int)); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* NCURSES_TERMCAP_H_incl */ diff --git a/windows/ncurses/include/ncurses/tic.h b/windows/ncurses/include/ncurses/tic.h deleted file mode 100644 index 28ee3882e..000000000 --- a/windows/ncurses/include/ncurses/tic.h +++ /dev/null @@ -1,346 +0,0 @@ -/**************************************************************************** - * Copyright (c) 1998-2007,2009 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/**************************************************************************** - * Author: Zeyd M. Ben-Halim 1992,1995 * - * and: Eric S. Raymond * - * and: Thomas E. Dickey 1996 on * - ****************************************************************************/ - -/* - * $Id: tic.h,v 1.65 2009/08/08 17:52:46 tom Exp $ - * tic.h - Global variables and structures for the terminfo - * compiler. - */ - -#ifndef __TIC_H -#define __TIC_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include /* for the _tracef() prototype, ERR/OK, bool defs */ - -/* -** The format of compiled terminfo files is as follows: -** -** Header (12 bytes), containing information given below -** Names Section, containing the names of the terminal -** Boolean Section, containing the values of all of the -** boolean capabilities -** A null byte may be inserted here to make -** sure that the Number Section begins on an -** even word boundary. -** Number Section, containing the values of all of the numeric -** capabilities, each as a short integer -** String Section, containing short integer offsets into the -** String Table, one per string capability -** String Table, containing the actual characters of the string -** capabilities. -** -** NOTE that all short integers in the file are stored using VAX/PDP-style -** byte-order, i.e., least-significant byte first. -** -** There is no structure definition here because it would only confuse -** matters. Terminfo format is a raw byte layout, not a structure -** dump. If you happen to be on a little-endian machine with 16-bit -** shorts that requires no padding between short members in a struct, -** then there is a natural C structure that captures the header, but -** not very helpfully. -*/ - -#define MAGIC 0432 /* first two bytes of a compiled entry */ - -#undef BYTE -#define BYTE(p,n) (unsigned char)((p)[n]) - -#define IS_NEG1(p) ((BYTE(p,0) == 0377) && (BYTE(p,1) == 0377)) -#define IS_NEG2(p) ((BYTE(p,0) == 0376) && (BYTE(p,1) == 0377)) -#define LOW_MSB(p) (BYTE(p,0) + 256*BYTE(p,1)) - -#define IS_TIC_MAGIC(p) (LOW_MSB(p) == MAGIC) - -/* - * The "maximum" here is misleading; XSI guarantees minimum values, which a - * given implementation may exceed. - */ -#define MAX_NAME_SIZE 512 /* maximum legal name field size (XSI:127) */ -#define MAX_ENTRY_SIZE 4096 /* maximum legal entry size */ - -/* - * The maximum size of individual name or alias is guaranteed in XSI to be at - * least 14, since that corresponds to the older filename lengths. Newer - * systems allow longer aliases, though not many terminal descriptions are - * written to use them. The MAX_ALIAS symbol is used for warnings. - */ -#if HAVE_LONG_FILE_NAMES -#define MAX_ALIAS 32 /* smaller than POSIX minimum for PATH_MAX */ -#else -#define MAX_ALIAS 14 /* SVr3 filename length */ -#endif - -/* location of user's personal info directory */ -#define PRIVATE_INFO "%s/.terminfo" /* plug getenv("HOME") into %s */ - -/* - * Some traces are designed to be used via tic's verbose option (and similar in - * infocmp and toe) rather than the 'trace()' function. So we use the bits - * above the normal trace() parameter as a debug-level. - */ - -#define MAX_DEBUG_LEVEL 15 -#define DEBUG_LEVEL(n) ((n) << TRACE_SHIFT) - -#define set_trace_level(n) \ - _nc_tracing &= DEBUG_LEVEL(MAX_DEBUG_LEVEL), \ - _nc_tracing |= DEBUG_LEVEL(n) - -#ifdef TRACE -#define DEBUG(n, a) if (_nc_tracing >= DEBUG_LEVEL(n)) _tracef a -#else -#define DEBUG(n, a) /*nothing*/ -#endif - -extern NCURSES_EXPORT_VAR(unsigned) _nc_tracing; -extern NCURSES_EXPORT(void) _nc_tracef (char *, ...) GCC_PRINTFLIKE(1,2); -extern NCURSES_EXPORT(const char *) _nc_visbuf (const char *); -extern NCURSES_EXPORT(const char *) _nc_visbuf2 (int, const char *); - -/* - * These are the types of tokens returned by the scanner. The first - * three are also used in the hash table of capability names. The scanner - * returns one of these values after loading the specifics into the global - * structure curr_token. - */ - -#define BOOLEAN 0 /* Boolean capability */ -#define NUMBER 1 /* Numeric capability */ -#define STRING 2 /* String-valued capability */ -#define CANCEL 3 /* Capability to be cancelled in following tc's */ -#define NAMES 4 /* The names for a terminal type */ -#define UNDEF 5 /* Undefined */ - -#define NO_PUSHBACK -1 /* used in pushtype to indicate no pushback */ - - /* - * The global structure in which the specific parts of a - * scanned token are returned. - * - */ - -struct token -{ - char *tk_name; /* name of capability */ - int tk_valnumber; /* value of capability (if a number) */ - char *tk_valstring; /* value of capability (if a string) */ -}; - -extern NCURSES_EXPORT_VAR(struct token) _nc_curr_token; - - /* - * Offsets to string capabilities, with the corresponding functionkey - * codes. - */ -struct tinfo_fkeys { - unsigned offset; - chtype code; - }; - -#if BROKEN_LINKER - -#define _nc_tinfo_fkeys _nc_tinfo_fkeysf() -extern NCURSES_EXPORT(const struct tinfo_fkeys *) _nc_tinfo_fkeysf (void); - -#else - -extern NCURSES_EXPORT_VAR(const struct tinfo_fkeys) _nc_tinfo_fkeys[]; - -#endif - -typedef short HashValue; - - /* - * The file comp_captab.c contains an array of these structures, one - * per possible capability. These are indexed by a hash table array of - * pointers to the same structures for use by the parser. - */ - -struct name_table_entry -{ - const char *nte_name; /* name to hash on */ - int nte_type; /* BOOLEAN, NUMBER or STRING */ - HashValue nte_index; /* index of associated variable in its array */ - HashValue nte_link; /* index in table of next hash, or -1 */ -}; - - /* - * Use this structure to hide differences between terminfo and termcap - * tables. - */ -typedef struct { - unsigned table_size; - const HashValue *table_data; - HashValue (*hash_of)(const char *); - int (*compare_names)(const char *, const char *); -} HashData; - -struct alias -{ - const char *from; - const char *to; - const char *source; -}; - -extern NCURSES_EXPORT(const struct name_table_entry *) _nc_get_table (bool); -extern NCURSES_EXPORT(const HashData *) _nc_get_hash_info (bool); -extern NCURSES_EXPORT(const HashValue *) _nc_get_hash_table (bool); -extern NCURSES_EXPORT(const struct alias *) _nc_get_alias_table (bool); - -#define NOTFOUND ((struct name_table_entry *) 0) - -/* out-of-band values for representing absent capabilities */ -#define ABSENT_BOOLEAN ((signed char)-1) /* 255 */ -#define ABSENT_NUMERIC (-1) -#define ABSENT_STRING (char *)0 - -/* out-of-band values for representing cancels */ -#define CANCELLED_BOOLEAN ((signed char)-2) /* 254 */ -#define CANCELLED_NUMERIC (-2) -#define CANCELLED_STRING (char *)(-1) - -#define VALID_BOOLEAN(s) ((unsigned char)(s) <= 1) /* reject "-1" */ -#define VALID_NUMERIC(s) ((s) >= 0) -#define VALID_STRING(s) ((s) != CANCELLED_STRING && (s) != ABSENT_STRING) - -/* termcap entries longer than this may break old binaries */ -#define MAX_TERMCAP_LENGTH 1023 - -/* this is a documented limitation of terminfo */ -#define MAX_TERMINFO_LENGTH 4096 - -#ifndef TERMINFO -#define TERMINFO "/usr/share/terminfo" -#endif - -/* access.c */ -extern NCURSES_EXPORT(unsigned) _nc_pathlast (const char *); -extern NCURSES_EXPORT(bool) _nc_is_abs_path (const char *); -extern NCURSES_EXPORT(bool) _nc_is_dir_path (const char *); -extern NCURSES_EXPORT(bool) _nc_is_file_path (const char *); -extern NCURSES_EXPORT(char *) _nc_basename (char *); -extern NCURSES_EXPORT(char *) _nc_rootname (char *); - -/* comp_hash.c: name lookup */ -extern NCURSES_EXPORT(struct name_table_entry const *) _nc_find_entry - (const char *, const HashValue *); -extern NCURSES_EXPORT(struct name_table_entry const *) _nc_find_type_entry - (const char *, int, bool); - -/* comp_scan.c: lexical analysis */ -extern NCURSES_EXPORT(int) _nc_get_token (bool); -extern NCURSES_EXPORT(void) _nc_panic_mode (char); -extern NCURSES_EXPORT(void) _nc_push_token (int); -extern NCURSES_EXPORT(void) _nc_reset_input (FILE *, char *); -extern NCURSES_EXPORT_VAR(int) _nc_curr_col; -extern NCURSES_EXPORT_VAR(int) _nc_curr_line; -extern NCURSES_EXPORT_VAR(int) _nc_syntax; -extern NCURSES_EXPORT_VAR(long) _nc_comment_end; -extern NCURSES_EXPORT_VAR(long) _nc_comment_start; -extern NCURSES_EXPORT_VAR(long) _nc_curr_file_pos; -extern NCURSES_EXPORT_VAR(long) _nc_start_line; -#define SYN_TERMINFO 0 -#define SYN_TERMCAP 1 - -/* comp_error.c: warning & abort messages */ -extern NCURSES_EXPORT(const char *) _nc_get_source (void); -extern NCURSES_EXPORT(void) _nc_err_abort (const char *const,...) GCC_PRINTFLIKE(1,2) GCC_NORETURN; -extern NCURSES_EXPORT(void) _nc_get_type (char *name); -extern NCURSES_EXPORT(void) _nc_set_source (const char *const); -extern NCURSES_EXPORT(void) _nc_set_type (const char *const); -extern NCURSES_EXPORT(void) _nc_syserr_abort (const char *const,...) GCC_PRINTFLIKE(1,2) GCC_NORETURN; -extern NCURSES_EXPORT(void) _nc_warning (const char *const,...) GCC_PRINTFLIKE(1,2); -extern NCURSES_EXPORT_VAR(bool) _nc_suppress_warnings; - -/* comp_expand.c: expand string into readable form */ -extern NCURSES_EXPORT(char *) _nc_tic_expand (const char *, bool, int); - -/* comp_scan.c: decode string from readable form */ -extern NCURSES_EXPORT(int) _nc_trans_string (char *, char *); - -/* captoinfo.c: capability conversion */ -extern NCURSES_EXPORT(char *) _nc_captoinfo (const char *, const char *, int const); -extern NCURSES_EXPORT(char *) _nc_infotocap (const char *, const char *, int const); - -/* home_terminfo.c */ -extern NCURSES_EXPORT(char *) _nc_home_terminfo (void); - -/* lib_tparm.c */ -#define NUM_PARM 9 - -extern NCURSES_EXPORT_VAR(int) _nc_tparm_err; - -extern NCURSES_EXPORT(int) _nc_tparm_analyze(const char *, char **, int *); - -/* lib_tputs.c */ -extern NCURSES_EXPORT_VAR(int) _nc_nulls_sent; /* Add one for every null sent */ - -/* comp_main.c: compiler main */ -extern const char * _nc_progname; - -/* db_iterator.c */ -typedef enum { - dbdTIC = 0, -#if USE_DATABASE - dbdEnvOnce, - dbdHome, - dbdEnvList, - dbdCfgList, - dbdCfgOnce, -#endif -#if USE_TERMCAP - dbdEnvOnce2, - dbdEnvList2, - dbdCfgList2, -#endif - dbdLAST -} DBDIRS; - -extern NCURSES_EXPORT(const char *) _nc_next_db(DBDIRS *, int *); -extern NCURSES_EXPORT(const char *) _nc_tic_dir (const char *); -extern NCURSES_EXPORT(void) _nc_first_db(DBDIRS *, int *); -extern NCURSES_EXPORT(void) _nc_last_db(void); - -/* write_entry.c */ -extern NCURSES_EXPORT(int) _nc_tic_written (void); - -#ifdef __cplusplus -} -#endif - -#endif /* __TIC_H */ diff --git a/windows/ncurses/include/ncurses/unctrl.h b/windows/ncurses/include/ncurses/unctrl.h deleted file mode 100644 index 318de7b57..000000000 --- a/windows/ncurses/include/ncurses/unctrl.h +++ /dev/null @@ -1,67 +0,0 @@ -/**************************************************************************** - * Copyright (c) 1998-2008,2009 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/**************************************************************************** - * Author: Zeyd M. Ben-Halim 1992,1995 * - * and: Eric S. Raymond * - ****************************************************************************/ - -/* - * unctrl.h - * - * Display a printable version of a control character. - * Control characters are displayed in caret notation (^x), DELETE is displayed - * as ^?. Printable characters are displayed as is. - */ - -/* $Id: unctrl.h.in,v 1.11 2009/04/18 21:00:52 tom Exp $ */ - -#ifndef NCURSES_UNCTRL_H_incl -#define NCURSES_UNCTRL_H_incl 1 - -#undef NCURSES_VERSION -#define NCURSES_VERSION "5.9" - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#undef unctrl -NCURSES_EXPORT(NCURSES_CONST char *) unctrl (chtype); - -#if 1 -NCURSES_EXPORT(NCURSES_CONST char *) NCURSES_SP_NAME(unctrl) (SCREEN*, chtype); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* NCURSES_UNCTRL_H_incl */ diff --git a/windows/ncurses/lib/Win32/libgcc_s_sjlj-1.dll b/windows/ncurses/lib/Win32/libgcc_s_sjlj-1.dll deleted file mode 100644 index 2f0a309f2e8ed2fbeb58b36257f90aa6b0b5a7a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 88085 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 diff --git a/windows/ncurses/lib/Win32/wform.lib b/windows/ncurses/lib/Win32/wform.lib deleted file mode 100644 index 8e36351eb23e086034ddc59c2bcaae428bc60bab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20764 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 diff --git a/windows/ncurses/lib/Win32/wmenu.lib b/windows/ncurses/lib/Win32/wmenu.lib deleted file mode 100644 index 1b129ce6314837d4d1f6dbf802e4f00dba9fe08b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17014 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 acwZU%wsnztR)M1ssLONA;ol1L>heGA`A&lX diff --git a/windows/ncurses/lib/Win32/wncurses.dll b/windows/ncurses/lib/Win32/wncurses.dll deleted file mode 100644 index f252bd22851e28218db7357b43dae7cefb51ca8e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 432882 zcmeFa3wTu3)jvFw3}Jx5Gs>tzBaU^{q(qu|jcrDvjwV3Vs8J%KqS6+p6j3S8V5}h* z&kS%p4#X<0y;v``t$l6(;tlYc8zg{AF}`YqifFCQVL&5jxK-x+{q{a*G6@Oz`oDbt z?|D8R&789@Yp=c5+H0-7_T^l9ZIdnAX0ti)e=23Ot;R3^1;yXP|7k$>Q76B6leJ1FtNj6)heT40)7k@O>cFZu_{-bTSZMK|KN7=KExBVWN9W~5m^Vn=&{BLvP z{}sfxXO4Kzl6c#ZLj1+Qc_@#UbN(|&^b0j*Jyu|S{1ZQ$9JW_W_%h6vaEau>{{)BG zs=haPmPjocX3HHUJBYsY5V0ZtO$gsq6GmS2cjylhVqeppkd{DKVFmr?`&HKDHonA z@bj`9Xe-KX8>HO)o95p3W1Hj+cw{R=`Hv1McOk+2|Nn-jz*KcdZl}Z7fD(y@UuD}g zhfixyoZg*fi*5PCy=`C4`NI^)vv<)30*H zx+1e5wXOJaPOL>)nu7vr!tURqpZ)SNU(NXg)03l{&{hJVQtzlc94``v*4?8#eQXmN ziM2#NeDnc4sC%=N=v&A`;ggBj=fBLhi3a00eR{nAU@KPBPos>fd6vWLKhjC@J26c9g@XFY6d&#kMHX4yJmS z6UXog`c>}Ea-V|&tX2D*`c+QN<4bK)cevDH?4?Ak4^@AQQJzYr;ww?X_9$rzA}5}G z2PAIMI>Hw`N(wXS5hQ8tYSIzddWWKqiFJi{<0aJ<*t*~gt=O07S)Og{9LCaw)H#fx z_~dWt97ekFdGRoIaR9MiBB70uK%!}}Ac65cKF7nS+t?Gg_p3P|m6JaL5Q``7L2Jer z2U97F3qNJTHYT8sL)Nk3CoxmtMGQz2<24k~dgCvjffpO)L;L$Qtz)Y87NjKBr5zi6 zZugu>r70-kTN6KpuxYhEC&97`yZY5fSvC+Ya z#>-ObUi%$q5tKH==OCCHzD}h828@lZ1&sIto4+ghih97V#16>!#3fr~>sFP!WXoVp zTjXw0@=mlh5WlNT{05+X+2G0V{yUZOcTqslo7jJt@T?Zc_Ej>Iv`HT){(w6ARUZrN zg;7?@HyJ6CHlu%AKNMtQ|IPqZf$j;1qDy#F)9{QJOekq72Bo4BlGbM2gIo~GJB90+qgez1-(boP@&anmi21_;aU&q8t&f#POT6Y^dc*zT5O@54eR< zQwBkhs>ap=_8mJH1NB8#z|chYam3{)uNty4SUTQ z`dnX7j3@nhme(Ci)xD{(Gq6s%_a1iAu&eu0k%YRYPzY>b-NJS8>Gp!Qz-tRn*XN$+ zP`^%vPbzpn@OIdpJXSCLy_!meM;Ck$_&hRPZMO$rizLw%ClLcEt1$`Ut%(I1$(MQifP5oz{#!qZ;Wz~&dJvc*YuE`0-QZ+uc)9zpIZ}D#l6yKvP zZ&zFG_U^#G$md{4yFR)CHIpm+Ey*5>P^SJ8@>QiY&#MN`xv^d??5nKH*BgXbY|+|~ z>e6lCcH~6ui=Y6ISaDOiZJfGrI(5-c%jwfDbpIGjz1OSI`;pLDY zmtGzt93?tu8059J;LX53B{l;7o|fm+Ykieq(E{*zxh!-(3$+)#6?jdFZN;DLgs~4#rZ-MPXllpa(t4SML1{ls(GjqKrddQAOcx zsN{eN`${lSJg8Kv_1O2~*BN)z%R%LiI~K^NAnH1y4oXqBgfO&r-PIUyy{be#fE?&l zq9tsh7X5Q9M)v^6r$oPk4}g-jXt&bm(WlIet=EJ3igpXq0m-ecMY%j}uU>t&E#ag* zmHP_yDKqq%d~H8u$xF7P=^(gj?};(HNS`~*7I$2y7vHVzSC*=VwZPx4yUxRl7mr1H-g$6C?15}$c?-ZRD_hidhrI*M#k%T0jXNfwnZjD? zDi?}7P|c~%^*QYLr!{pi`$u+MMy&U%4 zNBVecoN2+;Hu$W zdlxCW+V;el{X+WP7~A{7DWd2q!jBgn!AL9863VirfMNWZa%R# ziH>W3CwqcQjXty4Iz3Iwqp+$TLXdz{rbNHw@DkR|ALEkFx1V zfD&>B0Iy(-mTgm-@2F;*Y-#B=Xi0y9eE@b3vX+piY`yXocy*Y$K}Z9wT6ZKTIXduW zc!b*G(cPGm?$&D1v|SB4?14R+v-SAtXOZ@sov$VN4`jQF<0B0Q1_%#?7zPy(4)kk1a5uRlB4K*BKZL(=QYw- z+gZ?#*;0#Ldq2>#@HD-&kuKy(1)YJp9Dqy7+O`WP?v;+;JfoCZx54ea$T276cCQ4L{@m;ZKH>$Ys9QdATB7iEjC zVg@E^fS`b;35hn&!dURHH~x$tt-C*Cm3w=TYK-H+UMxhtC43B(!@o7isGUPARG^|ol0~q%AjAlu~hg4**`IwT9EGz z|5<6CQXN7UAnMA}Q5?Y_fqy5$Aya0;W+FWw>K#8E@A-N$r&DYBWE>FLLtNl>`UaHKdeJo-I?3+uzh`js={rHye% zP`?-$&(DcF8Zo5x+?sKw>NrGeXbRnOVAqS7QRY8P3jx~&!a34-ECH748fQD@QR+h) zqasLeG5l(Jv8B?drJDFpvi1XQ7i79%ySC5&UctVC4Y4h8&vG(dS^7Bhp^M_xC)whj zrnut?yoo8+ebH>2whI%acj{(?14Z$?1)`bDXGrM!Mfvg46>&!skaNWge=X;OL?lyX z))bq4mQ)+0=ju+E`Z-mlE7A(`%K5{3q-u(l{+Hw@+Ghn@}WxInomNTG5`Px_7-o}543EtQCv0I8-8edCc>Ee{`5j_YOC?nPtecbwy^STk67#V8P zwrdAaSy`Eibt&cVCbz*NyrS*Zc8};$R_@Ubz_P4NDdl@m=@V4yVWmuYw(M&y?CZ)I zzG|)1mv|7qH&m4n3fH(S+n#bCV%tHR5-WoZX{bT&+VD@HKT^le8uJyRALy++GEG@E zTs<&CS#^0<2nmHsv>T3iM9ZI;I+E5LfUMHZi`=I*E~ya70{23Ktc8f z6AScDS@|WI-l>%L6!n7XBX$|%DXvn@5dq?FOk~;u*r?+}>gBFrC~$RQ{m9V7t0ySY zb?}tn9)`5z{Vin6U>(v=YI$b&oVa5w@foKyxBhz1flxs;9>K$L4fQ926hJgGO7e8# zlnG%)WQ8VzV9TC|2#|r=8%2~J&H<}c%#^)?qe#gIYw+U>1?B?g()VCtNVVp#z-o_I zzuc|g=wSAyR z=*Pq_vuloLEGc+XS@t7h^M*h>q+On+ETgV4#sYs!Usj7Q`;=F&vPHX;=-Z-eQ?k^x zcF3TQohnqCd(c}!T73%VFO+-sR@;;o`TY?1=OA+6yoVYkQ{=tS8|zKI@!lxV)f9R! z3g>1B{fG?^k!?;X^5fzzDe_A&8xtK4R|GaL^ed}oa8zRX!N%TtR-}7d|0B^w*^$@} z*wNwa4JLDejdh!pRh6t*k&|4Te#EOIxsp=LH3RU*LzI-2uS0a(z!b>sq*fCtgF(K2 z0-8es4PTcjoW^q)1=L!{90zS96v)IWg|%lu&L%`op&%;J|G@Zx5IgW=W6_`d6}JE9 zu{_#-73swnz33TIaO4^&F(tp3EYR!d^!usMvJDHu8LppJiwgc*YB znP7MU81e&pC`&hjHjtVeV=W%i<8cng;~a77&>Jz3WQS|FR zJM;MQeRf7$tHiz!UeVHoZ_xVeOymlTivBj{b(B*Uv9z!;WtNTkm?Ko!7^pC!49Vzc zV+@X+P*Zg%bG5W{|rjZ6c*{c}*A>47E&yIYf_)VlbBeq_8imKt9@+$NSrtb*6oBqAa^J zq<#4=feo-P=P+$>`@&`WenYsRuYNzff~me`SMtcfybKBa0~jpQq(Qlz^ZjpXQ1X#EDF^ur)7yL;Go*4&IvcWzJ_Td-Fhld$ZcKH(Xymti3sb z;0D+mVS~P*y&2nA|NoS|ky`oxyY?opPyYz+m=jMO{~!w0$}pDU{-Apih;hlj9K zcho{e_3#tYCOMFkBXTAytI$k*#<)}{(7n(R(yq^8uPU*ZjWZJ&*2VfQoB)KQqCcj} z<$R;Xjs>0AmPoHrg(S?s060D)H3_rc4swgOzr79waTqkxs{dgBjp4{33uTwx;~tvRd}wup&fg1w0V3G>B^2v<@ z;``EHDMZLRh=$8anxkR%^&31|YtedbGvk$J!%B2JIw~8V=GLa6@qcia;0B}ufelEB zwkT1AC2ZPcL`5e%w9C+onp^xkL7F@yV}2V_>vC*0mHsWsV`cnlvIl~p!4OT(3AERL zPoJExI}q1@P#+FX=Y~HxEoBSZSOoH`VdLB-254axuX~fNz@^Kxt7}~-pI7%V7>d?h z=z|Sa`j$9R^$|qK38Lh6DHC#Un7ZDJ3Cm^ZuTcRyi+&hq;R!So-84LSkqmszlz*}Q z3t5kHo&>s8Bc3(vQ7`vV0Zk-SX;=t*Bmq=qAb$Fw1?pu1u0_od1snq)+`s}{jGsAZ z_W80tL(j8Bfu5)PV=zt@V03@BD6nHdfv-OmC{m{9iUMB_DDV$ifSP301p;qrg^M)T;)S215T(p&OWJtTf(fY3}dh@luk(j66fRNQSIW^^2 zYA=Ll%4ev{ZNb|F<>-P`K;6VWztl%+V;MknYo!GU5J6@}hBSmzwQF-0zJ61tu$9ZfP3K_b;l&H3u#w4KsD@`nuxWt`b)SzJp#J5ELC?t_74T@dz6*KMseTRKasrzcg0@%W006)cM%~M%KTF-|6iZ@~o-D@ZlFKamN@PdP z#U7I@(*tFLMFH-2XUAz!yvM-8K#4m#%EsE&HM!W%-UNa=Kol%{gmacujrF&*3lgUH zAWHp2`79#c#JW75l~wq!CJWmVg}?omT^gq^-l;#c! zVxForcj{x5RX1bD*4^3IKO5q<&|#s#*L4txyI@-&UV%+`%(>%elOEU?1-e)K`}SU} z*M+bF!CCL{r;<;wH4TFCkIqbcBgNqhix~Jd?KR^5h@nR7C2Zb zwjE>HHi*7y(}X=cG&vn#1;3r3v0GRF3e^~EsdMh>*2J^cop>1Xp_kEW=2{@QQi-)S z=XI%%1b)(9ewc;_eA4UAkDxm3rIb9m{%y&}49Ev;(T&u{Pd>q>cPg2pRzf8*tKcJ0}D0Hvv6{(WgS{<0>kqNaAX z4?DrNbG`VRSa4G|u+%yzYCt-(l-bi)J>i*?RDvKTB%#FJcgEM8jl#RYc@v^+yqJE^l;0|(4lchlfY>~cDh!)b z19ey%+ah)?SJ0KlLUT2i38NfPq1FV}eU;cF6jPXFrTO!TPf%`@cw9)X5PfKtdcFm@ zm<6+~wJPOe$F=?fWnb4RJusG~=7t9QzJ`~$372V=dO(Ri1oDXOW+eclH1}$|fk#k3 zn|uxIR^q21IWWUlsw~Aa2}*V;OO6sHHwU&tSjv^96fIfeE5d@It^j)sJfn+lbkW=R z3CjR(sT9Z7S-#Q{BdUF+*oje!RaBtEnMErRt_5}KXN1&x2T}AYOK1oDVtoplH14Ta zny<-$nuO;OFK()ts~_cW>40LfCB@#W?)nmCWp$%H@OGp}X`bfjbTpzqu-cCXYJmlI zSS`I4zab6oB&Qs#Y_HpZ^{QGx!Q2G2M#~NjDqi~s1PSlhJp|?D#iJKnfnaJJ*sB=7 znPSFV>~G9oLPC=b=#mx?-T2kxAe255j(gyJs2em&wQ~V}O_hi}kNTC|8O=@0K@A(0 z(I{S>oK(yZs{H!)P~*XacKx?ea(*$j8kjUuut$kU@frYG>+1Zyp~n3O?aJa-QKD<& zv1H)FPyke}o2l(@-9Exp1^dYhCAtRXwEg|lRxoW>!+yKEB?aEi(|<{AW#1flyZ$8Y z_W}b<@VsDTIcIuqN{Vqjh6k{864}aPDnf9ckMD^`j0L`kDc4?Q6{ym>&B2EC7*(zvPuS>>zi<^s>c>*G zb_T`V2txo6ag31fDjjrCxk zberBYPl+tYIPiu72erM*WgVE@E0?$Ptqt#&iucNPt&=*kn66$4a8#P##Z#dju3N3| zoMsQYgzTbUBe8T(iiD+WcTNbJ26ZmXQleNefjZdhufGj_FB*@^Xw-Le%dB7T!O+E~ z6GsR;`AU@N?^qCSA0A)EBgg~N0Ai8WUC?uLOX>J(Y!!U>*Lx7O1J-EX8yYs-uC+DK z2J=I$`;`z75Dak}lvFfRgzANz<-X!g!*N^%C}BfC8ZX#{<_pj(q5w3fIE)%dvqD)# zn`BHU2pj6W(1GqD(YOilGP1Qj#ES?O@C1za=FU=qnc7lgP)nIbtqusxQLLaF-4F#s z!+LDS1sp*LWTf{aVlxQH2!L)rl;A-Oq+&c^jzTv$b0EDe22vrM&*#LpM)chQ|4)$) zCiaOnw1bT8V(3~gnf{${{*G9o55GgB?Hej)u! zIfk%itv^Uf76M!|N@-p%eW6SjL#d$q-2X_ki$R7Mssc|1* zp2eKpe$3&iRCSF<1gcE_ayuaF^1Ml{I4#8azzy14q1L1l-4ekD;;xBJ^f(q?q^}VD z=nbE*H_*_%3UD}t(WJG7PD|NgTtc)Y(B{zKf$8`dI zJcODM{@aW^%p6>Z;W{unr3i!$JLCp9?QSPjqSVFe;dp)q=e8+$XARb53p5!b51L~y|LIvvl2rl3TtQlgbr^RpzWq4^JT-TcD*c-|7F z`NA9>JLqo4)RSS-+7~b#{W^v1#qrDk9WD=IuR z!P(1(d7u$pCx%U4fO54ZbHV@KpvN8_F>!iOi9X1_ph#GWS2+W3MLyQCB?v*TFQV%s z^%~+4LBQ!PbJ@e^=w&4+7e=Io0TA#+#t-|?;Sw_+L;Ew}?ICnw{P-v0d^4Ot)I8Oy zLI`+4p&Gk!y*WNZr%?Y?uxua*f`j=KBUfcAtVBY zTal%~$3GU6xjvzk;wZv6@E=jfi+&9n|0g|B|J%p^P545+@pLVbsd&$vH-f)1pZdLT zU$<3m<|k%3F%y;X5fdI{(n&$<2e)X*@`J-~`qzIC{>;Od7qp@px9~4|mII@Id?y3{ zZ&Y3Y19wJ3-s43{PIO^Z6s=p){iA3%E~K`h9F?nh5bMXri+=GpbqC>>qZ<{FF)w+9U$NLj z7_3h?NXs?z=#A4IcjJGT2J!xj=uW9c??RNPJ??Waks!QF{7UE25}1dvyrHfs%=BMC zue3ZhV5w*j{-pCCIYNHb_Cf0d4Z&ZsP0kuEd~V!pRsi8me+q>iU~Jm|?T4RLy#II= z_<>*!Fq!e4FL-(-ozcU&4@&@SJ!y%O)$Tl?YtoR}D!`r@16zsPK4 zDEvQp|6Aif{>b<*0rU*I_ru@v-=MO=0eKdXVNA&d+!-NkOP@`7`3I6*`GQ;sgCXD< z)EF*Bj0H@g;xB?wayDc<^^s6$CPQ#?OzfuscL$fZnI`O`B`XAX^Nf+Z%>WZco&M;M z^}U1EKjCC^elO~OGk(4Eec8*Q_|*ZJQhxv2@^+UA`Y`e~8_nQKoGqvl86_A>a)z4vv8w(rnAP<^kNVB<4N1u1q3At%NPLetzDJp$4@2+7cm8MT z{iou?%S$g*#pdJjkBIMGCg=hBFFX$9gnWNX{dX9AHv{s}{68YT zuW`}@QVc=gS^>R}zDI<2*Wuy4J^bESy@Y8e-8A5DXtH}5 z_%r@|#t~L4o-wP*1%~(f<1?VX8IsG~v6h&BnEHdyx90usP<|QXZ;%7g^bd?nz*KhJ zd^hI@=zlt1WcB;Lzl+(P6>d!L-ynSkEC0pD!So9o5g&QEiX+p)sK^lRMO38*n#S$TyFG-GMFj~;}>z@p2F2Q!Qkq?fQv`l!tOUNp6)m&f3;oZf;LVy~$!?L&V@&O;d59`i@);W@{JL zZn0H$RhcW|c)}ZYJmC%xgX4RhI9vAo47P|D;N<*+6Z_K02aHF&J2KxNWgZD(>WhKz zoNqPmc$u7w`u+<)+$11gHsObOTzeI7p~f8^(aj^$8QeJV8eWxEG2X5qPLSOmni%^X zUcz?(6l*8AKgKE{^KiA2UcEf5M1SQ(t#g;yl<4CCgOM20B&0y>H-Mo;|Bk;VN{#!u zdak*ZWd->4w=}LHzG8nz!z(YN9E!gvi?dm<-h0lZpM_m?8ni;h`)6XmgNc&3=Tts7 z)a0V#C#orXry3xQViMzu9BH1T=%Q=buc;0OXc(s+

RJTRP1MlVH? z#si}7-O8eJyz#oN=uyK_^8sHs@Z^@0tvLc;^3E)rt1NvNTiI5#W(KYF8XvYxY6_U5 zzOoJt+w0EG?0GB)IeLsaxOGWc`b$0}>^E#^( z7wYGS0-KcRe3oh6M4^!)G%8yNj+73NmbH~-Baw>zUU?-`o!Xm`ql^y#q2v-LFvo*_ zodZV|d#qkdKH@lwUKxW-Ryl};z|iFAGf3e%6-~-VU>BHzB)qdR?X|`Oxbg;^DnX+d zdECjilovW;R_b_(SrorOBeu#PO@`1z7$^+J@t~|8TLXBg9V-!UL+5TWsShkz_z6f($K?4oIvpdK4x}D$!0%># zq}t|)H>M6AJhw=z;YoRv8ALUm(CN3saV{lK=Tq#Qy#3+6v@~v zNQc^#d)!|GBI+xTgUk5-hB&V>iM)=EL6g==oEpUXNbXdZm@%NU97R)bV9it>++DLy ztB!{uKELn7RgQpr(1N5C&!k97aj0N8DA6A1)(geaw!uK;OzF5`3#q~%ZGFHWU;>^vAT1~1^(ANG=8FoO=9u0ozEfvM%s znN^c$z+|Mc1VSR+0x{-5yL6MUU?7^~_a%-;qnxx`Uqs3fDe*lClokUV$Kr%lGJc3! z^88M$P=UzD^6^)Re+60z{Qn9hUgUr`6qJ-3>3PLVlc`7^BnLAT$@8-R&jQb8VnGtU zLKeNsHxpUo0c1l1Td&svw8?##S^*)7D^Z}11d__C>qZ)LPzCp}Vz;?OyaMk+!eRkj zHEoIm&9xH!1)56>^-R3z6l$Eq<#u){)p33|sGhb_qI1Ele$e6q2(Go z_ds0ZEv!J@hRvhGFs?@-+*15{U%@pfi1Uk5w`jRSs~GPCd?vYm1QJUeN!UXb)(I~O zZh^cHky|Fdf}5Z?WyY97gkbkxOphPP^-X|gjUV1Vue~Y9Pn#S+>&5uF{Gj?##`rN= zm@#^gLdqD&083$Bj2GD{>3#6*M5g!ArbPb@g1{RQXe~y`)i4A!z79~qa_@BX!FU{* z(o+yU60Q|5^AxP~cNs;C1&dii`w6v-p)W|t!^VDm=o1dW??a$(ej?X@YOxi(383`9`W`SLzJ+1KP0YL)4j*eV z7k{);+*kEixcAGb0rXY$r}f3cnOd(bFZZ2+3mNcpI<~Mcrc=e2LR5nB#?zUJ>n{K_ zz!>&lU<7{8#3?rMezp9KUo3u?z+p{%h-WiMj>oSZ%?1=W_ zHcUKm;&{6D8A^DSR{;SJZa(DUA+qL)U$YK+{ccr<{#) zU+eCG>?3G8&AucD#wHpAG-cH&(8$65!ATQ$T_#TY8`Kougn|4qfnxssL@=D!aMy`8 z-gt`(F+&qCamd4H>b7R=h<2F}5?*3SP(>oBIGkiZ;Fie7~mlU1A%#VVNzyvQCUwj8|{{G-7T zqM2A$`K?*z_|G)Uj4RL%Skh-2_yXFu%s( z{y+!>Sa#auKw)eBX#Fb0Kz@TSxCFM=^^%vRm{|2~Y{z{p+NF-bb3U(8?@lKPGp5apvNKhjc&+3TIa*puq15TyB@Qnyk;Uq~- zPGEoiRNQ-kuU+_C;;xJ0m2sP1040^Q=F{4S!2b9}_WI*7N49C=yB1W!4W&L?F* zfxWk%s_h5;)$I-)cVghml=)w3yvsVTU=z;u?AZiqw|5FHjbZYqN1>&MV<4+#S@z`d z>OowxR|%D8$-Sz0(I zZ&VWe8qq@zTTR_6no?pv0&LuWt*o4c@{uj#YA87$pNthl5lfuvH;#B4w>3@sLWP&eM7<`|&Cur;1Tiiknps2%ik}aT*M=P%P<-E6D0b zYWv3HelQ$&Jb{OTNn_K3k3^qw9S!K(t*jEacuf`;?c-EV4x9MR-I*Fns-!+7C4RVg z0_PZDe5gMkg{<)K_5Jt-zFu*e%1^UmTWaQmNZwdiT`jJA;Ypzm&>Xh}#65pQQJd~4 z(j8AM;e9wcfwc>Nf>4sM3dvLSYx3bc=*2!g?<_rU3^JC?7!F1Jvz&Ndeqd{D&O|s5 zk@vK=4!D8p8i!<-SmwbsE;$9;<+(4fQ48h?-SiGhnR@9(4u08Ci@g5^1a|2SkH8h7 zTPKzz((4J<`B#_TBnoty1uTI8)h+#u`*Th}6kSj(t)^u>9xa3#UU~$sr))V=8CN&q z&EM6bGS#lB^AI7ycoDTjT67Gv)izJ#{zp(Ll8|S?@~vPIm07AwSt)7@?Psko%P-c- zGm~%P`;lV9fdhQWRbP6XP3fX3CH5HL>i07ap+75P61(J$A@P^kbo|K~KnNo@d7{jY zS9k(zaaw({!xz{k(Or0D-1Q5PI)1NC>;v!UcRI8Z{Z4!-$f4iq(rTRgoo-wuqF?0E zD%_fAEAn)w%GUVL-|O${REYuqB_ERZLkfX4{`&YP$A91Wz&TPuvnPn|Fk&0OdPm@M zgrFvO}5z5A!{FWKvMeZ?hT(R^j}ClClwxvyHzld7`fB>VC;>21lJ9>s>BvcAl%W7bI6@5X~u8dp-kS2ZbUW*zK%~ppE^W4%Ug^CP@s~Y zdW|#ib6AHUMvDG(_nywXy-v&${Cow^;A5#D@&lX>ZQq-Q3Ke3<`#E^WM1y5epw-Bc z1zL^ae&qC`qxj(LXJ|uayR7Wd8QFigvOgcwY8>O=2e3-)MJB>E1F<>V@#xL$7XzdC zG~T||=$P%TZ85;djUd;$n?V-aTc5^02#?f=cLdh z>0~7F{IgR?G7_%LsA8N4%7UI(`CEj>;qJ>Ssc};JvlK~u@k@RotKFY^1zfes`Awo= zFRc@%dxheon+_Zvg=H?z%NEudA;k4NY)f%ekQoQ-DyDnVL)_?v|~5nr`KNw4y|H)L}~(p$#!JWLsjX4S+VDfe$&S zF(6HeLHFE4G4P}@fPgZ3-?OM^PN%v8PcwBsaao~dF`riBY12|Zy^NYP9C{P!!nx%be0@6NLI9Olm5A}OyIpS*y1pxt;P;^iD=$18<8D+5HKF_x zQGUHFkHHD)_P`|Zk_+5d5dM+=j9^1=c)I=@3T^yF;Q%~CkqsP(m%)k%!x1jga|3&E zBgS-xc8x=y?$oYv>eF4g$4;N_)~<2KD|U$Jwld`lTwLRC(VihR7;@m6<3yB>(ZvX^ef#^p7rv$4$6Da6o4m!5vfV#M&rJUc&bPH6$=uHc71Vc~MUB8m?hmBDPw&YMZ=6)i zh0p(8pyt$7q5rdDy^#^7YZpEmx7v+Dl-Uxw$kB)|uW<-(-{h~qtMQW$_AFFzSO4<1 z#8yNo@D+_`2?_;yaqJ-Hp{(yi&$IB78=Ay^8S<07>V$*(llW5deNbL`^5ES(H8L5r;pXYkNF~Kh;J=8wP`Qzza?JIZ0ZTJ82eXKXbYdJ2MZfY z5FiqJY1Ds{Qj7&W)rN_xOSu;})z}(wp`7SY^e;d_AC3Y=`Vw_Mdaiw&^E|^q?0P-LO1*MsGXe3rWiM_3pwy_VsQW zp4qeC6Q=5sJ#!Ced1(=IB^u);Qn(gT_|mtaB@-8Z-%PJ^t1q^oH0CNd7*%I~zJq?5FplRVdAW`-!b1H|)ZM74EE|QSG$YBtib@XNzX6i2 z+DyzXO2>c6qWMRQ{61>&&@fM&sWvvF}%AK<5Z)la5LH_G&cSp&IV`G-EP&&0DO z)54mnBr*FB?8Fzc;ZF=kJg#^RAl{dc^$~9#!1O1cqKa=33R*2?{1Dy%KN!^xztl^A zR5SI-8%a09irKKQ+%yxN3_(B=Bdj?Yi)Gao~#CV}! zzFsyHw3?$Uk+tv z9x^ehz?Y~KUHnA`naq|xcvPpZSk4+EZnMUG|XnP==f{c{jd?Xfad04IkQzuIZ z(ckeALvLP*uJSuRFLA(0&EQGgKRVl{Jhc|2sZj3T1SD|}p)lfok%C$4ZW{Ed5{Z! z7{l?$9vIH+{!Sj;W|`CVt{v$M~yn z79L@=@}Ld96h~d1!I3dnuEd0|7jtZ>O<|O|LnA1p_Pf8s@HZv)Af6F9n4_ySoQU$~ zrBDX(vp?b$!!cKSSe>v9tWV=?UK}o_`h=%pn*Xa927*LRdvZ1LQlG%P4{dx*C}dVHB{K^3ZS5(!GKVNOnOOMUSxr z$?CLG{`D{c-H9l6~YC$mZ1WKL7&^<(X?E=PaqV`Ng9-_KEcp%Y8BN)-CT zrft%L&IVro9cyA1tRn<}X%x>WE^jo~FN9wM?W{x*%fX6h*)$7p;LJEXf`5tmzX7Qp z5Tt^o$jc-beI1ygLe*d>I$!hn1kI{&lZZ*PV*xk&B`R-wCvKI^RpQx5F=aps6?qQ| zZ9zN$;*^UvaF1@?IH`R4jD654HNPX_CqlyE&d4pXa>p>&l%ZV!#$D5C{!-A`P4*40 zL3iShyD-GA!w7;Ld7+lXRpeg}$9!?=V@Q={o!Hh9zaOtA8MMTBjF<783BK97?_~dm zf(_VOjfZsw>u`qJCrTSL@ki=`3THzAjF{6mzQGS43I73yXr{+vlH>IU5jv~& z`4AsvphQ`k#9t;jl-SuI=OF~Bum~_8< z$w2mo%nPaR;eU|TS&>9_Y=6MwxpT`RdaYYq@g*Y`+6-bh?8kS9r`jXi8uph)wvh4XA@x0aLkKft zGMHGEEhjdymiOSag;y!BmSx4KW|f{N14-|Fmh^UyZsG2dL=hRi1^;htRbIW&9>3OJ zdS3Wqel%*GY80vaMl5){^t<6ZN+(3NF`uiZ6`LCNjkx1Yvo30|diU9c2PE=X49(_k zZ7n@7vJ!omq^w-@4|GE9vBL(Alr3*8SzUnQhc8VVbuaDgi!-rkn7wH=fKFk$yZF7 ze?AYItp_j3bL7S3`UP&iY94LUPNbUM0N=!(pBlMZkeJ&j-TgI$BBLkVVeVf4vvTxbsKh_Qi=ByPuu)`VKkD1lS2R{m6xPcNoleub5PmdK~e(J!AjvW7ECgutK@(V30za{b+itCqOY1QY^2~7l$`sLSJ`S*+bDyZqq{Dvn$ z3aiLG6zNo_QyXv0pvo(QRKG@4XINm!>VHLZl)t(`s-GaLGuk?2^>t?T^9QNE1rsJs1h$5% z9;Bg3WDipJVNsXi(4p$e=ryXZsXCNyGf`c?-GeQcBIpTIME+qhwp+hCFYy@qrC*(^ zsd<18bNmaw|Ed^8G}SAU>P3-iP4&t5+eDE~V@o7MyQ;=H$(!z5-PCzLFlp#C1!mP99agE)V->iiE; zrzBk`ExlgiYUx=akRO}v-E7sJFY1<}F6A>*?9G`Y8amG^JV_KTPd6lnN52Ln*GF3w zJfcGIFclgs8GjGE@&(lxnbGfOBZ2!x&D%Z7W#S2+BvUJpu3Xke?pNY5d^1R|uI5D0 z7MYLfco9q=XO_kYGz~G)mp)D+tXG!)6lGR7-DtOA6DGCs4OCibRc!p6QXrTrbpeZf z0<|IDN{tWsn9hEJ4aRncm+Ce1usd_H-oykkfeOx}+#lGVMaoC#(6UT+cQyzNfe9ob zlVF_Syqy0aVqZJxr zp_@u#Ay`Si3rfM0< zw*AFs3o;<;isXraw&nL(lWYVNjA#98kIT^CIe_ts0MvncP3is6C@;d=CTMZ!i!fLeFc=8|-4ib}yg?+jw(#xxFD#e$ zNBXmLld%XC7U#gIdf4)%C&9tSl9b4W_gW?B@d$E358RRg@^lSz_7U0VgnH}i8 zl`gjr`zz%4j$&OAHThXO{+|3xdcSX`{Cj~q<=@)t%ilxgpB`%>atx;#;aNDm<&NBd z2?fGGv#aB-{|LNMcRB6~nFg}t*!Kon>n_lGS`#NDwp*g%TO54&9wvkM?1mHHxf}^t zz*|n?&6y0kXG`34zK~K8nFLC!NmcOz33PxiBROdBVNZNqD!oBN><{S})`$x{?CJe3 zhm`Nz(2-HzmM$;*TZ<6LgTMpF>L|B#RfV$~6{qZ=0Lo9|c@3amM0A1BDf-#sOBq;@ z2tb?aw|at$JKBrf(F8?KsV#& zrh~r}f|;0Fy^6dhwAML{EwNp_sT)EBW#hpe9{3<4KrrA8kdMx!mIb^=XUPXgTvpa# z5}jv&xIEF!Ya~pdv0iA8BK=&}`-9kk)5!4~&em?lW@ZmU9%~?PiAzU-?=3ZB0Gfwl zi4GzD=|xC6x1c;H3Dgxnhf6az68>bG*=RK%O_NY}5+WseS@p*;oTN{lMF^hnAz#*} ze4V{J%ZBawcpA^A{;k!Vh(Q7e10Rl*DCkp*)sKqQ{Y6T2BSw<8WD{EJ6g%8WCc^)( z(IRR@g!L*ulRhZ2fUW(W%KY;s+WcF6V%IU)LFjZDm<6#WwrRJ(A5UCji*XojmoDgU0oud zs&$niLgY@@RY6{SO+i;pnV6}o6iejJ(p5?(o@VRnBl2l(oLjp=DE33s%r6%yhQ)&zcdnyU%?AVDCREpg(xfFs#vBr)d|Czs+iUgKfB;CoCvjdsq2 z#b`2k-+_KfVXHAr{el~@4X#+}C((s4cy`8I4>TB4miEfhXBd(>!mtiYtRD~7^OzyR zZM+<<+Q(mRneyV-kr;tS(rVArceU8?gJBwn*ubsK*H`fKKiXP^rSjsFoq^7XlJrua z#-}<1?}o=}TlI0cDdmfPx=P#a7iZuq2&5%^{KT3W7;_-P#F|++)F~cjhUZ}DWrt^I zIlWU{_Q>Vpqmwli`qlWl4D4Clu|Rj+joPDteq!V2*spnYzS2C!f!h%RJqx#K9$#WL zQaMys;1>v(=RQpPeRY0vixwmH$=^>rw;Gh|49-N;w#eenVSMGY_|n_NbEk{k8BD^> z8Nx`nBl0O^1ZyRAA3zm4;GCq-tL^)Yo;%LTt&Nunr-2(!WE9w$_=n6a!;r_qgw4Mb z>@3H3b+nstBzvw8Un#z1Wc)H5cDlsXy4?X^A%p<&QOG`u+4#cV&2Byf@o)^j=5uXl zSuQ)#S(fL;4^pd`U5*EjeONnUvl5#WU=E$)z&}+dix7mBK!EJwFUF36Yx)^PXaI<|7f-(&s znl1^ng}<*a79xC?L(2xmo!Y~E1yh7sRhn;`7693l2iml^jZ@Hq>5nNmGF1-K5LDM? z#Xw$052sW|PR53d6VXB`JPUl$8fDaVIG z<|xgP=>;39rFj4mV&uUORU z(cYmDI#?TM*I?d;(vxiA32|3ZVBPIXsHxNDMJ~Vbv~K=xoHSF{y0HFM9-&W;YX#&1 zLq2O5u1{gAiZpXTD$UnVD`+=nkhtml#pF!`r9>9BO7P2jo2kVaPiB<8Z=Y@pG#;>9<}XgC|w9q)kyn(JmCOg6?>W|)@;Eh`(~uNfPdm? zP!Ec)ng}4uFuho-DMF+eyPowcu=m+hH$LvV4xJ8?i^U7@9j?|-vh=C=aNIrqF5NZ8 zzE7(>7H7&_fnAXvP$Q_-lvo_<_gPm|si$%=)N)`1<_| zr2YLFAi+G0&oF3T0}|JA)u9v!fv3@8x^k1a_e3~4r`b|;C-Fhzs~tGv0U?HYr?=3E z>1ql~1dtE=y75t81JWocU!qqiLN|wJ&F$UDqnBdJ(c8#YnkP8|5{j~HjZDZvf~d2M zw;%vO1L|0X?!}1+D-Dtqj>`j><-WqW>DSJ!witRVH_%z z5TO0k+)*=prA1rt*Q<@g6;OFNbmc%HdzWrXM*DOlF-v{`>0y0(K7I=IVj6*b z`$lcIUJUTZ1YME@-x#T7*(h8fN?=aWfi z`btYk<5xfWl_X^*kaD$jtjLAlo`@AKV2)>sq}Eu*xS9M}miUu*LzY;XE*=a^+$+Zr z+b;P8p%g>_ICZnt$DJ7BEx6z$vJ6r9kGxLCD99u(P%fm(?(c>62)pv^{etGY*kUN~ zUW)w~-<^{#pKX=98MY497vK|hO=T*kF%8o}(+vP_(ntAq4fnWY1)z3GtOURk;DamUhpiAds}6=~M}TNU74qOF+p z5@+6jk&84ygPozJ=|JSJQ?Q)}x%qn8f8nkh_`> z0}7PCgeW4f3_(+DHcd9~VWus8ji4upQfHNJplxccKS(uEe~l8$8@S-}FWh84f|L`& zrfc<3M#@k<#CfP={ddvVG=9O%Z)bIbMmx!)%tm9XJujN;wt3+6_0Ew_gnMTn$Y*zcam?8#$WDHnDKXw)^-LgJm43hzV z;16NqcTrN|CC-pRF@7?2MAU(&ry1Mr2;P~QVWv%fhw_euHcV}!lMOq8Us%Mj8g-PS zneQ<|+1o14T&_Rd?Sibmz>cw=|zR2MiFoL6c->>hPm(65xS}?wf$6tYc5_ z99 zaj{U;YK#^+2|HrpRl`h;Q@Oo9H)ML8d}Ce}%(Mi@8Sa&8=N*#12aS$%+v#JuzM&g& z1g^*%F%=cbs!MKhH1i0)Uiu8PA&e8WNg0@D#eD}Hf`UE+1>~sO`UbuoUAUgVTHBN| zcOg5i{}5CWS%GK7-Oh*?U5y3s=WJo_z*9>c9c74p^3MKCaMfEJzRfMaSNj>v!cJLw4dH61=~Pe;B|T{()#( zf)!|ZADS&02=Ri>6Km-7$ZV0ZvV8twypR~SSO=%GcnUa1MZht}VQ)VOr?f*vFj_|* zlz65lpyFBjts~ET#f-#Rc|bOkP-lq}DW>T+?$0;9Djk7}a z-mY)a<5G&33v)WRO0tWe0v6OxAsojsN_@`PG#dA5x%|L_#(hL@SK`yUV%UKN3EeHZ zoQYPiJKi`(%DaMJDj8{fSB!9PNuU zqD39 zm@61lpWUc(Gf(m3G8=K@RNBXQ%xl5a7=u-2SXeavZ04#yw%D!OolvpHRhdsHhCJQz zOePjoI)|?dIu_dTJ{HnzBY%o2YJ6SkwAlt>fSG_w3Pc2d@2~MBqviY%rLqJt6?JN9 zPO-e=oZnljdkA?dG+0B&q&3O+R)EXgII$Oj##PUm%Xi?v|6lTp+n$jE(0G`c*zVXx zX8;HbLUX?TtN6t@Tc6lZRe(5IcJWBaE^J-@44H<-KkdJnEsvULX6S3|lxb?%-V&@w zgI@eb46k5zj^uk{>&ecQoc1elDR3AG!bf@TJ4>K(+~Q6IL*5#W@BD!?|8kQ)A$lay z0IY|8!<=pU@MAs@%%uv=;3qu7C@@KA!k9bh&=AKWA$%*&?d}R~a8;=)7Wk1wI%{wz z_R(`?x-up5FR|;}Bw~+-0yMZb>Qs~zM9~S+8HAs*y>lnlD*;h$1OYd;lRHCbZMUc5+@>6TfNH=095Uy9{ILXt^6cWC#QEd8OhqlL$LU0bbcuJAWiyJ6mypRtdAN0D~7Kd!~_=% zVhTYu*xUJrU99m8Wt__kFdTybQoW%eF)LDV={GvYH!RS%^X<1|vhZz=37~?joZ9J{ z2H=eWrgJPzM^GY`i7!KTGwa8Y#K4}=b^j;i9|DQ32I4Prx(0zBc}a zg|DF>R;rFb4-NGnY`gZoplj>YwJBlOY*lJp9Xtzk&}fDS{XqT<2ueWT!|@yO9^QG8 zbxyI)H!X{o(qw@>RwNi}+Mamc0A`d$BMX?fUNV4LfjMoM5i?)DJOoUjA=F{4cKJ3a zdZ)I`GLKLKuo$}pzriep_y2Z<$K+73XFY`Q0BBJLX4u7GeMg!4rZ>#Y%49XJRs@0P zkEPqgrkd%{OynHYWv1^Izi$fK6U`0z{b=@^o7riOBSFI7y(#Fju@{Br&fLLZw)kRg5} z`lM@SOUNx_+kk5Z8sw2s(6oVeYAV_Rp#ZD#dJSJt+@+sob7KsSic{2T`m%_)U0fFNjU9w6Ea1=(4Bk(Al; ziq3k8`YL^eJ#&_{(a~~eiL{WYugg?I`!4uw^?NuP%dgJF1wNsADeg?)^-h*%r2~>E z^Cut8FUtJMl>kS2lC-DHS&(9$GoMyL0Lhz>N^cfZhZPw}%!^0(jofBQAW+zNA@)wR z5>)so@j~b*F+yIS%}otWrLpHR?L0S=9n^7^4Q~C>tXSKC)ns)|kO53!f8FtYu`nR- zz977jEMp1s@A%GPQBHu+kpsMf3@3kZ4vS>o<5#2nkV|~*3eM`|Rvy%1klbAk&PCSC z@r#vz>S*Q89xut)7mW7=Xi!c-hJ!`F<0Iu&7SNN{4uCmqiXl{x6hk_^VbkuE-M~vs z$9?I}@<;V}z8<4ILcvT>ANZAFu9l(JQjfbS=Od8wCurX-^a^O-O;rIS+?G_6o-Dht zU=8dq`;AlE>hRilS!^Bm(2Ru}Aiu|!V?$czT~W_wHT-i^!dP6EdkH1DCfQ3oVm`)) zq#thLiI7QK8cRBkGW^Kh#PZxaWcHz6AAsIZa69l~_Rss6j;tt-J*>iw>jS#}<(rxj zLuEfUkJD7*Jv}C%=pu4$@e90h3KcZDA%Tn6tYJ8LY-xKh;+1}%#C~pRG;_oY3ah33 z$^hMCd*f<`*7ut;;KP|a@#e7XIC8c6Usc;6Ig`&92NqsDFr z$+g^s>o_m9@RMnv9#9}57&ys--E0n#fG|g0kV7ybJ`RO%S9|Wk=C8rpyh>Fvvv*MB zE~ef|-lrmRa7s@=-8O*1t-`(OPh^EM7L#nWZ=Q<;zsuRX@Zi{Y%F&O9$#)vpzpcro zt;34r1A#d0ag>WL?xrkyl0GzzcEaeY^~_P{TJo7=F;78_vXPVj1dCJk?nRN@L9g85 zFI+w*@PD!zZa1M4OiKxA`})_8+lYN4*Ti;X6;O@__r9C>(4M%BzqW|{VbyYbLXIi= z*PfWplR40yhzDsJ^5Qy0!)pS<{9LM^_Czy3yPKyLCFm&<{i`I$=bqD?IZ2l^fOiCd zE9F;gri9;b2SBY5Ks7ZXdA(wrwBcE&dz^KCLJB_IVn1`-B{*_2WZp`ubVje?RF-?4 zIxwpOWu$Vk$-I`#CzoQkt1~CqhFoJab8tc(Y)>rY?{C#j6HTx7)i9dgIP>%fU#FU< z#XOyFp8mvBi+NhglbIxd@r@(Ei$p6a0?m2nDb%2oIsjnm{oviLYuNC=f@rq^X+c76 znM<|;o5y*;r1;5imuL!{8{6C$oNL?Mj|V^Jq~0M(v+6#naMvpmx6(r4io`Aa&}Wej z{cBH%WawYOq2y-WReuYZPVYC&?&7eiPEyC248nAqwaB0w6OmcH!4{d~B+d5zX;Tf$ zS~2v%LfPXOpSz#YLbi;u_Mfv)23Z4c;3V7WRr)@|5i;%vjX(Cq$Mf6O%p?9p)O7)C zs%g(jR;YhkeSO@B+4$(3Smcd~xLd)1NJHV}XEY2LHaQXU4qW#(4akVcoaT)vI)3Tj zH=Pqd6w>>aHzM*&_ton50k5*Rxb)H#Uec2XZ1XQ;=JJ&gZ?O#9sm@t1B7;urHG5^Y z=EmQ`Z|@U-%I`G*E~bD1IEL%V0)wD+$Lkha)8gll~k!gVBV<1=@eXGl=b||5Ld^q5TTaetf6t7S&5a{3NaOh{-r+^1;%df8f3}&m0rL^?)m(x|X(YEc-#B+)ZQ3U=*GJ6KCgz|1EUsii9R$$?fgb`Pa zWRiY1luW28Gn==Zkb&eGjupivkYBBSXm(g>zf$Dm3@wkvrg8ZhLb)n@EwQX*NF>^e9<`~(YMT!Vet8M6&%zh{s~)R?V&Ya|{u`q|cAPpY5s{lj)*D`x#N%+vU` z`*|*XcE$u)H{vVj+N?hqb3hElVt1=)*r)^P3uw<7vx%1HovhV9-ZX6G(NRUFJ;t}S zci!k??X%zU4v1OnwXhO2#ciR~;||ZxrvXf99jNh0kugll&ue+?!nLJ!mFn z1MwJx!$sy~F8Kexf)U%DCN1jz3^-iW*DW`T`dRlX6?T#hs_RCbE5Nn0*dyE}giAT#Baf`YccM+*Pq?(U^DVh$u> zLl9oG%#_^-0m=)kGw0D_kgv(?28Z>OQV*4kjO1#m>mN}yx|9boQV|~_<+d7DNm1sT zxvFTA%qt>;!@BF)OROzsL#o8NweG;ZY@KGqN=gEbOu%V@>TN3Wj|4RUHym$xsXrGo z4J>C*ezJ(qkLwRE5hW%F&K$JEq#jHX8)qdQzjZ$ZG5fnULQ42G`9acBZ@$69wOm~h ze@Mid3sLyzUkW=2ocA~KXfb^nPg;lpy`es!81L^buyw@ytr&{5*Q?O~BjR1d0#hhY z-wx@eCTl5>5y1^eq4^2*f9d|iyjD}`D(st62wJzHv6?M_rb=hY>qBme!xU#8<}5m~ zbWd220tN5U_V=QycbvyI^j+_sC`+E24Jc%ueN$|!jPYZ;5G*X;l3^ofP`<=;tVA8t z_#mW3bSIh}<3aAqs-;_2e`{!I%e$TNURCe7Lut?W59~Nz!yKqUK>Aj;f&+V~An0!% zM3|oleUN4r^{x$Ie2_P)v~QbnE|pO zSGuQ^m2s-G+wpW;Ad+7oJEcMWC0Xv)hpVHj%pDenUWUx`fNX}nY=(e;(}iqZdI;^U z*rrYnReXYEoHlJmZDFBT8v!!hK2u++VDLoN$u^*8auVO(r_^I&(_%J9to$O4lYC0U->5x`~mIrx5OWXd+M$)RPclxdjki*I& zJHnIs5gzI+Sq}eh%uSFPFTx7#mM6CLzGN)0KiM3n8}79ls=umn2(ekrNrlAcz1*9W zI9rDlizM12cSHn(>v0w|BQ?&71J-oB70{EM5Fv3p8?S?ALU}31E;eW=P#Ov5r}<#% z9zUU5`{M%IFSc@azun00w7nhaJ+#Ox$h%J6+P}oGj2^7e%y}68l{MsH#Ody{#w1lE zQoaWq!MjO|grjTx1*rYarJn(RZDA`h2yY?tXG&3asy7>maK|pZY2GhLabLtjUDk1q z!Oz~qIPbex0XI%iHv)hEUe5gc$RvQU9Xan-JErX3GNl-45 z)a8~&JJ(>|DBQ#$NVwpzemae?q9m4?Ro*fLyIkY-wB>%;(o|f~I5+?M?6HR}jFq~u3xdV$*VM&aOannHOcK8DG!)imiUcDwbiUPt1WBUK`X*%6q%TCH(m zGZzAZAgBG7MFM5CNG+2Pwji*e$Qxf;wH7CSVH8tI_$Nf>V^qdq!_7!c)_|mI34p^i zf}P9f-#Gew>Gx9+(*)tB>!Q)j##fD4zZXJI-^5}~Qv}oUFeFrOYki}1X z9@bw7v$OQVoFx-Z0Tk_oiG>=WL%%do;Z_n4=x)Aa2hc9ep*W}aAtUw^GE_!o{HIvv z+G}kd+T6Jw$}+&r2|+#HHA1R}#AVFfym2(HjShHHwEBG{kV@`A{Bx*p;9Ybj8646} zzl-hK|=zv9;6VL&@8&o%ey^A@Uy_8BTFl<%&8yPYDi}hb5c?fzp z$h%HCnU^E0m$o2=#dk{(YkN7T$#oTSK7}jM2VeTJp*J0`=JCH=Jf7R=XP&}i_MdjG zy(_zIui(vHYcFs4=J`X{B81g3^m?si#dfeOSsp4Id6RJdH-6ET`)Maj*PVmSqkB15 zJ+IH3pNIfv@2KhA@8#5eY%!}>dQzwR7s;E1lE;}bU017sU!@(rG2}Xn*m+;hGN@k>-rRO1V$_J#0Vw& ztHfE)0|%ZdaUzP_UqK!Xn$ph(kGWibihYYpKGPbhINro zJykLF_QOTCCX(pTxS&IY&uLK5zsw}H#76|=(wTD!5~X#n;p3ppo$QAewypWB<7OIt ziuBGi-Hh(;>$*P!f2KeMHTLZPvk(zAlq<?*qaLK3;HtvJ%L?@ro+5( z6_AxkXCqg0brd6iEGxF}dqAhy&-_p_n5qc2wWMD{`J~|Yhc3vSuN+D`JvcPhcs6^c zXX3FJiEWyF8h0qHpE<%ioxA-w5_WaRA)MD;MZFDN&*waLN}t$zp8CW&d?MO&aH_NM zZ7WCEEV1>$`NvUx8sE^)IJ05tN!IA>O^fvj!U#4j96^UusdAQFcG&8#x z0iS#aYK$Aef1ZUoZ8OHED`leAKksI<3ALf|eq+P4{KW3(g}qSi8)@bEKYWZ8@BkXw zmpX;6nRO&5>}6#nsetli{$!JbS(Ut4+;V({G$v-Gq%lIggh=9<;^nM#MmG;MmPM{0 zljLc|Zpv7w&sl^r`i}G10$ti{FB8`(4(GAfn@qxIo$*r;F5`y~sYf}8?oBFbUK`(dLhGo(HMQG#&K$X&v#k~7(AH9p#}v9#kR`r1 z55J~3-bA-qc;(k%o;%(!C=iC#>rTIryEP2R4AR;|=4aMIh zelsrw9RQi*E9#=h6}W9xgiUsmlawCDoWp>i*I#JQ#clKUslq}VSnA#Vl0=a3PGa3$ zT2wG=4{zRFRKqQ64tsucI|0Yf1=~0ubsQ$psXWHk(a5pLbIZ{L%IF__I+VlSjtHU7X<+&I`-v;yY9 z!R388c|3SR^w{{}%uW+XW26(|6DSHBDv?*$u{;!KE}8_s5{%iSAGd1+_Y@S=(#g*? z!eub|2F{tAtq3RiyS|Kl44V_&Zx@E4fuj8yOcA6u@>veYx9vf;I@>O_s;|WgLTECo z1H$VeL_#p_RlReknl+V>Y| zOV+(9hB^>mI@{@km<9Fj`}}&f%udrG2v5z3HO^!8hahCHY?$+2LE+&`h3`u`3zxQi z*emhZAN1YYcV*k#B|syhLwLs)#P`{S!nVQ@yH9oIBvciX|d} zzMQlgG?)^e#Vc$1g+m(?z1T)Q?-71SXUFA21+VXgYSf&EJD`i41cfq10}Bi094=(h zs13q6$-fJ}25B1iv@zx&K_eD0~7~gmUJ2{=Qg-|C`UZw zMK5tAh@M@JX$&anM3^ZkTOJ!5$1-9`7RCWK^8(?K{Ld)p9<1T#P)*dzu1<&*OK-7; zK1aHk2|O+2+rsHh?b=v~fVST&+YsmUfYi_{qYLts<@#Zx4d-`ediNIJ1iV zxjCS9XXlr2XeW6w-E4XK*QV~1ZQbZHCkA!DsGjQvlKV~F!@Mi>&{N&#W$WH9g|7xy z`NJFus?GsKl-P7xM6*Bu(L+zw?oYMu`W((zeF2~b8_bWNCG3FQ?{2U@KE@E!0Ii6z zFoTcp2OnVxnSBy(7Y+umU|mZaUR{te2rWcxiZ6{(6E25PvAFuDnZim*%QFJgja8 z)m576X7p6ut@&$AfRxQ>5t4{TUN`|D%N&SF9hs4H7nyrsq5s?@bxxrB8oM@HWK!P8E<{G*T z5g6^eTf1%T=kx^nEqQC95zO9qQa{J&Dgq4V z0l8sh2+8s|TXURPEHFjQ#EDso40$sY86i~k{>yIZeKj?5`UZ;cBo%o(pvg{BK`L`y zeUY~S<)?-7tqwEakLZ)>y+2&y6Y^JX9u}B+zyWzI0Q0{?*4%ghbd}7)zjm5{f3%%1 z$e(Wb^@6FWovv^Hk^NTAx2MBzGxY8H?6(rWeH4Cc(zo{PH!grk9?3)+fmlmlpTEq0 zF68sn@Us@NJ}U+^fS^b0ohHpqBNC^R!RMc5Ketf&zr)fk!Dj`?vZb|%9_A>$XaWde>s0b`9Mgsz|;eHJ=Jr1mwN6s0{{VMWb0u7 zshd?#SIo~&(gxO$zef(W>CF>noah9XXKP`cse4t+U-)C}W7a;4$=AEujGNBip3N@2 ze@WRFeM0BW{z7iB=gi>5e(EKbjRg{umnzV*{|cMSp9vw(5A&^rFX`E8LXPa^)*}BDVoXkRFx7;T92Wqbr1 z^Vn@nvANGG7-p4vz44IFPVUug5C=De~?7g>lp@WTi}Ps_1iniy4!8GUERn_0_}eGok9qV}&jclHAE@m?)2bZ%LD z*tilv*{~pdGNrNDnEZCXoAYWfV~5xa$*F2{-{;uVp+w(${S9;5{M5~9e{MeHG{pFH z={49kdwIRQNGtV|xl51o`qQU%+@ZO;0{pV`Rm}Y03m*ir9X1$~A_&CgK1`j0m&y&` zVsBVQdcyeL)vMAqI^Jf^Ygco&;rvKybJIx(;zh)n?0r#{hmx>OJ)3X?g{SxFeQuRo ziS70rX5q`uIQN{+j5N3x;udrvN3DtQx?5~ebQZg}gE;(mVIOVNwH4!YhSfUKcpE({ z^366Z%JpvUS|PuS33KIg zd2(3#XveQDA7k2O6y_Q-PdIzgVCe)cJaWLKnUg3@Y!miLPuPu9@FPqVj%BldLQ*6> zVRt2&Kpx9xk5?Oa$?n3Z>b36WgE&j$o?E2=TpTF@L2$C7Jq{2ezl^ECB*?Z!Sz%#^ ztFSm_1VwU-dkX*%iCJ%9r{2xXeM6lAU&GazL;oc=x-r1aAAJwOD`GAiGeEKxi6gc%C zI7=?+6Z^;+`vPucOeE9BM9yL&6+GY~JCTvt3!2)KflV9k~a;oKhW09DorV7aCcdc$;&nBZ_rb z0|E9&mbxQw+Z@@ybp(e}M;_QZf-|Wj4{9C35+C`E))AaM9a+{o0s=Ae;MNhGOC5Pg z>j*Z-Mjom$w2t5~>d5le5#`>By0Ve|8?5$%e*xfCYzNcRB}kM?~2A_@nl( zHkqZ_Gsw?bB#`^9ED-RY64jf}bT?_QLxfB8inU&}+hEwD?lU+33Lxs$N`RdVZwn6` zS^m|{_k02vo^O=--cUH5zGw4yg16TrY!2WsaUR@f;*kCRz#B&qJ~?OBQLcG$SArzY zgR4zqfG=QT1XTEb;Y82W zf2V2x6`U#YDDUtBdTcUNr`f;kWS63SHx<{^==hL*qB3m{$=@oF513qS=9g>fWcfYD zL&NX$;lX{*?ShH%R9&nIZ)Jz2z>~30E-5gtbJfF!$$y z7G(ogG8y(dH`BPTbSq;ist1`7`y<~kIeVf|DfZ^f1HDO8*s6o-^d4H_m2k#4_NE)Z z_lxFF(r1XJ2w8 zaf3;B78O6#Qd5P5`YDi^gTvC2&c)?CQlM_7TEe?%jk~O44+$!5d~k6wQT*m`m!OC$ zTblMMi0_%$K5Ow*ayWIHf=Krz)z7)B4Nx0T;ux9GncD%`Le^=%&ec?uFqZ~tPx~x{ z0Pos5<^qXeKclqjg^UKi7x!2Ea$!`}Dn_jeGHa#c1=Tj*BNvch2V%}IwM(3)$-OYy1;|mfj_-@5{5hS_3s6w>$D1_Z0(EFbFDKhZ-l0k@)B&39D|+DGPZh zaFQbhY|_tDx|AsG<4GpGPzh$VbYG{#OUNG#uZSZG8mkcLH@9j~1}BTEKMO+kJE`AL zJh8oyQE~ILs-%qx>PCHuyDaf|(E1NaksxfU2F$v4utnckr+OqS z9xHy=J{1R@)iTTVuJe{`?@Fq-1(WNf7SdqYJ9)dRcR$g9ZSTxpCKqmyLcG)+`=_t! z-$fg{?_US!hb5R=?1w(eK}Y)Fy&9R~Pp;)RtF|mO5J#h#2fg(czNGH(*20^QrKEr@ zA4auwbaKsfa~T0}IQ_Y%L= z@9$9Qv!>G8>=>RS{7dZ9#tr^&$sNuY-Fw{31uFDIbkASUN3FkHYbQkCV#0x{pz&hwDzjU>G(MwciP_qV_n)(*nRTpFTaCqYmb3)V zacyqNu~(a2{S$%n8wU&)Jp%zd8in>~F++ZJluSEi5lLzTV~}O8X07ZjYe<(YsdTmD}_VTPF zVuP-8u5W`;5U9?0UB~F%>{IglX5b57*|F^2UCL@iG@iieqZog-#`(GLZ&rYRGU%`aJ$7H6=)PbmGJZ~6lBsF6)VP3|Vulk>=pOR#K(2CalX4vPK zA^Xhi%s$Tu`5b;YGYpa0fqnk$tJ&vqdqb<*u@hjVD+lH3N4Orrx{402|OtpI{cuZP+<9 zxcq-|XyBv{V*c__;oA$kqJonuRR+s~7-Or(s2SENG&5gz8JF=Itap=_&L-7&ayIab z;Pn$T6!e8;hM5aM^QIoPfuSyk&^QN#2oabCo0`uz|48u~gO33QJIQk?+`|M-Q@vk3 zK@nOBdSQI7#fr@Yy&s6D`4jZ&UbzXn4RC8t9u{=%46FBM7_0M!aVKShiEJDL8Q1|Q zvsB@UsT3k`x_6zC3iqgPbDx{@HwiILQj9StceHJUSAGE;z3W7^s1s~jD0+3L=UIAH zdT&e30O-{`>NND~@p7I-kk%09|5B>6_#>F-cXl&D7Q@co&gfF+7@L_&n(#G@il_qXc@d7xQ0E_m}ba`<+vt#LnzK$c6V&*&r^S8{*8!Axc1{*iZ;;b8>M z$6c~)_9dq<)^cP5tTCmqaUn)aP5*+%qbNW$6oV1Mhviip`mXCZ+#A{-F@{b=GMo0$ z%Ck=Y%vb6dc?nFxk(m1(G5>7HXKVrfem*O}-`Bkxcf#M)iw2TbGh|y(;NaXQ&B5MA zmL`ncfp%z#Ei@9<_6bp#0@mQLkfH{1)@gLk!a&f7t)5v#a2)^7;1Zn^b}dt5ql(;h zE%+5UsTI7!ukcfDxm25Tvf3w%P*a#4N4x0(AIy#Kx|Z!eJMml0dHeWp5Q>;}x{aVW zl&CEoURF8J9K*YJRWP{Jw^&==NO21T$~Uiukme6Dbuby!A9I;ac63@Yd-KI!!6ANY zzpK~UaXg-HwwFBcB&5)juh4v=hhT_nM&Z9tO2Y#0Y|gm>EMdJ z&fX+kT#|Ttir@_1RXWMZJTlLf=G)Cue?{PiDiz~jixNT<(ftw@@tovv)gK_AlRS<$ zgMiLelBKAt90aVg2*_KRHAD>2D(VIi|3wVz4|ZoKAz8s&4;XfsGWNg{0`&iAcgDt? znKdl542>YbK+y6pfC;&qau`tcE)(Ii-)5J+Um{Ly=kKDTmRWdyRCyPLpmvf|)P+R` zyvU(r)YrHCUkQQD8uLXSvAh{%K25;S!ge@s0c?#tWnf#p6Kw0%zyucgDr4l4iDw;) z{CVJAq2-$!5xS8PN4CPU)L ziCkU`oxq?!a)MScdYGkcJcX)PP~zM)L!UI&@B|$Vs5SaGnla4ecpOJSj;7id;?+uAgAaZ#J?kV#Z!1`Bn5auQzw3 z=#Bhp^U~%iZGqMY^O#!8f%oL|tUKtb|CBb*gGE>3UEC~@@otsAsKi^Omcs=93h3qn zE1OJGRXb7Qk(`?6l86)n}eeFkn52gP5Edfvh+ql)eUwK34163p-FP#vTUx7Mpkkx1I=DnKzh5 zscHtt11GTC!Qid5wzn-DNNUDql8p?3wLp`RveFt(lMD_D7M<-}^&XE%ZB<5MOG#qm zE!t8e7ZgvfjQ9}kD7gjlt#|s@OJ+BinaS5IQg^G3R7l$&=FO0_N=asB?9_{J%u+LN z9K28g&P1>C9yg?+GhS}>u`Y5NMNCkavLy0R_%OgNRKHa?XHociJ+dS$3g5+o6$<~F z-|WnO1qw%6dqCk!wK7Z#IdLF|xliGs?GJ}uSh{jz(CV1{R^vV6)4Z#CXjKG~R_S?> zS$v4ifF;)hLmyns>Sf5aiW;=*!@9woL%frCnrz4UB?IX!Fxn%@4O#U zRX#XEo3kb-Yuw52kQK`Lp;C(hJM=PQyLVu45+^<6mi z5Ji$>G(*z2d#38&5J%G9O@Ir@dW~mji7yYy0M3^ewanJ+?L#Pg>L66+WCkg~+%!NX!u%x>W@xmtfYv*+6ImH$cdJQ!gR4djflrXG%~su`#DO z+G>oHX4J>mB@^b>^T)3M&#*J8iv-==dj8F2tmo;ZS?cj0asuc=ULK*ef4h>c1M3e< zyeGp2{X@$6+MYo^Ud#^}X*!VBp(ITztGzy3`K^2m(fS4m7HIuzez>9&T;$Xv8QpdM zPx;B~;1`$DLG2rM?bgAndM#pfh&&~B#V5;zEiC6JjkX8E$aT6qZBPAcp*;3D5yl!} zLRMxvnzuk^!ueceLo(Bj=#yN)w{S$)^87C&%&IO3V=gQ0iZDBhNyg^Rg8F5EF5k%Q z3d_bFO0l z3UEXACd+SRHqN2mB`+~cQ4k|^q6H9f$N5oJc4S`AmwG;b>_dN zI?n)=x+WJZ`A;@^CmGi43gj?liJ|_mhj+j$zf)M$1?QKpBl&!d3q}>%j}^Z~`-P!~ zr8~}c(y$185{ijW>QS20GeQz+MBAO@A`&G|J|%i+#mPVFQTfcSyYj7JBZfrf>m#0} zeC%f!ZA%%84AHO^{xhiXfvohHyhD%5XZFbnm6IDam%=iNY=vRyu=4n|+nG^?OZPplum@eU@@)LITPm^|vQ& zE8T;(^)E7<->a#R#wY*8+YSt8NBZ$+6)4Hmj4hG25}8di$rt{T?)ISuP4p@x-@!AA+3LG}AYxb2d-O^^8)d^vMw?CkJIv}j>=(yLeK;xQAdw|A)S#4_~RprAaT+y1S5H#N>j+4>029Vi; zN0(FVN)Mc#dT`CxXIHf^UTn$H2jOE9)|v%?zFA^(T?6k!#~)G``rC! zSVK~D1nGZI-_pVKuKL!g7CoWW28%P9=L3C98dgrnH+s-ut!wxgYA3s_Z_S<2t-kfZN~&J{Z|Yk`00Wuf z|4n`C8~7dPq@`Waw>~3~_b%vL<6k9PRt)pw(o1^Kw{~x5mUhs$o;+ul^sNJ_wp)Gc z;T6<58C2?ur@vP66E^wZ)wjl}uAgXJUG*(IG&ylG8ZQ{UYMkUH`v75UtDj*W@r%D6 z(k`cr3zdL#3!8BBk`h|B6L7eh@NT%-NSZu)$j>59@>q#i9hN^^ztc8^T|9ry?&uC4 zFrzwSD+%X>$g8+MwP+(9#P>Cu!aSnURmvsm2=7Miqd1Eq3#|+1FxbtUzv~2q^@+lo z-X^y!<2)Q1*28`AJZH_&5$Lt-zPPTs%54X4QQze!XuMjCD+ay{cJIWzIZ5253cNE) zI9qX_5$fMZsLxuF0{52qd#cn5^|-gNZSrF(W}l=#K|Uh^$X2N3Lx%h)!ntPzdakEs zuklH0=ia$qv-ThIv!eL!9ZszBmc~7FZ=cT7G=3y2%J(EzX{25Jmaet4gyZv#gMn4= z8|(NRd)=8^h5#z_*D@88!2b>nE1{n<+*%{RrhD->^vW7JvG8^J{F|jUg{|-&cYR`Y zr)DtgRp4i#H=hj+Hv$a+@Hj#H-nt6F$m-L`AJY#u5qJ_DaJ`uQ}n!M)XLN;N}?uxZWECR zYIThbi1Nn=8N8Ed%J>UVs)9uSFNn?|7dAU4PRiU8X*(Go^R-@H+K&xOSf~mihKj04mTyeEy&$&FSZV6|H^_H?;uEM#m2 z*8_J;#qv&U?M%fsQ#y;z$%s~(PHy!~#lC5lNC_wFLes<{T0im-6IIhMo?`;kTTar~&TQj#`Lh~N z<CQgc5I_S#3B_ zvD36aiIpsvimW$TYIslhj-n49Au4H_#f1G+5q-_6X9xRltL*hSGJ z{08n*Wp5W041otY=~Ph`eizAn{$I@23VLSo&lpt116vKV zgj#)oaCLhrP5ICA6fWKlW+hJs>5B~FT)EC#6U+0uxl0m;2|X3MmL?Aa3|}K*tb?g) zAMYM3UpUFf6c_}(@p^Z4E z*f4ToU#kp+^_+n-16+jwr3ufcJKuea9D$R#9Sd>#%AEP13lcvsl_~RXV`XFpSp{qNh3Jt(vW;jd6Ma$qB536{DvIOW^}S^*Po@H-c(tPwEEndnUd@UTvI}1NK}k zkgl@oj(~0!mG5cCGgwnA-v~j?9Cg|8H1Ic5BQW`ga)dWWZ3~|OgyF=e;!w*x0qXv< zpte6HEnHB$#0{Th_6#4i0Mj}XH^lbc&64{{cK9D%u=3}c&#z{O_X?TvJSCHRK{K@E z-q%7K9X$bbF6Os}Un8lCIc~>!TW17oI3u{19!}^)6DmTK0Fu7@PkyuJgp^z~5bvP)ew%n>pzgZ@+R%v~!ysWb!uNc9@bKad*`&;BGNv3An&l<8CE1 zV9vX8whvZJ=ETRChlFN%2i5W@u%(+7>lb3w6Y;7?)G@|l@wfE?@9A9*2?l2=wufga zKK8ot*lW;ih32bdi?k>qXwJ7|N8g2{ctX!4lYRDr*T`W!7o>T_wmEbEDlcNY+4Egd z`Fbn!q&CwyXS$9dEr*2Fi^!Zs!l}Zpob>bt4&VOiq;-YimyhO`=`E`#We^=%vr+Nx zyHswgfV}fU_zudXP18P3q!QU^#zKqV#OQ`1Nk(=RHHVY{mXGB5vgnpz0BQ3@xh1btUK< zh`;Tdll9i0Ua%O^i( z)V0P?As^8xx#$koLBODr8E_(}kiX7bsE}V$v7<7+1_ZSfqN_6guMmP?N-EA00(l~Q z4Iy|<1-_CHYC?=l>=kjvzxYYvM$DIK-)mjZMvPyP(Mpaj0`QfY0e z*#j=KL0SMr?{#=T;Eeifcu>MN7Bz8lKH*2N@4)P&Ppk`wq&)2PemB2X=njd`fz)XH z5X8g|=Os`B-Hj}D8?j}lgIrFkx6s2V521?x5x4*z01ZF}Grr&<2K0syBv9~5Jfkfo z75`m|&^$v4JY1@|@w?zP!5UaOP`C=M&|Cn%>tL`=$SZ@FUBU9xx^>tW}qR>VAz7OiY5s zfRcZvEj2z_)mL2icTpc%%Wy%Ud1w=h|q)c7Ee;AMiFpVX{6q}ksg)@SA2e?WKk;;u`PvT4x{Ws|K0`C;vS)4SHu1_?oQR4+%tnyt}iLrm?_P48- z=6Mu9!C7Pvcg28We{d?((TK#9gWbNrXYdn{LM^$tkdJa2DDY=fR0G)yLqfv>Kf+J0 zk-R2m=1H(9er7xjI4)u8bY?71Klcw--duOiR(C!W18KC@6?Q3pB6*#i2ro1!)r1LJ z=@N+rhc5tO;%N(dv$@eBn95kMw9wky&cW7@4WzW9vUb@^cq0uJKIa|?MxIZm5HADU`&e>x~$x?0B>5?@nE^$qJ*w@VS92MwEgAcYV`Y^Cvn&;P9wid9p5L?ao;`hvqD+rQh)02a# zK8}SMP&I7ufgk>=;F6WRsn(2Ws((Y(U8mY3C4Z_{-@{VBn8e&fPgj37a^CTuf0WP2 z$ca{$gSM9W#i49s)D}+PzJk<~)pivwBB$-1r8k+7%yb7b@uugQ?q>@MY75+rIICxm z-|ofIH?}W~H5{+SrGG(qu3kZh-=Hqb7OZf`m{-zA$wu8M2VZF=%enF^>P5)?2*^ie zJ6g!FiOA71LZSrftTPQanCk!D1tV;Nx8-P+gOyB2B?Tfz z3&K;>duk?l%bucELdSBOt>axY`R6^*r7Mf`s<9CeUZaK}*hKuU+H(}U)?+b9z4I6M|)S->YPsp_><8%@_N#%Tg)ix^v!%|`&j3U`awCl>i- z;|t0~C^kiwC1;R_0yAIZOLV|G+*)39Uv)no(8daU?G5IGm`6t3MMVfhs#yOP+!&~% zoIC5=3e%-m@zLIp=-)xHh6RL7rmX>M#ApVrNtZ65!dAYJTFH)=A(7VWh_MuPJt$Ip z3Zl_kaz*`PG#L=o*T}iS&08sDO_njk)X`8rr49$QG(oJ9~-?} zfmhl)wkBTVEZXcW`ZBgXeoXb6Ie%3glg0|5jL$%v86(v4L9rKS%9DVU84_Y@9*@;L z#HE!;Q;DUKAwatE52oq!6$s)d-UuX#-Uab<+)bh^wf$j(Ke8RErz5Loo$Adj@OoE= zhtV&lPJ#gufBFD#LL&0r2`L4*4q`2(CaVuC8{cI&_Or%AtiIT>zl|5b)weB|^)6_< ziCaugDTx0~o8F5DAu*;piOH^RlpzN^By`daE%f2;0JT~c(?jCf6wg`Q%!Bql+2zjz z*0;Ppt2f7}bYK52J}&TT9*#9XN^QU3O+NiAn*S%f9c|9yaPPG7PtKxe8SaTdU#8P? zq7sf_A{Cu*v|$Yr7%-=%Gv;2SsP-C0v+0o3!x%OlQkQ@s%#XV=x8FKVNE7spd2IFe zt;P)nm!jfW>66^X*j^ZGZ~muuI(HtEyk|!V4#EruU@5Nk=1+wu} z8ie}IMWuC8CsAWqjd!8~EadGLYyRAzp3QA^X^U!cw>s&E zCJZV!lBP+q#IvJehpBy>@>AZ>mnk9hErIy|MRw!2+r(agdVVYEMx1_&jhiVB4L66H6I8dDHYJH$J=T#b$_&01K3 z?fn3>Pics_k5sR6H)WPSECxGbqU%$!8ZU5Pmw$!o)bJuvcT@G|jNA}30MRGS;RDE9 z=~C120hb#0DicB}xOyb>QLS$7v=1*oUYsL3pSgohbuKcu2@ALa%nX8M4XWs!Ax^20KX3?7LL>(2z6>$ z0O2^m?-1%e@@>typ*&9dHHmn|564D7S`hyq{|si>-R_^vk9yFu_*M~Nysc=6&Su)r zEGS5_%oH+<3{l(=w|4Aj_%pMLwyAr+`z5w@vS^AEvC%ga#NUg_)Hlc(vn;j(EUDsU zuru#Q>ZO7z!dMJ)=6(u%oO#y>;rS}0hl-F!vE3VwTx^OG1(F}dEsJYaZ;&xyt2 z2z2{V=n=(Xxm9XUi-}q3eWPZDx4~OpE!-Ac?aVh9pedhD)0@EOd7)TN5Oy|42MyHC z3N-SG8acIuz_d>U&1@lsMQ+2XD$NB{e?mxVr`zW86(|5hFjPt3s!&q=J1me5QpC18 zr)(9SFoVs*jPD`t`AuQY7XkoUGXE6>=;w97L^rQ|e+WZzl7rN#P2M8009Nw^5V6W` z)f{Z#^9O5Pu9YiGh53M_&Zud+s0?A*r$=xb9I5udhRN-z_D9oqiNUmPW;0pRCuGAvV1xskZQmCtc z#)c>Z;Rwy*m3NUG?%)j~1?aK}sFORpAH0G79!g@@nYl^H*E40-T9Atvo%$1b6PGnh z0D(ESsWqOuSf}o=iJF-z=fPH~1>S;j{O!G90)O3=1EKYWtNqKVDy-kTR^(FF(bEMd z7HHE18F4ufi%Pxa*M^kSlk zZi6jIwIrFVoRfE|ep+jlxGkdoYb6Nr=Txf4bJTn1L7G&j{grtj$#uCeouRYyUV}yx ze0+C08!W*(V-SE?M`g@`+~(2#XSj`xC8LXHV%r*@_iv_j4jje`2{;t?$JEz_GW$O! zIrL}Cww5$^SBCcbv7&TZ{l-~|V++Xx7+c~A*=v~uoTh@YTMKSp&yJ*LA;DiSOjHY5 zg0CYKc?91G@jDRw)OFItiZw3O-v$uP(grsatblcqFve4e zj!tt>t9U_CU`ggxGMus6sX-TtUQoj(ejqAbXp7`w&Qwyq4s+fi&%ca0!ik-N=w>ko za=UZ^z%i>k*cDIW=xi~kSb^IZM!xvaxLdd&!>GCk8cHX4=P%{Y{s?qHC#h0dJNt-i zTuMWj$zS9dk`3Ke;mo@48|7<)jY2YU>bXmcxeUiyGI3&PGTxN=&TZfT@>;%B;{U|5 zOPEC#nI8NuQ+zyAZ@JbB!Ia)D#1{<^c>_aqzS~`CCf3RXsUw68rBs+5Da4&?AW1fR zKS4pgceHDam;g6r7T?rOw_eB*FvF_itBv4g$WQ$4fbcje7t+=73yX^1R_h1z$F$y& zmVOi7=QV}qqF=E?RI_UH`rfMR-EKjs>_BW|2{)lyGouQ1Tm-?WgI?b{-Y>E~}`&njHj<#B|t~c+JD>Lc-?c6z#yP?qjxNwUU9R4o@C$V+YPKniT`>3n zS1b~w_%*sqZL#{?JITO}Rv*b6@CTkZq4A{-rcArJrw457Y&Tcm=t+gGmc*Krl+vej<@;|HcOy`F5JqLg?BsVh#w@^5iW{ zM?t(=Z4Cqq)DQJX3Z$B5hPYqzMmyQ5eJK*^zt2=IR*fcdBJ=58Cc9dluEC+r7t86{ z{D+{tB#y&iu;TznZ+SBu16!76koQub^xx?LI$cfALUc+RIfuD?R#nEM^@X28Q;Si; zsilMwgqI)*S?#?-!4%x}J*10O#;OA#``kgihz}ZxpQd_t!k1CSqUgtH6-mE5qM+k;_WNv+nt(*<+R zFT<{VGgD=7AOxv3BJ6x)QvlgfG!eq}17r(daX^d^y(j%I(+lgBc2bH@?VkYdRBslz zo)kP-SlzFm1Je1pz~WHU*r&c~a4+76!D9^^ zK;XMl$dbjjxRb-Ql*^~;&Hf~lvkN8sV+6EggCKPf-~7)Igt{XN{u5f@$g#o2SN?wF z&VQdlmkrbLhmg}UKlV(o5mIvm>uB#DGbhV9n)%J{Q9i;@gz^v51-kkOKiO&?GSzHm z-^UHA!S6~7fsBgqVtbNaqW*F79w3#HC~MAOevA24JScH1iCDS&``$*ggiUn0?@%Yn zquvy3JoZ+!hh;LKQx5T>ds9=JSJWQJX2mb`>fNu=(Un&7(HKbH*W>xRB<<;6^C*NT zlW~5~dx(|$->d3Oi47`YrRjw#5nSG)=P-BXo@{RXWUK+k$N^4j9q)-}qPnZl+8-&C znZBG&mW1iuQpf!<)OgGK>dmf6>2PGBd{`fyc_aDcZfbiw(mOHDP}O24>o3ldal!4L zj1}iB!-ZAflBT0t>;X~KfFKc=%(97OO4VJ zTg+=fnr$9W^CXr2EI6Wx&A zCKF6FzT2Jp!A*1IRDGFlzD%%R^n;)^a+;<9 zpI(GC{n%BvFbiyOQKowu+ zjO7H~RFF%xyey0E*33e= z{dtP%pja{Y@NPBFJZy`7()b=yYuW6hJZei9pX6Og*)vsq^t@t|?P-Bo5viAa-#CHx659!kM>k7g(n%V*kh~Tu;qp0M3HU^a~+%grl}Mq1b7_n%v-; z`H?95b0HHojDb?pCd*_XdwY*18X}?NSsDEa!P8)Ioor**;;xO-(! z;GRI1Bx*t3*AYsDB{hYu&t{8z}*ytZSO}iYsUK4YxUKZGAcuf z{`)SF)@&Hv+_$1a%&cA<+pOJ1nn+<q;&`mD5ErXj0z%D&k(HyR~{l=F|BGWmn895eAYaGwd(OPMECT4{1tOukv5kQcl%wRfiuMAR6OyoR?ZEz%( zU&r3IesQH&oOCrGbYZPjtF}hINka)j*I&V7&}mlPcew^AK#%nl%2}^6yb0p!pm0Ap z!Mo$hgFRH6iEJ1gQjQ;L<*m?9kt!&jIrk1#ZY>5T5X$_M0YI=bcD-5-eT#p^i~D>K z`WcnP^hzVn;U_2t~Hm_xF=9Cnn*J zoaV2SNe!B`mpBcmG>>XD08&2?2bEcgGLcf%+B4xV!M*r@ObIAq4nqCjY+O!e2uM@Ar$W~P;4 z3t{+u-Qf|0E<2aQ(h89Kv&0$#u1qeg_f7m-0_^7LE-_L{rBL@FL zf(DHc>4-^9M-?f`v&C0WX-bt=tTRB52!oS>{QK`{TJ0%qtxD;`o_Z>+ z77#520tsl^@5h@vP0D!Jd^{{QC@#M*Q3J-zpHZ~1)4?EikOz4qE`t-bf! zd#|0j*_C*MXt$7(s9OK##wE&`d(h~|Vj&(F$#%JX?|2c#_`>Fm5yzmuX$WT|{~^iHbU>FzcblSe7%*ZYib6QP}&)yQkL(w+}jX?bEaEPV#tH zr2qEa)4gI5|0R`&1^CO0%qJrcXBUkh<)1SJGFKgIiO{_yZX5GIgaVLa)4|$QH73=g zw(w~qDj6f9ARMKIM+z`!fIsBw(CRzLkrmy)=N974Bf#*(uMYjyQA091!8JU6w4RfN zDa)`e3;Fsx+Oyq;?fTUb0du&z8*l^# z{=%D4uDSEkn=+3n{zlbkd>p!kqKGlHM?9$=<3(c~0}>ln#8*OE>c^9E`r#uf!$DB<_8Kw3T>M#L>HdGp16? z9E4zQ?U_F`+{&h&dnvw*)rI?-a3gwxIZOP4z6`srH&td8V-7v1&=~P*T%CSl$VuEr zrDis;cnXs#ovFGk?^$twsGQ8Bb7sQfW257#LMHp5->~m{6Ejcg)OC16|Dt=3q=u=$ z2l~!%nB#0v&hPSZ3yFLiGUrFu5b3KkGqk#9p#G{EYv$2UEIgC+qCc?s>#O)HWh*CY zB-4J&UfBc6df5Zq^lQD=WBK{JNjfq=i?s?^x0+`tc=X;3=f=c}!9x8OmpLKP9xctT z&lBGxKE9=5R)<+{#2#G8R6P)Vt~0KHG3Xs_z6Z%z)zGN2aO%Lu!#!Sh=@-LS*2c!{ zhKctKybK_{ETBI;jncc!c8M|9rGiQ5moXc($oB>ITl%?L*tvu5JFIWj3w{CB+diLO zU<#4HUd^Y^UOGthY0LY!uh&;w+lPPm?l0(D3Vq9=?P_nz?9)$~&X1JmyAVFk*N?EX@{6O(vEw;Pk8~l{9iebM3S7`nYOiU>@ zBw2j5`L(-JRczmbn~a3TeZ2jn(qM{X^1NbdwKNL^A(^@<*2Vj#%zZn#D@1}!w~GBH zAXHp+(SuDv&gY^SVHTy1A~mrmdLE4W1&=|mAY%zDrjW96Fs4G;rV0JeKfv7l>{PNoDGW7P;_{(PpxI9erkP1FMG|O8?Lk%M5;6p&0z!Lqew2AcK*rUOcwW zAY>(qNOC_)OpfEG&G6pqt%4Mgz7*P)q-K0vP+&|d!_1}WlZEjn*z*;+=-rH68 z%;G641=sF46F$dYP=t-2R@AA2mbVl_WEWpR3yVQQd{MW_nzX5|Zy}}d_6a71skvC@ zGJUS~XY-kT1vJ>L!p-*h!X+D}9nud7giIH}k$1|{)K_a*LvP3T1hIV$-docH+T!g+ zc4y_QLVSQT52U}gr}B+awb8#?YxTtMlWJ<^-sUsMPgr_GVf#yauT~vaf-6^=a~SFk z0kC0JP2cJ2uT7#uppJ^V6=ba2j3KW3%qAnJ2JB}_Vnq_xl-mw2ScIhQ@KjgKWBf} zfrGjyvS6<0pilDuW%lD?Mj7t77!IdiK9ze}Gwr7;H$j~yI)SSriwm7aD8rs5<%)yY zrK@Ix2p;u|_en~}PkEUjO>{JCN5SZ@!-T5&PoHjEUNzYw68}zij-DD$ha7fQiuc$Dj z*i0wk-_kjO45=RsEC_U&80z5Ou(`L>&ii8GH_~r3>5A1qcOcPfgu$?-k23A$&WH4K zezR`=1Sw+2WMUpg!DfPO4oBXs^-DJQD$&3+vE@_>Fyxh}7R*i!WNL6$sIV06O~iIK zg@*-r&k2r;e8F(#o5>prF;cx}bBV6+*;ErV`P-v~=^+l|L1fUVIStXbl5+}S(DYND zJ_GZT=z73Qp_pNTW@59J=K*;16z3FG6qLfoWK$BvLF_QBKXcU}@bVTI*_PR_b5*P) zOjDauztSRH>|weVmTp?5p4N>%w;aXjso_fqd3sa}zveb?eh`+fp>R3Bxp~h#av&_d z=DSDEM@A)fcE+02KZ|koxVXaFICE;<(-G-eZ%P8-S?&lRdF>~Cdfije=aJM7PYN^O zv-1z|I66Kth#-9OC23X_%9>|Frm7!4bfMy zc!r#@_14Ey?%mn&)(r&EfFzniC z3_VW=JL;ag@i=QOm{o3WwiS2r@xj-*Y)0h7@bQ(eH`^B<-<;UFu*OqNJDnS=lc9#> zWtaA0VN%4(yWYX7Lc6xe- ztYHBuHb8K-q2hDHb82=nADUER7qw|?>gDJ@PVpC8w;Ys)L+7%iQ(`63n)3AFZW&Vm zc^oPt)9mQ?Tx?}Jp9JhurVd_pRA0_bY?U835)jqSbX}Gy3m%}moY2xfU*YC*8{Hmi zwx@*n?ZD)Jxsv)-9g~lC^P4h|#qC#$&|{<<0g*6eI_Me(%G}N*qSs zJ!GQipi4$Uf_1`&Nk>gj&2F$^Rk5(t8CRjzc&IksRV32%Eh-4qJ#%A-=2SLLFWZf59yP9ta7f7L(;ipFsl2nB(a78{>4qeusEBMQ5z8sKu{R1&$Ckm;XTRYBtuK$@AM=`E{mMh z=8St2QHsB6sD2BZ4x~h1rqT5_bYHB9EfaIo6%vY}%WUhGe+3`fG27mnEL$RR_xAVI zkzI6Tsb;7^s0TvbdpD-sk1PL?^?#>#{Z^)a7t>)+j%PDO$nY&p>*~oG6fp>e80rdR zwI8!?Ywv&_z4du!Jr0P_#~=hsIkkdnDAOM~iEk;b+{G$&OQ{9~=zFyMbG-aTnfyUY zh*e4zIO_aKYtm{ppW}vR9*WDlLtASuXN!_6)^m-4E5yJrKRc-oYM{WNjfI={ zUHw2`#dhxdNwg2FkB0T`Ok)q2K4s}E+O>6V4;#I3KZo-TRcr>0)G~l*qPy_8rCXHC z?q;Zp|D_-@r)RKM%<N!%?`g`efaQb-N zUa*LqNs_wZ7;sCKQIl84tSi{+?#|3-jma;)be)Rd?&w|^CMWWsYY<2*ftQbfqQz9|IuBA~ zDAFY|XhtKf$L^@v-E7b74{Go(*IPiweir9A3E4fZwTy?&_QL+u<*%C5c|S7$~pT0HQW$G`p#mB)bu@jxsz}(O*QPZdJ zK3>a%A|xqso{iw3V$hzu;$4kJEFqGO9F<=@QqzLO&c#*aDs|3wYMG#$t=FpzHeY+l zlqOB(OM>>I74N1uz#zI>P@342yu4@e=|C&n^ydNw4F(lvNKWV^J2Wu9Iiz8p@+HZp zQd4DOd-5|qi-#xclc1$xpMfS>wbUs((VjRspaO@YZzP-g1T(9v4C>kXy+(k9d6H6# zTf5Ud_gJj<(n@FCyP7>Q5wwxf@Aox&V?bi}l9%FJicMd15YQ+cU}BaL%)IkHHdZ}m zm-B{OYa7DW+8ahdP}vU{n;)~*b|(2?a?ir zq4NS{RlevS#eiYZqg{=(OD2xVym1K~z;0-BA3il9o-)*0yEC|x26Nuq4030f2HX&i zzouDgx!qUN1XPh?%%!k*sRvr(8Xq3{9{*(z=>i29o8$ z1HiM^hQ>78q3hM2!#$A^rV+G&Or@z|UMn6m!kWt!eVR!|m0B~I*3gp15wwO$+f;9_ zm)4Zi5ZW`9)|AtlO)nOB%_+9&kC`W$7LQ;vOcQB(m?jkyEQj_})hG60HRoFO3YdmP znc(4Mkw_J&Jft3CA&~2$(@huA%3!w>T5g;E$?Kdm^i1-rA!p*b+5XWJ@$^rZI;M+0 z;$QSBwFrzGM`Vr~F=oj~U_46npgkqixF&w^MQKcT#m(lZUi z26ri~zrUYB8r(<;~_h~o61wuQ4bmG2BO=`OP3 zA?k5L=P;gAJe2AQN;adrdD)v%ut*6~Z$Hh5dEm;+-5?5(_FYS>s5FJkmXd^OAZi4k znpuE@yMS!=Gad;1HxecADCy)#Z;hgX{|i_ifG^=Fs(Zv9UwZw?$*;Vt^+crNT@Jh0 zBP-&2II-r8FJ*nn+8RB|LdBdmvR_ZlhY{n4(esfjM5XIOFvQF)q%E>z-(xSRDLn9$>${M+%b~hQzKVa73`JQ~mINb%Xt3cz zkN4bn5T2TyV$1Qv-4#F+B3b?Id9x{lzayWArz4{i+oN-&&1-hoJv+bAnNylRhVid% z-}UD?O+S!%-SFb|_+o(<{~X^^=69!AuXw}2i;CkT%SKAC=iEV=1}wRZAwlN2WD z4r+}S3bV<>(`jVSpiSwA)0@5i&B$Mw&DB5LJ28K>T6MY;iv^5617ThO&pcxPUY6$L zt+h`EcUWtGpPV|dr>^t79 zb3zWb8T=W*#jCM_!NpdKHiO{f$O+igzoOPqzsADLrBALc&&t_bXu-O@H=f>%MA26w zv;DO5>0)@Zt~2@BkTZ869>)hRdD&W91=3C7<8esQY+qY$PDhSMkL7{R@b?TD@M#9< zx?MM(hCN_Lp|xgWL9n%`Ku|lDysBP>5LnuczTpoH*lf?xTNFsd@LoW{cLp-z!z*`Y zprIy?;Y4527!TZDz=7I~p#s-mIQI9z4fVi$U>7aM9rO7rp%Ig3H2%i)Sj2Gp^LBU%{%iyfRhU?MyEY?uysn)Wi5i ztJpg@l)4yJW;s�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 diff --git a/windows/ncurses/lib/Win32/wncurses.lib b/windows/ncurses/lib/Win32/wncurses.lib deleted file mode 100644 index b0ce657a3799d4071f32a88c74c29beeebc825db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 123366 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 diff --git a/windows/ncurses/lib/Win32/wpanel.dll b/windows/ncurses/lib/Win32/wpanel.dll deleted file mode 100644 index d1c5bbdf77984cc66de8d718fffcafbd3f999669..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40517 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 XRxa47JxlnYZXfO_Bll?WsN}x^$|#2D diff --git a/windows/ncurses/lib/Win32/wpanel.lib b/windows/ncurses/lib/Win32/wpanel.lib deleted file mode 100644 index 5fcdfb6072d271113bb381c120b2145eb1008cbc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5050 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 E5 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 Bj|>0+ diff --git a/windows/ncurses/lib/x64/wform.lib b/windows/ncurses/lib/x64/wform.lib deleted file mode 100644 index 1c5fc56001c38f69a379e4b3adc295636f9c0be7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20002 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 UnzN-zZnwa0e;PdQ4QfmCUz*F9hX4Qo diff --git a/windows/ncurses/lib/x64/wmenu.dll b/windows/ncurses/lib/x64/wmenu.dll deleted file mode 100644 index bf11c2978b5edb87526ef5f361f8043fc0ac8a1d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 67812 zcmeEv3w%_?_5a-@3*qGkWECmsszHMyZZu$GL3hapZX`f>*@%xMXU<`Rs2=g`?#^1&A|*Q0SfcwAC`(ZteXr5LbUR8y)&AexsW7#@#Q z6rNbe5j|9wMg-Df0fONHo@Zh$$76LwT_xyWT5Lc<(j&P&6B{_*1d^#0f$%C23=hLw zTwhNhH}P#VWEzrW->yx0SQS)uae`jHt7J6>ao;<7oM0sZvjDB6+4k2 zy)+^i9*^V+PgJUyeE9_LMj*Uf=q3Je{gqYKlt@}zL)nDa6vv?y1t1TP3M$ zsN*!0e>wsNu{UM4yIXerVQd+(Zw~t-LHj%;13d|jrngY^>C^Bha_<}rSh@h$6khGU zYFps2je-1KWpXfSoEv!Q2jyTvGWa-%Pl}wi&CxUx#d`5N^xvG<`|10F_K)!r=&?DP z&I4l5{#U%B0!{x0xuCsWWS)l1=6#N)HvpD{_BpkTf--ED+PNu#U}`kh5wQQ_K}q6L zF->tn%UONX!_iA)u^3*samm49SAcp%`7t9UtJ{@az-AGwh+t@-Kv%My_1>}*<=}~O z^KRuI1c>bhXz2l2{XC-123ouQBov_s$wV!g9&Wb}6yRI!$w>BAA8VNCH{UXm&>m>= zTkY>ZB1zFPBxZ{oazu$WFKr1hBC!)w# zfVbOkK`GKtbTcu+Gf~uEvz|1vo>$d9dFl(QbHz21}=3;Z*WL{Yc#K|KCm@R#b$jGVpf`uvZ0zuLM<=2XvloF931|{Hny)|}6LT68 z$meRQ2Z89LGrD5@hZOSlcOO7fG#UtgZ zzSK;0L28Dq=B1`ZZn_kjNY0j|yddB~f(HR-MZ74|LS5fYjrXFGtaiA=SsnhXFp?-U zvgTJQLk|X?1Q(k+zsi3y{=}RwKL>MQtYK(@=iOIg_<0NLCPXeg55lQ$MP@qD;{fP- zmDOJkjeYb=^x`d={4wWkj0AYcHqxK2jV61NL-yssmz#IW4&RQTw`v<@$Mt^{d20>w z){?xnG3VGm!Tvvzw&T;8q|d&`?^miL_RlJ^v&yvnu~(}RjASI)wp%V(kM&ZY5c%E4943Y7Ui$L1?W z;m_QWj?L3Db8K&W9Zziasy4h$2DD;)2mX#`Fv!p58#y?)sO!0S`>{4R^w*7tU;~DC zZ9K_L-<=nNq2`5rsS{-Nm3Cih8fgVF+6^|n0L9Ru+x-=Cu-YRxA8<6?3Ah}*My83- z;d}Ss&)NV;@n7wO>8DW>lX*UVA&|1(RnqC@zv)H9&HKC?K{TceLJhN%yn(PSCw(V% z&bK0KfEaUj`~|%+Q|*D_XR_hRahl}VJUy+vIlS_I$L7mN_(Hyvm@g6ReCUR0UAJNU z4cfiWkX-88Tm8)~oR*y*l?u;~g-=35p zIaV)a_%sp#Z@VvbHcA)d%fSX$u#vPSt5>DE<>1(Aswrv^C{0aE4y;I>knCt0gtAm0 zln%UrCifI%z2LaL2c^=(=?CPXlIqS2rVb!wH-~2hGg2K*zelFmv0*?HW?~nqNY3CZ8uyb;X=#Y%&d11=M2RtGrixukjXc)8}u;hLf9i zD=EY(v%{avrS(ViLO0upnR0g)G^NaCIv|B%b~%KxAaKCeFj6jgLEh4t7^OK&%!f=r zj?EPXz!3SJD1de-fG0&Q82u^UA@dwb86yX;LgPJ^&1~odAe5`wX^yAD+mi;u;0iI3 zwM$=v{6_i{orFJ7U34*H*ogW{2HR<%K}dbk(ey0VKaQtZr(K`mXg&w8>){z?B9?>R zBFE;+3Yi26-9p1!peJQnR_K;5Fr~s>TRKb*X1mgNma8++cbzqz}Ue3 zr&WjVgJH08{@3N;4d}`T9ZjW-S6*sa&Ue=h;2=#UMP1xPX6=30QD0Wlf%(`8Ynfk|-8*Ta^0Fayp<(VV#$CKGudogv+$#QU}+iQCbnWJ+YPi%2K(Gh8zNFvQIB6T&n zkVgE#Fzy@3(On?L`?su%yk-`wAXkGX+e3t>`$NqKxM)oynP|{cUeJ?|xx>+v00?>k zuTd3VNPj{X++2GjOODlH<(|*vQ7lmT(tw3fu5M7 zDG9HH^}dWLPKKdK(JatwA@gOtvLcQ-FA$r@VCXXXmONf(6N7IKHdGz|snICj^zjY+ z@)^HhgPMWgJ$PmOy4IMgWZR#$)e)M(c<{z#N@$t{2!?&$n7_h{=FidOx&YD?&`M?* z=4KkmFK5N;F%zRN=b(QBsUR;@nmR=eVY0&dXvv>3)Ti&nx=U6MqjzNz8N^c}Kh|iB zARe19Pew*2L|XGGRDyKT`Xop57}RimvZFbT;uNMHN7LQ^ip4f1143r~2{)&k0W-C@ z2X%Hd-wWE&5|(HGHGCU6*w#oIR{@GSqv)sY5+yg%pQw*P_b@1VE6inyP6U+M@1|rF zC7$UR{9wY%k>S`pJIS^yt7GN$LgYK41rqs}6bq3%A?2n)n#dP$kzYa-bCxk~unF!Y zN5g>1!Fo12Hvb-Q_!T6lko>;@GBw3#=kTU@5d|Sb0hA3*Gkt%~6lPNTb`5(Du*(BC z7D$dYcOjX6FdcQQO7&3N`MOSG{!VrQrfWH{Jvpn#v8Ia2m7PCJjWXJA$-$BC$W#9$ z=ghwcjD1;XKmSgoroc)(Ssg2$rJ;(HbJL$_=%m3tIWL&xW~Sw6x&#!}{m>_y6C&?m zUux4(O+^l(vI))(Ym)bPlQf{nrhyu47l)M+%&x&U za9BRU257K{IBW`F29HhKEKxhW>T6pfr@`8rPeGIV)Uft81aFv#9Zes?EF4eWN3Qe1 zZEzdxlo7lEy%C*)u$p)K?HICilXGB`O}{293VL1GJyAxc?=Dy8()_CtpmL7Q%L~eV zYHl+AcnAAJg)yJH_df5}JqK6Ol$7KP<=g!8Iqa}6oDB*Gt%LJX!S?MLt5cW6lF0Wmw<2Fkf%;X7%_SbK1L}pz#p`dk077!!Y^$ zg!RF|a@F}V7WJrx@+|1ux8kMiPdq>7yq}TOO}T4*%y}yVVFZe8q(5Chk2w_vg5AV6 z(x0wd#CjJDM#AkV1x;;{1qqVX1axG@iHw=1jKN-2`qH?h(b|i-Mz6@~9yrtOG#>su z>~Xa_nhrs8c|juPXc~hy$qh8PBuDc>fOFN?x`wvo27XF_PY4j$k~}Lod=}a*8vF(1 zh2tCe&;|kR-tC@?rE;(8$$$?oW95*m*1BNS+h~Y=kF4P-pv&qt@Dviu)!BSZ{eW?K zo2@d0Kjd{htEY+HFp zN>GO5HH8*+$+oRXp2YqRAj=~GFS&s%$32d{G*?O~fto*6^ z&)nb$Fh@JCO5fRpEx#LK3)4d@#$n7GnwpcSX<`28-TA-Jl@o&y5iOmU4Ih3dV)H5SACNhPteFF`)mLFzhnsi$LSvwkJ$a#wzk&$bWaMj(=4v1`?em{QLZIFr%E`%Ucidi& z42%G}a+cyfO5AfoQ<6yBJAO?f9I+;MOa`*(e|aT6h8i`~KBg~}asDjzA30gwD~G_O zW{0NyllaaFW@H8ajdc$yy5sySz7c;jX#Z-`PyP0i~B%lVmY?Lm1Nj;{*^So(T3Y*Zv_qe z!Q4z*=GjiifDxPz?|ZjW3nRZQ34i7d@Pf4$3t+rtCpb1IVm!^nTEjz<8@AV6^q!No z6%NBzFO73qTfC0hTYTg%Vk`#)tnlKFtOF|iG$u*Z_Zg`V`U=kX(2#yB98~#H5~QUO z1Zm1`u7x_hPvcK4N8J@w5SO=z{l0h=)i-FfVgbxGFAJL$O*Kf#!8_N2%CkrkDdp6_ zjs)@-)5=x0%@NyO9w0|v`Zull(on++^rxmvS<%31Rw}HVRvriv5-$qTV;!bqaxlrV+oN-^Av%Aw*M=c` z23qAcT8?A*4M)z!Nf8EArs)q1E^vW>eVzS0n0;``HNkw6K3DBc16X>Oh0F zz#P-yb^SG)ShGEPS-q3A7IXdqheQV7F^%v4hU||TaD%G|*RbEK(Q7u~sCQC>#hk@` z(7VEb8(c-WR(g{RIO?6GsF-tjAM^$paD%G|*Glh`X~z1JEykQ%eskpdK5f7at|DB6 zL(0xCpgF8t`1u$0j3!8i23_QmvtD#G--j2+Q|#o0w(s7fysY^}%5+-#(!o!9n07j7 zCuKVZM)-dq{dd z)+fI4J0KdT8>I<5=3L5X(mIl_KW$^PKk<0zaq;xW2@fulWm`m&0V+Ry-#TMDrG0f(;ZVLVV6E)5)tJOc^>O}#Nipz8LLzAxr1ct}{B ziC81Ch&eB2xzy@icVqvO#wWD-RM?D5^1CAEfdy7PP{G@-LvlG5plMdV)Wc2oC%0;dRFdr6pC zOc>Y`W1!%)7#{wX$Rz|0*}tBOC~KQ?n>Mi|cQwYGyIVyo@N?S-Ax)mjYM`7!LVbQ7 zYswKZ=YKO)NEBneF-jAEdbsOD@~=Yn`-r+WcLY~a1>@aS>u*?A69x{YZ_b+QR!+eI zb?^q4isYH3;6Vp}M*6e)Pmei&%y{8VYgu%=#^o1F%A4E07fW5(|DH}$@^nneGcinF z&Zp#TJ|)lQQ}WuANj>OEZ%394V#!D|Mz5}iAg}7&gw=J|z54hD`}%q-*@YhmDE1|6 z>Amyo-LfNR%bEFZvYu!ras@v2KYnG>8?&$YcncciK|`xBhz!YhvuglidNKu25{yQc@Ks$dHewo_=Q+yYkLrwZC0xQ!raI$oH-Puan{zG zm*c%6t3x^88|X~(=kZgAB!7lnvXz#T*vf#L3KK$C6%$Xy3mwIre|eCqM-Q_(%mpAd z0B6ARS}NJ~JWA2gP~^kzSWKe}KPR6~hm_W?-7)8KMj_tSo{l-o8AzWGx*mx+=QB`z zgXr$~{O}`845(pP86gKUCF)Av3NhaInhu2j^5=`=Hi(_JnDeV&nyNw0OCwbZ?V}oS zgWfcw_Qm`l8ek1d9Q3+z0(*nY(L}BUnd>lq6pcN=m4IZv~DR z=a2r_@7|H%!|nHX16VTh0>*=`$6&v!okN888_)9yCiub}>!MPf7G z&auIJvAMp;z}Om`>q2Y85qBTFh4n<`Y}nnj3dd8q=w$PT!hzVq4xe80X1%s@NI5nE z91qfk0Bp`-1~$yFe17Hn!*HrBC8`7D0DAEC+6d>LA_s27{EsQ-t;jP6FhoPA4mM)F z6&Ztd2S!+&?bqkWoD&}~w<2^HbDqM07>Tvr#=pg!0~kmj^Sk!MoL~Nzshf6%RoLd2Cv)`f{%NI-9^ZZA8mQ+S5q0=tsCU^MX<)tL<`V(ruZT zIkWhWsXjCeq9u(=UfvYPEdkd>2i15;8Z#gV6eNQybJ ziz(uK85f%{2#_nDa?^?S^5{;P1Q@S&gRYdWYMSI`y)Ppy*d(&RbZCc)fQr{}cUh`DB_8 zsA4p!e7*b377{6%faZXI6S7}n${)gWKZdrLe-*N4A)giY?clqMfzC_yE~oW3Ql4YO zu9(vYDNwy^y7M(j>u{dc^$q@$V$M#iT?}<17Z&#MRzx1i+qLK)yFT=E_6mDqX#q zL5sA=xP53n=N=FBG2_1xiShv*>GxJa0XSg2AcuC z)HK>98;|~;gYrc`+Ad9-nO`l@R z%dvUo3F^1ww?m{+ae3;1!sVfSFZU5}UHZ3RRqhR}Ou-@SgRC}BO+U%|4CymR{Y2ef zzUA)@+xGI;zNH%wn-8um%1MuPrHcL%r$2&KZ8OT^yw-;u_KUn(U;E$34X4W+2rKgW zP})|W?#7siMI|Z?+e$+yN}v*udiqHycJofE*r;+keP~VumK>Uy68X*FSiP2}s9%oX z*1T^ex(2teIRCpqKF~$_MsuW4jYbpEYff^kX-B6cMApP_ppLwWr)W)_iOW&vK>ZgY z2g!4he1H_8HGDb)#sMhAi1)&%RXCo$(x83?vX*p^2}yW?F*=GdGw+8cO20S92vTc=}9gocIYonG~w z(8yDJms$BoI(MIdMu_AOp{3i(ljYznZgZr^$Zddnvts@zfxDVW@(~!FmSW`B8r|l< z4lYbN8L(1>T2@gl$U0}BXm0QqG@}xT-%pI>53ENx4RSR88#2-lL52rQicB&O!7@iVYj(lu%`bSa&2+^Jaknmai_^+UR-faHi z7m^LHT zBoB7TNBOe4Z~mB4qtWTI_O67tJICGiM)=-&SAo#8*rp?I?HWH!k~ct+63&v z+)IuWtp~C(?bNaCAsEfF6VRG2s8`B*#W4r_5?ivqb#HC64+tW?hI<{2&IZ9BD(J-&Ntxi^>Jj-k28hHb)P_M&gWqi?IfaD_T!=m8$WPo zlAqWstJyn_fa!9Cc8cE}twCuLXip~w94>lP22A+ZK`d`*s$ri+3EGqHAWb(mf)NA% z1?{;R=&>lp_|a>V@(+G>h9&tgzinJ@XGbU+w$rZ8yS8=>aM{$Ge{LP^$N*+)09 z|Hq(lFJ~0;sXoT_s-x*Eh-EO3&3L85t6d~5KeD3b>`0teSq`eu7^``u`fLn#flir2 z`*me@P(=LiB%(YsGlC;XO1QDriuEJhn=1j(PP4uR&`m&m{()74(rkBzTzKsonSVVt zavwpqc7?2KEn9!YocnJledrqP+7WZU$w0UW#qYj#{Tc1gK)Qaq9@5-8+J9XYr4I`Q z4yE8DPa*qd*nf~qcH+ZbJJ1nnZ*{d^7Mp@y=Kd$n16c>$rIg4aCDrBKn1UL}xQPbG z5dGoH$S+SJ!KZEqCBFMU9J}u{VaMKFogI_2y8ID2H1*Xi)O#Op7`(4hP``*=kCNyB zXA`m<_}6fMXUzF^kg9C)%VE$`C_r@)BM8<%+WzuPt@|tIvpuKr)XvxkuEq|^N~sIVsKqn)~50CJ?8u^%h&rJKAdG7U$y%D{A|5G zY{LioIw`KY(NG(V9}ns0Ew%#u2&0o>fTxjzjpwTK6!1HWetyde9z{R*jWge!RA{#KzTW@m;;*!P@&GEncj}ham@*ds~ao(BKJLEXoNy@jhD1->Q|{ zrN#Ga@hvPC{u@8f#Zgdj*xV%;hO0=Sa4pFPb16%oPDXP?20E!m!`y_xu5$&4O+cFA zL@uThp#`Zfx=oyh24L=6WZy_Clb7nkZeips!eJlWQ|6se{xe6lGmauq|8i*QJkt9D1O#%rVq ze_Gh|6(9dhpXLJgE5Tu*#UP@-iI2u&M`KNxHKlz8fVdFWk{6Vd^Riy4!-s?OQ-br7 zb8WBT)p5(~q(YjZ!lSZY^us1TkIbc0yykGO`aC}OK~zfi(dBG6u83WkyX9|*dFq#P z;@C48x9k-D!SBdbm^r;z2MqOYB$oi6+R3Ba)$F9Wrx<|X*w>mQ>9Sy+J2{3u7in57K4@do?&?FHCB z-x_%gBU}2u==GQYF@*n_NI>LdAj}2A?4Zw`9Jv)Z0Js3a%oAzgujzP&?QEiUh?D}> z0{>zmHyB!WsGp$o6$Qs$0h-v2b;{~z&?5iHn!Z2SZl8>7s9lQOISl02%Aq6=!V9MY zBnLXXBfH2J9HU3qISG8LnkM7?yaOGY2J7ndB zzTnu)P$CDP%5I(uF211i684VkTVD1)>;m?_(|;{z3GaBgEL(#7tf$^mH(4>o=ps1`Pmn}?5$tVaq*v?CyW$VtfeU1;MojLVAlSoifQ8RO$iamX>?U;hf=Q#ivDdpE)$O0D;S3TZG|v5d zGLxG+P!{a}fWJYMiAQ4l4uu@^5%12-EY zc**mrWE-gkr1m*T!g;?J9;e$D9x0ov_^M_L%c`gok#&Z~+ETww|Rg36j(I%jt*Z^e^Po zx5`;>E2qh7hx~O1^!D#D$W`qF%xvY2FJ0~0UH&?>vFSohT3n?d|9_zvsA@5{L1iyp zNv`R1k|8+uDO4T1M{;N(E}6guxro3tV{O4M37J+Xr;}=pQG2pcgl0z0| z4|0G)_6E?TG%EY=n~1Re8W1MLN$(=7-F{(_Bn?WE!tM6+kRoNH4i_K^)N@&la=MXp z^JGuV`5ci64ZHa~681H`#GKjqyNQTkdj)#KTcl+OQOLm=sr>+n5XymR*>6EI+5pR7 z7Rmg*plvD^U*Tnor-l&Kubhe@2oooLm67At{Sap=I#Q#f396T-VqK2W@k1ojcRvjd zQY4f3;1;i=DT780nsfgNILnN6u!TCmQU`rcy@!#00r|`3PrZx1tjEjLyBXOalI$x$ zK%2Rm?+oU&Wp%55zmN?G%A*V+w!0VopM#Ea#Z(;Bg#8{+p`IK0g+|5EM7$uO@)MRp z(nYU^F7)wi>R2k@J{1db+`kZh8{Gmqtr11V?hsy^=oKSzbgr>HANQD>%Iu5R;w11- z57SqJbYswfDNKlbgz919pAdZy5ayk6Wp)iB)aVW!$|~?z4*esb%t6!d`|17B74Z%P zMd#hupn`DCcB>u!aoFWlTriaKbIHsUWRY=2&PE%O67>3sn^n|5$5vv3d7375j1*U+ z2uAidXvSCH|5AQTR=>_2|Jfg0NaC30{Fdzl2Km(TBpI84!D+bIxNWGK{Z-<$WHq~o zW@CJ;P97gov%ir8F_&@?9qb+E%+a9!t+;E4Pm@4@>S0a4~OJXLiT(Im? zX3ENVX2$+(VZwg21~*|BH(@1BGha67@Ie%fE;0LXG~GcYnT@=Uj(PIcT%R;ba8wze zC1>rg**mOKS~i2(yYf3`>;CrVs4aw@e}%>)0hE>0FpqKD?qJNjRvny{1kdA4)HJ#T zf2NX+JDTXjB+Sko&D5QRt^Za~TEcoFS+{2Ej9SzUK-@n_KNww30AbJE5?R+P1|j-v z-(eVCBx3-^g3~-w^fTQsS>K-mr08B9#*8(MV9x`F5k`EU4jT0jtWoc7Kt+RNoA5$s z^cUhpI(a#Prrw8~mf(;Wu5WLTy@|>11iBbA2$L#?tl)*L*?Xu@(u5_p#2==r5{vZ#!>~ehLAC8-@>zL6co?zq1sU`s0nLQWvZGcs}1D% zCNn|zFC(e!`>1V0!@iUlO$c4tVN|;Ok(+6T2MJ z2(CoxQRKy(K}O!Wf(XJ38xu^(+UpDpfG=V4L~PD6!p0T+c7R_GTfBnWc* zg7cPwPd*`RiKI}^3JuF;sMiCvYY!u#+D{@bYDd>wSV(-9MyuG|x>K+u_74u)6Oacc z;y50T?{?Ze3hL?iHj-Wlvu$7UFLc9HUcqP*& zeQ!gtr|}+h?jhuNTOwT;N^r4N*jr>Dz2D2`BKjkjc&Es=E$QJ^S@hL>N&;Q5DqppH z)Q|)$@3*y-ugaRWNEt-eC|LjMdc`~*YUS}UIef~}XB&kZTm!K4mKKQGzcj7Cwfi}64k8~UQk{B|mz|a#D_=F$ z^J{$Kd=bXWEF=_6vOTCUyC;KNv+)-U36Zm58|c;V$R$o0$g=HiTrPurS0zBcX# zP|Sbm9}umCiKYzaIy0=dsed6avVhCfCSf{ej85f zAGFc39xF($Kl@G~2A>(wg6`QIQ{XYSvyQW52F)m6qli;W#31p?W-1iKz1s9za)A1qv}qP zakfHlfkBdd9!s&@WuMC9w-B)43Ul!mHpUoWz29TwF01GJr2Ff5d`7SLw>9`84L(AP zztG_4XzzlK$QN|P`)@V;`?dJGUhj*wcY!D9-_i@t^M$@+ zip64Fz+ToCzT*9VTl~=jxTpHdSgZ)41?l+@;=81f?nb!lzhbf72n!I3kk^g)Oauve zVZ65@otHCxL1FHKoLSPm+!?Z#T$s;6zBxac%~SKU=M^r@%blGgQOXxj<$Gsv*g}?? zo;z>8MkLQGQnPakG+6$;oXa`E1#@Q1$jjmB?7STByuy6%f(1GAW=qq&*)#PQR&cCTk_2IHmkDw+GXc0o1EdomntijOUhj3#g$e5y0VM0#Kq$+Ev+l7uXl~B zbyXDCyQ*tkl}n1REjzEitVF4-sg_)>%PZ>?e{t1Ze_7pfR=BLxRbEr)8dvICyj&@( zcNHtHVx5W*MlY9NSEGQID7massc@CxOPyWrhH-GoU9N@I*H_mpt9I4am-$O;Ty^w4 zy2Zqsz8G4mDXFP)EiJ37C&0MUiCpTVms?z^xauo^T4ux-a(VvD^;6WwWAS~)BEMsf zNbz_^cJ{@tv>CG(j(25D%$#_EIaiW?$p1k@NnK(diKb5B?q@A*s2JipV z4_1FO5u{d0%10a+fv@66x&`r}6D4UB()8O4a}d%92k{;RH`1Mmzd*<&94E>mOhLK@ z@k0ncq}vc*coJ5aNP7^^L&!(E2=N;T3y|(aybbMGfOH4qL8I~00!XJI_MeWE52PCr zN6(O?dywu%Jnl@0jIPh$kUzMB0P+9)xF*Zbkgrc;F)4jrbMV z#$Kd55Z^ojvLM}v_;G}8q}vd0N9Z9O#NSXrS~^dXPC`gp2RlHVhmeePKH_qO6r^hr zKY%b2=~l!W5XK-KM!bI_$|2p2I0CiLMF2u_b@{w*t{46}10>VN320{hWoroJQl%y)cLA)KI0qG9JQG`aMyAj(n z@GV0~ryw3YNs?Am8u4U=7Nk9hD-rHNx)yN&;Q^#u5YL~Cx*}bKxE|qgq#F^xfY63? z2jc54lB6e*u0hY&%!6Y;kQ zUlIIb=op~~X&2&5gl~|>m0{`k2+~841MxP5p-6Wi{t_VtY3aw3v~>#Fi{Oacy=WIo zBc7WL8b}u*UXcUcBHf7iK8zcsNVg*1jZlkpC*qrDK(~a0_)~<{NOvRt6UL1eq{E1l zG0v<-ItB6F2(3uBBHoMeIMSVnhhqF`BOJtMA#6n2jrdOp&mbK}{11d3NVm*{jpRwv zOGtYVUxDyC(nW~xKzN665FbML7-?yiBqbtrBb|bHB*IrnyAY=$^dRj zc@E_MHFSb_|2*g#>2Ad1=7TrVZp1AJQ;??kaReFZHpDkBKtDmc5%G-+@!J}dMts3f zV3SCD5Kkz;rZduR#P41KJ4Ct@@vKFlhjc#TR}or~?m%3F)6_PkYY`8`M)yXfQxKnz z5JuXKcpAd=?=ta z;gBxrVbDkX9zqJzorpg|a1p!+{RJTvX%FJ*2x&8pNefS@TC2G*Hy(6(x z?+au@z3Eb$*BScIV7q-{d;Q`Ak=g<@kH8)+KTMjS!I znBSY9fj*KyJpUhRfc^Fw>Xoq#HiUS#7Sh7-9k#$n*@`)A9Og6%XCku}a0K$V$u}aO zn*4V1p~-I|znc7e@@>g4CBKdQJMv>w5XeV%BPL&y{7~{g$v-AvlKe*U7ikSa{y(iT z$ls^61Nq|QGm=kBz8(2} z$QO4ZkZ(->I{CKb$I^O+);f)+gFe!{u=pa#-6OJ_)DN~zK~=`87N{3hRc=^W`?X#$L5 zqI5ofRxn+(VbnktZ+e1?Yx?0O!{npU0qqVLX~3K`8D+hspeMz zP3K1nDJ=2V)z{P&*4ETZNK)CtN-A7lS5{_75w1iTg(WpO!r;l$vig#`%35|r!SX7r zOUoK~US)NqhE+|Xvh12#r9Pf2tSK)yzE$%V)N%<=`RmK-YLz*o~KIdDse=?(>NN@@{w9ntZ?YHb!E$Wib==HlVJ56xTLsFBgF(|*_2{} z8s4fodTnv3NGK3mgVvSZ;4g#D7cVbl6=&rHFb=7&EiS>K5GPRYU(6G%?yQ8UJ9}AH zSuItgok>=fAgG=wtgn^Oe1!~^Hz&O-3?S8)6jzmL$ufnSJKo0i0BG%o#?s$d?e#Y% zll~^;(gD0(=#}wj&7r@sW-z`{Q|RxkIrKNyB=I-aEcz>J8vRWdkg=q8(6efbd0XfJ zq3AdO%GO`>$}vjD$}s>bo^X|#+QPb;Ws->f)o}&WsP{kp~X+o@AXJe+v^;+y-&(h+HwOH2TQY~Jp#i9;B)86mV;)k@jO^Y{a@pdhKMT_@p@rPQx zUyHxe;%~Hgz?+;?iWZO7;#4i3sKuFDJWY%9wD@u@F4E#EEf(@OXzz_$e7hDupvCL8 z_(?4eYw=53yjP1q*5Yn0{zi+FVH@;})MA$wPtf8iS}bev0xd4p;wmj}&|*#vzSR%* z!c_5ty>N^8E_>N4`O2!wl(Ou)N~IDL(tPb+LyweGjUl)Qx&c*l;CcJ z^okXhTPp1~Ko?Zhl@*r)D5WHzd|q+Al2cb#QzuEc(fj=6^_Wx^;P!>LetKn98KtD( zP|kwNlIydXTO%Dx$c5ulSzLvi3%$jfnV45rywn1g{*uV9W#pIDF=wN?q>K@RFJeoY zr&Qr`$8>)+yU4MinEaLmf@T-jD!2fWT>}N+H>3vZOhq|cHxrrO;RtX2esRhL$rg@y2^YpTl{;6BX9TV>7S!gACVD*~yo zcuD=Wg)B>YMk*|;tE;Y&q|vrQn&{cQd$X+&w@j{=QWFX_8tn;%{%QuhC9!yMO`Rg$ zkqC1E1nZ|na!Ij1Ni1ImGeW8(v9i9lt`gqpXNgNRtgjN6lr1T#h2DlI)mL6yU0j8g zVp6?Q$6#kss;aD7lEzc2x@1YMbPi9UNOqD^cv2JUl~RzRbXo%3LJeM=und=bN-79m%F@-4Ns_KbT2bnl zgIXcdU|gNBZ1MHimcn(xSzN+0atfDMm#`{G%M+HBRhLxNkQ_fnx~`Z~_z+COGA3Q2 zQdeA#mb#tZmzGIu6PD?P?@w3;6_r#}QRT=7`45DdxDJ++ci{zWsRkA!!Q(#_meemT zsZ%(oH1PRPgk?~CU42=-s1K_2pLC{{OdX_k*>(vToEm*Sa)7GuL_6$?Njh6|5^- zSFx^kUBkM@b*<~d58=eQ6FvpdN42_JGh319=I>H#a%)QKD1!X({4dwQ#B%trkntph zZ)5NSY?#L2icN%{WPFme7aMj~6K%$vc-nzvJ_6w+Fz_i_<^aTrERCZ9sRfyg4uedk zzaY;`O=LbS%K!wWY;%y8!2#OeiKWF#v6d!2N0MjaVmSKR!?@c-4FnW-g&N|7?2Hbx z{x||s#{0xXA<;%S)ML!g9K4P~7=(~$OU7TTlCA)>8v>Ii5^clr*ZhdKZ~?5h#p1GS zE34zJA@q~aG)8pHH0bU7=qCmETt8Mi1RV8wUgCL*v|?AqiNz6bsGRJCdfU2w3#3e0pdZW%oY{bSOVH$1aRWd@zR*E zD6$c5QK@kzT1r?H;h?f;K^#~0l7~=9^X`6Vemd}k=E*;-sWT~FdK~#hLK}T(J`9{r zfg=eU;W^$KTL9WzV?fh*|9>;g!FenTqejjfaIGX^sCaf zCdf!YT6KsR!?}c{)ybe?_FF{jxRArz6mjq8`?O9s3iH-+_a>wJQ6s^Fw@wjo%p)Wf zqSoo?N9+6+c%pUK!6T+VV+);%3WbF>j!-Y+bv|&qPc>?O3Lq(`35d`kr$ait7L=%l z@#lE!klNzA#veu3VJZYMkB1}~>9D&WI{XXpOghA&vQdXKpbfXsMjtwy3!Hp`6CV>8 zgfw;`31oVXx5j7$p}BFmg(+?o<9VhNzXW^H|lvUw9zTF0iH*C9sy3{nL=ZP@gyJ}Cdd{* zx^;-qDyK|Z9S7Rx{&l>yO5g9wtrwF*uSaP0GhM4RuA0YiDneSN)eTJGsMh->@=aRB zB?O~ZUxYSNU_{K9ID%HiorRQfLaRb!ycBV#Z}2pG=EqxOt96Z8H6b)M1~q{~AWz@@ zy|y13!v$Hh#&G6h)YzNgLpLM)(ilX*55-_i5IFh>$xD%h*(4_+>d*1k*ggHwSVliI z*3u7+IeTjiw|a~k`zQFc2yFoONKX>fQFK;s8{?%&V;`XqmS=|Ncx$Xx*BE)F=116A zUOzO})(?%*7-Q;{xRhqpm;>5q6xuj~#zY_FIHaE(v%q*e-uj_&-VVBnN7_}Z%oiQNYaTNU!uXBM@d$zDBf=mXaMTZC-aynG64&eM} z$FV1M9b);`>k&3qtLrco80MLXiZD;FA3CJ3y%jbFAH-;0jI$ToXcgK3ZtsWu7P`h( zlxEc7EYhkD5jx~_NQak$l6j0i-gdY{*P*Mo$oh)oo_^>s1;&iZK<2)EKl&v&p+mYh z*jtG|Ap+x%J{Ob$r&HiCiR-DQ?uS;F7_^Ej3cZyo-3D!Vgf@WN`w{mx+XPO0hGh`aSOA6ov-1TlpZR#$_k2Nq z0JDwpC?}x^2HffCAQ8j7pUTBOyiE%Wayh_%T*yJyfJ1c5k9GIJiX`^TQ*<5nZFMBUUA3D4XVu-#>_is%KL>0Dx4}GHJ zXgYkAaMFdwsNU}aQiKIBE5#J?DIkrL1Vr>@PMI{e6GJ*aL}GZpPhWPS9BV&m4p-|sG|yecPS|0QuEV2vjQ!9L{T!s| z-P)ynlZGyYe!7pMACk!joN#9Ep36&-#%LehT$AIiu@+rpea|UXy2h+lN3~%7VLvps z*Qhc7Vw1Lr&Rl3CC97|XVzV$V8MX=>y`S<@q_G{K^Plaft^LqgQ$IA8f&qc|Q)?d; zXY^5n#2>E;=dL=JK8k-J{ksR^oc-vT;t}(NpP8>zA ze4rm1bN54I72qX$C9bQQv_v?ek^CO1GO8l+Fktrp6( z+hd}WQG~jiAd^e+YNp&{k-5b}nRebxbTT{^$`dS<$x$M+(CdED!xqYGEtJXXOuQyn zStuu4D6h9rZnaP*ufR;X!9qF3LRqm;&a_ZYwou+{X+bOH3JYbIg>tvWHlDOl9%YgF z9t-6L3uW0N^Aw9VTo%d?SSYWyP%f}gUSOe|W}#eVp-f(psl76KEZPWLwBfc;F0xQg zu~6=`P=3HdInzRUwS{t#g|geCjgb~@cr27xSSZUD%A+ilyDc)y7RpT)$^{n6X%@=K z7Mb%clp8IS^DUHJ7RujPWG=8!zTHB(!a_OILfK`JxyV9!t%Y)t@yvTUJTVWC`W zq3pI$mMoNCvS_2$Lb<_0*<+!cVxj!8g>r+1a;b&#C<|rUYeMzoqx$6a7Rrql$^{n6 zl7(`Ig>qv*C|_lvoNS>?-m+Qd+vAkA`?SlUG4AaYEBqr#W`{=w)fQGS+;s%K-VZ)$ zMIVKdJUB=-`-i*~G-lh0LMNCC9&i8fCDekieEarxUh0RpQ+qUTN7Gn9*BCx#R<9J} z(=;Wba>6$*V%ng(i=23Dtvj`m`4Rh3E`TA@5$R9~S~s=yL*~bHnU$*gdcWy3mFWBe zt;}V1^~viuWC?mJ7Zx^@78c_>(@+|wh4S%UA;*Tct zA`d`undAAC(r~;~x=$SNN?o*Q5y``OB~ww;Gm&t-UatqxzHq1j*>hVz?D<*Up7E6u zxK`C*IPDgFFojuNANHeNDeaGqxgk?ueUR%XdlA*RPyI0a$@T)}J8*IrxxO36OP1aj zFJv(tcJxDsujo3&2WGEbR#;J1g%5(pkBh=E7p}u2kNm`|12`^A?~ZH!2q%WeqAz5~CWdJ~5b&T!y#Tq;IUf}9J82QkMHHqW_JO*bL`0z%ZE z?=!A?P>NBu9bsJ6#<4bi9JBfbqIJH}TZcwZ^CR|cT+j&qL*`WcCCfHHG$y3LZ{cHR z-#cB0^wznyq-064W#{H%Xrz0ZrbF|v%NW*9oSdF@Q3gJ>tj#+Nnuk*EY@zwWLL!WL zP=^rGHNc?}+uRnM7uD+-^NHZaJ;rP63*k%D;zR54K7en{g&=K0KjtdwQmrD52|f3kztD{Axequ+-+}WC za2kE0b*R{@R0?st?{os( z41ea;1m{i~yBbP4g^20T_h}un2FAky^R=%xPE#e zXs;x5OFv}3%qX)`QP=y%L>-uLnO#Senb_S0oK_(Zb9+3RYgtZXpML<@Y zO1%e2hY9CfKx*+V)Mgut>+o!}+?kBN_#<=}AGJhIJhti(X58x$Hr4|Da2s>?!ibLm z59>BYIM$O7YKyjhw8a9wEr`_!lQ9bWNy+~j|0+ef@}t) zWwx=@tAKQvAfEx^#s_fCRu|X&E2y*ib3ot6>biB!v#Of@2&)V0R##-orx!7@y{=nb z1EA)4knqUrx=|C5LeK5nAG=*|K`ej@%WKo!@ixROe*LLT=@i;H!l91KJyphII&^mo;Oq_NxZ4e!^=S~EVTfH=1 zZn%}-HDC0nzaP!&NN%dT`)GC7cGc+gmd|ncP=7D)-B(pLi`;H5^O0AhVjPRt3qyRb z=eX%m^SV>}VH*Ygu#NnF=w}vq>H5J}mewtg_a>?)z7|~aur@uqemD-<*neI>Y5mYo zX+QK+do=xM_M9*5+1gViF)!=3s-IK4;JAS}dZu=AJ*gFTXo6(aqMMi?lT$GIX%LNj z!7*|F3PenlC(-RJ6C^|2-_a$U{16(>%)RKCxR12deYJ&qfu-(WS-4jm6ZdZ{buX}R zPqT2}WZ_AndxwR4tA%@>g?rmEanG=D-(lgt z*1~<7h5N>1;+|yTUSZ*$Y2p5g#pc7u#GN)LOucDRk%hb4!hO4i`;KGc{+VT@&9rb& zws8NMg?q;_aZk3?z1G6rW8uEn!hP>CaVLMnta*=xdy0koJr?er$HaY_3-`z|araobcUri&S-2NjdR+H0aUW{o-eBP_TeyE{se8{caZj~yUvJ^wVBtR6 zQg>;twnqD2K5d$Xdz*!OqlJ5FoV&InyHa0qlowxLW?o8Fu&?!pHR*K9l?s3L_4p3< zI4{jNP7$>LZtv%~t;o2aZ~>h+G7Gm+3ZfVu&BM=#%Pf3;gUnjp6R|4ct1WBY#Y*#k zuwEHqq32#_B~(38i*BL$zHu&+g>Be|7&OC^mU?|Jt9#xu){*+nqfG}GnIMx-we+}A z!dku;_q`VGX%_B17Vb+e++D}S{dEg>mxX(`g?p)md)hH^Uu)sM9-EyeJ!jBPo(VG9 z1q;_8Vn^thxIbXw-e%$6XyNX*aL+s@?kyJXYc1R>EZo1s$Y!p)=a{(PW8qF`N*ZN8 zB4yNCxDU3}T|Or6trqSZE!Rx2w-f0Br zjK=?i^~#X?v6gX*{&keK%saw1Z07HKAiarCzy4USJ8sRCRhurM{7=@MWTKN$@>fwc zoW2bwkm(V3x;kOu42R{8K?xdr%@CRk%n(|Gm?51O2<^q0ap)Yx457VBGlX{R%@8_4 zFhgk1!3?1tR}RrE^MW+g2kZb9w%P*(6U6$N(2R!O{e9B<_}Iedf{PvpFHQ%aK`1H2 zXAtNOKq-NKp=U{L;rx8TD?!4~$gp3=;k)SKW=JNAw5@)AaV$oq==ljC4Vr`;QUZvu zIu5y+7~!Ee4p{?8hc-%Z$S(mYGSPVy5aF|NoG>85AL9_>)2Nr?zZxV-d=@%q~FOCJ61{yMT*HO`}ZTqAM(u z^C|%(GcGfJ7bz2(|493!EywW#hn~2eLj*}NLLLEx@3>M;3qj{X(0P0`-woq*{=n$C z40K)u1l`>L`4kXyO%DOm2m+)gq6}@6LT0=XIY4m1t`OsdjJLQBok)%{Y2yq)AhJP+ z8Gz7vH>Zp&DH{-3*9Jir5DsF_iy)O9Z1VY^zMw#1y z<1$IO84x!}#Wnv5AY@Uz-NkQQ@lQCC#>6jD@y}@r9d@FW@bvnU@L#~;pJW%M2H*;k z*at|E_%DiKw9#9cG=BkVF$6k9vub)i1*PH=vfnr>EJUucH;t#uO(w`CfV4rhxXoV$ zNQ+5_6@UnzpV#6hKq7kU5XIX7iH}i~z7G&Fs`FBh15%*tnQD=NT9l(Z#cS~#(J|S^ z>wu){)+>H>jDKpCG$wv&jh|%;9e##V8%+`(0z`a{mCG|gb2`YZIV1&;23c20-#nIE{da^;d$#fBOzqH*vooIQ$c-qF(C(snxYX zzpqBWsg^H3-AN)#e+EvANy4pw2>+1Rq5}|m;_bd45IS2Iy}O~3W?>g_;$z)G;K;g! zwd{ji{F}AoIEna}sMy2jynY0TOP86rUI+*p*+4m)a7?wx2c$*kMWspsSq+kLnQsO} ze9o8ix*d=Sz~!|NzojQJIzor{0tZHCpz~WmNSJtk-$D=$)NEr9Al+ac$N2z|wYofL z2KLK*ZF)bY^8W(PUQ=5P!dDe1n;Jag(fhi_l z?Z6>nI4|+*fF2Xh+raUdczsH|ba|j3_Opg-O?n;(bK0m|i}b?MwMx8tVbwOAH^N3tj89a-DGfFSTd=m5>4{~_FC?tnO8;uE{ms*8V zJvwFatB{TP#_{miz^TwFi{EABpMMwJ{{Wm0z3xPRGnLXIkf)M7MgR>xu7h56%2etd zK-L>el~5^q;=TKGDg{b$YZ*M;IPXyI7(hVSfO8HYPPk|o1hl$m0kYQA7Bc`T$R`|8 zuX%tJp$KV1GJ6iJy-N6uAFt_CC z7ot=vUQrPGv96K;mSzH{Lf5MJ4bn~>LO2V7(`eGzVnBB2@(}mQ;69suGoEORTHw$V zw}jOui2nPVdMyb1KHzlEG1lS{KN#6vB_$D9TcUk~x z(=|poj{wrCk3R%?4iK}(IssX$*OYMn4#*B&9)cVOq#g4dms$K4ZifkHAY6jg|F5ts zYi`>H!kqk!KIgTa)M?%3(U#?eGm4^GbUM@N3<{C3#ERGOup|HC{)~RRi-VM8=fNJF zi^XCufC6@c;SVTrXYYa`efs|dctHlQsRUUFUGye$(QW_pkR`Tm6#e5%2%o>vYXxKo z>YJ!S4mTB4${~Cs-VnvhIDx=42+~Xu#B{nd8S?f=>ew=^=}ibko;@v*>*Dd%RV0T! zZ=au^BV2>vH;Wa55gF|7szFk|e4`ODn9Dik%eSpLNI9oel?ogQuBGr^XoSCU8OQDY ztowAQmI%SDW;@;L6p@KlT&WnLqSaC(LNt#h0jDO|mAd!%QJO|XH0KJ}bGUcMB{zAO zo)pe>kq!kO3sDIT{AZr^JL&H$c>IN_w*5{a%JZnrBCqzN0oJ?vNqq*L7{C%wJ|}f^ zhcfCllMvbjEZ|OW1PJDw@)YEl%sg98Q8^wHC}puj%9nF1F8A$0>=r-A=YG*7WBX_3 zTf|BJ$qc75gMi05$FGj!POT`QGlj`kYs90gwh?ir0Q8u0SR=-iQywFF;90;^ilZX) z5R$7x6%)e+M)2M3i-6M1Wqd83#2<{*jgxtoQ%rA<8x7c5@^X?fNIAN=dyrdojZBN? z5V|t@JS~s@C|3zkZsbR!_|V*@f$*8OicHz`ho3GlFD~B)z^;;5bcKg=nSF#kTWz_A z9@J&&h=wYp88%*p9SmxD&Bhr!Pgk@#NE3eDRA6~T?Tem*tjmPjVH2=*l;^Qs#y6#y z+44k#jTw&p`Jv*Ys;oz>_mE}oR;X#sR;n_S)|r7W0E;2YH(beSUbTkqZ&R#thQx8k zF_E&y1(Sx}ws{wo`kRej4*_pX{{Ht%)ecpUVDjjWNac7rsEwX<$8z)2<;91Kp9!g2 zNw6?QsG#epB;^u9SK`i-0>v%A0a4Bm3`M1gWR)BF5zyOFRyKtJ9ig4v+_v3= z&I?4Ik3OzRU(vUmJJ6-gsKAGkKU1_4vJvjG0PFcDA(gu$?Q3W*%GjIJOpKjr4T$mE zukXO3gOa;ql#<&+Y70egTpasjc(^f3G*)|a5c0Xju$WMN+C{Ef6?sQ9R!^6|2&&Wo z8+;GIAu1iMIXi0KV%Z}_?-jP9{)6FYp3v0r?BnV+dAZR7-?w3jYd9GIL z`TflobvIvpnW;s*POy~|cUunU6xMEoRm1;1)R`&XUnq_BAwvw2!E>65ADQBA>L&Se zH-#df1_a_=UwqBsd+6f6g4W2QwdwCGVam)i`fXmYF5oXC_5@7&yTe?|Y@GjEEzt~`#VO1<=C%e|@EQX@< zMJxEN5F?Z&MTcTYD2#k!T4*?ku&o9p1STHM=@ovSFK<9Y@ZJJCduVR44n63~q5?Q> zL3TzrlQjc@F@9hsAq2bSlI;2nj*^{}CknIe3!~Yk!6bS(rIrnK)2RN?5c|nmHKTda zGB1pNJXz%@SflPxrEug08{nGc>E0?E56Uef$OrC%zddFvf{uP?WkjILnGk4Y+G9R* zMBpPU%0Nr04YVt${RG6?&U7R;R#|`~Gu`yCbJoTY?Lh@%ap>o5MOKlS9qXJ!CeW2G z+CpXNuCDAX!D94vRK~Uk=Bx|gmSoW@$|Sx@>_L_EwI8Y^Ga=^pHKRM4wrF5xQ2vgu z64Kr5%7HnIsh|+hjuoX_3nIHcu25<=R+(VJ?3}^{1mbrAFkR_sm$G{#dDrM*$@rM2 z1vEq;qcB-&fnk9`I@P!Op(Y_Yoe4AaD;!`C?syfT)UltyTV0sOmQ}Qx2cU&Rvwt3J)(cAqR*V}`2a?NjSZ446v zTqf25y56G4ns#Mcj@DbH;BR=JHfxVPq|Scj#Nh}m(~%U=#O=2@X&ifZ z^jH#Ku92SZ$QUSykvXFV+yMmIkf=-z%`0+6Xnx;}yF)CTLyXuR>^AiW1YP-FbXMyf zsq3-%6t?b1m|vwEuE04L4JH@Ic(=jJE{daSo6i&$LkG7JoME zC0QEbAJO$=OH$N2!#T}Eq4DY#ksA)uzU%i2TW_z5oa|#yw#Oa>;qCcEKn5gv3mP*J z*82!k`6F^!OtFthaauzgix(XzsXN7+sWViJ5!&FLLF*M}u+bA5x-U#_(11N$BI^pA zcgUp2Is5mrsS&3|db+PCQz!Ic_~3@MD2+9_6a^{IfRTQgI&`^f*%nAeYqH)AOv0kr=X6IanE4)2$A43 zgutH7F(9*t0XfEA$O%402<+Psqk@pJWUwD{0@Sr1IItz!O%$}!IubuV;DcdZG?Gd|`1u-z-Jr z&C)_NQL5Z%&PDl3G5TY<*qoz|WLngAy>z?TvIHhV9+Ca-)!}2wh&D>1(g&Z$+jK7W646F;T9(tD32kPG&OSEX+kyJOX2L z`Fg(4EY+j&iW%Xl{6a~3*nyO*ajJAHx?ZhKS8vJGj4jsdrAm`$OsWbMyE?8^8+O>x zH%B@j30`bbVX@w*)}vb0%+#_xk%kaAF)DK#6A82SX6vPrDfBT_!j+Pg zNX(RQT~VRBSZR`qs#^RZ`)Z6Jm*} zl4`BlFeMU8l|{la^31#~jT5F^=5r=rc$a)kl@#mco29xbi{q+vwpuTlGKnQi7V=G3#&K18qh5N? zlu1mL$Sg=p)O?sUmP5ll#Iu6cC@W9O7V`DD{Ss3pGD9Mx=E|jIc9N;ovphXYz|NIq z)$&DC#u4>gE#JiC#n0JvPFX_ZZ= zni`8UaTy{iU)Gw`pjMrv?Ltc=)RVW$aX&d?@+&yKc!tPDd_Gqr`4UOyM~#{*;uIEe{HQCw8l&?i3Wal~wwU2ck@85JfRgdgsC!_YY z%X6bAylQ`Y3E9}GWQs?2xD!$P-Q~GC5T4W=NFHxkC+>Hz$}&56Sw^ZYc8fVVn~|2o zcJnfB@3}0uCZu(04>}3E1eRr_n0OmH8NVkvt68l@_3AAtwsG^cP1(@oE>`?r((&$X zslj1uOI?NK@YOb=yU?iDzeM!b4x*odiC&^_fWDnX9|3GO%>hfm^e&3<1qK1OsK z_yxE)O!PId{W#J4z^}lYuyno!cAp^n5cmz4g|%{rEtXT@0(wpp)qo`c1}Qy2>u5ba zL>p)$ZK8*%haRELw1pm}$7m}(PEXL2^b|c!&(O2<96e9l=mpwNFVai2gL-KvhIkkC z(JQo@_RwD1NBijj9mHVt(;+%cN9ZUGP>u#^h>p=P9j6gGK_}@Hou*f5l+Msu8l!V` zo?fHZ=>m<@MY=>2G)Yr*nXb^)xNZM`?RpS5OV^f_*%GT^9y#rLENQB^d~4i{^BwAW zZT93!Hjl4p1%t*3u9j`$D!k&250}@Gfg#d~E7=S{d#k~e%YAHY1(gxB2b7$;ilic? zR!Lf2Auiocu~*fqb6g&?XSfp4cecpfY@?i;XXJWlqlPO9T;i=1ZY805EOj#Xa*bL& zpoTym;ItY7m1osJ$?|t=oHX~Us<>0VS3Q!vWTj$OY?Xu>c_~hgykz;iv7MS~>f=&F z(M}^Za{jI~>6MkuSZ+maG9{<_#T*hfXoS8_>03bSOG&oX>r!%hK{@KS z%3A7SziQm0Ni)i2CzpcHcFVzKrG~A=vT&k)X>e9jDN3faTGY|qkZ{3i-xwDp?*sNo zwe)BCQyn7OBZXuKCpo01!u}<7dP7*9+epc{8B3o_xhn1V?hftVkWFB>1D~G~mjy2|IWtX6 zPD_c(l9re>)Wy=C1?LTLE(7HwNS}dHi_P>_zg_H7>`Zy-yJXqEOM(}%JK5|ZmawmJ zV(IBrma{s$cn2irm@{NVWjI_)dhb%wCYQ49av5e`I4Mm{+Nd%Ot}MRFTsmoGx;98X z+^mMTev*cwYoLgx48WANX9wD`@?g7!>zvf2J0}@D@GNUj3LEOPqK%(ky!ZXZ`T5wy zTInrSZg?<$ef4%v@q-8H?^pBJHa-9=2i5`q`irHR#T$LsOp2hl6aB>|;&7C>2ZW3c){s|HSDB5suQ~?_xRFGvHtU83W1ete!N1yu!%V26~gtd z^2~QKqc4KC?Mtz)$87lMvR(Br5QN4ou&dw&FhAavysPwYlt%5Yg6F{eSni)T5r-_d z%46HfxV`}THcPSFQ5_nJ2Nf%kWNQ{b;PVQO7I-o+eNZk|dOPVj$;CR{2ZQ#YOtJ3* zGmmSMT`6Xch`Qc;ZtJBu;rfzeOgIxdpC@y%4*Qoo)_Qb#0@q`Fnaes5#@Vmn2=1d_ z0j`HqT$Ajq$iOvtq;XW+A6ee|a0>^X4p-6iAb6mU=EVx7)coAvlS zIC%dvk5cVj_1(|bki7s>J%U41ZfIs&*=q0&aIp@1I@D$c;gp5P()2W7k2t#Sdmft0 zM`C7g>Ubg->#&C*9#&g;guM~vYWLfsLmvOFQt||46=X}yBO0hO&+eZsH_&?LJqxBs zfrL@uX}Uip?I%~M^~oB>V}Q3QJ&B8TIC8lF2P=`@T6HydJv+HJ>-=fd|2QBvld*$6 zN%x}_ID4P4EZW4*!WHPzla|X^?^##^bHi)E+nS!l#a3bdd47aL>}*$a_wyg<$1|2g zjL-}m@i&RBZYSQC(huek??VQjz~1MZQ1Mj!K;6d)9T+pd357?@?X~F(UPKxWYs7n+ z?ssNjx3Cr_eKC%YEG&VUVZG9@#J;X9Jb{^EV@vKC@!NP37wdFaS~Dwk^7C%tJ54xZ z2c4_iFSkxv0zF|ZQdq?2lz}7AlU~KaPQ?r?fu8UybLolr$JU19Wy>L6w+tMCox=8* z^n(|2Lk(8<`!O(D_=v!;h>I{oPXZkHIKgnN;hB#QA3Vnzp85EwLi1!g^9PQ%)+>+@z09s`%fVlpdKwq&RKsZF*<|gKox17wY_5LK*(p=tzF{{rnBs3= zGjIfMXMR7T-VJ(^?oa4|9m_9J_yyXkc^Cp#6F$QeF43E_>NNo#eB$SM)=(qBCxo6S z>xmYaqZ68E6;8EWz#ocFAbp>*TTp>nIu$d?8Jg9)3Gmj@Ol4bN+yta^Ol1bQvW zW4_>6qZ{dU&9w?TZ^*ZPA;FbV?+vVnam}-aH^oKGvl=%=VD0gjBknVuj5=^gcbtfM j?590`*|}JU8r?vfw{z^vp9Hcqg!;iBr|8d;TUs+uB)}AS}YbD{zs!0%QF1ZKPUft@;_C`K4svFQ!MXft{b$> z>RC5v(yUwV&6|DCU4OXeraSV=Zo2c%yS#b7zd7$7-<^54+?l70pO|;YT{CaKI4377 z-vnLivRGy==xGU0xM`xLBFz%XwOICA&O5tjO3G=Le*v>*tHm+^g^_NtQ>DGP(qI0Z zBJifyGz(t%zjU7X?(`nKUlvQANal6v(R_%%n<=x?EFTO-_M2&za6+DCug&t|1p);B zyEn~Z%Sm|e{@9UbDd?Vt_uO~VESreXzwqy3@68on?hmnjxCxK(9o zyQicfF>MciynTwpY6}-3)xR=tT9Y);X<3Gvme{LevB;CInS3n=8f;hDx)Qe1cZZht z)bG+P!LU?w3QGHRYw>~is2WSFM7pY7`KK2!@Ux|XsJ~oC1JTb^ws)^8{rk)yH6IN7 zbS>>3Jo-CRq`+oWT|N+h^o9RSO+es=8?TqAH~9}+IZnRF&8lWQw+Q8m52)Id47778 zwPRNuO;R8i2y|=fbhE9minnTMHr|?53S5MOTG~&Oc?SZ=08UH$7H|GeWDZ1TaH|yf z6v?WVHvV-RVe8E)VI3<-099s0+x%%yU6p1LSaC`TM9X=9i^In6qR}W`0w_;VavlJ5 zJ@*UZKv-qXUN_S2pfn4mfkFOAhU)n8{ywVKM-8@nzo&#~JCg3(qp~0L2mS#*wxnH- zDjZ@<+BxQ9akwSz{8;kBv;sVK@lRmI8Dkv%nWF@LfaMF*qSvNbi~)pZts3fUybqp) za@z6JlC}w1#7n&=S~a$zo?y-H7x3DSS5$ajRCp9W`VOSGr2P%Gh(1O=HH3c`$NFzd zPXS5KdbZKSRG7AU#Fwv+Mx%sea2nAu-rqP1 z6Hz$!!kYDWP&^ps)>u;Z8W*DymzP)({TvemDL55*9L*7UK)xW$y#Qbw1bLBS%HkpY z%RNLZV?C0kfmP@ghVE|2$|WO&tYGkXb3iTC@bV%~i-#%sL)oPKAu99a7wBhhOR?xL z?MShBG^A^kt|6UQkx`|VkNu&lR4>m|*+)`+o8!?8n6tSTs~RJ_riOBZ)UJN-U#ukH zQeY8b!4^=aR6lAaTR`PWj;k{*7DcKbH`5htt-MgxYN&{-IP5M9Yq`}P6OjLK)SIR_ z8t09X{b8%iv3kx|vfr>)3=!kYtmZCjP(!xr@>U9r1Z*&^wu&^(c7nR zv+57q6vt*?hQG;*I=-D8GW$UR-SU)>r+-wpOtFd%$&SrZ&9&f`iJiw%Pa+ER$I~6?L&Tg<(L&%U+GLwI)HjL3KZ09Bv|Qk)SW+$?~=G zHKx_6-c7?#ofRP+@Qw~C{Y9CR>j(@Kw0;+g&yt7H9~ zJ!_&_(kZscIcER06kcvE z$}vua!b6IqK?=@9N#Fs$_$`t{w?^f{hG1Bc+@AcQienuK-B9U~ z)zHjtE!ZKUm9j5Tt-{SdcQ@>?5g|&|GSpRBqiStZ8#-+2L8w9{e}>wyJw;`os;QIm z^W3TL>Qov1nxZmqzFJG|QRhlSbI5cn`KmVLFODJ4NP#QRnB#jXFdn~@k*C?7L0bO7>9W7s>alKj1rHEzP8U0OzdcbAfPs7up8RAGlI@92_uMazQ9 zaXGR8BJ74xl3*&K;f3~pCZZI0G~21g?GTl?J=caj>MCxR9YbmXpb?d= zF6#yt+b0*cyMpcWIuz?_+0iuTOrqEn{~oK`zuV4+KLe9)b=(df)@T@L8aM}n6rs%Q z!c7>!d zcXsvnr2Hq|gXb7)5P&h7=UmG;&6dRlAU2;-wBaNGF30c_3&2;V0GuTRpalZ3($0oJ z0Gh0xVPKLJWF!HgoD$0J5e(zWt4QP4JD}R6no`h90Tx~r@{xxTKGa>-sO9>NnaH5| zIgwe_W)MoTi+MF%7#tPRkyoget6%d#R=!Tp_E9A%r;$X=Kd*WG&k+ zJFugo>o$Tl6vW8Ez~@kNPdDxd*3v+;{n_2xx1D!<^M&1- z7y9+TZr=$7a7tJ62hIM2F;FrJdMFz08nRFwG-OGE520}@EgnHrraSS+&9*|> z4KX~VjqnT&VaOaHWUC9F1@KG}0O6sFxCn57kb^6v#rsg-I17XzO8~~@u|o=e=0N4w z+9G!152+Jv#8D_pUoU?H^n1gc-Js@dApsTC{*S0%aV=45QX&+E)ek4o0A1 zds=GgQQ6w&ajf=5MlsuIq}$z?Zv1O}NCDcKMyO&c-_Vh&{}%Ye7)_j64xKI4%m!o= zYmdge1dVUPmok@Kprex2n2LO`-0E$-lq?fG?h5>W2ceH?(6X|QVmkiJE%m6F^vX5x7)qtf@Y5}k- zhs6nk6Gy^kEqjto4MPV%v-NF`La;_6?xU}rYJRuvOX3;F(dm-jR zvg45N9JG~Ui}Y2r6oT&UBNv9LIn3^TJw!`8Sff(7#eX=Z@;sTf$qk*U{==s!()eb@ z+6cRfgn>$Ni&EI)I4p$*ft;|_Qm7vuO3Iq#gBvk@7#qr+Ut-+^shJNMv$W8d!-BKX z=5aLoelT`p^g{%VB^YENdaaR3>Oj+k$hUg!`kE(cx$dU~`q#n-1wAE_pve?8V>YU< zAPwzd+w>Qys-F)R=yMJN4g)FhJ=G2#@V@WS{zPM`B)HZ4Zw$#Y65t(D&FMf!)kao$ zFlM-v%_@+k`jr@9YG^ngU0wV^k#V8HAwp=3ri3uMW8(`cQhj@It0$z;@Cr~73tQ7Q zysR5Mj<9c!OjX?4h=P$UyXP3qR)FDIacNi86I2<&vQL5JVn7~}f)9Y8Mmf}Sacffg zO_V;4r$_!2r^(|_fF{gO-8MQwEWTXm(q~w|y!;!iU-C`+pla2E6=Co1RLwnGEo+C+ z*79jl>VyJSOOfg(kV2_A`=l7lEOUQTacksYxAxFEE$6prG4iCar*Z#StYx;Aed;dL z6}Fx)hr=ME%=Rj54M|_&E`>E<(pdb1QrJ+q1~!ZE6T&Xlyo<7G*{4v6FR9jDSX$TW z&pw`NVV#A09W9j)kV?d?&?BVH|Gl-a#RE2|z^UO|%=)(5+@Wk%5}Iz`TN28(y9NMwag%h3b(x8|RoKSzd{k!Z6!#diql{mKe-h<@kiRDuhDpM|HDNN?s&qlsd z%Z{mKA9+Ig@1qBptR8U}t{oG~%^MTSen#K?7`m{laG&Foxl0Ro!K(sMo$cRcg( zuh#;+#WB(>S;YGW~ zL(=-$zk8@6E#1yOftA-Uc^cjdkQ?sc7tc(w99(6wI5DzXq+kJNYE>0hi}z}UZHx9T zsU^1@d|@MH|ItjTZfuGo)mV^sWXd^+cX}LtEV|gz4lca!wa;#ZlTdH>wvHU-SR;@+t za&@bq)tbykP{H2tU51BkVn1MBv2>-Rtj_!d-LL+J%4DvCgQ|rudQ(SYN?e*z4hMh~ zs0U=l(O!84@NvRn40IcGPUJIaZ}y{X`GP(mSvec@r7GgnbxmVSb{ zh0-Yc($JBSxyl%fB3!@lW;yx>NpY=I*QeY+HrrY5m{>F~t9;nROQZm1GZu8Lob@Sg z1q0aF6yuUueML*ld=_)K`i3R)!Ol^ke5+jean(a-U{4ox57(pX^k`A5T)kef@sN_)8r&l@!`HiESBA_s1lv7q3j|t`lr{c2`Gc*ex06Iy zuc7jT)?^+oI-q2(!Gz7`0aszrRIv3B*g6zV$#D3E>?C(GSX%k8;kUT6lj$KKO;TUK(EH8sBq1oFH+s5kXO+kMJvk% z-u^=*wa_VVLu_QW%EdZlK{45X3_Wg_t2!*Q=!0ueo17WOyb$AjmxpzrI@paFr_!cm zHZ*L{DB6>`!7bG{cb8nR8!pMYL%?=bNNp3OHhWQAYB$cCg}iAg0`cHz>Xj4NW4=Q2 ziprI%sd84Nf&Xwok#|XdqV=E)>+q(BkI!3z9`s@bgn>u<2)?J(7G__BYM z)d(YnN)tfv0fpl==AcI8399=y>=+Bt=dF;?-Ui{{LVN%as2-yVa7a!-fi+Uix5Q^i zN0#vgr%e?~a&gJxGGnwLwKlj1^uU9MwL$|)OV>f1 zff(MKE(QLMWn!!xI;;Plz|D0OuI5g5W}7{s0SdoB{aRGyt6_##+b#e9H|$^cM`k_uK#+!a`CQfKN$V?BoXE zBjC8I`!JFM9|1BM05?WJf&my3(-PbO&~6a&C&Fj8S^vC^{6>jWb?z^Y%WKRYyiE|Z zBCq{&_qaVc7mV~DgE@EtBqMY1r!I5wF-;}N9?+ha!oDPX(41%wc-Lr5HXCQ6NOya1 z5zNX9lfxczxJ|Ls(_R?ZIH!gHK2hUF)$omA5=ZU#0$Jcnr$O)C%r0M_PWo6hB&>?BSKjmV9;YtU*K06DWQxCd51 zhZTUA8&(~?h80*1(|>xHMp}+A8R5*%q8*swKu3NiX7CdWV0lIW2`m7mKq*>tIU1$V z0irG&17+FU6&hh>wuj@ovQ1h{_5vVCC5|LRuufX+1U-z27|YJ8op1$w(8CqL^8N@C zBhOv4=t(1wDY?I+_owsbdSU-vL911+I$K>D)_!wHqC?%J3kr8yW0HhnUP%2rzgs!_?=sHZG0TLGAeaJ$5e9#!`L~I45sH|wtIrMXhZvY9H6zBlC zVj4{U`?FAAt)#I1D}@CxLf`;|Zz>5F|>*oAh#`{@)er ze=GI{6q;@6T-#RxLCZ4W6gB>XegOrnuVVOncgB1E@}GeF?@@(l^&#R>Vpa_VqZwJ* zCEfxe3R$!_q2J>m{vHQWP9PpaOO$8YhhR7RFoMd={_pL>J*Iug(qi_Zs#lVI7=l68 zWgpHDoX9?`Lm6qoZ}FGghqGe#VHJkp|JXic0NnpO_Tfu#jO>F4eEdcG(27FHpO_*o zz4t8eta;>FR{fndWG9@9kdolp;ZY;1;U>N%kUwg#YdK;(YYs|08>`6$4`03GBsc#6140y}0)&sI%oUd+{b7{%`EXWmNnB zZ+iiUCn)gH3GBtPli7<0;0ll1i)RrhdJ=o_{E6+w3?#-}Tm07y z{zF_E;(T|gYY)7O{O2Qi8V!bnfgU#8}!wcshCEEBX7J1y%UXmmbjkb@kg|ZkpiTw(Jp5C zr%QErr$~!vMgY-G#~k1zrEoR20AxoP-u^Ic{D!^rR0=alomzmG%ByJOH_+<6T-8!t zp(#-)`t9Vbj z|DkkC#l+$$0{u>{)kfwblmz}88*@Q8My5NO=UobiGrZ)-#-t7|(yoE)=wt7u>g`br zxj#3fwEo*&*qar_sivd3ave28ZUwi$8T;j{DwilBr&V5#eqa-kCT@?vE?gR~Hk!OP zJ>(Q%)Z}l?V`F)54G;Lr`(XSQPaqfXqCtC3g54_<*FcFjLDZbq{M{yC`+AnOcfe?TP&7(Fd8q4@G%)GjE8< zBO=4ACGtA@iZ=R*JX-C$;(agEr^MwBPPe9g@45Sd|-IT$OCz&bn=+N+R7 z^Hv-Fj7=|Y$IewjiB$h{iPql@?|+H)Gwf`&x;3eyFGgx3&A4U9hS4nFKZ*^mo*Mz* zv9xuuTQgA0fInw)hP&aL6iN#oKsx5|E;c@^Vz618yoe>%wh}E*W<&Bvvf+bW#XA7< zQxuz#fj?^2+>a@IKxP+?WJ4~*<6u@ig4qfQ+ZJ?zI|aJ=hT%`s`o5KmZGnO~J2xk> zlj0{ycTtQpQ0e8yCXEOCP|z-Ls3Q?x0=P)|G7$UBa>LgduFNK>PEL{Pr;=g|Bd%=T zgR~}w-dl~Ww;!-fOo{Z5jX$71f@>2BhoZ9MNE>Aa+e0Iwl_OZAo3)mtBG_rERmt3h z(X>})R=CKpgeDDrp5h44`wzXt$sL|sN6@lJH<{2X-zp9xev&8imLg9O!d;je6XG5J zjCY)eiqm$(*Vr+pCTz_kPX{=PFQ)>ej?x!RI31CHLSZG7tF|lNoYM_!7+T--lIk8H zQJI>eXmT$2c6i=BumR~F?WO|I)RKpuK5>j>MqVmhnRn1Asvw?3+wjD4PF6c(u4-4IzX@r#zvYr#h^0qdFzp zW)`MnHoWjb0vRuS3kt&qXik(29;nO-M(3Rl;R_JCg__!vcP~St6u6rjE?d6>W67ekSib)yo+%?! zdz^ZtX@sgrn}#l?^#@Q`H)K|CqrVN?Gc(s9Vt}0rw}&bzeQ&WNUyoKPe*vV}LeFhxKjflV*`ZG$K`vqu@W>*^p`kBZqXB8<1t-L8Py`L9^Z{Z|Img&N|47IVJ0{L{HzHy9}NuUqj z3+X-F?R}E@eggaLX6rHB+ZEOXy(tA4@MCS|4Y~xEWAGuoN%i}N{hOpf3f+!ZZ8>#; z!liD&uQ@hVwi>)kd;Jvjg-iArGirds#R}Z13rS$)s`}OV!3eQSK`)2^YZ#Um!Oc&0 zrUSxp3}elOeY{XA(iF$Hh_DsKTBSvM@q}VOxEzR9@aE@BHD4k{K@e!oCsc^+_lJ0p z*%xy4*Cbll`Qkqf-(HrNr89JJOxz+$oF5Ojh_u|_5fJ8h~x$nHrSe}=^l1a zVf$#C-<|pZ!bi4NO!H``6^D!W;3N!1@-)qHz+`#mTOA+yzLV<5XUHwK`2c{W4{ZS6 zkG2s+T|=SCCd+AaOk@ud`S10o;(^0}CXxj;91?6&e=g(GI zd-`MI=)y0k->~D#u(T=+JSoJGpg3BjnkqbC`YKl+`q?TiTr0}8D#LQ7pxoS>703EY zgajgrNzbGi0+0Y?`jG;wsW7s-CDVk$S#`|n-x76c3rXo9B2K{!xSz~8Iv~YHOe(%c zaB#jc1QO1zfiaX1peodcERN3-q->Bv6r2S5W*L8=2eID9E0LU+F~(Cm?*M;)k7Kvs zGJxanGEd+W->Q$Ipe2J`zJ)p%MPK*CDEcR!1;Q3%3~IsOirEDwIzY0K2VHzf#a`_4 zuXZ0_iuP>&^S~RxVSiv}_ep`loL_v&Bn7hZqVWT9Za90ZRve~Y@@`9kukfh7%17HC zDX;-=B;<>Tx>EhFVHd5(Xp=&;Kjb(jg^0SuTs>7<$bEw7I6c2F(vQ$Hw?_>-5s<%H zO?{j6G$Dq8`(qXv(JQa7z;UTjgcB*eQR%8sg?Jv9fj>83Ppwkq!Tz&xDI__Rjwp9d zn5_Wkz19>)whIds$l+`Xhs}$&X?`-pj#W|#LNV#FI9v-$n>=atXnkh^7g<|DTGH4B z4sdEjJ^@q4At&AQmXCm(y(rw7^K%UF7O$saqXzC+% zPbvINVf3^Wi}~Ba!Y;;c|AWaR68Ys9fI$cL+esg;7`G zXS{JV5czX?3yxQmw~VrJ=p<2FsTJb`)T5?EBWP|lB`bxSM05UdMWmMUL@M$(;R%R^ zW9aO)7`Kz0#`jw>-y13bVqxpa&qMhx;gvFRLT(H!191T}GKGr+TmhP#2TSkmEiJ7& z0tzIYPlLT`&4ARI8Dzicol56|)x28IST46uX-ksILq3w=A36^HEuuWnAo%ot9DJTD z;5(AaV`p5d-y#JT0It~&lJ8s;!r)P~S`sTRQ58L5^@jC*7$bO2#(r}?gdNw){o12^ z%(Z(B9&nzzga%4UFpSxHPyC;lfhTAPt0_Vpj?PqzkM|D1omXchDfqsd0b%mH0M7Lv9 zR{%<6v(Vp@mvvw=so#tZd$n*SxPKcmWoSmW5i)>qFmEx=f|kSJd)VRv6vg0f#}OME zC^$+Cs;aC(zYi$Y;#?KMy0Ho2@A*Z`PX(b=_St^*Rs4;tFxNzc>M&5l2gh4lG)+j_ z1r*MAF44J`)49JU+pz;D)wN@V+E^TB6YR0|3zsCZRN)X4{DBKe0|9c6V-U zA%*21{0V?IC8H#Sz~{ONm_{BUkKdN@q3KI(C84oLy`#$=Tjq=?anPo4Y1Vz`dDv<( zKC%AO>~2Sxl^(qx@!a9mlEO{y20dkb$Wv{TS+Tz2O>>ryc;=>BTAxLh2@M(nhGP9| zy1gj=OkZ&q4n}HKc_0-iECndujQf$`Ivr>^;2dB@1o^NjrBa}lI)rd>$WA{sREmSm z8+~6P0h4tQa1X~X(CWLLToN+@^}xt%tM?KtR-7_NfM}fw%PGTi1z)J?tkR7?5@RR= zJ8znieG|2z&Ze?`c~P?%`M2~B5{qt|f%rWEIKF)6>&2XwYKr*BI8PjY0lX6Iw9{>Z z%Q-Do#}!MgPsJ04Z@m8I)TH`J#S-ZYSG1`|uV|@WZ6X9p(_kPPBKRE+Pw|`v0$^Pi zqr$15TPBGjE_$YCkM(KUK#=T7neuxgOEiTzFqhy;GFc3 zdqTyLQ;+5@pkoenvPP=^l6=l?4F|XyJ=QJvd_4X|( zSpT(~S+FUTA%+>(_c>FMAE_f?_{X*9ACO}FZ7a>sXt~GJCQ{lBaN{M%%bJqNixg3j zVZ2D3e)0N!DDyAho~-^}D~deCi^S`L1|0Usl=l@D8NB%}dmPJuhw{HaJ|FyEf-I7c zbf(&mmp{-i8-=_mgu|~0f`;!NHYcqN3DQz$uX2_`Iya zy;1)bdduZY5T^yhn-oG^9+B_n`2(?LfPWw^-smNAdBn~e|vLAm& z-uLGmhacM8Oj*jy-P&uS)SCR0wf8&~xs4Y|Y)_15KV^OyBS<`-)8h}6chC8NE#z-9 zy*KiA>ObE2j+F5RC3Wj>OkbSC;l~QZ;V06=LPg%=MNXLCaSZvxIEr2QriiViyt^(t zu6=Hg;d+VD^;wkDN28n{zG>{I*sETsGlTH$>obHeek&3RuGG#?b2APO@v- zM{bI{8pT2Y|*+lx%fn-kg=U=c`j-$^RX8TQ|o|ov;L$u#D zews-s#_4@B`h0i@INWc-BKo|Cgl_by;NAHz$InBkPxLt_0lz;G%*64tloazX9sG^xAHf@TJiJ9GfhXi6fnY}tivIrHgh~DV7HNs{dGL8c z@PzUy;K3D0G`rD+(I4*G*b!7?OB-}S!uU_t&*pv;_J3yph=;A$` z(U<`TGX$OQ_QdEFZ{LIVzq(k^rGJdT322;y$~52RBd%+F9pC;RO&}*||MOpI|HhNG zkIE-#zia=MG&U)0K}(PJLOu~(?`gt34_X?>BRV;0J!~dd)MgBXkq(Oxmq#;E_`k&Z z82iIb7YW*&5+kTFXs^)kG#ujmiI;!;xblDPi}fj|e?s}=>35x3@dWfc)f|4KZbuo`|zl~2(Br1Ad!1;0Gr{U@%U%s-NsS4<$s$%_>+ z??T=aic9Q?ck(8h0<1yPmjex&(Gkh?$!b@ei z77=<1)|SE)ozRnI3`D7J_?)Obj=&eU8~YYg|6=`l;RiHX5BFBL`o^EGr?j}fF{Xh~ z3GV{F;rooVWgI`_8>|%gJB9Ai-ezok(z}}QPX3s5_%q`~>efEF7t-MVWGUn_#`!?G z7kocNQ^5~}GQy`z=g&HDD5DL&AA1tN#X|OS3{I1OoPI{IR}wu9AJKOjT=}q<1;5bV$!-44C2B)t1%KcfC zpOuhL?->d28F){Jz?(_O!KZxNN%C!)JS4F_ybn!$?+HJnGtQ6W@yC9QeEP5CpZP2K z1AZm{tY68``<49uC(GC5e0Zjx0BdSb#2@NkzmwF@M!Z@!0vc@o4l6FKNs>?EC)GdW zB=vhzeX0xn`b+H(JV|{!_*=vfF(+Rlh7KPCV!lCJ7w{PgAIEchpadSwhZ>FlBm7Pf z|5OD{V}W0kuV+vz?k$aF#KwEvUSI0BSP;-rH!|C2dnwOrd&%ylB@rewag$vORRi~B z-&xnCTDryq%bAk!uBDBkHw@+gFu?Y7+7(IfN&DZ`yEmaoO9~al<*aV@F}d!B=%XiN z%OMzc<8XiA)-2@V6jb0QJVrA=6MHP*>+$5>LWeSsub9hfnFb>UgIS3f*pACAIU)^Ob@UTY@yAc zx3DiQipXpLB5b}zr+7Gz@fDsl7mY)fM=bEyccK+*i-s761em#Mmp`x zrpc+6dNhU*nmQT`=6Xwr&ZlSF11c^Io*KFv zfNg;|zDF7Qeboq^*pIa0=m$ijco*u#uwnHie_Zx!Y$#^Xd0AO|?nk8J{*GWS(p=he z#6|2aOF=4wk?=9UrxQjA$T}p#tf4K_fuwkuA zt}T|Z>ff5GI`-e!SNdQgj>O|cN5rZ#g5=omi^RkzHl~u*!jlklLEs1Rlt^G%s0H6? zTrbD81vaxlaH3Q7VJnDA)Z#;71$tnSJdMVOM=&I=$u|l?otQpEI9X+H(1^C>WB8P4 zmy=j}PmM`00)(IDS}j63kU{!m8EiQ!)TiGERk)u8N&KO(}2-i+M!o^*5w>bfAF_b7! z3c&-UPM^mkq8vdMu5ro{s}`6}X%zEzE1_f#IpYmTh?wtTu4@V(^cC-OO&FQfLoR}- z!9_Ai)D{JT*@VP08q{wtf|}z6F^btnDVPcxP@u(7^bu-7UY3utIK2)+I1jX>NWoK} zK=5Rfg4GyCxXh?H++d_4wAqG@f6NrYde8@lD3Fxm&7v*JmJ|ex{fy91t2ec|hlqe+ z8WaT??*CQmY-K!d^{1gE+bdYX}4{BHQpB zQP-F%igIB?m8Xf+tj!pV zf5kH~j~b_OM$Jfpr6?977;Uo^H5GL65;hppjbs+A~{IHuMh&?C6>AW;2)c+1%je%5h*enjco(|Z8} zfu2K_kurshxo}yN6i7jF-sMYBDkeWz?}1ntM4VWDFrJDClb(%o34>`xJ|P%<78r@K zR3)A;mR=#kZs0@dKx6ljbfA$2(pE8$Zv5H5U5umnOa&qd1mcqwE;%s)T@Q8&rF=ON z;&>79oh83dbUCpjR!L0yTFByQQbL<);`$pMUsQRv(X7$rV8`)31EB&2W{MjsRq zt!gNc*edQMyqK5eZ4dVI>lT zlJoDvIl&g2p&$iFCF_6<#vD){gZgMkeDUBBw!%0SIhevFsf8VJO-E{B8CMJGRL)cd zm^;uGzc3lpS!fv<6cMP%xH6pMaytfV61r6wlf((HGm#51gM60E`2`yi1haK|!D(Nca^t+F7H~15_b@6RnSm;6m2l9>XUy-m?|0 z$^uP5V|_4|M*0Q&`DszfrQqGavS=FJF&F7DS7-_Ml@6`?507(z#I04eM|e=ukv9JrBt4Z!YlGXb^XsE6bd>%nz!4#!^LpRA1?OTtREmxayJA_e@yay z<}U#Vq0c^1C>}%qGlIHlvU!cdOz+$+5tyh>|iiAhhS)LSB@I)7m(*<+4=U=C?@A$p7wL}em z*dOz;`~01VXC4Tg{he3`QGno;DX1p}deS2nsd%*TY^&FO|xmwZI!ER{OOiEkN)MwWtfbm^~3bY*W4h1o(PH|0!c3u($ukJmH4=+d=! zh#}~Bb2@Art)t1r;0Y7O^>|uF-9VH${fL>Ys}T!dVtmrVH@1I;PE?dYdA-30jO9wP zluRdE<7h!VJdYQ=k`|TH;>7^M+s5LvA_ud3756C)gUy^WaNx{cK0M1e<9kv;$rRc+e(*HFRo8Pip zz&}n)!-+QH)8JJj=^B!4?dKw(t8fjpGs8ZQE{&<8?(S(EnSMADPpMc zCsbPG#zp>M_!tBV(RK;Gn3D4|{0#b`H=%H~wB8BLboEaSop~)FM&2YCeJ>{9A$5kE zZPK^PsUmJzfAh-JxCb*PFWQ-BkD>E-otgZehEEl?N(yX8|D^@*<1aFxip?kJ;KTw{I@l^b(hE9Aaomuzdg7{55{ticKYE-*FTluAqzQe$Zch1#^hha{s6lgw01z1@gE-tpqAjWcPbj%sNC|P!mos zrz|;mq;O+!Yo#u}Rzj)~iivz`h@AceUJTz(!T(6JxcF2G_5wT=N9Q+tz1qTl*x&$< zZjJW+Ej~;_)Yyl*@JCY+(joo6)npf!!frO4#x;4_Y@0q&U*gd>4eA$EG(nn*Y zrKu?F`@$$iN^HGA@#4l#4!a7(wM6?iUm+U20Hw-nBQ<=3C_cVo{N?%p_xO3QlIk2% z-7P8l?{WTWjT8Tz>#zz3( zzcg$bLEr5*_;I2??9i%`f zLBxxt`p$|6@hsJVfS4+}aUJnaTkPvZC0cf|tl6p;(QZS!qh+p-UowolN4cShU}Q`! zfIgyY+Do(nmyXs3^x;(2H<-xTj$^lM`7PaXsTvtDLO42;}6I#r_<+T z0L1WtS6q3~;SIq*(qA_=EyvIjrYZ7468X9Q&DMB0Jo@lt__+NT=(mr>{%x*SOHuPQ zZKR_#G586GEdZK0hV%OUu`k0_d~$Bmc?a*zs^v$aLDzp?of?mO8C1GLtB zpXguCy>!0kSC<(;=6J< z72=jgHKB@${@fcqWozJ17!S=SJKAu24DQ>0n7*@EqCG}G9%e7mCh%jFm*weeg=;J9i{M+z(w^>NiYN(qmJHNQq#g57w zcPPR9d~d!>yVWl9j~&Pxce;Y#d3(zTKjmjtU4y=JW$tvbd+h#(bpN4#zSTHLECmJ- z`2XNf6sjiA$iV}p2P-fFUB&pC2qJoh=SO-*$q+4zkT{Kk8(qTO$o-zVbB z8^3V{f5K-F4t^rnlR|I}`bo~*qp-VTU1)Iy;MX>&Ec#vjO~(8@ixilOKA3Gt0lJ>1 zs~uRu|8YA3D?stxGx!a%jQ!lkS%86W8jQ*iQ=Ui)quy+7K}-sLSswNm8mhP_AW>*{ zS$!MbAt!_wdlMs@h;k5EgP*2koyB{M`DF2G!2?yZmnw%0sz& zs?X3zw){s@?)%CUT0kSOINYq{pJQnmO(evj^d26}%oqF%&uVD&ZcpebQZ>@jN%?t- z29?m}??@evyN=HU--hE$hpSLvVvnOu2jI2K+?kPUM6UMCT-7Fnx)Bo1V+x#-#=EvN}@F&2ccCVCqPgjtukec%U z7AHCdDm=zVPZ8Lh(S=RNUt`$dyC7-pfKNyR8fvEPw`W?(IllDmYbTw)XjTc+$ugwV-v=a%QV*}xN3J)18Ea4 zz7l2eIAHBkJem_0dqf7lYY2-y!fsAc>{!L^_DG}G;FCj)(P(KB^T~vGQxRBl-db$k z+)d+!@EJ?^(0O61;?Yvf_B{+QBQo%XA`dPb)vmUCLe5+q_fkU~OSd!vgYr?T!Od&|!^OuNxcvi)Xx+`BxD@1#=z|YmHsFav?$LQHTo{6vLXx%|8 zaJ~|G1rOkw6!kVip%-J1^$>D<&Vh#q zuCSHjLP~d;;lToM<{Ma3I(EXfj1pMZOM!2(6|Kg$8%JXX#jj8BFY81Bix=M-tHLi5 z7f}L&DBAHAL#_`S_0a%EyUjGK0#Lc$IYPp>2*Y@l*$=M5ZM=aEi4CmeFQs{^f5jBu zK$#dH%CLF`@0F9tYlM3eb~n@U27D%iPSR^m{9i=n^+{;m!}eiGOvCi4f6?1^?2PK~ z;V}@VduQ^bz&Lb6(Ky6-*Rl}&A-YyE#ez?I;$Et%p>X!x1B|qVn6c2w&pcUr1H-CQ zdSopqDpyB&j{+Z%@z7EoujSKD0{7tKuEY#_Q1M`=hf+M?c26aLiWI29?mzGQPrRbJ zm%Ezx9ewdvI4x4(5c1;s9cRs*+7leSKD#`zk8iym@8f591ib^C-r9>E;B2BK)nG>g zT^0~zxVwq9{ZSy^{~Z3pDPM(0EcyE3$G8K3Ag^E_2v$lji^Bz@r){7YKNnevVKvC$uB#Kzl&CadB2x}7BIS>PNeB`$i#3nxMa9zn`K;>XyI zKe767To%T0SDhICQgA>5eEC0wkZ~nXQsN~0sp&YeCo=2T&rB4F=U$DA#7aEI#eNK! z11=IH2v_rC)>XiezaLND1!zu;F6WduZDkI4Y8dR8#7eVuu`B8vEmbq_?Bw~HwdD?*c)(JzeOB?6nK!)=$`<;xC{PMG5CA1C<2QXG*bT)#zdfy%lGI!W!Q@pUspN76vXK$iSI-! z*dHno6k9~2NMDJ)AwgFX#5~=G7HFFcJ#Ns?=grY~N(-dm7#bKt&ys@c$(wfO5kwjx zi-=27;6la6Tf<@+jXMsNaW$1BghdxL?oAxwoXt~b6@<1OM zanYjuHL9tNt`MHN!LI`*-tpluEw@M&w|FU9hGu(3DPH|DKCpmA@O)IkCxY<#dY4tT zuH&8JpE<>Mzb}A$Z~7~?NI&QcjV=?jDTu1V=e($*8x?U4ux}?Jl;^?cbcf=GyOc<8 zG5$Cj@urphStGRE3*7!y_%hlmc<$l$^5oB2WcTs!h0bcmP%mp#3(+-2dgEzQR4(?3 zaT(e$$E%`o{%|oTNdz;OhvUo?qcSkg90*|MaAKxnGIKFXavll8LZ$U1GfYO}R>95s zl`nyfq>UQ%-{X;t9L+xx_&1if#+CVOi}(I6p5a7XjA!tM{Xi7N4viN|Ytf4UN_zPo z!IwOsBL!~eFAxOnjln?V1FopFS+gm!@zeZNm~|2m=rk2NZMHNYOC@f>AIU^Tx%#NE zPy-O3G%{p6-{^-2(&rlQGN%vS7=~+H@%cF|?Fsm!O!@63>X2SKA1fSVI4yH3$V0VoLXBvZtViv_UryGl@F(39^X5W?7iKN{aVrv5*T zvgNhL15|~G(>swkX(n+zq~+!Jsjqy%Xm1n|_S%~?Y{;?w+Bu}8%<+Ja0k;#y$jvq% z69x>6Z=_Hg#6%2L{f2*vQ3}R1=+$@$;P{B^8{>77BtpVPt2$Dl#dzTRG4%2d5RcD? z(%c`Iq~zv2cm+COoC_Lp{YHZTy98leq9@gmHX{v~$BvLnEQ;7`vDKnjzvIEueE)}b zY!2xM{vq@q|Ee*U1ipJrCI$(_%fYJj}7|z7lTb>?CEVb^~~+2riq%S~2mrL*;~kd6DrM#FbQ3l4TT5oI7r zoK`|=RNwgnM&=)Ae9L@lH64%sBRw#lq?+gO%z^mz4EmZcsR6bR@?W@JDcs98G#naO zyryssYoLeKg{!S?{>~mal7eDJ8U8?HOy)?b_9_SXaBI@|gX(qCe&H^tg+yBDk3Vm< zAW+%~=j|fUNqlad5)jVW2jd{Q+dnOfb-R{?Prt_O`OH|4A!}W-eHeYmeOyufI~<8N z?n2X07D69V|53+D5-bJju1FeET~hu?tRa7e9m4Vq>c-?mw*%!9$TY4qHHXtYG-nPc z+O)uMBH5(|Fq}djz+$VYadZz;d_t=>4*c!staMROe3ZJ_55&GM;AeLMcSGe9L>a#V zA}DC#AFULxXw_oKXrNZS+vxpedM9Lz=kR3OEB=03;yV_labc{ii;=x_hQ6&kh9Eg% z2-U@i;(FEhptcqIo&&v}>wn^Cif?K%H_z_^Yu6wC1+YX_4z`fMz5)YEu+rp^k{^Yh zQKi5KK>L?S#%q569cuDVIK}-<%RsWIQ7fh_uxIh}`ZJ_LbVe$K8CIl1FbRJVgRlX7|H6}gs0)Y_7ztlk*1nwp8-&Ci-n~R z5KI`Fm@@n-DWD@0z#Agxn*8(YMf;_xEdak7pc|wQM!+|HoptzC-fOUS!r?u?QRF|A zdEaNlFOULHp!V>KeOq`b?81iBwyHy!_pbpEs(i@x~xT4DV%_si1MF!hVN5$jtpA9RL(*)I)lmI{cn1)Q=4oU#R= zEZm?ogt2P^gbO}IHyZdiTA3bs31KUU-y%9TL>@`>H}dm>!j@u>L8o;xA93CsO(Xh- z6l-+JK^(k+Tb=xEIKM1hzD@67mT(H`rX>HRIDg3R8}ydN?!&u46_NE-S6DD75$nJX z&<+}dHk=~&bL~}=F0Dx+b)BL9e5yyxQz`qthO+@I4pE@Azg7)zVb~Bat!RTE; z=graIThIFd2L}7g7J&YbQKg~LHI-R0wPZ5=4>4PbK8&AJ>N-U997CN1& zLSb?`#nQ<|sJ|o9I}_4}Qu?zZy%fDbdFEe)L}G4$()}MGlns+I|06v0=N3OXb?BcL zjxKb0uN1hAT!!GeXbpl%Rdg4sGhQ0yq`-Ml@E}4SYN+fd)&F2AxIx}}@QbDrYN^V! zX8>DXhWKsE3i_iDx;i#1<=%tM`d(;7=BHUKNfs|;iq?Jqj@f}l70A|iPUu$kU0#(I z)7`5M>#E8fBd>O^`XI0BJV8}USJf%h>g?`Sf5)pTC#bsW%{anDQvI^-Rc*W~%{03s z{BXRg>eP>caWQR!RXe^nh;<+HdrnaA>Ucfw5!V~LSACSP9q-L!{!*$=e53Ebs#+!Z z24S8&R6mPL%j6<1oRbLgY@YJ;tPB(+iRFYi2;^1m>6gGoo;aOKZWoD|qd=f$PzykJ z9q;B${3q% zO4{SpjN@^tDvjemszxF}V*!Cw;~F6c%paiaKo#|p=-}0n5t2fQdQERWSCInac^>Kl=@!17 zM|Fs3rY0H8fkP*?RP9Bld9E3CXv`*8k9JWeio~?tTwp%gu3t+o25s_;n93c1s=CY* zpFU2>7mC8kNX0&!lCq1D>3j)zRwUO={tD5B_HlEO8fiE2!Uv*mHC2*Q;anm%`{5`niyxs3OvUTX1rU0M&DbJLny(l z{F7e)4Jg+GilL$t_4pq(T2Uu?el6lFu$?_qv;@JxSD~?L%L6D(SK*vk&YcKCL$F5g zovQYjjy#%t->tn(lTfVLy{GX=7HXVf4o*E`JP&%sd!0!ICk-@jf0GKYoo^DYiqiG7 zEAfpYvjbo(LNJW4@F5gTXrFlrqJ>YdEui@-&mm?92tj10J%H@UpX2`B9C|lsc|)7{ z=J^Lx-dptSJ^+d9?yti!FS~CNrsot1?wlFQz67#aIZ~=u%R%9EYp0{3@-ns;hdHpZ zHJEjZhjTE2kKa6w&eDex=>!U&g5%1(>#;iI95WM|Xab#8^+10MJ`^VRv+`h%#Pw2h z+ADo=@FE^BkX#-?ADmrXI^>OuXQnOg9sO*vaFdjXu8JCseTOlaS z-Mu66;K4pKWvbw>ieFS{_ZF(!nWJ7L3S%ilV?)($%af}f?2na6+V$}2t1N8+^ouW- z`#`B3b6LpOPqb4q2|KxGWP_XVCJj~Lpi@2gqu|6-Opx^43n1f&l6p_Y#mr&AP_#5V zwHgxmYJJo3<_5Huw0Hgq)5VKCZwJ<-Bnogfbw8++Jbl=CkT*J(_83Q108`-)RM7$L zvj3ni5cct(>b-#CwW;j3Je8>!s5#f4n`+TBGOZRwbVzi_GK>2-qr+Y6Z!in0nBan?a4g9iHJ%ygS zT6zx$NNB4~rDdRKU)G$H{2fL9&LZ&vBKD{S-4<821G+{3?I|=4L}9)LZmA|iN&if< z?fVD1Ev|--)^4J7?H%3|K8?ki5(zit@lMU57wo*eg<(oFlAXM?p8(RvB~~JQ?+d!h zPrR<4nP2)lZV3?~fiyC@{+apH>u7^)1`?j9ig=!d=ab(6m4U&r|SB%~SdeJX5puJPXgy{~zYwJU*)GeBe$!hNxB+d-xdKrlOQrl`g zKmuqr-~vch)T;LqP(Wo<%=>-Lx%bXY2rlm*@8{+7A#?A!XMN6dp6xv6IqvgRo>hya zPvcp&=*Io#RT||@24<=@)u{se(veb=#v4asV&H3=&yOo#2{LyN9?E?hE;dgsb)G{l z_2`TKzMESm^mntvc~pIN>5+N(?ms|(I#n9{*BV#bz9}cVJ(F|o&JP5T*5MtJL&OWw z*K-!h+wbXttS66NSvgOW4A}~sZ{n{mRJ32yG}ffq-k57&R02ZC?H}y+ZVxN+% z1CC&Ze*s`fZR02Eq)kFQw(vB-irFlXyLu*O0t+REnI#;8t8s8uyt}a=7=2kTzXHI~^M>bk z-H%0-b$3S>3wgbLU3ON6vqKSsCK-lr|Mo64Kyo!XY_^n5P@_eTqQGUjLhVS7mKpJv z)%!00{om?+o&PQpEL{NGZkiG*c~v<6V=BvP7iiUA>o(XFh@gbzHDU6ZX@g1JF6gv;YLBr)N=3=ainc1S?Y)io0NwLzfj)uVu)$K z9R7A-{-kF%~2?;jub*Wke$x(^gV>n*WmKowkzj@D-T(Sq# z(&F=SjnH-u@#h6gZ0e{oLK{PgynxzIYUiW_ftoUhu8F?CHM-;=cn)N6eE-Z%JQX5s zJO*rp;{L)KUx0mLTDdvpG(4@X@%UR0ni;CK#uXJHccr?&o8eF*yfY`HPEHtW3N zy2Pl0+RP=}>dYmaRx>A7q|Ati@98tb{v@F)8Rz-^ zLnU-FSkmr1D16O_x6pElFFDoI&s6xteZNop=I_l-08aJ`aIH;aa8f__^@!Zc6v=1B zseJhu{(8+rFaUs+k4d9vHg*2bEl=@Y%a^2=Ps`TxJm^I0-$fhALAS&+iZjx$8?iyO zivFU*LRh2l0zW?+f$4-}GP*^U%|saKq)gS&9UxDz`IT7>3Sse<$7=vvw+=VhBSinMUOt_;#8 z8SCm-9)Gv0J!Ji*NOITIuM=+)c~ocg6M1nS5f`s3@H+4Mn&lGUl&}?k@N3`jlAcsO<+5dZlztKfFXPRHOzZ=LRA>avHSn z?=?~!DI%PecM4liHCEnXqpZBlK>x_=LY5@2*`M6Hw#Jt^;T5vzPUC43kt@u7=|Z$Z zIPl7(83{SptX9QD&lC~7A}9x5oA`{H!@vP-8_zlxu+X+MN)b-}p)j@UMUfc%^^#(* z!D9#`g_5QOdHzTZa*?&M_?L2V_9Z-Ak}D4Gy!=>{*b8{OIXiQCDD&-L=6^$(YjK~S z{)>P;>t}&?r(aVQ;0of3j9FI&18;G|X_dLY%Bb5E3gAbhw*2Z=1U@0)i!t_#lI2{S z8Z^d!#qM!A$HKU`kkE;x5X!2O^(9=?Zih-bNhzjaq5Y+7*+iH5gV*aXEhTMy%FV_Z z4A2z)5lcocFW#a~8GkuvHP_bE+xR3gbcs^f%&*?ymz&#UJHC(~IG}CcErvAVRxd`b z5YAMaC=$qJlDJyd7m_%M72UTt`lKiM9(0=1KC1@@!2<)5%M@kR4 zQ;T2U-#&Ne8tcTBmy3wjQ$P3OF@Js^LjB3Ys?!YshBCK=N)fz9fW4Y0>oIi1cIS2G!NvOgw!6^2PLiA*L$P0_=pQ z7Pkb4N!3LS(W~>`rS6}fD-DbxTwz!>$piPe#ng21JWih5D9rN(ilq70RhOhyNX)E0 z3T93Re7cCLd)jbjfLFoE_Es9HxXfv|!Mla_V~^0ezwY@qSI?&& z`=?)vp^hilkNMI{S^aI1LtRBlB4^1_OEHk1&CZXfne(piH!Bx|Tv&TmB<{*aWx=#k zo518Gp^_%bYq1>@-1EibB>xe4+AlyDB)`D;v;t}HDowe6Ww>gPQudNn8uUYn3)5Fp z>A^&76}tUwT^-TT(&?iQ54o>kmRrSODT}p7PMPT9FS^n_V@?NX3jYv00%xeqH#;(Si+&2_>KV*z~KTM7NMGvT}ZzB)+SA|Me zhU-_>2HIJ`Dje`^ybDDi35p^Wx%_TDlLnDkX-hde*e7XQV*cq;~0 z7-Lo#3#zfZ+YR91Nts`8h5HtxWd|UKl3fk`{m__a^Hy8Wh0RwMo1X~jugki)SV%hS ziFHRTD2cv#7rChYy#D-If)9OZFt9RYj9pm;rMq`zqu9ipIc&w5XCrJ)O{jH|3gfly-A?xDYhO9&Ra;UN3;{Ln}g}%5?*K_DgYCS6W1xjS$Lh_SIiU9^ZTzezr=cRC>wy4~b(d>iKr^Vd-BtTS}^zV7Fu%Zh>!4~L=^_-m2 zv!0ZYbk;vbR}*P%d|~5A`_bF!BN(~9ab$c;Y{$c=KZ~q3xTpV%MN6PJOIMGVl zN{-w3VS!@x|X~0x_y~ja~3(e{;1CP)3zNkkQs#D7UN|!WjMMZ<;6$P{Ff=p4mU0idfpbOp18i zC`BI-dYnSfpHKXMOwTdhz(9lxFq`lW7`bgPV{^4#%{ynT2We(y8RKqEn<4EU z{;?;d=r{LG5h_X8&!cHo5aq?=ck6B0*VK3~q&;naOPRx015^9OZ2*lPp7W45NP2YF#l~#We+8GHBt`IU9`B+dpT_OA#G>SltE|s4=CQ>{RImv}XK-h;5xYjx zx$2q^SMa!lEo*LHSVh2IE*Kyoln8RFm4i(-s|0+>O^Pml~Fqwjysa~`Xs z!W>_~57yH`673?~GJc5s*0hWtD!=Epj2|YywJqa^%WqxF_`~IQOw0Hq$d3dQB8H$B%PlliuT(a?P{m+3c^;&dY_; zsdX%{l!j8*m%1=$^zE$VJD`IezC|||YUzPUreF&VF|R-F%W*#Y+)o(>u^yEo`>ddz z$dMah=pDfEP+fcRx4Cp#cz8|8$p8#9T_EgTT(@&M{4yqQY zDKn~-H^lzzlRli!+Zb8l$$7HTgX-zq%UCO3lDFQV_pcHD#npV*+dE$pQaWuso(k9H zVwMFif23Na3@>G`(;73)J{pM-No}O57jaC~dgM%VG|0K?q~s?zYxl({CA&)w$bWK_Vv0WKcXWaxqCQ=B|9SbW4=sDacGnHp3={3uTkYL zjK2$&c6WX1x99RV<XFY`1R|bE|BNRw9Jvl#yy*M-d+w-qZ+Sdg}WMzdpJRc!-|k z-tP@4DtSYyh;XOidDHAiZ&eMxNj|$q0xFu70{0hqSFJF5h8&U)a>3QTq<8&G*iKLR z&3dTlVaCgrM7u=EBH9~zR&CL-gg@wO%sB#5MTE+RcH5Bc0)tlqZ)UUKfo(dIx5PD> z;rcCNyMr3Gh{9{cmhl$>Za4o|h}kD-eqFLQ@G7;QKpd;-V*{8nXVrx3*U;L#b%_%W z4)1)c2Fp$RhuEAy&hE;WCO9&R&1~cJqYx&*aa)$exrssL=UREkoofv$wvXnT6zonj z)(9&I?3x(_Vb4Ot9o?5Gn%5N_E3HeF$ct^$21_kc442*Ew_>)-L>vF2Cc1^ql}|FK z5q)mw^f#dtC&(dYtkSP*lE55R!HGnA@eMd4RymIi2V@$)Jw7d^-8QpBm=;g%n8Fxs zpkvng^rDWQ0a`{b&74q|IPD-c^fzj-e@b7w`nFL4>0amhN(Nx+b^0l=8P0!12MDfE%yuk?pso;G|@E<%Bhnf+>_9R-x0 z`I_n$U?_HkC##Xrdl`p}$Jsz)s=iy*C`s_^tuGczg;)Zf|Lvp^vScYp25^~^p*Z#pC1wq{8MTn{-n_IJ@2RqoMvxR z56WT3{!l$fVTPIuwsR7k1AWr@D;lEsSF&b#_#im1VWc7&??2jC{4P z)5)CzN}N+AjepW^j$NT^eOwJf5>D0$3;l#6bizgjdC8Hl6Kp@>s}E&V)>c2EODEWV z9dEfg{DhS%;XFO~aP$^p`t`FTRLtB?4O`<2g*tq`iC*&ikYpZl_=in$1T+hR1EOu_ zMUA2(XMOVV9rv*#=d_rIb0@h^6#AW)(?^~rsiS-F><_XtqUHS>x$; ztPv~c7nJneoZutxXuOa5o^n>J!c^O?=Z&+&25l}OgGdH4q;;G86Vv+wiE$o%3zL2LLsK2Da} z#GIlgN{Ho)1&<(h_#>*MfcL?ze6b%9n^}a5}W>IBJ>AU;Q0Ja!rWZ`tZ4GE;Gwm6xZ-bFi=0Um z@{HgJEiKiqW`yQl()P^bVZ9@j>JNh(B2&S-MKI0ppumVblyp_Q#8lm5*b=gUneK?n z!60$V=!ll`q=D}Ru^X;3c|q)s&~HOzDib+{`mIpE{XoAJ^JX_3D-h#&$~yXGFN{d! zJtKY^V3#!-=H>$VEq$Ml&tZNB&5f8u6bUEJx|V5L#3MPDD|G+tv7m8Zn{j7*u$-G_ z1RUmF5?(swPCF`_=xEEMU(%K+%gdvC1pZ8(&>{K9qfj9E=jnR(!EZBqvG-I?Gh!c6 zt5=^?rZ@cxrGRww%acE<8iLo+c_k#+D4UhN@r%8p`J$*<30 zh@d6aC7u*6Q=2&EX#rcn=B9_ns~vHqQT)d1h1XAY;jrDHJ7C1lqH$Lf4V$Qk?cEm@ zSQq7*yO{CphRj=j+E7wCC50zNelBd6ZE;~>oM#+eAiCXg3_P;l8lB5HA28RJb(E}) zx7`#&`Z{k)uw=KQXRf>e{|AfINt@<9ujLu0UEyk;&6c2%I4?NQ3wuhO72X4q z2>%61K6}i#dkInXoDcc->_2E+yQ=;9U6+0?4VzUkgGX3Zt~>{MZ@U@rO9jbh6#Ny+ zIS(o>m_Lt9P8ek@P2OS)XhP9ca|Ksnu2eQh);(g)L5F4fy#u_^%efgudk=NL3|;wE*V~q}KHK)-u*yW>$Jc43RM6kVseS-)7=m!3XEdRq~pY zUp(E{)z2B9Fqg~JqI^o%#zDICWSulCZ*H`~;n2vLS7WlTFcx1iB&gr0u-`POadpb6T$eI!;mU`IlZ|BD0Q09_g^t~^MeVV158A7X+8NYo< zD05X{-SoGX_a(SK3VCF@m}RaO#cD{%Tuq?36(y^pn{t92UvBR@GMM>VaP^m5D#Iqt zI-;P=$+OC{>XGaft2IVKh0i2 zv+HQKtz?PPMxvYgqFj&Zl#6WUUc@ZaN`u@<<_@lgXt8gFGTWoOvO-2^4GrO%#i&*X z150OZR3{r0(48YG+e81y^7ATZcI;yyU{{(xm`uw&GiJM9&3`3s~B1#VMq*0chSB;K}2MkSOjq_UV?fyn?-} zj7+Bz(GPp5Dv+w5TltqzSyzW^LJ$&nUP}3M>e$lwkuox!#x~!I&~k{@h;FSm3{m9b!DsNYHsmO%MEc=v1%HUtS+qO5isZ=m71N!x`yN&CkW=STx! zW#mY+v$Snz=h4B!rjNQKeMvxeI~^;;E%r77?cSn)4ukHP=bt$$ET{kd*2xer`d z?EX!)|FFs6!=)O2m;1bYaAi&VMBvhobZUqFni7Qh(g|C4-;lj>_juL8hHj> z#ZS~&x<2ve6JzemUjV(^-1cRBBM9#-fIz*7oXi58cAT+z&4@b`9v;bIp~Cj}*+E)U z`oDgiL9;^5t3TeJ_WJzrzrxn@B*?^;+ZbXeo!^_IarUfznq{%XWXInoEv)1QRx}vl%4a)@> z-b5EdUvQBR4-2fC#RMU95CSeS=mP%J@lkd!_j^1rRpSd%fsZf6@s%@+gc1f;&l)br zFmbG)iW+Z6#O_NLNGFBLXF1sqoJO=t0vhnWQQv zYQ&-Scp5fDZyA=cn1aM&eMJ7kKk;r@o<;N|xsRpB8UquC{L7vrFt8=h{PCbv)5AP+ zMhLMPya{VLJ9xR+rn#g&oK?xO+QAu-Yt*T;8Pqv*nqS#4RoNX<83WHX_tsjs-_MJ= zC)mwi=~gMdykZc1w9+?A;ZrFGh?_<*JzE=pCt1wBP16QtMAl0~jrW;*<;D@@%bwj? zN*A&t*O#r4u1Gv_W8Q2UL%GehJ0FwKLbKJ>@-E1bFY~Pzn;C?)RTj9`1ZzTRu03ml zEE(eQO3oVV-X>}yZn(q@NBrF@-E!pY4Gtv;+q>(vxQ2GkMdreAcSOi8wivr>S` zytE*Q>b}>RN{Q6QgPN8RKa>sA>yrb8}ppDQQuIcQV1Mb39s6tG81khxQ2 z$4Hu!qWD-%Dk>dqg@zPJoLV~vB~0osuf>D1)U6GF6yfee0&h%T=-wHidGJJPPW#h0X8T{4T-_YL5>!dxG{`FXo#S9hivMTdsBlbUq=!^7-amRU`cLeFVFZ0W6 z4U-GK+IU7I=wsX_R|;bjd714M=x8YMOW=FrrJaxtE;B3J5?v(7)2G7t?Td-)ewHH_ zoCx-T?@L*Qr*e1LE5YtJkZM1vG2gDW&Kg3=u72Xrm+~Dg-CW+dxvqXkZAsVI#A&}G zs@&MO+5O3?Gk4Zz%_^v|3|Rnq_B|N*+%)kczG$^8N*`dvI6Q~5Qx{(o6OPYB@GH*H zMaSmaU$bAz;;1pJa~VI~W7Xk_(4n9DM1D~#>szjuSVy2xVNqeLz+OjV2%=Us=RBNH z<_GvkD`68~?sKycLG44yAfMUlJ6EJlX;a=uEf19r%A`uQVUVH;B>8F3+#D?VFS}YZ zV^X57{wr6G-F2==xAwnZWxHB;3RI_G;Vj*$O4{V(Y3qKf(v@TSQd$bKRNc=Wy}KSW-- zgnESHq{#zrvEJn)B)DL<(%rZdY5Gxcrt^GS@i{>l;!q%_#=F^78KXu)jCLb#LrbHa}pm5}1mYT)ru6z(9QLlk0$TzVG#M@w)~3rTKvQ|i(wjjyW3(O{|;(+Vf?PtJ>S zzcLLyASELwGfj92P_<@AL-eNHjG6tdx&MVT>|A}+OFKHc&DBP1I?w~5 zYONfD{6_3F`auOoY@9q;6%?FyM8?b?tMM2M#vLJNKsuxEpVJU*-k6bjOq)zdH&fJ> zDJM1ig!;Ah>uldx@Pt@EA_I3WRlog@>F)lrTS<>QJC9l#c&YIaj>e2<`BxFkFn$Zr zDeDfr6xn3V?+BVNn(I`4_I?bxsQ#_s&NacKxOSlvjWL8%*9s~jy(8HCu^cDkPOnH6 za${o!wKa|~=D)#_)C1d{fgJ9wD1S9l5)`>)vWgaoRgHDEjcO)|`E;T^3^TnDz8H}LFIed@aMCsS$nVrkO(FIN=^8U$ z$~;d{ad2ho%R~74D2GjwC-S+_o|Bb{AmdLFXA!p9kDr#A(R|GNtS=YU@E8~I8g%O? zQxm(IH!J5wG8pq;4+h?794g;(1Qm^Tdm!DbDCdH3xxd24LvayOcxXG9Ar2JrP08;9 z-LWZkP(I1EFNi&Lc9{mA@BsHbW+cZ*t#)TJFP8oetXw7O`+->F@#XDDn zok9(oUz¬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 SRF&msiHyuEh^4^?lm7$$MGc7n diff --git a/windows/ncurses/lib/x64/wpanel.dll b/windows/ncurses/lib/x64/wpanel.dll deleted file mode 100644 index 42c0ff75247e4041dea1984ffa7bec717b9144eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45915 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 KMkI^9D*qpYGb5V- diff --git a/windows/ncurses/lib/x64/wpanel.lib b/windows/ncurses/lib/x64/wpanel.lib deleted file mode 100644 index ff689e449c7c492f43d21ce1daf4cbfd09bc82a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4828 zcmcIo%}-lL5dX!rgc=NnB>j+D)s>=zUR*v*WTL8a+EgkEA;b`g+l%e@3YLuDlWoee zH%=V#C*;sSqNj-7IaE=Pt(3nYhn%7un$CE3y}Pw}dD!Ghxc5%=JtcKcNkTgK?9z*@o0U$pO0TfK-k+qJ=(bE-MzDYhhC`fM_x7Tbi#d4)^G;G zuLbo+y}7Fd+>uE5K|^s3C7j(>c+m6}(-{bVukHtmYmvg+4}Z}-ixgfnI8?70N;utP zc$F%>44byO)u0g`Dz4Brmp0-DO~qCNn}5&_T2ZH^1oX(3IIK7Qo&q%xek+I?m6|@5 zI}(X@(2 z5^?@75)uVx`nfHnUCy41@m~>3;GZHG?}{ShI3)X;V@o&r82dSy#j=@|H;kR^tYF(l zXeau$J%pt!;YMx$>8)TiCw9)&A5mvzXi408ztNDGdsihZtm>NfIPD*e;g5%vt@I_T zWfUF!Hts3D zgIJjN!2pVBrYJE`{4-^g&<<+heneZ%l>fooxAq$(3f@}^`otwlIXttcXS!z-JxZp) zG9+STR?G~~f5|`U;kAIG8Zk;?lYWQEE*Iq`OT9*jy(HE3lHa>KLnixv zg%#cXyLvt&9c)9lxR}-Lgq2X!;$ThO`*0>Pg=-`&F?Qo@=oCduks%YFW@+$gJ|-QU zYpr@~mbUWm=vt^{#6&1v5&n1MGOG^}p)n`ozQSqvEJcPK{X}%Zf!j-()rUAy@4pQ< zyKxPqD-`<< Qa5beXtgDGHKi0AS1KzZzHvj+t diff --git a/windows/patches/icu/0001-Upgrade-projects-to-VS2013.patch b/windows/patches/icu/0001-Upgrade-projects-to-VS2013.patch deleted file mode 100644 index 53ab005f5..000000000 --- a/windows/patches/icu/0001-Upgrade-projects-to-VS2013.patch +++ /dev/null @@ -1,2279 +0,0 @@ -From f0d00332540713c5d3e3981a5a29dc0ae226d999 Mon Sep 17 00:00:00 2001 -From: Tim Hughes -Date: Mon, 21 Apr 2014 12:54:15 +0100 -Subject: [PATCH 1/3] Upgrade projects to VS2013 . - -Signed-off-by: Tim Hughes ---- - source/common/common.vcxproj | 42 ++- - source/extra/uconv/uconv.vcxproj | 8 +- - source/i18n/i18n.vcxproj | 48 +-- - source/i18n/i18n.vcxproj.filters | 3 +- - source/io/io.vcxproj | 8 +- - source/layout/layout.vcxproj | 8 +- - source/layoutex/layoutex.vcxproj | 8 +- - source/samples/cal/cal.vcxproj | 528 +++++++++++++++++---------------- - source/samples/date/date.vcxproj | 8 +- - source/stubdata/stubdata.vcxproj | 42 ++- - source/test/cintltst/cintltst.vcxproj | 8 +- - source/test/intltest/intltest.vcxproj | 38 +-- - source/test/iotest/iotest.vcxproj | 8 +- - source/test/letest/letest.vcxproj | 8 +- - source/tools/ctestfw/ctestfw.vcxproj | 8 +- - source/tools/genbrk/genbrk.vcxproj | 8 +- - source/tools/genccode/genccode.vcxproj | 8 +- - source/tools/gencfu/gencfu.vcxproj | 8 +- - source/tools/gencmn/gencmn.vcxproj | 8 +- - source/tools/gencnval/gencnval.vcxproj | 8 +- - source/tools/gendict/gendict.vcxproj | 8 +- - source/tools/gennorm2/gennorm2.vcxproj | 8 +- - source/tools/genrb/derb.vcxproj | 8 +- - source/tools/genrb/genrb.vcxproj | 8 +- - source/tools/gensprep/gensprep.vcxproj | 8 +- - source/tools/gentest/gentest.vcxproj | 8 +- - source/tools/icuinfo/icuinfo.vcxproj | 8 +- - source/tools/icuinfo/testplug.vcxproj | 8 +- - source/tools/icupkg/icupkg.vcxproj | 8 +- - source/tools/makeconv/makeconv.vcxproj | 8 +- - source/tools/pkgdata/pkgdata.vcxproj | 8 +- - source/tools/toolutil/toolutil.vcxproj | 10 +- - 32 files changed, 531 insertions(+), 380 deletions(-) - -diff --git a/source/common/common.vcxproj b/source/common/common.vcxproj -index ef0dfc1..0b1eab3 100644 ---- a/source/common/common.vcxproj -+++ b/source/common/common.vcxproj -@@ -1,5 +1,5 @@ -  -- -+ - - - Debug -@@ -26,21 +26,25 @@ - DynamicLibrary - false - MultiByte -+ v120 - - - DynamicLibrary - false - MultiByte -+ v120 - - - DynamicLibrary - false - MultiByte -+ v120 - - - DynamicLibrary - false - MultiByte -+ v120 - - - -@@ -65,17 +69,33 @@ - - <_ProjectFileVersion>10.0.30319.1 - .\..\..\lib\ -- .\x86\Release\ -+ x86\$(Configuration) - false - .\..\..\lib\ -- .\x86\Debug\ -- true -+ x86\$(Configuration) -+ false - .\x64\Release\ -- .\x64\Release\ -+ x64\$(Configuration) - false - .\x64\Debug\ -- .\x64\Debug\ -- true -+ x64\$(Configuration) -+ false -+ -+ -+ icuuc52d -+ ..\..\bin -+ -+ -+ icuuc52 -+ ..\..\bin -+ -+ -+ icuuc52d -+ ..\..\bin64 -+ -+ -+ icuuc52 -+ ..\..\bin64 - - - -@@ -104,7 +124,6 @@ - 0x0409 - - -- ..\..\bin\icuuc52.dll - true - .\..\..\lib\icuuc.pdb - true -@@ -135,7 +154,6 @@ - .\x86\Debug/ - .\x86\Debug/ - .\x86\Debug/ -- true - Level3 - true - EditAndContinue -@@ -145,7 +163,6 @@ - 0x0409 - - -- ..\..\bin\icuuc52d.dll - true - true - .\..\..\lib\icuucd.pdb -@@ -183,7 +200,6 @@ - 0x0409 - - -- ..\..\bin64\icuuc52.dll - true - .\..\..\lib64\icuuc.pdb - true -@@ -212,7 +228,6 @@ - .\x64\Debug/ - .\x64\Debug/ - .\x64\Debug/ -- true - Level3 - true - ProgramDatabase -@@ -222,7 +237,6 @@ - 0x0409 - - -- ..\..\bin64\icuuc52d.dll - true - true - .\..\..\lib64\icuucd.pdb -@@ -1751,4 +1765,4 @@ - - - -- -+ -\ No newline at end of file -diff --git a/source/extra/uconv/uconv.vcxproj b/source/extra/uconv/uconv.vcxproj -index 3ff795c..1e9829f 100644 ---- a/source/extra/uconv/uconv.vcxproj -+++ b/source/extra/uconv/uconv.vcxproj -@@ -1,5 +1,5 @@ -  -- -+ - - - Debug -@@ -26,21 +26,25 @@ - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - -@@ -292,4 +296,4 @@ - - - -- -+ -\ No newline at end of file -diff --git a/source/i18n/i18n.vcxproj b/source/i18n/i18n.vcxproj -index 3c1eebb..3f216cc 100644 ---- a/source/i18n/i18n.vcxproj -+++ b/source/i18n/i18n.vcxproj -@@ -1,5 +1,5 @@ -- -- -+ -+ - - - Debug -@@ -26,21 +26,25 @@ - DynamicLibrary - false - MultiByte -+ v120 - - - DynamicLibrary - false - MultiByte -+ v120 - - - DynamicLibrary - false - MultiByte -+ v120 - - - DynamicLibrary - false - MultiByte -+ v120 - - - -@@ -64,18 +68,30 @@ - - - <_ProjectFileVersion>10.0.30319.1 -- .\..\..\lib\ -- .\x86\Release\ -+ ..\..\bin -+ x86\$(Configuration) - false -- .\..\..\lib\ -- .\x86\Debug\ -- true -- .\x64\Release\ -- .\x64\Release\ -+ ..\..\bin -+ x86\$(Configuration) -+ false -+ ..\..\bin64 -+ x64\$(Configuration) - false -- .\x64\Debug\ -- .\x64\Debug\ -- true -+ ..\..\bin64 -+ x64\$(Configuration) -+ false -+ -+ -+ icuin52d -+ -+ -+ icuin52 -+ -+ -+ icuin52d -+ -+ -+ icuin52 - - - -@@ -107,7 +123,6 @@ - ../common;%(AdditionalIncludeDirectories) - - -- ..\..\bin\icuin52.dll - true - .\..\..\lib\icuin.pdb - true -@@ -139,7 +154,6 @@ - .\x86\Debug/ - .\x86\Debug/ - .\x86\Debug/ -- true - Level3 - true - EditAndContinue -@@ -151,7 +165,6 @@ - ../common;%(AdditionalIncludeDirectories) - - -- ..\..\bin\icuin52d.dll - true - true - .\..\..\lib\icuind.pdb -@@ -192,7 +205,6 @@ - ../common;%(AdditionalIncludeDirectories) - - -- ..\..\bin64\icuin52.dll - true - .\..\..\lib64\icuin.pdb - true -@@ -222,7 +234,6 @@ - .\x64\Debug/ - .\x64\Debug/ - .\x64\Debug/ -- true - Level3 - true - ProgramDatabase -@@ -234,7 +245,6 @@ - ../common;%(AdditionalIncludeDirectories) - - -- ..\..\bin64\icuin52d.dll - true - true - .\..\..\lib64\icuind.pdb -@@ -1625,4 +1635,4 @@ - - - -- -+ -\ No newline at end of file -diff --git a/source/i18n/i18n.vcxproj.filters b/source/i18n/i18n.vcxproj.filters -index da3b9aa..554a235 100644 ---- a/source/i18n/i18n.vcxproj.filters -+++ b/source/i18n/i18n.vcxproj.filters -@@ -1050,5 +1050,6 @@ - - misc - -+ - -- -+ -\ No newline at end of file -diff --git a/source/io/io.vcxproj b/source/io/io.vcxproj -index 8944e2a..7b5e178 100644 ---- a/source/io/io.vcxproj -+++ b/source/io/io.vcxproj -@@ -1,5 +1,5 @@ -  -- -+ - - - Debug -@@ -26,21 +26,25 @@ - DynamicLibrary - false - MultiByte -+ v120 - - - DynamicLibrary - false - MultiByte -+ v120 - - - DynamicLibrary - false - MultiByte -+ v120 - - - DynamicLibrary - false - MultiByte -+ v120 - - - -@@ -319,4 +323,4 @@ - - - -- -+ -\ No newline at end of file -diff --git a/source/layout/layout.vcxproj b/source/layout/layout.vcxproj -index d80eb54..90a5e42 100644 ---- a/source/layout/layout.vcxproj -+++ b/source/layout/layout.vcxproj -@@ -1,5 +1,5 @@ -  -- -+ - - - Debug -@@ -26,21 +26,25 @@ - DynamicLibrary - false - MultiByte -+ v120 - - - DynamicLibrary - false - MultiByte -+ v120 - - - DynamicLibrary - false - MultiByte -+ v120 - - - DynamicLibrary - false - MultiByte -+ v120 - - - -@@ -576,4 +580,4 @@ - - - -- -+ -\ No newline at end of file -diff --git a/source/layoutex/layoutex.vcxproj b/source/layoutex/layoutex.vcxproj -index dac4cfe..f2c8dd8 100644 ---- a/source/layoutex/layoutex.vcxproj -+++ b/source/layoutex/layoutex.vcxproj -@@ -1,5 +1,5 @@ -  -- -+ - - - Debug -@@ -27,21 +27,25 @@ - DynamicLibrary - false - MultiByte -+ v120 - - - DynamicLibrary - false - MultiByte -+ v120 - - - DynamicLibrary - false - MultiByte -+ v120 - - - DynamicLibrary - false - MultiByte -+ v120 - - - -@@ -327,4 +331,4 @@ - - - -- -+ -\ No newline at end of file -diff --git a/source/samples/cal/cal.vcxproj b/source/samples/cal/cal.vcxproj -index 13dae70..947e173 100644 ---- a/source/samples/cal/cal.vcxproj -+++ b/source/samples/cal/cal.vcxproj -@@ -1,264 +1,268 @@ -- -- -- -- -- Debug -- Win32 -- -- -- Debug -- x64 -- -- -- Release -- Win32 -- -- -- Release -- x64 -- -- -- -- {F7659D77-09CF-4FE9-ACEE-927287AA9509} -- -- -- -- Application -- false -- MultiByte -- -- -- Application -- false -- MultiByte -- -- -- Application -- false -- MultiByte -- -- -- Application -- false -- MultiByte -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- <_ProjectFileVersion>10.0.30319.1 -- .\x86\Release\ -- .\x86\Release\ -- false -- .\x64\Release\ -- .\x64\Release\ -- false -- .\x86\Debug\ -- .\x86\Debug\ -- true -- .\x64\Debug\ -- .\x64\Debug\ -- true -- -- -- -- .\x86\Release/cal.tlb -- -- -- OnlyExplicitInline -- ..\..\..\include;%(AdditionalIncludeDirectories) -- WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) -- true -- MultiThreadedDLL -- true -- true -- -- -- .\x86\Release/cal.pch -- .\x86\Release/ -- .\x86\Release/ -- .\x86\Release/ -- Level3 -- true -- Default -- -- -- NDEBUG;%(PreprocessorDefinitions) -- 0x0409 -- -- -- icuuc.lib;icuin.lib;%(AdditionalDependencies) -- .\x86\Release/cal.exe -- true -- ../../../lib;%(AdditionalLibraryDirectories) -- .\x86\Release/cal.pdb -- Console -- false -- -- -- -- -- -- -- X64 -- .\x64\Release/cal.tlb -- -- -- OnlyExplicitInline -- ..\..\..\include;%(AdditionalIncludeDirectories) -- WIN64;WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) -- true -- MultiThreadedDLL -- true -- true -- -- -- .\x64\Release/cal.pch -- .\x64\Release/ -- .\x64\Release/ -- .\x64\Release/ -- Level3 -- true -- Default -- -- -- NDEBUG;%(PreprocessorDefinitions) -- 0x0409 -- -- -- icuuc.lib;icuin.lib;%(AdditionalDependencies) -- .\x64\Release/cal.exe -- true -- ../../../lib64;%(AdditionalLibraryDirectories) -- .\x64\Release/cal.pdb -- Console -- false -- -- -- MachineX64 -- -- -- -- -- .\x86\Debug/cal.tlb -- -- -- Disabled -- ..\..\..\include;%(AdditionalIncludeDirectories) -- WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) -- EnableFastChecks -- MultiThreadedDebugDLL -- true -- -- -- .\x86\Debug/cal.pch -- .\x86\Debug/ -- .\x86\Debug/ -- .\x86\Debug/ -- true -- Level3 -- true -- EditAndContinue -- Default -- -- -- _DEBUG;%(PreprocessorDefinitions) -- 0x0409 -- -- -- icuucd.lib;icuind.lib;%(AdditionalDependencies) -- .\x86\Debug/cal.exe -- true -- ../../../lib;%(AdditionalLibraryDirectories) -- true -- .\x86\Debug/cal.pdb -- Console -- false -- -- -- -- -- -- -- X64 -- .\x64\Debug/cal.tlb -- -- -- Disabled -- ..\..\..\include;%(AdditionalIncludeDirectories) -- WIN64;WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) -- EnableFastChecks -- MultiThreadedDebugDLL -- true -- -- -- .\x64\Debug/cal.pch -- .\x64\Debug/ -- .\x64\Debug/ -- .\x64\Debug/ -- true -- Level3 -- true -- ProgramDatabase -- Default -- -- -- _DEBUG;%(PreprocessorDefinitions) -- 0x0409 -- -- -- icuucd.lib;icuind.lib;%(AdditionalDependencies) -- .\x64\Debug/cal.exe -- true -- ../../../lib64;%(AdditionalLibraryDirectories) -- true -- .\x64\Debug/cal.pdb -- Console -- false -- -- -- MachineX64 -- -- -- -+ -+ -+ -+ -+ Debug -+ Win32 -+ -+ -+ Debug -+ x64 -+ -+ -+ Release -+ Win32 -+ -+ -+ Release -+ x64 -+ -+ -+ -+ {F7659D77-09CF-4FE9-ACEE-927287AA9509} -+ -+ -+ -+ Application -+ false -+ MultiByte -+ v120 -+ -+ -+ Application -+ false -+ MultiByte -+ v120 -+ -+ -+ Application -+ false -+ MultiByte -+ v120 -+ -+ -+ Application -+ false -+ MultiByte -+ v120 -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ <_ProjectFileVersion>10.0.30319.1 -+ .\x86\Release\ -+ .\x86\Release\ -+ false -+ .\x64\Release\ -+ .\x64\Release\ -+ false -+ .\x86\Debug\ -+ .\x86\Debug\ -+ true -+ .\x64\Debug\ -+ .\x64\Debug\ -+ true -+ -+ -+ -+ .\x86\Release/cal.tlb -+ -+ -+ OnlyExplicitInline -+ ..\..\..\include;%(AdditionalIncludeDirectories) -+ WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) -+ true -+ MultiThreadedDLL -+ true -+ true -+ -+ -+ .\x86\Release/cal.pch -+ .\x86\Release/ -+ .\x86\Release/ -+ .\x86\Release/ -+ Level3 -+ true -+ Default -+ -+ -+ NDEBUG;%(PreprocessorDefinitions) -+ 0x0409 -+ -+ -+ icuuc.lib;icuin.lib;%(AdditionalDependencies) -+ .\x86\Release/cal.exe -+ true -+ ../../../lib;%(AdditionalLibraryDirectories) -+ .\x86\Release/cal.pdb -+ Console -+ false -+ -+ -+ -+ -+ -+ -+ X64 -+ .\x64\Release/cal.tlb -+ -+ -+ OnlyExplicitInline -+ ..\..\..\include;%(AdditionalIncludeDirectories) -+ WIN64;WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) -+ true -+ MultiThreadedDLL -+ true -+ true -+ -+ -+ .\x64\Release/cal.pch -+ .\x64\Release/ -+ .\x64\Release/ -+ .\x64\Release/ -+ Level3 -+ true -+ Default -+ -+ -+ NDEBUG;%(PreprocessorDefinitions) -+ 0x0409 -+ -+ -+ icuuc.lib;icuin.lib;%(AdditionalDependencies) -+ .\x64\Release/cal.exe -+ true -+ ../../../lib64;%(AdditionalLibraryDirectories) -+ .\x64\Release/cal.pdb -+ Console -+ false -+ -+ -+ MachineX64 -+ -+ -+ -+ -+ .\x86\Debug/cal.tlb -+ -+ -+ Disabled -+ ..\..\..\include;%(AdditionalIncludeDirectories) -+ WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) -+ EnableFastChecks -+ MultiThreadedDebugDLL -+ true -+ -+ -+ .\x86\Debug/cal.pch -+ .\x86\Debug/ -+ .\x86\Debug/ -+ .\x86\Debug/ -+ true -+ Level3 -+ true -+ EditAndContinue -+ Default -+ -+ -+ _DEBUG;%(PreprocessorDefinitions) -+ 0x0409 -+ -+ -+ icuucd.lib;icuind.lib;%(AdditionalDependencies) -+ .\x86\Debug/cal.exe -+ true -+ ../../../lib;%(AdditionalLibraryDirectories) -+ true -+ .\x86\Debug/cal.pdb -+ Console -+ false -+ -+ -+ -+ -+ -+ -+ X64 -+ .\x64\Debug/cal.tlb -+ -+ -+ Disabled -+ ..\..\..\include;%(AdditionalIncludeDirectories) -+ WIN64;WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) -+ EnableFastChecks -+ MultiThreadedDebugDLL -+ true -+ -+ -+ .\x64\Debug/cal.pch -+ .\x64\Debug/ -+ .\x64\Debug/ -+ .\x64\Debug/ -+ true -+ Level3 -+ true -+ ProgramDatabase -+ Default -+ -+ -+ _DEBUG;%(PreprocessorDefinitions) -+ 0x0409 -+ -+ -+ icuucd.lib;icuind.lib;%(AdditionalDependencies) -+ .\x64\Debug/cal.exe -+ true -+ ../../../lib64;%(AdditionalLibraryDirectories) -+ true -+ .\x64\Debug/cal.pdb -+ Console -+ false -+ -+ -+ MachineX64 -+ -+ -+ - -- false -- -+ false -+ - -- false -- -- -- -- -- -- -- -- {73c0a65b-d1f2-4de1-b3a6-15dad2c23f3d} -- false -- -- -- {0178b127-6269-407d-b112-93877bb62776} -- false -- -- -- -- -- -- -+ false -+ -+ -+ -+ -+ -+ -+ -+ {73c0a65b-d1f2-4de1-b3a6-15dad2c23f3d} -+ false -+ -+ -+ {0178b127-6269-407d-b112-93877bb62776} -+ false -+ -+ -+ -+ -+ -+ -\ No newline at end of file -diff --git a/source/samples/date/date.vcxproj b/source/samples/date/date.vcxproj -index 0632b3f..38d70a9 100644 ---- a/source/samples/date/date.vcxproj -+++ b/source/samples/date/date.vcxproj -@@ -1,5 +1,5 @@ -  -- -+ - - - Debug -@@ -26,21 +26,25 @@ - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - -@@ -255,4 +259,4 @@ - - - -- -+ -\ No newline at end of file -diff --git a/source/stubdata/stubdata.vcxproj b/source/stubdata/stubdata.vcxproj -index ed4ca6b..541f19f 100644 ---- a/source/stubdata/stubdata.vcxproj -+++ b/source/stubdata/stubdata.vcxproj -@@ -1,5 +1,5 @@ -  -- -+ - - - Debug -@@ -26,21 +26,25 @@ - DynamicLibrary - false - MultiByte -+ v120 - - - DynamicLibrary - false - MultiByte -+ v120 - - - DynamicLibrary - false - MultiByte -+ v120 - - - DynamicLibrary - false - MultiByte -+ v120 - - - -@@ -64,21 +68,35 @@ - - - <_ProjectFileVersion>10.0.30319.1 -- .\x86\Release\ -- .\x86\Release\ -+ ..\..\bin - false - false -- .\x86\Debug\ -- .\x86\Debug\ -+ ..\..\bin - false -- .\x64\Release\ -- .\x64\Release\ -+ ..\..\bin64 - false - false -- .\x64\Debug\ -- .\x64\Debug\ -+ ..\..\bin64 - false - -+ -+ icudt52d -+ x86\$(Configuration) -+ false -+ -+ -+ icudt52d -+ x64\$(Configuration) -+ false -+ -+ -+ icudt52 -+ x86\$(Configuration) -+ -+ -+ icudt52 -+ x64\$(Configuration) -+ - - - NDEBUG;%(PreprocessorDefinitions) -@@ -113,7 +131,6 @@ - echo "File with stubdata build time, used as a dependency to trigger fresh data build, since stubdata dll will overwrite the real one." > "$(ProjectDir)stubdatabuilt.txt" - - -- ..\..\bin\icudt52.dll - true - true - .\x86\Release\icudt.pdb -@@ -160,7 +177,6 @@ - echo "File with stubdata build time, used as a dependency to trigger fresh data build, since stubdata dll will overwrite the real one." > "$(ProjectDir)stubdatabuilt.txt" - - -- ..\..\bin\icudt52.dll - true - .\x86\Debug/icudt.pdb - true -@@ -207,7 +223,6 @@ - echo "File with stubdata build time, used as a dependency to trigger fresh data build, since stubdata dll will overwrite the real one." > "$(ProjectDir)stubdatabuilt.txt" - - -- ..\..\bin64\icudt52.dll - true - true - .\x64\Release\icudt.pdb -@@ -252,7 +267,6 @@ - echo "File with stubdata build time, used as a dependency to trigger fresh data build, since stubdata dll will overwrite the real one." > "$(ProjectDir)stubdatabuilt.txt" - - -- ..\..\bin64\icudt52.dll - true - .\x64\Debug/icudt.pdb - true -@@ -277,4 +291,4 @@ - - - -- -+ -\ No newline at end of file -diff --git a/source/test/cintltst/cintltst.vcxproj b/source/test/cintltst/cintltst.vcxproj -index 17529b6..f04da0c 100644 ---- a/source/test/cintltst/cintltst.vcxproj -+++ b/source/test/cintltst/cintltst.vcxproj -@@ -1,5 +1,5 @@ -  -- -+ - - - Debug -@@ -26,21 +26,25 @@ - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - -@@ -373,4 +377,4 @@ - - - -- -+ -\ No newline at end of file -diff --git a/source/test/intltest/intltest.vcxproj b/source/test/intltest/intltest.vcxproj -index 8a6698e..9ee9bc7 100644 ---- a/source/test/intltest/intltest.vcxproj -+++ b/source/test/intltest/intltest.vcxproj -@@ -1,5 +1,5 @@ -  -- -+ - - - Debug -@@ -27,21 +27,25 @@ - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - -@@ -229,7 +233,7 @@ - - - -- false -+ false - - - -@@ -260,7 +264,7 @@ - - - -- false -+ false - - - false -@@ -276,7 +280,7 @@ - - - -- false -+ false - - - -@@ -284,7 +288,7 @@ - - - -- false -+ false - - - -@@ -326,13 +330,13 @@ - - - -- false -+ false - - - - - -- false -+ false - - - false -@@ -351,7 +355,7 @@ - - - -- false -+ false - - - -@@ -360,35 +364,35 @@ - - - -- false -+ false - - -- false -+ false - - -- false -+ false - - - - - -- false -+ false - - - - -- false -+ false - - -- false -+ false - - -- false -+ false - - - - -- false -+ false - - - -@@ -561,4 +565,4 @@ - - - -- -+ -\ No newline at end of file -diff --git a/source/test/iotest/iotest.vcxproj b/source/test/iotest/iotest.vcxproj -index 0d39d29..5172208 100644 ---- a/source/test/iotest/iotest.vcxproj -+++ b/source/test/iotest/iotest.vcxproj -@@ -1,5 +1,5 @@ -  -- -+ - - - Debug -@@ -26,21 +26,25 @@ - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - -@@ -259,4 +263,4 @@ - - - -- -+ -\ No newline at end of file -diff --git a/source/test/letest/letest.vcxproj b/source/test/letest/letest.vcxproj -index a71d629..be01399 100644 ---- a/source/test/letest/letest.vcxproj -+++ b/source/test/letest/letest.vcxproj -@@ -1,5 +1,5 @@ -  -- -+ - - - Debug -@@ -26,21 +26,25 @@ - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - -@@ -274,4 +278,4 @@ - - - -- -+ -\ No newline at end of file -diff --git a/source/tools/ctestfw/ctestfw.vcxproj b/source/tools/ctestfw/ctestfw.vcxproj -index 7dbdc9f..9281a1b 100644 ---- a/source/tools/ctestfw/ctestfw.vcxproj -+++ b/source/tools/ctestfw/ctestfw.vcxproj -@@ -1,5 +1,5 @@ -  -- -+ - - - Debug -@@ -26,21 +26,25 @@ - DynamicLibrary - false - MultiByte -+ v120 - - - DynamicLibrary - false - MultiByte -+ v120 - - - DynamicLibrary - false - MultiByte -+ v120 - - - DynamicLibrary - false - MultiByte -+ v120 - - - -@@ -280,4 +284,4 @@ - - - -- -+ -\ No newline at end of file -diff --git a/source/tools/genbrk/genbrk.vcxproj b/source/tools/genbrk/genbrk.vcxproj -index 73e5372..8ae2620 100644 ---- a/source/tools/genbrk/genbrk.vcxproj -+++ b/source/tools/genbrk/genbrk.vcxproj -@@ -1,5 +1,5 @@ -  -- -+ - - - Debug -@@ -26,21 +26,25 @@ - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - -@@ -255,4 +259,4 @@ - - - -- -+ -\ No newline at end of file -diff --git a/source/tools/genccode/genccode.vcxproj b/source/tools/genccode/genccode.vcxproj -index f6fd59d..e1bb8fb 100644 ---- a/source/tools/genccode/genccode.vcxproj -+++ b/source/tools/genccode/genccode.vcxproj -@@ -1,5 +1,5 @@ -  -- -+ - - - Debug -@@ -26,21 +26,25 @@ - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - -@@ -251,4 +255,4 @@ - - - -- -+ -\ No newline at end of file -diff --git a/source/tools/gencfu/gencfu.vcxproj b/source/tools/gencfu/gencfu.vcxproj -index 18c63a6..315ca7b 100644 ---- a/source/tools/gencfu/gencfu.vcxproj -+++ b/source/tools/gencfu/gencfu.vcxproj -@@ -1,5 +1,5 @@ -  -- -+ - - - Debug -@@ -27,20 +27,24 @@ - Application - false - MultiByte -+ v120 - - - Application - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - -@@ -238,4 +242,4 @@ - - - -- -+ -\ No newline at end of file -diff --git a/source/tools/gencmn/gencmn.vcxproj b/source/tools/gencmn/gencmn.vcxproj -index 6c83ef4..91f0a64 100644 ---- a/source/tools/gencmn/gencmn.vcxproj -+++ b/source/tools/gencmn/gencmn.vcxproj -@@ -1,5 +1,5 @@ -  -- -+ - - - Debug -@@ -26,21 +26,25 @@ - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - -@@ -255,4 +259,4 @@ - - - -- -+ -\ No newline at end of file -diff --git a/source/tools/gencnval/gencnval.vcxproj b/source/tools/gencnval/gencnval.vcxproj -index ca12c12..474f1a2 100644 ---- a/source/tools/gencnval/gencnval.vcxproj -+++ b/source/tools/gencnval/gencnval.vcxproj -@@ -1,5 +1,5 @@ -  -- -+ - - - Debug -@@ -26,21 +26,25 @@ - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - -@@ -255,4 +259,4 @@ - - - -- -+ -\ No newline at end of file -diff --git a/source/tools/gendict/gendict.vcxproj b/source/tools/gendict/gendict.vcxproj -index 6852b44..968f817 100644 ---- a/source/tools/gendict/gendict.vcxproj -+++ b/source/tools/gendict/gendict.vcxproj -@@ -1,5 +1,5 @@ -  -- -+ - - - Debug -@@ -26,21 +26,25 @@ - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - -@@ -255,4 +259,4 @@ - - - -- -+ -\ No newline at end of file -diff --git a/source/tools/gennorm2/gennorm2.vcxproj b/source/tools/gennorm2/gennorm2.vcxproj -index 4245a0b..bf60570 100644 ---- a/source/tools/gennorm2/gennorm2.vcxproj -+++ b/source/tools/gennorm2/gennorm2.vcxproj -@@ -1,5 +1,5 @@ -  -- -+ - - - Debug -@@ -27,20 +27,24 @@ - - Application - Unicode -+ v120 - - - Application - Unicode - true -+ v120 - - - Application - Unicode -+ v120 - - - Application - Unicode - true -+ v120 - - - -@@ -263,4 +267,4 @@ - - - -- -+ -\ No newline at end of file -diff --git a/source/tools/genrb/derb.vcxproj b/source/tools/genrb/derb.vcxproj -index b2e27e6..9c14c94 100644 ---- a/source/tools/genrb/derb.vcxproj -+++ b/source/tools/genrb/derb.vcxproj -@@ -1,5 +1,5 @@ -  -- -+ - - - Debug -@@ -26,21 +26,25 @@ - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - -@@ -278,4 +282,4 @@ - - - -- -+ -\ No newline at end of file -diff --git a/source/tools/genrb/genrb.vcxproj b/source/tools/genrb/genrb.vcxproj -index b7f48ef..ad02f5b 100644 ---- a/source/tools/genrb/genrb.vcxproj -+++ b/source/tools/genrb/genrb.vcxproj -@@ -1,5 +1,5 @@ -  -- -+ - - - Debug -@@ -26,21 +26,25 @@ - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - -@@ -278,4 +282,4 @@ - - - -- -+ -\ No newline at end of file -diff --git a/source/tools/gensprep/gensprep.vcxproj b/source/tools/gensprep/gensprep.vcxproj -index 533b546..fad1e63 100644 ---- a/source/tools/gensprep/gensprep.vcxproj -+++ b/source/tools/gensprep/gensprep.vcxproj -@@ -1,5 +1,5 @@ -  -- -+ - - - Debug -@@ -26,21 +26,25 @@ - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - -@@ -257,4 +261,4 @@ - - - -- -+ -\ No newline at end of file -diff --git a/source/tools/gentest/gentest.vcxproj b/source/tools/gentest/gentest.vcxproj -index f8fb903..96a8b15 100644 ---- a/source/tools/gentest/gentest.vcxproj -+++ b/source/tools/gentest/gentest.vcxproj -@@ -1,5 +1,5 @@ -  -- -+ - - - Debug -@@ -27,21 +27,25 @@ - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - -@@ -244,4 +248,4 @@ - - - -- -+ -\ No newline at end of file -diff --git a/source/tools/icuinfo/icuinfo.vcxproj b/source/tools/icuinfo/icuinfo.vcxproj -index 6da52ed..864b5e7 100644 ---- a/source/tools/icuinfo/icuinfo.vcxproj -+++ b/source/tools/icuinfo/icuinfo.vcxproj -@@ -1,5 +1,5 @@ -  -- -+ - - - Debug -@@ -28,21 +28,25 @@ - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - -@@ -256,4 +260,4 @@ - - - -- -+ -\ No newline at end of file -diff --git a/source/tools/icuinfo/testplug.vcxproj b/source/tools/icuinfo/testplug.vcxproj -index edf6858..cc5a0ec 100644 ---- a/source/tools/icuinfo/testplug.vcxproj -+++ b/source/tools/icuinfo/testplug.vcxproj -@@ -1,5 +1,5 @@ -  -- -+ - - - Debug -@@ -26,21 +26,25 @@ - DynamicLibrary - false - MultiByte -+ v120 - - - DynamicLibrary - false - MultiByte -+ v120 - - - DynamicLibrary - false - MultiByte -+ v120 - - - DynamicLibrary - false - MultiByte -+ v120 - - - -@@ -255,4 +259,4 @@ - - - -- -+ -\ No newline at end of file -diff --git a/source/tools/icupkg/icupkg.vcxproj b/source/tools/icupkg/icupkg.vcxproj -index b3c762c..606276d 100644 ---- a/source/tools/icupkg/icupkg.vcxproj -+++ b/source/tools/icupkg/icupkg.vcxproj -@@ -1,5 +1,5 @@ -  -- -+ - - - Debug -@@ -27,21 +27,25 @@ - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - -@@ -244,4 +248,4 @@ - - - -- -+ -\ No newline at end of file -diff --git a/source/tools/makeconv/makeconv.vcxproj b/source/tools/makeconv/makeconv.vcxproj -index 110dee9..3d302d3 100644 ---- a/source/tools/makeconv/makeconv.vcxproj -+++ b/source/tools/makeconv/makeconv.vcxproj -@@ -1,5 +1,5 @@ -  -- -+ - - - Debug -@@ -26,21 +26,25 @@ - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - -@@ -260,4 +264,4 @@ - - - -- -+ -\ No newline at end of file -diff --git a/source/tools/pkgdata/pkgdata.vcxproj b/source/tools/pkgdata/pkgdata.vcxproj -index 18fa39d..b2d72bd 100644 ---- a/source/tools/pkgdata/pkgdata.vcxproj -+++ b/source/tools/pkgdata/pkgdata.vcxproj -@@ -1,5 +1,5 @@ -  -- -+ - - - Debug -@@ -26,21 +26,25 @@ - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - Application - false - MultiByte -+ v120 - - - -@@ -271,4 +275,4 @@ - - - -- -+ -\ No newline at end of file -diff --git a/source/tools/toolutil/toolutil.vcxproj b/source/tools/toolutil/toolutil.vcxproj -index 8cb1277..5574582 100644 ---- a/source/tools/toolutil/toolutil.vcxproj -+++ b/source/tools/toolutil/toolutil.vcxproj -@@ -1,5 +1,5 @@ -  -- -+ - - - Debug -@@ -26,21 +26,25 @@ - DynamicLibrary - false - MultiByte -+ v120 - - - DynamicLibrary - false - MultiByte -+ v120 - - - DynamicLibrary - false - MultiByte -+ v120 - - - DynamicLibrary - false - MultiByte -+ v120 - - - -@@ -267,7 +271,7 @@ - - - -- false -+ false - - - false -@@ -328,4 +332,4 @@ - - - -- -+ -\ No newline at end of file --- -1.9.0.msysgit.0 - diff --git a/windows/patches/icu/0002-Qt-requires-U_CHARSET_IS_UTF8-1.patch b/windows/patches/icu/0002-Qt-requires-U_CHARSET_IS_UTF8-1.patch deleted file mode 100644 index 5b9f3e959..000000000 --- a/windows/patches/icu/0002-Qt-requires-U_CHARSET_IS_UTF8-1.patch +++ /dev/null @@ -1,26 +0,0 @@ -From fca4313ae7ac54ebb5a6f3b46451306223b53aeb Mon Sep 17 00:00:00 2001 -From: Tim Hughes -Date: Mon, 21 Apr 2014 13:33:29 +0100 -Subject: [PATCH 2/3] Qt requires U_CHARSET_IS_UTF8 1 - -Signed-off-by: Tim Hughes ---- - source/common/unicode/platform.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/source/common/unicode/platform.h b/source/common/unicode/platform.h -index 1b2ab30..cca7039 100644 ---- a/source/common/unicode/platform.h -+++ b/source/common/unicode/platform.h -@@ -543,7 +543,7 @@ - #elif U_PLATFORM == U_PF_ANDROID || U_PLATFORM_IS_DARWIN_BASED - # define U_CHARSET_IS_UTF8 1 - #else --# define U_CHARSET_IS_UTF8 0 -+# define U_CHARSET_IS_UTF8 1 - #endif - - /** @} */ --- -1.9.0.msysgit.0 - diff --git a/windows/patches/icu/0003-Add-minimal-icu.sln.patch b/windows/patches/icu/0003-Add-minimal-icu.sln.patch deleted file mode 100644 index 62ce164d8..000000000 --- a/windows/patches/icu/0003-Add-minimal-icu.sln.patch +++ /dev/null @@ -1,71 +0,0 @@ -From dcb7b9172a3f7ec5d607696a86fefad69c03a400 Mon Sep 17 00:00:00 2001 -From: Tim Hughes -Date: Mon, 21 Apr 2014 13:33:59 +0100 -Subject: [PATCH 3/3] Add minimal icu.sln - -Signed-off-by: Tim Hughes ---- - source/allinone/icu.sln | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 51 insertions(+) - create mode 100644 source/allinone/icu.sln - -diff --git a/source/allinone/icu.sln b/source/allinone/icu.sln -new file mode 100644 -index 0000000..b09697f ---- /dev/null -+++ b/source/allinone/icu.sln -@@ -0,0 +1,51 @@ -+Microsoft Visual Studio Solution File, Format Version 12.00 -+# Visual Studio Express 2013 for Windows Desktop -+VisualStudioVersion = 12.0.21005.1 -+MinimumVisualStudioVersion = 10.0.40219.1 -+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "..\common\common.vcxproj", "{73C0A65B-D1F2-4DE1-B3A6-15DAD2C23F3D}" -+EndProject -+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "i18n", "..\i18n\i18n.vcxproj", "{0178B127-6269-407D-B112-93877BB62776}" -+EndProject -+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stubdata", "..\stubdata\stubdata.vcxproj", "{203EC78A-0531-43F0-A636-285439BDE025}" -+EndProject -+Global -+ GlobalSection(SolutionConfigurationPlatforms) = preSolution -+ Debug|Win32 = Debug|Win32 -+ Debug|x64 = Debug|x64 -+ Release|Win32 = Release|Win32 -+ Release|x64 = Release|x64 -+ EndGlobalSection -+ GlobalSection(ProjectConfigurationPlatforms) = postSolution -+ {73C0A65B-D1F2-4DE1-B3A6-15DAD2C23F3D}.Debug|Win32.ActiveCfg = Debug|Win32 -+ {73C0A65B-D1F2-4DE1-B3A6-15DAD2C23F3D}.Debug|Win32.Build.0 = Debug|Win32 -+ {73C0A65B-D1F2-4DE1-B3A6-15DAD2C23F3D}.Debug|x64.ActiveCfg = Debug|x64 -+ {73C0A65B-D1F2-4DE1-B3A6-15DAD2C23F3D}.Debug|x64.Build.0 = Debug|x64 -+ {73C0A65B-D1F2-4DE1-B3A6-15DAD2C23F3D}.Release|Win32.ActiveCfg = Release|Win32 -+ {73C0A65B-D1F2-4DE1-B3A6-15DAD2C23F3D}.Release|Win32.Build.0 = Release|Win32 -+ {73C0A65B-D1F2-4DE1-B3A6-15DAD2C23F3D}.Release|x64.ActiveCfg = Release|x64 -+ {73C0A65B-D1F2-4DE1-B3A6-15DAD2C23F3D}.Release|x64.Build.0 = Release|x64 -+ {0178B127-6269-407D-B112-93877BB62776}.Debug|Win32.ActiveCfg = Debug|Win32 -+ {0178B127-6269-407D-B112-93877BB62776}.Debug|Win32.Build.0 = Debug|Win32 -+ {0178B127-6269-407D-B112-93877BB62776}.Debug|x64.ActiveCfg = Debug|x64 -+ {0178B127-6269-407D-B112-93877BB62776}.Debug|x64.Build.0 = Debug|x64 -+ {0178B127-6269-407D-B112-93877BB62776}.Release|Win32.ActiveCfg = Release|Win32 -+ {0178B127-6269-407D-B112-93877BB62776}.Release|Win32.Build.0 = Release|Win32 -+ {0178B127-6269-407D-B112-93877BB62776}.Release|x64.ActiveCfg = Release|x64 -+ {0178B127-6269-407D-B112-93877BB62776}.Release|x64.Build.0 = Release|x64 -+ {203EC78A-0531-43F0-A636-285439BDE025}.Debug|Win32.ActiveCfg = Debug|Win32 -+ {203EC78A-0531-43F0-A636-285439BDE025}.Debug|Win32.Build.0 = Debug|Win32 -+ {203EC78A-0531-43F0-A636-285439BDE025}.Debug|x64.ActiveCfg = Debug|x64 -+ {203EC78A-0531-43F0-A636-285439BDE025}.Debug|x64.Build.0 = Debug|x64 -+ {203EC78A-0531-43F0-A636-285439BDE025}.Release|Win32.ActiveCfg = Release|Win32 -+ {203EC78A-0531-43F0-A636-285439BDE025}.Release|Win32.Build.0 = Release|Win32 -+ {203EC78A-0531-43F0-A636-285439BDE025}.Release|x64.ActiveCfg = Release|x64 -+ {203EC78A-0531-43F0-A636-285439BDE025}.Release|x64.Build.0 = Release|x64 -+ EndGlobalSection -+ GlobalSection(SolutionProperties) = preSolution -+ HideSolutionNode = FALSE -+ EndGlobalSection -+ GlobalSection(SubversionScc) = preSolution -+ Svn-Managed = True -+ Manager = AnkhSVN - Subversion Support for Visual Studio -+ EndGlobalSection -+EndGlobal --- -1.9.0.msysgit.0 - diff --git a/windows/qt_plugin_import.cpp b/windows/qt_plugin_import.cpp deleted file mode 100644 index b3afd8a4e..000000000 --- a/windows/qt_plugin_import.cpp +++ /dev/null @@ -1,4 +0,0 @@ -// This file is autogenerated by qmake. It imports static plugin classes for -// static plugins specified using QTPLUGIN and QT_PLUGIN_CLASS. variables. -#include -Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin) diff --git a/windows/stdafx.cpp b/windows/stdafx.cpp deleted file mode 100644 index d3c5fc299..000000000 --- a/windows/stdafx.cpp +++ /dev/null @@ -1,21 +0,0 @@ -/* - This file is part of cpp-ethereum. - - cpp-ethereum is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - cpp-ethereum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with cpp-ethereum. If not, see . -*/ -/** @file stdafx.cpp - * @author Tim Hughes - * @date 2014 - */ - diff --git a/windows/stdafx.h b/windows/stdafx.h deleted file mode 100644 index 5a4e4d27d..000000000 --- a/windows/stdafx.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - This file is part of cpp-ethereum. - - cpp-ethereum is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - cpp-ethereum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with cpp-ethereum. If not, see . -*/ -/** @file stdafx.h - * @author Tim Hughes - * @date 2014 - */ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#pragma warning(push) -#pragma warning(disable: 4100 4267) -#include -#pragma warning(pop) - - From c1948f05e1244d8465f2a9c608ca1a9f1a1f2f5e Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 9 Dec 2014 01:15:25 +0100 Subject: [PATCH 451/641] removed old unused precompiled headers for msvc --- libdevcore/_libdevcore.cpp | 13 ------------- libethcore/_libethcore.cpp | 7 ------- libevm/_libevm.cpp | 6 ------ libp2p/_libp2p.cpp | 9 --------- 4 files changed, 35 deletions(-) delete mode 100644 libdevcore/_libdevcore.cpp delete mode 100644 libethcore/_libethcore.cpp delete mode 100644 libevm/_libevm.cpp delete mode 100644 libp2p/_libp2p.cpp diff --git a/libdevcore/_libdevcore.cpp b/libdevcore/_libdevcore.cpp deleted file mode 100644 index 0605791de..000000000 --- a/libdevcore/_libdevcore.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#ifdef _MSC_VER -#include "All.h" -#include "Common.cpp" -#include "CommonData.cpp" -#include "CommonIO.cpp" -#include "CommonJS.h" -#include "FixedHash.cpp" -#include "Guards.cpp" -#include "Log.cpp" -#include "RangeMask.cpp" -#include "RLP.cpp" -#include "Worker.cpp" -#endif diff --git a/libethcore/_libethcore.cpp b/libethcore/_libethcore.cpp deleted file mode 100644 index 93eaf0d16..000000000 --- a/libethcore/_libethcore.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#ifdef _MSC_VER -#include "All.h" -#include "BlockInfo.cpp" -#include "CommonEth.cpp" -#include "ProofOfWork.cpp" -#include "Exceptions.cpp" -#endif diff --git a/libevm/_libevm.cpp b/libevm/_libevm.cpp deleted file mode 100644 index 27186cbf2..000000000 --- a/libevm/_libevm.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#ifdef _MSC_VER -#include "All.h" -#include "ExtVMFace.cpp" -#include "FeeStructure.cpp" -#include "VM.cpp" -#endif diff --git a/libp2p/_libp2p.cpp b/libp2p/_libp2p.cpp deleted file mode 100644 index 440ba362b..000000000 --- a/libp2p/_libp2p.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#ifdef _MSC_VER -#include "All.h" -#include "Capability.cpp" -#include "Common.cpp" -#include "Host.cpp" -#include "HostCapability.cpp" -#include "Session.cpp" -#include "UPnP.cpp" -#endif From 5f4627043da856068a82b482ba76c46e2a3c26f4 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 9 Dec 2014 09:39:46 +0100 Subject: [PATCH 452/641] - returning empty string instead of NULL --- libdevcore/CommonJS.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libdevcore/CommonJS.cpp b/libdevcore/CommonJS.cpp index 8d8638da5..9dc04b7e7 100644 --- a/libdevcore/CommonJS.cpp +++ b/libdevcore/CommonJS.cpp @@ -87,22 +87,22 @@ std::string fromRaw(h256 _n, unsigned* _inc) std::string s((char const*)_n.data(), 32); auto l = s.find_first_of('\0'); if (!l) - return NULL; + return ""; if (l != std::string::npos) { auto p = s.find_first_not_of('\0', l); if (!(p == std::string::npos || (_inc && p == 31))) - return NULL; + return ""; if (_inc) *_inc = (byte)s[31]; s.resize(l); } for (auto i: s) if (i < 32) - return NULL; + return ""; return s; } - return NULL; + return ""; } Address fromString(std::string _sn) From 44de002f3fc2c88f228e25cf09e87a7165c63a4b Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 9 Dec 2014 13:08:02 +0100 Subject: [PATCH 453/641] added curl libaries, which are required for testeth project --- cmake/EthDependencies.cmake | 6 ++++++ extdep/CMakeLists.txt | 1 + libp2p/Host.cpp | 2 +- test/CMakeLists.txt | 1 + 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index fb2aafd47..f957dd3ac 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -71,6 +71,12 @@ if (GMP_FOUND) message(" - gmp lib : ${GMP_LIBRARY}") endif() +# curl is only requried for tests +# TODO specify min curl version, on windows we are currenly using 7.29 +find_package (curl) +message(" - curl header: ${CURL_INCLUDE_DIR}") +message(" - curl lib : ${CURL_LIBRARY}") + # TODO make headless client optional find_package (QT5Core REQUIRED) find_package (QT5Gui REQUIRED) diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index cea32c80f..031093f56 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -44,6 +44,7 @@ else() eth_download(qt) eth_download(cryptopp) eth_download(boost) + eth_download(curl) endif() diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index 93a6ce672..52ceb5df3 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -42,7 +42,7 @@ Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, bool m_clientVersion(_clientVersion), m_netPrefs(_n), m_ifAddresses(Network::getInterfaceAddresses()), - m_ioService(2), + m_ioService(), m_acceptorV4(m_ioService), m_key(KeyPair::create()) { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e27e0949d..3beb36643 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -18,6 +18,7 @@ target_link_libraries(testeth secp256k1) target_link_libraries(testeth solidity) target_link_libraries(testeth webthree) target_link_libraries(testeth ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY_RELEASE}) +target_link_libraries(testeth ${CURL_LIBRARY}) if (JSON_RPC_CPP_FOUND) target_link_libraries(testeth web3jsonrpc) From 546ff5c4f692d4e3ecdeb51223ca21963b95f5d1 Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 9 Dec 2014 16:19:17 +0100 Subject: [PATCH 454/641] ubuntu cmake fixes --- cmake/EthDependencies.cmake | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index f957dd3ac..de1407b0a 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -5,7 +5,7 @@ # this must be set to point to the same directory as $ETH_DEPENDENCY_INSTALL_DIR in /extdep directory string(TOLOWER ${CMAKE_SYSTEM_NAME} _system_name) set (CMAKE_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/extdep/install/${_system_name}") -set (CMAKE_PREFIX_PATH ${CMAKE_DEPENDENCY_INSTALL_DIR}) +set (CMAKE_PREFIX_PATH ${CMAKE_DEPENDENCY_INSTALL_DIR} ";/usr") # Qt5 requires opengl # TODO use proper version of windows SDK (32 vs 64) @@ -73,13 +73,13 @@ endif() # curl is only requried for tests # TODO specify min curl version, on windows we are currenly using 7.29 -find_package (curl) +find_package (CURL) message(" - curl header: ${CURL_INCLUDE_DIR}") message(" - curl lib : ${CURL_LIBRARY}") # TODO make headless client optional -find_package (QT5Core REQUIRED) -find_package (QT5Gui REQUIRED) +find_package (Qt5Core REQUIRED) +find_package (Qt5Gui REQUIRED) find_package (Qt5Quick REQUIRED) find_package (Qt5Qml REQUIRED) find_package (Qt5Network REQUIRED) @@ -87,16 +87,20 @@ find_package (Qt5Widgets REQUIRED) find_package (Qt5WebKit REQUIRED) find_package (Qt5WebKitWidgets REQUIRED) -# we have to specify here if we want static and boost version, that is really important -set(Boost_USE_STATIC_LIBS ON) -set(Boost_USE_MULTITHREADED ON) - -# TODO hanlde other msvc versions or it will fail find them if (${CMAKE_CXX_COMPILER_ID} MATCHES "MSVC") + # TODO hanlde other msvc versions or it will fail find them set(Boost_COMPILER -vc120) + set(Boost_USE_STATIC_LIBS ON) + set(Boost_USE_MULTITHREADED ON) +elseif(APPLE) + set(Boost_USE_STATIC_LIBS ON) + set(Boost_USE_MULTITHREADED ON) +elseif(UNIX) + set(Boost_USE_STATIC_LIBS OFF) + set(Boost_USE_MULTITHREADED ON) endif() -find_package(Boost 1.55.0 REQUIRED COMPONENTS thread date_time system regex chrono filesystem unit_test_framework) +find_package(Boost 1.54.0 REQUIRED COMPONENTS thread date_time system regex chrono filesystem unit_test_framework) message(" - boost header: ${Boost_INCLUDE_DIRS}") message(" - boost lib : ${Boost_LIBRARIES}") From c9e413daafaaab668918bfd24182eea6944d8a9c Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Tue, 9 Dec 2014 16:54:05 +0100 Subject: [PATCH 455/641] empty sha test && common fix on mac --- cmake/EthDependencies.cmake | 2 +- test/genesis.cpp | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index de1407b0a..600d9b72e 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -5,7 +5,7 @@ # this must be set to point to the same directory as $ETH_DEPENDENCY_INSTALL_DIR in /extdep directory string(TOLOWER ${CMAKE_SYSTEM_NAME} _system_name) set (CMAKE_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/extdep/install/${_system_name}") -set (CMAKE_PREFIX_PATH ${CMAKE_DEPENDENCY_INSTALL_DIR} ";/usr") +set (CMAKE_PREFIX_PATH ${CMAKE_DEPENDENCY_INSTALL_DIR}) # Qt5 requires opengl # TODO use proper version of windows SDK (32 vs 64) diff --git a/test/genesis.cpp b/test/genesis.cpp index 6839d42e2..90974d1b8 100644 --- a/test/genesis.cpp +++ b/test/genesis.cpp @@ -36,6 +36,15 @@ namespace js = json_spirit; BOOST_AUTO_TEST_SUITE(BasicTests) +BOOST_AUTO_TEST_CASE(emptySHA3Types) +{ + h256 emptyListSHA3(fromHex("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")); + BOOST_REQUIRE_EQUAL(emptyListSHA3, EmptyListSHA3); + + h256 emptySHA3(fromHex("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); + BOOST_REQUIRE_EQUAL(emptySHA3, EmptySHA3); +} + BOOST_AUTO_TEST_CASE(genesis_tests) { string testPath = test::getTestPath(); From ea8d11378c29003745b240bf2f4598a3885228a1 Mon Sep 17 00:00:00 2001 From: ethdev Date: Tue, 9 Dec 2014 17:05:12 +0100 Subject: [PATCH 456/641] small windows fix --- cmake/EthDependencies.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 600d9b72e..7c0fe048c 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -87,7 +87,7 @@ find_package (Qt5Widgets REQUIRED) find_package (Qt5WebKit REQUIRED) find_package (Qt5WebKitWidgets REQUIRED) -if (${CMAKE_CXX_COMPILER_ID} MATCHES "MSVC") +if (WIN32) # TODO hanlde other msvc versions or it will fail find them set(Boost_COMPILER -vc120) set(Boost_USE_STATIC_LIBS ON) From 7418077b4c7577b4462696a9d6f3bd922ec93e51 Mon Sep 17 00:00:00 2001 From: subtly Date: Tue, 9 Dec 2014 18:52:04 +0100 Subject: [PATCH 457/641] fix for windows compliation (circular dependency between statics initialized dynamically and dynamically initialized statics) --- libdevcrypto/SHA3.cpp | 2 +- test/crypto.cpp | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/libdevcrypto/SHA3.cpp b/libdevcrypto/SHA3.cpp index 1fc9be950..b7a47b745 100644 --- a/libdevcrypto/SHA3.cpp +++ b/libdevcrypto/SHA3.cpp @@ -30,7 +30,7 @@ namespace dev { h256 EmptySHA3 = sha3(bytesConstRef()); -h256 EmptyListSHA3 = sha3(RLPEmptyList); +h256 EmptyListSHA3 = sha3(rlpList()); std::string sha3(std::string const& _input, bool _hex) { diff --git a/test/crypto.cpp b/test/crypto.cpp index 466015ad7..291893f59 100644 --- a/test/crypto.cpp +++ b/test/crypto.cpp @@ -44,6 +44,15 @@ static CryptoPP::OID s_curveOID(CryptoPP::ASN1::secp256k1()); static CryptoPP::DL_GroupParameters_EC s_params(s_curveOID); static CryptoPP::DL_GroupParameters_EC::EllipticCurve s_curve(s_params.GetCurve()); +BOOST_AUTO_TEST_CASE(emptySHA3Types) +{ + h256 emptyListSHA3(fromHex("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")); + BOOST_REQUIRE_EQUAL(emptyListSHA3, EmptyListSHA3); + + h256 emptySHA3(fromHex("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); + BOOST_REQUIRE_EQUAL(emptySHA3, EmptySHA3); +} + BOOST_AUTO_TEST_CASE(cryptopp_patch) { KeyPair k = KeyPair::create(); From 391512d0a25a68ba2cf56deac5f8e826b8ff5d33 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Tue, 9 Dec 2014 19:48:03 +0100 Subject: [PATCH 458/641] fixed compiler settings on windows, added few comments --- cmake/EthCompilerSettings.cmake | 16 +++++++++------- cmake/EthDependencies.cmake | 23 +++++++++++++++++------ 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index d821067a8..677467bea 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -4,7 +4,12 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wno-unknown-pragmas -Wextra -DSHAREDLIB -fPIC") + set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DETH_DEBUG") + set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG -DETH_RELEASE") + set(CMAKE_CXX_FLAGS_RELEASE "-O4 -DNDEBUG -DETH_RELEASE") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -DETH_DEBUG") set(ETH_SHARED 1) + execute_process( COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION) if (NOT (GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7)) @@ -14,6 +19,10 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wno-unknown-pragmas -Wextra -DSHAREDLIB -fPIC") + set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DETH_DEBUG") + set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG -DETH_RELEASE") + set(CMAKE_CXX_FLAGS_RELEASE "-O4 -DNDEBUG -DETH_RELEASE") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -DETH_DEBUG") set(ETH_SHARED 1) elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") @@ -28,10 +37,3 @@ else () message(FATAL_ERROR "Your C++ compiler does not support C++11. You have ${CMAKE_CXX_COMPILER_ID}") endif () -# Initialize CXXFLAGS -# CMAKE_CXX_FLAGS was set before -set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DETH_DEBUG") -set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG -DETH_RELEASE") -set(CMAKE_CXX_FLAGS_RELEASE "-O4 -DNDEBUG -DETH_RELEASE") -set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -DETH_DEBUG") - diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 7c0fe048c..f55a93d38 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -77,6 +77,8 @@ find_package (CURL) message(" - curl header: ${CURL_INCLUDE_DIR}") message(" - curl lib : ${CURL_LIBRARY}") +# find all of the Qt packages +# remember to use 'Qt' instead of 'QT', cause unix is case sensitive # TODO make headless client optional find_package (Qt5Core REQUIRED) find_package (Qt5Gui REQUIRED) @@ -87,17 +89,26 @@ find_package (Qt5Widgets REQUIRED) find_package (Qt5WebKit REQUIRED) find_package (Qt5WebKitWidgets REQUIRED) -if (WIN32) +# use multithreaded boost libraries, with -mt suffix +set(Boost_USE_MULTITHREADED ON) + +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + # TODO hanlde other msvc versions or it will fail find them set(Boost_COMPILER -vc120) + # use static boost libraries *.lib set(Boost_USE_STATIC_LIBS ON) - set(Boost_USE_MULTITHREADED ON) -elseif(APPLE) + +elseif (APPLE) + + # use static boost libraries *.a set(Boost_USE_STATIC_LIBS ON) - set(Boost_USE_MULTITHREADED ON) -elseif(UNIX) + +elseif (UNIX) + + # use dynamic boost libraries .dll set(Boost_USE_STATIC_LIBS OFF) - set(Boost_USE_MULTITHREADED ON) + endif() find_package(Boost 1.54.0 REQUIRED COMPONENTS thread date_time system regex chrono filesystem unit_test_framework) From 281a9e2b226280b212fe72c241b0cf5a9930d5a8 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 10 Dec 2014 11:39:41 +0100 Subject: [PATCH 459/641] jsonrpc option in cmakes, removed all warnings --- CMakeLists.txt | 54 ++++++++++++++----------- alethzero/CMakeLists.txt | 11 ++++-- cmake/EthDependencies.cmake | 46 ++++++++++++++-------- libdevcore/CMakeLists.txt | 7 ++++ libdevcrypto/CMakeLists.txt | 6 +++ libethcore/CMakeLists.txt | 6 +++ libethereum/CMakeLists.txt | 8 +++- libevm/CMakeLists.txt | 6 +++ libevmcore/CMakeLists.txt | 6 +++ libjsqrc/CMakeLists.txt | 5 +++ liblll/CMakeLists.txt | 6 +++ libp2p/CMakeLists.txt | 6 +++ libqethereum/CMakeLists.txt | 9 ++++- libserpent/CMakeLists.txt | 6 +++ libsolidity/CMakeLists.txt | 6 +++ libweb3jsonrpc/CMakeLists.txt | 8 +++- libwebthree/CMakeLists.txt | 8 +++- libwhisper/CMakeLists.txt | 10 ++++- mix/CMakeLists.txt | 11 ++++-- secp256k1/CMakeLists.txt | 6 +++ third/CMakeLists.txt | 74 +++++++++++++++-------------------- 21 files changed, 212 insertions(+), 93 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d070ccc1e..3aad38f71 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,7 @@ function(createDefaultCacheConfig) set(LANGUAGES OFF CACHE BOOL "Limit build to Serpent/LLL tools") set(VMTRACE OFF CACHE BOOL "VM tracing and run-time checks (useful for cross-implementation VM debugging)") set(PARANOIA OFF CACHE BOOL "Additional run-time checks") + set(JSONRPC ON CACHE BOOL "Build with jsonprc. default on") endfunction() @@ -85,7 +86,7 @@ cmake_policy(SET CMP0015 NEW) createDefaultCacheConfig() configureProject() -message("-- LANGUAGES: ${LANGUAGES}; VMTRACE: ${VMTRACE}; PARANOIA: ${PARANOIA}; HEADLESS: ${HEADLESS}") +message("-- LANGUAGES: ${LANGUAGES}; VMTRACE: ${VMTRACE}; PARANOIA: ${PARANOIA}; HEADLESS: ${HEADLESS}; JSONRPC: ${JSONRPC}") # Default TARGET_PLATFORM to "linux". @@ -107,23 +108,27 @@ include(EthDependencies) createBuildInfo() -add_subdirectory(libdevcore) -add_subdirectory(libevmcore) -add_subdirectory(liblll) -add_subdirectory(libserpent) -add_subdirectory(libsolidity) +# TODO discuss that during PR. are we still using that? + if(NOT APPLE) if(PYTHON_LS) add_subdirectory(libpyserpent) endif() endif() +add_subdirectory(libdevcore) +add_subdirectory(libevmcore) +add_subdirectory(liblll) +add_subdirectory(libserpent) +add_subdirectory(libsolidity) add_subdirectory(lllc) add_subdirectory(solc) add_subdirectory(sc) -if (JSON_RPC_CPP_FOUND) + +if (JSONRPC) add_subdirectory(libweb3jsonrpc) endif() + if (NOT LANGUAGES) add_subdirectory(secp256k1) add_subdirectory(libp2p) @@ -133,6 +138,8 @@ if (NOT LANGUAGES) add_subdirectory(libethcore) add_subdirectory(libevm) add_subdirectory(libethereum) + +# TODO is this 'TODO remove' still valid? # add_subdirectory(libethereumx) # TODO remove add_subdirectory(libwebthree) @@ -141,38 +148,39 @@ if (NOT LANGUAGES) if("x${CMAKE_BUILD_TYPE}" STREQUAL "xDebug") add_subdirectory(exp) endif () + + # TODO check msvc if(NOT ("${TARGET_PLATFORM}" STREQUAL "w64")) add_subdirectory(neth) endif () - if(QTQML) - add_definitions(-DETH_QTQML) - endif() - if(NOT HEADLESS) + # TODO discuss that during PR. are we still using that? + #if(QTQML) + #add_definitions(-DETH_QTQML) + #endif() + + if (NOT HEADLESS) + + # TODO move that somewhere else! if ("${TARGET_PLATFORM}" STREQUAL "w64") cmake_policy(SET CMP0020 NEW) endif () - if (NOT JSON_RPC_CPP_FOUND) - message(FATAL_ERROR "Alethzero requires jsonrpc.") - endif() - + add_subdirectory(libjsqrc) add_subdirectory(libqethereum) - if (NOT JSON_RPC_CPP_FOUND) - message (FATAL_ERROR "AlethZero requires json-rpc-cpp!") - else() - add_subdirectory(alethzero) - endif() + add_subdirectory(alethzero) add_subdirectory(third) add_subdirectory(mix) - if(QTQML) + + # TODO discuss that during PR. are we still using that? + #if(QTQML) #add_subdirectory(iethxi) #add_subdirectory(walleth) // resurect once we want to submit ourselves to QML. - endif() + #endif() + endif() endif() - enable_testing() add_test(NAME alltests WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/test COMMAND testeth) diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index 07500390b..47d1f73e8 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -1,4 +1,9 @@ -cmake_policy(SET CMP0015 OLD) +cmake_policy(SET CMP0015 NEW) +# this policy was introduced in cmake 3.0 +# remove if, once 3.0 will be used on unix +if (APPLE) + cmake_policy(SET CMP0043 OLD) +endif() set(CMAKE_INCLUDE_CURRENT_DIR ON) aux_source_directory(. SRC_LIST) @@ -36,7 +41,7 @@ endif () add_dependencies(${EXECUTABLE} BuildInfo.h) -qt5_use_modules(${EXECUTABLE} Core) +target_link_libraries(${EXECUTABLE} Qt5::Core) target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) target_link_libraries(${EXECUTABLE} webthree) target_link_libraries(${EXECUTABLE} qethereum) @@ -57,7 +62,7 @@ if (APPLE) # First have qt5 install plugins and frameworks # replace CMAKE_PREFIX_PATH with QT_PATH ? add_custom_command(TARGET ${EXECUTABLE} POST_BUILD - COMMAND ${CMAKE_PREFIX_PATH}/bin/macdeployqt ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app + COMMAND ${CMAKE_DEPENDENCY_INSTALL_DIR}/bin/macdeployqt ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) # This tool and next will inspect linked libraries in order to determine which dependencies are required diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index f55a93d38..4877b06d5 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -36,12 +36,17 @@ message(" - Jsoncpp lib : ${JSONCPP_LIBRARIES}") # json-rpc-cpp support is currently not mandatory # TODO make headless client optional # TODO get rid of -DETH_JSONRPC -find_package (JsonRpcCpp 0.3.2) -if (JSON_RPC_CPP_FOUND) +if (JSONRPC) + + find_package (JsonRpcCpp 0.3.2) + if (NOT JSON_RPC_CPP_FOUND) + message (FATAL_ERROR "JSONRPC 0.3.2. not found") + endif() message (" - json-rpc-cpp header: ${JSON_RPC_CPP_INCLUDE_DIRS}") message (" - json-rpc-cpp lib : ${JSON_RPC_CPP_LIBRARIES}") add_definitions(-DETH_JSONRPC) -endif() + +endif() #JSONRPC # TODO readline package does not yet check for correct version number # TODO make readline package dependent on cmake options @@ -77,36 +82,45 @@ find_package (CURL) message(" - curl header: ${CURL_INCLUDE_DIR}") message(" - curl lib : ${CURL_LIBRARY}") +# do not compile GUI +if (NOT HEADLESS) + +# we need json rpc to build alethzero + if (NOT JSON_RPC_CPP_FOUND) + message (FATAL_ERROR "JSONRPC is required for GUI client") + endif() + # find all of the Qt packages # remember to use 'Qt' instead of 'QT', cause unix is case sensitive # TODO make headless client optional -find_package (Qt5Core REQUIRED) -find_package (Qt5Gui REQUIRED) -find_package (Qt5Quick REQUIRED) -find_package (Qt5Qml REQUIRED) -find_package (Qt5Network REQUIRED) -find_package (Qt5Widgets REQUIRED) -find_package (Qt5WebKit REQUIRED) -find_package (Qt5WebKitWidgets REQUIRED) + find_package (Qt5Core REQUIRED) + find_package (Qt5Gui REQUIRED) + find_package (Qt5Quick REQUIRED) + find_package (Qt5Qml REQUIRED) + find_package (Qt5Network REQUIRED) + find_package (Qt5Widgets REQUIRED) + find_package (Qt5WebKit REQUIRED) + find_package (Qt5WebKitWidgets REQUIRED) + +endif() #HEADLESS # use multithreaded boost libraries, with -mt suffix set(Boost_USE_MULTITHREADED ON) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") - # TODO hanlde other msvc versions or it will fail find them +# TODO hanlde other msvc versions or it will fail find them set(Boost_COMPILER -vc120) - # use static boost libraries *.lib +# use static boost libraries *.lib set(Boost_USE_STATIC_LIBS ON) elseif (APPLE) - # use static boost libraries *.a +# use static boost libraries *.a set(Boost_USE_STATIC_LIBS ON) elseif (UNIX) - - # use dynamic boost libraries .dll +# use dynamic boost libraries .dll set(Boost_USE_STATIC_LIBS OFF) endif() diff --git a/libdevcore/CMakeLists.txt b/libdevcore/CMakeLists.txt index 06cbe850c..b1a21470f 100644 --- a/libdevcore/CMakeLists.txt +++ b/libdevcore/CMakeLists.txt @@ -1,4 +1,11 @@ cmake_policy(SET CMP0015 OLD) +# this policy was introduced in cmake 3.0 +# remove if, once 3.0 will be used on unix +if (APPLE) + # old policy do not use MACOSX_RPATH + cmake_policy(SET CMP0042 OLD) +endif() + set(CMAKE_AUTOMOC OFF) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") diff --git a/libdevcrypto/CMakeLists.txt b/libdevcrypto/CMakeLists.txt index d2db758af..059cae7f9 100644 --- a/libdevcrypto/CMakeLists.txt +++ b/libdevcrypto/CMakeLists.txt @@ -1,4 +1,10 @@ cmake_policy(SET CMP0015 OLD) +# this policy was introduced in cmake 3.0 +# remove if, once 3.0 will be used on unix +if (APPLE) + # old policy do not use MACOSX_RPATH + cmake_policy(SET CMP0042 OLD) +endif() set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) diff --git a/libethcore/CMakeLists.txt b/libethcore/CMakeLists.txt index 869b6092b..b2e90a622 100644 --- a/libethcore/CMakeLists.txt +++ b/libethcore/CMakeLists.txt @@ -1,4 +1,10 @@ cmake_policy(SET CMP0015 NEW) +# this policy was introduced in cmake 3.0 +# remove if, once 3.0 will be used on unix +if (APPLE) + # old policy do not use MACOSX_RPATH + cmake_policy(SET CMP0042 OLD) +endif() set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) diff --git a/libethereum/CMakeLists.txt b/libethereum/CMakeLists.txt index ac5bd7136..40c53a8a5 100644 --- a/libethereum/CMakeLists.txt +++ b/libethereum/CMakeLists.txt @@ -1,4 +1,10 @@ -cmake_policy(SET CMP0015 OLD) +cmake_policy(SET CMP0015 NEW) +# this policy was introduced in cmake 3.0 +# remove if, once 3.0 will be used on unix +if (APPLE) + # old policy do not use MACOSX_RPATH + cmake_policy(SET CMP0042 OLD) +endif() set(CMAKE_AUTOMOC OFF) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") diff --git a/libevm/CMakeLists.txt b/libevm/CMakeLists.txt index 717904912..a4a8c4f3c 100644 --- a/libevm/CMakeLists.txt +++ b/libevm/CMakeLists.txt @@ -1,4 +1,10 @@ cmake_policy(SET CMP0015 NEW) +# this policy was introduced in cmake 3.0 +# remove if, once 3.0 will be used on unix +if (APPLE) + # old policy do not use MACOSX_RPATH + cmake_policy(SET CMP0042 OLD) +endif() set(CMAKE_AUTOMOC OFF) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") diff --git a/libevmcore/CMakeLists.txt b/libevmcore/CMakeLists.txt index 0f71dcd40..737df945b 100644 --- a/libevmcore/CMakeLists.txt +++ b/libevmcore/CMakeLists.txt @@ -1,4 +1,10 @@ cmake_policy(SET CMP0015 NEW) +# this policy was introduced in cmake 3.0 +# remove if, once 3.0 will be used on unix +if (APPLE) + # old policy do not use MACOSX_RPATH + cmake_policy(SET CMP0042 OLD) +endif() set(CMAKE_AUTOMOC OFF) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") diff --git a/libjsqrc/CMakeLists.txt b/libjsqrc/CMakeLists.txt index b8beec2ff..9533ddd1a 100644 --- a/libjsqrc/CMakeLists.txt +++ b/libjsqrc/CMakeLists.txt @@ -1,4 +1,9 @@ cmake_policy(SET CMP0015 NEW) +# this policy was introduced in cmake 3.0 +# remove if, once 3.0 will be used on unix +if (APPLE) + cmake_policy(SET CMP0043 OLD) +endif() set(CMAKE_AUTOMOC OFF) qt5_add_resources(JSQRC js.qrc) diff --git a/liblll/CMakeLists.txt b/liblll/CMakeLists.txt index e2c000010..908b8caf3 100644 --- a/liblll/CMakeLists.txt +++ b/liblll/CMakeLists.txt @@ -1,4 +1,10 @@ cmake_policy(SET CMP0015 NEW) +# this policy was introduced in cmake 3.0 +# remove if, once 3.0 will be used on unix +if (APPLE) + # old policy do not use MACOSX_RPATH + cmake_policy(SET CMP0042 OLD) +endif() set(CMAKE_AUTOMOC OFF) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") diff --git a/libp2p/CMakeLists.txt b/libp2p/CMakeLists.txt index e354a1c65..5ace09dda 100644 --- a/libp2p/CMakeLists.txt +++ b/libp2p/CMakeLists.txt @@ -1,4 +1,10 @@ cmake_policy(SET CMP0015 NEW) +# this policy was introduced in cmake 3.0 +# remove if, once 3.0 will be used on unix +if (APPLE) + # old policy do not use MACOSX_RPATH + cmake_policy(SET CMP0042 OLD) +endif() set(CMAKE_AUTOMOC OFF) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") diff --git a/libqethereum/CMakeLists.txt b/libqethereum/CMakeLists.txt index 56e0ba94a..9bc8c5de8 100644 --- a/libqethereum/CMakeLists.txt +++ b/libqethereum/CMakeLists.txt @@ -1,4 +1,11 @@ -cmake_policy(SET CMP0015 OLD) +cmake_policy(SET CMP0015 NEW) +# this policy was introduced in cmake 3.0 +# remove if, once 3.0 will be used on unix +if (APPLE) + # old policy do not use MACOSX_RPATH + cmake_policy(SET CMP0042 OLD) + cmake_policy(SET CMP0043 OLD) +endif() set(CMAKE_INCLUDE_CURRENT_DIR ON) aux_source_directory(. SRC_LIST) diff --git a/libserpent/CMakeLists.txt b/libserpent/CMakeLists.txt index 365b1bc9e..4d4a25e58 100644 --- a/libserpent/CMakeLists.txt +++ b/libserpent/CMakeLists.txt @@ -1,4 +1,10 @@ cmake_policy(SET CMP0015 NEW) +# this policy was introduced in cmake 3.0 +# remove if, once 3.0 will be used on unix +if (APPLE) + # old policy do not use MACOSX_RPATH + cmake_policy(SET CMP0042 OLD) +endif() set(CMAKE_AUTOMOC OFF) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index 895b22ae0..ad93609f0 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -1,4 +1,10 @@ cmake_policy(SET CMP0015 NEW) +# this policy was introduced in cmake 3.0 +# remove if, once 3.0 will be used on unix +if (APPLE) + # old policy do not use MACOSX_RPATH + cmake_policy(SET CMP0042 OLD) +endif() set(CMAKE_AUTOMOC OFF) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") diff --git a/libweb3jsonrpc/CMakeLists.txt b/libweb3jsonrpc/CMakeLists.txt index 133471d18..5ddbc186f 100644 --- a/libweb3jsonrpc/CMakeLists.txt +++ b/libweb3jsonrpc/CMakeLists.txt @@ -1,4 +1,10 @@ -cmake_policy(SET CMP0015 OLD) +cmake_policy(SET CMP0015 NEW) +# this policy was introduced in cmake 3.0 +# remove if, once 3.0 will be used on unix +if (APPLE) + # old policy do not use MACOSX_RPATH + cmake_policy(SET CMP0042 OLD) +endif() set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) diff --git a/libwebthree/CMakeLists.txt b/libwebthree/CMakeLists.txt index 09fe7f736..661786d1a 100644 --- a/libwebthree/CMakeLists.txt +++ b/libwebthree/CMakeLists.txt @@ -1,4 +1,10 @@ -cmake_policy(SET CMP0015 OLD) +cmake_policy(SET CMP0015 NEW) +# this policy was introduced in cmake 3.0 +# remove if, once 3.0 will be used on unix +if (APPLE) + # old policy do not use MACOSX_RPATH + cmake_policy(SET CMP0042 OLD) +endif() set(CMAKE_AUTOMOC OFF) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") diff --git a/libwhisper/CMakeLists.txt b/libwhisper/CMakeLists.txt index 3ab2f6097..89650db88 100644 --- a/libwhisper/CMakeLists.txt +++ b/libwhisper/CMakeLists.txt @@ -1,4 +1,10 @@ -cmake_policy(SET CMP0015 OLD) +cmake_policy(SET CMP0015 NEW) +# this policy was introduced in cmake 3.0 +# remove if, once 3.0 will be used on unix +if (APPLE) + # old policy do not use MACOSX_RPATH + cmake_policy(SET CMP0042 OLD) +endif() set(CMAKE_AUTOMOC OFF) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") @@ -30,4 +36,4 @@ target_link_libraries(${EXECUTABLE} p2p) target_link_libraries(${EXECUTABLE} secp256k1) install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) -install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) \ No newline at end of file +install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/mix/CMakeLists.txt b/mix/CMakeLists.txt index bdb682a09..03e8b45ff 100644 --- a/mix/CMakeLists.txt +++ b/mix/CMakeLists.txt @@ -1,9 +1,14 @@ +cmake_policy(SET CMP0015 NEW) +# this policy was introduced in cmake 3.0 +# remove if, once 3.0 will be used on unix +if (APPLE) + cmake_policy(SET CMP0043 OLD) +endif() + set(CMAKE_INCLUDE_CURRENT_DIR ON) aux_source_directory(. SRC_LIST) include_directories(..) -#qt5_wrap_ui(ui_Main.h Main.ui) - qt5_add_resources(UI_RESOURCES qml.qrc) # Set name of binary and add_executable() @@ -54,7 +59,7 @@ target_link_libraries(${EXECUTEABLE} jsqrc) if (APPLE) # First have qt5 install plugins and frameworks add_custom_command(TARGET ${EXECUTEABLE} POST_BUILD - COMMAND /usr/local/opt/qt5/bin/macdeployqt -qmldir=${CMAKE_CURRENT_SOURCE_DIR}/qml ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTEABLE}.app + COMMAND ${CMAKE_DEPENDENCY_INSTALL_DIR}/bin/macdeployqt -qmldir=${CMAKE_CURRENT_SOURCE_DIR}/qml ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTEABLE}.app WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) # This tool and next will inspect linked libraries in order to determine which dependencies are required diff --git a/secp256k1/CMakeLists.txt b/secp256k1/CMakeLists.txt index 230bf76b9..beeee598f 100644 --- a/secp256k1/CMakeLists.txt +++ b/secp256k1/CMakeLists.txt @@ -1,4 +1,10 @@ cmake_policy(SET CMP0015 NEW) +# this policy was introduced in cmake 3.0 +# remove if, once 3.0 will be used on unix +if (APPLE) + # old policy do not use MACOSX_RPATH + cmake_policy(SET CMP0042 OLD) +endif() set(CMAKE_AUTOMOC OFF) set(CMAKE_ASM_COMPILER "yasm") diff --git a/third/CMakeLists.txt b/third/CMakeLists.txt index 383985318..de0581067 100644 --- a/third/CMakeLists.txt +++ b/third/CMakeLists.txt @@ -1,26 +1,21 @@ +cmake_policy(SET CMP0015 NEW) +# this policy was introduced in cmake 3.0 +# remove if, once 3.0 will be used on unix +if (APPLE) + cmake_policy(SET CMP0043 OLD) +endif() + set(CMAKE_INCLUDE_CURRENT_DIR ON) aux_source_directory(. SRC_LIST) include_directories(..) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) -if (APPLE) - # Add homebrew path for qt5 - #set(CMAKE_PREFIX_PATH /usr/local/opt/qt5) - #include_directories(/usr/local/opt/qt5/include /usr/local/include) -elseif ("${TARGET_PLATFORM}" STREQUAL "w64") - set(SRC_LIST ${SRC_LIST} ../windows/qt_plugin_import.cpp) - include_directories(/usr/x86_64-w64-mingw32/include /usr/x86_64-w64-mingw32/include/QtCore /usr/x86_64-w64-mingw32/include/QtGui /usr/x86_64-w64-mingw32/include/QtQuick /usr/x86_64-w64-mingw32/include/QtQml /usr/x86_64-w64-mingw32/include/QtNetwork /usr/x86_64-w64-mingw32/include/QtWidgets /usr/x86_64-w64-mingw32/include/QtWebKit /usr/x86_64-w64-mingw32/include/QtWebKitWidgets) -elseif (UNIX) - set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ";$ENV{QTDIR}/lib/cmake") -endif () - - qt5_wrap_ui(ui_Main.h Main.ui) # Set name of binary and add_executable() file(GLOB HEADERS "*.h") if (APPLE) - set(EXECUTEABLE Third) + set(EXECUTABLE Third) set(BIN_INSTALL_DIR ".") set(DOC_INSTALL_DIR ".") @@ -31,34 +26,45 @@ if (APPLE) set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION}") set(MACOSX_BUNDLE_COPYRIGHT "${PROJECT_COPYRIGHT_YEAR} ${PROJECT_VENDOR}") set(MACOSX_BUNDLE_GUI_IDENTIFIER "${PROJECT_DOMAIN_SECOND}.${PROJECT_DOMAIN_FIRST}") - set(MACOSX_BUNDLE_BUNDLE_NAME ${EXECUTEABLE}) + set(MACOSX_BUNDLE_BUNDLE_NAME ${EXECUTABLE}) set(MACOSX_BUNDLE_ICON_FILE third) include(BundleUtilities) - add_executable(${EXECUTEABLE} MACOSX_BUNDLE third.icns Main.ui ${SRC_LIST} ${HEADERS}) - set_target_properties(${EXECUTEABLE} PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/EthereumMacOSXBundleInfo.plist.in") - SET_SOURCE_FILES_PROPERTIES(${EXECUTEABLE} PROPERTIES MACOSX_PACKAGE_LOCATION MacOS) + add_executable(${EXECUTABLE} MACOSX_BUNDLE third.icns Main.ui ${SRC_LIST} ${HEADERS}) + set_target_properties(${EXECUTABLE} PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/EthereumMacOSXBundleInfo.plist.in") + SET_SOURCE_FILES_PROPERTIES(${EXECUTABLE} PROPERTIES MACOSX_PACKAGE_LOCATION MacOS) SET_SOURCE_FILES_PROPERTIES(${MACOSX_BUNDLE_ICON_FILE}.icns PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") else () - set(EXECUTEABLE third) - add_executable(${EXECUTEABLE} Main.ui ${SRC_LIST} ${HEADERS}) + set(EXECUTABLE third) + add_executable(${EXECUTABLE} Main.ui ${SRC_LIST} ${HEADERS}) endif () -qt5_use_modules(${EXECUTEABLE} Core)# Gui Widgets Network WebKit WebKitWidgets) -target_link_libraries(${EXECUTEABLE} webthree qethereum ethereum evm ethcore secp256k1 gmp serpent lll evmcore devcore web3jsonrpc jsqrc) +target_link_libraries(${EXECUTABLE} Qt5::Core) +target_link_libraries(${EXECUTABLE} webthree) +target_link_libraries(${EXECUTABLE} qethereum) +target_link_libraries(${EXECUTABLE} ethereum) +target_link_libraries(${EXECUTABLE} evm) +target_link_libraries(${EXECUTABLE} ethcore) +target_link_libraries(${EXECUTABLE} secp256k1) +target_link_libraries(${EXECUTABLE} serpent) +target_link_libraries(${EXECUTABLE} lll) +target_link_libraries(${EXECUTABLE} evmcore) +target_link_libraries(${EXECUTABLE} devcore) +target_link_libraries(${EXECUTABLE} web3jsonrpc) +target_link_libraries(${EXECUTABLE} jsqrc) if (APPLE) # First have qt5 install plugins and frameworks - add_custom_command(TARGET ${EXECUTEABLE} POST_BUILD - COMMAND ${CMAKE_PREFIX_PATH}/bin/macdeployqt ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTEABLE}.app + add_custom_command(TARGET ${EXECUTABLE} POST_BUILD + COMMAND ${CMAKE_DEPENDENCY_INSTALL_DIR}/bin/macdeployqt ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) # This tool and next will inspect linked libraries in order to determine which dependencies are required if (${CMAKE_CFG_INTDIR} STREQUAL ".") - set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${EXECUTEABLE}.app") + set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${EXECUTABLE}.app") else () - set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/\$ENV{CONFIGURATION}/${EXECUTEABLE}.app") + set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/\$ENV{CONFIGURATION}/${EXECUTABLE}.app") endif () install(CODE " include(BundleUtilities) @@ -72,23 +78,7 @@ if (APPLE) file(REMOVE \${LINGER_RM}) endif () ") -elseif ("${TARGET_PLATFORM}" STREQUAL "w64") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-keep-inline-dllexport -static-libgcc -static-libstdc++ -static") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-s -Wl,-subsystem,windows -mthreads -L/usr/x86_64-w64-mingw32/plugins/platforms") - target_link_libraries(${EXECUTEABLE} gcc) - target_link_libraries(${EXECUTEABLE} mingw32 qtmain mswsock iphlpapi qwindows shlwapi Qt5PlatformSupport opengl32 gdi32 comdlg32 oleaut32 imm32 winmm ole32 uuid ws2_32) - target_link_libraries(${EXECUTEABLE} boost_system-mt-s) - target_link_libraries(${EXECUTEABLE} boost_filesystem-mt-s) - target_link_libraries(${EXECUTEABLE} boost_thread_win32-mt-s) - target_link_libraries(${EXECUTEABLE} crypt32) - target_link_libraries(${EXECUTEABLE} Qt5PlatformSupport) - set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) -elseif (UNIX) else () - target_link_libraries(${EXECUTEABLE} boost_system) - target_link_libraries(${EXECUTEABLE} boost_filesystem) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTEABLE} ${CMAKE_THREAD_LIBS_INIT}) - install( TARGETS ${EXECUTEABLE} RUNTIME DESTINATION bin ) + install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin) endif () From 7c26fa0afe2d2ff1d1498ec1df4262d2b46ef888 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 10 Dec 2014 11:52:08 +0100 Subject: [PATCH 460/641] common changes in cmakes --- mix/CMakeLists.txt | 57 ++++++++++++++++++++++---------------------- neth/CMakeLists.txt | 43 +++++++++------------------------ third/CMakeLists.txt | 2 ++ 3 files changed, 42 insertions(+), 60 deletions(-) diff --git a/mix/CMakeLists.txt b/mix/CMakeLists.txt index 03e8b45ff..3980f5642 100644 --- a/mix/CMakeLists.txt +++ b/mix/CMakeLists.txt @@ -14,7 +14,7 @@ qt5_add_resources(UI_RESOURCES qml.qrc) # Set name of binary and add_executable() file(GLOB HEADERS "*.h") if (APPLE) - set(EXECUTEABLE mix) + set(EXECUTABLE mix) set(BIN_INSTALL_DIR ".") set(DOC_INSTALL_DIR ".") @@ -25,48 +25,48 @@ if (APPLE) set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION}") set(MACOSX_BUNDLE_COPYRIGHT "${PROJECT_COPYRIGHT_YEAR} ${PROJECT_VENDOR}") set(MACOSX_BUNDLE_GUI_IDENTIFIER "${PROJECT_DOMAIN_SECOND}.${PROJECT_DOMAIN_FIRST}") - set(MACOSX_BUNDLE_BUNDLE_NAME ${EXECUTEABLE}) + set(MACOSX_BUNDLE_BUNDLE_NAME ${EXECUTABLE}) set(MACOSX_BUNDLE_ICON_FILE mix) include(BundleUtilities) - add_executable(${EXECUTEABLE} MACOSX_BUNDLE ${SRC_LIST} ${HEADERS} ${UI_RESOURCES}) - set_target_properties(${EXECUTEABLE} PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/EthereumMacOSXBundleInfo.plist.in") - SET_SOURCE_FILES_PROPERTIES(${EXECUTEABLE} PROPERTIES MACOSX_PACKAGE_LOCATION MacOS) + add_executable(${EXECUTABLE} MACOSX_BUNDLE ${SRC_LIST} ${HEADERS} ${UI_RESOURCES}) + set_target_properties(${EXECUTABLE} PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/EthereumMacOSXBundleInfo.plist.in") + SET_SOURCE_FILES_PROPERTIES(${EXECUTABLE} PROPERTIES MACOSX_PACKAGE_LOCATION MacOS) SET_SOURCE_FILES_PROPERTIES(${MACOSX_BUNDLE_ICON_FILE}.icns PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") else () - set(EXECUTEABLE mix) - add_executable(${EXECUTEABLE} ${SRC_LIST} ${HEADERS} ${UI_RESOURCES}) + set(EXECUTABLE mix) + add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS} ${UI_RESOURCES}) endif () -target_link_libraries(${EXECUTEABLE} Qt5::Core) -target_link_libraries(${EXECUTEABLE} Qt5::Gui) -target_link_libraries(${EXECUTEABLE} webthree) -target_link_libraries(${EXECUTEABLE} qethereum) -target_link_libraries(${EXECUTEABLE} ethereum) -target_link_libraries(${EXECUTEABLE} evm) -target_link_libraries(${EXECUTEABLE} ethcore) -target_link_libraries(${EXECUTEABLE} devcrypto) -target_link_libraries(${EXECUTEABLE} secp256k1) -target_link_libraries(${EXECUTEABLE} serpent) -target_link_libraries(${EXECUTEABLE} lll) -target_link_libraries(${EXECUTEABLE} solidity) -target_link_libraries(${EXECUTEABLE} evmcore) -target_link_libraries(${EXECUTEABLE} devcore) -target_link_libraries(${EXECUTEABLE} web3jsonrpc) -target_link_libraries(${EXECUTEABLE} jsqrc) +target_link_libraries(${EXECUTABLE} Qt5::Core) +target_link_libraries(${EXECUTABLE} Qt5::Gui) +target_link_libraries(${EXECUTABLE} webthree) +target_link_libraries(${EXECUTABLE} qethereum) +target_link_libraries(${EXECUTABLE} ethereum) +target_link_libraries(${EXECUTABLE} evm) +target_link_libraries(${EXECUTABLE} ethcore) +target_link_libraries(${EXECUTABLE} devcrypto) +target_link_libraries(${EXECUTABLE} secp256k1) +target_link_libraries(${EXECUTABLE} serpent) +target_link_libraries(${EXECUTABLE} lll) +target_link_libraries(${EXECUTABLE} solidity) +target_link_libraries(${EXECUTABLE} evmcore) +target_link_libraries(${EXECUTABLE} devcore) +target_link_libraries(${EXECUTABLE} web3jsonrpc) +target_link_libraries(${EXECUTABLE} jsqrc) if (APPLE) # First have qt5 install plugins and frameworks - add_custom_command(TARGET ${EXECUTEABLE} POST_BUILD - COMMAND ${CMAKE_DEPENDENCY_INSTALL_DIR}/bin/macdeployqt -qmldir=${CMAKE_CURRENT_SOURCE_DIR}/qml ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTEABLE}.app + add_custom_command(TARGET ${EXECUTABLE} POST_BUILD + COMMAND ${CMAKE_DEPENDENCY_INSTALL_DIR}/bin/macdeployqt -qmldir=${CMAKE_CURRENT_SOURCE_DIR}/qml ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) # This tool and next will inspect linked libraries in order to determine which dependencies are required if (${CMAKE_CFG_INTDIR} STREQUAL ".") - set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${EXECUTEABLE}.app") + set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${EXECUTABLE}.app") else () - set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/\$ENV{CONFIGURATION}/${EXECUTEABLE}.app") + set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/\$ENV{CONFIGURATION}/${EXECUTABLE}.app") endif () install(CODE " include(BundleUtilities) @@ -81,5 +81,6 @@ if (APPLE) endif () ") else() - install( TARGETS ${EXECUTEABLE} RUNTIME DESTINATION bin) + install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin) endif () + diff --git a/neth/CMakeLists.txt b/neth/CMakeLists.txt index 4dd49874d..731f1e4fc 100644 --- a/neth/CMakeLists.txt +++ b/neth/CMakeLists.txt @@ -2,52 +2,31 @@ cmake_policy(SET CMP0015 NEW) aux_source_directory(. SRC_LIST) -include_directories(..) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) include_directories(${LEVELDB_INCLUDE_DIR}) +include_directories(..) set(EXECUTABLE neth) add_executable(${EXECUTABLE} ${SRC_LIST}) -target_link_libraries(${EXECUTABLE} webthree) -target_link_libraries(${EXECUTABLE} ethereum) -target_link_libraries(${EXECUTABLE} secp256k1) -target_link_libraries(${EXECUTABLE} gmp) +add_dependencies(${EXECUTABLE} BuildInfo.h) + +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) + if(MINIUPNPC_FOUND) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) endif() -target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) + if(JSON_RPC_CPP_FOUND) target_link_libraries(${EXECUTABLE} web3jsonrpc) endif() -if ("${TARGET_PLATFORM}" STREQUAL "w64") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") - target_link_libraries(${EXECUTABLE} gcc) - target_link_libraries(${EXECUTABLE} gdi32) - target_link_libraries(${EXECUTABLE} ws2_32) - target_link_libraries(${EXECUTABLE} mswsock) - target_link_libraries(${EXECUTABLE} shlwapi) - target_link_libraries(${EXECUTABLE} iphlpapi) - target_link_libraries(${EXECUTABLE} cryptopp) - target_link_libraries(${EXECUTABLE} ncurses) - target_link_libraries(${EXECUTABLE} form) - target_link_libraries(${EXECUTABLE} boost_system-mt-s) - target_link_libraries(${EXECUTABLE} boost_filesystem-mt-s) - target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) - set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) -elseif (UNIX) - target_link_libraries(${EXECUTABLE} ncurses) - target_link_libraries(${EXECUTABLE} form) -else () - target_link_libraries(${EXECUTABLE} boost_system) - target_link_libraries(${EXECUTABLE} boost_filesystem) - target_link_libraries(${EXECUTABLE} ncurses) - target_link_libraries(${EXECUTABLE} form) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -endif () +target_link_libraries(${EXECUTABLE} webthree) +target_link_libraries(${EXECUTABLE} ethereum) +target_link_libraries(${EXECUTABLE} secp256k1) +target_link_libraries(${EXECUTABLE} ncurses) +target_link_libraries(${EXECUTABLE} form) install( TARGETS ${EXECUTABLE} DESTINATION bin ) diff --git a/third/CMakeLists.txt b/third/CMakeLists.txt index de0581067..98efde545 100644 --- a/third/CMakeLists.txt +++ b/third/CMakeLists.txt @@ -40,6 +40,8 @@ else () add_executable(${EXECUTABLE} Main.ui ${SRC_LIST} ${HEADERS}) endif () +add_dependencies(${EXECUTABLE} BuildInfo.h) + target_link_libraries(${EXECUTABLE} Qt5::Core) target_link_libraries(${EXECUTABLE} webthree) target_link_libraries(${EXECUTABLE} qethereum) From 8098a94941743962a12497345fbf6912b06fc59a Mon Sep 17 00:00:00 2001 From: ethdev Date: Wed, 10 Dec 2014 11:53:43 +0100 Subject: [PATCH 461/641] io_service is 2 again --- libp2p/Host.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index 52ceb5df3..93a6ce672 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -42,7 +42,7 @@ Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, bool m_clientVersion(_clientVersion), m_netPrefs(_n), m_ifAddresses(Network::getInterfaceAddresses()), - m_ioService(), + m_ioService(2), m_acceptorV4(m_ioService), m_key(KeyPair::create()) { From 3fae34304125dd7206cb0033a47ce6d90c5de95a Mon Sep 17 00:00:00 2001 From: ethdev Date: Wed, 10 Dec 2014 12:31:09 +0100 Subject: [PATCH 462/641] cmake improvements on windows --- CMakeLists.txt | 3 +++ alethzero/CMakeLists.txt | 2 ++ libjsqrc/CMakeLists.txt | 4 +++- libqethereum/CMakeLists.txt | 4 +++- libqethereum/QEthereum.cpp | 8 -------- libqethereum/QmlEthereum.cpp | 8 -------- mix/CMakeLists.txt | 4 +++- third/CMakeLists.txt | 2 ++ third/MainWin.cpp | 12 ------------ 9 files changed, 16 insertions(+), 31 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3aad38f71..00f24c863 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,8 @@ # cmake global cmake_minimum_required(VERSION 2.8.9) +# let cmake autolink dependencies on windows +# it's specified globally, cause qt libraries requires that on windows and they are also found globally +cmake_policy(SET CMP0020 NEW) project(ethereum) diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index 47d1f73e8..0ea0ef8a6 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -1,4 +1,6 @@ cmake_policy(SET CMP0015 NEW) +# let cmake autolink dependencies on windows +cmake_policy(SET CMP0020 NEW) # this policy was introduced in cmake 3.0 # remove if, once 3.0 will be used on unix if (APPLE) diff --git a/libjsqrc/CMakeLists.txt b/libjsqrc/CMakeLists.txt index 9533ddd1a..58dcb76ce 100644 --- a/libjsqrc/CMakeLists.txt +++ b/libjsqrc/CMakeLists.txt @@ -1,7 +1,9 @@ cmake_policy(SET CMP0015 NEW) +# let cmake autolink dependencies on windows +cmake_policy(SET CMP0020 NEW) # this policy was introduced in cmake 3.0 # remove if, once 3.0 will be used on unix -if (APPLE) +if (${CMAKE_MAJOR_VERSION} GREATER 2) cmake_policy(SET CMP0043 OLD) endif() set(CMAKE_AUTOMOC OFF) diff --git a/libqethereum/CMakeLists.txt b/libqethereum/CMakeLists.txt index 9bc8c5de8..9585943f0 100644 --- a/libqethereum/CMakeLists.txt +++ b/libqethereum/CMakeLists.txt @@ -1,7 +1,9 @@ cmake_policy(SET CMP0015 NEW) +# let cmake autolink dependencies on windows +cmake_policy(SET CMP0020 NEW) # this policy was introduced in cmake 3.0 # remove if, once 3.0 will be used on unix -if (APPLE) +if (${CMAKE_MAJOR_VERSION} GREATER 2) # old policy do not use MACOSX_RPATH cmake_policy(SET CMP0042 OLD) cmake_policy(SET CMP0043 OLD) diff --git a/libqethereum/QEthereum.cpp b/libqethereum/QEthereum.cpp index 5e5253829..daf773a22 100644 --- a/libqethereum/QEthereum.cpp +++ b/libqethereum/QEthereum.cpp @@ -227,11 +227,3 @@ void QWebThreeConnector::onProcessData(QString const& _json, QString const& _add OnRequest(_json.toStdString(), (void*)&_addInfo); } -// extra bits needed to link on VS -#ifdef _MSC_VER - -// include moc file, ofuscated to hide from automoc -#include\ -"moc_QEthereum.cpp" - -#endif diff --git a/libqethereum/QmlEthereum.cpp b/libqethereum/QmlEthereum.cpp index b1b926f42..812247b36 100644 --- a/libqethereum/QmlEthereum.cpp +++ b/libqethereum/QmlEthereum.cpp @@ -178,11 +178,3 @@ void QmlEthereum::transact(Secret _secret, Address _dest, u256 _amount, u256 _ga #endif -// extra bits needed to link on VS -#ifdef _MSC_VER - -// include moc file, ofuscated to hide from automoc -#include\ -"moc_QmlEthereum.cpp" - -#endif diff --git a/mix/CMakeLists.txt b/mix/CMakeLists.txt index 3980f5642..ce8099ce0 100644 --- a/mix/CMakeLists.txt +++ b/mix/CMakeLists.txt @@ -1,7 +1,9 @@ cmake_policy(SET CMP0015 NEW) +# let cmake autolink dependencies on windows +cmake_policy(SET CMP0020 NEW) # this policy was introduced in cmake 3.0 # remove if, once 3.0 will be used on unix -if (APPLE) +if (${CMAKE_MAJOR_VERSION} GREATER 2) cmake_policy(SET CMP0043 OLD) endif() diff --git a/third/CMakeLists.txt b/third/CMakeLists.txt index 98efde545..5237e471e 100644 --- a/third/CMakeLists.txt +++ b/third/CMakeLists.txt @@ -1,4 +1,6 @@ cmake_policy(SET CMP0015 NEW) +# let cmake autolink dependencies on windows +cmake_policy(SET CMP0020 NEW) # this policy was introduced in cmake 3.0 # remove if, once 3.0 will be used on unix if (APPLE) diff --git a/third/MainWin.cpp b/third/MainWin.cpp index 71192d630..894f1af0f 100644 --- a/third/MainWin.cpp +++ b/third/MainWin.cpp @@ -611,15 +611,3 @@ void Main::on_mine_triggered() else ethereum()->stopMining(); } - -// extra bits needed to link on VS -#ifdef _MSC_VER - -// include moc file, ofuscated to hide from automoc -#include\ -"moc_MainWin.cpp" - -#include\ -"moc_MiningView.cpp" - -#endif From 48dfbaf3c9c3a32f9c5f2f2fee2ed948a19ee08d Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 10 Dec 2014 12:49:12 +0100 Subject: [PATCH 463/641] updated cmake policies --- libdevcore/CMakeLists.txt | 2 +- libdevcrypto/CMakeLists.txt | 2 +- libethcore/CMakeLists.txt | 2 +- libethereum/CMakeLists.txt | 2 +- libevm/CMakeLists.txt | 2 +- libevmcore/CMakeLists.txt | 2 +- liblll/CMakeLists.txt | 2 +- libp2p/CMakeLists.txt | 2 +- libserpent/CMakeLists.txt | 2 +- libsolidity/CMakeLists.txt | 2 +- libweb3jsonrpc/CMakeLists.txt | 2 +- libwebthree/CMakeLists.txt | 2 +- libwhisper/CMakeLists.txt | 2 +- secp256k1/CMakeLists.txt | 2 +- third/CMakeLists.txt | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/libdevcore/CMakeLists.txt b/libdevcore/CMakeLists.txt index b1a21470f..cb5f8eb3f 100644 --- a/libdevcore/CMakeLists.txt +++ b/libdevcore/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_policy(SET CMP0015 OLD) # this policy was introduced in cmake 3.0 # remove if, once 3.0 will be used on unix -if (APPLE) +if (${CMAKE_MAJOR_VERSION} GREATER 2) # old policy do not use MACOSX_RPATH cmake_policy(SET CMP0042 OLD) endif() diff --git a/libdevcrypto/CMakeLists.txt b/libdevcrypto/CMakeLists.txt index 059cae7f9..f5661bab1 100644 --- a/libdevcrypto/CMakeLists.txt +++ b/libdevcrypto/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_policy(SET CMP0015 OLD) # this policy was introduced in cmake 3.0 # remove if, once 3.0 will be used on unix -if (APPLE) +if (${CMAKE_MAJOR_VERSION} GREATER 2) # old policy do not use MACOSX_RPATH cmake_policy(SET CMP0042 OLD) endif() diff --git a/libethcore/CMakeLists.txt b/libethcore/CMakeLists.txt index b2e90a622..ede6eb087 100644 --- a/libethcore/CMakeLists.txt +++ b/libethcore/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_policy(SET CMP0015 NEW) # this policy was introduced in cmake 3.0 # remove if, once 3.0 will be used on unix -if (APPLE) +if (${CMAKE_MAJOR_VERSION} GREATER 2) # old policy do not use MACOSX_RPATH cmake_policy(SET CMP0042 OLD) endif() diff --git a/libethereum/CMakeLists.txt b/libethereum/CMakeLists.txt index 40c53a8a5..02cb8f96d 100644 --- a/libethereum/CMakeLists.txt +++ b/libethereum/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_policy(SET CMP0015 NEW) # this policy was introduced in cmake 3.0 # remove if, once 3.0 will be used on unix -if (APPLE) +if (${CMAKE_MAJOR_VERSION} GREATER 2) # old policy do not use MACOSX_RPATH cmake_policy(SET CMP0042 OLD) endif() diff --git a/libevm/CMakeLists.txt b/libevm/CMakeLists.txt index a4a8c4f3c..e62501f93 100644 --- a/libevm/CMakeLists.txt +++ b/libevm/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_policy(SET CMP0015 NEW) # this policy was introduced in cmake 3.0 # remove if, once 3.0 will be used on unix -if (APPLE) +if (${CMAKE_MAJOR_VERSION} GREATER 2) # old policy do not use MACOSX_RPATH cmake_policy(SET CMP0042 OLD) endif() diff --git a/libevmcore/CMakeLists.txt b/libevmcore/CMakeLists.txt index 737df945b..21dee65c2 100644 --- a/libevmcore/CMakeLists.txt +++ b/libevmcore/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_policy(SET CMP0015 NEW) # this policy was introduced in cmake 3.0 # remove if, once 3.0 will be used on unix -if (APPLE) +if (${CMAKE_MAJOR_VERSION} GREATER 2) # old policy do not use MACOSX_RPATH cmake_policy(SET CMP0042 OLD) endif() diff --git a/liblll/CMakeLists.txt b/liblll/CMakeLists.txt index 908b8caf3..28e5cb758 100644 --- a/liblll/CMakeLists.txt +++ b/liblll/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_policy(SET CMP0015 NEW) # this policy was introduced in cmake 3.0 # remove if, once 3.0 will be used on unix -if (APPLE) +if (${CMAKE_MAJOR_VERSION} GREATER 2) # old policy do not use MACOSX_RPATH cmake_policy(SET CMP0042 OLD) endif() diff --git a/libp2p/CMakeLists.txt b/libp2p/CMakeLists.txt index 5ace09dda..8c5d49da0 100644 --- a/libp2p/CMakeLists.txt +++ b/libp2p/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_policy(SET CMP0015 NEW) # this policy was introduced in cmake 3.0 # remove if, once 3.0 will be used on unix -if (APPLE) +if (${CMAKE_MAJOR_VERSION} GREATER 2) # old policy do not use MACOSX_RPATH cmake_policy(SET CMP0042 OLD) endif() diff --git a/libserpent/CMakeLists.txt b/libserpent/CMakeLists.txt index 4d4a25e58..e28aeb032 100644 --- a/libserpent/CMakeLists.txt +++ b/libserpent/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_policy(SET CMP0015 NEW) # this policy was introduced in cmake 3.0 # remove if, once 3.0 will be used on unix -if (APPLE) +if (${CMAKE_MAJOR_VERSION} GREATER 2) # old policy do not use MACOSX_RPATH cmake_policy(SET CMP0042 OLD) endif() diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index ad93609f0..44a7b9bb2 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_policy(SET CMP0015 NEW) # this policy was introduced in cmake 3.0 # remove if, once 3.0 will be used on unix -if (APPLE) +if (${CMAKE_MAJOR_VERSION} GREATER 2) # old policy do not use MACOSX_RPATH cmake_policy(SET CMP0042 OLD) endif() diff --git a/libweb3jsonrpc/CMakeLists.txt b/libweb3jsonrpc/CMakeLists.txt index 5ddbc186f..3c5d589ca 100644 --- a/libweb3jsonrpc/CMakeLists.txt +++ b/libweb3jsonrpc/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_policy(SET CMP0015 NEW) # this policy was introduced in cmake 3.0 # remove if, once 3.0 will be used on unix -if (APPLE) +if (${CMAKE_MAJOR_VERSION} GREATER 2) # old policy do not use MACOSX_RPATH cmake_policy(SET CMP0042 OLD) endif() diff --git a/libwebthree/CMakeLists.txt b/libwebthree/CMakeLists.txt index 661786d1a..20b4ee603 100644 --- a/libwebthree/CMakeLists.txt +++ b/libwebthree/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_policy(SET CMP0015 NEW) # this policy was introduced in cmake 3.0 # remove if, once 3.0 will be used on unix -if (APPLE) +if (${CMAKE_MAJOR_VERSION} GREATER 2) # old policy do not use MACOSX_RPATH cmake_policy(SET CMP0042 OLD) endif() diff --git a/libwhisper/CMakeLists.txt b/libwhisper/CMakeLists.txt index 89650db88..b0bb20b2b 100644 --- a/libwhisper/CMakeLists.txt +++ b/libwhisper/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_policy(SET CMP0015 NEW) # this policy was introduced in cmake 3.0 # remove if, once 3.0 will be used on unix -if (APPLE) +if (${CMAKE_MAJOR_VERSION} GREATER 2) # old policy do not use MACOSX_RPATH cmake_policy(SET CMP0042 OLD) endif() diff --git a/secp256k1/CMakeLists.txt b/secp256k1/CMakeLists.txt index beeee598f..cc4f1b87c 100644 --- a/secp256k1/CMakeLists.txt +++ b/secp256k1/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_policy(SET CMP0015 NEW) # this policy was introduced in cmake 3.0 # remove if, once 3.0 will be used on unix -if (APPLE) +if (${CMAKE_MAJOR_VERSION} GREATER 2) # old policy do not use MACOSX_RPATH cmake_policy(SET CMP0042 OLD) endif() diff --git a/third/CMakeLists.txt b/third/CMakeLists.txt index 5237e471e..b28210719 100644 --- a/third/CMakeLists.txt +++ b/third/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_policy(SET CMP0015 NEW) cmake_policy(SET CMP0020 NEW) # this policy was introduced in cmake 3.0 # remove if, once 3.0 will be used on unix -if (APPLE) +if (${CMAKE_MAJOR_VERSION} GREATER 2) cmake_policy(SET CMP0043 OLD) endif() From 17252cecf1fff3750341e2f3b6b33ef874449538 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 10 Dec 2014 14:16:22 +0100 Subject: [PATCH 464/641] minimum cmake version upgraded to 2.8.12 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 00f24c863..a4ed1c400 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ # cmake global -cmake_minimum_required(VERSION 2.8.9) +cmake_minimum_required(VERSION 2.8.12) # let cmake autolink dependencies on windows # it's specified globally, cause qt libraries requires that on windows and they are also found globally cmake_policy(SET CMP0020 NEW) From 0aefbb6b2defd2f46d52903a33917a302e8ea909 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 10 Dec 2014 16:56:30 +0100 Subject: [PATCH 465/641] recent changes from solc working on macos --- cmake/EthDependencies.cmake | 2 +- solc/CMakeLists.txt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 4877b06d5..8d65bc62b 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -125,7 +125,7 @@ elseif (UNIX) endif() -find_package(Boost 1.54.0 REQUIRED COMPONENTS thread date_time system regex chrono filesystem unit_test_framework) +find_package(Boost 1.54.0 REQUIRED COMPONENTS thread date_time system regex chrono filesystem unit_test_framework program_options) message(" - boost header: ${Boost_INCLUDE_DIRS}") message(" - boost lib : ${Boost_LIBRARIES}") diff --git a/solc/CMakeLists.txt b/solc/CMakeLists.txt index e7cc5a1a6..cf1e42572 100644 --- a/solc/CMakeLists.txt +++ b/solc/CMakeLists.txt @@ -11,8 +11,8 @@ set(EXECUTABLE solc) file(GLOB HEADERS "*.h") add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) -target_link_libraries(${EXECUTABLE} boost_filesystem) -target_link_libraries(${EXECUTABLE} boost_program_options) +target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARY_RELEASE}) +target_link_libraries(${EXECUTABLE} ${Boost_PROGRAM_OPTIONS_LIBRARY_RELEASE}) target_link_libraries(${EXECUTABLE} solidity) install( TARGETS ${EXECUTABLE} DESTINATION bin ) From d608ebf36b758c67d173d271ad7973c566a1b9b6 Mon Sep 17 00:00:00 2001 From: ethdev Date: Wed, 10 Dec 2014 16:58:05 +0100 Subject: [PATCH 466/641] windows boost compiling with program_options module --- extdep/compile/boost.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extdep/compile/boost.cmake b/extdep/compile/boost.cmake index c87c907b7..f38c70f02 100644 --- a/extdep/compile/boost.cmake +++ b/extdep/compile/boost.cmake @@ -5,7 +5,7 @@ set(boost_address_model) # on windows 64: # set(boost_address_model address-model=64) -set(boost_targets --with-filesystem --with-system --with-thread --with-date_time --with-regex --with-test --with-chrono) +set(boost_targets --with-filesystem --with-system --with-thread --with-date_time --with-regex --with-test --with-chrono --with-program_options) ExternalProject_Add(boost URL http://downloads.sourceforge.net/project/boost/boost/1.55.0/boost_1_55_0.tar.gz BINARY_DIR boost-prefix/src/boost From b68e671e2675fb76c9bb95947de91ae00ba67354 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 10 Dec 2014 22:08:29 +0100 Subject: [PATCH 467/641] Update evmjit submodule url --- .gitmodules | 2 +- evmjit | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index d7fb4f437..26c29d38d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "evmjit"] path = evmjit - url = ../evmjit + url = https://github.com/ethereum/evmjit branch = develop diff --git a/evmjit b/evmjit index c9f5694a2..b1b94de24 160000 --- a/evmjit +++ b/evmjit @@ -1 +1 @@ -Subproject commit c9f5694a285412f693b160cf83e6258b0c41c504 +Subproject commit b1b94de243e8dd3a36b8be42794ed70a09271cfe From 15d7d99225003456c747b4c58919bd3b979e8be0 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 11 Dec 2014 12:11:29 +0100 Subject: [PATCH 468/641] extdep minimum cmake version required set to 2.8.12 --- extdep/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index 031093f56..ea708fbe3 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 2.8.12) include(ExternalProject) include(CMakeParseArguments) From fb72a7ce5faf4399ed6dfe5f4962c214a9483aa4 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 11 Dec 2014 15:06:11 +0100 Subject: [PATCH 469/641] fixed styling issues --- CMakeLists.txt | 8 ++--- cmake/FindGmp.cmake | 6 ++-- cmake/FindJsonRpcCpp.cmake | 27 ++++++++-------- cmake/FindLevelDB.cmake | 12 +++---- cmake/FindMiniupnpc.cmake | 6 ++-- cmake/FindReadline.cmake | 6 ++-- eth/CMakeLists.txt | 10 +++--- exp/CMakeLists.txt | 4 +-- extdep/compile/argtable2.cmake | 16 ++++----- extdep/compile/boost.cmake | 4 +-- extdep/compile/cryptopp.cmake | 52 ++++++++++++++--------------- extdep/compile/curl.cmake | 43 ++++++++++++------------ extdep/compile/icu.cmake | 20 ++++++------ extdep/compile/jom.cmake | 18 +++++------ extdep/compile/json-rpc-cpp.cmake | 54 +++++++++++++++---------------- extdep/compile/jsoncpp.cmake | 23 ++++++------- extdep/compile/leveldb.cmake | 32 +++++++++--------- extdep/compile/qt.cmake | 42 ++++++++++++------------ extdep/compile/snappy.cmake | 14 ++++---- extdep/miniupnpc.cmake | 4 +-- libethereum/CMakeLists.txt | 2 +- libethereumx/CMakeLists.txt | 31 ++++-------------- libevm/CMakeLists.txt | 7 ++-- libevmcore/CMakeLists.txt | 3 +- libjsqrc/CMakeLists.txt | 2 +- liblll/CMakeLists.txt | 1 + libp2p/CMakeLists.txt | 4 ++- libpyserpent/CMakeLists.txt | 26 ++------------- libqethereum/CMakeLists.txt | 15 ++++++--- libserpent/CMakeLists.txt | 1 + libsolidity/CMakeLists.txt | 5 +-- libweb3jsonrpc/CMakeLists.txt | 2 +- libwebthree/CMakeLists.txt | 7 ++-- libwhisper/CMakeLists.txt | 7 ++-- mix/CMakeLists.txt | 2 +- neth/CMakeLists.txt | 6 ++-- secp256k1/CMakeLists.txt | 3 +- test/CMakeLists.txt | 2 +- walleth/CMakeLists.txt | 17 +--------- 39 files changed, 251 insertions(+), 293 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a4ed1c400..21c17e9ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -146,8 +146,8 @@ if (NOT LANGUAGES) # add_subdirectory(libethereumx) # TODO remove add_subdirectory(libwebthree) - add_subdirectory(test) - add_subdirectory(eth) + add_subdirectory(test) + add_subdirectory(eth) if("x${CMAKE_BUILD_TYPE}" STREQUAL "xDebug") add_subdirectory(exp) endif () @@ -170,8 +170,8 @@ if (NOT LANGUAGES) endif () add_subdirectory(libjsqrc) - add_subdirectory(libqethereum) - add_subdirectory(alethzero) + add_subdirectory(libqethereum) + add_subdirectory(alethzero) add_subdirectory(third) add_subdirectory(mix) diff --git a/cmake/FindGmp.cmake b/cmake/FindGmp.cmake index 4d7a3a04c..dc2bce813 100644 --- a/cmake/FindGmp.cmake +++ b/cmake/FindGmp.cmake @@ -18,14 +18,14 @@ find_path( find_library( GMP_LIBRARY - NAMES gmp - DOC "gmp library" + NAMES gmp + DOC "gmp library" ) # handle the QUIETLY and REQUIRED arguments and set GMP_FOUND to TRUE # if all listed variables are TRUE, hide their existence from configuration view include(FindPackageHandleStandardArgs) find_package_handle_standard_args(gmp DEFAULT_MSG - GMP_INCLUDE_DIR GMP_LIBRARY) + GMP_INCLUDE_DIR GMP_LIBRARY) mark_as_advanced (GMP_INCLUDE_DIR GMP_LIBRARY) diff --git a/cmake/FindJsonRpcCpp.cmake b/cmake/FindJsonRpcCpp.cmake index 00da29f75..221180337 100644 --- a/cmake/FindJsonRpcCpp.cmake +++ b/cmake/FindJsonRpcCpp.cmake @@ -11,34 +11,33 @@ # only look in default directories find_path( - JSON_RPC_CPP_INCLUDE_DIR - NAMES jsonrpccpp/server.h - PATH_SUFFIXES jsonrpc - DOC "json-rpc-cpp include dir" + JSON_RPC_CPP_INCLUDE_DIR + NAMES jsonrpccpp/server.h + PATH_SUFFIXES jsonrpc + DOC "json-rpc-cpp include dir" ) find_library( - JSON_RPC_CPP_COMMON_LIBRARY - NAMES jsonrpccpp-common - DOC "json-rpc-cpp common library" + JSON_RPC_CPP_COMMON_LIBRARY + NAMES jsonrpccpp-common + DOC "json-rpc-cpp common library" ) find_library( - JSON_RPC_CPP_SERVER_LIBRARY - NAMES jsonrpccpp-server - DOC "json-rpc-cpp server library" + JSON_RPC_CPP_SERVER_LIBRARY + NAMES jsonrpccpp-server + DOC "json-rpc-cpp server library" ) find_library( - JSON_RPC_CPP_CLIENT_LIBRARY - NAMES jsonrpccpp-client - DOC "json-rpc-cpp client library" + JSON_RPC_CPP_CLIENT_LIBRARY + NAMES jsonrpccpp-client + DOC "json-rpc-cpp client library" ) # message (" - json-rcp-cpp header : ${JSON_RPC_CPP_INCLUDE_DIRS}") # message (" - json-rcp-cpp lib : ${JSON_RPC_CPP_LIBRARIES}") - # handle the QUIETLY and REQUIRED arguments and set JSON_RPC_CPP_FOUND to TRUE # if all listed variables are TRUE, hide their existence from configuration view include(FindPackageHandleStandardArgs) diff --git a/cmake/FindLevelDB.cmake b/cmake/FindLevelDB.cmake index 26629d35f..3806be9ad 100644 --- a/cmake/FindLevelDB.cmake +++ b/cmake/FindLevelDB.cmake @@ -11,15 +11,15 @@ # only look in default directories find_path( - LEVELDB_INCLUDE_DIR - NAMES leveldb/db.h + LEVELDB_INCLUDE_DIR + NAMES leveldb/db.h DOC "leveldb include dir" ) find_library( - LEVELDB_LIBRARY - NAMES leveldb - DOC "leveldb library" + LEVELDB_LIBRARY + NAMES leveldb + DOC "leveldb library" ) # message (" - leveldb header : ${LEVELDB_INCLUDE_DIR}") @@ -30,6 +30,6 @@ find_library( # if all listed variables are TRUE, hide their existence from configuration view include(FindPackageHandleStandardArgs) find_package_handle_standard_args(leveldb DEFAULT_MSG - LEVELDB_INCLUDE_DIR LEVELDB_LIBRARY) + LEVELDB_INCLUDE_DIR LEVELDB_LIBRARY) mark_as_advanced (LEVELDB_INCLUDE_DIR LEVELDB_LIBRARY) diff --git a/cmake/FindMiniupnpc.cmake b/cmake/FindMiniupnpc.cmake index 90a202dce..55795d0f9 100644 --- a/cmake/FindMiniupnpc.cmake +++ b/cmake/FindMiniupnpc.cmake @@ -18,14 +18,14 @@ find_path( find_library( MINIUPNPC_LIBRARY - NAMES miniupnpc - DOC "miniupnpc library" + NAMES miniupnpc + DOC "miniupnpc library" ) # handle the QUIETLY and REQUIRED arguments and set MINIUPNPC_FOUND to TRUE # if all listed variables are TRUE, hide their existence from configuration view include(FindPackageHandleStandardArgs) find_package_handle_standard_args(miniupnpc DEFAULT_MSG - MINIUPNPC_INCLUDE_DIR MINIUPNPC_LIBRARY) + MINIUPNPC_INCLUDE_DIR MINIUPNPC_LIBRARY) mark_as_advanced (MINIUPNPC_INCLUDE_DIR MINIUPNPC_LIBRARY) diff --git a/cmake/FindReadline.cmake b/cmake/FindReadline.cmake index 16eb483ee..3db845bd0 100644 --- a/cmake/FindReadline.cmake +++ b/cmake/FindReadline.cmake @@ -18,14 +18,14 @@ find_path( find_library( READLINE_LIBRARY - NAMES readline - DOC "readline library" + NAMES readline + DOC "readline library" ) # handle the QUIETLY and REQUIRED arguments and set READLINE_FOUND to TRUE # if all listed variables are TRUE, hide their existence from configuration view include(FindPackageHandleStandardArgs) find_package_handle_standard_args(readline DEFAULT_MSG - READLINE_INCLUDE_DIR READLINE_LIBRARY) + READLINE_INCLUDE_DIR READLINE_LIBRARY) mark_as_advanced (READLINE_INCLUDE_DIR READLINE_LIBRARY) diff --git a/eth/CMakeLists.txt b/eth/CMakeLists.txt index fe5571f60..a7feb4927 100644 --- a/eth/CMakeLists.txt +++ b/eth/CMakeLists.txt @@ -17,16 +17,16 @@ add_dependencies(${EXECUTABLE} BuildInfo.h) target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARY_RELEASE}) target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARY_RELEASE}) -if(MINIUPNPC_FOUND) +if (MINIUPNPC_FOUND) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) endif() -if(JSON_RPC_CPP_FOUND) - target_link_libraries(${EXECUTABLE} web3jsonrpc) +if (READLINE_FOUND) + target_link_libraries(${EXECUTABLE} ${READLINE_LIBRARY}) endif() -if (READLINE_FOUND) -target_link_libraries(${EXECUTABLE} ${READLINE_LIBRARY}) +if (JSONRPC) + target_link_libraries(${EXECUTABLE} web3jsonrpc) endif() target_link_libraries(${EXECUTABLE} webthree) diff --git a/exp/CMakeLists.txt b/exp/CMakeLists.txt index 1cd5218e2..47db2afe7 100644 --- a/exp/CMakeLists.txt +++ b/exp/CMakeLists.txt @@ -12,8 +12,8 @@ add_executable(${EXECUTABLE} ${SRC_LIST}) target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) -if(MINIUPNPC_FOUND) -target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) +if (MINIUPNPC_FOUND) + target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) endif() target_link_libraries(${EXECUTABLE} ethereum) diff --git a/extdep/compile/argtable2.cmake b/extdep/compile/argtable2.cmake index 88063a40f..778d6a299 100644 --- a/extdep/compile/argtable2.cmake +++ b/extdep/compile/argtable2.cmake @@ -1,13 +1,13 @@ -if(APPLE) +if (APPLE) -elseif(WIN32) +elseif (WIN32) ExternalProject_Add(argtable2 - GIT_REPOSITORY https://github.com/debris/argtable.git - GIT_TAG master - BINARY_DIR argtable2-prefix/src/argtable2 - CONFIGURE_COMMAND cmake . - BUILD_COMMAND devenv argtable2.sln /build release - INSTALL_COMMAND cmd /c cp src/Release/argtable2.lib ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp src/argtable2.h ${ETH_DEPENDENCY_INSTALL_DIR}/include + GIT_REPOSITORY https://github.com/debris/argtable.git + GIT_TAG master + BINARY_DIR argtable2-prefix/src/argtable2 + CONFIGURE_COMMAND cmake . + BUILD_COMMAND devenv argtable2.sln /build release + INSTALL_COMMAND cmd /c cp src/Release/argtable2.lib ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp src/argtable2.h ${ETH_DEPENDENCY_INSTALL_DIR}/include ) else() endif() diff --git a/extdep/compile/boost.cmake b/extdep/compile/boost.cmake index f38c70f02..7449cf47b 100644 --- a/extdep/compile/boost.cmake +++ b/extdep/compile/boost.cmake @@ -1,6 +1,6 @@ -if(APPLE) +if (APPLE) -elseif(WIN32) +elseif (WIN32) set(boost_address_model) # on windows 64: # set(boost_address_model address-model=64) diff --git a/extdep/compile/cryptopp.cmake b/extdep/compile/cryptopp.cmake index 9f54244bc..a7e65d6c6 100644 --- a/extdep/compile/cryptopp.cmake +++ b/extdep/compile/cryptopp.cmake @@ -1,33 +1,33 @@ # CryptoPP does not have good cross-platform support, there exist several different other projects to make it work ... # TODO the OS X build throws a lot of warnings, but compiles fine -if(APPLE) - ExternalProject_Add(cryptopp - URL https://downloads.sourceforge.net/project/cryptopp/cryptopp/5.6.2/cryptopp562.zip - BINARY_DIR cryptopp-prefix/src/cryptopp - CONFIGURE_COMMAND "" - BUILD_COMMAND make CXX=clang++ CXXFLAGS=-DCRYPTOPP_DISABLE_ASM - INSTALL_COMMAND make install PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} - ) -elseif(WIN32) - file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/include/cryptopp) +if (APPLE) + ExternalProject_Add(cryptopp + URL https://downloads.sourceforge.net/project/cryptopp/cryptopp/5.6.2/cryptopp562.zip + BINARY_DIR cryptopp-prefix/src/cryptopp + CONFIGURE_COMMAND "" + BUILD_COMMAND make CXX=clang++ CXXFLAGS=-DCRYPTOPP_DISABLE_ASM + INSTALL_COMMAND make install PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} + ) +elseif (WIN32) + file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/include/cryptopp) - ExternalProject_Add(cryptopp - SVN_REPOSITORY http://svn.code.sf.net/p/cryptopp/code/trunk/c5 - SVN_REVISION -r "541" - BINARY_DIR cryptopp-prefix/src/cryptopp - CONFIGURE_COMMAND devenv cryptest.sln /upgrade - BUILD_COMMAND devenv cryptest.sln /build release - INSTALL_COMMAND cmd /c cp Win32/DLL_Output/Release/cryptopp.dll ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp Win32/DLL_Output/Release/cryptopp.lib ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp *.h ${ETH_DEPENDENCY_INSTALL_DIR}/include/cryptopp - ) + ExternalProject_Add(cryptopp + SVN_REPOSITORY http://svn.code.sf.net/p/cryptopp/code/trunk/c5 + SVN_REVISION -r "541" + BINARY_DIR cryptopp-prefix/src/cryptopp + CONFIGURE_COMMAND devenv cryptest.sln /upgrade + BUILD_COMMAND devenv cryptest.sln /build release + INSTALL_COMMAND cmd /c cp Win32/DLL_Output/Release/cryptopp.dll ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp Win32/DLL_Output/Release/cryptopp.lib ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp *.h ${ETH_DEPENDENCY_INSTALL_DIR}/include/cryptopp + ) # on Linux, the default Makefile does not work. else() - ExternalProject_Add(cryptopp - URL https://github.com/mmoss/cryptopp/archive/v5.6.2.zip - BINARY_DIR cryptopp-prefix/src/cryptopp - CONFIGURE_COMMAND "" - BUILD_COMMAND scons --shared --prefix=${ETH_DEPENDENCY_INSTALL_DIR} - INSTALL_COMMAND "" - ) + ExternalProject_Add(cryptopp + URL https://github.com/mmoss/cryptopp/archive/v5.6.2.zip + BINARY_DIR cryptopp-prefix/src/cryptopp + CONFIGURE_COMMAND "" + BUILD_COMMAND scons --shared --prefix=${ETH_DEPENDENCY_INSTALL_DIR} + INSTALL_COMMAND "" + ) endif() - + diff --git a/extdep/compile/curl.cmake b/extdep/compile/curl.cmake index d4963c1d5..64f253d43 100644 --- a/extdep/compile/curl.cmake +++ b/extdep/compile/curl.cmake @@ -1,30 +1,29 @@ -if(APPLE) -ExternalProject_Add(curl - URL http://curl.haxx.se/download/curl-7.38.0.tar.bz2 - BINARY_DIR curl-prefix/src/curl - CONFIGURE_COMMAND ./configure --with-darwinssl --prefix=${ETH_DEPENDENCY_INSTALL_DIR} --exec-prefix=${ETH_DEPENDENCY_INSTALL_DIR} - BUILD_COMMAND make -j 3 - INSTALL_COMMAND make install +if (APPLE) + ExternalProject_Add(curl + URL http://curl.haxx.se/download/curl-7.38.0.tar.bz2 + BINARY_DIR curl-prefix/src/curl + CONFIGURE_COMMAND ./configure --with-darwinssl --prefix=${ETH_DEPENDENCY_INSTALL_DIR} --exec-prefix=${ETH_DEPENDENCY_INSTALL_DIR} + BUILD_COMMAND make -j 3 + INSTALL_COMMAND make install ) -elseif(WIN32) -ExternalProject_Add(curl - GIT_REPOSITORY https://github.com/debris/libcurl-7.29 - GIT_TAG master - BINARY_DIR curl-prefix/src/curl - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND cmd /c cp lib/release/libcurl.lib ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp -R include/curl ${ETH_DEPENDENCY_INSTALL_DIR}/include +elseif (WIN32) + ExternalProject_Add(curl + GIT_REPOSITORY https://github.com/debris/libcurl-7.29 + GIT_TAG master + BINARY_DIR curl-prefix/src/curl + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND cmd /c cp lib/release/libcurl.lib ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp -R include/curl ${ETH_DEPENDENCY_INSTALL_DIR}/include ) else() -ExternalProject_Add(curl - URL http://curl.haxx.se/download/curl-7.38.0.tar.bz2 - BINARY_DIR curl-prefix/src/curl - CONFIGURE_COMMAND CONFIG_CMD ./configure --prefix=${ETH_DEPENDENCY_INSTALL_DIR} --exec-prefix=${ETH_DEPENDENCY_INSTALL_DIR} - BUILD_COMMAND make -j 3 - INSTALL_COMMAND make install + ExternalProject_Add(curl + URL http://curl.haxx.se/download/curl-7.38.0.tar.bz2 + BINARY_DIR curl-prefix/src/curl + CONFIGURE_COMMAND CONFIG_CMD ./configure --prefix=${ETH_DEPENDENCY_INSTALL_DIR} --exec-prefix=${ETH_DEPENDENCY_INSTALL_DIR} + BUILD_COMMAND make -j 3 + INSTALL_COMMAND make install ) endif() - diff --git a/extdep/compile/icu.cmake b/extdep/compile/icu.cmake index c0c4d46fc..ba3f3a9f0 100644 --- a/extdep/compile/icu.cmake +++ b/extdep/compile/icu.cmake @@ -1,15 +1,13 @@ -if(APPLE) +if (APPLE) -# patch for VS2013 and Windows Qt build -elseif(WIN32) -ExternalProject_Add(icu - GIT_REPOSITORY https://github.com/debris/icu-win32.git - GIT_TAG master - BINARY_DIR icu-prefix/src/icu - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - #INSTALL_COMMAND cmd /c cp lib/* ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp -R include/uni ${ETH_DEPENDENCY_INSTALL_DIR}/include && cp bin/* ${ETH_DEPENDENCY_INSTALL_DIR}/bin - INSTALL_COMMAND cmake -E copy_directory . ${ETH_DEPENDENCY_INSTALL_DIR} +elseif (WIN32) + ExternalProject_Add(icu + GIT_REPOSITORY https://github.com/debris/icu-win32.git + GIT_TAG master + BINARY_DIR icu-prefix/src/icu + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND cmake -E copy_directory . ${ETH_DEPENDENCY_INSTALL_DIR} ) else() diff --git a/extdep/compile/jom.cmake b/extdep/compile/jom.cmake index 17ae6caab..f300fb2ad 100644 --- a/extdep/compile/jom.cmake +++ b/extdep/compile/jom.cmake @@ -1,18 +1,16 @@ -if(APPLE) +if (APPLE) -elseif(WIN32) -# nmake is not working for qt on windows, do not know why -ExternalProject_Add(jom - URL http://download.qt-project.org/official_releases/jom/jom.zip - BINARY_DIR jom-prefix/src/jom - CONFIGURE_COMMAND "" - BUILD_COMMAND "" -INSTALL_COMMAND cmake -E copy jom.exe ${ETH_DEPENDENCY_INSTALL_DIR}/bin +elseif (WIN32) + ExternalProject_Add(jom + URL http://download.qt-project.org/official_releases/jom/jom.zip + BINARY_DIR jom-prefix/src/jom + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND cmake -E copy jom.exe ${ETH_DEPENDENCY_INSTALL_DIR}/bin ) else() endif() - diff --git a/extdep/compile/json-rpc-cpp.cmake b/extdep/compile/json-rpc-cpp.cmake index cb2985e58..9d56b0dac 100644 --- a/extdep/compile/json-rpc-cpp.cmake +++ b/extdep/compile/json-rpc-cpp.cmake @@ -3,37 +3,37 @@ # DO NOT CHANGE ANYTHING HERE! if(APPLE) -ExternalProject_Add(json-rpc-cpp - # DEPENDS argtable2 jsoncpp - # DEPENDS curl # re-enable later, when we build curl again - GIT_REPOSITORY https://github.com/cinemast/libjson-rpc-cpp.git - GIT_TAG v0.3.2 - BINARY_DIR json-rpc-cpp-prefix/src/json-rpc-cpp - CONFIGURE_COMMAND cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_MODULE_PATH:PATH=${CMAKE_CURRENT_SOURCE_DIR}/cmake -DETH_DEPENDENCY_INSTALL_DIR:PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST -Wno-dev . - BUILD_COMMAND make -j 3 - INSTALL_COMMAND make install && ${CMAKE_CURRENT_SOURCE_DIR}/scripts/json-rpc-cpp_osx.sh . ${ETH_DEPENDENCY_INSTALL_DIR} + ExternalProject_Add(json-rpc-cpp + # DEPENDS argtable2 jsoncpp + # DEPENDS curl # re-enable later, when we build curl again + GIT_REPOSITORY https://github.com/cinemast/libjson-rpc-cpp.git + GIT_TAG v0.3.2 + BINARY_DIR json-rpc-cpp-prefix/src/json-rpc-cpp + CONFIGURE_COMMAND cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_MODULE_PATH:PATH=${CMAKE_CURRENT_SOURCE_DIR}/cmake -DETH_DEPENDENCY_INSTALL_DIR:PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST -Wno-dev . + BUILD_COMMAND make -j 3 + INSTALL_COMMAND make install && ${CMAKE_CURRENT_SOURCE_DIR}/scripts/json-rpc-cpp_osx.sh . ${ETH_DEPENDENCY_INSTALL_DIR} ) -elseif(WIN32) -ExternalProject_Add(json-rpc-cpp - DEPENDS argtable2 jsoncpp curl - GIT_REPOSITORY https://github.com/debris/libjson-rpc-cpp.git - GIT_TAG windows - BINARY_DIR json-rpc-cpp-prefix/src/json-rpc-cpp - CONFIGURE_COMMAND cmake -DCMAKE_PREFIX_PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCURL_LIBRARIES=${ETH_DEPENDENCY_INSTALL_DIR}/lib/libcurl.lib . - BUILD_COMMAND devenv libjson-rpc-cpp.sln /build release - INSTALL_COMMAND cmd /c cp lib/Release/* ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp -R src/jsonrpccpp ${ETH_DEPENDENCY_INSTALL_DIR}/include +elseif (WIN32) + ExternalProject_Add(json-rpc-cpp + DEPENDS argtable2 jsoncpp curl + GIT_REPOSITORY https://github.com/debris/libjson-rpc-cpp.git + GIT_TAG windows + BINARY_DIR json-rpc-cpp-prefix/src/json-rpc-cpp + CONFIGURE_COMMAND cmake -DCMAKE_PREFIX_PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCURL_LIBRARIES=${ETH_DEPENDENCY_INSTALL_DIR}/lib/libcurl.lib . + BUILD_COMMAND devenv libjson-rpc-cpp.sln /build release + INSTALL_COMMAND cmd /c cp lib/Release/* ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp -R src/jsonrpccpp ${ETH_DEPENDENCY_INSTALL_DIR}/include ) else() -ExternalProject_Add(json-rpc-cpp - # DEPENDS argtable2 jsoncpp - # DEPENDS curl # re-enable later, when we build curl again - GIT_REPOSITORY https://github.com/cinemast/libjson-rpc-cpp.git - GIT_TAG v0.3.2 - BINARY_DIR json-rpc-cpp-prefix/src/json-rpc-cpp - CONFIGURE_COMMAND cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_MODULE_PATH:PATH=${CMAKE_CURRENT_SOURCE_DIR}/cmake -DETH_DEPENDENCY_INSTALL_DIR:PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST . - BUILD_COMMAND make -j 3 - INSTALL_COMMAND make install + ExternalProject_Add(json-rpc-cpp + # DEPENDS argtable2 jsoncpp + # DEPENDS curl # re-enable later, when we build curl again + GIT_REPOSITORY https://github.com/cinemast/libjson-rpc-cpp.git + GIT_TAG v0.3.2 + BINARY_DIR json-rpc-cpp-prefix/src/json-rpc-cpp + CONFIGURE_COMMAND cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_MODULE_PATH:PATH=${CMAKE_CURRENT_SOURCE_DIR}/cmake -DETH_DEPENDENCY_INSTALL_DIR:PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST . + BUILD_COMMAND make -j 3 + INSTALL_COMMAND make install ) endif() diff --git a/extdep/compile/jsoncpp.cmake b/extdep/compile/jsoncpp.cmake index b3bdef5e2..c0d6c97cd 100644 --- a/extdep/compile/jsoncpp.cmake +++ b/extdep/compile/jsoncpp.cmake @@ -1,15 +1,16 @@ -if(APPLE) +if (APPLE) -elseif(WIN32) +elseif (WIN32) + + file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/include/jsoncpp) + ExternalProject_Add(jsoncpp + GIT_REPOSITORY https://github.com/open-source-parsers/jsoncpp + GIT_TAG svn-import + BINARY_DIR jsoncpp-prefix/src/jsoncpp + CONFIGURE_COMMAND cmake . + BUILD_COMMAND devenv jsoncpp.sln /build release + INSTALL_COMMAND cmd /c cp lib/Release/jsoncpp.lib ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp -R include/json ${ETH_DEPENDENCY_INSTALL_DIR}/include/jsoncpp + ) -file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/include/jsoncpp) -ExternalProject_Add(jsoncpp - GIT_REPOSITORY https://github.com/open-source-parsers/jsoncpp - GIT_TAG svn-import - BINARY_DIR jsoncpp-prefix/src/jsoncpp - CONFIGURE_COMMAND cmake . - BUILD_COMMAND devenv jsoncpp.sln /build release - INSTALL_COMMAND cmd /c cp lib/Release/jsoncpp.lib ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp -R include/json ${ETH_DEPENDENCY_INSTALL_DIR}/include/jsoncpp -) else() endif() diff --git a/extdep/compile/leveldb.cmake b/extdep/compile/leveldb.cmake index 9774c8c57..2f5388c14 100644 --- a/extdep/compile/leveldb.cmake +++ b/extdep/compile/leveldb.cmake @@ -1,21 +1,21 @@ if (APPLE) -ExternalProject_Add(leveldb - #DEPENDS snappy - URL https://leveldb.googlecode.com/files/leveldb-1.15.0.tar.gz - BINARY_DIR leveldb-prefix/src/leveldb - #CONFIGURE_COMMAND patch < ${CMAKE_CURRENT_SOURCE_DIR}/compile/leveldb_osx.patch - CONFIGURE_COMMAND "" - BUILD_COMMAND export ETH_DEPENDENCY_INSTALL_DIR=${ETH_DEPENDENCY_INSTALL_DIR} && make -j 3 - INSTALL_COMMAND cp -rf include/leveldb ${ETH_DEPENDENCY_INSTALL_DIR}/include/ && cp libleveldb.a ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp libleveldb.dylib.1.15 ${ETH_DEPENDENCY_INSTALL_DIR}/lib/libleveldb.dylib + ExternalProject_Add(leveldb + #DEPENDS snappy + URL https://leveldb.googlecode.com/files/leveldb-1.15.0.tar.gz + BINARY_DIR leveldb-prefix/src/leveldb + #CONFIGURE_COMMAND patch < ${CMAKE_CURRENT_SOURCE_DIR}/compile/leveldb_osx.patch + CONFIGURE_COMMAND "" + BUILD_COMMAND export ETH_DEPENDENCY_INSTALL_DIR=${ETH_DEPENDENCY_INSTALL_DIR} && make -j 3 + INSTALL_COMMAND cp -rf include/leveldb ${ETH_DEPENDENCY_INSTALL_DIR}/include/ && cp libleveldb.a ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp libleveldb.dylib.1.15 ${ETH_DEPENDENCY_INSTALL_DIR}/lib/libleveldb.dylib ) -elseif(WIN32) -ExternalProject_Add(leveldb - GIT_REPOSITORY https://github.com/debris/leveldb-win32.git - GIT_TAG master - BINARY_DIR leveldb-prefix/src/leveldb - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND cmd /c cp lib/LibLevelDB.lib ${ETH_DEPENDENCY_INSTALL_DIR}/lib/leveldb.lib && cp -R include/leveldb ${ETH_DEPENDENCY_INSTALL_DIR}/include +elseif (WIN32) + ExternalProject_Add(leveldb + GIT_REPOSITORY https://github.com/debris/leveldb-win32.git + GIT_TAG master + BINARY_DIR leveldb-prefix/src/leveldb + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND cmd /c cp lib/LibLevelDB.lib ${ETH_DEPENDENCY_INSTALL_DIR}/lib/leveldb.lib && cp -R include/leveldb ${ETH_DEPENDENCY_INSTALL_DIR}/include ) else() diff --git a/extdep/compile/qt.cmake b/extdep/compile/qt.cmake index 049b3ba94..5fb8a1440 100644 --- a/extdep/compile/qt.cmake +++ b/extdep/compile/qt.cmake @@ -1,28 +1,28 @@ -if(APPLE) -ExternalProject_add(qt - URL http://qtmirror.ics.com/pub/qtproject/official_releases/qt/5.3/5.3.2/single/qt-everywhere-opensource-src-5.3.2.tar.gz - BINARY_DIR qt-prefix/src/qt - PATCH_COMMAND patch -d qtmultimedia/src/plugins/avfoundation/mediaplayer < ${CMAKE_CURRENT_SOURCE_DIR}/compile/qt_osx.patch - CONFIGURE_COMMAND ./configure -prefix ${ETH_DEPENDENCY_INSTALL_DIR} -system-zlib -qt-libpng -qt-libjpeg -confirm-license -opensource -nomake tests -release -nomake examples -no-xcb -arch x86_64 - BUILD_COMMAND make - INSTALL_COMMAND make install +if (APPLE) + ExternalProject_add(qt + URL http://qtmirror.ics.com/pub/qtproject/official_releases/qt/5.3/5.3.2/single/qt-everywhere-opensource-src-5.3.2.tar.gz + BINARY_DIR qt-prefix/src/qt + PATCH_COMMAND patch -d qtmultimedia/src/plugins/avfoundation/mediaplayer < ${CMAKE_CURRENT_SOURCE_DIR}/compile/qt_osx.patch + CONFIGURE_COMMAND ./configure -prefix ${ETH_DEPENDENCY_INSTALL_DIR} -system-zlib -qt-libpng -qt-libjpeg -confirm-license -opensource -nomake tests -release -nomake examples -no-xcb -arch x86_64 + BUILD_COMMAND make + INSTALL_COMMAND make install ) elseif(WIN32) -ExternalProject_Add(qt - DEPENDS icu jom - URL http://qtmirror.ics.com/pub/qtproject/official_releases/qt/5.3/5.3.2/single/qt-everywhere-opensource-src-5.3.2.tar.gz - BINARY_DIR qt-prefix/src/qt - UPDATE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/compile/qt_tools.bat - #PATCH_COMMAND cmake -E copy ${CMAKE_CURRENT_SOURCE_DIR}/compile/qt_configure.bat qtbase/configure.bat - CONFIGURE_COMMAND configure -prefix ${ETH_DEPENDENCY_INSTALL_DIR} -opensource -confirm-license -release -opengl desktop -platform win32-msvc2013 -icu -I ${ETH_DEPENDENCY_INSTALL_DIR}/include -L ${ETH_DEPENDENCY_INSTALL_DIR}/lib -nomake tests -nomake examples - BUILD_COMMAND nmake - INSTALL_COMMAND nmake install + ExternalProject_Add(qt + DEPENDS icu jom + URL http://qtmirror.ics.com/pub/qtproject/official_releases/qt/5.3/5.3.2/single/qt-everywhere-opensource-src-5.3.2.tar.gz + BINARY_DIR qt-prefix/src/qt + UPDATE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/compile/qt_tools.bat + #PATCH_COMMAND cmake -E copy ${CMAKE_CURRENT_SOURCE_DIR}/compile/qt_configure.bat qtbase/configure.bat + CONFIGURE_COMMAND configure -prefix ${ETH_DEPENDENCY_INSTALL_DIR} -opensource -confirm-license -release -opengl desktop -platform win32-msvc2013 -icu -I ${ETH_DEPENDENCY_INSTALL_DIR}/include -L ${ETH_DEPENDENCY_INSTALL_DIR}/lib -nomake tests -nomake examples + BUILD_COMMAND nmake + INSTALL_COMMAND nmake install ) -ExternalProject_Add_Step(qt configure_paths - COMMAND set PATH=${ETH_DEPENDENCY_INSTALL_DIR}/bin;%cd%/gnuwin32/bin;%cd%/qtbase/bin;%PATH% - DEPENDEES patch - DEPENDERS configure + ExternalProject_Add_Step(qt configure_paths + COMMAND set PATH=${ETH_DEPENDENCY_INSTALL_DIR}/bin;%cd%/gnuwin32/bin;%cd%/qtbase/bin;%PATH% + DEPENDEES patch + DEPENDERS configure ) else() diff --git a/extdep/compile/snappy.cmake b/extdep/compile/snappy.cmake index a15418304..0f7ba300e 100644 --- a/extdep/compile/snappy.cmake +++ b/extdep/compile/snappy.cmake @@ -1,10 +1,10 @@ -if(APPLE) -ExternalProject_Add(snappy - URL https://snappy.googlecode.com/files/snappy-1.1.1.tar.gz - BINARY_DIR snappy-prefix/src/snappy - CONFIGURE_COMMAND ./configure --disable-dependency-tracking --prefix=${ETH_DEPENDENCY_INSTALL_DIR} - BUILD_COMMAND "" - INSTALL_COMMAND make install +if (APPLE) + ExternalProject_Add(snappy + URL https://snappy.googlecode.com/files/snappy-1.1.1.tar.gz + BINARY_DIR snappy-prefix/src/snappy + CONFIGURE_COMMAND ./configure --disable-dependency-tracking --prefix=${ETH_DEPENDENCY_INSTALL_DIR} + BUILD_COMMAND "" + INSTALL_COMMAND make install ) elseif(WIN32) diff --git a/extdep/miniupnpc.cmake b/extdep/miniupnpc.cmake index b690ec2f2..4fbed6807 100644 --- a/extdep/miniupnpc.cmake +++ b/extdep/miniupnpc.cmake @@ -1,3 +1,4 @@ +# TODO this file is not used yet, but will be in future include(ExternalProject) ExternalProject_Add(miniupnpc @@ -6,6 +7,5 @@ ExternalProject_Add(miniupnpc CONFIGURE_COMMAND "" BUILD_COMMAND make -j 3 INSTALL_COMMAND make install INSTALLPREFIX=${ETH_DEPENDENCY_INSTALL_DIR} - ) - +) diff --git a/libethereum/CMakeLists.txt b/libethereum/CMakeLists.txt index 02cb8f96d..e1bad4426 100644 --- a/libethereum/CMakeLists.txt +++ b/libethereum/CMakeLists.txt @@ -28,7 +28,7 @@ target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARY_RELEASE}) if (MINIUPNPC_FOUND) -target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) + target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) endif() target_link_libraries(${EXECUTABLE} evm) diff --git a/libethereumx/CMakeLists.txt b/libethereumx/CMakeLists.txt index 1063f7981..4a3cdcda7 100644 --- a/libethereumx/CMakeLists.txt +++ b/libethereumx/CMakeLists.txt @@ -8,20 +8,19 @@ include_directories(..) set(EXECUTABLE ethereumx) -if(ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST}) -else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST}) -endif() - file(GLOB HEADERS "*.h") +if (ETH_STATIC) + add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) +else() + add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) +endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS}) if (MINIUPNPC_LS) -target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) + target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() target_link_libraries(${EXECUTABLE} ethereum) @@ -29,24 +28,6 @@ target_link_libraries(${EXECUTABLE} evm) target_link_libraries(${EXECUTABLE} lll) target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} secp256k1) -target_link_libraries(${EXECUTABLE} gmp) - -if (APPLE) - # Latest mavericks boost libraries only come with -mt - target_link_libraries(${EXECUTABLE} boost_system-mt) - target_link_libraries(${EXECUTABLE} boost_regex-mt) - target_link_libraries(${EXECUTABLE} boost_filesystem-mt) - target_link_libraries(${EXECUTABLE} boost_thread-mt) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -elseif (UNIX) - target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -endif () install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libevm/CMakeLists.txt b/libevm/CMakeLists.txt index e62501f93..57004ebbb 100644 --- a/libevm/CMakeLists.txt +++ b/libevm/CMakeLists.txt @@ -17,7 +17,8 @@ include_directories(${LEVELDB_INCLUDE_DIR}) set(EXECUTABLE evm) file(GLOB HEADERS "*.h") -if(ETH_STATIC) + +if (ETH_STATIC) add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) @@ -25,8 +26,8 @@ endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) -if(MINIUPNPC_FOUND) -target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) +if (MINIUPNPC_FOUND) + target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) endif() target_link_libraries(${EXECUTABLE} ethcore) diff --git a/libevmcore/CMakeLists.txt b/libevmcore/CMakeLists.txt index 21dee65c2..9727ee1c9 100644 --- a/libevmcore/CMakeLists.txt +++ b/libevmcore/CMakeLists.txt @@ -17,7 +17,8 @@ include_directories(..) set(EXECUTABLE evmcore) file(GLOB HEADERS "*.h") -if(ETH_STATIC) + +if (ETH_STATIC) add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) diff --git a/libjsqrc/CMakeLists.txt b/libjsqrc/CMakeLists.txt index 58dcb76ce..a6dbf023b 100644 --- a/libjsqrc/CMakeLists.txt +++ b/libjsqrc/CMakeLists.txt @@ -10,6 +10,6 @@ set(CMAKE_AUTOMOC OFF) qt5_add_resources(JSQRC js.qrc) add_library(jsqrc STATIC ${JSQRC}) -qt5_use_modules(jsqrc Core) +target_link_libraries(jsqrc Qt5::Core) install( TARGETS jsqrc ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) diff --git a/liblll/CMakeLists.txt b/liblll/CMakeLists.txt index 28e5cb758..fb79d5873 100644 --- a/liblll/CMakeLists.txt +++ b/liblll/CMakeLists.txt @@ -17,6 +17,7 @@ include_directories(..) set(EXECUTABLE lll) file(GLOB HEADERS "*.h") + if(ETH_STATIC) add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) else() diff --git a/libp2p/CMakeLists.txt b/libp2p/CMakeLists.txt index 8c5d49da0..f542afd0f 100644 --- a/libp2p/CMakeLists.txt +++ b/libp2p/CMakeLists.txt @@ -17,6 +17,7 @@ include_directories(${LEVELDB_INCLUDE_DIR}) set(EXECUTABLE p2p) file(GLOB HEADERS "*.h") + if(ETH_STATIC) add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) else() @@ -24,8 +25,9 @@ else() endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) + if(MINIUPNPC_FOUND) -target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) + target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) endif() target_link_libraries(${EXECUTABLE} devcrypto) diff --git a/libpyserpent/CMakeLists.txt b/libpyserpent/CMakeLists.txt index e6f32ec81..1ffa49ac0 100644 --- a/libpyserpent/CMakeLists.txt +++ b/libpyserpent/CMakeLists.txt @@ -4,11 +4,11 @@ aux_source_directory(. SRC_LIST) set(EXECUTABLE pyserpent) -# set(CMAKE_INSTALL_PREFIX ../lib) -add_library(${EXECUTABLE} SHARED ${SRC_LIST}) - file(GLOB HEADERS "*.h") +# set(CMAKE_INSTALL_PREFIX ../lib) +add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) + include_directories(..) target_link_libraries(${EXECUTABLE} serpent) @@ -17,26 +17,6 @@ target_link_libraries(${EXECUTABLE} evmcore) target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} ${PYTHON_LS}) -if("${TARGET_PLATFORM}" STREQUAL "w64") - target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) - target_link_libraries(${EXECUTABLE} iphlpapi) - target_link_libraries(${EXECUTABLE} ws2_32) - target_link_libraries(${EXECUTABLE} mswsock) - target_link_libraries(${EXECUTABLE} shlwapi) -elseif (APPLE) - # Latest mavericks boost libraries only come with -mt - target_link_libraries(${EXECUTABLE} boost_thread-mt) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -elseif (UNIX) - target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY}) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -else () - target_link_libraries(${EXECUTABLE} boost_thread) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -endif () - install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libqethereum/CMakeLists.txt b/libqethereum/CMakeLists.txt index 9585943f0..e2c8f9a05 100644 --- a/libqethereum/CMakeLists.txt +++ b/libqethereum/CMakeLists.txt @@ -12,8 +12,8 @@ endif() set(CMAKE_INCLUDE_CURRENT_DIR ON) aux_source_directory(. SRC_LIST) -include_directories(..) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) +include_directories(..) set(EXECUTABLE qethereum) @@ -25,11 +25,18 @@ else() add_library(${EXECUTABLE} SHARED ${RESOURCE_ADDED} ${SRC_LIST} ${HEADERS}) endif() -qt5_use_modules(${EXECUTABLE} Core Gui WebKit WebKitWidgets Widgets Network Quick Qml) -target_link_libraries(${EXECUTABLE} ethereum) -target_link_libraries(${EXECUTABLE} secp256k1) +target_link_libraries(${EXECUTABLE} Qt5::Core) +target_link_libraries(${EXECUTABLE} Qt5::Gui) +target_link_libraries(${EXECUTABLE} Qt5::WebKit) +target_link_libraries(${EXECUTABLE} Qt5::WebKitWidgets) +target_link_libraries(${EXECUTABLE} Qt5::Widgets) +target_link_libraries(${EXECUTABLE} Qt5::Network) +target_link_libraries(${EXECUTABLE} Qt5::Quick) +target_link_libraries(${EXECUTABLE} Qt5::Qml) target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_COMMON_LIBRARY}) target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_SERVER_LIBRARY}) +target_link_libraries(${EXECUTABLE} ethereum) +target_link_libraries(${EXECUTABLE} secp256k1) install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libserpent/CMakeLists.txt b/libserpent/CMakeLists.txt index e28aeb032..1c5b8e147 100644 --- a/libserpent/CMakeLists.txt +++ b/libserpent/CMakeLists.txt @@ -16,6 +16,7 @@ include_directories(..) set(EXECUTABLE serpent) file(GLOB HEADERS "*.h") + if(ETH_STATIC) add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) else() diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index 44a7b9bb2..0a0b62bdd 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -18,15 +18,16 @@ include_directories(..) set(EXECUTABLE solidity) file(GLOB HEADERS "*.h") -if(ETH_STATIC) + +if (ETH_STATIC) add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() +target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) target_link_libraries(${EXECUTABLE} evmcore) target_link_libraries(${EXECUTABLE} devcore) -target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libweb3jsonrpc/CMakeLists.txt b/libweb3jsonrpc/CMakeLists.txt index 3c5d589ca..74fea58b7 100644 --- a/libweb3jsonrpc/CMakeLists.txt +++ b/libweb3jsonrpc/CMakeLists.txt @@ -9,9 +9,9 @@ set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) -include_directories(..) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) include_directories(${LEVELDB_INCLUDE_DIR}) +include_directories(..) set(EXECUTABLE web3jsonrpc) diff --git a/libwebthree/CMakeLists.txt b/libwebthree/CMakeLists.txt index 20b4ee603..837ecb313 100644 --- a/libwebthree/CMakeLists.txt +++ b/libwebthree/CMakeLists.txt @@ -17,7 +17,8 @@ include_directories(..) set(EXECUTABLE webthree) file(GLOB HEADERS "*.h") -if(ETH_STATIC) + +if (ETH_STATIC) add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) @@ -25,8 +26,8 @@ endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) -if(MINIUPNPC_FOUND) -target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) +if (MINIUPNPC_FOUND) + target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) endif() target_link_libraries(${EXECUTABLE} ethereum) diff --git a/libwhisper/CMakeLists.txt b/libwhisper/CMakeLists.txt index b0bb20b2b..8beb1b988 100644 --- a/libwhisper/CMakeLists.txt +++ b/libwhisper/CMakeLists.txt @@ -17,7 +17,8 @@ include_directories(${LEVELDB_INCLUDE_DIR}) set(EXECUTABLE whisper) file(GLOB HEADERS "*.h") -if(ETH_STATIC) + +if (ETH_STATIC) add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) @@ -25,8 +26,8 @@ endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) -if(MINIUPNPC_FOUND) -target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) +if (MINIUPNPC_FOUND) + target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) endif() target_link_libraries(${EXECUTABLE} ethcore) diff --git a/mix/CMakeLists.txt b/mix/CMakeLists.txt index ce8099ce0..8f73c546b 100644 --- a/mix/CMakeLists.txt +++ b/mix/CMakeLists.txt @@ -31,7 +31,7 @@ if (APPLE) set(MACOSX_BUNDLE_ICON_FILE mix) include(BundleUtilities) - add_executable(${EXECUTABLE} MACOSX_BUNDLE ${SRC_LIST} ${HEADERS} ${UI_RESOURCES}) + add_executable(${EXECUTABLE} MACOSX_BUNDLE ${SRC_LIST} ${HEADERS} ${UI_RESOURCES}) set_target_properties(${EXECUTABLE} PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/EthereumMacOSXBundleInfo.plist.in") SET_SOURCE_FILES_PROPERTIES(${EXECUTABLE} PROPERTIES MACOSX_PACKAGE_LOCATION MacOS) SET_SOURCE_FILES_PROPERTIES(${MACOSX_BUNDLE_ICON_FILE}.icns PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") diff --git a/neth/CMakeLists.txt b/neth/CMakeLists.txt index 731f1e4fc..14d710ef2 100644 --- a/neth/CMakeLists.txt +++ b/neth/CMakeLists.txt @@ -14,12 +14,12 @@ add_dependencies(${EXECUTABLE} BuildInfo.h) target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) -if(MINIUPNPC_FOUND) +if (MINIUPNPC_FOUND) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) endif() -if(JSON_RPC_CPP_FOUND) - target_link_libraries(${EXECUTABLE} web3jsonrpc) +if (JSONRPC) + target_link_libraries(${EXECUTABLE} web3jsonrpc) endif() target_link_libraries(${EXECUTABLE} webthree) diff --git a/secp256k1/CMakeLists.txt b/secp256k1/CMakeLists.txt index cc4f1b87c..747d5e1cb 100644 --- a/secp256k1/CMakeLists.txt +++ b/secp256k1/CMakeLists.txt @@ -24,7 +24,8 @@ if (APPLE OR UNIX) else() include_directories(${Boost_INCLUDE_DIRS}) - if(ETH_STATIC) + + if (ETH_STATIC) add_library(${EXECUTABLE} STATIC ${EXECUTABLE}.c) else() add_library(${EXECUTABLE} SHARED ${EXECUTABLE}.c) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3beb36643..440334964 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -20,7 +20,7 @@ target_link_libraries(testeth webthree) target_link_libraries(testeth ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY_RELEASE}) target_link_libraries(testeth ${CURL_LIBRARY}) -if (JSON_RPC_CPP_FOUND) +if (JSONRPC) target_link_libraries(testeth web3jsonrpc) target_link_libraries(testeth ${JSON_RPC_CPP_CLIENT_LIBRARY}) endif() diff --git a/walleth/CMakeLists.txt b/walleth/CMakeLists.txt index 26e010b97..44bf5f0f9 100644 --- a/walleth/CMakeLists.txt +++ b/walleth/CMakeLists.txt @@ -85,7 +85,7 @@ if (APPLE) install(CODE " include(BundleUtilities) set(BU_CHMOD_BUNDLE_ITEMS 1) - fixup_bundle(\"${APPS}\" \"${BUNDLELIBS}\" \"../libqethereum ../libethereum ../secp256k1\") + fixup_bundle(\"${APPS}\" \"${BUNDLELIBS}\" \"../libqethereum ../libethereum ../secp256k1\") " COMPONENT RUNTIME ) if (${ADDFRAMEWORKS}) @@ -96,22 +96,7 @@ if (APPLE) ) endif () -elseif ("${TARGET_PLATFORM}" STREQUAL "w64") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-keep-inline-dllexport -static-libgcc -static-libstdc++ -static") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-s -Wl,-subsystem,windows -mthreads -L/usr/x86_64-w64-mingw32/plugins/platforms") - target_link_libraries(${EXECUTEABLE} gcc) - target_link_libraries(${EXECUTEABLE} mingw32 qtmain mswsock iphlpapi qwindows shlwapi Qt5PlatformSupport gdi32 comdlg32 oleaut32 imm32 winmm ole32 uuid ws2_32) - target_link_libraries(${EXECUTEABLE} boost_system-mt-s) - target_link_libraries(${EXECUTEABLE} boost_filesystem-mt-s) - target_link_libraries(${EXECUTEABLE} boost_thread_win32-mt-s) - target_link_libraries(${EXECUTEABLE} Qt5PlatformSupport) - set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) -elseif (UNIX) else () - target_link_libraries(${EXECUTEABLE} boost_system) - target_link_libraries(${EXECUTEABLE} boost_filesystem) - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTEABLE} ${CMAKE_THREAD_LIBS_INIT}) install( TARGETS ${EXECUTEABLE} RUNTIME DESTINATION bin ) endif () From d439e65fee953ade58bb6ebcd9ba45a095c9ec6e Mon Sep 17 00:00:00 2001 From: ethdev Date: Thu, 11 Dec 2014 17:37:10 +0100 Subject: [PATCH 470/641] copying dlls to executable directory on windows --- alethzero/CMakeLists.txt | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index 0ea0ef8a6..a8d258efc 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -85,7 +85,23 @@ if (APPLE) file(REMOVE \${LINGER_RM}) endif () ") -else () - install( TARGETS ${EXECUTEABLE} RUNTIME DESTINATION bin) +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin) + + file (GLOB DLLS ${CMAKE_DEPENDENCY_INSTALL_DIR}/bin/*.dll) + + foreach(DLL ${DLLS}) + add_custom_command(TARGET ${EXECUTABLE} POST_BUILD + COMMAND cmake -E copy ${DLL} $ + ) + endforeach() + + add_custom_command(TARGET ${EXECUTABLE} POST_BUILD + COMMAND cmake -E copy_directory + "${CMAKE_DEPENDENCY_INSTALL_DIR}/plugins/platforms" + $/platforms + ) +else() + install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin) endif () From f47ed026036c5dbb0154a3edb28ac3cc780b05ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 11 Dec 2014 18:42:51 +0100 Subject: [PATCH 471/641] Integrate VMFactory with evmjit submodule --- libevm/VMFactory.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libevm/VMFactory.cpp b/libevm/VMFactory.cpp index af37ec710..b6549ba04 100644 --- a/libevm/VMFactory.cpp +++ b/libevm/VMFactory.cpp @@ -18,6 +18,10 @@ #include "VMFactory.h" #include "VM.h" +#if ETH_EVMJIT +#include +#endif + namespace dev { namespace eth @@ -34,8 +38,12 @@ void VMFactory::setKind(VMKind _kind) std::unique_ptr VMFactory::create(u256 _gas) { - asserts(g_kind == VMKind::Interpreter && "Only interpreter supported for now"); +#if ETH_EVMJIT + return std::unique_ptr(g_kind == VMKind::JIT ? (VMFace*)new JitVM(_gas) : new VM(_gas)); +#else + asserts(g_kind == VMKind::Interpreter && "JIT disabled in build configuration"); return std::unique_ptr(new VM(_gas)); +#endif } } From a749a38246400c74c3cb26803b3c78339abec9ed Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 11 Dec 2014 19:55:43 +0100 Subject: [PATCH 472/641] EthExecutableHelper.cmake --- CMakeLists.txt | 1 + ...st.in => EthereumMacOSXBundleInfo.plist.in | 0 alethzero/CMakeLists.txt | 76 ++----------- cmake/EthDependencies.cmake | 4 +- cmake/EthExecutableHelper.cmake | 103 ++++++++++++++++++ extdep/CMakeLists.txt | 1 + mix/CMakeLists.txt | 2 +- third/CMakeLists.txt | 2 +- 8 files changed, 119 insertions(+), 70 deletions(-) rename alethzero/EthereumMacOSXBundleInfo.plist.in => EthereumMacOSXBundleInfo.plist.in (100%) create mode 100644 cmake/EthExecutableHelper.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 21c17e9ea..33f1052bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -108,6 +108,7 @@ message("-- CXXFLAGS: ${CMAKE_CXX_FLAGS}") # this must be an include, as a function it would messs up with variable scope! include(EthDependencies) +include(EthExecutableHelper) createBuildInfo() diff --git a/alethzero/EthereumMacOSXBundleInfo.plist.in b/EthereumMacOSXBundleInfo.plist.in similarity index 100% rename from alethzero/EthereumMacOSXBundleInfo.plist.in rename to EthereumMacOSXBundleInfo.plist.in diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index a8d258efc..b72491984 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -3,43 +3,29 @@ cmake_policy(SET CMP0015 NEW) cmake_policy(SET CMP0020 NEW) # this policy was introduced in cmake 3.0 # remove if, once 3.0 will be used on unix -if (APPLE) +if (${CMAKE_MAJOR_VERSION} GREATER 2) cmake_policy(SET CMP0043 OLD) endif() set(CMAKE_INCLUDE_CURRENT_DIR ON) aux_source_directory(. SRC_LIST) -include_directories(..) + include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) +include_directories(..) qt5_wrap_ui(ui_Main.h Main.ui) -# Set name of binary and add_executable() file(GLOB HEADERS "*.h") + if (APPLE) set(EXECUTABLE AlethZero) - set(BIN_INSTALL_DIR ".") - set(DOC_INSTALL_DIR ".") - - set(PROJECT_VERSION "${ETH_VERSION}") - set(MACOSX_BUNDLE_INFO_STRING "${PROJECT_NAME} ${PROJECT_VERSION}") - set(MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_NAME} ${PROJECT_VERSION}") - set(MACOSX_BUNDLE_LONG_VERSION_STRING "${PROJECT_NAME} ${PROJECT_VERSION}") - set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION}") - set(MACOSX_BUNDLE_COPYRIGHT "${PROJECT_COPYRIGHT_YEAR} ${PROJECT_VENDOR}") - set(MACOSX_BUNDLE_GUI_IDENTIFIER "${PROJECT_DOMAIN_SECOND}.${PROJECT_DOMAIN_FIRST}") - set(MACOSX_BUNDLE_BUNDLE_NAME ${EXECUTABLE}) - set(MACOSX_BUNDLE_ICON_FILE alethzero) - include(BundleUtilities) - - add_executable(${EXECUTABLE} MACOSX_BUNDLE alethzero.icns Main.ui ${SRC_LIST} ${HEADERS}) - set_target_properties(${EXECUTABLE} PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/EthereumMacOSXBundleInfo.plist.in") - SET_SOURCE_FILES_PROPERTIES(${EXECUTABLE} PROPERTIES MACOSX_PACKAGE_LOCATION MacOS) - SET_SOURCE_FILES_PROPERTIES(${MACOSX_BUNDLE_ICON_FILE}.icns PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") else () set(EXECUTABLE alethzero) - add_executable(${EXECUTABLE} Main.ui ${SRC_LIST} ${HEADERS}) endif () + +# eth_add_executable is defined in cmake/EthExecutableHelper.cmake +# including SRC_LIST && HEADERS is implicit +eth_add_executable(${EXECUTABLE} ICON alethzero) add_dependencies(${EXECUTABLE} BuildInfo.h) @@ -60,48 +46,6 @@ target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} web3jsonrpc) target_link_libraries(${EXECUTABLE} jsqrc) -if (APPLE) - # First have qt5 install plugins and frameworks - # replace CMAKE_PREFIX_PATH with QT_PATH ? - add_custom_command(TARGET ${EXECUTABLE} POST_BUILD - COMMAND ${CMAKE_DEPENDENCY_INSTALL_DIR}/bin/macdeployqt ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app - WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - - # This tool and next will inspect linked libraries in order to determine which dependencies are required - if (${CMAKE_CFG_INTDIR} STREQUAL ".") - set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${EXECUTABLE}.app") - else () - set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/\$ENV{CONFIGURATION}/${EXECUTABLE}.app") - endif () - install(CODE " - include(BundleUtilities) - set(BU_CHMOD_BUNDLE_ITEMS 1) - fixup_bundle(\"${APP_BUNDLE_PATH}\" \"${BUNDLELIBS}\" \"../libqethereum ../libethereum ../secp256k1\") - " COMPONENT RUNTIME ) - # Cleanup duplicate libs from macdeployqt - install(CODE " - file(GLOB LINGER_RM \"${APP_BUNDLE_PATH}/Contents/Frameworks/*.dylib\") - if (LINGER_RM) - file(REMOVE \${LINGER_RM}) - endif () - ") -elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") - install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin) - - file (GLOB DLLS ${CMAKE_DEPENDENCY_INSTALL_DIR}/bin/*.dll) - - foreach(DLL ${DLLS}) - add_custom_command(TARGET ${EXECUTABLE} POST_BUILD - COMMAND cmake -E copy ${DLL} $ - ) - endforeach() - - add_custom_command(TARGET ${EXECUTABLE} POST_BUILD - COMMAND cmake -E copy_directory - "${CMAKE_DEPENDENCY_INSTALL_DIR}/plugins/platforms" - $/platforms - ) -else() - install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin) -endif () +# eth_install_executable is defined in cmake/EthExecutableHelper.cmake +eth_install_executable(${EXECUTABLE}) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 8d65bc62b..31f9420ad 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -4,8 +4,8 @@ # by defining this variable, cmake will look for dependencies first in our own repository before looking in system paths like /usr/local/ ... # this must be set to point to the same directory as $ETH_DEPENDENCY_INSTALL_DIR in /extdep directory string(TOLOWER ${CMAKE_SYSTEM_NAME} _system_name) -set (CMAKE_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/extdep/install/${_system_name}") -set (CMAKE_PREFIX_PATH ${CMAKE_DEPENDENCY_INSTALL_DIR}) +set (ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/extdep/install/${_system_name}") +set (CMAKE_PREFIX_PATH ${ETH_DEPENDENCY_INSTALL_DIR}) # Qt5 requires opengl # TODO use proper version of windows SDK (32 vs 64) diff --git a/cmake/EthExecutableHelper.cmake b/cmake/EthExecutableHelper.cmake new file mode 100644 index 000000000..a3196389f --- /dev/null +++ b/cmake/EthExecutableHelper.cmake @@ -0,0 +1,103 @@ +# +# this function requires the following variables to be specified: +# ETH_VERSION +# PROJECT_NAME +# PROJECT_VERSION +# PROJECT_COPYRIGHT_YEAR +# PROJECT_VENDOR +# PROJECT_DOMAIN_SECOND +# PROJECT_DOMAIN_FIRST +# SRC_LIST +# HEADERS +# +# params: +# ICON +# + +macro(eth_add_executable EXECUTABLE) + set (extra_macro_args ${ARGN}) + set (options) + set (one_value_args ICON) + set (multi_value_args) + cmake_parse_arguments (ETH_ADD_EXECUTABLE "${options}" "${one_value_args}" "${multi_value_args}" "${extra_macro_args}") + + if (APPLE) + + add_executable(${EXECUTABLE} MACOSX_BUNDLE alethzero.icns Main.ui ${SRC_LIST} ${HEADERS}) + set(PROJECT_VERSION "${ETH_VERSION}") + set(MACOSX_BUNDLE_INFO_STRING "${PROJECT_NAME} ${PROJECT_VERSION}") + set(MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_NAME} ${PROJECT_VERSION}") + set(MACOSX_BUNDLE_LONG_VERSION_STRING "${PROJECT_NAME} ${PROJECT_VERSION}") + set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION}") + set(MACOSX_BUNDLE_COPYRIGHT "${PROJECT_COPYRIGHT_YEAR} ${PROJECT_VENDOR}") + set(MACOSX_BUNDLE_GUI_IDENTIFIER "${PROJECT_DOMAIN_SECOND}.${PROJECT_DOMAIN_FIRST}") + set(MACOSX_BUNDLE_BUNDLE_NAME ${EXECUTABLE}) + set(MACOSX_BUNDLE_ICON_FILE ${ETH_ADD_EXECUTABLE_ICON}) + set_target_properties(${EXECUTABLE} PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_SOURCE_DIR}/EthereumMacOSXBundleInfo.plist.in") + set_source_files_properties(${EXECUTABLE} PROPERTIES MACOSX_PACKAGE_LOCATION MacOS) + set_source_files_properties(${MACOSX_BUNDLE_ICON_FILE}.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources) + + else () + add_executable(${EXECUTABLE} Main.ui ${SRC_LIST} ${HEADERS}) + endif() + +endmacro() + +# +# this function requires the following variables to be specified: +# ETH_DEPENDENCY_INSTALL_DIR +# + +macro(eth_install_executable EXECUTABLE) + + if (APPLE) + # First have qt5 install plugins and frameworks + add_custom_command(TARGET ${EXECUTABLE} POST_BUILD + COMMAND ${ETH_DEPENDENCY_INSTALL_DIR}/bin/macdeployqt ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app + WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + + # This tool and next will inspect linked libraries in order to determine which dependencies are required + if (${CMAKE_CFG_INTDIR} STREQUAL ".") + set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${EXECUTABLE}.app") + else () + set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/\$ENV{CONFIGURATION}/${EXECUTABLE}.app") + endif () + + # TODO check, how fixup_bundle works and if it is required + install(CODE " + include(BundleUtilities) + set(BU_CHMOD_BUNDLE_ITEMS 1) + fixup_bundle(\"${APP_BUNDLE_PATH}\" \"${BUNDLELIBS}\" \"../libqethereum ../libethereum ../secp256k1\") + " COMPONENT RUNTIME ) + # Cleanup duplicate libs from macdeployqt + install(CODE " + file(GLOB LINGER_RM \"${APP_BUNDLE_PATH}/Contents/Frameworks/*.dylib\") + if (LINGER_RM) + file(REMOVE \${LINGER_RM}) + endif () + ") + elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + + # copy all dlls to executable directory + file (GLOB DLLS ${CMAKE_DEPENDENCY_INSTALL_DIR}/bin/*.dll) + + foreach(DLL ${DLLS}) + add_custom_command(TARGET ${EXECUTABLE} POST_BUILD + COMMAND cmake -E copy ${DLL} $ + ) + endforeach() + + add_custom_command(TARGET ${EXECUTABLE} POST_BUILD + COMMAND cmake -E copy_directory + "${ETH_DEPENDENCY_INSTALL_DIR}/plugins/platforms" + $/platforms + ) + + install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin) + else() + install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin) + endif () + +endmacro() + + diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index ea708fbe3..bfba8e962 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -40,6 +40,7 @@ else() if (APPLE) eth_download(snappy OSX_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/scripts/snappy_osx.sh) endif() + eth_download(leveldb OSX_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/scripts/leveldb_osx.sh) eth_download(qt) eth_download(cryptopp) diff --git a/mix/CMakeLists.txt b/mix/CMakeLists.txt index 8f73c546b..e36bf3812 100644 --- a/mix/CMakeLists.txt +++ b/mix/CMakeLists.txt @@ -61,7 +61,7 @@ target_link_libraries(${EXECUTABLE} jsqrc) if (APPLE) # First have qt5 install plugins and frameworks add_custom_command(TARGET ${EXECUTABLE} POST_BUILD - COMMAND ${CMAKE_DEPENDENCY_INSTALL_DIR}/bin/macdeployqt -qmldir=${CMAKE_CURRENT_SOURCE_DIR}/qml ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app + COMMAND ${ETH_DEPENDENCY_INSTALL_DIR}/bin/macdeployqt -qmldir=${CMAKE_CURRENT_SOURCE_DIR}/qml ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) # This tool and next will inspect linked libraries in order to determine which dependencies are required diff --git a/third/CMakeLists.txt b/third/CMakeLists.txt index b28210719..9c8a9e4f0 100644 --- a/third/CMakeLists.txt +++ b/third/CMakeLists.txt @@ -61,7 +61,7 @@ target_link_libraries(${EXECUTABLE} jsqrc) if (APPLE) # First have qt5 install plugins and frameworks add_custom_command(TARGET ${EXECUTABLE} POST_BUILD - COMMAND ${CMAKE_DEPENDENCY_INSTALL_DIR}/bin/macdeployqt ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app + COMMAND ${ETH_DEPENDENCY_INSTALL_DIR}/bin/macdeployqt ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) # This tool and next will inspect linked libraries in order to determine which dependencies are required From ba242853697604299e8df2736f3e4972e756cf6e Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 11 Dec 2014 21:23:27 +0100 Subject: [PATCH 473/641] mix is using executable helper --- alethzero/CMakeLists.txt | 5 ++- cmake/EthExecutableHelper.cmake | 21 +++++++++--- mix/CMakeLists.txt | 60 +++++---------------------------- 3 files changed, 30 insertions(+), 56 deletions(-) diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index b72491984..b1efb64cf 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -25,7 +25,10 @@ endif () # eth_add_executable is defined in cmake/EthExecutableHelper.cmake # including SRC_LIST && HEADERS is implicit -eth_add_executable(${EXECUTABLE} ICON alethzero) +eth_add_executable(${EXECUTABLE} + ICON alethzero + UI_RESOURCES alethzero.icns Main.ui +) add_dependencies(${EXECUTABLE} BuildInfo.h) diff --git a/cmake/EthExecutableHelper.cmake b/cmake/EthExecutableHelper.cmake index a3196389f..d63dd930e 100644 --- a/cmake/EthExecutableHelper.cmake +++ b/cmake/EthExecutableHelper.cmake @@ -18,12 +18,12 @@ macro(eth_add_executable EXECUTABLE) set (extra_macro_args ${ARGN}) set (options) set (one_value_args ICON) - set (multi_value_args) + set (multi_value_args UI_RESOURCES) cmake_parse_arguments (ETH_ADD_EXECUTABLE "${options}" "${one_value_args}" "${multi_value_args}" "${extra_macro_args}") if (APPLE) - add_executable(${EXECUTABLE} MACOSX_BUNDLE alethzero.icns Main.ui ${SRC_LIST} ${HEADERS}) + add_executable(${EXECUTABLE} MACOSX_BUNDLE ${SRC_LIST} ${HEADERS} ${ETH_ADD_EXECUTABLE_UI_RESOURCES}) set(PROJECT_VERSION "${ETH_VERSION}") set(MACOSX_BUNDLE_INFO_STRING "${PROJECT_NAME} ${PROJECT_VERSION}") set(MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_NAME} ${PROJECT_VERSION}") @@ -38,7 +38,7 @@ macro(eth_add_executable EXECUTABLE) set_source_files_properties(${MACOSX_BUNDLE_ICON_FILE}.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources) else () - add_executable(${EXECUTABLE} Main.ui ${SRC_LIST} ${HEADERS}) + add_executable(${EXECUTABLE} ${ETH_ADD_EXECUTABLE_UI_RESOURCES} ${SRC_LIST} ${HEADERS}) endif() endmacro() @@ -47,13 +47,26 @@ endmacro() # this function requires the following variables to be specified: # ETH_DEPENDENCY_INSTALL_DIR # +# params: +# QMLDIR +# macro(eth_install_executable EXECUTABLE) + set (extra_macro_args ${ARGN}) + set (options) + set (one_value_args QMLDIR) + set (multi_value_args) + cmake_parse_arguments (ETH_INSTALL_EXECUTABLE "${options}" "${one_value_args}" "${multi_value_args}" "${extra_macro_args}") + + if (ETH_INSTALL_EXECUTABLE_QMLDIR) + set(eth_qml_dir "-qmldir=${ETH_INSTALL_EXECUTABLE_QMLDIR}") + endif() + if (APPLE) # First have qt5 install plugins and frameworks add_custom_command(TARGET ${EXECUTABLE} POST_BUILD - COMMAND ${ETH_DEPENDENCY_INSTALL_DIR}/bin/macdeployqt ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app + COMMAND ${ETH_DEPENDENCY_INSTALL_DIR}/bin/macdeployqt ${eth_qml_dir} ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) # This tool and next will inspect linked libraries in order to determine which dependencies are required diff --git a/mix/CMakeLists.txt b/mix/CMakeLists.txt index e36bf3812..9bd1ac978 100644 --- a/mix/CMakeLists.txt +++ b/mix/CMakeLists.txt @@ -8,38 +8,20 @@ if (${CMAKE_MAJOR_VERSION} GREATER 2) endif() set(CMAKE_INCLUDE_CURRENT_DIR ON) + aux_source_directory(. SRC_LIST) include_directories(..) qt5_add_resources(UI_RESOURCES qml.qrc) -# Set name of binary and add_executable() file(GLOB HEADERS "*.h") -if (APPLE) - set(EXECUTABLE mix) - set(BIN_INSTALL_DIR ".") - set(DOC_INSTALL_DIR ".") - - set(PROJECT_VERSION "${ETH_VERSION}") - set(MACOSX_BUNDLE_INFO_STRING "${PROJECT_NAME} ${PROJECT_VERSION}") - set(MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_NAME} ${PROJECT_VERSION}") - set(MACOSX_BUNDLE_LONG_VERSION_STRING "${PROJECT_NAME} ${PROJECT_VERSION}") - set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION}") - set(MACOSX_BUNDLE_COPYRIGHT "${PROJECT_COPYRIGHT_YEAR} ${PROJECT_VENDOR}") - set(MACOSX_BUNDLE_GUI_IDENTIFIER "${PROJECT_DOMAIN_SECOND}.${PROJECT_DOMAIN_FIRST}") - set(MACOSX_BUNDLE_BUNDLE_NAME ${EXECUTABLE}) - set(MACOSX_BUNDLE_ICON_FILE mix) - include(BundleUtilities) - add_executable(${EXECUTABLE} MACOSX_BUNDLE ${SRC_LIST} ${HEADERS} ${UI_RESOURCES}) - set_target_properties(${EXECUTABLE} PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/EthereumMacOSXBundleInfo.plist.in") - SET_SOURCE_FILES_PROPERTIES(${EXECUTABLE} PROPERTIES MACOSX_PACKAGE_LOCATION MacOS) - SET_SOURCE_FILES_PROPERTIES(${MACOSX_BUNDLE_ICON_FILE}.icns PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") +set(EXECUTABLE mix) -else () - set(EXECUTABLE mix) - add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS} ${UI_RESOURCES}) -endif () +eth_add_executable(${EXECUTABLE} + ICON mix + UI_RESOURCES ${UI_RESOURCES} +) target_link_libraries(${EXECUTABLE} Qt5::Core) target_link_libraries(${EXECUTABLE} Qt5::Gui) @@ -58,31 +40,7 @@ target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} web3jsonrpc) target_link_libraries(${EXECUTABLE} jsqrc) -if (APPLE) - # First have qt5 install plugins and frameworks - add_custom_command(TARGET ${EXECUTABLE} POST_BUILD - COMMAND ${ETH_DEPENDENCY_INSTALL_DIR}/bin/macdeployqt -qmldir=${CMAKE_CURRENT_SOURCE_DIR}/qml ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app - WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - - # This tool and next will inspect linked libraries in order to determine which dependencies are required - if (${CMAKE_CFG_INTDIR} STREQUAL ".") - set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${EXECUTABLE}.app") - else () - set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/\$ENV{CONFIGURATION}/${EXECUTABLE}.app") - endif () - install(CODE " - include(BundleUtilities) - set(BU_CHMOD_BUNDLE_ITEMS 1) - fixup_bundle(\"${APP_BUNDLE_PATH}\" \"${BUNDLELIBS}\" \"../libqethereum ../libethereum ../secp256k1\") - " COMPONENT RUNTIME ) - # Cleanup duplicate libs from macdeployqt - install(CODE " - file(GLOB LINGER_RM \"${APP_BUNDLE_PATH}/Contents/Frameworks/*.dylib\") - if (LINGER_RM) - file(REMOVE \${LINGER_RM}) - endif () - ") -else() - install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin) -endif () +eth_install_executable(${EXECUTABLE} + QMLDIR ${CMAKE_CURRENT_SOURCE_DIR}/qml +) From 24ff0baa0522cd18058cbd428fe9e9ab03bd92a4 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 11 Dec 2014 21:31:16 +0100 Subject: [PATCH 474/641] third is using executable helper --- alethzero/CMakeLists.txt | 1 - mix/CMakeLists.txt | 2 ++ third/CMakeLists.txt | 60 ++++++++-------------------------------- 3 files changed, 13 insertions(+), 50 deletions(-) diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index b1efb64cf..c4237eaee 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -24,7 +24,6 @@ else () endif () # eth_add_executable is defined in cmake/EthExecutableHelper.cmake -# including SRC_LIST && HEADERS is implicit eth_add_executable(${EXECUTABLE} ICON alethzero UI_RESOURCES alethzero.icns Main.ui diff --git a/mix/CMakeLists.txt b/mix/CMakeLists.txt index 9bd1ac978..555f6290f 100644 --- a/mix/CMakeLists.txt +++ b/mix/CMakeLists.txt @@ -18,6 +18,7 @@ file(GLOB HEADERS "*.h") set(EXECUTABLE mix) +# eth_add_executable is defined in cmake/EthExecutableHelper.cmake eth_add_executable(${EXECUTABLE} ICON mix UI_RESOURCES ${UI_RESOURCES} @@ -40,6 +41,7 @@ target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} web3jsonrpc) target_link_libraries(${EXECUTABLE} jsqrc) +# eth_install_executable is defined in cmake/EthExecutableHelper.cmake eth_install_executable(${EXECUTABLE} QMLDIR ${CMAKE_CURRENT_SOURCE_DIR}/qml ) diff --git a/third/CMakeLists.txt b/third/CMakeLists.txt index 9c8a9e4f0..c9c95cf33 100644 --- a/third/CMakeLists.txt +++ b/third/CMakeLists.txt @@ -9,39 +9,26 @@ endif() set(CMAKE_INCLUDE_CURRENT_DIR ON) aux_source_directory(. SRC_LIST) -include_directories(..) + include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) +include_directories(..) qt5_wrap_ui(ui_Main.h Main.ui) -# Set name of binary and add_executable() file(GLOB HEADERS "*.h") + if (APPLE) set(EXECUTABLE Third) - set(BIN_INSTALL_DIR ".") - set(DOC_INSTALL_DIR ".") - - set(PROJECT_VERSION "${ETH_VERSION}") - set(MACOSX_BUNDLE_INFO_STRING "${PROJECT_NAME} ${PROJECT_VERSION}") - set(MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_NAME} ${PROJECT_VERSION}") - set(MACOSX_BUNDLE_LONG_VERSION_STRING "${PROJECT_NAME} ${PROJECT_VERSION}") - set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION}") - set(MACOSX_BUNDLE_COPYRIGHT "${PROJECT_COPYRIGHT_YEAR} ${PROJECT_VENDOR}") - set(MACOSX_BUNDLE_GUI_IDENTIFIER "${PROJECT_DOMAIN_SECOND}.${PROJECT_DOMAIN_FIRST}") - set(MACOSX_BUNDLE_BUNDLE_NAME ${EXECUTABLE}) - set(MACOSX_BUNDLE_ICON_FILE third) - include(BundleUtilities) - - add_executable(${EXECUTABLE} MACOSX_BUNDLE third.icns Main.ui ${SRC_LIST} ${HEADERS}) - set_target_properties(${EXECUTABLE} PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/EthereumMacOSXBundleInfo.plist.in") - SET_SOURCE_FILES_PROPERTIES(${EXECUTABLE} PROPERTIES MACOSX_PACKAGE_LOCATION MacOS) - SET_SOURCE_FILES_PROPERTIES(${MACOSX_BUNDLE_ICON_FILE}.icns PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") - else () set(EXECUTABLE third) - add_executable(${EXECUTABLE} Main.ui ${SRC_LIST} ${HEADERS}) endif () +# eth_add_executable is defined in cmake/EthExecutableHelper.cmake +eth_add_executable(${EXECUTABLE} + ICON third + UI_RESOURCES third.icns Main.ui +) + add_dependencies(${EXECUTABLE} BuildInfo.h) target_link_libraries(${EXECUTABLE} Qt5::Core) @@ -58,31 +45,6 @@ target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} web3jsonrpc) target_link_libraries(${EXECUTABLE} jsqrc) -if (APPLE) - # First have qt5 install plugins and frameworks - add_custom_command(TARGET ${EXECUTABLE} POST_BUILD - COMMAND ${ETH_DEPENDENCY_INSTALL_DIR}/bin/macdeployqt ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app - WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - - # This tool and next will inspect linked libraries in order to determine which dependencies are required - if (${CMAKE_CFG_INTDIR} STREQUAL ".") - set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${EXECUTABLE}.app") - else () - set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/\$ENV{CONFIGURATION}/${EXECUTABLE}.app") - endif () - install(CODE " - include(BundleUtilities) - set(BU_CHMOD_BUNDLE_ITEMS 1) - fixup_bundle(\"${APP_BUNDLE_PATH}\" \"${BUNDLELIBS}\" \"../libqethereum ../libethereum ../secp256k1\") - " COMPONENT RUNTIME ) - # Cleanup duplicate libs from macdeployqt - install(CODE " - file(GLOB LINGER_RM \"${APP_BUNDLE_PATH}/Contents/Frameworks/*.dylib\") - if (LINGER_RM) - file(REMOVE \${LINGER_RM}) - endif () - ") -else () - install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin) -endif () +# eth_install_executable is defined in cmake/EthExecutableHelper.cmake +eth_install_executable(${EXECUTABLE}) From 24ed9d0d16a95d616fa233cc19b40f7b85c82df9 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 11 Dec 2014 21:37:22 +0100 Subject: [PATCH 475/641] removed unused plists --- mix/EthereumMacOSXBundleInfo.plist.in | 38 ------------------------- third/EthereumMacOSXBundleInfo.plist.in | 38 ------------------------- 2 files changed, 76 deletions(-) delete mode 100644 mix/EthereumMacOSXBundleInfo.plist.in delete mode 100644 third/EthereumMacOSXBundleInfo.plist.in diff --git a/mix/EthereumMacOSXBundleInfo.plist.in b/mix/EthereumMacOSXBundleInfo.plist.in deleted file mode 100644 index 684ad7908..000000000 --- a/mix/EthereumMacOSXBundleInfo.plist.in +++ /dev/null @@ -1,38 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleExecutable - ${MACOSX_BUNDLE_EXECUTABLE_NAME} - CFBundleGetInfoString - ${MACOSX_BUNDLE_INFO_STRING} - CFBundleIconFile - ${MACOSX_BUNDLE_ICON_FILE} - CFBundleIdentifier - ${MACOSX_BUNDLE_GUI_IDENTIFIER} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleLongVersionString - ${MACOSX_BUNDLE_LONG_VERSION_STRING} - CFBundleName - ${MACOSX_BUNDLE_BUNDLE_NAME} - CFBundlePackageType - APPL - CFBundleShortVersionString - ${MACOSX_BUNDLE_SHORT_VERSION_STRING} - CFBundleSignature - ???? - CFBundleVersion - ${MACOSX_BUNDLE_BUNDLE_VERSION} - CSResourcesFileMapped - - LSRequiresCarbon - - NSHumanReadableCopyright - ${MACOSX_BUNDLE_COPYRIGHT} - NSHighResolutionCapable - - - diff --git a/third/EthereumMacOSXBundleInfo.plist.in b/third/EthereumMacOSXBundleInfo.plist.in deleted file mode 100644 index 684ad7908..000000000 --- a/third/EthereumMacOSXBundleInfo.plist.in +++ /dev/null @@ -1,38 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleExecutable - ${MACOSX_BUNDLE_EXECUTABLE_NAME} - CFBundleGetInfoString - ${MACOSX_BUNDLE_INFO_STRING} - CFBundleIconFile - ${MACOSX_BUNDLE_ICON_FILE} - CFBundleIdentifier - ${MACOSX_BUNDLE_GUI_IDENTIFIER} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleLongVersionString - ${MACOSX_BUNDLE_LONG_VERSION_STRING} - CFBundleName - ${MACOSX_BUNDLE_BUNDLE_NAME} - CFBundlePackageType - APPL - CFBundleShortVersionString - ${MACOSX_BUNDLE_SHORT_VERSION_STRING} - CFBundleSignature - ???? - CFBundleVersion - ${MACOSX_BUNDLE_BUNDLE_VERSION} - CSResourcesFileMapped - - LSRequiresCarbon - - NSHumanReadableCopyright - ${MACOSX_BUNDLE_COPYRIGHT} - NSHighResolutionCapable - - - From 88393195b4d9835e7b35d0705c072a2686fef07d Mon Sep 17 00:00:00 2001 From: ethdev Date: Thu, 11 Dec 2014 22:26:20 +0100 Subject: [PATCH 476/641] fixed copying dlls on windows --- cmake/EthExecutableHelper.cmake | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cmake/EthExecutableHelper.cmake b/cmake/EthExecutableHelper.cmake index d63dd930e..6c7ea4f50 100644 --- a/cmake/EthExecutableHelper.cmake +++ b/cmake/EthExecutableHelper.cmake @@ -92,11 +92,11 @@ macro(eth_install_executable EXECUTABLE) elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") # copy all dlls to executable directory - file (GLOB DLLS ${CMAKE_DEPENDENCY_INSTALL_DIR}/bin/*.dll) + file (GLOB DLLS ${ETH_DEPENDENCY_INSTALL_DIR}/bin/*.dll) foreach(DLL ${DLLS}) add_custom_command(TARGET ${EXECUTABLE} POST_BUILD - COMMAND cmake -E copy ${DLL} $ + COMMAND cmake -E copy "${DLL}" "$" ) endforeach() @@ -105,8 +105,9 @@ macro(eth_install_executable EXECUTABLE) "${ETH_DEPENDENCY_INSTALL_DIR}/plugins/platforms" $/platforms ) - + install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin) + else() install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin) endif () From 3a82a664becde13342a70e37a411de59612f3b5c Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Fri, 12 Dec 2014 10:27:43 +0100 Subject: [PATCH 477/641] fixed misspelling at->and --- extdep/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt index bfba8e962..19cd00f7b 100644 --- a/extdep/CMakeLists.txt +++ b/extdep/CMakeLists.txt @@ -19,7 +19,7 @@ if (ETH_COMPILE) include(compile/curl.cmake) include(compile/json-rpc-cpp.cmake) - # qt at its dependencies + # qt and its dependencies include(compile/icu.cmake) include(compile/jom.cmake) include(compile/qt.cmake) From 1099a89120976ddb40bfed9e7263871afd363130 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Fri, 12 Dec 2014 10:38:43 +0100 Subject: [PATCH 478/641] when using unrecognized compiled, show warning instead of fatal_error --- cmake/EthCompilerSettings.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index 677467bea..8cf8b51b4 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -34,6 +34,6 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") set(ETH_STATIC 1) else () - message(FATAL_ERROR "Your C++ compiler does not support C++11. You have ${CMAKE_CXX_COMPILER_ID}") + message(WARNING "Your compiler is not tested, if you run into any issues, we'd welcome any patches.") endif () From 967d54992153841b116914f481ce20a596a7eb75 Mon Sep 17 00:00:00 2001 From: ethdev Date: Fri, 12 Dec 2014 11:21:39 +0100 Subject: [PATCH 479/641] all_build is working on windows --- CMakeLists.txt | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 33f1052bb..c57d11e89 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -154,7 +154,7 @@ if (NOT LANGUAGES) endif () # TODO check msvc - if(NOT ("${TARGET_PLATFORM}" STREQUAL "w64")) + if(NOT ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")) add_subdirectory(neth) endif () @@ -164,11 +164,6 @@ if (NOT LANGUAGES) #endif() if (NOT HEADLESS) - - # TODO move that somewhere else! - if ("${TARGET_PLATFORM}" STREQUAL "w64") - cmake_policy(SET CMP0020 NEW) - endif () add_subdirectory(libjsqrc) add_subdirectory(libqethereum) From 6966da558d046fff5ef7ed3ac5537b1dc54575e4 Mon Sep 17 00:00:00 2001 From: ethdev Date: Fri, 12 Dec 2014 11:24:46 +0100 Subject: [PATCH 480/641] added todo --- cmake/EthExecutableHelper.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/EthExecutableHelper.cmake b/cmake/EthExecutableHelper.cmake index 6c7ea4f50..adda57692 100644 --- a/cmake/EthExecutableHelper.cmake +++ b/cmake/EthExecutableHelper.cmake @@ -92,6 +92,7 @@ macro(eth_install_executable EXECUTABLE) elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") # copy all dlls to executable directory + # TODO improve that by copying only required dlls file (GLOB DLLS ${ETH_DEPENDENCY_INSTALL_DIR}/bin/*.dll) foreach(DLL ${DLLS}) From de2c793effbdebd5787c3c4cca069a3dc21e0e0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 12 Dec 2014 11:48:15 +0100 Subject: [PATCH 481/641] Add "--jit" option to State tests --- evmjit | 2 +- test/TestHelper.cpp | 17 +++++++++++++++++ test/TestHelper.h | 1 + test/state.cpp | 2 ++ test/vm.cpp | 19 +++++-------------- 5 files changed, 26 insertions(+), 15 deletions(-) diff --git a/evmjit b/evmjit index b1b94de24..b3a17341e 160000 --- a/evmjit +++ b/evmjit @@ -1 +1 @@ -Subproject commit b1b94de243e8dd3a36b8be42794ed70a09271cfe +Subproject commit b3a17341e4ee3f2af12270d92cf404293deefc73 diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index b0935d0b6..6f7bf31db 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -26,6 +26,7 @@ #include #include #include +#include using namespace std; using namespace dev::eth; @@ -472,4 +473,20 @@ void executeTests(const string& _name, const string& _testPathAppendix, std::fun } } + +void processCommandLineOptions() +{ + auto argc = boost::unit_test::framework::master_test_suite().argc; + auto argv = boost::unit_test::framework::master_test_suite().argv; + + for (auto i = 0; i < argc; ++i) + { + if (std::string(argv[i]) == "--jit") + { + eth::VMFactory::setKind(eth::VMKind::JIT); + break; + } + } +} + } } // namespaces diff --git a/test/TestHelper.h b/test/TestHelper.h index 3203eae83..20328c913 100644 --- a/test/TestHelper.h +++ b/test/TestHelper.h @@ -76,6 +76,7 @@ void checkLog(eth::LogEntries _resultLogs, eth::LogEntries _expectedLogs); void executeTests(const std::string& _name, const std::string& _testPathAppendix, std::function doTests); std::string getTestPath(); void userDefinedTest(std::string testTypeFlag, std::function doTests); +void processCommandLineOptions(); template void checkAddresses(mapType& _expectedAddrs, mapType& _resultAddrs) diff --git a/test/state.cpp b/test/state.cpp index 07c8373e2..961f0f13b 100644 --- a/test/state.cpp +++ b/test/state.cpp @@ -43,6 +43,8 @@ namespace dev { namespace test { void doStateTests(json_spirit::mValue& v, bool _fillin) { + processCommandLineOptions(); + for (auto& i: v.get_obj()) { cnote << i.first; diff --git a/test/vm.cpp b/test/vm.cpp index bcd7df9b7..075b3f2a0 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -277,6 +277,8 @@ namespace dev { namespace test { void doVMTests(json_spirit::mValue& v, bool _fillin) { + processCommandLineOptions(); + for (auto& i: v.get_obj()) { cnote << i.first; @@ -286,20 +288,7 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) BOOST_REQUIRE(o.count("pre") > 0); BOOST_REQUIRE(o.count("exec") > 0); - auto argc = boost::unit_test::framework::master_test_suite().argc; - auto argv = boost::unit_test::framework::master_test_suite().argv; - - for (auto i = 0; i < argc; ++i) - { - if (std::string(argv[i]) == "--jit") - { - VMFactory::setKind(VMKind::JIT); - break; - } - } - - dev::test::FakeExtVM fev; - + FakeExtVM fev; fev.importEnv(o["env"].get_obj()); fev.importState(o["pre"].get_obj()); @@ -340,6 +329,8 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) } auto endTime = std::chrono::high_resolution_clock::now(); + auto argc = boost::unit_test::framework::master_test_suite().argc; + auto argv = boost::unit_test::framework::master_test_suite().argv; for (auto i = 0; i < argc; ++i) { if (std::string(argv[i]) == "--show-times") From faf541f8aee09cd2d51ea9f7d0da8ba1662498bf Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Fri, 12 Dec 2014 12:01:32 +0100 Subject: [PATCH 482/641] renamed _DIR -> _DIRS && _LIBRARY -> _LIBRARIES according to cmake guidelines --- cmake/EthDependencies.cmake | 20 ++++++++++---------- cmake/FindGmp.cmake | 7 +++++-- cmake/FindLevelDB.cmake | 13 ++++++------- cmake/FindMiniupnpc.cmake | 7 +++++-- cmake/FindReadline.cmake | 7 +++++-- eth/CMakeLists.txt | 4 ++-- exp/CMakeLists.txt | 6 +++--- libdevcrypto/CMakeLists.txt | 8 ++++---- libethcore/CMakeLists.txt | 6 +++--- libethereum/CMakeLists.txt | 6 +++--- libevm/CMakeLists.txt | 6 +++--- libp2p/CMakeLists.txt | 6 +++--- libweb3jsonrpc/CMakeLists.txt | 6 +++--- libwebthree/CMakeLists.txt | 6 +++--- libwhisper/CMakeLists.txt | 6 +++--- neth/CMakeLists.txt | 6 +++--- secp256k1/CMakeLists.txt | 2 +- test/CMakeLists.txt | 2 +- 18 files changed, 66 insertions(+), 58 deletions(-) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 31f9420ad..24e5bd07d 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -24,8 +24,8 @@ message(" - CryptoPP header: ${CRYPTOPP_INCLUDE_DIRS}") message(" - CryptoPP lib : ${CRYPTOPP_LIBRARIES}") find_package (LevelDB REQUIRED) -message(" - LevelDB header: ${LEVELDB_INCLUDE_DIR}") -message(" - LevelDB lib: ${LEVELDB_LIBRARY}") +message(" - LevelDB header: ${LEVELDB_INCLUDE_DIRS}") +message(" - LevelDB lib: ${LEVELDB_LIBRARIES}") # TODO the Jsoncpp package does not yet check for correct version number find_package (Jsoncpp 0.60 REQUIRED) @@ -53,8 +53,8 @@ endif() #JSONRPC # TODO get rid of -DETH_READLINE find_package (Readline 6.3.8) if (READLINE_FOUND) - message (" - readline header: ${READLINE_INCLUDE_DIR}") - message (" - readline lib : ${READLINE_LIBRARY}") + message (" - readline header: ${READLINE_INCLUDE_DIRS}") + message (" - readline lib : ${READLINE_LIBRARIES}") add_definitions(-DETH_READLINE) endif () @@ -63,8 +63,8 @@ endif () # TODO get rid of -DMINIUPNPC find_package (Miniupnpc 1.8.2013) if (MINIUPNPC_FOUND) - message (" - miniupnpc header: ${MINIUPNPC_INCLUDE_DIR}") - message (" - miniupnpc lib : ${MINIUPNPC_LIBRARY}") + message (" - miniupnpc header: ${MINIUPNPC_INCLUDE_DIRS}") + message (" - miniupnpc lib : ${MINIUPNPC_LIBRARIES}") add_definitions(-DETH_MINIUPNPC) endif() @@ -72,15 +72,15 @@ endif() # TODO it is also not required in msvc build find_package (Gmp 6.0.0) if (GMP_FOUND) - message(" - gmp Header: ${GMP_INCLUDE_DIR}") - message(" - gmp lib : ${GMP_LIBRARY}") + message(" - gmp Header: ${GMP_INCLUDE_DIRS}") + message(" - gmp lib : ${GMP_LIBRARIES}") endif() # curl is only requried for tests # TODO specify min curl version, on windows we are currenly using 7.29 find_package (CURL) -message(" - curl header: ${CURL_INCLUDE_DIR}") -message(" - curl lib : ${CURL_LIBRARY}") +message(" - curl header: ${CURL_INCLUDE_DIRS}") +message(" - curl lib : ${CURL_LIBRARIES}") # do not compile GUI if (NOT HEADLESS) diff --git a/cmake/FindGmp.cmake b/cmake/FindGmp.cmake index dc2bce813..4dc8f48c4 100644 --- a/cmake/FindGmp.cmake +++ b/cmake/FindGmp.cmake @@ -5,8 +5,8 @@ # if you nee to add a custom library search path, do it via via CMAKE_FIND_ROOT_PATH # # This module defines -# GMP_INCLUDE_DIR, where to find header, etc. -# GMP_LIBRARY, the libraries needed to use gmp. +# GMP_INCLUDE_DIRS, where to find header, etc. +# GMP_LIBRARIES, the libraries needed to use gmp. # GMP_FOUND, If false, do not try to use gmp. # only look in default directories @@ -22,6 +22,9 @@ find_library( DOC "gmp library" ) +set(GMP_INCLUDE_DIRS ${GMP_INCLUDE_DIR}) +set(GMP_LIBRARIES ${GMP_LIBRARY}) + # handle the QUIETLY and REQUIRED arguments and set GMP_FOUND to TRUE # if all listed variables are TRUE, hide their existence from configuration view include(FindPackageHandleStandardArgs) diff --git a/cmake/FindLevelDB.cmake b/cmake/FindLevelDB.cmake index 3806be9ad..6bd373a9f 100644 --- a/cmake/FindLevelDB.cmake +++ b/cmake/FindLevelDB.cmake @@ -5,8 +5,8 @@ # if you nee to add a custom library search path, do it via via CMAKE_FIND_ROOT_PATH # # This module defines -# LEVELDB_INCLUDE_DIR, where to find header, etc. -# LEVELDB_LIBRARY, the libraries needed to use leveldb. +# LEVELDB_INCLUDE_DIRS, where to find header, etc. +# LEVELDB_LIBRARIES, the libraries needed to use leveldb. # LEVELDB_FOUND, If false, do not try to use leveldb. # only look in default directories @@ -14,17 +14,16 @@ find_path( LEVELDB_INCLUDE_DIR NAMES leveldb/db.h DOC "leveldb include dir" - ) +) find_library( LEVELDB_LIBRARY NAMES leveldb DOC "leveldb library" - ) - -# message (" - leveldb header : ${LEVELDB_INCLUDE_DIR}") -# message (" - leveldb lib : ${LEVELDB_LIBRARY}") +) +set(LEVELDB_INCLUDE_DIRS ${LEVELDB_INCLUDE_DIR}) +set(LEVELDB_LIBRARIES ${LEVELDB_LIBRARY}) # handle the QUIETLY and REQUIRED arguments and set LEVELDB_FOUND to TRUE # if all listed variables are TRUE, hide their existence from configuration view diff --git a/cmake/FindMiniupnpc.cmake b/cmake/FindMiniupnpc.cmake index 55795d0f9..4ecbb0c4a 100644 --- a/cmake/FindMiniupnpc.cmake +++ b/cmake/FindMiniupnpc.cmake @@ -5,8 +5,8 @@ # if you nee to add a custom library search path, do it via via CMAKE_FIND_ROOT_PATH # # This module defines -# MINIUPNPC_INCLUDE_DIR, where to find header, etc. -# MINIUPNPC_LIBRARY, the libraries needed to use gmp. +# MINIUPNPC_INCLUDE_DIRS, where to find header, etc. +# MINIUPNPC_LIBRARIES, the libraries needed to use gmp. # MINIUPNPC_FOUND, If false, do not try to use gmp. # only look in default directories @@ -22,6 +22,9 @@ find_library( DOC "miniupnpc library" ) +set(MINIUPNPC_INCLUDE_DIRS ${MINIUPNPC_INCLUDE_DIR}) +set(MINIUPNPC_LIBRARIES ${MINIUPNPC_LIBRARY}) + # handle the QUIETLY and REQUIRED arguments and set MINIUPNPC_FOUND to TRUE # if all listed variables are TRUE, hide their existence from configuration view include(FindPackageHandleStandardArgs) diff --git a/cmake/FindReadline.cmake b/cmake/FindReadline.cmake index 3db845bd0..1f47db4a7 100644 --- a/cmake/FindReadline.cmake +++ b/cmake/FindReadline.cmake @@ -5,8 +5,8 @@ # if you nee to add a custom library search path, do it via via CMAKE_FIND_ROOT_PATH # # This module defines -# READLINE_INCLUDE_DIR, where to find header, etc. -# READLINE_LIBRARY, the libraries needed to use readline. +# READLINE_INCLUDE_DIRS, where to find header, etc. +# READLINE_LIBRARIES, the libraries needed to use readline. # READLINE_FOUND, If false, do not try to use readline. # only look in default directories @@ -22,6 +22,9 @@ find_library( DOC "readline library" ) +set(READLINE_INCLUDE_DIRS ${READLINE_INCLUDE_DIR}) +set(READLINE_LIBRARIES ${READLINE_LIBRARY}) + # handle the QUIETLY and REQUIRED arguments and set READLINE_FOUND to TRUE # if all listed variables are TRUE, hide their existence from configuration view include(FindPackageHandleStandardArgs) diff --git a/eth/CMakeLists.txt b/eth/CMakeLists.txt index a7feb4927..9996d1170 100644 --- a/eth/CMakeLists.txt +++ b/eth/CMakeLists.txt @@ -18,11 +18,11 @@ target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARY_RELEASE}) target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARY_RELEASE}) if (MINIUPNPC_FOUND) - target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) + target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARIES}) endif() if (READLINE_FOUND) - target_link_libraries(${EXECUTABLE} ${READLINE_LIBRARY}) + target_link_libraries(${EXECUTABLE} ${READLINE_LIBRARIES}) endif() if (JSONRPC) diff --git a/exp/CMakeLists.txt b/exp/CMakeLists.txt index 47db2afe7..98eae7baf 100644 --- a/exp/CMakeLists.txt +++ b/exp/CMakeLists.txt @@ -3,17 +3,17 @@ set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) -include_directories(${LEVELDB_INCLUDE_DIR}) +include_directories(${LEVELDB_INCLUDE_DIRS}) include_directories(..) set(EXECUTABLE exp) add_executable(${EXECUTABLE} ${SRC_LIST}) -target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) if (MINIUPNPC_FOUND) - target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) + target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARIES}) endif() target_link_libraries(${EXECUTABLE} ethereum) diff --git a/libdevcrypto/CMakeLists.txt b/libdevcrypto/CMakeLists.txt index f5661bab1..354053483 100644 --- a/libdevcrypto/CMakeLists.txt +++ b/libdevcrypto/CMakeLists.txt @@ -9,8 +9,8 @@ set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) -include_directories(${CRYPTOPP_INCLUDE_DIR}) -include_directories(${LEVELDB_INCLUDE_DIR}) +include_directories(${CRYPTOPP_INCLUDE_DIRS}) +include_directories(${LEVELDB_INCLUDE_DIRS}) include_directories(..) set(EXECUTABLE devcrypto) @@ -23,8 +23,8 @@ else() endif() target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARY_RELEASE}) -target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) -target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) +target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LIBRARIES}) target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} secp256k1) diff --git a/libethcore/CMakeLists.txt b/libethcore/CMakeLists.txt index ede6eb087..960936b3a 100644 --- a/libethcore/CMakeLists.txt +++ b/libethcore/CMakeLists.txt @@ -9,8 +9,8 @@ set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) -include_directories(${CRYPTOPP_INCLUDE_DIR}) -include_directories(${LEVELDB_INCLUDE_DIR}) +include_directories(${CRYPTOPP_INCLUDE_DIRS}) +include_directories(${LEVELDB_INCLUDE_DIRS}) include_directories(..) set(EXECUTABLE ethcore) @@ -23,7 +23,7 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} secp256k1) diff --git a/libethereum/CMakeLists.txt b/libethereum/CMakeLists.txt index e1bad4426..c13f2ba18 100644 --- a/libethereum/CMakeLists.txt +++ b/libethereum/CMakeLists.txt @@ -11,7 +11,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) -include_directories(${LEVELDB_INCLUDE_DIR}) +include_directories(${LEVELDB_INCLUDE_DIRS}) include_directories(..) set(EXECUTABLE ethereum) @@ -24,11 +24,11 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARY_RELEASE}) if (MINIUPNPC_FOUND) - target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) + target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARIES}) endif() target_link_libraries(${EXECUTABLE} evm) diff --git a/libevm/CMakeLists.txt b/libevm/CMakeLists.txt index 57004ebbb..94f7e5e79 100644 --- a/libevm/CMakeLists.txt +++ b/libevm/CMakeLists.txt @@ -12,7 +12,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) include_directories(..) -include_directories(${LEVELDB_INCLUDE_DIR}) +include_directories(${LEVELDB_INCLUDE_DIRS}) set(EXECUTABLE evm) @@ -24,10 +24,10 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) if (MINIUPNPC_FOUND) - target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) + target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARIES}) endif() target_link_libraries(${EXECUTABLE} ethcore) diff --git a/libp2p/CMakeLists.txt b/libp2p/CMakeLists.txt index f542afd0f..c94ebebbd 100644 --- a/libp2p/CMakeLists.txt +++ b/libp2p/CMakeLists.txt @@ -11,8 +11,8 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) +include_directories(${LEVELDB_INCLUDE_DIRS}) include_directories(..) -include_directories(${LEVELDB_INCLUDE_DIR}) set(EXECUTABLE p2p) @@ -24,10 +24,10 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) if(MINIUPNPC_FOUND) - target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) + target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARIES}) endif() target_link_libraries(${EXECUTABLE} devcrypto) diff --git a/libweb3jsonrpc/CMakeLists.txt b/libweb3jsonrpc/CMakeLists.txt index 74fea58b7..9a0771ef7 100644 --- a/libweb3jsonrpc/CMakeLists.txt +++ b/libweb3jsonrpc/CMakeLists.txt @@ -10,7 +10,7 @@ set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) -include_directories(${LEVELDB_INCLUDE_DIR}) +include_directories(${LEVELDB_INCLUDE_DIRS}) include_directories(..) set(EXECUTABLE web3jsonrpc) @@ -23,13 +23,13 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_COMMON_LIBRARY}) target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_SERVER_LIBRARY}) if (MINIUPNPC_FOUND) - target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) + target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARIES}) endif() target_link_libraries(${EXECUTABLE} webthree) diff --git a/libwebthree/CMakeLists.txt b/libwebthree/CMakeLists.txt index 837ecb313..587d81493 100644 --- a/libwebthree/CMakeLists.txt +++ b/libwebthree/CMakeLists.txt @@ -11,7 +11,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) -include_directories(${LEVELDB_INCLUDE_DIR}) +include_directories(${LEVELDB_INCLUDE_DIRS}) include_directories(..) set(EXECUTABLE webthree) @@ -24,10 +24,10 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) if (MINIUPNPC_FOUND) - target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) + target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARIES}) endif() target_link_libraries(${EXECUTABLE} ethereum) diff --git a/libwhisper/CMakeLists.txt b/libwhisper/CMakeLists.txt index 8beb1b988..f51af33b7 100644 --- a/libwhisper/CMakeLists.txt +++ b/libwhisper/CMakeLists.txt @@ -12,7 +12,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) include_directories(..) -include_directories(${LEVELDB_INCLUDE_DIR}) +include_directories(${LEVELDB_INCLUDE_DIRS}) set(EXECUTABLE whisper) @@ -24,10 +24,10 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) if (MINIUPNPC_FOUND) - target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) + target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARIES}) endif() target_link_libraries(${EXECUTABLE} ethcore) diff --git a/neth/CMakeLists.txt b/neth/CMakeLists.txt index 14d710ef2..63619fd84 100644 --- a/neth/CMakeLists.txt +++ b/neth/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_policy(SET CMP0015 NEW) aux_source_directory(. SRC_LIST) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) -include_directories(${LEVELDB_INCLUDE_DIR}) +include_directories(${LEVELDB_INCLUDE_DIRS}) include_directories(..) set(EXECUTABLE neth) @@ -12,10 +12,10 @@ add_executable(${EXECUTABLE} ${SRC_LIST}) add_dependencies(${EXECUTABLE} BuildInfo.h) -target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) if (MINIUPNPC_FOUND) -target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARIES}) endif() if (JSONRPC) diff --git a/secp256k1/CMakeLists.txt b/secp256k1/CMakeLists.txt index 747d5e1cb..8dbe175d5 100644 --- a/secp256k1/CMakeLists.txt +++ b/secp256k1/CMakeLists.txt @@ -20,7 +20,7 @@ if (APPLE OR UNIX) add_library(${EXECUTABLE} SHARED ${EXECUTABLE}.c field_5x52_asm.asm) endif() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -DUSE_FIELD_GMP -DUSE_NUM_GMP -DUSE_FIELD_INV_NUM") - target_link_libraries(${EXECUTABLE} ${GMP_LIBRARY}) + target_link_libraries(${EXECUTABLE} ${GMP_LIBRARIES}) else() include_directories(${Boost_INCLUDE_DIRS}) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 440334964..73003e805 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -18,7 +18,7 @@ target_link_libraries(testeth secp256k1) target_link_libraries(testeth solidity) target_link_libraries(testeth webthree) target_link_libraries(testeth ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY_RELEASE}) -target_link_libraries(testeth ${CURL_LIBRARY}) +target_link_libraries(testeth ${CURL_LIBRARIES}) if (JSONRPC) target_link_libraries(testeth web3jsonrpc) From b121491080c60a9c3752f38d23af6e302ca17558 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Fri, 12 Dec 2014 12:40:59 +0100 Subject: [PATCH 483/641] removed walleth, libpyserpent, iethxi and QmlEthereum class --- CMakeLists.txt | 19 -- iethxi/CMakeLists.txt | 91 ------- iethxi/EthereumMacOSXBundleInfo.plist.in | 38 --- iethxi/Main.ui | 168 ------------- iethxi/MainWin.cpp | 59 ----- iethxi/MainWin.h | 18 -- iethxi/Resources.qrc | 5 - iethxi/Simple.qml | 9 - iethxi/main.cpp | 9 - libpyserpent/CMakeLists.txt | 22 -- libpyserpent/pyserpent.cpp | 173 ------------- libqethereum/QmlEthereum.cpp | 180 -------------- libqethereum/QmlEthereum.h | 283 --------------------- walleth/CMakeLists.txt | 102 -------- walleth/EthereumMacOSXBundleInfo.plist.in | 38 --- walleth/Main.ui | 168 ------------- walleth/MainWin.cpp | 286 ---------------------- walleth/MainWin.h | 84 ------- walleth/Resources.qrc | 5 - walleth/Simple.qml | 38 --- walleth/main.cpp | 11 - 21 files changed, 1806 deletions(-) delete mode 100644 iethxi/CMakeLists.txt delete mode 100644 iethxi/EthereumMacOSXBundleInfo.plist.in delete mode 100644 iethxi/Main.ui delete mode 100644 iethxi/MainWin.cpp delete mode 100644 iethxi/MainWin.h delete mode 100644 iethxi/Resources.qrc delete mode 100644 iethxi/Simple.qml delete mode 100644 iethxi/main.cpp delete mode 100644 libpyserpent/CMakeLists.txt delete mode 100644 libpyserpent/pyserpent.cpp delete mode 100644 libqethereum/QmlEthereum.cpp delete mode 100644 libqethereum/QmlEthereum.h delete mode 100644 walleth/CMakeLists.txt delete mode 100644 walleth/EthereumMacOSXBundleInfo.plist.in delete mode 100644 walleth/Main.ui delete mode 100644 walleth/MainWin.cpp delete mode 100644 walleth/MainWin.h delete mode 100644 walleth/Resources.qrc delete mode 100644 walleth/Simple.qml delete mode 100644 walleth/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c57d11e89..d6bf59636 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -112,14 +112,6 @@ include(EthExecutableHelper) createBuildInfo() -# TODO discuss that during PR. are we still using that? - -if(NOT APPLE) - if(PYTHON_LS) - add_subdirectory(libpyserpent) - endif() -endif() - add_subdirectory(libdevcore) add_subdirectory(libevmcore) add_subdirectory(liblll) @@ -158,11 +150,6 @@ if (NOT LANGUAGES) add_subdirectory(neth) endif () - # TODO discuss that during PR. are we still using that? - #if(QTQML) - #add_definitions(-DETH_QTQML) - #endif() - if (NOT HEADLESS) add_subdirectory(libjsqrc) @@ -170,12 +157,6 @@ if (NOT LANGUAGES) add_subdirectory(alethzero) add_subdirectory(third) add_subdirectory(mix) - - # TODO discuss that during PR. are we still using that? - #if(QTQML) - #add_subdirectory(iethxi) - #add_subdirectory(walleth) // resurect once we want to submit ourselves to QML. - #endif() endif() endif() diff --git a/iethxi/CMakeLists.txt b/iethxi/CMakeLists.txt deleted file mode 100644 index c2203a4f6..000000000 --- a/iethxi/CMakeLists.txt +++ /dev/null @@ -1,91 +0,0 @@ -cmake_policy(SET CMP0015 OLD) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) -aux_source_directory(. SRC_LIST) - -include_directories(..) -link_directories(../libethcore) -link_directories(../libethereum) -link_directories(../libqethereum) - -qt5_wrap_ui(ui_Main.h Main.ui) -qt5_add_resources(RESOURCE_ADDED Resources.qrc) - -# Set name of binary and add_executable() -if (APPLE) - set(EXECUTABLE IEthXi) - set(CMAKE_INSTALL_PREFIX ./) - set(BIN_INSTALL_DIR ".") - set(DOC_INSTALL_DIR ".") - - set(PROJECT_VERSION "${ETH_VERSION}") - set(MACOSX_BUNDLE_INFO_STRING "${PROJECT_NAME} ${PROJECT_VERSION}") - set(MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_NAME} ${PROJECT_VERSION}") - set(MACOSX_BUNDLE_LONG_VERSION_STRING "${PROJECT_NAME} ${PROJECT_VERSION}") - set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION}") - set(MACOSX_BUNDLE_COPYRIGHT "${PROJECT_COPYRIGHT_YEAR} ${PROJECT_VENDOR}") - set(MACOSX_BUNDLE_GUI_IDENTIFIER "${PROJECT_DOMAIN_SECOND}.${PROJECT_DOMAIN_FIRST}") - set(MACOSX_BUNDLE_BUNDLE_NAME ${EXECUTABLE}) - include(BundleUtilities) - - add_executable(${EXECUTABLE} MACOSX_BUNDLE Main.ui ${RESOURCE_ADDED} ${SRC_LIST}) -else () - set(EXECUTABLE iethxi) - add_executable(${EXECUTABLE} Main.ui ${RESOURCE_ADDED} ${SRC_LIST}) -endif () - -qt5_use_modules(${EXECUTABLE} Core Gui Widgets Network Quick Qml) -target_link_libraries(${EXECUTABLE} qethereum) -target_link_libraries(${EXECUTABLE} ethereum) -target_link_libraries(${EXECUTABLE} secp256k1) - -if (APPLE) - if (${ADDFRAMEWORKS}) - set_target_properties(${EXECUTABLE} PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/EthereumMacOSXBundleInfo.plist.in") - endif () - - SET_SOURCE_FILES_PROPERTIES(${EXECUTABLE} PROPERTIES MACOSX_PACKAGE_LOCATION MacOS) - - # This is a workaround for when the build-type defaults to Debug, and when a multi-config generator like xcode is used, where the type - # will not be set but defaults to release. - set(generator_lowercase "${CMAKE_GENERATOR}") - string(TOLOWER "${CMAKE_GENERATOR}" generator_lowercase) - if ("${generator_lowercase}" STREQUAL "xcode") - # TODO: Not sure how to resolve this. Possibly \${TARGET_BUILD_DIR} - set(binary_build_dir "${CMAKE_CURRENT_BINARY_DIR}/Debug") - else () - set(binary_build_dir "${CMAKE_CURRENT_BINARY_DIR}") - endif () - - set(APPS ${binary_build_dir}/${EXECUTABLE}.app) - - # This tool and the next will automatically looked at the linked libraries in order to determine what dependencies are required. Thus, target_link_libaries only needs to add ethereum and secp256k1 (above) - install(CODE " - include(BundleUtilities) - set(BU_CHMOD_BUNDLE_ITEMS 1) - fixup_bundle(\"${APPS}\" \"${BUNDLELIBS}\" \"../libqethereum ../libethereum ../secp256k1\") - " COMPONENT RUNTIME ) - - if (${ADDFRAMEWORKS}) - add_custom_target(addframeworks ALL - COMMAND /usr/local/opt/qt5/bin/macdeployqt ${binary_build_dir}/${EXECUTABLE}.app - WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - DEPENDS ${PROJECT_NAME} - ) - endif () - -elseif ("${TARGET_PLATFORM}" STREQUAL "w64") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-keep-inline-dllexport -static-libgcc -static-libstdc++ -static") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-s -Wl,-subsystem,windows -mthreads -L/usr/x86_64-w64-mingw32/plugins/platforms") - target_link_libraries(${EXECUTABLE} gcc) - target_link_libraries(${EXECUTABLE} mingw32 qtmain mswsock iphlpapi qwindows shlwapi Qt5PlatformSupport gdi32 comdlg32 oleaut32 imm32 winmm ole32 uuid ws2_32) - target_link_libraries(${EXECUTABLE} boost_system-mt-s) - target_link_libraries(${EXECUTABLE} boost_filesystem-mt-s) - target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) - target_link_libraries(${EXECUTABLE} Qt5PlatformSupport) - set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) -elseif (UNIX) -else () - message(ERROR "platform not supported") -endif () - diff --git a/iethxi/EthereumMacOSXBundleInfo.plist.in b/iethxi/EthereumMacOSXBundleInfo.plist.in deleted file mode 100644 index 684ad7908..000000000 --- a/iethxi/EthereumMacOSXBundleInfo.plist.in +++ /dev/null @@ -1,38 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleExecutable - ${MACOSX_BUNDLE_EXECUTABLE_NAME} - CFBundleGetInfoString - ${MACOSX_BUNDLE_INFO_STRING} - CFBundleIconFile - ${MACOSX_BUNDLE_ICON_FILE} - CFBundleIdentifier - ${MACOSX_BUNDLE_GUI_IDENTIFIER} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleLongVersionString - ${MACOSX_BUNDLE_LONG_VERSION_STRING} - CFBundleName - ${MACOSX_BUNDLE_BUNDLE_NAME} - CFBundlePackageType - APPL - CFBundleShortVersionString - ${MACOSX_BUNDLE_SHORT_VERSION_STRING} - CFBundleSignature - ???? - CFBundleVersion - ${MACOSX_BUNDLE_BUNDLE_VERSION} - CSResourcesFileMapped - - LSRequiresCarbon - - NSHumanReadableCopyright - ${MACOSX_BUNDLE_COPYRIGHT} - NSHighResolutionCapable - - - diff --git a/iethxi/Main.ui b/iethxi/Main.ui deleted file mode 100644 index fe289ba9f..000000000 --- a/iethxi/Main.ui +++ /dev/null @@ -1,168 +0,0 @@ - - - Main - - - - 0 - 0 - 562 - 488 - - - - Walleth - - - true - - - QMainWindow::AllowNestedDocks|QMainWindow::AllowTabbedDocks|QMainWindow::VerticalTabs - - - true - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - 0 wei - - - - - - - 0 peers - - - - - - - 1 block - - - - - - - - - - - 0 - 0 - 562 - 25 - - - - - &File - - - - - - &Network - - - - - - - - T&ools - - - - - - - - &Help - - - - - - - - - - - - &Quit - - - - - true - - - true - - - Use &UPnP - - - - - &Connect to Peer... - - - - - true - - - Enable &Network - - - - - true - - - &Mine - - - - - &New Address - - - - - &About... - - - - - true - - - &Preview - - - - - - - diff --git a/iethxi/MainWin.cpp b/iethxi/MainWin.cpp deleted file mode 100644 index 2d5b57094..000000000 --- a/iethxi/MainWin.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "BuildInfo.h" -#include "MainWin.h" -#include "ui_Main.h" -using namespace std; -using namespace eth; - -Main::Main(QWidget *parent) : - QObject(parent) -{ -/* qRegisterMetaType("eth::u256"); - qRegisterMetaType("eth::KeyPair"); - qRegisterMetaType("eth::Secret"); - qRegisterMetaType("eth::Address"); - qRegisterMetaType("QmlAccount*"); - qRegisterMetaType("QmlEthereum*"); - - qmlRegisterType("org.ethereum", 1, 0, "Ethereum"); - qmlRegisterType("org.ethereum", 1, 0, "Account"); - qmlRegisterSingletonType("org.ethereum", 1, 0, "Balance", QmlEthereum::constructU256Helper); - qmlRegisterSingletonType("org.ethereum", 1, 0, "Key", QmlEthereum::constructKeyHelper); -*/ - /* - ui->librariesView->setModel(m_libraryMan); - ui->graphsView->setModel(m_graphMan); - */ - - - - -// QQmlContext* context = m_view->rootContext(); -// context->setContextProperty("u256", new U256Helper(this)); -} - -Main::~Main() -{ -} - -// extra bits needed to link on VS -#ifdef _MSC_VER - -// include moc file, ofuscated to hide from automoc -#include\ -"moc_MainWin.cpp" - -#endif diff --git a/iethxi/MainWin.h b/iethxi/MainWin.h deleted file mode 100644 index acbea8ca8..000000000 --- a/iethxi/MainWin.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef MAIN_H -#define MAIN_H - -#include - -class Main: public QObject -{ - Q_OBJECT - -public: - explicit Main(QWidget *parent = 0); - ~Main(); - -private: - QQmlApplicationEngine* m_view; -}; - -#endif // MAIN_H diff --git a/iethxi/Resources.qrc b/iethxi/Resources.qrc deleted file mode 100644 index 1789216ed..000000000 --- a/iethxi/Resources.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - Simple.qml - - diff --git a/iethxi/Simple.qml b/iethxi/Simple.qml deleted file mode 100644 index ac9dc5e37..000000000 --- a/iethxi/Simple.qml +++ /dev/null @@ -1,9 +0,0 @@ -import QtQuick.Controls 1.1 - -ApplicationWindow { - title: "My App" - Button { - text: "Push Me" - anchors.centerIn: parent - } -} diff --git a/iethxi/main.cpp b/iethxi/main.cpp deleted file mode 100644 index 569b6d17c..000000000 --- a/iethxi/main.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include -#include - -int main(int argc, char *argv[]) -{ - QApplication a(argc, argv); - QQmlApplicationEngine app(QUrl("qrc:/Simple.qml")); - return a.exec(); -} diff --git a/libpyserpent/CMakeLists.txt b/libpyserpent/CMakeLists.txt deleted file mode 100644 index 1ffa49ac0..000000000 --- a/libpyserpent/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -cmake_policy(SET CMP0015 NEW) - -aux_source_directory(. SRC_LIST) - -set(EXECUTABLE pyserpent) - -file(GLOB HEADERS "*.h") - -# set(CMAKE_INSTALL_PREFIX ../lib) -add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) - -include_directories(..) - -target_link_libraries(${EXECUTABLE} serpent) -target_link_libraries(${EXECUTABLE} lll) -target_link_libraries(${EXECUTABLE} evmcore) -target_link_libraries(${EXECUTABLE} devcore) -target_link_libraries(${EXECUTABLE} ${PYTHON_LS}) - -install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) -install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) - diff --git a/libpyserpent/pyserpent.cpp b/libpyserpent/pyserpent.cpp deleted file mode 100644 index ff8813fcf..000000000 --- a/libpyserpent/pyserpent.cpp +++ /dev/null @@ -1,173 +0,0 @@ -#include -#include "structmember.h" - -#include -#include -#include -#include - -#define PYMETHOD(name, FROM, method, TO) \ - static PyObject * name(PyObject *, PyObject *args) { \ - try { \ - FROM(med) \ - return TO(method(med)); \ - } \ - catch (std::string e) { \ - PyErr_SetString(PyExc_Exception, e.c_str()); \ - return NULL; \ - } \ - } - -#define FROMSTR(v) \ - const char *command; \ - int len; \ - if (!PyArg_ParseTuple(args, "s#", &command, &len)) \ - return NULL; \ - std::string v = std::string(command, len); \ - -#define FROMNODE(v) \ - PyObject *node; \ - if (!PyArg_ParseTuple(args, "O", &node)) \ - return NULL; \ - Node v = cppifyNode(node); - -#define FROMLIST(v) \ - PyObject *node; \ - if (!PyArg_ParseTuple(args, "O", &node)) \ - return NULL; \ - std::vector v = cppifyNodeList(node); - -// Convert metadata into python wrapper form [file, ln, ch] -PyObject* pyifyMetadata(Metadata m) { - PyObject* a = PyList_New(0); - PyList_Append(a, Py_BuildValue("s#", m.file.c_str(), m.file.length())); - PyList_Append(a, Py_BuildValue("i", m.ln)); - PyList_Append(a, Py_BuildValue("i", m.ch)); - return a; -} - -// Convert node into python wrapper form -// [token=0/astnode=1, val, metadata, args] -PyObject* pyifyNode(Node n) { - PyObject* a = PyList_New(0); - PyList_Append(a, Py_BuildValue("i", n.type == ASTNODE)); - PyList_Append(a, Py_BuildValue("s#", n.val.c_str(), n.val.length())); - PyList_Append(a, pyifyMetadata(n.metadata)); - for (unsigned i = 0; i < n.args.size(); i++) - PyList_Append(a, pyifyNode(n.args[i])); - return a; -} - -// Convert string into python wrapper form -PyObject* pyifyString(std::string s) { - return Py_BuildValue("s#", s.c_str(), s.length()); -} - -// Convert list of nodes into python wrapper form -PyObject* pyifyNodeList(std::vector n) { - PyObject* a = PyList_New(0); - for (unsigned i = 0; i < n.size(); i++) - PyList_Append(a, pyifyNode(n[i])); - return a; -} - -// Convert pyobject int into normal form -int cppifyInt(PyObject* o) { - int out; - if (!PyArg_Parse(o, "i", &out)) - err("Argument should be integer", Metadata()); - return out; -} - -// Convert pyobject string into normal form -std::string cppifyString(PyObject* o) { - const char *command; - if (!PyArg_Parse(o, "s", &command)) - err("Argument should be string", Metadata()); - return std::string(command); -} - -// Convert metadata from python wrapper form -Metadata cppifyMetadata(PyObject* o) { - std::string file = cppifyString(PyList_GetItem(o, 0)); - int ln = cppifyInt(PyList_GetItem(o, 1)); - int ch = cppifyInt(PyList_GetItem(o, 2)); - return Metadata(file, ln, ch); -} - -// Convert node from python wrapper form -Node cppifyNode(PyObject* o) { - Node n; - int isAstNode = cppifyInt(PyList_GetItem(o, 0)); - n.type = isAstNode ? ASTNODE : TOKEN; - n.val = cppifyString(PyList_GetItem(o, 1)); - n.metadata = cppifyMetadata(PyList_GetItem(o, 2)); - std::vector args; - for (int i = 3; i < PyList_Size(o); i++) { - args.push_back(cppifyNode(PyList_GetItem(o, i))); - } - n.args = args; - return n; -} - -//Convert list of nodes into normal form -std::vector cppifyNodeList(PyObject* o) { - std::vector out; - for (int i = 0; i < PyList_Size(o); i++) { - out.push_back(cppifyNode(PyList_GetItem(o,i))); - } - return out; -} - -PYMETHOD(ps_compile, FROMSTR, compile, pyifyString) -PYMETHOD(ps_compile_chunk, FROMSTR, compileChunk, pyifyString) -PYMETHOD(ps_compile_to_lll, FROMSTR, compileToLLL, pyifyNode) -PYMETHOD(ps_compile_chunk_to_lll, FROMSTR, compileChunkToLLL, pyifyNode) -PYMETHOD(ps_compile_lll, FROMNODE, compileLLL, pyifyString) -PYMETHOD(ps_parse, FROMSTR, parseSerpent, pyifyNode) -PYMETHOD(ps_rewrite, FROMNODE, rewrite, pyifyNode) -PYMETHOD(ps_rewrite_chunk, FROMNODE, rewriteChunk, pyifyNode) -PYMETHOD(ps_pretty_compile, FROMSTR, prettyCompile, pyifyNodeList) -PYMETHOD(ps_pretty_compile_chunk, FROMSTR, prettyCompileChunk, pyifyNodeList) -PYMETHOD(ps_pretty_compile_lll, FROMNODE, prettyCompileLLL, pyifyNodeList) -PYMETHOD(ps_serialize, FROMLIST, serialize, pyifyString) -PYMETHOD(ps_deserialize, FROMSTR, deserialize, pyifyNodeList) -PYMETHOD(ps_parse_lll, FROMSTR, parseLLL, pyifyNode) - - -static PyMethodDef PyextMethods[] = { - {"compile", ps_compile, METH_VARARGS, - "Compile code."}, - {"compile_chunk", ps_compile_chunk, METH_VARARGS, - "Compile code chunk (no wrappers)."}, - {"compile_to_lll", ps_compile_to_lll, METH_VARARGS, - "Compile code to LLL."}, - {"compile_chunk_to_lll", ps_compile_chunk_to_lll, METH_VARARGS, - "Compile code chunk to LLL (no wrappers)."}, - {"compile_lll", ps_compile_lll, METH_VARARGS, - "Compile LLL to EVM."}, - {"parse", ps_parse, METH_VARARGS, - "Parse serpent"}, - {"rewrite", ps_rewrite, METH_VARARGS, - "Rewrite parsed serpent to LLL"}, - {"rewrite_chunk", ps_rewrite_chunk, METH_VARARGS, - "Rewrite parsed serpent to LLL (no wrappers)"}, - {"pretty_compile", ps_pretty_compile, METH_VARARGS, - "Compile to EVM opcodes"}, - {"pretty_compile_chunk", ps_pretty_compile_chunk, METH_VARARGS, - "Compile chunk to EVM opcodes (no wrappers)"}, - {"pretty_compile_lll", ps_pretty_compile_lll, METH_VARARGS, - "Compile LLL to EVM opcodes"}, - {"serialize", ps_serialize, METH_VARARGS, - "Convert EVM opcodes to bin"}, - {"deserialize", ps_deserialize, METH_VARARGS, - "Convert EVM bin to opcodes"}, - {"parse_lll", ps_parse_lll, METH_VARARGS, - "Parse LLL"}, - {NULL, NULL, 0, NULL} /* Sentinel */ -}; - -PyMODINIT_FUNC initserpent_pyext(void) -{ - Py_InitModule( "serpent_pyext", PyextMethods ); -} diff --git a/libqethereum/QmlEthereum.cpp b/libqethereum/QmlEthereum.cpp deleted file mode 100644 index 812247b36..000000000 --- a/libqethereum/QmlEthereum.cpp +++ /dev/null @@ -1,180 +0,0 @@ -#if ETH_QTQML -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include "QmlEthereum.h" -using namespace std; - -// types -using dev::bytes; -using dev::bytesConstRef; -using dev::h160; -using dev::h256; -using dev::u160; -using dev::u256; -using dev::u256s; -using dev::RLP; -using dev::Address; -using dev::eth::BlockInfo; -using dev::eth::Client; -using dev::eth::Instruction; -using dev::KeyPair; -using dev::eth::NodeMode; -using dev::Secret; -using dev::eth::Transaction; -using dev::p2p::PeerInfo; - -// functions -using dev::toHex; -using dev::fromHex; -using dev::right160; -using dev::simpleDebugOut; -using dev::toLog2; -using dev::toString; -using dev::eth::disassemble; -using dev::eth::formatBalance; -using dev::eth::units; - -// vars -using dev::g_logPost; -using dev::g_logVerbosity; - -// Horrible global for the mainwindow. Needed for the QmlEthereums to find the Main window which acts as multiplexer for now. -// Can get rid of this once we've sorted out ITC for signalling & multiplexed querying. -dev::eth::Client* g_qmlClient; -QObject* g_qmlMain; -#if 0 -QmlAccount::QmlAccount(QObject*) -{ -} - -QmlAccount::~QmlAccount() -{ -} - -void QmlAccount::setEthereum(QmlEthereum* _eth) -{ - if (m_eth == _eth) - return; -// if (m_eth) -// disconnect(m_eth, SIGNAL(changed()), this, SIGNAL(changed())); - m_eth = _eth; -// if (m_eth) -// connect(m_eth, SIGNAL(changed()), this, SIGNAL(changed())); - ethChanged(); -// changed(); -} - -dev::u256 QmlAccount::balance() const -{ - if (m_eth) - return m_eth->balanceAt(m_address); - return u256(0); -} - -double QmlAccount::txCount() const -{ - if (m_eth) - return m_eth->txCountAt(m_address); - return 0; -} - -bool QmlAccount::isContract() const -{ - if (m_eth) - return m_eth->isContractAt(m_address); - return 0; -} - -QmlEthereum::QmlEthereum(QObject* _p): QObject(_p) -{ -// connect(g_qmlMain, SIGNAL(changed()), SIGNAL(changed())); -} - -QmlEthereum::~QmlEthereum() -{ -} - -Client* QmlEthereum::client() const -{ - return g_qmlClient; -} - -Address QmlEthereum::coinbase() const -{ - return client()->address(); -} - -void QmlEthereum::setCoinbase(Address _a) -{ - if (client()->address() != _a) - { - client()->setAddress(_a); -// changed(); - } -} - -u256 QmlEthereum::balanceAt(Address _a) const -{ - return client()->postState().balance(_a); -} - -bool QmlEthereum::isContractAt(Address _a) const -{ - return client()->postState().addressHasCode(_a); -} - -bool QmlEthereum::isMining() const -{ - return client()->isMining(); -} - -bool QmlEthereum::isListening() const -{ - return client()->haveNetwork(); -} - -void QmlEthereum::setMining(bool _l) -{ - if (_l) - client()->startMining(); - else - client()->stopMining(); -} - -void QmlEthereum::setListening(bool _l) -{ - if (_l) - client()->startNetwork(); - else - client()->stopNetwork(); -} - -double QmlEthereum::txCountAt(Address _a) const -{ - return (double)client()->postState().transactionsFrom(_a); -} - -unsigned QmlEthereum::peerCount() const -{ - return (unsigned)client()->peerCount(); -} - -void QmlEthereum::transact(Secret _secret, u256 _amount, u256 _gasPrice, u256 _gas, QByteArray _init) -{ - client()->transact(_secret, _amount, bytes(_init.data(), _init.data() + _init.size()), _gas, _gasPrice); -} - -void QmlEthereum::transact(Secret _secret, Address _dest, u256 _amount, u256 _gasPrice, u256 _gas, QByteArray _data) -{ - client()->transact(_secret, _amount, _dest, bytes(_data.data(), _data.data() + _data.size()), _gas, _gasPrice); -} - -#endif - diff --git a/libqethereum/QmlEthereum.h b/libqethereum/QmlEthereum.h deleted file mode 100644 index d242540a1..000000000 --- a/libqethereum/QmlEthereum.h +++ /dev/null @@ -1,283 +0,0 @@ -#pragma once - -#include -#if ETH_QTQML -#include -#endif -#include -#include - -namespace dev { namespace eth { -class Client; -class State; -}} - -class QQmlEngine; -class QmlAccount; -class QmlEthereum; - -extern dev::eth::Client* g_qmlClient; -extern QObject* g_qmlMain; - -Q_DECLARE_METATYPE(dev::u256) -Q_DECLARE_METATYPE(dev::Address) -Q_DECLARE_METATYPE(dev::Secret) -Q_DECLARE_METATYPE(dev::KeyPair) -//Q_DECLARE_METATYPE(QmlAccount*) -//Q_DECLARE_METATYPE(QmlEthereum*) - -class QmlU256Helper: public QObject -{ - Q_OBJECT - -public: - QmlU256Helper(QObject* _p = nullptr): QObject(_p) {} - - Q_INVOKABLE dev::u256 add(dev::u256 _a, dev::u256 _b) const { return _a + _b; } - Q_INVOKABLE dev::u256 sub(dev::u256 _a, dev::u256 _b) const { return _a - _b; } - Q_INVOKABLE dev::u256 mul(dev::u256 _a, int _b) const { return _a * _b; } - Q_INVOKABLE dev::u256 mul(int _a, dev::u256 _b) const { return _a * _b; } - Q_INVOKABLE dev::u256 div(dev::u256 _a, int _b) const { return _a / _b; } - - Q_INVOKABLE dev::u256 wei(double _s) const { return (dev::u256)_s; } - Q_INVOKABLE dev::u256 szabo(double _s) const { return (dev::u256)(_s * (double)dev::eth::szabo); } - Q_INVOKABLE dev::u256 finney(double _s) const { return (dev::u256)(_s * (double)dev::eth::finney); } - Q_INVOKABLE dev::u256 ether(double _s) const { return (dev::u256)(_s * (double)dev::eth::ether); } - Q_INVOKABLE dev::u256 wei(unsigned _s) const { return (dev::u256)_s; } - Q_INVOKABLE dev::u256 szabo(unsigned _s) const { return (dev::u256)(_s * dev::eth::szabo); } - Q_INVOKABLE dev::u256 finney(unsigned _s) const { return (dev::u256)(_s * dev::eth::finney); } - Q_INVOKABLE dev::u256 ether(unsigned _s) const { return (dev::u256)(_s * dev::eth::ether); } - Q_INVOKABLE double toWei(dev::u256 _t) const { return (double)_t; } - Q_INVOKABLE double toSzabo(dev::u256 _t) const { return toWei(_t) / (double)dev::eth::szabo; } - Q_INVOKABLE double toFinney(dev::u256 _t) const { return toWei(_t) / (double)dev::eth::finney; } - Q_INVOKABLE double toEther(dev::u256 _t) const { return toWei(_t) / (double)dev::eth::ether; } - - Q_INVOKABLE double value(dev::u256 _t) const { return (double)_t; } - - Q_INVOKABLE QString stringOf(dev::u256 _t) const { return QString::fromStdString(dev::eth::formatBalance(_t)); } -}; - -class QmlKeyHelper: public QObject -{ - Q_OBJECT - -public: - QmlKeyHelper(QObject* _p = nullptr): QObject(_p) {} - - Q_INVOKABLE dev::KeyPair create() const { return dev::KeyPair::create(); } - Q_INVOKABLE dev::Address address(dev::KeyPair _p) const { return _p.address(); } - Q_INVOKABLE dev::Secret secret(dev::KeyPair _p) const { return _p.secret(); } - Q_INVOKABLE dev::KeyPair keypair(dev::Secret _k) const { return dev::KeyPair(_k); } - - Q_INVOKABLE bool isNull(dev::Address _a) const { return !_a; } - - Q_INVOKABLE dev::Address addressOf(QString _s) const { return dev::Address(_s.toStdString()); } - Q_INVOKABLE QString stringOf(dev::Address _a) const { return QString::fromStdString(dev::toHex(_a.asArray())); } - Q_INVOKABLE QString toAbridged(dev::Address _a) const { return QString::fromStdString(_a.abridged()); } -}; -#if 0 -class QmlAccount: public QObject -{ - Q_OBJECT - -public: - QmlAccount(QObject* _p = nullptr); - virtual ~QmlAccount(); - - Q_INVOKABLE QmlEthereum* ethereum() const { return m_eth; } - Q_INVOKABLE dev::u256 balance() const; - Q_INVOKABLE double txCount() const; - Q_INVOKABLE bool isContract() const; - Q_INVOKABLE dev::Address address() const { return m_address; } - - // TODO: past transactions models. - -public slots: - void setEthereum(QmlEthereum* _eth); - void setAddress(dev::Address _a) { m_address = _a; } - -signals: - void changed(); - void ethChanged(); - -private: - QmlEthereum* m_eth = nullptr; - dev::Address m_address; - - Q_PROPERTY(dev::u256 balance READ balance NOTIFY changed STORED false) - Q_PROPERTY(double txCount READ txCount NOTIFY changed STORED false) - Q_PROPERTY(bool isContract READ isContract NOTIFY changed STORED false) - Q_PROPERTY(dev::Address address READ address WRITE setAddress NOTIFY changed) - Q_PROPERTY(QmlEthereum* ethereum READ ethereum WRITE setEthereum NOTIFY ethChanged) -}; - -class QmlEthereum: public QObject -{ - Q_OBJECT - -public: - QmlEthereum(QObject* _p = nullptr); - virtual ~QmlEthereum(); - - dev::eth::Client* client() const; - - static QObject* constructU256Helper(QQmlEngine*, QJSEngine*) { return new QmlU256Helper; } - static QObject* constructKeyHelper(QQmlEngine*, QJSEngine*) { return new QmlKeyHelper; } - - Q_INVOKABLE dev::Address coinbase() const; - - Q_INVOKABLE bool isListening() const; - Q_INVOKABLE bool isMining() const; - - Q_INVOKABLE dev::u256 balanceAt(dev::Address _a) const; - Q_INVOKABLE double txCountAt(dev::Address _a) const; - Q_INVOKABLE bool isContractAt(dev::Address _a) const; - - Q_INVOKABLE unsigned peerCount() const; - - Q_INVOKABLE QmlEthereum* self() { return this; } - -public slots: - void transact(dev::Secret _secret, dev::Address _dest, dev::u256 _amount, dev::u256 _gasPrice, dev::u256 _gas, QByteArray _data); - void transact(dev::Secret _secret, dev::u256 _amount, dev::u256 _gasPrice, dev::u256 _gas, QByteArray _init); - void setCoinbase(dev::Address); - void setMining(bool _l); - - void setListening(bool _l); - -signals: - void coinbaseChanged(); -// void netChanged(); -// void miningChanged(); - -private: - Q_PROPERTY(dev::Address coinbase READ coinbase WRITE setCoinbase NOTIFY coinbaseChanged) - Q_PROPERTY(bool listening READ isListening WRITE setListening) - Q_PROPERTY(bool mining READ isMining WRITE setMining) -}; -#endif -#if 0 -template T to(QVariant const& _s) { if (_s.type() != QVariant::String) return T(); auto s = _s.toString().toLatin1(); assert(s.size() == sizeof(T)); return *(T*)s.data(); } -template QVariant toQJS(T const& _s) { QLatin1String ret((char*)&_s, sizeof(T)); assert(QVariant(QString(ret)).toString().toLatin1().size() == sizeof(T)); assert(*(T*)(QVariant(QString(ret)).toString().toLatin1().data()) == _s); return QVariant(QString(ret)); } - -class U256Helper: public QObject -{ - Q_OBJECT - -public: - U256Helper(QObject* _p = nullptr): QObject(_p) {} - - static dev::u256 in(QVariant const& _s) { return to(_s); } - static QVariant out(dev::u256 const& _s) { return toQJS(_s); } - - Q_INVOKABLE QVariant add(QVariant _a, QVariant _b) const { return out(in(_a) + in(_b)); } - Q_INVOKABLE QVariant sub(QVariant _a, QVariant _b) const { return out(in(_a) - in(_b)); } - Q_INVOKABLE QVariant mul(QVariant _a, int _b) const { return out(in(_a) * in(_b)); } - Q_INVOKABLE QVariant mul(int _a, QVariant _b) const { return out(in(_a) * in(_b)); } - Q_INVOKABLE QVariant div(QVariant _a, int _b) const { return out(in(_a) / in(_b)); } - - Q_INVOKABLE QVariant wei(double _s) const { return out(dev::u256(_s)); } - Q_INVOKABLE QVariant szabo(double _s) const { return out(dev::u256(_s * (double)dev::eth::szabo)); } - Q_INVOKABLE QVariant finney(double _s) const { return out(dev::u256(_s * (double)dev::eth::finney)); } - Q_INVOKABLE QVariant ether(double _s) const { return out(dev::u256(_s * (double)dev::eth::ether)); } - Q_INVOKABLE QVariant wei(unsigned _s) const { return value(_s); } - Q_INVOKABLE QVariant szabo(unsigned _s) const { return out(dev::u256(_s) * dev::eth::szabo); } - Q_INVOKABLE QVariant finney(unsigned _s) const { return out(dev::u256(_s) * dev::eth::finney); } - Q_INVOKABLE QVariant ether(unsigned _s) const { return out(dev::u256(_s) * dev::eth::ether); } - Q_INVOKABLE double toWei(QVariant _t) const { return toValue(_t); } - Q_INVOKABLE double toSzabo(QVariant _t) const { return toWei(_t) / (double)dev::eth::szabo; } - Q_INVOKABLE double toFinney(QVariant _t) const { return toWei(_t) / (double)dev::eth::finney; } - Q_INVOKABLE double toEther(QVariant _t) const { return toWei(_t) / (double)dev::eth::ether; } - - Q_INVOKABLE QVariant value(unsigned _s) const { return out(dev::u256(_s)); } - Q_INVOKABLE double toValue(QVariant _t) const { return (double)in(_t); } - - Q_INVOKABLE QString ethOf(QVariant _t) const { return QString::fromStdString(dev::eth::formatBalance(in(_t))); } - Q_INVOKABLE QString stringOf(QVariant _t) const { return QString::fromStdString(dev::eth::toString(in(_t))); } - - Q_INVOKABLE QByteArray bytesOf(QVariant _t) const { dev::h256 b = in(_t); return QByteArray((char const*)&b, sizeof(dev::h256)); } - Q_INVOKABLE QVariant fromHex(QString _s) const { return out((dev::u256)dev::h256(_s.toStdString())); } - - Q_INVOKABLE QVariant fromAddress(QVariant/*dev::Address*/ _a) const { return out((dev::eth::u160)to(_a)); } - Q_INVOKABLE QVariant toAddress(QVariant/*dev::Address*/ _a) const { return toQJS((dev::eth::u160)in(_a)); } - - Q_INVOKABLE bool isNull(QVariant/*dev::Address*/ _a) const { return !in(_a); } -}; - -class KeyHelper: public QObject -{ - Q_OBJECT - -public: - KeyHelper(QObject* _p = nullptr): QObject(_p) {} - - static dev::Address in(QVariant const& _s) { return to(_s); } - static QVariant out(dev::Address const& _s) { return toQJS(_s); } - - Q_INVOKABLE QVariant/*dev::KeyPair*/ create() const { return toQJS(dev::KeyPair::create()); } - Q_INVOKABLE QVariant/*dev::Address*/ address(QVariant/*dev::KeyPair*/ _p) const { return out(to(_p).address()); } - Q_INVOKABLE QVariant/*dev::Secret*/ secret(QVariant/*dev::KeyPair*/ _p) const { return toQJS(to(_p).secret()); } - Q_INVOKABLE QVariant/*dev::KeyPair*/ keypair(QVariant/*dev::Secret*/ _k) const { return toQJS(dev::KeyPair(to(_k))); } - - Q_INVOKABLE bool isNull(QVariant/*dev::Address*/ _a) const { return !in(_a); } - - Q_INVOKABLE QVariant/*dev::Address*/ addressOf(QString _s) const { return out(dev::Address(_s.toStdString())); } - Q_INVOKABLE QString stringOf(QVariant/*dev::Address*/ _a) const { return QString::fromStdString(dev::eth::toHex(in(_a).asArray())); } - Q_INVOKABLE QString toAbridged(QVariant/*dev::Address*/ _a) const { return QString::fromStdString(in(_a).abridged()); } - -}; - -class BytesHelper: public QObject -{ - Q_OBJECT - -public: - BytesHelper(QObject* _p = nullptr): QObject(_p) {} - - Q_INVOKABLE QByteArray concat(QVariant _v, QVariant _w) const - { - QByteArray ba; - if (_v.type() == QVariant::ByteArray) - ba = _v.toByteArray(); - else - ba = _v.toString().toLatin1(); - QByteArray ba2; - if (_w.type() == QVariant::ByteArray) - ba2 = _w.toByteArray(); - else - ba2 = _w.toString().toLatin1(); - ba.append(ba2); - return QByteArray(ba); - } - Q_INVOKABLE QByteArray concat(QByteArray _v, QByteArray _w) const - { - _v.append(_w); - return _v; - } - Q_INVOKABLE QByteArray fromString(QString _s) const - { - return _s.toLatin1(); - } - Q_INVOKABLE QByteArray fromString(QString _s, unsigned _padding) const - { - QByteArray b = _s.toLatin1(); - for (unsigned i = b.size(); i < _padding; ++i) - b.append((char)0); - b.resize(_padding); - return b; - } - Q_INVOKABLE QString toString(QByteArray _b) const - { - while (_b.size() && !_b[_b.size() - 1]) - _b.resize(_b.size() - 1); - return QString::fromLatin1(_b); - } - Q_INVOKABLE QVariant u256of(QByteArray _s) const - { - while (_s.size() < 32) - _s.append((char)0); - dev::h256 ret((uint8_t const*)_s.data(), dev::h256::ConstructFromPointer); - return toQJS(ret); - } -}; -#endif diff --git a/walleth/CMakeLists.txt b/walleth/CMakeLists.txt deleted file mode 100644 index 44bf5f0f9..000000000 --- a/walleth/CMakeLists.txt +++ /dev/null @@ -1,102 +0,0 @@ -cmake_policy(SET CMP0015 NEW) - -if ("${TARGET_PLATFORM}" STREQUAL "w64") - cmake_policy(SET CMP0020 NEW) -endif () - - -set(CMAKE_INCLUDE_CURRENT_DIR ON) -aux_source_directory(. SRC_LIST) - -include_directories(..) -link_directories(../libethcore) -link_directories(../libethereum) -link_directories(../libqethereum) - -# Find Qt5 for Apple and update src_list for windows -if (APPLE) - # homebrew defaults to qt4 and installs qt5 as 'keg-only' - # which places it into /usr/local/opt insteadof /usr/local. - - set(CMAKE_PREFIX_PATH /usr/local/opt/qt5) - include_directories(/usr/local/opt/qt5/include /usr/local/include) -elseif ("${TARGET_PLATFORM}" STREQUAL "w64") - set(SRC_LIST ${SRC_LIST} ../windows/qt_plugin_import.cpp) -elseif (UNIX) - set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ";$ENV{QTDIR}/lib/cmake") -endif () - - -find_package(Qt5Widgets REQUIRED) -find_package(Qt5Gui REQUIRED) -find_package(Qt5Quick REQUIRED) -find_package(Qt5Qml REQUIRED) -find_package(Qt5Network REQUIRED) -qt5_wrap_ui(ui_Main.h Main.ui) -qt5_add_resources(RESOURCE_ADDED Resources.qrc) - -# Set name of binary and add_executable() -if (APPLE) - set(EXECUTEABLE Walleth) - set(CMAKE_INSTALL_PREFIX ./) - set(BIN_INSTALL_DIR ".") - set(DOC_INSTALL_DIR ".") - - set(PROJECT_VERSION "${ETH_VERSION}") - set(MACOSX_BUNDLE_INFO_STRING "${PROJECT_NAME} ${PROJECT_VERSION}") - set(MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_NAME} ${PROJECT_VERSION}") - set(MACOSX_BUNDLE_LONG_VERSION_STRING "${PROJECT_NAME} ${PROJECT_VERSION}") - set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION}") - set(MACOSX_BUNDLE_COPYRIGHT "${PROJECT_COPYRIGHT_YEAR} ${PROJECT_VENDOR}") - set(MACOSX_BUNDLE_GUI_IDENTIFIER "${PROJECT_DOMAIN_SECOND}.${PROJECT_DOMAIN_FIRST}") - set(MACOSX_BUNDLE_BUNDLE_NAME ${EXECUTEABLE}) - include(BundleUtilities) - - add_executable(${EXECUTEABLE} MACOSX_BUNDLE Main.ui ${RESOURCE_ADDED} ${SRC_LIST}) -else () - set(EXECUTEABLE walleth) - add_executable(${EXECUTEABLE} Main.ui ${RESOURCE_ADDED} ${SRC_LIST}) -endif () - -qt5_use_modules(${EXECUTEABLE} Core Gui Widgets Network Quick Qml) -target_link_libraries(${EXECUTEABLE} qethereum ethereum secp256k1) - -if (APPLE) - if (${ADDFRAMEWORKS}) - set_target_properties(${EXECUTEABLE} PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/EthereumMacOSXBundleInfo.plist.in") - endif () - - SET_SOURCE_FILES_PROPERTIES(${EXECUTEABLE} PROPERTIES MACOSX_PACKAGE_LOCATION MacOS) - - # This is a workaround for when the build-type defaults to Debug, and when a multi-config generator like xcode is used, where the type - # will not be set but defaults to release. - set(generator_lowercase "${CMAKE_GENERATOR}") - string(TOLOWER "${CMAKE_GENERATOR}" generator_lowercase) - if ("${generator_lowercase}" STREQUAL "xcode") - # TODO: Not sure how to resolve this. Possibly \${TARGET_BUILD_DIR} - set(binary_build_dir "${CMAKE_CURRENT_BINARY_DIR}/Debug") - else () - set(binary_build_dir "${CMAKE_CURRENT_BINARY_DIR}") - endif () - - set(APPS ${binary_build_dir}/${EXECUTEABLE}.app) - - # This tool and the next will automatically looked at the linked libraries in order to determine what dependencies are required. Thus, target_link_libaries only needs to add ethereum and secp256k1 (above) - install(CODE " - include(BundleUtilities) - set(BU_CHMOD_BUNDLE_ITEMS 1) - fixup_bundle(\"${APPS}\" \"${BUNDLELIBS}\" \"../libqethereum ../libethereum ../secp256k1\") - " COMPONENT RUNTIME ) - - if (${ADDFRAMEWORKS}) - add_custom_target(addframeworks ALL - COMMAND /usr/local/opt/qt5/bin/macdeployqt ${binary_build_dir}/${EXECUTEABLE}.app - WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - DEPENDS ${PROJECT_NAME} - ) - endif () - -else () - install( TARGETS ${EXECUTEABLE} RUNTIME DESTINATION bin ) -endif () - diff --git a/walleth/EthereumMacOSXBundleInfo.plist.in b/walleth/EthereumMacOSXBundleInfo.plist.in deleted file mode 100644 index 684ad7908..000000000 --- a/walleth/EthereumMacOSXBundleInfo.plist.in +++ /dev/null @@ -1,38 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleExecutable - ${MACOSX_BUNDLE_EXECUTABLE_NAME} - CFBundleGetInfoString - ${MACOSX_BUNDLE_INFO_STRING} - CFBundleIconFile - ${MACOSX_BUNDLE_ICON_FILE} - CFBundleIdentifier - ${MACOSX_BUNDLE_GUI_IDENTIFIER} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleLongVersionString - ${MACOSX_BUNDLE_LONG_VERSION_STRING} - CFBundleName - ${MACOSX_BUNDLE_BUNDLE_NAME} - CFBundlePackageType - APPL - CFBundleShortVersionString - ${MACOSX_BUNDLE_SHORT_VERSION_STRING} - CFBundleSignature - ???? - CFBundleVersion - ${MACOSX_BUNDLE_BUNDLE_VERSION} - CSResourcesFileMapped - - LSRequiresCarbon - - NSHumanReadableCopyright - ${MACOSX_BUNDLE_COPYRIGHT} - NSHighResolutionCapable - - - diff --git a/walleth/Main.ui b/walleth/Main.ui deleted file mode 100644 index 6904590a8..000000000 --- a/walleth/Main.ui +++ /dev/null @@ -1,168 +0,0 @@ - - - Main - - - - 0 - 0 - 562 - 488 - - - - Walleth - - - true - - - QMainWindow::AllowNestedDocks|QMainWindow::AllowTabbedDocks|QMainWindow::VerticalTabs - - - true - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - 0 wei - - - - - - - 0 peers - - - - - - - 1 block - - - - - - - - - - - 0 - 0 - 562 - 20 - - - - - &File - - - - - - &Network - - - - - - - - T&ools - - - - - - - - &Help - - - - - - - - - - - - &Quit - - - - - true - - - true - - - Use &UPnP - - - - - &Connect to Peer... - - - - - true - - - Enable &Network - - - - - true - - - &Mine - - - - - &New Address - - - - - &About... - - - - - true - - - &Preview - - - - - - - diff --git a/walleth/MainWin.cpp b/walleth/MainWin.cpp deleted file mode 100644 index f56cad65d..000000000 --- a/walleth/MainWin.cpp +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -//#include -//#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "BuildInfo.h" -#include "MainWin.h" -#include "ui_Main.h" -using namespace std; - -// types -using dev::bytes; -using dev::bytesConstRef; -using dev::h160; -using dev::h256; -using dev::u160; -using dev::u256; -using dev::u256s; -using dev::Address; -using dev::eth::BlockInfo; -using dev::eth::Client; -using dev::eth::Instruction; -using dev::KeyPair; -using dev::eth::NodeMode; -using dev::p2p::PeerInfo; -using dev::RLP; -using dev::Secret; -using dev::eth::Transaction; - -// functions -using dev::toHex; -using dev::fromHex; -using dev::right160; -using dev::simpleDebugOut; -using dev::toLog2; -using dev::toString; -using dev::eth::units; -using dev::eth::disassemble; -using dev::eth::formatBalance; - -// vars -using dev::g_logPost; -using dev::g_logVerbosity; - -Main::Main(QWidget *parent) : - QMainWindow(parent), - ui(new Ui::Main) -{ - setWindowFlags(Qt::Window); - ui->setupUi(this); - setWindowIcon(QIcon(":/Ethereum.png")); - - g_qmlMain = this; - - m_client.reset(new Client("Walleth", Address(), dev::getDataDir() + "/Walleth")); - - g_qmlClient = m_client.get(); - - qRegisterMetaType("dev::u256"); - qRegisterMetaType("dev::KeyPair"); - qRegisterMetaType("dev::Secret"); - qRegisterMetaType("dev::Address"); - qRegisterMetaType("QmlAccount*"); - qRegisterMetaType("QmlEthereum*"); - - qmlRegisterType("org.ethereum", 1, 0, "Ethereum"); - qmlRegisterType("org.ethereum", 1, 0, "Account"); - qmlRegisterSingletonType("org.ethereum", 1, 0, "Balance", QmlEthereum::constructU256Helper); - qmlRegisterSingletonType("org.ethereum", 1, 0, "Key", QmlEthereum::constructKeyHelper); - - /* - ui->librariesView->setModel(m_libraryMan); - ui->graphsView->setModel(m_graphMan); - */ - - m_view = new QQuickView(); - -// QQmlContext* context = m_view->rootContext(); -// context->setContextProperty("u256", new U256Helper(this)); - - m_view->setSource(QUrl("qrc:/Simple.qml")); - - QWidget* w = QWidget::createWindowContainer(m_view); - m_view->setResizeMode(QQuickView::SizeRootObjectToView); - ui->fullDisplay->insertWidget(0, w); - m_view->create(); - -// m_timelinesItem = m_view->rootObject()->findChild("timelines"); - - readSettings(); - refresh(); - - m_refreshNetwork = new QTimer(this); - connect(m_refreshNetwork, SIGNAL(timeout()), SLOT(refreshNetwork())); - m_refreshNetwork->start(1000); - - connect(&m_webCtrl, &QNetworkAccessManager::finished, [&](QNetworkReply* _r) - { - m_servers = QString::fromUtf8(_r->readAll()).split("\n", QString::SkipEmptyParts); - if (m_servers.size()) - { - ui->net->setChecked(true); - on_net_triggered(true); - } - }); - QNetworkRequest r(QUrl("http://www.ethereum.org/servers.poc" + QString(dev::Version).section('.', 1, 1) + ".txt")); - r.setHeader(QNetworkRequest::UserAgentHeader, "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1712.0 Safari/537.36"); - m_webCtrl.get(r); - srand(time(0)); - - startTimer(200); - - statusBar()->addPermanentWidget(ui->balance); - statusBar()->addPermanentWidget(ui->peerCount); - statusBar()->addPermanentWidget(ui->blockCount); -} - -Main::~Main() -{ - writeSettings(); -} - -void Main::timerEvent(QTimerEvent *) -{ - -} - -void Main::on_about_triggered() -{ - QMessageBox::about(this, "About Walleth PoC-" + QString(dev::Version).section('.', 1, 1), QString("Walleth/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM) "\n" DEV_QUOTED(ETH_COMMIT_HASH) + (ETH_CLEAN_REPO ? "\nCLEAN" : "\n+ LOCAL CHANGES") + "\n\nBy Gav Wood, 2014.\nBased on a design by Vitalik Buterin.\n\nThanks to the various contributors including: Alex Leverington, Tim Hughes, caktux, Eric Lombrozo, Marko Simovic."); -} - -void Main::writeSettings() -{ - QSettings s("ethereum", "walleth"); - QByteArray b; - b.resize(sizeof(Secret) * m_myKeys.size()); - auto p = b.data(); - for (auto i: m_myKeys) - { - memcpy(p, &(i.secret()), sizeof(Secret)); - p += sizeof(Secret); - } - s.setValue("address", b); - - s.setValue("upnp", ui->upnp->isChecked()); - s.setValue("clientName", m_clientName); - s.setValue("idealPeers", m_idealPeers); - s.setValue("port", m_port); - - bytes d = client()->savePeers(); - if (d.size()) - m_peers = QByteArray((char*)d.data(), (int)d.size()); - s.setValue("peers", m_peers); - - s.setValue("geometry", saveGeometry()); - s.setValue("windowState", saveState()); -} - -void Main::readSettings() -{ - QSettings s("ethereum", "walleth"); - - restoreGeometry(s.value("geometry").toByteArray()); - restoreState(s.value("windowState").toByteArray()); - - QByteArray b = s.value("address").toByteArray(); - if (b.isEmpty()) - m_myKeys.append(KeyPair::create()); - else - { - h256 k; - for (unsigned i = 0; i < b.size() / sizeof(Secret); ++i) - { - memcpy(&k, b.data() + i * sizeof(Secret), sizeof(Secret)); - m_myKeys.append(KeyPair(k)); - } - } - //m_eth->setAddress(m_myKeys.last().address()); - m_peers = s.value("peers").toByteArray(); - ui->upnp->setChecked(s.value("upnp", true).toBool()); - m_clientName = s.value("clientName", "").toString(); - m_idealPeers = s.value("idealPeers", 5).toInt(); - m_port = s.value("port", 30303).toInt(); -} - -void Main::refreshNetwork() -{ - auto ps = client()->peers(); - ui->peerCount->setText(QString::fromStdString(toString(ps.size())) + " peer(s)"); -} - -void Main::refresh() -{ - auto d = client()->blockChain().details(); - auto diff = BlockInfo(client()->blockChain().block()).difficulty; - ui->blockCount->setText(QString("#%1 @%3 T%2").arg(d.number).arg(toLog2(d.totalDifficulty)).arg(toLog2(diff))); - - m_keysChanged = false; - u256 totalBalance = 0; - for (auto i: m_myKeys) - { - u256 b = m_client->balanceAt(i.address()); - totalBalance += b; - } - ui->balance->setText(QString::fromStdString(formatBalance(totalBalance))); -} - -void Main::on_net_triggered(bool _auto) -{ - string n = string("Walleth/v") + dev::Version; - if (m_clientName.size()) - n += "/" + m_clientName.toStdString(); - n += "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM); - client()->setClientVersion(n); - if (ui->net->isChecked()) - { - if (_auto) - { - QString s = m_servers[rand() % m_servers.size()]; - client()->startNetwork(m_port, s.section(':', 0, 0).toStdString(), s.section(':', 1).toInt(), NodeMode::Full, m_idealPeers, "", ui->upnp->isChecked()); - } - else - client()->startNetwork(m_port, string(), 0, NodeMode::Full, m_idealPeers, "", ui->upnp->isChecked()); - if (m_peers.size()) - client()->restorePeers(bytesConstRef((byte*)m_peers.data(), m_peers.size())); - } - else - client()->stopNetwork(); -} - -void Main::on_connect_triggered() -{ - if (!ui->net->isChecked()) - { - ui->net->setChecked(true); - on_net_triggered(); - } - bool ok = false; - QString s = QInputDialog::getItem(this, "Connect to a Network Peer", "Enter a peer to which a connection may be made:", m_servers, m_servers.count() ? rand() % m_servers.count() : 0, true, &ok); - if (ok && s.contains(":")) - { - string host = s.section(":", 0, 0).toStdString(); - unsigned short port = s.section(":", 1).toInt(); - client()->connect(host, port); - } -} - -void Main::on_mine_triggered() -{ - if (ui->mine->isChecked()) - { - client()->setAddress(m_myKeys.last().address()); - client()->startMining(); - } - else - client()->stopMining(); -} - -void Main::on_create_triggered() -{ - m_myKeys.append(KeyPair::create()); - m_keysChanged = true; -} - -// extra bits needed to link on VS -#ifdef _MSC_VER - -// include moc file, ofuscated to hide from automoc -#include\ -"moc_MainWin.cpp" - -// include qrc content -#include\ -"qrc_Resources.cpp" - -#endif diff --git a/walleth/MainWin.h b/walleth/MainWin.h deleted file mode 100644 index 860db8bc9..000000000 --- a/walleth/MainWin.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef MAIN_H -#define MAIN_H - -#include -#include -#include -#include -#include -#include - -namespace Ui { -class Main; -} - -namespace dev { namespace eth { -class Client; -class State; -}} - -class QQuickView; -class QQmlEngine; -class QJSEngine; - -class Main : public QMainWindow -{ - Q_OBJECT - -public: - explicit Main(QWidget *parent = 0); - ~Main(); - - dev::eth::Client* client() const { return m_client.get(); } - -private slots: - void on_connect_triggered(); - void on_mine_triggered(); - void on_create_triggered(); - void on_net_triggered(bool _auto = false); - void on_about_triggered(); - void on_preview_triggered() { refresh(); } - void on_quit_triggered() { close(); } - - void refresh(); - void refreshNetwork(); - -protected: - virtual void timerEvent(QTimerEvent *); - -private: -/* QString pretty(dev::Address _a) const; - QString render(dev::Address _a) const; - dev::Address fromString(QString const& _a) const; -*/ - dev::eth::State const& state() const; - - void updateFee(); - void readSettings(); - void writeSettings(); - - dev::u256 fee() const; - dev::u256 total() const; - dev::u256 value() const; - - std::unique_ptr ui; - - QByteArray m_peers; - QMutex m_guiLock; - QTimer* m_refresh; - QTimer* m_refreshNetwork; - QVector m_myKeys; - bool m_keysChanged = false; - int m_port; - int m_idealPeers; - QString m_clientName; - QStringList m_servers; - - QQuickView* m_view; - - QNetworkAccessManager m_webCtrl; - - std::unique_ptr m_client; -}; - -#endif // MAIN_H diff --git a/walleth/Resources.qrc b/walleth/Resources.qrc deleted file mode 100644 index 1789216ed..000000000 --- a/walleth/Resources.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - Simple.qml - - diff --git a/walleth/Simple.qml b/walleth/Simple.qml deleted file mode 100644 index 53cb7def4..000000000 --- a/walleth/Simple.qml +++ /dev/null @@ -1,38 +0,0 @@ -import QtQml 2.2 -import QtQuick 2.1 -import QtQuick.Controls 1.0 -import QtQuick.Layouts 1.0 -import Qt.labs.settings 1.0 -import org.ethereum 1.0 - -Item { - id: main - anchors.fill: parent - anchors.margins: 9 - -// Qt.application.name: "Walleth" -// Qt.application.organization: "Ethereum" -// Qt.application.domain: "org.ethereum" - - Ethereum { - id: eth - } - - Account { - id: myAccount - address: Key.addressOf("84fc4ba9373c30bfe32d8c5a502854e7f1175878") - ethereum: eth - // TODO: state: eth.latest // could be eth.pending - // will provide balance, txCount, isContract, incomingTransactions (list model), outgoingTransactions (list model). - // transaction lists' items will provide value, from, to, final balance. - } - - // KeyPair provides makeTransaction(recvAddress, value, data (array)) - - Text { - text: "Balance: " + Balance.stringOf(myAccount.balance) + " [" + myAccount.txCount + "]" + "\nAccount: " + Key.stringOf(myAccount.address) - Layout.minimumHeight: 30 - Layout.fillHeight: true - Layout.fillWidth: true - } -} diff --git a/walleth/main.cpp b/walleth/main.cpp deleted file mode 100644 index 42afd5e66..000000000 --- a/walleth/main.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "MainWin.h" -#include - -int main(int argc, char *argv[]) -{ - QApplication a(argc, argv); - Main w; - w.show(); - - return a.exec(); -} From c14cb82acd78d366cf2de0263fd473254ad3b032 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Fri, 12 Dec 2014 12:50:57 +0100 Subject: [PATCH 484/641] removed LANGUAGES command line option --- CMakeLists.txt | 59 +++++++++++++++++--------------------- libdevcrypto/TrieDB.cpp | 4 --- libethcore/BlockInfo.cpp | 4 --- libethcore/ProofOfWork.cpp | 3 -- 4 files changed, 26 insertions(+), 44 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d6bf59636..98da62bdc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,6 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") # Normally, set(...CACHE...) creates cache variables, but does not modify them. function(createDefaultCacheConfig) set(HEADLESS OFF CACHE BOOL "Do not compile GUI (AlethZero)") - set(LANGUAGES OFF CACHE BOOL "Limit build to Serpent/LLL tools") set(VMTRACE OFF CACHE BOOL "VM tracing and run-time checks (useful for cross-implementation VM debugging)") set(PARANOIA OFF CACHE BOOL "Additional run-time checks") set(JSONRPC ON CACHE BOOL "Build with jsonprc. default on") @@ -24,10 +23,6 @@ endfunction() # propagates CMake configuration options to the compiler function(configureProject) - if (LANGUAGES) - add_definitions(-DETH_LANGUAGES) - endif () - if (PARANOIA) if ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") add_definitions(-DETH_PARANOIA) @@ -89,7 +84,7 @@ cmake_policy(SET CMP0015 NEW) createDefaultCacheConfig() configureProject() -message("-- LANGUAGES: ${LANGUAGES}; VMTRACE: ${VMTRACE}; PARANOIA: ${PARANOIA}; HEADLESS: ${HEADLESS}; JSONRPC: ${JSONRPC}") +message("-- VMTRACE: ${VMTRACE}; PARANOIA: ${PARANOIA}; HEADLESS: ${HEADLESS}; JSONRPC: ${JSONRPC}") # Default TARGET_PLATFORM to "linux". @@ -125,40 +120,38 @@ if (JSONRPC) add_subdirectory(libweb3jsonrpc) endif() -if (NOT LANGUAGES) - add_subdirectory(secp256k1) - add_subdirectory(libp2p) - add_subdirectory(libdevcrypto) - add_subdirectory(libwhisper) +add_subdirectory(secp256k1) +add_subdirectory(libp2p) +add_subdirectory(libdevcrypto) +add_subdirectory(libwhisper) - add_subdirectory(libethcore) - add_subdirectory(libevm) - add_subdirectory(libethereum) +add_subdirectory(libethcore) +add_subdirectory(libevm) +add_subdirectory(libethereum) # TODO is this 'TODO remove' still valid? # add_subdirectory(libethereumx) # TODO remove - add_subdirectory(libwebthree) - add_subdirectory(test) - add_subdirectory(eth) - if("x${CMAKE_BUILD_TYPE}" STREQUAL "xDebug") - add_subdirectory(exp) - endif () +add_subdirectory(libwebthree) +add_subdirectory(test) +add_subdirectory(eth) +if("x${CMAKE_BUILD_TYPE}" STREQUAL "xDebug") + add_subdirectory(exp) +endif () - # TODO check msvc - if(NOT ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")) - add_subdirectory(neth) - endif () +# TODO check msvc +if(NOT ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")) + add_subdirectory(neth) +endif () - if (NOT HEADLESS) - - add_subdirectory(libjsqrc) - add_subdirectory(libqethereum) - add_subdirectory(alethzero) - add_subdirectory(third) - add_subdirectory(mix) - - endif() +if (NOT HEADLESS) + + add_subdirectory(libjsqrc) + add_subdirectory(libqethereum) + add_subdirectory(alethzero) + add_subdirectory(third) + add_subdirectory(mix) + endif() enable_testing() diff --git a/libdevcrypto/TrieDB.cpp b/libdevcrypto/TrieDB.cpp index 674f21aa4..6f476c14b 100644 --- a/libdevcrypto/TrieDB.cpp +++ b/libdevcrypto/TrieDB.cpp @@ -24,9 +24,5 @@ using namespace std; using namespace dev; -#if !ETH_LANGUAGES - h256 const dev::c_shaNull = sha3(rlp("")); h256 const dev::EmptyTrie = c_shaNull; - -#endif diff --git a/libethcore/BlockInfo.cpp b/libethcore/BlockInfo.cpp index fbf056867..bf973b565 100644 --- a/libethcore/BlockInfo.cpp +++ b/libethcore/BlockInfo.cpp @@ -19,8 +19,6 @@ * @date 2014 */ -#if !ETH_LANGUAGES - #include #include #include @@ -197,5 +195,3 @@ void BlockInfo::verifyParent(BlockInfo const& _parent) const BOOST_THROW_EXCEPTION(InvalidNumber()); } } - -#endif diff --git a/libethcore/ProofOfWork.cpp b/libethcore/ProofOfWork.cpp index bfb8942cc..181e379b5 100644 --- a/libethcore/ProofOfWork.cpp +++ b/libethcore/ProofOfWork.cpp @@ -19,8 +19,6 @@ * @date 2014 */ -#if !ETH_LANGUAGES - #include #include #include @@ -107,4 +105,3 @@ h256 DaggerEvaluator::eval(h256 const& _root, h256 const& _nonce) } } -#endif From 15c78c848cccdd7db787216b3f001cb0ced903c1 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Fri, 12 Dec 2014 13:13:29 +0100 Subject: [PATCH 485/641] jsonrpc _library -> _libraries --- cmake/FindJsonRpcCpp.cmake | 15 +++++++-------- libqethereum/CMakeLists.txt | 3 +-- libweb3jsonrpc/CMakeLists.txt | 3 +-- test/CMakeLists.txt | 8 ++++---- 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/cmake/FindJsonRpcCpp.cmake b/cmake/FindJsonRpcCpp.cmake index 221180337..eecf518f8 100644 --- a/cmake/FindJsonRpcCpp.cmake +++ b/cmake/FindJsonRpcCpp.cmake @@ -7,6 +7,8 @@ # This module defines # JSON_RCP_CPP_INCLUDE_DIRS, where to find header, etc. # JSON_RCP_CPP_LIBRARIES, the libraries needed to use json-rpc-cpp. +# JSON_RPC_CPP_SERVER_LIBRARIES, the libraries needed to use json-rpc-cpp-server +# JSON_RPC_CPP_CLIENT_LIBRARIES, the libraries needed to use json-rpc-cpp-client # JSON_RCP_CPP_FOUND, If false, do not try to use json-rpc-cpp. # only look in default directories @@ -35,8 +37,11 @@ find_library( DOC "json-rpc-cpp client library" ) -# message (" - json-rcp-cpp header : ${JSON_RPC_CPP_INCLUDE_DIRS}") -# message (" - json-rcp-cpp lib : ${JSON_RPC_CPP_LIBRARIES}") +# these are the variables to be uses by the calling script +set (JSON_RPC_CPP_INCLUDE_DIRS ${JSON_RPC_CPP_INCLUDE_DIR}) +set (JSON_RPC_CPP_LIBRARIES ${JSON_RPC_CPP_COMMON_LIBRARY} ${JSON_RPC_CPP_SERVER_LIBRARY} ${JSON_RPC_CPP_CLIENT_LIBRARY}) +set (JSON_RPC_CPP_SERVER_LIBRARIES ${JSON_RPC_CPP_COMMON_LIBRARY} ${JSON_RPC_CPP_SERVER_LIBRARY}) +set (JSON_RPC_CPP_CLIENT_LIBRARIES ${JSON_RPC_CPP_COMMON_LIBRARY} ${JSON_RPC_CPP_CLIENT_LIBRARY}) # handle the QUIETLY and REQUIRED arguments and set JSON_RPC_CPP_FOUND to TRUE # if all listed variables are TRUE, hide their existence from configuration view @@ -45,9 +50,3 @@ find_package_handle_standard_args(json_rpc_cpp DEFAULT_MSG JSON_RPC_CPP_COMMON_LIBRARY JSON_RPC_CPP_SERVER_LIBRARY JSON_RPC_CPP_CLIENT_LIBRARY JSON_RPC_CPP_INCLUDE_DIR) mark_as_advanced (JSON_RPC_CPP_COMMON_LIBRARY JSON_RPC_CPP_SERVER_LIBRARY JSON_RPC_CPP_CLIENT_LIBRARY JSON_RPC_CPP_INCLUDE_DIR) -# these are the variables to be uses by the calling script -set (JSON_RPC_CPP_INCLUDE_DIRS ${JSON_RPC_CPP_INCLUDE_DIR}) -set (JSON_RPC_CPP_LIBRARIES ${JSON_RPC_CPP_COMMON_LIBRARY} ${JSON_RPC_CPP_SERVER_LIBRARY} ${JSON_RPC_CPP_CLIENT_LIBRARY}) - -# message (" - json-rcp-cpp header : ${JSON_RPC_CPP_INCLUDE_DIRS}") -# message (" - json-rcp-cpp lib : ${JSON_RPC_CPP_LIBRARIES}") diff --git a/libqethereum/CMakeLists.txt b/libqethereum/CMakeLists.txt index e2c8f9a05..683bfec56 100644 --- a/libqethereum/CMakeLists.txt +++ b/libqethereum/CMakeLists.txt @@ -33,8 +33,7 @@ target_link_libraries(${EXECUTABLE} Qt5::Widgets) target_link_libraries(${EXECUTABLE} Qt5::Network) target_link_libraries(${EXECUTABLE} Qt5::Quick) target_link_libraries(${EXECUTABLE} Qt5::Qml) -target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_COMMON_LIBRARY}) -target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_SERVER_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_SERVER_LIBRARIES}) target_link_libraries(${EXECUTABLE} ethereum) target_link_libraries(${EXECUTABLE} secp256k1) diff --git a/libweb3jsonrpc/CMakeLists.txt b/libweb3jsonrpc/CMakeLists.txt index 9a0771ef7..5068ede56 100644 --- a/libweb3jsonrpc/CMakeLists.txt +++ b/libweb3jsonrpc/CMakeLists.txt @@ -25,8 +25,7 @@ endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) -target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_COMMON_LIBRARY}) -target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_SERVER_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_SERVER_LIBRARIES}) if (MINIUPNPC_FOUND) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARIES}) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 73003e805..7e618f7ea 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -12,19 +12,19 @@ file(GLOB HEADERS "*.h") add_executable(testeth ${SRC_LIST} ${HEADERS}) add_executable(createRandomTest createRandomTest.cpp vm.cpp TestHelper.cpp) +target_link_libraries(testeth ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY_RELEASE}) +target_link_libraries(testeth ${CURL_LIBRARIES}) target_link_libraries(testeth ethereum) target_link_libraries(testeth ethcore) target_link_libraries(testeth secp256k1) target_link_libraries(testeth solidity) target_link_libraries(testeth webthree) -target_link_libraries(testeth ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY_RELEASE}) -target_link_libraries(testeth ${CURL_LIBRARIES}) if (JSONRPC) target_link_libraries(testeth web3jsonrpc) - target_link_libraries(testeth ${JSON_RPC_CPP_CLIENT_LIBRARY}) + target_link_libraries(testeth ${JSON_RPC_CPP_CLIENT_LIBRARIES}) endif() +target_link_libraries(createRandomTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY_RELEASE}) target_link_libraries(createRandomTest ethereum) target_link_libraries(createRandomTest ethcore) -target_link_libraries(createRandomTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY_RELEASE}) From 4da294f86d984efb60293a979b703722f2785e9a Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 12 Dec 2014 14:01:26 +0100 Subject: [PATCH 486/641] - CommonJS => fromString(string _sn) fromString(string const& _sn). - Wrapping string with QApplication::tr(), used for localization. --- libdevcore/CommonJS.cpp | 7 +------ libdevcore/CommonJS.h | 2 +- mix/AssemblyDebuggerCtrl.cpp | 5 ++--- mix/AssemblyDebuggerModel.cpp | 3 ++- mix/ConstantCompilationCtrl.cpp | 6 +++--- mix/ConstantCompilationModel.cpp | 3 ++- mix/KeyEventManager.cpp | 2 -- 7 files changed, 11 insertions(+), 17 deletions(-) diff --git a/libdevcore/CommonJS.cpp b/libdevcore/CommonJS.cpp index 9dc04b7e7..ad3ade71f 100644 --- a/libdevcore/CommonJS.cpp +++ b/libdevcore/CommonJS.cpp @@ -105,13 +105,8 @@ std::string fromRaw(h256 _n, unsigned* _inc) return ""; } -Address fromString(std::string _sn) +Address fromString(std::string const& _sn) { - if (_sn.size() > 32) - _sn.resize(32); - h256 n; - memcpy(n.data(), _sn.data(), _sn.size()); - memset(n.data() + _sn.size(), 0, 32 - _sn.size()); if (_sn.size() == 40) return Address(fromHex(_sn)); else diff --git a/libdevcore/CommonJS.h b/libdevcore/CommonJS.h index 0fb087f72..8b96b2e68 100644 --- a/libdevcore/CommonJS.h +++ b/libdevcore/CommonJS.h @@ -51,7 +51,7 @@ bytes padded(bytes _b, unsigned _l); bytes unpadded(bytes _s); std::string prettyU256(u256 _n); std::string fromRaw(h256 _n, unsigned* _inc = nullptr); -Address fromString(std::string _a); +Address fromString(std::string const& _a); template FixedHash jsToFixed(std::string const& _s) { diff --git a/mix/AssemblyDebuggerCtrl.cpp b/mix/AssemblyDebuggerCtrl.cpp index 36318ccb7..678f94d77 100644 --- a/mix/AssemblyDebuggerCtrl.cpp +++ b/mix/AssemblyDebuggerCtrl.cpp @@ -47,7 +47,7 @@ QString AssemblyDebuggerCtrl::contentUrl() const QString AssemblyDebuggerCtrl::title() const { - return "debugger"; + return QApplication::tr("debugger"); } void AssemblyDebuggerCtrl::start() const @@ -63,7 +63,6 @@ void AssemblyDebuggerCtrl::keyPressed(int _key) QString code = m_doc->toPlainText(); QtConcurrent::run([this, code]() { - if (!m_modelDebugger->compile(m_doc->toPlainText())) { emit dataAvailable(false, DebuggingStatusResult::Compilationfailed); @@ -101,5 +100,5 @@ void AssemblyDebuggerCtrl::updateGUI(bool success, DebuggingStatusResult reason, this->addContentOn(this); } else - m_ctx->displayMessageDialog("debugger","compilation failed"); + m_ctx->displayMessageDialog(QApplication::tr("debugger"), QApplication::tr("compilation failed")); } diff --git a/mix/AssemblyDebuggerModel.cpp b/mix/AssemblyDebuggerModel.cpp index bcf58835c..ad6ba156d 100644 --- a/mix/AssemblyDebuggerModel.cpp +++ b/mix/AssemblyDebuggerModel.cpp @@ -17,6 +17,7 @@ * used as a model to debug contract assembly code. */ +#include #include "libethereum/Executive.h" #include "libethereum/Transaction.h" #include "libethereum/ExtVM.h" @@ -90,7 +91,7 @@ DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::u2 { DebuggingContent r; r.contentAvailable = false; - r.message = "compile failed"; + r.message = QApplication::tr("compilation failed"); return r; } diff --git a/mix/ConstantCompilationCtrl.cpp b/mix/ConstantCompilationCtrl.cpp index 8b0577d93..3ccd87f77 100644 --- a/mix/ConstantCompilationCtrl.cpp +++ b/mix/ConstantCompilationCtrl.cpp @@ -43,7 +43,7 @@ QString ConstantCompilationCtrl::contentUrl() const QString ConstantCompilationCtrl::title() const { - return "compiler"; + return QApplication::tr("compiler"); } void ConstantCompilationCtrl::start() const @@ -80,13 +80,13 @@ void ConstantCompilationCtrl::writeOutPut(CompilerResult const& _res) status->setProperty("text", "succeeded"); status->setProperty("color", "green"); content->setProperty("text", _res.hexCode); - qDebug() << QString("compile succeeded " + _res.hexCode); + qDebug() << QString(QApplication::tr("compile succeeded") + " " + _res.hexCode); } else { status->setProperty("text", "failure"); status->setProperty("color", "red"); content->setProperty("text", _res.comment); - qDebug() << QString("compile failed " + _res.comment); + qDebug() << QString(QApplication::tr("compile failed") + " " + _res.comment); } } diff --git a/mix/ConstantCompilationModel.cpp b/mix/ConstantCompilationModel.cpp index f50ac805b..817d01635 100644 --- a/mix/ConstantCompilationModel.cpp +++ b/mix/ConstantCompilationModel.cpp @@ -20,6 +20,7 @@ * Ethereum IDE client. */ +#include #include #include #include @@ -55,7 +56,7 @@ CompilerResult ConstantCompilationModel::compile(QString _code) catch (...) { res.success = false; - res.comment = "Uncaught exception."; + res.comment = QApplication::tr("Uncaught exception."); res.hexCode = ""; } return res; diff --git a/mix/KeyEventManager.cpp b/mix/KeyEventManager.cpp index f5d638869..c32caadb8 100644 --- a/mix/KeyEventManager.cpp +++ b/mix/KeyEventManager.cpp @@ -39,5 +39,3 @@ void KeyEventManager::keyPressed(QVariant _event) { emit onKeyPressed(_event.toInt()); } - - From e113ce92dd5fe94330586d0abb8ba16435aa0923 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Fri, 12 Dec 2014 14:04:53 +0100 Subject: [PATCH 487/641] removed unused libs/includes from libethcore --- libethcore/All.h | 7 ------- libethcore/CMakeLists.txt | 5 +---- 2 files changed, 1 insertion(+), 11 deletions(-) delete mode 100644 libethcore/All.h diff --git a/libethcore/All.h b/libethcore/All.h deleted file mode 100644 index cb1d3f5a3..000000000 --- a/libethcore/All.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include "BlockInfo.h" -#include "CommonEth.h" -#include "ProofOfWork.h" -#include "Exceptions.h" - diff --git a/libethcore/CMakeLists.txt b/libethcore/CMakeLists.txt index 960936b3a..984aa3ce5 100644 --- a/libethcore/CMakeLists.txt +++ b/libethcore/CMakeLists.txt @@ -9,8 +9,7 @@ set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) -include_directories(${CRYPTOPP_INCLUDE_DIRS}) -include_directories(${LEVELDB_INCLUDE_DIRS}) +include_directories(${Boost_INCLUDE_DIRS}) include_directories(..) set(EXECUTABLE ethcore) @@ -23,10 +22,8 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} devcore) -target_link_libraries(${EXECUTABLE} secp256k1) install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) From 0f00ede521613776811c956573a3252dfccf13ca Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Fri, 12 Dec 2014 14:25:55 +0100 Subject: [PATCH 488/641] removed unused libs/includes from libdevcrypto --- libdevcrypto/All.h | 8 -------- libdevcrypto/CMakeLists.txt | 2 +- libethcore/CommonEth.cpp | 1 - 3 files changed, 1 insertion(+), 10 deletions(-) delete mode 100644 libdevcrypto/All.h diff --git a/libdevcrypto/All.h b/libdevcrypto/All.h deleted file mode 100644 index 9070725e9..000000000 --- a/libdevcrypto/All.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include "Common.h" -#include "AES.h" -#include "ECDHE.h" -#include "FileSystem.h" -#include "SHA3.h" -#include "TrieDB.h" diff --git a/libdevcrypto/CMakeLists.txt b/libdevcrypto/CMakeLists.txt index 354053483..c0fa56026 100644 --- a/libdevcrypto/CMakeLists.txt +++ b/libdevcrypto/CMakeLists.txt @@ -9,6 +9,7 @@ set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) +include_directories(${Boost_INCLUDE_DIRS}) include_directories(${CRYPTOPP_INCLUDE_DIRS}) include_directories(${LEVELDB_INCLUDE_DIRS}) include_directories(..) @@ -26,7 +27,6 @@ target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARY_RELEASE}) target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LIBRARIES}) target_link_libraries(${EXECUTABLE} devcore) -target_link_libraries(${EXECUTABLE} secp256k1) install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libethcore/CommonEth.cpp b/libethcore/CommonEth.cpp index 36726dae4..5e510572e 100644 --- a/libethcore/CommonEth.cpp +++ b/libethcore/CommonEth.cpp @@ -21,7 +21,6 @@ #include "CommonEth.h" #include -#include #include #include "Exceptions.h" using namespace std; From 70f3e2be09161e49081b80a4581f7ea2b8021f09 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Fri, 12 Dec 2014 14:34:11 +0100 Subject: [PATCH 489/641] removed unused libs/includes from libevm --- libdevcore/All.h | 8 -------- libevm/CMakeLists.txt | 8 -------- 2 files changed, 16 deletions(-) delete mode 100644 libdevcore/All.h diff --git a/libdevcore/All.h b/libdevcore/All.h deleted file mode 100644 index eac152d42..000000000 --- a/libdevcore/All.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include "Common.h" -#include "CommonData.h" -#include "CommonIO.h" -#include "FixedHash.h" -#include "Log.h" -#include "RLP.h" diff --git a/libevm/CMakeLists.txt b/libevm/CMakeLists.txt index 94f7e5e79..5b7f39323 100644 --- a/libevm/CMakeLists.txt +++ b/libevm/CMakeLists.txt @@ -12,7 +12,6 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) include_directories(..) -include_directories(${LEVELDB_INCLUDE_DIRS}) set(EXECUTABLE evm) @@ -24,17 +23,10 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) - -if (MINIUPNPC_FOUND) - target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARIES}) -endif() - target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} evmcore) target_link_libraries(${EXECUTABLE} devcore) -target_link_libraries(${EXECUTABLE} secp256k1) install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) From 1da073190a2253d4dc0e34d42ec0d799566385e9 Mon Sep 17 00:00:00 2001 From: ethdev Date: Fri, 12 Dec 2014 14:37:42 +0100 Subject: [PATCH 490/641] fixed windows --- libevm/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/libevm/CMakeLists.txt b/libevm/CMakeLists.txt index 5b7f39323..a260b442c 100644 --- a/libevm/CMakeLists.txt +++ b/libevm/CMakeLists.txt @@ -11,6 +11,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) +include_directories(${Boost_INCLUDE_DIRS}) include_directories(..) set(EXECUTABLE evm) From 1fcf85ae0ac4bb825dcd37f10c3f15473417c8d4 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Fri, 12 Dec 2014 14:45:49 +0100 Subject: [PATCH 491/641] removed unnecessary miniupnpc links --- eth/CMakeLists.txt | 4 ---- exp/CMakeLists.txt | 4 ---- libethereum/CMakeLists.txt | 4 ---- libevm/CMakeLists.txt | 2 ++ libp2p/CMakeLists.txt | 8 ++++---- libweb3jsonrpc/CMakeLists.txt | 4 ---- libwebthree/CMakeLists.txt | 4 ---- libwhisper/CMakeLists.txt | 4 ---- neth/CMakeLists.txt | 4 ---- 9 files changed, 6 insertions(+), 32 deletions(-) diff --git a/eth/CMakeLists.txt b/eth/CMakeLists.txt index 9996d1170..739c2991c 100644 --- a/eth/CMakeLists.txt +++ b/eth/CMakeLists.txt @@ -17,10 +17,6 @@ add_dependencies(${EXECUTABLE} BuildInfo.h) target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARY_RELEASE}) target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARY_RELEASE}) -if (MINIUPNPC_FOUND) - target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARIES}) -endif() - if (READLINE_FOUND) target_link_libraries(${EXECUTABLE} ${READLINE_LIBRARIES}) endif() diff --git a/exp/CMakeLists.txt b/exp/CMakeLists.txt index 98eae7baf..49bbbf16b 100644 --- a/exp/CMakeLists.txt +++ b/exp/CMakeLists.txt @@ -12,10 +12,6 @@ add_executable(${EXECUTABLE} ${SRC_LIST}) target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) -if (MINIUPNPC_FOUND) - target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARIES}) -endif() - target_link_libraries(${EXECUTABLE} ethereum) target_link_libraries(${EXECUTABLE} p2p) target_link_libraries(${EXECUTABLE} gmp) diff --git a/libethereum/CMakeLists.txt b/libethereum/CMakeLists.txt index c13f2ba18..792ed0cf1 100644 --- a/libethereum/CMakeLists.txt +++ b/libethereum/CMakeLists.txt @@ -27,10 +27,6 @@ endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARY_RELEASE}) -if (MINIUPNPC_FOUND) - target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARIES}) -endif() - target_link_libraries(${EXECUTABLE} evm) target_link_libraries(${EXECUTABLE} lll) target_link_libraries(${EXECUTABLE} whisper) diff --git a/libevm/CMakeLists.txt b/libevm/CMakeLists.txt index a260b442c..96b8f9ade 100644 --- a/libevm/CMakeLists.txt +++ b/libevm/CMakeLists.txt @@ -11,6 +11,8 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) +# we may not use it in libevm, but one of our dependecies is including boost in header file +# and windows is failing to build without that include_directories(${Boost_INCLUDE_DIRS}) include_directories(..) diff --git a/libp2p/CMakeLists.txt b/libp2p/CMakeLists.txt index c94ebebbd..50ca138f4 100644 --- a/libp2p/CMakeLists.txt +++ b/libp2p/CMakeLists.txt @@ -11,7 +11,10 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) +# we may not use it in libp2p, but one of our dependecies is including leveldb in header file +# and windows is failing to build without that include_directories(${LEVELDB_INCLUDE_DIRS}) +include_directories(${MINIUPNPC_INCLUDE_DIRS}) include_directories(..) set(EXECUTABLE p2p) @@ -24,15 +27,12 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) - -if(MINIUPNPC_FOUND) +if (MINIUPNPC_FOUND) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARIES}) endif() target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} devcore) -target_link_libraries(${EXECUTABLE} secp256k1) install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libweb3jsonrpc/CMakeLists.txt b/libweb3jsonrpc/CMakeLists.txt index 5068ede56..f371024e6 100644 --- a/libweb3jsonrpc/CMakeLists.txt +++ b/libweb3jsonrpc/CMakeLists.txt @@ -27,10 +27,6 @@ target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_SERVER_LIBRARIES}) -if (MINIUPNPC_FOUND) - target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARIES}) -endif() - target_link_libraries(${EXECUTABLE} webthree) target_link_libraries(${EXECUTABLE} secp256k1) target_link_libraries(${EXECUTABLE} solidity) diff --git a/libwebthree/CMakeLists.txt b/libwebthree/CMakeLists.txt index 587d81493..1d8f23918 100644 --- a/libwebthree/CMakeLists.txt +++ b/libwebthree/CMakeLists.txt @@ -26,10 +26,6 @@ endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) -if (MINIUPNPC_FOUND) - target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARIES}) -endif() - target_link_libraries(${EXECUTABLE} ethereum) target_link_libraries(${EXECUTABLE} evm) target_link_libraries(${EXECUTABLE} lll) diff --git a/libwhisper/CMakeLists.txt b/libwhisper/CMakeLists.txt index f51af33b7..79879922e 100644 --- a/libwhisper/CMakeLists.txt +++ b/libwhisper/CMakeLists.txt @@ -26,10 +26,6 @@ endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) -if (MINIUPNPC_FOUND) - target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARIES}) -endif() - target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} devcore) diff --git a/neth/CMakeLists.txt b/neth/CMakeLists.txt index 63619fd84..4db3d2cf4 100644 --- a/neth/CMakeLists.txt +++ b/neth/CMakeLists.txt @@ -14,10 +14,6 @@ add_dependencies(${EXECUTABLE} BuildInfo.h) target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) -if (MINIUPNPC_FOUND) -target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARIES}) -endif() - if (JSONRPC) target_link_libraries(${EXECUTABLE} web3jsonrpc) endif() From 97262fa114d9559b00646dc07c97601518598a04 Mon Sep 17 00:00:00 2001 From: ethdev Date: Fri, 12 Dec 2014 14:52:24 +0100 Subject: [PATCH 492/641] windows fix for previous commit --- libp2p/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libp2p/CMakeLists.txt b/libp2p/CMakeLists.txt index 50ca138f4..6f3f6b712 100644 --- a/libp2p/CMakeLists.txt +++ b/libp2p/CMakeLists.txt @@ -14,7 +14,10 @@ aux_source_directory(. SRC_LIST) # we may not use it in libp2p, but one of our dependecies is including leveldb in header file # and windows is failing to build without that include_directories(${LEVELDB_INCLUDE_DIRS}) -include_directories(${MINIUPNPC_INCLUDE_DIRS}) + +if (MINIUPNPC_FOUND) + include_directories(${MINIUPNPC_INCLUDE_DIRS}) +endif() include_directories(..) set(EXECUTABLE p2p) From 056a19474066f53486afef992879a7e8fee036ce Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Fri, 12 Dec 2014 16:43:42 +0100 Subject: [PATCH 493/641] common changes --- CMakeLists.txt | 3 --- exp/CMakeLists.txt | 3 --- libdevcrypto/CMakeLists.txt | 2 +- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 98da62bdc..02e3a1a05 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -129,9 +129,6 @@ add_subdirectory(libethcore) add_subdirectory(libevm) add_subdirectory(libethereum) -# TODO is this 'TODO remove' still valid? -# add_subdirectory(libethereumx) # TODO remove - add_subdirectory(libwebthree) add_subdirectory(test) add_subdirectory(eth) diff --git a/exp/CMakeLists.txt b/exp/CMakeLists.txt index 49bbbf16b..d0aadc8ae 100644 --- a/exp/CMakeLists.txt +++ b/exp/CMakeLists.txt @@ -10,11 +10,8 @@ set(EXECUTABLE exp) add_executable(${EXECUTABLE} ${SRC_LIST}) -target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) - target_link_libraries(${EXECUTABLE} ethereum) target_link_libraries(${EXECUTABLE} p2p) -target_link_libraries(${EXECUTABLE} gmp) install( TARGETS ${EXECUTABLE} DESTINATION bin) diff --git a/libdevcrypto/CMakeLists.txt b/libdevcrypto/CMakeLists.txt index c0fa56026..20eab916a 100644 --- a/libdevcrypto/CMakeLists.txt +++ b/libdevcrypto/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_policy(SET CMP0015 OLD) +cmake_policy(SET CMP0015 NEW) # this policy was introduced in cmake 3.0 # remove if, once 3.0 will be used on unix if (${CMAKE_MAJOR_VERSION} GREATER 2) From 5e2df7fcbc8ce5a8c9dc0c84f92dcdf3243cd4c0 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Fri, 12 Dec 2014 17:17:05 +0100 Subject: [PATCH 494/641] removed duplicated, unused file --- extdep/compile/configure.bat | 111 ----------------------------------- 1 file changed, 111 deletions(-) delete mode 100644 extdep/compile/configure.bat diff --git a/extdep/compile/configure.bat b/extdep/compile/configure.bat deleted file mode 100644 index bd810938a..000000000 --- a/extdep/compile/configure.bat +++ /dev/null @@ -1,111 +0,0 @@ -::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -:: -:: Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -:: Contact: http://www.qt-project.org/legal -:: -:: This file is part of the tools applications of the Qt Toolkit. -:: -:: $QT_BEGIN_LICENSE:LGPL$ -:: Commercial License Usage -:: Licensees holding valid commercial Qt licenses may use this file in -:: accordance with the commercial license agreement provided with the -:: Software or, alternatively, in accordance with the terms contained in -:: a written agreement between you and Digia. For licensing terms and -:: conditions see http://qt.digia.com/licensing. For further information -:: use the contact form at http://qt.digia.com/contact-us. -:: -:: GNU Lesser General Public License Usage -:: Alternatively, this file may be used under the terms of the GNU Lesser -:: General Public License version 2.1 as published by the Free Software -:: Foundation and appearing in the file LICENSE.LGPL included in the -:: packaging of this file. Please review the following information to -:: ensure the GNU Lesser General Public License version 2.1 requirements -:: will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -:: -:: In addition, as a special exception, Digia gives you certain additional -:: rights. These rights are described in the Digia Qt LGPL Exception -:: version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -:: -:: GNU General Public License Usage -:: Alternatively, this file may be used under the terms of the GNU -:: General Public License version 3.0 as published by the Free Software -:: Foundation and appearing in the file LICENSE.GPL included in the -:: packaging of this file. Please review the following information to -:: ensure the GNU General Public License version 3.0 requirements will be -:: met: http://www.gnu.org/copyleft/gpl.html. -:: -:: -:: $QT_END_LICENSE$ -:: -::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: - -@echo off -set QTSRC=%~dp0 -set QTDIR=%CD% -::if not exist %QTSRC%\.gitignore goto sconf -echo Please wait while bootstrapping configure ... - -for %%C in (cl.exe icl.exe g++.exe perl.exe) do set %%C=%%~$PATH:C - -if "%perl.exe%" == "" ( - echo Perl not found in PATH. Aborting. >&2 - exit /b 1 -) -if not exist mkspecs ( - md mkspecs - if errorlevel 1 goto exit -) -perl %QTSRC%bin\syncqt.pl -minimal -module QtCore -outdir %QTDIR% %QTSRC% -if errorlevel 1 goto exit - -if not exist tools\configure ( - md tools\configure - if errorlevel 1 goto exit -) -cd tools\configure -if errorlevel 1 goto exit - -echo #### Generated by configure.bat - DO NOT EDIT! ####> Makefile -echo/>> Makefile -for /f "tokens=3 usebackq" %%V in (`findstr QT_VERSION_STR %QTSRC%\src\corelib\global\qglobal.h`) do @echo QTVERSION = %%~V>> Makefile -if not "%cl.exe%" == "" ( - echo CXX = cl>>Makefile - echo EXTRA_CXXFLAGS =>>Makefile - rem This must have a trailing space. - echo QTSRC = %QTSRC% >> Makefile - set tmpl=win32 - set make=nmake -) else if not "%icl.exe%" == "" ( - echo CXX = icl>>Makefile - echo EXTRA_CXXFLAGS = /Zc:forScope>>Makefile - rem This must have a trailing space. - echo QTSRC = %QTSRC% >> Makefile - set tmpl=win32 - set make=nmake -) else if not "%g++.exe%" == "" ( - echo CXX = g++>>Makefile - echo EXTRA_CXXFLAGS =>>Makefile - rem This must NOT have a trailing space. - echo QTSRC = %QTSRC:\=/%>> Makefile - set tmpl=mingw - set make=mingw32-make -) else ( - echo No suitable compiler found in PATH. Aborting. >&2 - cd ..\.. - exit /b 1 -) -echo/>> Makefile -type %QTSRC%tools\configure\Makefile.%tmpl% >> Makefile - -%make% -if errorlevel 1 (cd ..\.. & exit /b 1) - -cd ..\.. - -:conf -configure.exe -srcdir %QTSRC% %* -goto exit - -:sconf -%QTSRC%\configure.exe %* -:exit From a2def239d2def75a32728f9e7ab0fe2bf0b3c195 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Fri, 12 Dec 2014 17:20:44 +0100 Subject: [PATCH 495/641] common changes --- libdevcore/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdevcore/CMakeLists.txt b/libdevcore/CMakeLists.txt index cb5f8eb3f..001c568b5 100644 --- a/libdevcore/CMakeLists.txt +++ b/libdevcore/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_policy(SET CMP0015 OLD) +cmake_policy(SET CMP0015 NEW) # this policy was introduced in cmake 3.0 # remove if, once 3.0 will be used on unix if (${CMAKE_MAJOR_VERSION} GREATER 2) From b0af628f11168b00d1f900f96844466dfcdc72f1 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 10 Dec 2014 23:01:40 +0100 Subject: [PATCH 496/641] Calls to bare contracts. --- libsolidity/ExpressionCompiler.cpp | 122 ++++++++++++++++------------- libsolidity/ExpressionCompiler.h | 20 +++++ libsolidity/Types.cpp | 7 ++ libsolidity/Types.h | 3 +- 4 files changed, 95 insertions(+), 57 deletions(-) diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 3beb423de..add5f73be 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -194,7 +194,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) else { FunctionType const& function = dynamic_cast(*_functionCall.getExpression().getType()); - std::vector> arguments = _functionCall.getArguments(); + vector> arguments = _functionCall.getArguments(); if (asserts(arguments.size() == function.getParameterTypes().size())) BOOST_THROW_EXCEPTION(InternalCompilerError()); @@ -227,50 +227,23 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) break; } case Location::EXTERNAL: + case Location::BARE: { - unsigned dataOffset = 1; // reserve one byte for the function index - for (unsigned i = 0; i < arguments.size(); ++i) - { - arguments[i]->accept(*this); - Type const& type = *function.getParameterTypes()[i]; - appendTypeConversion(*arguments[i]->getType(), type); - unsigned const numBytes = type.getCalldataEncodedSize(); - if (numBytes == 0 || numBytes > 32) - BOOST_THROW_EXCEPTION(CompilerError() - << errinfo_sourceLocation(arguments[i]->getLocation()) - << errinfo_comment("Type " + type.toString() + " not yet supported.")); - bool const leftAligned = type.getCategory() == Type::Category::STRING; - CompilerUtils(m_context).storeInMemory(dataOffset, numBytes, leftAligned); - dataOffset += numBytes; - } - //@todo only return the first return value for now - Type const* firstType = function.getReturnParameterTypes().empty() ? nullptr : - function.getReturnParameterTypes().front().get(); - unsigned retSize = firstType ? firstType->getCalldataEncodedSize() : 0; - // CALL arguments: outSize, outOff, inSize, inOff, value, addr, gas (stack top) - m_context << u256(retSize) << u256(0) << u256(dataOffset) << u256(0) << u256(0); - _functionCall.getExpression().accept(*this); // pushes addr and function index - m_context << u256(0) << eth::Instruction::MSTORE8 - << u256(25) << eth::Instruction::GAS << eth::Instruction::SUB - << eth::Instruction::CALL - << eth::Instruction::POP; // @todo do not ignore failure indicator - if (retSize > 0) - { - bool const leftAligned = firstType->getCategory() == Type::Category::STRING; - CompilerUtils(m_context).loadFromMemory(0, retSize, leftAligned); - } + FunctionCallOptions options; + options.bare = function.getLocation() == Location::BARE; + options.obtainAddress = [&]() { _functionCall.getExpression().accept(*this); }; + appendExternalFunctionCall(function, arguments, options); break; } case Location::SEND: - m_context << u256(0) << u256(0) << u256(0) << u256(0); - arguments.front()->accept(*this); - //@todo might not be necessary - appendTypeConversion(*arguments.front()->getType(), *function.getParameterTypes().front(), true); - _functionCall.getExpression().accept(*this); - m_context << u256(25) << eth::Instruction::GAS << eth::Instruction::SUB - << eth::Instruction::CALL - << eth::Instruction::POP; + { + FunctionCallOptions options; + options.bare = true; + options.obtainAddress = [&]() { _functionCall.getExpression().accept(*this); }; + options.obtainValue = [&]() { arguments.front()->accept(*this); }; + appendExternalFunctionCall(FunctionType({}, {}, Location::EXTERNAL), {}, options); break; + } case Location::SUICIDE: arguments.front()->accept(*this); //@todo might not be necessary @@ -292,19 +265,11 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) {Location::SHA256, 2}, {Location::RIPEMD160, 3}}; u256 contractAddress = contractAddresses.find(function.getLocation())->second; - // @todo later, combine this code with external function call - for (unsigned i = 0; i < arguments.size(); ++i) - { - arguments[i]->accept(*this); - appendTypeConversion(*arguments[i]->getType(), *function.getParameterTypes()[i], true); - // @todo move this once we actually use memory - CompilerUtils(m_context).storeInMemory(i * 32); - } - m_context << u256(32) << u256(0) << u256(arguments.size() * 32) << u256(0) << u256(0) - << contractAddress << u256(500) //@todo determine actual gas requirement - << eth::Instruction::CALL - << eth::Instruction::POP; - CompilerUtils(m_context).loadFromMemory(0); + FunctionCallOptions options; + options.bare = true; + options.obtainAddress = [&]() { m_context << contractAddress; }; + options.packDensely = false; + appendExternalFunctionCall(function, arguments, options); break; } default: @@ -326,11 +291,9 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) IntegerType(0, IntegerType::Modifier::ADDRESS), true); m_context << eth::Instruction::BALANCE; } - else if (member == "send") - { + else if (member == "send" || member.substr(0, 4) == "call") appendTypeConversion(*_memberAccess.getExpression().getType(), IntegerType(0, IntegerType::Modifier::ADDRESS), true); - } else BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid member access to integer.")); break; @@ -587,6 +550,53 @@ void ExpressionCompiler::appendHighBitsCleanup(IntegerType const& _typeOnStack) m_context << ((u256(1) << _typeOnStack.getNumBits()) - 1) << eth::Instruction::AND; } +void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functionType, + vector> const& _arguments, + FunctionCallOptions const& _options) +{ + if (asserts(_arguments.size() == _functionType.getParameterTypes().size())) + BOOST_THROW_EXCEPTION(InternalCompilerError()); + + unsigned dataOffset = _options.bare ? 0 : 1; // reserve one byte for the function index + for (unsigned i = 0; i < _arguments.size(); ++i) + { + _arguments[i]->accept(*this); + Type const& type = *_functionType.getParameterTypes()[i]; + appendTypeConversion(*_arguments[i]->getType(), type); + unsigned const numBytes = _options.packDensely ? type.getCalldataEncodedSize() : 32; + if (numBytes == 0 || numBytes > 32) + BOOST_THROW_EXCEPTION(CompilerError() + << errinfo_sourceLocation(_arguments[i]->getLocation()) + << errinfo_comment("Type " + type.toString() + " not yet supported.")); + bool const leftAligned = type.getCategory() == Type::Category::STRING; + CompilerUtils(m_context).storeInMemory(dataOffset, numBytes, leftAligned); + dataOffset += numBytes; + } + //@todo only return the first return value for now + Type const* firstType = _functionType.getReturnParameterTypes().empty() ? nullptr : + _functionType.getReturnParameterTypes().front().get(); + unsigned retSize = firstType ? firstType->getCalldataEncodedSize() : 0; + if (!_options.packDensely && retSize > 0) + retSize = 32; + // CALL arguments: outSize, outOff, inSize, inOff, value, addr, gas (stack top) + m_context << u256(retSize) << u256(0) << u256(dataOffset) << u256(0); + if (_options.obtainValue) + _options.obtainValue(); + else + m_context << u256(0); + _options.obtainAddress(); + if (!_options.bare) + m_context << u256(0) << eth::Instruction::MSTORE8; + m_context << u256(25) << eth::Instruction::GAS << eth::Instruction::SUB + << eth::Instruction::CALL + << eth::Instruction::POP; // @todo do not ignore failure indicator + if (retSize > 0) + { + bool const leftAligned = firstType->getCategory() == Type::Category::STRING; + CompilerUtils(m_context).loadFromMemory(0, retSize, leftAligned); + } +} + ExpressionCompiler::LValue::LValue(CompilerContext& _compilerContext, LValueType _type, Type const& _dataType, unsigned _baseStackOffset): m_context(&_compilerContext), m_type(_type), m_baseStackOffset(_baseStackOffset), diff --git a/libsolidity/ExpressionCompiler.h b/libsolidity/ExpressionCompiler.h index c0b173d46..0bba211ce 100644 --- a/libsolidity/ExpressionCompiler.h +++ b/libsolidity/ExpressionCompiler.h @@ -20,6 +20,7 @@ * Solidity AST to EVM bytecode compiler for expressions. */ +#include #include #include #include @@ -83,6 +84,25 @@ private: //// Appends code that cleans higher-order bits for integer types. void appendHighBitsCleanup(IntegerType const& _typeOnStack); + /// Additional options used in appendExternalFunctionCall. + struct FunctionCallOptions + { + FunctionCallOptions() {} + /// Invoked to copy the address to the stack + std::function obtainAddress; + /// Invoked to copy the ethe value to the stack (if not specified, value is 0). + std::function obtainValue; + /// If true, do not prepend function index to call data + bool bare = false; + /// If false, use calling convention that all arguments and return values are packed as + /// 32 byte values with padding. + bool packDensely = true; + }; + + /// Appends code to call a function of the given type with the given arguments. + void appendExternalFunctionCall(FunctionType const& _functionType, std::vector> const& _arguments, + FunctionCallOptions const& _options = FunctionCallOptions()); + /** * Helper class to store and retrieve lvalues to and from various locations. * All types except STACK store a reference in a slot on the stack, STACK just diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index 00e530c3f..a0a809b9b 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -194,6 +194,11 @@ u256 IntegerType::literalValue(Literal const& _literal) const const MemberList IntegerType::AddressMemberList = MemberList({{"balance", make_shared(256)}, + {"callstring32", make_shared(TypePointers({make_shared(32)}), + TypePointers(), FunctionType::Location::BARE)}, + {"callstring32string32", make_shared(TypePointers({make_shared(32), + make_shared(32)}), + TypePointers(), FunctionType::Location::BARE)}, {"send", make_shared(TypePointers({make_shared(256)}), TypePointers(), FunctionType::Location::SEND)}}); @@ -424,6 +429,8 @@ unsigned FunctionType::getSizeOnStack() const return 1; case Location::EXTERNAL: return 2; + case Location::BARE: + return 1; default: return 0; } diff --git a/libsolidity/Types.h b/libsolidity/Types.h index 8e93bd31d..807e60c74 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -296,8 +296,9 @@ class FunctionType: public Type public: /// The meaning of the value(s) on the stack referencing the function: /// INTERNAL: jump tag, EXTERNAL: contract address + function index, + /// BARE: contract address (non-abi contract call) /// OTHERS: special virtual function, nothing on the stack - enum class Location { INTERNAL, EXTERNAL, SEND, SHA3, SUICIDE, ECRECOVER, SHA256, RIPEMD160 }; + enum class Location { INTERNAL, EXTERNAL, SEND, SHA3, SUICIDE, ECRECOVER, SHA256, RIPEMD160, BARE }; virtual Category getCategory() const override { return Category::FUNCTION; } explicit FunctionType(FunctionDefinition const& _function, bool _isInternal = true); From ebd8f5bfa5d57ea6b5835cee9e921b8a819a6444 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Fri, 12 Dec 2014 17:41:44 +0100 Subject: [PATCH 497/641] 04 changed to 03 --- cmake/EthCompilerSettings.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index 8cf8b51b4..24252cc0b 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -6,7 +6,7 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wno-unknown-pragmas -Wextra -DSHAREDLIB -fPIC") set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DETH_DEBUG") set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG -DETH_RELEASE") - set(CMAKE_CXX_FLAGS_RELEASE "-O4 -DNDEBUG -DETH_RELEASE") + set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -DETH_RELEASE") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -DETH_DEBUG") set(ETH_SHARED 1) @@ -21,7 +21,7 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wno-unknown-pragmas -Wextra -DSHAREDLIB -fPIC") set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DETH_DEBUG") set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG -DETH_RELEASE") - set(CMAKE_CXX_FLAGS_RELEASE "-O4 -DNDEBUG -DETH_RELEASE") + set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -DETH_RELEASE") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -DETH_DEBUG") set(ETH_SHARED 1) From 0305a8480feb7283117a403960a7ac6d05ba02fb Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Fri, 12 Dec 2014 17:52:33 +0100 Subject: [PATCH 498/641] fixed leak in q_webthreeconnector in mainwin --- alethzero/MainWin.cpp | 3 +-- alethzero/MainWin.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 1b26b3dc2..db1b5dd10 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -153,8 +153,7 @@ Main::Main(QWidget *parent) : m_webThree.reset(new WebThreeDirect(string("AlethZero/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir() + "/AlethZero", false, {"eth", "shh"})); - // w3stubserver, on dealloc, deletes m_qwebConnector - m_qwebConnector = new QWebThreeConnector(); // owned by WebThreeStubServer + m_qwebConnector.reset(new QWebThreeConnector()); m_server.reset(new OurWebThreeStubServer(*m_qwebConnector, *web3(), keysAsVector(m_myKeys))); connect(&*m_server, SIGNAL(onNewId(QString)), SLOT(addNewId(QString))); m_server->setIdentities(keysAsVector(owned())); diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index 50b9df413..2582aa23d 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -256,7 +256,7 @@ private: QString m_logHistory; bool m_logChanged = true; - QWebThreeConnector* m_qwebConnector; + std::unique_ptr m_qwebConnector; std::unique_ptr m_server; QWebThree* m_qweb = nullptr; }; From 921d816a29beba5495f4aa229d476ec65250df0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 12 Dec 2014 18:53:57 +0100 Subject: [PATCH 499/641] Update Visual Studio projects --- windows/LibEthereum.vcxproj | 7 ++++--- windows/LibEthereum.vcxproj.filters | 12 ++++++++++++ windows/LibEvmJit.vcxproj | 2 ++ windows/LibEvmJit.vcxproj.filters | 2 ++ 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/windows/LibEthereum.vcxproj b/windows/LibEthereum.vcxproj index 66efe7dc2..b4624f962 100644 --- a/windows/LibEthereum.vcxproj +++ b/windows/LibEthereum.vcxproj @@ -125,7 +125,6 @@ - @@ -146,7 +145,7 @@ true true - + @@ -170,6 +169,7 @@ true true + true true @@ -343,7 +343,6 @@ - @@ -372,6 +371,7 @@ true + @@ -408,6 +408,7 @@ true true + true true diff --git a/windows/LibEthereum.vcxproj.filters b/windows/LibEthereum.vcxproj.filters index 76201d823..e70393706 100644 --- a/windows/LibEthereum.vcxproj.filters +++ b/windows/LibEthereum.vcxproj.filters @@ -198,6 +198,12 @@ + + libevm + + + libp2p + @@ -437,6 +443,12 @@ libevm + + libevm + + + libp2p + diff --git a/windows/LibEvmJit.vcxproj b/windows/LibEvmJit.vcxproj index 077757aab..c3b1f65a7 100644 --- a/windows/LibEvmJit.vcxproj +++ b/windows/LibEvmJit.vcxproj @@ -130,6 +130,7 @@ + @@ -147,6 +148,7 @@ + diff --git a/windows/LibEvmJit.vcxproj.filters b/windows/LibEvmJit.vcxproj.filters index 06f1ed308..88dc8d329 100644 --- a/windows/LibEvmJit.vcxproj.filters +++ b/windows/LibEvmJit.vcxproj.filters @@ -16,6 +16,7 @@ + @@ -35,6 +36,7 @@ + From 2eaed59cd4a003c2f8c2e404893067f3eb73cb9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 12 Dec 2014 18:54:39 +0100 Subject: [PATCH 500/641] Fix dev::contents function on MSVC --- libdevcore/CommonIO.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libdevcore/CommonIO.cpp b/libdevcore/CommonIO.cpp index 8fc4fedb3..ec8ca605c 100644 --- a/libdevcore/CommonIO.cpp +++ b/libdevcore/CommonIO.cpp @@ -65,6 +65,8 @@ bytes dev::contents(std::string const& _file) // get length of file: is.seekg (0, is.end); streamoff length = is.tellg(); + if (length == 0) // return early, MSVC does not like reading 0 bytes + return {}; is.seekg (0, is.beg); bytes ret(length); is.read((char*)ret.data(), length); From 2d70c4df7e539bc40615d2802de8882f90bbdcfb Mon Sep 17 00:00:00 2001 From: winsvega Date: Sat, 13 Dec 2014 18:55:25 +0300 Subject: [PATCH 501/641] Init code test filler --- test/stInitCodeTestFiller.json | 302 +++++++++++++++++++++++++++++++++ 1 file changed, 302 insertions(+) create mode 100644 test/stInitCodeTestFiller.json diff --git a/test/stInitCodeTestFiller.json b/test/stInitCodeTestFiller.json new file mode 100644 index 000000000..76d8f7957 --- /dev/null +++ b/test/stInitCodeTestFiller.json @@ -0,0 +1,302 @@ +{ + "TransactionContractCreation" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "45678256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : + { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "100000", + "code" : "", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : + { + "data" : "0x600a80600c6000396000f200600160008035811a8100", + "gasLimit" : "599", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "", + "value" : "1" + } + }, + + + "NotEnoughCashContractCreation" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "45678256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : + { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "2", + "code" : "", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : + { + "data" : "0x600a80600c6000396000f200600160008035811a8100", + "gasLimit" : "599", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "", + "value" : "1" + } + }, + + "OutOfGasContractCreation" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "45678256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : + { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000", + "code" : "", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : + { + "data" : "0x600a80600c6000396000f200600160008035811a8100", + "gasLimit" : "590", + "gasPrice" : "3", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "", + "value" : "1" + } + }, + + "TransactionSuicideInitCode" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "45678256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : + { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000", + "code" : "", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : + { + "data" : "0x600a80600c6000396000fff2ffff600160008035811a81", + "gasLimit" : "1000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "", + "value" : "1" + } + }, + + "TransactionStopInitCode" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "45678256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : + { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000", + "code" : "", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : + { + "data" : "0x600a80600c600039600000f20000600160008035811a81", + "gasLimit" : "1000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "", + "value" : "1" + } + }, + + "TransactionCreateSuicideContract" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "45678256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : + { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000", + "code" : "", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : + { + "data" : "0x600a80600c6000396000f200ff600160008035811a81", + "gasLimit" : "1000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "", + "value" : "1" + } + }, + + "CallTheContractToCreateEmptyContract" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "45678256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : + { + "095e7baea6a6c7c4c2dfeb977efac326af552d87": { + "balance": "0", + "nonce": 0, + "code": "{(CREATE 0 0 32)}", + "storage": {} + }, + + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "100000", + "code" : "", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : + { + "data" : "0x00", + "gasLimit" : "10000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "1" + } + }, + + "CallRecursiveContract" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "45678256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : + { + "095e7baea6a6c7c4c2dfeb977efac326af552d87": { + "balance": "0", + "nonce": 0, + "code": "{[[ 2 ]](ADDRESS)(CODECOPY 0 0 32)(CREATE 0 0 32)}", + "storage": {} + }, + + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "100000", + "code" : "", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : + { + "data" : "0x00", + "gasLimit" : "10000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "1" + } + }, + + "CallTheContractToCreateContractWithInitCode" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "45678256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : + { + "095e7baea6a6c7c4c2dfeb977efac326af552d87": { + "balance": "10000", + "nonce": 0, + "code": "{[[ 2 ]](ADDRESS)(CODECOPY 0 0 32)(CREATE 0 0 32)}", + "storage": {} + }, + + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "100000", + "code" : "", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : + { + "data" : "0x00", + "gasLimit" : "10000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "1" + } + } +} From 761bd331237a1f4eabf0a14ec6a9bd6f1b43b126 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 13 Dec 2014 19:16:35 +0100 Subject: [PATCH 502/641] Avoid noting safe exceptions unless the user *really* wants it. --- libethereum/Executive.cpp | 13 +++++++------ libethereum/State.h | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index 3bf26cf89..773bc2d38 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -166,8 +166,9 @@ bool Executive::go(OnOpFunc const& _onOp) { if (m_vm) { +#if ETH_TIMED_EXECUTIONS boost::timer t; -// auto sgas = m_vm->gas(); +#endif try { m_out = m_vm->go(*m_ext, _onOp); @@ -188,11 +189,9 @@ bool Executive::go(OnOpFunc const& _onOp) } catch (VMException const& _e) { - clog(StateChat) << "Safe VM Exception"; - m_endGas = 0;//m_vm->gas(); + clog(StateSafeExceptions) << "Safe VM Exception. " << diagnostic_information(_e); + m_endGas = 0; m_excepted = true; - - // Write state out only in the case of a non-excepted transaction. m_ext->revert(); } catch (Exception const& _e) @@ -205,7 +204,9 @@ bool Executive::go(OnOpFunc const& _onOp) // TODO: AUDIT: check that this can never reasonably happen. Consider what to do if it does. cwarn << "Unexpected std::exception in VM. This is probably unrecoverable. " << _e.what(); } -// cnote << "VM took:" << t.elapsed() << "; gas used: " << (sgas - m_endGas); +#if ETH_TIMED_EXECUTIONS + cnote << "VM took:" << t.elapsed() << "; gas used: " << (sgas - m_endGas); +#endif } return true; } diff --git a/libethereum/State.h b/libethereum/State.h index afa1f1d2c..a85c622df 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -51,6 +51,7 @@ class BlockChain; struct StateChat: public LogChannel { static const char* name() { return "-S-"; } static const int verbosity = 4; }; struct StateTrace: public LogChannel { static const char* name() { return "=S="; } static const int verbosity = 7; }; struct StateDetail: public LogChannel { static const char* name() { return "/S/"; } static const int verbosity = 14; }; +struct StateSafeExceptions: public LogChannel { static const char* name() { return "(S)"; } static const int verbosity = 21; }; struct PrecompiledAddress { From a1a6dcab3495fe7530564e2c8f787d9723d275e1 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 13 Dec 2014 20:15:08 +0100 Subject: [PATCH 503/641] Core repotting. --- libdevcrypto/Common.h | 5 ++ libethcore/BlockInfo.h | 4 +- libethcore/CommonEth.h | 3 + libethereum/CachedAddressState.cpp | 101 +++++++++++++++++++++ libethereum/CachedAddressState.h | 60 +++++++++++++ libethereum/Executive.cpp | 5 +- libethereum/Precompiled.cpp | 88 ++++++++++++++++++ libethereum/Precompiled.h | 44 +++++++++ libethereum/State.cpp | 137 +---------------------------- libethereum/State.h | 11 --- libevm/ExtVMFace.h | 2 - 11 files changed, 307 insertions(+), 153 deletions(-) create mode 100644 libethereum/CachedAddressState.cpp create mode 100644 libethereum/CachedAddressState.h create mode 100644 libethereum/Precompiled.cpp create mode 100644 libethereum/Precompiled.h diff --git a/libdevcrypto/Common.h b/libdevcrypto/Common.h index 96631fcf9..02d52f495 100644 --- a/libdevcrypto/Common.h +++ b/libdevcrypto/Common.h @@ -45,6 +45,11 @@ using Signature = h520; struct SignatureStruct { + SignatureStruct() {} + SignatureStruct(Signature const& _s) { *(h520*)this = _s; } + SignatureStruct(h256 _r, h256 _s, byte _v): r(_r), s(_s), v(_v) {} + operator Signature() const { return *(h520 const*)this; } + /// @returns true if r,s,v values are valid, otherwise false bool isValid(); diff --git a/libethcore/BlockInfo.h b/libethcore/BlockInfo.h index fc52880fa..18dd53ff3 100644 --- a/libethcore/BlockInfo.h +++ b/libethcore/BlockInfo.h @@ -69,7 +69,7 @@ public: h256 stateRoot; h256 transactionsRoot; h256 receiptsRoot; - h512 logBloom; // TODO LogBloom - get include + LogBloom logBloom; u256 difficulty; u256 number; u256 gasLimit; @@ -118,7 +118,7 @@ public: u256 calculateDifficulty(BlockInfo const& _parent) const; u256 calculateGasLimit(BlockInfo const& _parent) const; - /// No-nonce sha3 of the header only. + /// sha3 of the header only. h256 headerHash(IncludeNonce _n) const; void streamRLP(RLPStream& _s, IncludeNonce _n) const; }; diff --git a/libethcore/CommonEth.h b/libethcore/CommonEth.h index 1965a881a..be7db8434 100644 --- a/libethcore/CommonEth.h +++ b/libethcore/CommonEth.h @@ -44,6 +44,9 @@ std::string formatBalance(u256 _b); /// Get information concerning the currency denominations. std::vector> const& units(); +/// The log bloom's size (512 bit). +using LogBloom = h512; + // The various denominations; here for ease of use where needed within code. static const u256 Uether = ((((u256(1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000000; static const u256 Vether = ((((u256(1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000; diff --git a/libethereum/CachedAddressState.cpp b/libethereum/CachedAddressState.cpp new file mode 100644 index 000000000..5f9be6944 --- /dev/null +++ b/libethereum/CachedAddressState.cpp @@ -0,0 +1,101 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file CachedAddressState.cpp + * @author Gav Wood + * @date 2014 + */ + +#include "CachedAddressState.h" + +#include +#include +#include "Account.h" +using namespace std; +using namespace dev; +using namespace dev::eth; + +bool CachedAddressState::exists() const +{ + return (m_r && (!m_s || m_s->isAlive())) || (m_s && m_s->isAlive()); +} + +u256 CachedAddressState::balance() const +{ + return m_r ? m_s ? m_s->balance() : m_r[1].toInt() : 0; +} + +u256 CachedAddressState::nonce() const +{ + return m_r ? m_s ? m_s->nonce() : m_r[0].toInt() : 0; +} + +bytes CachedAddressState::code() const +{ + if (m_s && m_s->codeCacheValid()) + return m_s->code(); + h256 h = m_r ? m_s ? m_s->codeHash() : m_r[3].toHash() : EmptySHA3; + return h == EmptySHA3 ? bytes() : asBytes(m_o->lookup(h)); +} + +std::map CachedAddressState::storage() const +{ + std::map ret; + if (m_r) + { + TrieDB memdb(const_cast(m_o), m_r[2].toHash()); // promise we won't alter the overlay! :) + for (auto const& j: memdb) + ret[j.first] = RLP(j.second).toInt(); + } + if (m_s) + for (auto const& j: m_s->storageOverlay()) + if ((!ret.count(j.first) && j.second) || (ret.count(j.first) && ret.at(j.first) != j.second)) + ret[j.first] = j.second; + return ret; +} + +AccountDiff CachedAddressState::diff(CachedAddressState const& _c) +{ + AccountDiff ret; + ret.exist = Diff(exists(), _c.exists()); + ret.balance = Diff(balance(), _c.balance()); + ret.nonce = Diff(nonce(), _c.nonce()); + ret.code = Diff(code(), _c.code()); + auto st = storage(); + auto cst = _c.storage(); + auto it = st.begin(); + auto cit = cst.begin(); + while (it != st.end() || cit != cst.end()) + { + if (it != st.end() && cit != cst.end() && it->first == cit->first && (it->second || cit->second) && (it->second != cit->second)) + ret.storage[it->first] = Diff(it->second, cit->second); + else if (it != st.end() && (cit == cst.end() || it->first < cit->first) && it->second) + ret.storage[it->first] = Diff(it->second, 0); + else if (cit != cst.end() && (it == st.end() || it->first > cit->first) && cit->second) + ret.storage[cit->first] = Diff(0, cit->second); + if (it == st.end()) + ++cit; + else if (cit == cst.end()) + ++it; + else if (it->first < cit->first) + ++it; + else if (it->first > cit->first) + ++cit; + else + ++it, ++cit; + } + return ret; +} diff --git a/libethereum/CachedAddressState.h b/libethereum/CachedAddressState.h new file mode 100644 index 000000000..301f54338 --- /dev/null +++ b/libethereum/CachedAddressState.h @@ -0,0 +1,60 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file CachedAddressState.h + * @author Gav Wood + * @date 2014 + */ + +#pragma once + +#include +#include +#include +#include "AccountDiff.h" + +namespace dev +{ + +class OverlayDB; + +namespace eth +{ + +class Account; + +class CachedAddressState +{ +public: + CachedAddressState(std::string const& _rlp, Account const* _s, OverlayDB const* _o): m_rS(_rlp), m_r(m_rS), m_s(_s), m_o(_o) {} + + bool exists() const; + u256 balance() const; + u256 nonce() const; + bytes code() const; + std::map storage() const; + AccountDiff diff(CachedAddressState const& _c); + +private: + std::string m_rS; + RLP m_r; + Account const* m_s; + OverlayDB const* m_o; +}; + +} + +} diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index 773bc2d38..438505f1a 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -28,6 +28,7 @@ #include "Interface.h" #include "State.h" #include "ExtVM.h" +#include "Precompiled.h" using namespace std; using namespace dev; using namespace dev::eth; @@ -98,8 +99,8 @@ bool Executive::call(Address _receiveAddress, Address _codeAddress, Address _sen // cnote << "Transferring" << formatBalance(_value) << "to receiver."; m_s.addBalance(_receiveAddress, _value); - auto it = !(_codeAddress & ~h160(0xffffffff)) ? State::precompiled().find((unsigned)(u160)_codeAddress) : State::precompiled().end(); - if (it != State::precompiled().end()) + auto it = !(_codeAddress & ~h160(0xffffffff)) ? precompiled().find((unsigned)(u160)_codeAddress) : precompiled().end(); + if (it != precompiled().end()) { bigint g = it->second.gas(_data); if (_gas < g) diff --git a/libethereum/Precompiled.cpp b/libethereum/Precompiled.cpp new file mode 100644 index 000000000..1861385da --- /dev/null +++ b/libethereum/Precompiled.cpp @@ -0,0 +1,88 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file Precompiled.cpp + * @author Gav Wood + * @date 2014 + */ + +#include "Precompiled.h" + +#include +#include +#include +using namespace std; +using namespace dev; +using namespace dev::eth; + +static bytes ecrecoverCode(bytesConstRef _in) +{ + struct inType + { + h256 hash; + h256 v; + h256 r; + h256 s; + } in; + + memcpy(&in, _in.data(), min(_in.size(), sizeof(in))); + + h256 ret; + + if ((u256)in.v > 28) + return ret.asBytes(); + SignatureStruct sig(in.r, in.s, (byte)((int)(u256)in.v - 27)); + if (!sig.isValid()) + return ret.asBytes(); + + try + { + ret = dev::sha3(recover(sig, in.hash)); + } + catch (...) {} + + memset(ret.data(), 0, 12); + return ret.asBytes(); +} + +static bytes sha256Code(bytesConstRef _in) +{ + bytes ret(32); + sha256(_in, &ret); + return ret; +} + +static bytes ripemd160Code(bytesConstRef _in) +{ + bytes ret(32); + ripemd160(_in, &ret); + // leaves the 20-byte hash left-aligned. we want it right-aligned: + memmove(ret.data() + 12, ret.data(), 20); + memset(ret.data(), 0, 12); + return ret; +} + +static const std::map c_precompiled = +{ + { 1, { [](bytesConstRef) -> bigint { return (bigint)500; }, ecrecoverCode }}, + { 2, { [](bytesConstRef i) -> bigint { return (bigint)50 + (i.size() + 31) / 32 * 50; }, sha256Code }}, + { 3, { [](bytesConstRef i) -> bigint { return (bigint)50 + (i.size() + 31) / 32 * 50; }, ripemd160Code }} +}; + +std::map const& dev::eth::precompiled() +{ + return c_precompiled; +} diff --git a/libethereum/Precompiled.h b/libethereum/Precompiled.h new file mode 100644 index 000000000..c65cd9a63 --- /dev/null +++ b/libethereum/Precompiled.h @@ -0,0 +1,44 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file Precompiled.h + * @author Gav Wood + * @date 2014 + */ + +#pragma once + +#include +#include +#include + +namespace dev +{ +namespace eth +{ + +/// Information structure regarding an account that is precompiled (i.e. 1, 2, 3). +struct PrecompiledAddress +{ + std::function gas; + std::function exec; +}; + +/// Info on precompiled contract accounts baked into the protocol. +std::map const& precompiled(); + +} +} diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 30290c315..64210f20a 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -34,6 +34,7 @@ #include "Defaults.h" #include "ExtVM.h" #include "Executive.h" +#include "CachedAddressState.h" using namespace std; using namespace dev; using namespace dev::eth; @@ -42,59 +43,6 @@ using namespace dev::eth; static const u256 c_blockReward = 1500 * finney; -bytes ecrecoverCode(bytesConstRef _in) -{ - struct inType - { - h256 hash; - h256 v; - h256 r; - h256 s; - } in; - - memcpy(&in, _in.data(), min(_in.size(), sizeof(in))); - - h256 ret; - - if ((u256)in.v > 28) - return ret.asBytes(); - SignatureStruct sig{in.r, in.s, (byte)((int)(u256)in.v - 27)}; - if (!sig.isValid()) - return ret.asBytes(); - - byte pubkey[65]; - int pubkeylen = 65; - secp256k1_start(); - if (secp256k1_ecdsa_recover_compact(in.hash.data(), 32, in.r.data(), pubkey, &pubkeylen, 0, (int)(u256)in.v - 27)) - ret = dev::sha3(bytesConstRef(&(pubkey[1]), 64)); - memset(ret.data(), 0, 12); - return ret.asBytes(); -} - -bytes sha256Code(bytesConstRef _in) -{ - bytes ret(32); - sha256(_in, &ret); - return ret; -} - -bytes ripemd160Code(bytesConstRef _in) -{ - bytes ret(32); - ripemd160(_in, &ret); - // leaves the 20-byte hash left-aligned. we want it right-aligned: - memmove(ret.data() + 12, ret.data(), 20); - memset(ret.data(), 0, 12); - return ret; -} - -const std::map State::c_precompiled = -{ - { 1, { [](bytesConstRef) -> bigint { return (bigint)500; }, ecrecoverCode }}, - { 2, { [](bytesConstRef i) -> bigint { return (bigint)50 + (i.size() + 31) / 32 * 50; }, sha256Code }}, - { 3, { [](bytesConstRef i) -> bigint { return (bigint)50 + (i.size() + 31) / 32 * 50; }, ripemd160Code }} -}; - OverlayDB State::openDB(std::string _path, bool _killExisting) { if (_path.empty()) @@ -226,89 +174,6 @@ Address State::nextActiveAddress(Address _a) const return (*it).first; } -// TODO: repot -struct CachedAddressState -{ - CachedAddressState(std::string const& _rlp, Account const* _s, OverlayDB const* _o): rS(_rlp), r(rS), s(_s), o(_o) {} - - bool exists() const - { - return (r && (!s || s->isAlive())) || (s && s->isAlive()); - } - - u256 balance() const - { - return r ? s ? s->balance() : r[1].toInt() : 0; - } - - u256 nonce() const - { - return r ? s ? s->nonce() : r[0].toInt() : 0; - } - - bytes code() const - { - if (s && s->codeCacheValid()) - return s->code(); - h256 h = r ? s ? s->codeHash() : r[3].toHash() : EmptySHA3; - return h == EmptySHA3 ? bytes() : asBytes(o->lookup(h)); - } - - std::map storage() const - { - std::map ret; - if (r) - { - TrieDB memdb(const_cast(o), r[2].toHash()); // promise we won't alter the overlay! :) - for (auto const& j: memdb) - ret[j.first] = RLP(j.second).toInt(); - } - if (s) - for (auto const& j: s->storageOverlay()) - if ((!ret.count(j.first) && j.second) || (ret.count(j.first) && ret.at(j.first) != j.second)) - ret[j.first] = j.second; - return ret; - } - - AccountDiff diff(CachedAddressState const& _c) - { - AccountDiff ret; - ret.exist = Diff(exists(), _c.exists()); - ret.balance = Diff(balance(), _c.balance()); - ret.nonce = Diff(nonce(), _c.nonce()); - ret.code = Diff(code(), _c.code()); - auto st = storage(); - auto cst = _c.storage(); - auto it = st.begin(); - auto cit = cst.begin(); - while (it != st.end() || cit != cst.end()) - { - if (it != st.end() && cit != cst.end() && it->first == cit->first && (it->second || cit->second) && (it->second != cit->second)) - ret.storage[it->first] = Diff(it->second, cit->second); - else if (it != st.end() && (cit == cst.end() || it->first < cit->first) && it->second) - ret.storage[it->first] = Diff(it->second, 0); - else if (cit != cst.end() && (it == st.end() || it->first > cit->first) && cit->second) - ret.storage[cit->first] = Diff(0, cit->second); - if (it == st.end()) - ++cit; - else if (cit == cst.end()) - ++it; - else if (it->first < cit->first) - ++it; - else if (it->first > cit->first) - ++cit; - else - ++it, ++cit; - } - return ret; - } - - std::string rS; - RLP r; - Account const* s; - OverlayDB const* o; -}; - StateDiff State::diff(State const& _c) const { StateDiff ret; diff --git a/libethereum/State.h b/libethereum/State.h index a85c622df..611647566 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -53,12 +53,6 @@ struct StateTrace: public LogChannel { static const char* name() { return "=S="; struct StateDetail: public LogChannel { static const char* name() { return "/S/"; } static const int verbosity = 14; }; struct StateSafeExceptions: public LogChannel { static const char* name() { return "(S)"; } static const int verbosity = 21; }; -struct PrecompiledAddress -{ - std::function gas; - std::function exec; -}; - /** * @brief Model of the current state of the ledger. * Maintains current ledger (m_current) as a fast hash-map. This is hashed only when required (i.e. to create or verify a block). @@ -250,9 +244,6 @@ public: /// the block since all state changes are ultimately reversed. void cleanup(bool _fullCommit); - /// Info on precompiled contract accounts baked into the protocol. - static std::map const& precompiled() { return c_precompiled; } - private: /// Undo the changes to the state for committing to mine. void uncommitToMine(); @@ -311,8 +302,6 @@ private: static std::string c_defaultPath; - static const std::map c_precompiled; - friend std::ostream& operator<<(std::ostream& _out, State const& _s); }; diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h index b8c4184ab..84dee4272 100644 --- a/libevm/ExtVMFace.h +++ b/libevm/ExtVMFace.h @@ -36,8 +36,6 @@ namespace dev namespace eth { -using LogBloom = h512; - struct LogEntry { LogEntry() {} From efa6fd99b28649e6fd92ae15cc04f38fdc8b95b8 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 13 Dec 2014 21:21:36 +0100 Subject: [PATCH 504/641] Windows fix? --- test/solidityEndToEndTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/solidityEndToEndTest.cpp b/test/solidityEndToEndTest.cpp index 130e44a9a..0970c4f4b 100644 --- a/test/solidityEndToEndTest.cpp +++ b/test/solidityEndToEndTest.cpp @@ -402,7 +402,7 @@ BOOST_AUTO_TEST_CASE(empty_string_on_stack) " }\n" "}\n"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction(0, bytes({0x02})) == bytes({0x00, 0x02, 'a', 'b', 'c', 0x00})); + BOOST_CHECK(callContractFunction(0, bytes({0x02})) == bytes({0x00, 0x02, (byte)'a', (byte)'b', (byte)'c', 0x00})); } BOOST_AUTO_TEST_CASE(state_smoke_test) From 24a2c6f2ed6c90281e80c987413ce785b83bd501 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 13 Dec 2014 21:24:13 +0100 Subject: [PATCH 505/641] Another Windows fix? --- test/TestHelper.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index e8940cc7a..0c1ee290f 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -330,9 +330,11 @@ void checkStorage(map _expectedStore, map _resultStore, } } BOOST_CHECK_EQUAL(_resultStore.size(), _expectedStore.size()); +#ifndef __WIN32__ for (auto&& resultStorePair : _resultStore) if (!_expectedStore.count(resultStorePair.first)) BOOST_ERROR(_expectedAddr << ": unexpected store key " << resultStorePair.first); +#endif } void checkLog(LogEntries _resultLogs, LogEntries _expectedLogs) From 35f2985eb9bbc9eb7c000bf42cc1bff0f1a4d7f2 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Sat, 13 Dec 2014 21:39:21 +0100 Subject: [PATCH 506/641] merge --- test/state.cpp | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/test/state.cpp b/test/state.cpp index b5b238299..f183c4813 100644 --- a/test/state.cpp +++ b/test/state.cpp @@ -45,7 +45,7 @@ void doStateTests(json_spirit::mValue& v, bool _fillin) { for (auto& i: v.get_obj()) { - cnote << i.first; + cerr << i.first << endl; mObject& o = i.second.get_obj(); BOOST_REQUIRE(o.count("env") > 0); @@ -81,6 +81,9 @@ void doStateTests(json_spirit::mValue& v, bool _fillin) // check output checkOutput(output, o); + // check logs + checkLog(theState.pending().size() ? theState.log(0) : LogEntries(), importer.m_environment.sub.logs); + // check addresses auto expectedAddrs = importer.m_statePost.addresses(); auto resultAddrs = theState.addresses(); @@ -122,6 +125,26 @@ BOOST_AUTO_TEST_CASE(stPreCompiledContracts) dev::test::executeTests("stPreCompiledContracts", "/StateTests", dev::test::doStateTests); } +BOOST_AUTO_TEST_CASE(stLogTests) +{ + dev::test::executeTests("stLogTests", "/StateTests", dev::test::doStateTests); +} + +BOOST_AUTO_TEST_CASE(stRecursiveCreate) +{ + dev::test::executeTests("stRecursiveCreate", "/StateTests", dev::test::doStateTests); +} + +BOOST_AUTO_TEST_CASE(stInitCodeTest) +{ + dev::test::executeTests("stInitCodeTest", "/StateTests", dev::test::doStateTests); +} + +BOOST_AUTO_TEST_CASE(stSpecialTest) +{ + dev::test::executeTests("stSpecialTest", "/StateTests", dev::test::doStateTests); +} + BOOST_AUTO_TEST_CASE(stCreateTest) { for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i) From 37c93e0458c9be22cacf9ea382834392ca0e5690 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 13 Dec 2014 21:40:04 +0100 Subject: [PATCH 507/641] Fixes for windows? --- test/TestHelper.cpp | 4 ++-- test/solidityEndToEndTest.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index 0c1ee290f..b700b65a7 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -330,11 +330,11 @@ void checkStorage(map _expectedStore, map _resultStore, } } BOOST_CHECK_EQUAL(_resultStore.size(), _expectedStore.size()); -#ifndef __WIN32__ for (auto&& resultStorePair : _resultStore) + { if (!_expectedStore.count(resultStorePair.first)) BOOST_ERROR(_expectedAddr << ": unexpected store key " << resultStorePair.first); -#endif + } } void checkLog(LogEntries _resultLogs, LogEntries _expectedLogs) diff --git a/test/solidityEndToEndTest.cpp b/test/solidityEndToEndTest.cpp index 0970c4f4b..2c1885ad8 100644 --- a/test/solidityEndToEndTest.cpp +++ b/test/solidityEndToEndTest.cpp @@ -402,7 +402,7 @@ BOOST_AUTO_TEST_CASE(empty_string_on_stack) " }\n" "}\n"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction(0, bytes({0x02})) == bytes({0x00, 0x02, (byte)'a', (byte)'b', (byte)'c', 0x00})); + BOOST_CHECK(callContractFunction(0, bytes({0x02})) == bytes({0x00, 0x02, 0x61/*'a'*/, 0x62/*'b'*/, 0x63/*'c'*/, 0x00})); } BOOST_AUTO_TEST_CASE(state_smoke_test) From a068543f21db9efd7e659aa4848d7e959bc711ba Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 13 Dec 2014 21:43:38 +0100 Subject: [PATCH 508/641] State reworked slightly. Additional experimentation for State to demo how easily it is to create states. --- exp/main.cpp | 80 ++++++++------------------------------------- libethereum/State.h | 16 ++++----- 2 files changed, 21 insertions(+), 75 deletions(-) diff --git a/exp/main.cpp b/exp/main.cpp index 8be79cad5..6192ab96c 100644 --- a/exp/main.cpp +++ b/exp/main.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include using namespace std; @@ -36,7 +37,7 @@ using namespace dev::eth; using namespace dev::p2p; using namespace dev::shh; -#if 1 +#if 0 int main() { DownloadMan man; @@ -72,72 +73,17 @@ int main() cnote << i;*/ return 0; } -#endif - -/*int other(bool& o_started) +#else +int main() { - setThreadName("other"); - - short listenPort = 30300; - - Host ph("Test", NetworkPreferences(listenPort, "", false, true)); - auto wh = ph.registerCapability(new WhisperHost()); - - ph.start(); - - o_started = true; - - /// Only interested in odd packets - auto w = wh->installWatch(BuildTopicMask()("odd")); - - unsigned last = 0; - unsigned total = 0; - - for (int i = 0; i < 100 && last < 81; ++i) - { - for (auto i: wh->checkWatch(w)) - { - Message msg = wh->envelope(i).open(); - last = RLP(msg.payload()).toInt(); - cnote << "New message from:" << msg.from().abridged() << RLP(msg.payload()).toInt(); - total += last; - } - this_thread::sleep_for(chrono::milliseconds(50)); - } - return total; + KeyPair u = KeyPair::create(); + KeyPair cb = KeyPair::create(); + OverlayDB db; + State s(cb.address(), db); + cnote << s.rootHash(); + s.addBalance(u.address(), 1000 * ether); + s.commit(); + cnote << s.rootHash(); } +#endif -int main(int, char**) -{ - g_logVerbosity = 0; - - bool started = false; - unsigned result; - std::thread listener([&](){ return (result = other(started)); }); - while (!started) - this_thread::sleep_for(chrono::milliseconds(50)); - - short listenPort = 30303; - string remoteHost = "127.0.0.1"; - short remotePort = 30300; - - Host ph("Test", NetworkPreferences(listenPort, "", false, true)); - auto wh = ph.registerCapability(new WhisperHost()); - - ph.start(); - - if (!remoteHost.empty()) - ph.connect(remoteHost, remotePort); - - KeyPair us = KeyPair::create(); - for (int i = 0; i < 10; ++i) - { - wh->post(us.sec(), RLPStream().append(i * i).out(), BuildTopic(i)(i % 2 ? "odd" : "even")); - this_thread::sleep_for(chrono::milliseconds(250)); - } - - listener.join(); - assert(result == 1 + 9 + 25 + 49 + 81); - - return 0; -}*/ diff --git a/libethereum/State.h b/libethereum/State.h index 611647566..b071e7674 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -244,6 +244,12 @@ public: /// the block since all state changes are ultimately reversed. void cleanup(bool _fullCommit); + /// Commit all changes waiting in the address cache to the DB. + void commit(); + + /// Sets m_currentBlock to a clean state, (i.e. no change from m_previousBlock). + void resetCurrent(); + private: /// Undo the changes to the state for committing to mine. void uncommitToMine(); @@ -257,25 +263,19 @@ private: /// Retrieve all information about a given address into a cache. void ensureCached(std::map& _cache, Address _a, bool _requireCode, bool _forceCreate) const; - /// Commit all changes waiting in the address cache to the DB. - void commit(); - /// Execute the given block, assuming it corresponds to m_currentBlock. If _bc is passed, it will be used to check the uncles. /// Throws on failure. u256 enact(bytesConstRef _block, BlockChain const* _bc = nullptr, bool _checkNonce = true); - /// Sets m_currentBlock to a clean state, (i.e. no change from m_previousBlock). - void resetCurrent(); - /// Finalise the block, applying the earned rewards. void applyRewards(Addresses const& _uncleAddresses); - void refreshManifest(RLPStream* _txs = nullptr); - /// @returns gas used by transactions thus far executed. u256 gasUsed() const { return m_receipts.size() ? m_receipts.back().gasUsed() : 0; } + /// Debugging only. Good for checking the Trie is in shape. bool isTrieGood(bool _enforceRefs, bool _requireNoLeftOvers) const; + /// Debugging only. Good for checking the Trie is in shape. void paranoia(std::string const& _when, bool _enforceRefs = false) const; OverlayDB m_db; ///< Our overlay for the state tree. From 4a0ac1f4c2f294052e052e1a1533302f2509a189 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 13 Dec 2014 21:48:23 +0100 Subject: [PATCH 509/641] Silly windows fix. --- test/solidityEndToEndTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/solidityEndToEndTest.cpp b/test/solidityEndToEndTest.cpp index 2c1885ad8..15722abe1 100644 --- a/test/solidityEndToEndTest.cpp +++ b/test/solidityEndToEndTest.cpp @@ -402,7 +402,7 @@ BOOST_AUTO_TEST_CASE(empty_string_on_stack) " }\n" "}\n"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction(0, bytes({0x02})) == bytes({0x00, 0x02, 0x61/*'a'*/, 0x62/*'b'*/, 0x63/*'c'*/, 0x00})); + BOOST_CHECK(callContractFunction(0, bytes(1, 0x02)) == bytes({0x00, 0x02, 0x61/*'a'*/, 0x62/*'b'*/, 0x63/*'c'*/, 0x00})); } BOOST_AUTO_TEST_CASE(state_smoke_test) From 0cd39343eb086ac277fba92c0815894aa0aedb31 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 13 Dec 2014 22:40:57 +0100 Subject: [PATCH 510/641] Demonstration of how to create a completely custom state for execution of transactions. --- exp/main.cpp | 13 +++++++++++-- libethcore/BlockInfo.cpp | 19 +++++++++++++++++++ libethcore/BlockInfo.h | 2 ++ libethereum/ExtVM.h | 1 + libethereum/State.cpp | 39 +++++++++++++++++++++++++++++++++------ libethereum/State.h | 7 ++++++- 6 files changed, 72 insertions(+), 9 deletions(-) diff --git a/exp/main.cpp b/exp/main.cpp index 6192ab96c..aee6e6efd 100644 --- a/exp/main.cpp +++ b/exp/main.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include using namespace std; @@ -79,11 +80,19 @@ int main() KeyPair u = KeyPair::create(); KeyPair cb = KeyPair::create(); OverlayDB db; - State s(cb.address(), db); + State s(cb.address(), db, BaseState::Empty); cnote << s.rootHash(); - s.addBalance(u.address(), 1000 * ether); + s.addBalance(u.address(), 1 * ether); + Address c = s.newContract(1000 * ether, compileLLL("(suicide (caller))")); s.commit(); cnote << s.rootHash(); + State before = s; + cnote << s; + Transaction t(0, 10000, 10000, c, bytes(), 0, u.secret()); + cnote << s.balance(c); + s.execute(t.rlp()); + cnote << before.diff(s); + cnote << s; } #endif diff --git a/libethcore/BlockInfo.cpp b/libethcore/BlockInfo.cpp index bf973b565..6c08bb346 100644 --- a/libethcore/BlockInfo.cpp +++ b/libethcore/BlockInfo.cpp @@ -40,6 +40,25 @@ BlockInfo::BlockInfo(bytesConstRef _block, bool _checkNonce) populate(_block, _checkNonce); } +void BlockInfo::setEmpty() +{ + parentHash = h256(); + sha3Uncles = EmptyListSHA3; + coinbaseAddress = Address(); + stateRoot = EmptyTrie; + transactionsRoot = EmptyTrie; + receiptsRoot = EmptyTrie; + logBloom = LogBloom(); + difficulty = 0; + number = 0; + gasLimit = 0; + gasUsed = 0; + timestamp = 0; + extraData.clear(); + nonce = h256(); + hash = headerHash(WithNonce); +} + BlockInfo BlockInfo::fromHeader(bytesConstRef _block) { BlockInfo ret; diff --git a/libethcore/BlockInfo.h b/libethcore/BlockInfo.h index 18dd53ff3..99efc6a17 100644 --- a/libethcore/BlockInfo.h +++ b/libethcore/BlockInfo.h @@ -108,6 +108,8 @@ public: } bool operator!=(BlockInfo const& _cmp) const { return !operator==(_cmp); } + void setEmpty(); + void populateFromHeader(RLP const& _header, bool _checkNonce = true); void populate(bytesConstRef _block, bool _checkNonce = true); void populate(bytes const& _block, bool _checkNonce = true) { populate(&_block, _checkNonce); } diff --git a/libethereum/ExtVM.h b/libethereum/ExtVM.h index 9699a68ad..cfe40874f 100644 --- a/libethereum/ExtVM.h +++ b/libethereum/ExtVM.h @@ -73,6 +73,7 @@ public: virtual void suicide(Address _a) override final { m_s.addBalance(_a, m_s.balance(myAddress)); + m_s.subBalance(myAddress, m_s.balance(myAddress)); ExtVMFace::suicide(_a); } diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 64210f20a..fd00761e1 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -63,7 +63,7 @@ OverlayDB State::openDB(std::string _path, bool _killExisting) return OverlayDB(db); } -State::State(Address _coinbaseAddress, OverlayDB const& _db): +State::State(Address _coinbaseAddress, OverlayDB const& _db, BaseState _bs): m_db(_db), m_state(&m_db), m_ourAddress(_coinbaseAddress), @@ -74,12 +74,19 @@ State::State(Address _coinbaseAddress, OverlayDB const& _db): paranoia("beginning of normal construction.", true); - dev::eth::commit(genesisState(), m_db, m_state); - m_db.commit(); + if (_bs == BaseState::Genesis) + { + dev::eth::commit(genesisState(), m_db, m_state); + m_db.commit(); - paranoia("after DB commit of normal construction.", true); + paranoia("after DB commit of normal construction.", true); + m_previousBlock = BlockChain::genesis(); + } + else + { + m_previousBlock.setEmpty(); + } - m_previousBlock = BlockChain::genesis(); resetCurrent(); assert(m_state.root() == m_previousBlock.stateRoot); @@ -857,6 +864,23 @@ void State::subBalance(Address _id, bigint _amount) it->second.addBalance(-_amount); } +Address State::newContract(u256 _balance, bytes const& _code) +{ + auto h = sha3(_code); + m_db.insert(h, &_code); + while (true) + { + Address ret = Address::random(); + ensureCached(ret, false, false); + auto it = m_cache.find(ret); + if (it == m_cache.end()) + { + m_cache[ret] = Account(0, _balance, EmptyTrie, h); + return ret; + } + } +} + u256 State::transactionsFrom(Address _id) const { ensureCached(_id, false, false); @@ -993,8 +1017,11 @@ u256 State::execute(bytesConstRef _rlp, bytes* o_output, bool _commit) ctrace << "Executing" << e.t() << "on" << h; ctrace << toHex(e.t().rlp()); #endif - +#if ETH_TRACE e.go(e.simpleTrace()); +#else + e.go(); +#endif e.finalize(); #if ETH_PARANOIA diff --git a/libethereum/State.h b/libethereum/State.h index b071e7674..763a67451 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -53,6 +53,8 @@ struct StateTrace: public LogChannel { static const char* name() { return "=S="; struct StateDetail: public LogChannel { static const char* name() { return "/S/"; } static const int verbosity = 14; }; struct StateSafeExceptions: public LogChannel { static const char* name() { return "(S)"; } static const int verbosity = 21; }; +enum class BaseState { Empty, Genesis }; + /** * @brief Model of the current state of the ledger. * Maintains current ledger (m_current) as a fast hash-map. This is hashed only when required (i.e. to create or verify a block). @@ -66,7 +68,7 @@ class State public: /// Construct state object. - State(Address _coinbaseAddress = Address(), OverlayDB const& _db = OverlayDB()); + State(Address _coinbaseAddress = Address(), OverlayDB const& _db = OverlayDB(), BaseState _bs = BaseState::Genesis); /// Construct state object from arbitrary point in blockchain. State(OverlayDB const& _db, BlockChain const& _bc, h256 _hash); @@ -183,6 +185,9 @@ public: /// Set the value of a storage position of an account. void setStorage(Address _contract, u256 _location, u256 _value) { m_cache[_contract].setStorage(_location, _value); } + /// Create a new contract. + Address newContract(u256 _balance, bytes const& _code); + /// Get the storage of an account. /// @note This is expensive. Don't use it unless you need to. /// @returns std::map if no account exists at that address. From bf3fbae3979d2d8d3efacb7f50abf4eac7ab7412 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 13 Dec 2014 22:44:28 +0100 Subject: [PATCH 511/641] Demonstration readability improved. Clear how the State diff works. --- exp/main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/exp/main.cpp b/exp/main.cpp index aee6e6efd..3c4a1b207 100644 --- a/exp/main.cpp +++ b/exp/main.cpp @@ -85,14 +85,14 @@ int main() s.addBalance(u.address(), 1 * ether); Address c = s.newContract(1000 * ether, compileLLL("(suicide (caller))")); s.commit(); - cnote << s.rootHash(); State before = s; - cnote << s; + cnote << "State before transaction: " << before; Transaction t(0, 10000, 10000, c, bytes(), 0, u.secret()); + cnote << "Transaction: " << t; cnote << s.balance(c); s.execute(t.rlp()); + cnote << "State after transaction: " << s; cnote << before.diff(s); - cnote << s; } #endif From 1e80a16ec84e83d9176506a2a9ca4091dc6d0f03 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Sat, 13 Dec 2014 23:46:20 +0100 Subject: [PATCH 512/641] fixed macdeplyqt path on macos --- cmake/EthDependencies.cmake | 11 +++++++++++ cmake/EthExecutableHelper.cmake | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 24e5bd07d..ee93a5311 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -17,6 +17,11 @@ if (WIN32) #set (CMAKE_PREFIX_PATH "C:/Program Files/Windows Kits/8.1/Lib/winv6.3/um/x64") endif() +# homebrew installs qts in opt +if (APPLE) + set (CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "/usr/local/opt/qt5") +endif() + # Dependencies must have a version number, to ensure reproducible build. The version provided here is the one that is in the extdep repository. If you use system libraries, version numbers may be different. find_package (CryptoPP 5.6.2 EXACT REQUIRED) @@ -102,6 +107,12 @@ if (NOT HEADLESS) find_package (Qt5WebKit REQUIRED) find_package (Qt5WebKitWidgets REQUIRED) + # we need to find path to macdeployqt on mac + if (APPLE) + set (MACDEPLOYQT_APP ${Qt5Core_DIR}/../../../bin/macdeployqt) + message(" - macdeployqt path: ${MACDEPLOYQT_APP}") + endif() + endif() #HEADLESS # use multithreaded boost libraries, with -mt suffix diff --git a/cmake/EthExecutableHelper.cmake b/cmake/EthExecutableHelper.cmake index adda57692..56aa3f6c3 100644 --- a/cmake/EthExecutableHelper.cmake +++ b/cmake/EthExecutableHelper.cmake @@ -66,7 +66,7 @@ macro(eth_install_executable EXECUTABLE) if (APPLE) # First have qt5 install plugins and frameworks add_custom_command(TARGET ${EXECUTABLE} POST_BUILD - COMMAND ${ETH_DEPENDENCY_INSTALL_DIR}/bin/macdeployqt ${eth_qml_dir} ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app + COMMAND ${MACDEPLOYQT_APP} ${eth_qml_dir} ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) # This tool and next will inspect linked libraries in order to determine which dependencies are required From 5162715101adc9df8b3713039a9f33479e2eb9a0 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Sun, 14 Dec 2014 00:10:52 +0100 Subject: [PATCH 513/641] ungly fix for compiling exp on mac --- exp/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/exp/main.cpp b/exp/main.cpp index 3c4a1b207..27707decb 100644 --- a/exp/main.cpp +++ b/exp/main.cpp @@ -20,6 +20,7 @@ * Ethereum client. */ #include +#include #include #include #include From 960f62b05a9a61300400dd566d5ad815f24e3101 Mon Sep 17 00:00:00 2001 From: Lu Guanqun Date: Sun, 14 Dec 2014 21:20:59 +0800 Subject: [PATCH 514/641] update to the correct file name --- alethzero/OurWebThreeStubServer.cpp | 2 +- alethzero/OurWebThreeStubServer.h | 2 +- libdevcore/CommonData.cpp | 2 +- libdevcore/CommonData.h | 2 +- libdevcore/RangeMask.h | 2 +- libdevcrypto/OverlayDB.cpp | 2 +- libdevcrypto/OverlayDB.h | 2 +- libdevcrypto/SHA3.h | 2 +- libethereum/CommonNet.cpp | 2 +- libethereum/CommonNet.h | 2 +- libevmcore/Assembly.h | 2 +- libp2p/HostCapability.h | 2 +- libwhisper/Interface.h | 2 +- mix/CodeEditorExtensionManager.cpp | 2 +- mix/CodeEditorExtensionManager.h | 2 +- mix/ConstantCompilationCtrl.cpp | 2 +- mix/ConstantCompilationCtrl.h | 2 +- mix/ConstantCompilationModel.cpp | 2 +- mix/ConstantCompilationModel.h | 2 +- mix/Extension.cpp | 2 +- mix/Extension.h | 2 +- mix/MixApplication.cpp | 2 +- mix/MixApplication.h | 2 +- test/genesis.cpp | 2 +- test/hexPrefix.cpp | 2 +- 25 files changed, 25 insertions(+), 25 deletions(-) diff --git a/alethzero/OurWebThreeStubServer.cpp b/alethzero/OurWebThreeStubServer.cpp index fec0f9e8d..0c6f42b5a 100644 --- a/alethzero/OurWebThreeStubServer.cpp +++ b/alethzero/OurWebThreeStubServer.cpp @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file OurWebThreeStubServer.h +/** @file OurWebThreeStubServer.cpp * @author Gav Wood * @date 2014 */ diff --git a/alethzero/OurWebThreeStubServer.h b/alethzero/OurWebThreeStubServer.h index ef13964b9..fb026d07e 100644 --- a/alethzero/OurWebThreeStubServer.h +++ b/alethzero/OurWebThreeStubServer.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file OurWebThreeStubServer.cpp +/** @file OurWebThreeStubServer.h * @author Gav Wood * @date 2014 */ diff --git a/libdevcore/CommonData.cpp b/libdevcore/CommonData.cpp index 215f9c4b3..fc3910cfe 100644 --- a/libdevcore/CommonData.cpp +++ b/libdevcore/CommonData.cpp @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file Common.cpp +/** @file CommonData.cpp * @author Gav Wood * @date 2014 */ diff --git a/libdevcore/CommonData.h b/libdevcore/CommonData.h index 5f14f38f8..87d2f5e28 100644 --- a/libdevcore/CommonData.h +++ b/libdevcore/CommonData.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file Common.h +/** @file CommonData.h * @author Gav Wood * @date 2014 * diff --git a/libdevcore/RangeMask.h b/libdevcore/RangeMask.h index ac58ec8b1..19262515c 100644 --- a/libdevcore/RangeMask.h +++ b/libdevcore/RangeMask.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file EthereumHost.h +/** @file RangeMask.h * @author Gav Wood * @date 2014 */ diff --git a/libdevcrypto/OverlayDB.cpp b/libdevcrypto/OverlayDB.cpp index 8ccae6606..9e110bb84 100644 --- a/libdevcrypto/OverlayDB.cpp +++ b/libdevcrypto/OverlayDB.cpp @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file TrieDB.cpp +/** @file OverlayDB.cpp * @author Gav Wood * @date 2014 */ diff --git a/libdevcrypto/OverlayDB.h b/libdevcrypto/OverlayDB.h index 777d1e7df..e9bd53343 100644 --- a/libdevcrypto/OverlayDB.h +++ b/libdevcrypto/OverlayDB.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file MemoryDB.h +/** @file OverlayDB.h * @author Gav Wood * @date 2014 */ diff --git a/libdevcrypto/SHA3.h b/libdevcrypto/SHA3.h index f27e378ba..66b8efe11 100644 --- a/libdevcrypto/SHA3.h +++ b/libdevcrypto/SHA3.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file FixedHash.h +/** @file SHA3.h * @author Gav Wood * @date 2014 * diff --git a/libethereum/CommonNet.cpp b/libethereum/CommonNet.cpp index eb92f0b18..5a9d3d0c9 100644 --- a/libethereum/CommonNet.cpp +++ b/libethereum/CommonNet.cpp @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file PeerNetwork.cpp +/** @file CommonNet.cpp * @author Gav Wood * @date 2014 */ diff --git a/libethereum/CommonNet.h b/libethereum/CommonNet.h index 4192c861e..2ee260650 100644 --- a/libethereum/CommonNet.h +++ b/libethereum/CommonNet.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file PeerNetwork.h +/** @file CommonNet.h * @author Gav Wood * @date 2014 * diff --git a/libevmcore/Assembly.h b/libevmcore/Assembly.h index b144dd8d9..5523710d4 100644 --- a/libevmcore/Assembly.h +++ b/libevmcore/Assembly.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file CodeFragment.h +/** @file Assembly.h * @author Gav Wood * @date 2014 */ diff --git a/libp2p/HostCapability.h b/libp2p/HostCapability.h index da454860a..9666ef65a 100644 --- a/libp2p/HostCapability.h +++ b/libp2p/HostCapability.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file Common.h +/** @file HostCapability.h * @author Gav Wood * @date 2014 * diff --git a/libwhisper/Interface.h b/libwhisper/Interface.h index 1af93f591..0b7b52cf7 100644 --- a/libwhisper/Interface.h +++ b/libwhisper/Interface.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file WhisperHost.h +/** @file Interface.h * @author Gav Wood * @date 2014 */ diff --git a/mix/CodeEditorExtensionManager.cpp b/mix/CodeEditorExtensionManager.cpp index c778d466f..9d0e8508d 100644 --- a/mix/CodeEditorExtensionManager.cpp +++ b/mix/CodeEditorExtensionManager.cpp @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file CodeEditorExtensionMan.cpp +/** @file CodeEditorExtensionManager.cpp * @author Yann yann@ethdev.com * @date 2014 * Ethereum IDE client. diff --git a/mix/CodeEditorExtensionManager.h b/mix/CodeEditorExtensionManager.h index 2b8402bf2..522429511 100644 --- a/mix/CodeEditorExtensionManager.h +++ b/mix/CodeEditorExtensionManager.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file CodeEditorExtensionMan.h +/** @file CodeEditorExtensionManager.h * @author Yann yann@ethdev.com * @date 2014 * Ethereum IDE client. diff --git a/mix/ConstantCompilationCtrl.cpp b/mix/ConstantCompilationCtrl.cpp index 06b9c0284..12eca8a40 100644 --- a/mix/ConstantCompilationCtrl.cpp +++ b/mix/ConstantCompilationCtrl.cpp @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file ConstantCompilation.cpp +/** @file ConstantCompilationCtrl.cpp * @author Yann yann@ethdev.com * @date 2014 * Ethereum IDE client. diff --git a/mix/ConstantCompilationCtrl.h b/mix/ConstantCompilationCtrl.h index e4661c800..8e32b7589 100644 --- a/mix/ConstantCompilationCtrl.h +++ b/mix/ConstantCompilationCtrl.h @@ -11,7 +11,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file ConstantCompilation.h +/** @file ConstantCompilationCtrl.h * @author Yann yann@ethdev.com * @date 2014 * Ethereum IDE client. diff --git a/mix/ConstantCompilationModel.cpp b/mix/ConstantCompilationModel.cpp index ea12a267c..722305763 100644 --- a/mix/ConstantCompilationModel.cpp +++ b/mix/ConstantCompilationModel.cpp @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file ApplicationCtx.h +/** @file ConstantCompilationModel.cpp * @author Yann yann@ethdev.com * @date 2014 * Ethereum IDE client. diff --git a/mix/ConstantCompilationModel.h b/mix/ConstantCompilationModel.h index 4a17853f6..9b8855a3e 100644 --- a/mix/ConstantCompilationModel.h +++ b/mix/ConstantCompilationModel.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file ApplicationCtx.h +/** @file ConstantCompilationModel.h * @author Yann yann@ethdev.com * @date 2014 * Ethereum IDE client. diff --git a/mix/Extension.cpp b/mix/Extension.cpp index 5aeb0cc17..cb1394194 100644 --- a/mix/Extension.cpp +++ b/mix/Extension.cpp @@ -11,7 +11,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file Feature.cpp +/** @file Extension.cpp * @author Yann yann@ethdev.com * @date 2014 * Ethereum IDE client. diff --git a/mix/Extension.h b/mix/Extension.h index f8fef0aa6..84fe8e2dc 100644 --- a/mix/Extension.h +++ b/mix/Extension.h @@ -11,7 +11,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file Feature.h +/** @file Extension.h * @author Yann yann@ethdev.com * @date 2014 * Ethereum IDE client. diff --git a/mix/MixApplication.cpp b/mix/MixApplication.cpp index e67ca1b12..d374188b9 100644 --- a/mix/MixApplication.cpp +++ b/mix/MixApplication.cpp @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file main.cpp +/** @file MixApplication.cpp * @author Yann yann@ethdev.com * @date 2014 */ diff --git a/mix/MixApplication.h b/mix/MixApplication.h index fdc506268..b0ea0f216 100644 --- a/mix/MixApplication.h +++ b/mix/MixApplication.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file main.cpp +/** @file MixApplication.h * @author Yann yann@ethdev.com * @date 2014 * This class will be use instead of QApplication to launch the application. the method 'notify' allows to catch all exceptions. diff --git a/test/genesis.cpp b/test/genesis.cpp index 1b354dab8..8cdb84024 100644 --- a/test/genesis.cpp +++ b/test/genesis.cpp @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file trie.cpp +/** @file genesis.cpp * @author Gav Wood * @date 2014 * Trie test functions. diff --git a/test/hexPrefix.cpp b/test/hexPrefix.cpp index 1f02bac91..551983db3 100644 --- a/test/hexPrefix.cpp +++ b/test/hexPrefix.cpp @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file main.cpp +/** @file hexPrefix.cpp * @author Gav Wood * @date 2014 * Main test functions. From 5652bd37790be8b0ce9ccb70f0220a9dfdbf8e6f Mon Sep 17 00:00:00 2001 From: Lu Guanqun Date: Sun, 14 Dec 2014 21:21:35 +0800 Subject: [PATCH 515/641] typo fix --- libp2p/Session.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libp2p/Session.h b/libp2p/Session.h index e8de1c398..cd2dbf5a7 100644 --- a/libp2p/Session.h +++ b/libp2p/Session.h @@ -110,7 +110,7 @@ private: std::array m_data; ///< Data buffer for the write queue. bytes m_incoming; ///< The incoming read queue of bytes. - PeerInfo m_info; ///< Dyanamic information about this peer. + PeerInfo m_info; ///< Dynamic information about this peer. unsigned m_protocolVersion = 0; ///< The protocol version of the peer. std::shared_ptr m_node; ///< The Node object. Might be null if we constructed using a bare address/port. From 092528d87aba350c01f58b4c24cc4405d2da2f57 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 14 Dec 2014 18:48:43 +0100 Subject: [PATCH 516/641] Minor fix for finalize. --- libethereum/Executive.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index 438505f1a..ed3077628 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -220,7 +220,8 @@ bool Executive::go(OnOpFunc const& _onOp) void Executive::finalize(OnOpFunc const&) { // SSTORE refunds. - m_endGas += min((m_t.gas() - m_endGas) / 2, m_ext->sub.refunds); + if (m_ext) + m_endGas += min((m_t.gas() - m_endGas) / 2, m_ext->sub.refunds); // cnote << "Refunding" << formatBalance(m_endGas * m_ext->gasPrice) << "to origin (=" << m_endGas << "*" << formatBalance(m_ext->gasPrice) << ")"; m_s.addBalance(m_sender, m_endGas * m_t.gasPrice()); From b6aa6efb4623674b2898607827fe4060e1e2a56f Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 14 Dec 2014 18:49:44 +0100 Subject: [PATCH 517/641] Another fix for finalize. --- libethereum/Executive.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index ed3077628..f05591ba2 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -236,5 +236,6 @@ void Executive::finalize(OnOpFunc const&) m_s.m_cache[a].kill(); // Logs - m_logs = m_ext->sub.logs; + if (m_ext) + m_logs = m_ext->sub.logs; } From 302c16ec4475c73c77f4ebd799182e4beaa8cc3a Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 14 Dec 2014 21:10:17 +0100 Subject: [PATCH 518/641] Documentation and reduction. --- libethereum/Executive.cpp | 37 ++++++++++--------- libethereum/Executive.h | 75 +++++++++++++++++++++++++++------------ libethereum/ExtVM.cpp | 4 +-- 3 files changed, 72 insertions(+), 44 deletions(-) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index f05591ba2..d16cf794c 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -40,15 +40,19 @@ u256 Executive::gasUsed() const return m_t.gas() - m_endGas; } +void Executive::accrueSubState(SubState& _parentContext) +{ + if (m_ext) + _parentContext += m_ext->sub; +} + bool Executive::setup(bytesConstRef _rlp) { // Entry point for a user-executed transaction. m_t = Transaction(_rlp); - m_sender = m_t.sender(); - // Avoid invalid transactions. - auto nonceReq = m_s.transactionsFrom(m_sender); + auto nonceReq = m_s.transactionsFrom(m_t.sender()); if (m_t.nonce() != nonceReq) { clog(StateDetail) << "Invalid Nonce: Require" << nonceReq << " Got" << m_t.nonce(); @@ -67,10 +71,10 @@ bool Executive::setup(bytesConstRef _rlp) u256 cost = m_t.value() + m_t.gas() * m_t.gasPrice(); // Avoid unaffordable transactions. - if (m_s.balance(m_sender) < cost) + if (m_s.balance(m_t.sender()) < cost) { - clog(StateDetail) << "Not enough cash: Require >" << cost << " Got" << m_s.balance(m_sender); - BOOST_THROW_EXCEPTION(NotEnoughCash() << RequirementError((bigint)cost, (bigint)m_s.balance(m_sender))); + clog(StateDetail) << "Not enough cash: Require >" << cost << " Got" << m_s.balance(m_t.sender()); + BOOST_THROW_EXCEPTION(NotEnoughCash() << RequirementError((bigint)cost, (bigint)m_s.balance(m_t.sender()))); } u256 startGasUsed = m_s.gasUsed(); @@ -81,16 +85,16 @@ bool Executive::setup(bytesConstRef _rlp) } // Increment associated nonce for sender. - m_s.noteSending(m_sender); + m_s.noteSending(m_t.sender()); // Pay... clog(StateDetail) << "Paying" << formatBalance(cost) << "from sender (includes" << m_t.gas() << "gas at" << formatBalance(m_t.gasPrice()) << ")"; - m_s.subBalance(m_sender, cost); + m_s.subBalance(m_t.sender(), cost); if (m_t.isCreation()) - return create(m_sender, m_t.value(), m_t.gasPrice(), m_t.gas() - (u256)gasCost, &m_t.data(), m_sender); + return create(m_t.sender(), m_t.value(), m_t.gasPrice(), m_t.gas() - (u256)gasCost, &m_t.data(), m_t.sender()); else - return call(m_t.receiveAddress(), m_t.receiveAddress(), m_sender, m_t.value(), m_t.gasPrice(), bytesConstRef(&m_t.data()), m_t.gas() - (u256)gasCost, m_sender); + return call(m_t.receiveAddress(), m_t.receiveAddress(), m_t.sender(), m_t.value(), m_t.gasPrice(), bytesConstRef(&m_t.data()), m_t.gas() - (u256)gasCost, m_t.sender()); } bool Executive::call(Address _receiveAddress, Address _codeAddress, Address _senderAddress, u256 _value, u256 _gasPrice, bytesConstRef _data, u256 _gas, Address _originAddress) @@ -212,22 +216,17 @@ bool Executive::go(OnOpFunc const& _onOp) return true; } -/*u256 Executive::gas() const -{ - return m_vm ? m_vm->gas() : m_endGas; -}*/ - void Executive::finalize(OnOpFunc const&) { - // SSTORE refunds. + // SSTORE refunds... + // must be done before the miner gets the fees. if (m_ext) m_endGas += min((m_t.gas() - m_endGas) / 2, m_ext->sub.refunds); // cnote << "Refunding" << formatBalance(m_endGas * m_ext->gasPrice) << "to origin (=" << m_endGas << "*" << formatBalance(m_ext->gasPrice) << ")"; - m_s.addBalance(m_sender, m_endGas * m_t.gasPrice()); + m_s.addBalance(m_t.sender(), m_endGas * m_t.gasPrice()); u256 feesEarned = (m_t.gas() - m_endGas) * m_t.gasPrice(); -// cnote << "Transferring" << formatBalance(gasSpent) << "to miner."; m_s.addBalance(m_s.m_currentBlock.coinbaseAddress, feesEarned); // Suicides... @@ -235,7 +234,7 @@ void Executive::finalize(OnOpFunc const&) for (auto a: m_ext->sub.suicides) m_s.m_cache[a].kill(); - // Logs + // Logs.. if (m_ext) m_logs = m_ext->sub.logs; } diff --git a/libethereum/Executive.h b/libethereum/Executive.h index c5baada1d..729014bef 100644 --- a/libethereum/Executive.h +++ b/libethereum/Executive.h @@ -39,53 +39,82 @@ struct Manifest; struct VMTraceChannel: public LogChannel { static const char* name() { return "EVM"; } static const int verbosity = 11; }; - +/** + * @brief Message-call/contract-creation executor; useful for executing transactions. + * + * Two ways of using this class - either as a transaction executive or a CALL/CREATE executive. + * In the first use, after construction, begin with setup() and end with finalize(). Call go() + * after setup() only if it returns false. + * In the second use, after construction, begin with call() or create() and end with + * accrueSubState(). Call go() after call()/create() only if it returns false. + */ class Executive { public: + /// Basic constructor. Executive(State& _s, unsigned _level): m_s(_s), m_depth(_level) {} + /// Basic destructor. ~Executive() = default; + Executive(Executive const&) = delete; void operator=(Executive) = delete; + /// Set up the executive for evaluating a transaction. You must call finalize() following this. + /// @returns true iff go() must be called (and thus a VM execution in required). bool setup(bytesConstRef _transaction); + /// Finalise a transaction previously set up with setup(). + /// @warning Only valid after setup(), and possibly go(). + void finalize(OnOpFunc const& _onOp = OnOpFunc()); + /// @returns the transaction from setup(). + /// @warning Only valid after setup(). + Transaction const& t() const { return m_t; } + /// @returns the log entries created by this operation. + /// @warning Only valid after finalise(). + LogEntries const& logs() const { return m_logs; } + /// @returns total gas used in the transaction/operation. + /// @warning Only valid after finalise(). + u256 gasUsed() const; + + /// Set up the executive for evaluating a bare CREATE (contract-creation) operation. + /// @returns false iff go() must be called (and thus a VM execution in required). bool create(Address _txSender, u256 _endowment, u256 _gasPrice, u256 _gas, bytesConstRef _code, Address _originAddress); + /// Set up the executive for evaluating a bare CALL (message call) operation. + /// @returns false iff go() must be called (and thus a VM execution in required). bool call(Address _myAddress, Address _codeAddress, Address _txSender, u256 _txValue, u256 _gasPrice, bytesConstRef _txData, u256 _gas, Address _originAddress); + /// Finalise an operation through accruing the substate into the parent context. + void accrueSubState(SubState& _parentContext); + + /// Executes (or continues execution of) the VM. + /// @returns false iff go() must be called again to finish the transction. bool go(OnOpFunc const& _onOp = OnOpFunc()); - void finalize(OnOpFunc const& _onOp = OnOpFunc()); - u256 gasUsed() const; + /// Operation function for providing a simple trace of the VM execution. static OnOpFunc simpleTrace(); - Transaction const& t() const { return m_t; } - + /// @returns gas remaining after the transaction/operation. u256 endGas() const { return m_endGas; } - + /// @returns output data of the transaction/operation. bytesConstRef out() const { return m_out; } + /// @returns the new address for the created contract in the CREATE operation. h160 newAddress() const { return m_newAddress; } - LogEntries const& logs() const { return m_logs; } + /// @returns true iff the operation ended with a VM exception. bool excepted() const { return m_excepted; } - VMFace const& vm() const { return *m_vm; } - ExtVM const& ext() const { return *m_ext; } - State const& state() const { return m_s; } - private: - State& m_s; - std::shared_ptr m_ext; - std::unique_ptr m_vm; + State& m_s; ///< The state to which this operation/transaction is applied. + std::shared_ptr m_ext; ///< The VM externality object for the VM execution or null if no VM is required. + std::unique_ptr m_vm; ///< The VM object or null if no VM is required. bytes m_precompiledOut; ///< Used for the output when there is no VM for a contract (i.e. precompiled). - bytesConstRef m_out; ///< Holds the copyable output. - Address m_newAddress; + bytesConstRef m_out; ///< The copyable output. + Address m_newAddress; ///< The address of the created contract in the case of create() being called. - Transaction m_t; - bool m_isCreation; - bool m_excepted = false; - unsigned m_depth = 0; - Address m_sender; - u256 m_endGas; + unsigned m_depth = 0; ///< The context's call-depth. + bool m_isCreation = false; ///< True if the transaction creates a contract, or if create() is called. + bool m_excepted = false; ///< True if the VM execution resulted in an exception. + u256 m_endGas; ///< The final amount of gas for the transaction. - LogEntries m_logs; + Transaction m_t; ///< The original transaction in the case that setup() was called. + LogEntries m_logs; ///< The log entries created by this transaction. Only valid }; } diff --git a/libethereum/ExtVM.cpp b/libethereum/ExtVM.cpp index fcd703b25..a005a030b 100644 --- a/libethereum/ExtVM.cpp +++ b/libethereum/ExtVM.cpp @@ -32,7 +32,7 @@ bool ExtVM::call(Address _receiveAddress, u256 _txValue, bytesConstRef _txData, if (!e.call(_receiveAddress, _codeAddressOverride ? _codeAddressOverride : _receiveAddress, _myAddressOverride ? _myAddressOverride : myAddress, _txValue, gasPrice, _txData, io_gas, origin)) { e.go(_onOp); - sub += e.ext().sub; + e.accrueSubState(sub); } io_gas = e.endGas(); e.out().copyTo(_out); @@ -49,7 +49,7 @@ h160 ExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _code, OnOpFunc if (!e.create(myAddress, _endowment, gasPrice, io_gas, _code, origin)) { e.go(_onOp); - sub += e.ext().sub; + e.accrueSubState(sub); } io_gas = e.endGas(); return e.newAddress(); From 8eee0a2033d3539ffc1bf311a5021322d7bc4fe5 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 15 Dec 2014 01:02:33 +0100 Subject: [PATCH 519/641] Correctly check for string prefix plus indentation change. --- libsolidity/ExpressionCompiler.cpp | 2 +- libsolidity/Types.cpp | 20 ++++++++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index add5f73be..f872e0581 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -291,7 +291,7 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) IntegerType(0, IntegerType::Modifier::ADDRESS), true); m_context << eth::Instruction::BALANCE; } - else if (member == "send" || member.substr(0, 4) == "call") + else if (member == "send" || member.substr(0, min(member.size(), 4)) == "call") appendTypeConversion(*_memberAccess.getExpression().getType(), IntegerType(0, IntegerType::Modifier::ADDRESS), true); else diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index a0a809b9b..c2d488418 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -193,14 +193,18 @@ u256 IntegerType::literalValue(Literal const& _literal) const } const MemberList IntegerType::AddressMemberList = - MemberList({{"balance", make_shared(256)}, - {"callstring32", make_shared(TypePointers({make_shared(32)}), - TypePointers(), FunctionType::Location::BARE)}, - {"callstring32string32", make_shared(TypePointers({make_shared(32), - make_shared(32)}), - TypePointers(), FunctionType::Location::BARE)}, - {"send", make_shared(TypePointers({make_shared(256)}), - TypePointers(), FunctionType::Location::SEND)}}); + MemberList({{"balance", + make_shared(256)}, + {"callstring32", + make_shared(TypePointers({make_shared(32)}), + TypePointers(), FunctionType::Location::BARE)}, + {"callstring32string32", + make_shared(TypePointers({make_shared(32), + make_shared(32)}), + TypePointers(), FunctionType::Location::BARE)}, + {"send", + make_shared(TypePointers({make_shared(256)}), + TypePointers(), FunctionType::Location::SEND)}}); shared_ptr StaticStringType::smallestTypeForLiteral(string const& _literal) { From d76b3f472e1751ec3f4d080c16bdaf1fe7e3b1e0 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 15 Dec 2014 09:57:10 +0100 Subject: [PATCH 520/641] - Send String value to QML instead of int value (gas, gasCost, gasLeft). - Wrap label with QApplication::tr (localization). - Use of std::hex, std::dec instead of QTextStream (to avoid warning). --- mix/DebuggingStateWrapper.cpp | 41 +++++++++++++++++++++++++---------- mix/DebuggingStateWrapper.h | 10 +++++---- mix/qml/js/Debugger.js | 5 ++--- 3 files changed, 38 insertions(+), 18 deletions(-) diff --git a/mix/DebuggingStateWrapper.cpp b/mix/DebuggingStateWrapper.cpp index 2315cd5a8..36b098379 100644 --- a/mix/DebuggingStateWrapper.cpp +++ b/mix/DebuggingStateWrapper.cpp @@ -20,9 +20,8 @@ * Used to translate c++ type (u256, bytes, ...) into friendly value (to be used by QML). */ +#include #include -#include -#include #include "libevmcore/Instruction.h" #include "libdevcore/CommonJS.h" #include "libdevcrypto/Common.h" @@ -44,7 +43,7 @@ std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCod { QString s = QString::fromStdString(instructionInfo((Instruction)b).name); std::ostringstream out; - out << hex << std::setw(4) << std::setfill('0') << i; + out << std::hex << std::setw(4) << std::setfill('0') << i; codeMapping[i] = codeStr.size(); int line = i; if (b >= (byte)Instruction::PUSH1 && b <= (byte)Instruction::PUSH32) @@ -66,6 +65,27 @@ std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCod return std::make_tuple(codeStr, new QQMLMap(codeMapping, _objUsedAsParent)); } +QString DebuggingStateWrapper::gasLeft() +{ + std::ostringstream ss; + ss << std::dec << (m_state.gas - m_state.gasCost); + return QString::fromStdString(ss.str()); +} + +QString DebuggingStateWrapper::gasCost() +{ + std::ostringstream ss; + ss << std::dec << m_state.gasCost; + return QString::fromStdString(ss.str()); +} + +QString DebuggingStateWrapper::gas() +{ + std::ostringstream ss; + ss << std::dec << m_state.gas; + return QString::fromStdString(ss.str()); +} + QString DebuggingStateWrapper::debugStack() { QString stack; @@ -99,11 +119,10 @@ QStringList DebuggingStateWrapper::levels() QStringList levelsStr; for (unsigned i = 0; i <= m_state.levels.size(); ++i) { - DebuggingState const& s = i ? *m_state.levels[m_state.levels.size() - i] : m_state; std::ostringstream out; out << m_state.cur.abridged(); if (i) - out << " " << instructionInfo(m_state.inst).name << " @0x" << hex << m_state.curPC; + out << " " << instructionInfo(m_state.inst).name << " @0x" << std::hex << m_state.curPC; levelsStr.append(QString::fromStdString(out.str())); } return levelsStr; @@ -112,14 +131,14 @@ QStringList DebuggingStateWrapper::levels() QString DebuggingStateWrapper::headerInfo() { std::ostringstream ss; - ss << dec << " STEP: " << m_state.steps << " | PC: 0x" << hex << m_state.curPC << " : " << dev::eth::instructionInfo(m_state.inst).name << " | ADDMEM: " << dec << m_state.newMemSize << " words | COST: " << dec << m_state.gasCost << " | GAS: " << dec << m_state.gas; + ss << std::dec << " " << QApplication::tr("STEP").toStdString() << " : " << m_state.steps << " | PC: 0x" << std::hex << m_state.curPC << " : " << dev::eth::instructionInfo(m_state.inst).name << " | ADDMEM: " << std::dec << m_state.newMemSize << " " << QApplication::tr("words").toStdString() << " | " << QApplication::tr("COST").toStdString() << " : " << std::dec << m_state.gasCost << " | " << QApplication::tr("GAS").toStdString() << " : " << std::dec << m_state.gas; return QString::fromStdString(ss.str()); } QString DebuggingStateWrapper::endOfDebug() { if (m_state.gasCost > m_state.gas) - return "OUT-OF-GAS"; + return QApplication::tr("OUT-OF-GAS"); else if (m_state.inst == Instruction::RETURN && m_state.stack.size() >= 2) { unsigned from = (unsigned)m_state.stack.back(); @@ -128,12 +147,12 @@ QString DebuggingStateWrapper::endOfDebug() bytes out(size, 0); for (; o < size && from + o < m_state.memory.size(); ++o) out[o] = m_state.memory[from + o]; - return "RETURN " + QString::fromStdString(dev::memDump(out, 16, false)); + return QApplication::tr("RETURN") + " " + QString::fromStdString(dev::memDump(out, 16, false)); } else if (m_state.inst == Instruction::STOP) - return "STOP"; + return QApplication::tr("STOP"); else if (m_state.inst == Instruction::SUICIDE && m_state.stack.size() >= 1) - return "SUICIDE 0x" + QString::fromStdString(toString(right160(m_state.stack.back()))); + return QApplication::tr("SUICIDE") + " 0x" + QString::fromStdString(toString(right160(m_state.stack.back()))); else - return "EXCEPTION"; + return QApplication::tr("EXCEPTION"); } diff --git a/mix/DebuggingStateWrapper.h b/mix/DebuggingStateWrapper.h index 09089fe58..d91d3d69c 100644 --- a/mix/DebuggingStateWrapper.h +++ b/mix/DebuggingStateWrapper.h @@ -99,8 +99,9 @@ class DebuggingStateWrapper: public QObject Q_OBJECT Q_PROPERTY(int step READ step) Q_PROPERTY(int curPC READ curPC) - Q_PROPERTY(int gasCost READ gasCost) - Q_PROPERTY(int gas READ gas) + Q_PROPERTY(QString gasCost READ gasCost) + Q_PROPERTY(QString gas READ gas) + Q_PROPERTY(QString gasLeft READ gasLeft) Q_PROPERTY(QString debugStack READ debugStack) Q_PROPERTY(QString debugStorage READ debugStorage) Q_PROPERTY(QString debugMemory READ debugMemory) @@ -113,8 +114,9 @@ public: DebuggingStateWrapper(bytes _code, bytes _data, QObject* _parent): QObject(_parent), m_code(_code), m_data(_data) {} int step() { return (int)m_state.steps; } int curPC() { return (int)m_state.curPC; } - int gasCost() { return (int)m_state.gasCost; } - int gas() { return (int)m_state.gas; } + QString gasLeft(); + QString gasCost(); + QString gas(); QString debugStack(); QString debugStorage(); QString debugMemory(); diff --git a/mix/qml/js/Debugger.js b/mix/qml/js/Debugger.js index ddaa362a6..5cd88d726 100644 --- a/mix/qml/js/Debugger.js +++ b/mix/qml/js/Debugger.js @@ -57,7 +57,6 @@ function endOfDebug() debugStorageTxt.text = ""; debugCallDataTxt.text = ""; debugStackTxt.text = ""; - debugMemoryTxt.text = state.endOfDebug - var gascost = state.gas - state.gasCost; - headerInfoLabel.text = "EXIT | GAS: " + gascost; + debugMemoryTxt.text = state.endOfDebug; + headerInfoLabel.text = "EXIT | GAS: " + state.gasLeft; } From f42f24165bc9f2385d5d9779eb540fd86acee87b Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 15 Dec 2014 10:43:22 +0100 Subject: [PATCH 521/641] Bugfix: Avoid accessing temporary after its lifetime. --- eth/main.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index 49eac8876..1520e86c4 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -441,9 +441,8 @@ int main(int argc, char** argv) #endif else if (cmd == "address") { - cout << "Current address:" << endl; - const char* addchr = toHex(us.address().asArray()).c_str(); - cout << addchr << endl; + cout << "Current address:" << endl + << toHex(us.address().asArray()) << endl; } else if (cmd == "secret") { From 5026c5855ded326a5ea7e675d8c084ccda88c8ee Mon Sep 17 00:00:00 2001 From: Christian Date: Fri, 12 Dec 2014 16:49:26 +0100 Subject: [PATCH 522/641] Create contracts. --- libsolidity/AST.cpp | 38 ++++++++++++++++++++++++++---- libsolidity/AST.h | 28 ++++++++++++++++++++++ libsolidity/ASTForward.h | 1 + libsolidity/ASTPrinter.cpp | 13 ++++++++++ libsolidity/ASTPrinter.h | 2 ++ libsolidity/ASTVisitor.h | 4 ++++ libsolidity/AST_accept.h | 20 ++++++++++++++++ libsolidity/Compiler.cpp | 17 ++++++++----- libsolidity/Compiler.h | 6 +++-- libsolidity/CompilerContext.cpp | 8 +++++++ libsolidity/CompilerContext.h | 12 +++++++--- libsolidity/CompilerStack.cpp | 6 ++++- libsolidity/CompilerStack.h | 2 +- libsolidity/ExpressionCompiler.cpp | 38 ++++++++++++++++++++++++++++++ libsolidity/ExpressionCompiler.h | 1 + libsolidity/InterfaceHandler.cpp | 8 +++---- libsolidity/InterfaceHandler.h | 8 +++---- libsolidity/Parser.cpp | 12 +++++++++- libsolidity/Types.cpp | 13 ++++++++++ libsolidity/Types.h | 11 +++++++-- libsolidity/grammar.txt | 3 ++- test/solidityCompiler.cpp | 2 +- 22 files changed, 222 insertions(+), 31 deletions(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 8174d138a..3fcf8ba0b 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -54,6 +54,14 @@ vector ContractDefinition::getInterfaceFunctions() co return exportedFunctions; } +FunctionDefinition const* ContractDefinition::getConstructor() const +{ + for (ASTPointer const& f: m_definedFunctions) + if (f->getName() == getName()) + return f.get(); + return nullptr; +} + void StructDefinition::checkMemberTypes() const { for (ASTPointer const& member: getMembers()) @@ -235,13 +243,12 @@ void FunctionCall::checkTypeRequirements() BOOST_THROW_EXCEPTION(createTypeError("Explicit type conversion not allowed.")); m_type = type.getActualType(); } - else + else if (FunctionType const* functionType = dynamic_cast(expressionType)) { //@todo would be nice to create a struct type from the arguments // and then ask if that is implicitly convertible to the struct represented by the // function parameters - FunctionType const& functionType = dynamic_cast(*expressionType); - TypePointers const& parameterTypes = functionType.getParameterTypes(); + TypePointers const& parameterTypes = functionType->getParameterTypes(); if (parameterTypes.size() != m_arguments.size()) BOOST_THROW_EXCEPTION(createTypeError("Wrong argument count for function call.")); for (size_t i = 0; i < m_arguments.size(); ++i) @@ -249,11 +256,13 @@ void FunctionCall::checkTypeRequirements() BOOST_THROW_EXCEPTION(createTypeError("Invalid type for argument in function call.")); // @todo actually the return type should be an anonymous struct, // but we change it to the type of the first return value until we have structs - if (functionType.getReturnParameterTypes().empty()) + if (functionType->getReturnParameterTypes().empty()) m_type = make_shared(); else - m_type = functionType.getReturnParameterTypes().front(); + m_type = functionType->getReturnParameterTypes().front(); } + else + BOOST_THROW_EXCEPTION(createTypeError("Type is not callable.")); } bool FunctionCall::isTypeConversion() const @@ -261,6 +270,25 @@ bool FunctionCall::isTypeConversion() const return m_expression->getType()->getCategory() == Type::Category::TYPE; } +void NewExpression::checkTypeRequirements() +{ + m_contractName->checkTypeRequirements(); + for (ASTPointer const& argument: m_arguments) + argument->checkTypeRequirements(); + + m_contract = dynamic_cast(m_contractName->getReferencedDeclaration()); + if (!m_contract) + BOOST_THROW_EXCEPTION(createTypeError("Identifier is not a contract.")); + shared_ptr type = make_shared(*m_contract); + m_type = type; + TypePointers const& parameterTypes = type->getConstructorType()->getParameterTypes(); + if (parameterTypes.size() != m_arguments.size()) + BOOST_THROW_EXCEPTION(createTypeError("Wrong argument count for constructor call.")); + for (size_t i = 0; i < m_arguments.size(); ++i) + if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[i])) + BOOST_THROW_EXCEPTION(createTypeError("Invalid type for argument in constructor call.")); +} + void MemberAccess::checkTypeRequirements() { m_expression->checkTypeRequirements(); diff --git a/libsolidity/AST.h b/libsolidity/AST.h index 19c4b4275..3a15bbebe 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -181,6 +181,9 @@ public: /// Returns the functions that make up the calling interface in the intended order. std::vector getInterfaceFunctions() const; + /// Returns the constructor or nullptr if no constructor was specified + FunctionDefinition const* getConstructor() const; + private: std::vector> m_definedStructs; std::vector> m_stateVariables; @@ -740,6 +743,31 @@ private: std::vector> m_arguments; }; +/** + * Expression that creates a new contract, e.g. "new SomeContract(1, 2)". + */ +class NewExpression: public Expression +{ +public: + NewExpression(Location const& _location, ASTPointer const& _contractName, + std::vector> const& _arguments): + Expression(_location), m_contractName(_contractName), m_arguments(_arguments) {} + virtual void accept(ASTVisitor& _visitor) override; + virtual void accept(ASTConstVisitor& _visitor) const override; + virtual void checkTypeRequirements() override; + + std::vector> getArguments() const { return {m_arguments.begin(), m_arguments.end()}; } + + /// Returns the referenced contract. Can only be called after type checking. + ContractDefinition const* getContract() const { return m_contract; } + +private: + ASTPointer m_contractName; + std::vector> m_arguments; + + ContractDefinition const* m_contract = nullptr; +}; + /** * Access to a member of an object. Example: x.name */ diff --git a/libsolidity/ASTForward.h b/libsolidity/ASTForward.h index 8b4bac1ce..d6c4c9f44 100644 --- a/libsolidity/ASTForward.h +++ b/libsolidity/ASTForward.h @@ -62,6 +62,7 @@ class Assignment; class UnaryOperation; class BinaryOperation; class FunctionCall; +class NewExpression; class MemberAccess; class IndexAccess; class PrimaryExpression; diff --git a/libsolidity/ASTPrinter.cpp b/libsolidity/ASTPrinter.cpp index eddb51340..970822a9a 100644 --- a/libsolidity/ASTPrinter.cpp +++ b/libsolidity/ASTPrinter.cpp @@ -226,6 +226,14 @@ bool ASTPrinter::visit(FunctionCall const& _node) return goDeeper(); } +bool ASTPrinter::visit(NewExpression const& _node) +{ + writeLine("NewExpression"); + printType(_node); + printSourcePart(_node); + return goDeeper(); +} + bool ASTPrinter::visit(MemberAccess const& _node) { writeLine("MemberAccess to member " + _node.getMemberName()); @@ -402,6 +410,11 @@ void ASTPrinter::endVisit(FunctionCall const&) m_indentation--; } +void ASTPrinter::endVisit(NewExpression const&) +{ + m_indentation--; +} + void ASTPrinter::endVisit(MemberAccess const&) { m_indentation--; diff --git a/libsolidity/ASTPrinter.h b/libsolidity/ASTPrinter.h index 5a9187154..15b65e3f0 100644 --- a/libsolidity/ASTPrinter.h +++ b/libsolidity/ASTPrinter.h @@ -67,6 +67,7 @@ public: bool visit(UnaryOperation const& _node) override; bool visit(BinaryOperation const& _node) override; bool visit(FunctionCall const& _node) override; + bool visit(NewExpression const& _node) override; bool visit(MemberAccess const& _node) override; bool visit(IndexAccess const& _node) override; bool visit(PrimaryExpression const& _node) override; @@ -99,6 +100,7 @@ public: void endVisit(UnaryOperation const&) override; void endVisit(BinaryOperation const&) override; void endVisit(FunctionCall const&) override; + void endVisit(NewExpression const&) override; void endVisit(MemberAccess const&) override; void endVisit(IndexAccess const&) override; void endVisit(PrimaryExpression const&) override; diff --git a/libsolidity/ASTVisitor.h b/libsolidity/ASTVisitor.h index 4e1a49458..5728cd3d0 100644 --- a/libsolidity/ASTVisitor.h +++ b/libsolidity/ASTVisitor.h @@ -68,6 +68,7 @@ public: virtual bool visit(UnaryOperation&) { return true; } virtual bool visit(BinaryOperation&) { return true; } virtual bool visit(FunctionCall&) { return true; } + virtual bool visit(NewExpression&) { return true; } virtual bool visit(MemberAccess&) { return true; } virtual bool visit(IndexAccess&) { return true; } virtual bool visit(PrimaryExpression&) { return true; } @@ -102,6 +103,7 @@ public: virtual void endVisit(UnaryOperation&) { } virtual void endVisit(BinaryOperation&) { } virtual void endVisit(FunctionCall&) { } + virtual void endVisit(NewExpression&) { } virtual void endVisit(MemberAccess&) { } virtual void endVisit(IndexAccess&) { } virtual void endVisit(PrimaryExpression&) { } @@ -140,6 +142,7 @@ public: virtual bool visit(UnaryOperation const&) { return true; } virtual bool visit(BinaryOperation const&) { return true; } virtual bool visit(FunctionCall const&) { return true; } + virtual bool visit(NewExpression const&) { return true; } virtual bool visit(MemberAccess const&) { return true; } virtual bool visit(IndexAccess const&) { return true; } virtual bool visit(PrimaryExpression const&) { return true; } @@ -174,6 +177,7 @@ public: virtual void endVisit(UnaryOperation const&) { } virtual void endVisit(BinaryOperation const&) { } virtual void endVisit(FunctionCall const&) { } + virtual void endVisit(NewExpression const&) { } virtual void endVisit(MemberAccess const&) { } virtual void endVisit(IndexAccess const&) { } virtual void endVisit(PrimaryExpression const&) { } diff --git a/libsolidity/AST_accept.h b/libsolidity/AST_accept.h index 173273c6d..e0454d33e 100644 --- a/libsolidity/AST_accept.h +++ b/libsolidity/AST_accept.h @@ -419,6 +419,26 @@ void FunctionCall::accept(ASTConstVisitor& _visitor) const _visitor.endVisit(*this); } +void NewExpression::accept(ASTVisitor& _visitor) +{ + if (_visitor.visit(*this)) + { + m_contractName->accept(_visitor); + listAccept(m_arguments, _visitor); + } + _visitor.endVisit(*this); +} + +void NewExpression::accept(ASTConstVisitor& _visitor) const +{ + if (_visitor.visit(*this)) + { + m_contractName->accept(_visitor); + listAccept(m_arguments, _visitor); + } + _visitor.endVisit(*this); +} + void MemberAccess::accept(ASTVisitor& _visitor) { if (_visitor.visit(*this)) diff --git a/libsolidity/Compiler.cpp b/libsolidity/Compiler.cpp index 258336917..48d8be88a 100644 --- a/libsolidity/Compiler.cpp +++ b/libsolidity/Compiler.cpp @@ -33,9 +33,11 @@ using namespace std; namespace dev { namespace solidity { -void Compiler::compileContract(ContractDefinition const& _contract, vector const& _magicGlobals) +void Compiler::compileContract(ContractDefinition const& _contract, vector const& _magicGlobals, + map const& _contracts) { m_context = CompilerContext(); // clear it just in case + m_context.setCompiledContracts(_contracts); for (MagicVariableDeclaration const* variable: _magicGlobals) m_context.addMagicGlobal(*variable); @@ -50,12 +52,14 @@ void Compiler::compileContract(ContractDefinition const& _contract, vectorgetName() != _contract.getName()) // don't add the constructor here function->accept(*this); - packIntoContractCreator(_contract); + packIntoContractCreator(_contract, _contracts); } -void Compiler::packIntoContractCreator(ContractDefinition const& _contract) +void Compiler::packIntoContractCreator(ContractDefinition const& _contract, + map const& _contracts) { CompilerContext runtimeContext; + runtimeContext.setCompiledContracts(_contracts); swap(m_context, runtimeContext); registerStateVariables(_contract); @@ -67,11 +71,14 @@ void Compiler::packIntoContractCreator(ContractDefinition const& _contract) constructor = function.get(); break; } + eth::AssemblyItem sub = m_context.addSubroutine(runtimeContext.getAssembly()); + // stack contains sub size if (constructor) { eth::AssemblyItem returnTag = m_context.pushNewTag(); m_context.addFunction(*constructor); // note that it cannot be called due to syntactic reasons - //@todo copy constructor arguments from calldata to memory prior to this + // copy constructor arguments + //@todo ask assembly for the size of the current program //@todo calling other functions inside the constructor should either trigger a parse error //or we should copy them here (register them above and call "accept") - detecting which // functions are referenced / called needs to be done in a recursive way. @@ -81,8 +88,6 @@ void Compiler::packIntoContractCreator(ContractDefinition const& _contract) m_context << returnTag; } - eth::AssemblyItem sub = m_context.addSubroutine(runtimeContext.getAssembly()); - // stack contains sub size m_context << eth::Instruction::DUP1 << sub << u256(0) << eth::Instruction::CODECOPY; m_context << u256(0) << eth::Instruction::RETURN; } diff --git a/libsolidity/Compiler.h b/libsolidity/Compiler.h index 639e98410..57e40cdae 100644 --- a/libsolidity/Compiler.h +++ b/libsolidity/Compiler.h @@ -32,14 +32,16 @@ class Compiler: private ASTConstVisitor public: explicit Compiler(bool _optimize = false): m_optimize(_optimize), m_returnTag(m_context.newTag()) {} - void compileContract(ContractDefinition const& _contract, std::vector const& _magicGlobals); + void compileContract(ContractDefinition const& _contract, std::vector const& _magicGlobals, + std::map const& _contracts); bytes getAssembledBytecode() { return m_context.getAssembledBytecode(m_optimize); } void streamAssembly(std::ostream& _stream) const { m_context.streamAssembly(_stream); } private: /// Creates a new compiler context / assembly, packs the current code into the data part and /// adds the constructor code. - void packIntoContractCreator(ContractDefinition const& _contract); + void packIntoContractCreator(ContractDefinition const& _contract, + std::map const& _contracts); void appendFunctionSelector(ContractDefinition const& _contract); /// Creates code that unpacks the arguments for the given function, from memory if /// @a _fromMemory is true, otherwise from call data. @returns the size of the data in bytes. diff --git a/libsolidity/CompilerContext.cpp b/libsolidity/CompilerContext.cpp index cd22c4e8b..47401436a 100644 --- a/libsolidity/CompilerContext.cpp +++ b/libsolidity/CompilerContext.cpp @@ -62,6 +62,14 @@ void CompilerContext::addFunction(FunctionDefinition const& _function) m_functionEntryLabels.insert(std::make_pair(&_function, m_asm.newTag())); } +bytes const& CompilerContext::getCompiledContract(const ContractDefinition& _contract) const +{ + auto ret = m_compiledContracts.find(&_contract); + if (asserts(ret != m_compiledContracts.end())) + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Compiled contract not found.")); + return *ret->second; +} + bool CompilerContext::isLocalVariable(Declaration const* _declaration) const { return m_localVariables.count(_declaration) > 0; diff --git a/libsolidity/CompilerContext.h b/libsolidity/CompilerContext.h index 652e65a63..99f5ae94c 100644 --- a/libsolidity/CompilerContext.h +++ b/libsolidity/CompilerContext.h @@ -39,8 +39,6 @@ namespace solidity { class CompilerContext { public: - CompilerContext(): m_stateVariablesSize(0) {} - void addMagicGlobal(MagicVariableDeclaration const& _declaration); void addStateVariable(VariableDeclaration const& _declaration); void startNewFunction() { m_localVariables.clear(); m_asm.setDeposit(0); } @@ -48,6 +46,9 @@ public: void addAndInitializeVariable(VariableDeclaration const& _declaration); void addFunction(FunctionDefinition const& _function); + void setCompiledContracts(std::map const& _contracts) { m_compiledContracts = _contracts; } + bytes const& getCompiledContract(ContractDefinition const& _contract) const; + void adjustStackOffset(int _adjustment) { m_asm.adjustDeposit(_adjustment); } bool isMagicGlobal(Declaration const* _declaration) const { return m_magicGlobals.count(_declaration); } @@ -80,6 +81,8 @@ public: /// Adds a subroutine to the code (in the data section) and pushes its size (via a tag) /// on the stack. @returns the assembly item corresponding to the pushed subroutine, i.e. its offset. eth::AssemblyItem addSubroutine(eth::Assembly const& _assembly) { return m_asm.appendSubSize(_assembly); } + /// Adds data to the data section, pushes a reference to the stack + eth::AssemblyItem appendData(bytes const& _data) { return m_asm.append(_data); } /// Append elements to the current instruction list and adjust @a m_stackOffset. CompilerContext& operator<<(eth::AssemblyItem const& _item) { m_asm.append(_item); return *this; } @@ -90,13 +93,16 @@ public: eth::Assembly const& getAssembly() const { return m_asm; } void streamAssembly(std::ostream& _stream) const { _stream << m_asm; } bytes getAssembledBytecode(bool _optimize = false) { return m_asm.optimise(_optimize).assemble(); } + private: eth::Assembly m_asm; /// Magic global variables like msg, tx or this, distinguished by type. std::set m_magicGlobals; + /// Other already compiled contracts to be used in contract creation calls. + std::map m_compiledContracts; /// Size of the state variables, offset of next variable to be added. - u256 m_stateVariablesSize; + u256 m_stateVariablesSize = 0; /// Storage offsets of state variables std::map m_stateVariables; /// Offsets of local variables on the stack (relative to stack base). diff --git a/libsolidity/CompilerStack.cpp b/libsolidity/CompilerStack.cpp index 7aaa79b1c..23f5fd68f 100644 --- a/libsolidity/CompilerStack.cpp +++ b/libsolidity/CompilerStack.cpp @@ -96,16 +96,20 @@ void CompilerStack::compile(bool _optimize) { if (!m_parseSuccessful) parse(); + + map contractBytecode; for (Source const* source: m_sourceOrder) for (ASTPointer const& node: source->ast->getNodes()) if (ContractDefinition* contract = dynamic_cast(node.get())) { m_globalContext->setCurrentContract(*contract); shared_ptr compiler = make_shared(_optimize); - compiler->compileContract(*contract, m_globalContext->getMagicVariables()); + compiler->compileContract(*contract, m_globalContext->getMagicVariables(), + contractBytecode); Contract& compiledContract = m_contracts[contract->getName()]; compiledContract.bytecode = compiler->getAssembledBytecode(); compiledContract.compiler = move(compiler); + contractBytecode[compiledContract.contract] = &compiledContract.bytecode; } } diff --git a/libsolidity/CompilerStack.h b/libsolidity/CompilerStack.h index b6c34f1ac..5ad6f0a60 100644 --- a/libsolidity/CompilerStack.h +++ b/libsolidity/CompilerStack.h @@ -108,7 +108,7 @@ private: struct Contract { - ContractDefinition* contract; + ContractDefinition const* contract; std::shared_ptr compiler; bytes bytecode; std::shared_ptr interfaceHandler; diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index f872e0581..743503bbf 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -279,6 +279,44 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) return false; } +bool ExpressionCompiler::visit(NewExpression const& _newExpression) +{ + ContractType const* type = dynamic_cast(_newExpression.getType().get()); + if (asserts(type)) + BOOST_THROW_EXCEPTION(InternalCompilerError()); + TypePointers const& types = type->getConstructorType()->getParameterTypes(); + vector> arguments = _newExpression.getArguments(); + if (asserts(arguments.size() == types.size())) + BOOST_THROW_EXCEPTION(InternalCompilerError()); + + // copy the contracts code into memory + bytes const& bytecode = m_context.getCompiledContract(*_newExpression.getContract()); + m_context << u256(bytecode.size()); + //@todo could be done by actually appending the Assembly, but then we probably need to compile + // multiple times. Will revisit once external fuctions are inlined. + m_context.appendData(bytecode); + //@todo copy to memory position 0, shift as soon as we use memory + m_context << u256(0) << eth::Instruction::CODECOPY; + + unsigned dataOffset = bytecode.size(); + for (unsigned i = 0; i < arguments.size(); ++i) + { + arguments[i]->accept(*this); + appendTypeConversion(*arguments[i]->getType(), *types[i]); + unsigned const numBytes = types[i]->getCalldataEncodedSize(); + if (numBytes > 32) + BOOST_THROW_EXCEPTION(CompilerError() + << errinfo_sourceLocation(arguments[i]->getLocation()) + << errinfo_comment("Type " + types[i]->toString() + " not yet supported.")); + bool const leftAligned = types[i]->getCategory() == Type::Category::STRING; + CompilerUtils(m_context).storeInMemory(dataOffset, numBytes, leftAligned); + dataOffset += numBytes; + } + // size, offset, endowment + m_context << u256(dataOffset) << u256(0) << u256(0) << eth::Instruction::CREATE; + return false; +} + void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) { ASTString const& member = _memberAccess.getMemberName(); diff --git a/libsolidity/ExpressionCompiler.h b/libsolidity/ExpressionCompiler.h index 0bba211ce..67b16aac0 100644 --- a/libsolidity/ExpressionCompiler.h +++ b/libsolidity/ExpressionCompiler.h @@ -60,6 +60,7 @@ private: virtual void endVisit(UnaryOperation const& _unaryOperation) override; virtual bool visit(BinaryOperation const& _binaryOperation) override; virtual bool visit(FunctionCall const& _functionCall) override; + virtual bool visit(NewExpression const& _newExpression) override; virtual void endVisit(MemberAccess const& _memberAccess) override; virtual bool visit(IndexAccess const& _indexAccess) override; virtual void endVisit(Identifier const& _identifier) override; diff --git a/libsolidity/InterfaceHandler.cpp b/libsolidity/InterfaceHandler.cpp index f26088afa..1310f504a 100644 --- a/libsolidity/InterfaceHandler.cpp +++ b/libsolidity/InterfaceHandler.cpp @@ -15,7 +15,7 @@ InterfaceHandler::InterfaceHandler() m_lastTag = DocTagType::NONE; } -std::unique_ptr InterfaceHandler::getDocumentation(ContractDefinition& _contractDef, +std::unique_ptr InterfaceHandler::getDocumentation(ContractDefinition const& _contractDef, DocumentationType _type) { switch(_type) @@ -32,7 +32,7 @@ std::unique_ptr InterfaceHandler::getDocumentation(ContractDefiniti return nullptr; } -std::unique_ptr InterfaceHandler::getABIInterface(ContractDefinition& _contractDef) +std::unique_ptr InterfaceHandler::getABIInterface(ContractDefinition const& _contractDef) { Json::Value methods(Json::arrayValue); @@ -63,7 +63,7 @@ std::unique_ptr InterfaceHandler::getABIInterface(ContractDefinitio return std::unique_ptr(new std::string(m_writer.write(methods))); } -std::unique_ptr InterfaceHandler::getUserDocumentation(ContractDefinition& _contractDef) +std::unique_ptr InterfaceHandler::getUserDocumentation(ContractDefinition const& _contractDef) { Json::Value doc; Json::Value methods(Json::objectValue); @@ -88,7 +88,7 @@ std::unique_ptr InterfaceHandler::getUserDocumentation(ContractDefi return std::unique_ptr(new std::string(m_writer.write(doc))); } -std::unique_ptr InterfaceHandler::getDevDocumentation(ContractDefinition& _contractDef) +std::unique_ptr InterfaceHandler::getDevDocumentation(ContractDefinition const& _contractDef) { // LTODO: Somewhere in this function warnings for mismatch of param names // should be thrown diff --git a/libsolidity/InterfaceHandler.h b/libsolidity/InterfaceHandler.h index b1cd4b562..d271a6697 100644 --- a/libsolidity/InterfaceHandler.h +++ b/libsolidity/InterfaceHandler.h @@ -67,23 +67,23 @@ public: /// types provided by @c DocumentationType /// @return A unique pointer contained string with the json /// representation of provided type - std::unique_ptr getDocumentation(ContractDefinition& _contractDef, + std::unique_ptr getDocumentation(ContractDefinition const& _contractDef, DocumentationType _type); /// Get the ABI Interface of the contract /// @param _contractDef The contract definition /// @return A unique pointer contained string with the json /// representation of the contract's ABI Interface - std::unique_ptr getABIInterface(ContractDefinition& _contractDef); + std::unique_ptr getABIInterface(ContractDefinition const& _contractDef); /// Get the User documentation of the contract /// @param _contractDef The contract definition /// @return A unique pointer contained string with the json /// representation of the contract's user documentation - std::unique_ptr getUserDocumentation(ContractDefinition& _contractDef); + std::unique_ptr getUserDocumentation(ContractDefinition const& _contractDef); /// Get the Developer's documentation of the contract /// @param _contractDef The contract definition /// @return A unique pointer contained string with the json /// representation of the contract's developer documentation - std::unique_ptr getDevDocumentation(ContractDefinition& _contractDef); + std::unique_ptr getDevDocumentation(ContractDefinition const& _contractDef); private: void resetUser(); diff --git a/libsolidity/Parser.cpp b/libsolidity/Parser.cpp index b678b2fc0..21651eb14 100644 --- a/libsolidity/Parser.cpp +++ b/libsolidity/Parser.cpp @@ -437,7 +437,17 @@ ASTPointer Parser::parseUnaryExpression() { ASTNodeFactory nodeFactory(*this); Token::Value token = m_scanner->getCurrentToken(); - if (Token::isUnaryOp(token) || Token::isCountOp(token)) + if (token == Token::NEW) + { + expectToken(Token::NEW); + ASTPointer contractName = ASTNodeFactory(*this).createNode(expectIdentifierToken()); + expectToken(Token::LPAREN); + vector> arguments(parseFunctionCallArguments()); + expectToken(Token::RPAREN); + nodeFactory.markEndPosition(); + return nodeFactory.createNode(contractName, arguments); + } + else if (Token::isUnaryOp(token) || Token::isCountOp(token)) { // prefix expression m_scanner->next(); diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index c2d488418..f1cd7c228 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -310,6 +310,19 @@ MemberList const& ContractType::getMembers() const return *m_members; } +shared_ptr const& ContractType::getConstructorType() const +{ + if (!m_constructorType) + { + FunctionDefinition const* constr = m_contract.getConstructor(); + if (constr) + m_constructorType = make_shared(*constr); + else + m_constructorType = make_shared(TypePointers(), TypePointers()); + } + return m_constructorType; +} + unsigned ContractType::getFunctionIndex(string const& _functionName) const { unsigned index = 0; diff --git a/libsolidity/Types.h b/libsolidity/Types.h index 807e60c74..48539a1d7 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -39,6 +39,7 @@ namespace solidity // @todo realMxN, dynamic strings, text, arrays class Type; // forward +class FunctionType; // forward using TypePointer = std::shared_ptr; using TypePointers = std::vector; @@ -249,10 +250,16 @@ public: virtual MemberList const& getMembers() const override; + /// Returns the function type of the constructor. Note that the location part of the function type + /// is not used, as this type cannot be the type of a variable or expression. + std::shared_ptr const& getConstructorType() const; + unsigned getFunctionIndex(std::string const& _functionName) const; private: ContractDefinition const& m_contract; + /// Type of the constructor, @see getConstructorType. Lazily initialized. + mutable std::shared_ptr m_constructorType; /// List of member types, will be lazy-initialized because of recursive references. mutable std::unique_ptr m_members; }; @@ -339,8 +346,8 @@ public: virtual std::string toString() const override; virtual bool canLiveOutsideStorage() const override { return false; } - TypePointer getKeyType() const { return m_keyType; } - TypePointer getValueType() const { return m_valueType; } + TypePointer const& getKeyType() const { return m_keyType; } + TypePointer const& getValueType() const { return m_valueType; } private: TypePointer m_keyType; diff --git a/libsolidity/grammar.txt b/libsolidity/grammar.txt index c0ab06074..793e91882 100644 --- a/libsolidity/grammar.txt +++ b/libsolidity/grammar.txt @@ -25,11 +25,12 @@ Break = 'break' ';' Return = 'return' Expression? ';' VariableDefinition = VariableDeclaration ( = Expression )? ';' -Expression = Assignment | UnaryOperation | BinaryOperation | FunctionCall | IndexAccess | +Expression = Assignment | UnaryOperation | BinaryOperation | FunctionCall | NewExpression | IndexAccess | MemberAccess | PrimaryExpression // The expression syntax is actually much more complicated Assignment = Expression (AssignmentOp Expression) FunctionCall = Expression '(' ( Expression ( ',' Expression )* ) ')' +NewExpression = 'new' Identifier '(' ( Expression ( ',' Expression )* ) ')' MemberAccess = Expression '.' Identifier IndexAccess = Expression '[' Expresison ']' PrimaryExpression = Identifier | NumberLiteral | StringLiteral | ElementaryTypeName | '(' Expression ')' diff --git a/test/solidityCompiler.cpp b/test/solidityCompiler.cpp index eae8f3142..29f61454a 100644 --- a/test/solidityCompiler.cpp +++ b/test/solidityCompiler.cpp @@ -56,7 +56,7 @@ bytes compileContract(const string& _sourceCode) BOOST_REQUIRE_NO_THROW(resolver.resolveNamesAndTypes(*contract)); Compiler compiler; - compiler.compileContract(*contract, {}); + compiler.compileContract(*contract, {}, {}); // debug //compiler.streamAssembly(cout); return compiler.getAssembledBytecode(); From 7801b87ddb2b21f32af1495e367f11bc99c88766 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 15 Dec 2014 12:59:17 +0100 Subject: [PATCH 523/641] Packing and unpacking of constructor arguments. --- libevmcore/Assembly.cpp | 21 ++++++++++++++++++++- libevmcore/Assembly.h | 5 ++++- libsolidity/Compiler.cpp | 16 ++++++++++++---- libsolidity/CompilerContext.h | 2 ++ test/solidityEndToEndTest.cpp | 26 ++++++++++++++++++++++++++ 5 files changed, 64 insertions(+), 6 deletions(-) diff --git a/libevmcore/Assembly.cpp b/libevmcore/Assembly.cpp index 059810af8..b78f03035 100644 --- a/libevmcore/Assembly.cpp +++ b/libevmcore/Assembly.cpp @@ -39,6 +39,7 @@ unsigned AssemblyItem::bytesRequired(unsigned _addressLength) const case Push: return 1 + max(1, dev::bytesRequired(m_data)); case PushSubSize: + case PushProgramSize: return 4; // worst case: a 16MB program case PushTag: case PushData: @@ -59,7 +60,7 @@ int AssemblyItem::deposit() const { case Operation: return instructionInfo((Instruction)(byte)m_data).ret - instructionInfo((Instruction)(byte)m_data).args; - case Push: case PushString: case PushTag: case PushData: case PushSub: case PushSubSize: + case Push: case PushString: case PushTag: case PushData: case PushSub: case PushSubSize: case PushProgramSize: return 1; case Tag: return 0; @@ -146,6 +147,9 @@ ostream& dev::eth::operator<<(ostream& _out, AssemblyItemsConstRef _i) case PushSubSize: _out << " PUSHss[" << hex << h256(i.data()).abridged() << "]"; break; + case PushProgramSize: + _out << " PUSHSIZE"; + break; case NoOptimizeBegin: _out << " DoNotOptimze{{"; break; @@ -185,6 +189,9 @@ ostream& Assembly::streamRLP(ostream& _out, string const& _prefix) const case PushSubSize: _out << _prefix << " PUSH #[$" << h256(i.m_data).abridged() << "]" << endl; break; + case PushProgramSize: + _out << _prefix << " PUSHSIZE" << endl; + break; case Tag: _out << _prefix << "tag" << i.m_data << ": " << endl << _prefix << " JUMPDEST" << endl; break; @@ -303,6 +310,7 @@ Assembly& Assembly::optimise(bool _enable) { { PushString, Instruction::POP }, [](AssemblyItemsConstRef) -> AssemblyItems { return {}; } }, { { PushSub, Instruction::POP }, [](AssemblyItemsConstRef) -> AssemblyItems { return {}; } }, { { PushSubSize, Instruction::POP }, [](AssemblyItemsConstRef) -> AssemblyItems { return {}; } }, + { { PushProgramSize, Instruction::POP }, [](AssemblyItemsConstRef) -> AssemblyItems { return {}; } }, { { Push, PushTag, Instruction::JUMPI }, [](AssemblyItemsConstRef m) -> AssemblyItems { if (m[0].data()) return { m[1], Instruction::JUMP }; else return {}; } }, { { Instruction::ISZERO, Instruction::ISZERO }, [](AssemblyItemsConstRef) -> AssemblyItems { return {}; } }, }; @@ -468,6 +476,7 @@ bytes Assembly::assemble() const vector tagPos(m_usedTags); map tagRef; multimap dataRef; + vector sizeRef; ///< Pointers to code locations where the size of the program is inserted unsigned bytesPerTag = dev::bytesRequired(totalBytes); byte tagPush = (byte)Instruction::PUSH1 - 1 + bytesPerTag; @@ -526,6 +535,11 @@ bytes Assembly::assemble() const toBigEndian(s, byr); break; } + case PushProgramSize: + ret.push_back(tagPush); + sizeRef.push_back(ret.size()); + ret.resize(ret.size() + bytesPerTag); + break; case Tag: tagPos[(unsigned)i.m_data] = ret.size(); ret.push_back((byte)Instruction::JUMPDEST); @@ -561,5 +575,10 @@ bytes Assembly::assemble() const } } } + for (unsigned pos: sizeRef) + { + bytesRef r(ret.data() + pos, bytesPerTag); + toBigEndian(ret.size(), r); + } return ret; } diff --git a/libevmcore/Assembly.h b/libevmcore/Assembly.h index 5523710d4..81e4a9ff7 100644 --- a/libevmcore/Assembly.h +++ b/libevmcore/Assembly.h @@ -32,7 +32,7 @@ namespace dev namespace eth { -enum AssemblyItemType { UndefinedItem, Operation, Push, PushString, PushTag, PushSub, PushSubSize, Tag, PushData, NoOptimizeBegin, NoOptimizeEnd }; +enum AssemblyItemType { UndefinedItem, Operation, Push, PushString, PushTag, PushSub, PushSubSize, PushProgramSize, Tag, PushData, NoOptimizeBegin, NoOptimizeEnd }; class Assembly; @@ -86,6 +86,9 @@ public: AssemblyItem const& append(std::string const& _data) { return append(newPushString(_data)); } AssemblyItem const& append(bytes const& _data) { return append(newData(_data)); } AssemblyItem appendSubSize(Assembly const& _a) { auto ret = newSub(_a); append(newPushSubSize(ret.data())); return ret; } + /// Pushes the final size of the current assembly itself. Use this when the code is modified + /// after compilation and CODESIZE is not an option. + void appendProgramSize() { append(AssemblyItem(PushProgramSize)); } AssemblyItem appendJump() { auto ret = append(newPushTag()); append(Instruction::JUMP); return ret; } AssemblyItem appendJumpI() { auto ret = append(newPushTag()); append(Instruction::JUMPI); return ret; } diff --git a/libsolidity/Compiler.cpp b/libsolidity/Compiler.cpp index 48d8be88a..f2877c1ce 100644 --- a/libsolidity/Compiler.cpp +++ b/libsolidity/Compiler.cpp @@ -77,12 +77,21 @@ void Compiler::packIntoContractCreator(ContractDefinition const& _contract, { eth::AssemblyItem returnTag = m_context.pushNewTag(); m_context.addFunction(*constructor); // note that it cannot be called due to syntactic reasons - // copy constructor arguments - //@todo ask assembly for the size of the current program + // copy constructor arguments from code to memory and then to stack, they are supplied after the actual program + unsigned argumentSize = 0; + for (ASTPointer const& var: constructor->getParameters()) + argumentSize += var->getType()->getCalldataEncodedSize(); + if (argumentSize > 0) + { + m_context << u256(argumentSize); + m_context.appendProgramSize(); + m_context << u256(1); // copy it to byte one as expected for ABI calls + m_context << eth::Instruction::CODECOPY; + appendCalldataUnpacker(*constructor, true); + } //@todo calling other functions inside the constructor should either trigger a parse error //or we should copy them here (register them above and call "accept") - detecting which // functions are referenced / called needs to be done in a recursive way. - appendCalldataUnpacker(*constructor, true); m_context.appendJumpTo(m_context.getFunctionEntryLabel(*constructor)); constructor->accept(*this); m_context << returnTag; @@ -135,7 +144,6 @@ unsigned Compiler::appendCalldataUnpacker(FunctionDefinition const& _function, b { // We do not check the calldata size, everything is zero-padded. unsigned dataOffset = 1; - //@todo this can be done more efficiently, saving some CALLDATALOAD calls for (ASTPointer const& var: _function.getParameters()) { diff --git a/libsolidity/CompilerContext.h b/libsolidity/CompilerContext.h index 99f5ae94c..795f447ab 100644 --- a/libsolidity/CompilerContext.h +++ b/libsolidity/CompilerContext.h @@ -81,6 +81,8 @@ public: /// Adds a subroutine to the code (in the data section) and pushes its size (via a tag) /// on the stack. @returns the assembly item corresponding to the pushed subroutine, i.e. its offset. eth::AssemblyItem addSubroutine(eth::Assembly const& _assembly) { return m_asm.appendSubSize(_assembly); } + /// Pushes the size of the final program + void appendProgramSize() { return m_asm.appendProgramSize(); } /// Adds data to the data section, pushes a reference to the stack eth::AssemblyItem appendData(bytes const& _data) { return m_asm.append(_data); } diff --git a/test/solidityEndToEndTest.cpp b/test/solidityEndToEndTest.cpp index 15722abe1..b6f63aa72 100644 --- a/test/solidityEndToEndTest.cpp +++ b/test/solidityEndToEndTest.cpp @@ -1012,6 +1012,32 @@ BOOST_AUTO_TEST_CASE(strings_in_calls) BOOST_CHECK(callContractFunction(0, bytes({0, 'a', 1})) == bytes({0, 'a', 0, 0, 0})); } +BOOST_AUTO_TEST_CASE(constructor_arguments) +{ + char const* sourceCode = R"( + contract Helper { + string3 name; + bool flag; + function Helper(string3 x, bool f) { + name = x; + flag = f; + } + function getName() returns (string3 ret) { return name; } + function getFlag() returns (bool ret) { return flag; } + } + contract Main { + Helper h; + function Main() { + h = new Helper("abc", true); + } + function getFlag() returns (bool ret) { return h.getFlag(); } + function getName() returns (string3 ret) { return h.getName(); } + })"; + compileAndRun(sourceCode, 0, "Main"); + BOOST_REQUIRE(callContractFunction(0) == bytes({0x01})); + BOOST_REQUIRE(callContractFunction(1) == bytes({'a', 'b', 'c'})); +} + BOOST_AUTO_TEST_SUITE_END() } From 1efde49fd7e1ef2f7b7cb573584311f98748e93f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 15 Dec 2014 15:13:57 +0100 Subject: [PATCH 524/641] Update usage of ExtVMFace in evmjit submodule --- evmjit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evmjit b/evmjit index b3a17341e..dbf8174fc 160000 --- a/evmjit +++ b/evmjit @@ -1 +1 @@ -Subproject commit b3a17341e4ee3f2af12270d92cf404293deefc73 +Subproject commit dbf8174fc6f8be9e6d1e62a627388fa23eb2308f From a3473ad88d39a1491d3b13da7efd11537eede1f1 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 15 Dec 2014 16:09:50 +0100 Subject: [PATCH 525/641] Check that constructor does not have "returns" directive. --- libsolidity/AST.cpp | 11 +++++++++++ libsolidity/AST.h | 4 ++++ libsolidity/NameAndTypeResolver.cpp | 6 +----- test/solidityNameAndTypeResolution.cpp | 9 +++++++++ 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 3fcf8ba0b..5e344eadb 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -39,6 +39,17 @@ TypeError ASTNode::createTypeError(string const& _description) const return TypeError() << errinfo_sourceLocation(getLocation()) << errinfo_comment(_description); } +void ContractDefinition::checkTypeRequirements() +{ + FunctionDefinition const* constructor = getConstructor(); + if (constructor && !constructor->getReturnParameters().empty()) + BOOST_THROW_EXCEPTION(constructor->getReturnParameterList()->createTypeError( + "Non-empty \"returns\" directive for constructor.")); + + for (ASTPointer const& function: getDefinedFunctions()) + function->checkTypeRequirements(); +} + vector ContractDefinition::getInterfaceFunctions() const { vector exportedFunctions; diff --git a/libsolidity/AST.h b/libsolidity/AST.h index 3a15bbebe..72f96394f 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -174,6 +174,10 @@ public: std::vector> const& getStateVariables() const { return m_stateVariables; } std::vector> const& getDefinedFunctions() const { return m_definedFunctions; } + /// Checks that the constructor does not have a "returns" statement and calls + /// checkTypeRequirements on all its functions. + void checkTypeRequirements(); + /// @return A shared pointer of an ASTString. /// Can contain a nullptr in which case indicates absence of documentation ASTPointer const& getDocumentation() const { return m_documentation; } diff --git a/libsolidity/NameAndTypeResolver.cpp b/libsolidity/NameAndTypeResolver.cpp index 540b066eb..2ad276801 100644 --- a/libsolidity/NameAndTypeResolver.cpp +++ b/libsolidity/NameAndTypeResolver.cpp @@ -62,11 +62,7 @@ void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract) // First, the parameter types of all functions need to be resolved before we can check // the types, since it is possible to call functions that are only defined later // in the source. - for (ASTPointer const& function: _contract.getDefinedFunctions()) - { - m_currentScope = &m_scopes[function.get()]; - function->checkTypeRequirements(); - } + _contract.checkTypeRequirements(); m_currentScope = &m_scopes[nullptr]; } diff --git a/test/solidityNameAndTypeResolution.cpp b/test/solidityNameAndTypeResolution.cpp index 03eaebb3a..0ea6e51b9 100644 --- a/test/solidityNameAndTypeResolution.cpp +++ b/test/solidityNameAndTypeResolution.cpp @@ -284,6 +284,15 @@ BOOST_AUTO_TEST_CASE(assignment_to_struct) BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); } +BOOST_AUTO_TEST_CASE(returns_in_constructor) +{ + char const* text = "contract test {\n" + " function test() returns (uint a) {\n" + " }\n" + "}\n"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} + BOOST_AUTO_TEST_SUITE_END() } From 592e60ec1742749ae4d81e8b24e472bcbe88582f Mon Sep 17 00:00:00 2001 From: ethdev Date: Mon, 15 Dec 2014 18:19:58 +0100 Subject: [PATCH 526/641] start of implementing windows debug --- cmake/EthDependencies.cmake | 4 ++++ libdevcore/CMakeLists.txt | 8 ++++---- solc/CMakeLists.txt | 4 ++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index ee93a5311..7ff225594 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -141,6 +141,10 @@ find_package(Boost 1.54.0 REQUIRED COMPONENTS thread date_time system regex chro message(" - boost header: ${Boost_INCLUDE_DIRS}") message(" - boost lib : ${Boost_LIBRARIES}") +message("debug ${Boost_SYSTEM_LIBRARY_DEBUG}") +message("release ${Boost_SYSTEM_LIBRARY_RELEASE}") +message("other ${Boost_SYSTEM_LIBRARY}") + if (APPLE) link_directories(/usr/local/lib) include_directories(/usr/local/include) diff --git a/libdevcore/CMakeLists.txt b/libdevcore/CMakeLists.txt index 001c568b5..ce8abcbb3 100644 --- a/libdevcore/CMakeLists.txt +++ b/libdevcore/CMakeLists.txt @@ -25,10 +25,10 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY_RELEASE}) -target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARY_RELEASE}) -target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARY_RELEASE}) -target_link_libraries(${EXECUTABLE} ${Boost_CHRONO_LIBRARY_RELEASE}) +target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${Boost_CHRONO_LIBRARY}) if (APPLE) find_package(Threads REQUIRED) diff --git a/solc/CMakeLists.txt b/solc/CMakeLists.txt index cf1e42572..bc8632373 100644 --- a/solc/CMakeLists.txt +++ b/solc/CMakeLists.txt @@ -11,8 +11,8 @@ set(EXECUTABLE solc) file(GLOB HEADERS "*.h") add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) -target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARY_RELEASE}) -target_link_libraries(${EXECUTABLE} ${Boost_PROGRAM_OPTIONS_LIBRARY_RELEASE}) +target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${Boost_PROGRAM_OPTIONS_LIBRARY}) target_link_libraries(${EXECUTABLE} solidity) install( TARGETS ${EXECUTABLE} DESTINATION bin ) From 708d5536aec6c678cda52595d3d08a810cd0eb9d Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 15 Dec 2014 18:42:53 +0100 Subject: [PATCH 527/641] modyfied findjsoncpp cmake to look for debug library --- cmake/FindJsoncpp.cmake | 138 ++++++++++++---------------------------- 1 file changed, 41 insertions(+), 97 deletions(-) diff --git a/cmake/FindJsoncpp.cmake b/cmake/FindJsoncpp.cmake index fe72a9042..c2f0aca43 100644 --- a/cmake/FindJsoncpp.cmake +++ b/cmake/FindJsoncpp.cmake @@ -1,103 +1,47 @@ -# - try to find JSONCPP library +# Find jsoncpp # -# Cache Variables: (probably not for direct use in your scripts) -# JSONCPP_INCLUDE_DIR -# JSONCPP_LIBRARY -# -# Non-cache variables you might use in your CMakeLists.txt: -# JSONCPP_FOUND -# JSONCPP_INCLUDE_DIRS -# JSONCPP_LIBRARIES -# -# Requires these CMake modules: -# FindPackageHandleStandardArgs (known included with CMake >=2.6.2) -# -# Author: -# 2011 Philippe Crassous (ENSAM ParisTech / Institut Image) p.crassous _at_ free.fr -# -# Adapted from the Virtual Reality Peripheral Network library. -# https://github.com/rpavlik/vrpn/blob/master/README.Legal -# - -set(JSONCPP_ROOT_DIR - "${JSONCPP_ROOT_DIR}" - CACHE - PATH - "Directory to search for JSONCPP") -set(_jsoncppnames) -set(_pathsuffixes - suncc - vacpp - mingw - msvc6 - msvc7 - msvc71 - msvc80 - msvc90 - linux-gcc) -if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") - execute_process(COMMAND - ${CMAKE_CXX_COMPILER} - -dumpversion - OUTPUT_VARIABLE - _gnucxx_ver - OUTPUT_STRIP_TRAILING_WHITESPACE) - list(APPEND - _jsoncppnames - json_linux-gcc-${_gnucxx_ver}_libmt - json_linux-gcc_libmt) - list(APPEND _pathsuffixes linux-gcc-${_gnucxx_ver}) -elseif(MSVC) - if(MSVC_VERSION EQUAL 1200) - list(APPEND _jsoncppnames json_vc6_libmt) - elseif(MSVC_VERSION EQUAL 1300) - list(APPEND _jsoncppnames json_vc7_libmt) - elseif(MSVC_VERSION EQUAL 1310) - list(APPEND _jsoncppnames json_vc71_libmt) - elseif(MSVC_VERSION EQUAL 1400) - list(APPEND _jsoncppnames json_vc8_libmt) - elseif(MSVC_VERSION EQUAL 1500) - list(APPEND _jsoncppnames json_vc9_libmt) - elseif(MSVC_VERSION EQUAL 1600) - list(APPEND _jsoncppnames json_vc10_libmt) - endif() -else() - list(APPEND _jsoncppnames - json_suncc_libmt - json_vacpp_libmt) -endif() - -list(APPEND _jsoncppnames - json_mingw_libmt - jsoncpp) - -find_library(JSONCPP_LIBRARY - NAMES - ${_jsoncppnames} - PATHS - "${JSONCPP_ROOT_DIR}/libs" - PATH_SUFFIXES - ${_pathsuffixes}) - -find_path(JSONCPP_INCLUDE_DIR - NAMES - json/json.h - PATHS - "${JSONCPP_ROOT_DIR}" - PATH_SUFFIXES jsoncpp - include) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(JSONCPP - DEFAULT_MSG +# Find the jsoncpp includes and library +# +# if you nee to add a custom library search path, do it via via CMAKE_FIND_ROOT_PATH +# +# This module defines +# JSONCPP_INCLUDE_DIRS, where to find header, etc. +# JSONCPP_LIBRARIES, the libraries needed to use jsoncpp. +# JSONCPP_FOUND, If false, do not try to use jsoncpp. + +# only look in default directories +find_path( + JSONCPP_INCLUDE_DIR + NAMES jsoncpp/json/json.h + DOC "jsoncpp include dir" +) + +find_library( JSONCPP_LIBRARY - JSONCPP_INCLUDE_DIR) + NAMES jsoncpp + DOC "jsoncpp library" +) + +set(JSONCPP_INCLUDE_DIRS ${JSONCPP_INCLUDE_DIR}) +set(JSONCPP_LIBRARIES ${JSONCPP_LIBRARY}) + +# debug library on windows +# same naming convention as in qt (appending debug library with d) +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + find_library( + JSONCPP_LIBRARY_DEBUG + NAMES jsoncppd + DOC "jsoncpp debug library" + ) + + set(JSONCPP_LIBRARIES ${JSONCPP_LIBRARIES} ${JSONCPP_LIBRARY_DEBUG}) -if(JSONCPP_FOUND) - set(JSONCPP_LIBRARIES "${JSONCPP_LIBRARY}") - set(JSONCPP_INCLUDE_DIRS "${JSONCPP_INCLUDE_DIR}") - mark_as_advanced(JSONCPP_ROOT_DIR) endif() -mark_as_advanced(JSONCPP_INCLUDE_DIR JSONCPP_LIBRARY) +# handle the QUIETLY and REQUIRED arguments and set GMP_FOUND to TRUE +# if all listed variables are TRUE, hide their existence from configuration view +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(jsoncpp DEFAULT_MSG + JSONCPP_INCLUDE_DIR JSONCPP_LIBRARY) +mark_as_advanced (JSONCPP_INCLUDE_DIR JSONCPP_LIBRARY) From f42dbcac1ccdfeaef7329214f026793d861e807d Mon Sep 17 00:00:00 2001 From: ethdev Date: Mon, 15 Dec 2014 19:01:20 +0100 Subject: [PATCH 528/641] boost library -> libraries --- cmake/EthDependencies.cmake | 4 ---- eth/CMakeLists.txt | 4 ++-- libdevcore/CMakeLists.txt | 8 ++++---- libdevcrypto/CMakeLists.txt | 2 +- libethereum/CMakeLists.txt | 2 +- solc/CMakeLists.txt | 4 ++-- test/CMakeLists.txt | 4 ++-- 7 files changed, 12 insertions(+), 16 deletions(-) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 7ff225594..ee93a5311 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -141,10 +141,6 @@ find_package(Boost 1.54.0 REQUIRED COMPONENTS thread date_time system regex chro message(" - boost header: ${Boost_INCLUDE_DIRS}") message(" - boost lib : ${Boost_LIBRARIES}") -message("debug ${Boost_SYSTEM_LIBRARY_DEBUG}") -message("release ${Boost_SYSTEM_LIBRARY_RELEASE}") -message("other ${Boost_SYSTEM_LIBRARY}") - if (APPLE) link_directories(/usr/local/lib) include_directories(/usr/local/include) diff --git a/eth/CMakeLists.txt b/eth/CMakeLists.txt index 739c2991c..27fd542c1 100644 --- a/eth/CMakeLists.txt +++ b/eth/CMakeLists.txt @@ -14,8 +14,8 @@ add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) add_dependencies(${EXECUTABLE} BuildInfo.h) -target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARY_RELEASE}) -target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARY_RELEASE}) +target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARIES}) +target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARIES}) if (READLINE_FOUND) target_link_libraries(${EXECUTABLE} ${READLINE_LIBRARIES}) diff --git a/libdevcore/CMakeLists.txt b/libdevcore/CMakeLists.txt index ce8abcbb3..df93361a4 100644 --- a/libdevcore/CMakeLists.txt +++ b/libdevcore/CMakeLists.txt @@ -25,10 +25,10 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY}) -target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARY}) -target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARY}) -target_link_libraries(${EXECUTABLE} ${Boost_CHRONO_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARIES}) +target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARIES}) +target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARIES}) +target_link_libraries(${EXECUTABLE} ${Boost_CHRONO_LIBRARIES}) if (APPLE) find_package(Threads REQUIRED) diff --git a/libdevcrypto/CMakeLists.txt b/libdevcrypto/CMakeLists.txt index 20eab916a..4cd6daf21 100644 --- a/libdevcrypto/CMakeLists.txt +++ b/libdevcrypto/CMakeLists.txt @@ -23,7 +23,7 @@ else() add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARY_RELEASE}) +target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LIBRARIES}) target_link_libraries(${EXECUTABLE} devcore) diff --git a/libethereum/CMakeLists.txt b/libethereum/CMakeLists.txt index 792ed0cf1..3906074fd 100644 --- a/libethereum/CMakeLists.txt +++ b/libethereum/CMakeLists.txt @@ -25,7 +25,7 @@ else() endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) -target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARY_RELEASE}) +target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARIES}) target_link_libraries(${EXECUTABLE} evm) target_link_libraries(${EXECUTABLE} lll) diff --git a/solc/CMakeLists.txt b/solc/CMakeLists.txt index bc8632373..8c0ece27e 100644 --- a/solc/CMakeLists.txt +++ b/solc/CMakeLists.txt @@ -11,8 +11,8 @@ set(EXECUTABLE solc) file(GLOB HEADERS "*.h") add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) -target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARY}) -target_link_libraries(${EXECUTABLE} ${Boost_PROGRAM_OPTIONS_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARIES}) +target_link_libraries(${EXECUTABLE} ${Boost_PROGRAM_OPTIONS_LIBRARIES}) target_link_libraries(${EXECUTABLE} solidity) install( TARGETS ${EXECUTABLE} DESTINATION bin ) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7e618f7ea..f862de24c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -12,7 +12,7 @@ file(GLOB HEADERS "*.h") add_executable(testeth ${SRC_LIST} ${HEADERS}) add_executable(createRandomTest createRandomTest.cpp vm.cpp TestHelper.cpp) -target_link_libraries(testeth ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY_RELEASE}) +target_link_libraries(testeth ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) target_link_libraries(testeth ${CURL_LIBRARIES}) target_link_libraries(testeth ethereum) target_link_libraries(testeth ethcore) @@ -25,6 +25,6 @@ if (JSONRPC) target_link_libraries(testeth ${JSON_RPC_CPP_CLIENT_LIBRARIES}) endif() -target_link_libraries(createRandomTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY_RELEASE}) +target_link_libraries(createRandomTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) target_link_libraries(createRandomTest ethereum) target_link_libraries(createRandomTest ethcore) From 10763f2407923578f0560d13c06d017dbd4b0de1 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 15 Dec 2014 19:16:31 +0100 Subject: [PATCH 529/641] - call initKeyEventManager in a SLOT connected to ressourceLoaded SIGNAL --- mix/AppContext.h | 1 + mix/main.cpp | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/mix/AppContext.h b/mix/AppContext.h index 0016ab3be..ce00205d8 100644 --- a/mix/AppContext.h +++ b/mix/AppContext.h @@ -59,6 +59,7 @@ private: public slots: void quitApplication() { delete Instance; } + void resourceLoaded(QObject* _obj, QUrl _url) { Q_UNUSED(_obj); Q_UNUSED(_url); initKeyEventManager(); } }; } diff --git a/mix/main.cpp b/mix/main.cpp index 33a139f85..36a742f8f 100644 --- a/mix/main.cpp +++ b/mix/main.cpp @@ -35,9 +35,7 @@ int main(int _argc, char *_argv[]) QQmlApplicationEngine* engine = new QQmlApplicationEngine(); AppContext::setApplicationContext(engine); QObject::connect(&app, SIGNAL(lastWindowClosed()), AppContext::getInstance(), SLOT(quitApplication())); //use to kill ApplicationContext and other stuff - - engine->load(QUrl(QStringLiteral("qrc:/qml/main.qml"))); - - AppContext::getInstance()->initKeyEventManager(); //has to be called after the loading of the main view. + QObject::connect(engine, SIGNAL(objectCreated(QObject*, QUrl)), AppContext::getInstance(), SLOT(resourceLoaded(QObject*, QUrl))); + engine->load(QUrl("qrc:/qml/main.qml")); return app.exec(); } From 95217d0584cb76a8a50031ff658dd95f56af0c0e Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 15 Dec 2014 19:40:04 +0100 Subject: [PATCH 530/641] - add parameter QObject* in initKeyEventManager. --- mix/AppContext.cpp | 4 ++-- mix/AppContext.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mix/AppContext.cpp b/mix/AppContext.cpp index 5b8b76139..92b3f4c0a 100644 --- a/mix/AppContext.cpp +++ b/mix/AppContext.cpp @@ -52,9 +52,9 @@ dev::eth::Client* AppContext::getEthereumClient() return m_webThree->ethereum(); } -void AppContext::initKeyEventManager() +void AppContext::initKeyEventManager(QObject* _res) { - QObject* mainContent = m_applicationEngine->rootObjects().at(0)->findChild("mainContent", Qt::FindChildrenRecursively); + QObject* mainContent = _res->findChild("mainContent", Qt::FindChildrenRecursively); if (mainContent) QObject::connect(mainContent, SIGNAL(keyPressed(QVariant)), m_keyEventManager.get(), SLOT(keyPressed(QVariant))); else diff --git a/mix/AppContext.h b/mix/AppContext.h index ce00205d8..baa2905ba 100644 --- a/mix/AppContext.h +++ b/mix/AppContext.h @@ -47,7 +47,7 @@ public: static void setApplicationContext(QQmlApplicationEngine* _engine); QQmlApplicationEngine* appEngine(); dev::eth::Client* getEthereumClient(); - void initKeyEventManager(); + void initKeyEventManager(QObject* _obj); KeyEventManager* getKeyEventManager(); void displayMessageDialog(QString _title, QString _message); @@ -59,7 +59,7 @@ private: public slots: void quitApplication() { delete Instance; } - void resourceLoaded(QObject* _obj, QUrl _url) { Q_UNUSED(_obj); Q_UNUSED(_url); initKeyEventManager(); } + void resourceLoaded(QObject* _obj, QUrl _url) { Q_UNUSED(_url); initKeyEventManager(_obj); } }; } From 905934f4c8e67d796d6d8a97a74d8003c9feeed5 Mon Sep 17 00:00:00 2001 From: winsvega Date: Mon, 15 Dec 2014 23:50:43 +0300 Subject: [PATCH 531/641] Transaction Test Filler --- test/stTransactionTestFiller.json | 191 ++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 test/stTransactionTestFiller.json diff --git a/test/stTransactionTestFiller.json b/test/stTransactionTestFiller.json new file mode 100644 index 000000000..260e7953f --- /dev/null +++ b/test/stTransactionTestFiller.json @@ -0,0 +1,191 @@ +{ + "EmptyTransaction" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "45678256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : + { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "100000", + "code" : "", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : + { + "data" : "", + "gasLimit" : "", + "gasPrice" : "", + "nonce" : "", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "", + "value" : "" + } + }, + + "TransactionSendingToEmpty" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "45678256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : + { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "100000", + "code" : "", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : + { + "data" : "", + "gasLimit" : "500", + "gasPrice" : "1", + "nonce" : "", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "", + "value" : "" + } + }, + + + "TransactionSendingToZero" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "45678256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : + { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "100000", + "code" : "", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : + { + "data" : "", + "gasLimit" : "5000", + "gasPrice" : "1", + "nonce" : "", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "0000000000000000000000000000000000000000", + "value" : "1" + } + }, + + + "TransactionToItself" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "45678256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : + { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "100000", + "code" : "", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : + { + "data" : "", + "gasLimit" : "5000", + "gasPrice" : "1", + "nonce" : "", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "a94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "value" : "1" + } + }, + + + "TransactionToItselfNotEnoughFounds" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "45678256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : + { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1101", + "code" : "", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : + { + "data" : "", + "gasLimit" : "600", + "gasPrice" : "1", + "nonce" : "", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "a94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "value" : "502" + } + }, + + + "TransactionFromCoinbaseNotEnoughFounds" : { + "env" : { + "currentCoinbase" : "a94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "currentDifficulty" : "45678256", + "currentGasLimit" : "1100", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : + { + "b94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000", + "code" : "", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : + { + "data" : "", + "gasLimit" : "600", + "gasPrice" : "1", + "nonce" : "", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "b94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "value" : "502" + } + } +} From 93d70bf9573087e5e27017188e3a306f518e2e6d Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Tue, 16 Dec 2014 12:25:14 +0100 Subject: [PATCH 532/641] search for leveldb debug library --- cmake/FindLevelDB.cmake | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/cmake/FindLevelDB.cmake b/cmake/FindLevelDB.cmake index 6bd373a9f..b2f59ec4d 100644 --- a/cmake/FindLevelDB.cmake +++ b/cmake/FindLevelDB.cmake @@ -25,6 +25,19 @@ find_library( set(LEVELDB_INCLUDE_DIRS ${LEVELDB_INCLUDE_DIR}) set(LEVELDB_LIBRARIES ${LEVELDB_LIBRARY}) +# debug library on windows +# same naming convention as in qt (appending debug library with d) +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + find_library( + LEVELDB_LIBRARY_DEBUG + NAMES leveldbd + DOC "leveldb debug library" + ) + + set(LEVELDB_LIBRARIES ${LEVELDB_LIBRARIES} ${LEVELDB_LIBRARY_DEBUG}) + +endif() + # handle the QUIETLY and REQUIRED arguments and set LEVELDB_FOUND to TRUE # if all listed variables are TRUE, hide their existence from configuration view include(FindPackageHandleStandardArgs) From a68cb3f0b8294e44c4c72e219ac61814b1843b81 Mon Sep 17 00:00:00 2001 From: ethdev Date: Tue, 16 Dec 2014 12:45:03 +0100 Subject: [PATCH 533/641] jsoncpp && leveldb are now using optimized/debug --- alethzero/CMakeLists.txt | 1 - cmake/FindJsoncpp.cmake | 3 ++- cmake/FindLevelDB.cmake | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index c4237eaee..39c02d6be 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -32,7 +32,6 @@ eth_add_executable(${EXECUTABLE} add_dependencies(${EXECUTABLE} BuildInfo.h) target_link_libraries(${EXECUTABLE} Qt5::Core) -target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) target_link_libraries(${EXECUTABLE} webthree) target_link_libraries(${EXECUTABLE} qethereum) target_link_libraries(${EXECUTABLE} ethereum) diff --git a/cmake/FindJsoncpp.cmake b/cmake/FindJsoncpp.cmake index c2f0aca43..392b57ffb 100644 --- a/cmake/FindJsoncpp.cmake +++ b/cmake/FindJsoncpp.cmake @@ -27,6 +27,7 @@ set(JSONCPP_LIBRARIES ${JSONCPP_LIBRARY}) # debug library on windows # same naming convention as in qt (appending debug library with d) +# boost is using the same "hack" as us with "optimized" and "debug" if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") find_library( JSONCPP_LIBRARY_DEBUG @@ -34,7 +35,7 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") DOC "jsoncpp debug library" ) - set(JSONCPP_LIBRARIES ${JSONCPP_LIBRARIES} ${JSONCPP_LIBRARY_DEBUG}) + set(JSONCPP_LIBRARIES optimized ${JSONCPP_LIBRARIES} debug ${JSONCPP_LIBRARY_DEBUG}) endif() diff --git a/cmake/FindLevelDB.cmake b/cmake/FindLevelDB.cmake index b2f59ec4d..a4aef1705 100644 --- a/cmake/FindLevelDB.cmake +++ b/cmake/FindLevelDB.cmake @@ -27,6 +27,7 @@ set(LEVELDB_LIBRARIES ${LEVELDB_LIBRARY}) # debug library on windows # same naming convention as in qt (appending debug library with d) +# boost is using the same "hack" as us with "optimized" and "debug" if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") find_library( LEVELDB_LIBRARY_DEBUG @@ -34,7 +35,7 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") DOC "leveldb debug library" ) - set(LEVELDB_LIBRARIES ${LEVELDB_LIBRARIES} ${LEVELDB_LIBRARY_DEBUG}) + set(LEVELDB_LIBRARIES optimized ${LEVELDB_LIBRARIES} debug ${LEVELDB_LIBRARY_DEBUG}) endif() From b2bcf713a60781cdce8a9db19a054d6abd5e0a19 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 16 Dec 2014 13:17:30 +0100 Subject: [PATCH 534/641] - Replace Qt5.3 ModalDialog by custom modal dialog. --- mix/AppContext.cpp | 9 ++++----- mix/Extension.cpp | 5 ++--- mix/qml.qrc | 2 ++ mix/qml/AlertMessageDialog.qml | 27 +++++++++++++++++++++++++++ mix/qml/BasicMessage.qml | 1 + mix/qml/Debugger.qml | 8 -------- mix/qml/ModalDialog.qml | 27 +++++++++++++++++++++++++++ mix/qml/main.qml | 22 +++------------------- 8 files changed, 66 insertions(+), 35 deletions(-) create mode 100644 mix/qml/AlertMessageDialog.qml create mode 100644 mix/qml/ModalDialog.qml diff --git a/mix/AppContext.cpp b/mix/AppContext.cpp index 92b3f4c0a..89f2849cd 100644 --- a/mix/AppContext.cpp +++ b/mix/AppContext.cpp @@ -74,14 +74,13 @@ void AppContext::setApplicationContext(QQmlApplicationEngine* _engine) void AppContext::displayMessageDialog(QString _title, QString _message) { - QQmlComponent component(m_applicationEngine.get(), QUrl("qrc:/qml/BasicMessage.qml")); - QObject* dialog = component.create(); - dialog->findChild("messageContent", Qt::FindChildrenRecursively)->setProperty("text", _message); - QObject* dialogWin = AppContext::getInstance()->appEngine()->rootObjects().at(0)->findChild("messageDialog", Qt::FindChildrenRecursively); + QObject* dialogWin = m_applicationEngine.get()->rootObjects().at(0)->findChild("alertMessageDialog", Qt::FindChildrenRecursively); + QObject* dialogWinComponent = m_applicationEngine.get()->rootObjects().at(0)->findChild("alertMessageDialogContent", Qt::FindChildrenRecursively); QMetaObject::invokeMethod(dialogWin, "close"); - dialogWin->setProperty("contentItem", QVariant::fromValue(dialog)); + dialogWinComponent->setProperty("source", QString("qrc:/qml/BasicMessage.qml")); dialogWin->setProperty("title", _title); dialogWin->setProperty("width", "250"); dialogWin->setProperty("height", "100"); + dialogWin->findChild("messageContent", Qt::FindChildrenRecursively)->setProperty("text", _message); QMetaObject::invokeMethod(dialogWin, "open"); } diff --git a/mix/Extension.cpp b/mix/Extension.cpp index f9a8ad94d..e46fc4145 100644 --- a/mix/Extension.cpp +++ b/mix/Extension.cpp @@ -65,11 +65,10 @@ void Extension::addContentOn(QObject* _view) Q_UNUSED(_view); if (m_displayBehavior == ExtensionDisplayBehavior::ModalDialog) { - QQmlComponent component(AppContext::getInstance()->appEngine(), QUrl(contentUrl())); - QObject* dialog = component.create(); QObject* dialogWin = AppContext::getInstance()->appEngine()->rootObjects().at(0)->findChild("dialog", Qt::FindChildrenRecursively); + QObject* dialogWinComponent = AppContext::getInstance()->appEngine()->rootObjects().at(0)->findChild("modalDialogContent", Qt::FindChildrenRecursively); QMetaObject::invokeMethod(dialogWin, "close"); - dialogWin->setProperty("contentItem", QVariant::fromValue(dialog)); + dialogWinComponent->setProperty("source", contentUrl()); dialogWin->setProperty("title", title()); QMetaObject::invokeMethod(dialogWin, "open"); } diff --git a/mix/qml.qrc b/mix/qml.qrc index 2fa92d661..d14aa9974 100644 --- a/mix/qml.qrc +++ b/mix/qml.qrc @@ -7,5 +7,7 @@ qml/Debugger.qml qml/js/Debugger.js qml/BasicMessage.qml + qml/ModalDialog.qml + qml/AlertMessageDialog.qml diff --git a/mix/qml/AlertMessageDialog.qml b/mix/qml/AlertMessageDialog.qml new file mode 100644 index 000000000..f89ade45f --- /dev/null +++ b/mix/qml/AlertMessageDialog.qml @@ -0,0 +1,27 @@ +import QtQuick 2.2 +import QtQuick.Window 2.0 + +Window +{ + id: alertMessageDialog + title: "" + modality: Qt.WindowModal + height: 150 + width: 200 + visible: false + Loader + { + focus: true + id: alertMessageDialogContent + objectName: "alertMessageDialogContent" + anchors.fill: parent + } + function open() + { + visible = true + } + function close() + { + visible = false + } +} diff --git a/mix/qml/BasicMessage.qml b/mix/qml/BasicMessage.qml index 0678c9b54..233717009 100644 --- a/mix/qml/BasicMessage.qml +++ b/mix/qml/BasicMessage.qml @@ -18,3 +18,4 @@ Rectangle { text: "" } } + diff --git a/mix/qml/Debugger.qml b/mix/qml/Debugger.qml index e895d1ada..fa3e8aba4 100644 --- a/mix/qml/Debugger.qml +++ b/mix/qml/Debugger.qml @@ -21,7 +21,6 @@ Rectangle { font.italic: true id: headerInfoLabel } - } Keys.onPressed: { @@ -138,7 +137,6 @@ Rectangle { horizontalAlignment: "AlignHCenter" font.family: "Verdana" font.pointSize: 8 - font.letterSpacing: 2 width: parent.width height: 15 anchors.top : parent.top @@ -149,7 +147,6 @@ Rectangle { width: parent.width font.family: "Verdana" font.pointSize: 8 - font.letterSpacing: 2 height: parent.height - 15 id:debugStackTxt readOnly: true; @@ -166,7 +163,6 @@ Rectangle { horizontalAlignment: "AlignHCenter" font.family: "Verdana" font.pointSize: 8 - font.letterSpacing: 2 width: parent.width height: 15 anchors.top : parent.top @@ -177,7 +173,6 @@ Rectangle { width: parent.width font.family: "Verdana" font.pointSize: 8 - font.letterSpacing: 2 height: parent.height - 15 id: debugMemoryTxt readOnly: true; @@ -194,7 +189,6 @@ Rectangle { horizontalAlignment: "AlignHCenter" font.family: "Verdana" font.pointSize: 8 - font.letterSpacing: 2 width: parent.width height: 15 anchors.top : parent.top @@ -205,7 +199,6 @@ Rectangle { width: parent.width font.family: "Verdana" font.pointSize: 8 - font.letterSpacing: 2 height: parent.height - 15 id:debugStorageTxt readOnly: true; @@ -222,7 +215,6 @@ Rectangle { horizontalAlignment: "AlignHCenter" font.family: "Verdana" font.pointSize: 8 - font.letterSpacing: 2 width: parent.width height: 15 anchors.top : parent.top diff --git a/mix/qml/ModalDialog.qml b/mix/qml/ModalDialog.qml new file mode 100644 index 000000000..983420926 --- /dev/null +++ b/mix/qml/ModalDialog.qml @@ -0,0 +1,27 @@ +import QtQuick 2.2 +import QtQuick.Window 2.0 + +Window +{ + id: modalDialog + title: "" + modality: Qt.WindowModal + height: 400 + width: 700 + visible: false + Loader + { + focus: true + id: modalDialogContent + objectName: "modalDialogContent" + anchors.fill: parent + } + function open() + { + visible = true + } + function close() + { + visible = false + } +} diff --git a/mix/qml/main.qml b/mix/qml/main.qml index 05b29eb62..52c47e063 100644 --- a/mix/qml/main.qml +++ b/mix/qml/main.qml @@ -30,29 +30,13 @@ ApplicationWindow { MainContent { } - Dialog { - x: mainApplication.x + (mainApplication.width - width) / 2 - y: mainApplication.y + (mainApplication.height - height) / 2 + ModalDialog { objectName: "dialog" id: dialog - height: 400 - width: 700 - modality: Qt.WindowModal - contentItem: Rectangle { - objectName: "dialogContent" - } } - Dialog { - x: mainApplication.x + (mainApplication.width - width) / 2 - y: mainApplication.y + (mainApplication.height - height) / 2 - objectName: "messageDialog" + AlertMessageDialog { + objectName: "alertMessageDialog" id: messageDialog - height: 150 - width: 200 - modality: Qt.WindowModal - contentItem: Rectangle { - objectName: "messageContent" - } } } From e2223b8057e40a3af5a79c2df7f48a7674bc2cb5 Mon Sep 17 00:00:00 2001 From: ethdev Date: Tue, 16 Dec 2014 15:31:34 +0100 Subject: [PATCH 535/641] missing boost include in eth --- eth/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/eth/CMakeLists.txt b/eth/CMakeLists.txt index 27fd542c1..c98f3cbec 100644 --- a/eth/CMakeLists.txt +++ b/eth/CMakeLists.txt @@ -3,6 +3,7 @@ set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) +include_directories(${Boost_INCLUDE_DIRS}) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) include_directories(..) From 0532223f516a8853bfd90e38bcdd51d2fa27e39b Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Tue, 16 Dec 2014 16:03:23 +0100 Subject: [PATCH 536/641] fixed typo --- cmake/FindGmp.cmake | 2 +- cmake/FindJsonRpcCpp.cmake | 2 +- cmake/FindJsoncpp.cmake | 4 ++-- cmake/FindLevelDB.cmake | 2 +- cmake/FindMiniupnpc.cmake | 2 +- cmake/FindReadline.cmake | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cmake/FindGmp.cmake b/cmake/FindGmp.cmake index 4dc8f48c4..1cffa7efa 100644 --- a/cmake/FindGmp.cmake +++ b/cmake/FindGmp.cmake @@ -2,7 +2,7 @@ # # Find the gmp includes and library # -# if you nee to add a custom library search path, do it via via CMAKE_FIND_ROOT_PATH +# if you nee to add a custom library search path, do it via via CMAKE_PREFIX_PATH # # This module defines # GMP_INCLUDE_DIRS, where to find header, etc. diff --git a/cmake/FindJsonRpcCpp.cmake b/cmake/FindJsonRpcCpp.cmake index eecf518f8..3072ff244 100644 --- a/cmake/FindJsonRpcCpp.cmake +++ b/cmake/FindJsonRpcCpp.cmake @@ -2,7 +2,7 @@ # # Find the json-rpc-cpp includes and library # -# if you nee to add a custom library search path, do it via via CMAKE_FIND_ROOT_PATH +# if you nee to add a custom library search path, do it via via CMAKE_PREFIX_PATH # # This module defines # JSON_RCP_CPP_INCLUDE_DIRS, where to find header, etc. diff --git a/cmake/FindJsoncpp.cmake b/cmake/FindJsoncpp.cmake index 392b57ffb..36ba12a3e 100644 --- a/cmake/FindJsoncpp.cmake +++ b/cmake/FindJsoncpp.cmake @@ -2,7 +2,7 @@ # # Find the jsoncpp includes and library # -# if you nee to add a custom library search path, do it via via CMAKE_FIND_ROOT_PATH +# if you nee to add a custom library search path, do it via via CMAKE_PREFIX_PATH # # This module defines # JSONCPP_INCLUDE_DIRS, where to find header, etc. @@ -39,7 +39,7 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") endif() -# handle the QUIETLY and REQUIRED arguments and set GMP_FOUND to TRUE +# handle the QUIETLY and REQUIRED arguments and set JSONCPP_FOUND to TRUE # if all listed variables are TRUE, hide their existence from configuration view include(FindPackageHandleStandardArgs) find_package_handle_standard_args(jsoncpp DEFAULT_MSG diff --git a/cmake/FindLevelDB.cmake b/cmake/FindLevelDB.cmake index a4aef1705..b1a9a5815 100644 --- a/cmake/FindLevelDB.cmake +++ b/cmake/FindLevelDB.cmake @@ -2,7 +2,7 @@ # # Find the leveldb includes and library # -# if you nee to add a custom library search path, do it via via CMAKE_FIND_ROOT_PATH +# if you nee to add a custom library search path, do it via via CMAKE_PREFIX_PATH # # This module defines # LEVELDB_INCLUDE_DIRS, where to find header, etc. diff --git a/cmake/FindMiniupnpc.cmake b/cmake/FindMiniupnpc.cmake index 4ecbb0c4a..1438a8526 100644 --- a/cmake/FindMiniupnpc.cmake +++ b/cmake/FindMiniupnpc.cmake @@ -2,7 +2,7 @@ # # Find the miniupnpc includes and library # -# if you nee to add a custom library search path, do it via via CMAKE_FIND_ROOT_PATH +# if you nee to add a custom library search path, do it via via CMAKE_PREFIX_PATH # # This module defines # MINIUPNPC_INCLUDE_DIRS, where to find header, etc. diff --git a/cmake/FindReadline.cmake b/cmake/FindReadline.cmake index 1f47db4a7..c1cdfd33a 100644 --- a/cmake/FindReadline.cmake +++ b/cmake/FindReadline.cmake @@ -2,7 +2,7 @@ # # Find the readline includes and library # -# if you nee to add a custom library search path, do it via via CMAKE_FIND_ROOT_PATH +# if you nee to add a custom library search path, do it via via CMAKE_PREFIX_PATH # # This module defines # READLINE_INCLUDE_DIRS, where to find header, etc. From a22376093a54bc7f478e9458ca4f350cd623c846 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 16 Dec 2014 16:14:13 +0100 Subject: [PATCH 537/641] Prepared State premine. Fixes for Qt 5.2. --- mix/AssemblyDebuggerCtrl.cpp | 3 +-- mix/AssemblyDebuggerModel.cpp | 39 +++++++++++++++++++++-------------- mix/AssemblyDebuggerModel.h | 21 ++++++++++++------- mix/qml/BasicMessage.qml | 6 +++--- mix/qml/Debugger.qml | 6 +++--- mix/qml/MainContent.qml | 4 ++-- mix/qml/main.qml | 2 +- 7 files changed, 48 insertions(+), 33 deletions(-) diff --git a/mix/AssemblyDebuggerCtrl.cpp b/mix/AssemblyDebuggerCtrl.cpp index 678f94d77..e955dfd23 100644 --- a/mix/AssemblyDebuggerCtrl.cpp +++ b/mix/AssemblyDebuggerCtrl.cpp @@ -69,11 +69,10 @@ void AssemblyDebuggerCtrl::keyPressed(int _key) return; } - KeyPair ad = KeyPair::create(); u256 gasPrice = 10000000000000; u256 gas = 1000000; u256 amount = 100; - DebuggingContent debuggingContent = m_modelDebugger->getContractInitiationDebugStates(amount, gasPrice, gas, m_doc->toPlainText(), ad); + DebuggingContent debuggingContent = m_modelDebugger->getContractInitiationDebugStates(amount, gasPrice, gas, m_doc->toPlainText()); //we need to wrap states in a QObject before sending to QML. QList wStates; diff --git a/mix/AssemblyDebuggerModel.cpp b/mix/AssemblyDebuggerModel.cpp index 151c14773..1e07760e1 100644 --- a/mix/AssemblyDebuggerModel.cpp +++ b/mix/AssemblyDebuggerModel.cpp @@ -18,30 +18,36 @@ */ #include -#include "libethereum/Executive.h" -#include "libethereum/Transaction.h" -#include "libethereum/ExtVM.h" -#include "libevm/VM.h" -#include "libdevcore/Common.h" +#include +#include +#include +#include +#include #include "AppContext.h" #include "TransactionBuilder.h" #include "AssemblyDebuggerModel.h" #include "ConstantCompilationModel.h" #include "DebuggingStateWrapper.h" +using namespace std; using namespace dev; using namespace dev::eth; using namespace dev::mix; -AssemblyDebuggerModel::AssemblyDebuggerModel() +AssemblyDebuggerModel::AssemblyDebuggerModel(): + m_userAccount(KeyPair::create()), + m_baseState(Address(), m_overlayDB, BaseState::Empty) { + m_baseState.addBalance(m_userAccount.address(), 10000000 * ether); m_currentExecution = std::unique_ptr(new Executive(m_executiveState, 0)); } DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::bytesConstRef _rawTransaction) { + // Reset the state back to our clean premine. + m_executiveState = m_baseState; + QList states; - Transaction tr(_rawTransaction); - m_currentExecution->create(tr.sender(), tr.value(), tr.gasPrice(), tr.gas(), &tr.data(), tr.sender()); + m_currentExecution->setup(_rawTransaction); std::vector levels; bytes code; bytesConstRef data; @@ -67,7 +73,9 @@ DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::by vm.stack(), vm.memory(), gasCost, ext.state().storage(ext.myAddress), levels})); }; + m_currentExecution->go(onOp); + cdebug << states.size(); m_currentExecution->finalize(onOp); DebuggingContent d; @@ -79,11 +87,12 @@ DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::by return d; } -DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::u256 _value, - dev::u256 _gasPrice, - dev::u256 _gas, - QString _code, - KeyPair _key) +DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates( + dev::u256 _value, + dev::u256 _gasPrice, + dev::u256 _gas, + QString _code +) { ConstantCompilationModel compiler; CompilerResult res = compiler.compile(_code); @@ -96,8 +105,8 @@ DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::u2 } TransactionBuilder trBuild; - Transaction tr = trBuild.getCreationTransaction(_value, _gasPrice, _gas, res.bytes, - m_executiveState.transactionsFrom(dev::toAddress(_key.secret())), _key.secret()); + Transaction tr = trBuild.getCreationTransaction(_value, _gasPrice, min(_gas, m_baseState.gasLimitRemaining()), res.bytes, + m_executiveState.transactionsFrom(dev::toAddress(m_userAccount.secret())), m_userAccount.secret()); bytes b = tr.rlp(); dev::bytesConstRef bytesRef = &b; return getContractInitiationDebugStates(bytesRef); diff --git a/mix/AssemblyDebuggerModel.h b/mix/AssemblyDebuggerModel.h index 3ed6818bc..b6e0224e8 100644 --- a/mix/AssemblyDebuggerModel.h +++ b/mix/AssemblyDebuggerModel.h @@ -21,9 +21,10 @@ #include #include -#include "libethereum/State.h" -#include "libethereum/Executive.h" -#include "libdevcore/Common.h" +#include +#include +#include +#include #include "DebuggingStateWrapper.h" namespace dev @@ -31,17 +32,23 @@ namespace dev namespace mix { +/** + * @brief Long-life object for managing all executions. + */ class AssemblyDebuggerModel { public: AssemblyDebuggerModel(); - DebuggingContent getContractInitiationDebugStates(dev::u256, dev::u256, dev::u256, QString, KeyPair); - DebuggingContent getContractInitiationDebugStates(dev::bytesConstRef); + DebuggingContent getContractInitiationDebugStates(u256, u256, u256, QString); + DebuggingContent getContractInitiationDebugStates(bytesConstRef); bool compile(QString); private: - std::unique_ptr m_currentExecution; - dev::eth::State m_executiveState; + KeyPair m_userAccount; + OverlayDB m_overlayDB; + eth::State m_baseState; + eth::State m_executiveState; + std::unique_ptr m_currentExecution; }; } diff --git a/mix/qml/BasicMessage.qml b/mix/qml/BasicMessage.qml index 233717009..7127d29ff 100644 --- a/mix/qml/BasicMessage.qml +++ b/mix/qml/BasicMessage.qml @@ -1,7 +1,7 @@ import QtQuick 2.2 -import QtQuick.Controls.Styles 1.2 -import QtQuick.Controls 1.2 -import QtQuick.Dialogs 1.2 +import QtQuick.Controls.Styles 1.1 +import QtQuick.Controls 1.1 +import QtQuick.Dialogs 1.1 import QtQuick.Layouts 1.1 Rectangle { diff --git a/mix/qml/Debugger.qml b/mix/qml/Debugger.qml index fa3e8aba4..18f706970 100644 --- a/mix/qml/Debugger.qml +++ b/mix/qml/Debugger.qml @@ -1,7 +1,7 @@ import QtQuick 2.2 -import QtQuick.Controls.Styles 1.2 -import QtQuick.Controls 1.2 -import QtQuick.Dialogs 1.2 +import QtQuick.Controls.Styles 1.1 +import QtQuick.Controls 1.1 +import QtQuick.Dialogs 1.1 import QtQuick.Layouts 1.1 import "js/Debugger.js" as Debugger diff --git a/mix/qml/MainContent.qml b/mix/qml/MainContent.qml index 1da48a1c8..6d08f79ec 100644 --- a/mix/qml/MainContent.qml +++ b/mix/qml/MainContent.qml @@ -1,7 +1,7 @@ import QtQuick 2.2 -import QtQuick.Controls 1.2 +import QtQuick.Controls 1.1 import QtQuick.Layouts 1.0 -import QtQuick.Controls.Styles 1.2 +import QtQuick.Controls.Styles 1.1 import CodeEditorExtensionManager 1.0 Rectangle { diff --git a/mix/qml/main.qml b/mix/qml/main.qml index 52c47e063..42ee3ef97 100644 --- a/mix/qml/main.qml +++ b/mix/qml/main.qml @@ -1,7 +1,7 @@ import QtQuick 2.2 import QtQuick.Controls 1.1 import QtQuick.Controls.Styles 1.1 -import QtQuick.Dialogs 1.2 +import QtQuick.Dialogs 1.1 import QtQuick.Layouts 1.1 import QtQuick.Window 2.0 import CodeEditorExtensionManager 1.0 From c00153e5c145cc7ac780195357a7ed6be9e9763a Mon Sep 17 00:00:00 2001 From: Christian Date: Tue, 16 Dec 2014 16:15:34 +0100 Subject: [PATCH 538/641] Stylistic changes. --- libevmcore/Assembly.cpp | 8 +++++++- libsolidity/AST.h | 2 +- libsolidity/Types.cpp | 6 +++--- libsolidity/grammar.txt | 2 +- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/libevmcore/Assembly.cpp b/libevmcore/Assembly.cpp index b78f03035..74bd015a6 100644 --- a/libevmcore/Assembly.cpp +++ b/libevmcore/Assembly.cpp @@ -60,7 +60,13 @@ int AssemblyItem::deposit() const { case Operation: return instructionInfo((Instruction)(byte)m_data).ret - instructionInfo((Instruction)(byte)m_data).args; - case Push: case PushString: case PushTag: case PushData: case PushSub: case PushSubSize: case PushProgramSize: + case Push: + case PushString: + case PushTag: + case PushData: + case PushSub: + case PushSubSize: + case PushProgramSize: return 1; case Tag: return 0; diff --git a/libsolidity/AST.h b/libsolidity/AST.h index 72f96394f..4bb623b49 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -763,7 +763,7 @@ public: std::vector> getArguments() const { return {m_arguments.begin(), m_arguments.end()}; } /// Returns the referenced contract. Can only be called after type checking. - ContractDefinition const* getContract() const { return m_contract; } + ContractDefinition const* getContract() const { if (asserts(m_contract)) BOOST_THROW_EXCEPTION(InternalCompilerError()); else return m_contract; } private: ASTPointer m_contractName; diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index f1cd7c228..eba11cb0d 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -314,9 +314,9 @@ shared_ptr const& ContractType::getConstructorType() const { if (!m_constructorType) { - FunctionDefinition const* constr = m_contract.getConstructor(); - if (constr) - m_constructorType = make_shared(*constr); + FunctionDefinition const* constructor = m_contract.getConstructor(); + if (constructor) + m_constructorType = make_shared(*constructor); else m_constructorType = make_shared(TypePointers(), TypePointers()); } diff --git a/libsolidity/grammar.txt b/libsolidity/grammar.txt index 793e91882..a26f717a1 100644 --- a/libsolidity/grammar.txt +++ b/libsolidity/grammar.txt @@ -29,7 +29,7 @@ Expression = Assignment | UnaryOperation | BinaryOperation | FunctionCall | NewE MemberAccess | PrimaryExpression // The expression syntax is actually much more complicated Assignment = Expression (AssignmentOp Expression) -FunctionCall = Expression '(' ( Expression ( ',' Expression )* ) ')' +FunctionCall = Expression '(' Expression ( ',' Expression )* ')' NewExpression = 'new' Identifier '(' ( Expression ( ',' Expression )* ) ')' MemberAccess = Expression '.' Identifier IndexAccess = Expression '[' Expresison ']' From 76db957b529f5d436ba2d53787def77769f7729f Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Tue, 16 Dec 2014 18:00:39 +0100 Subject: [PATCH 539/641] fixed macdeployqt options order --- cmake/EthExecutableHelper.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmake/EthExecutableHelper.cmake b/cmake/EthExecutableHelper.cmake index 56aa3f6c3..9d273522e 100644 --- a/cmake/EthExecutableHelper.cmake +++ b/cmake/EthExecutableHelper.cmake @@ -61,12 +61,13 @@ macro(eth_install_executable EXECUTABLE) if (ETH_INSTALL_EXECUTABLE_QMLDIR) set(eth_qml_dir "-qmldir=${ETH_INSTALL_EXECUTABLE_QMLDIR}") + message(STATUS "${EXECUTABLE} qmldir: ${eth_qml_dir}") endif() if (APPLE) # First have qt5 install plugins and frameworks add_custom_command(TARGET ${EXECUTABLE} POST_BUILD - COMMAND ${MACDEPLOYQT_APP} ${eth_qml_dir} ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app + COMMAND ${MACDEPLOYQT_APP} ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app ${eth_qml_dir} WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) # This tool and next will inspect linked libraries in order to determine which dependencies are required From 381c30ecd0cba487e523551dd1e7737847cb9f5f Mon Sep 17 00:00:00 2001 From: wanderer Date: Fri, 12 Dec 2014 09:35:18 -0500 Subject: [PATCH 540/641] changed output stacktrace format to json --- test/vm.cpp | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/test/vm.cpp b/test/vm.cpp index 49d6ed104..27e1da238 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -262,12 +262,45 @@ eth::OnOpFunc FakeExtVM::simpleTrace() dev::LogOutputStream(true) << o.str(); dev::LogOutputStream(false) << " | " << std::dec << ext.depth << " | " << ext.myAddress << " | #" << steps << " | " << std::hex << std::setw(4) << std::setfill('0') << vm.curPC() << " : " << instructionInfo(inst).name << " | " << std::dec << vm.gas() << " | -" << std::dec << gasCost << " | " << newMemSize << "x32" << " ]"; + /*creates json stack trace*/ if (eth::VMTraceChannel::verbosity <= g_logVerbosity) { + std::ostringstream ofile; + + u256s stack = vm.stack(); + ofile << endl << "{" << endl << " \"stack\":[" << endl; + for (vector::iterator i = stack.begin(); i != stack.end(); ++i){ + ofile << " \"" << (h256)*i << "\""; + if(next(i) != stack.end()){ + ofile << ","; + } + + ofile << endl; + } + + ofile << " ]," << endl; + ofile << " \"memory\": \""; + for(auto i: vm.memory()) + ofile << setfill('0') << setw(2) << hex << (unsigned)i; + ofile << "\"," << endl; + + ofile << " \"storage\": [" << endl; + for (auto const& i: std::get<2>(ext.addresses.find(ext.myAddress)->second)){ + ofile << " [" << endl; + ofile << " \"" << std::showbase << std::hex << i.first << "\": \"" << i.second << "\"" << std::endl; + } + + ofile << " ]," << endl; + ofile << " \"depth\": " << dec << ext.depth << "," << endl; + ofile << " \"gas\":" << dec < Date: Sun, 14 Dec 2014 13:11:54 -0500 Subject: [PATCH 541/641] using json_spirit --- test/vm.cpp | 77 ++++++++++++++++++++++++++++++++--------------------- test/vm.h | 2 +- 2 files changed, 47 insertions(+), 32 deletions(-) diff --git a/test/vm.cpp b/test/vm.cpp index 27e1da238..39ffdb7b2 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -265,42 +265,57 @@ eth::OnOpFunc FakeExtVM::simpleTrace() /*creates json stack trace*/ if (eth::VMTraceChannel::verbosity <= g_logVerbosity) { - std::ostringstream ofile; - - u256s stack = vm.stack(); - ofile << endl << "{" << endl << " \"stack\":[" << endl; - for (vector::iterator i = stack.begin(); i != stack.end(); ++i){ - ofile << " \"" << (h256)*i << "\""; - if(next(i) != stack.end()){ - ofile << ","; - } + Object o_step; - ofile << endl; - } + /*add the stack*/ + Array a_stack; + for (auto i: vm.stack()) + a_stack.push_back((string)i); - ofile << " ]," << endl; - ofile << " \"memory\": \""; - for(auto i: vm.memory()) - ofile << setfill('0') << setw(2) << hex << (unsigned)i; - ofile << "\"," << endl; + o_step.push_back(Pair( "stack", a_stack )); - ofile << " \"storage\": [" << endl; - for (auto const& i: std::get<2>(ext.addresses.find(ext.myAddress)->second)){ - ofile << " [" << endl; - ofile << " \"" << std::showbase << std::hex << i.first << "\": \"" << i.second << "\"" << std::endl; + /*add the memory*/ + Array a_mem; + for(auto i: vm.memory()) + a_mem.push_back(i); + + o_step.push_back(Pair("memory", a_mem)); + + /*add the storage*/ + Object storage; + for (auto const& i: std::get<2>(ext.addresses.find(ext.myAddress)->second)) + storage.push_back(Pair( (string)i.first , (string)i.second)); + + /*add all the other details*/ + o_step.push_back(Pair("storage", storage)); + o_step.push_back(Pair("depth", to_string(ext.depth))); + o_step.push_back(Pair("gas", (string)vm.gas())); + o_step.push_back(Pair("address", "0x" + toString(ext.myAddress ))); + o_step.push_back(Pair("step", steps )); + o_step.push_back(Pair("pc", (int)vm.curPC())); + o_step.push_back(Pair("opcode", instructionInfo(inst).name )); + + ifstream is( "./stackTrace.json"); + string istr((std::istreambuf_iterator(is) ), (std::istreambuf_iterator())); + is.close(); + Value iv; + Array a_trace; + + /*try to parse the current trace file*/ + try{ + read_string(istr, iv); + a_trace = iv.get_array(); } + catch(...){} + + /*add this step to the array of steps*/ + a_trace.push_back(o_step); + + ofstream os( "./stackTrace.json"); - ofile << " ]," << endl; - ofile << " \"depth\": " << dec << ext.depth << "," << endl; - ofile << " \"gas\":" << dec <. #include #include #include -#include "JsonSpiritHeaders.h" +#include #include #include #include From 4dd5240111dde6368df728fa752f9ae2d7efe53b Mon Sep 17 00:00:00 2001 From: wanderer Date: Tue, 16 Dec 2014 14:28:03 -0500 Subject: [PATCH 542/641] append JSON objects to log --- test/vm.cpp | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/test/vm.cpp b/test/vm.cpp index 39ffdb7b2..010eb4d75 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -295,26 +295,10 @@ eth::OnOpFunc FakeExtVM::simpleTrace() o_step.push_back(Pair("pc", (int)vm.curPC())); o_step.push_back(Pair("opcode", instructionInfo(inst).name )); - ifstream is( "./stackTrace.json"); - string istr((std::istreambuf_iterator(is) ), (std::istreambuf_iterator())); - is.close(); - Value iv; - Array a_trace; - - /*try to parse the current trace file*/ - try{ - read_string(istr, iv); - a_trace = iv.get_array(); - } - catch(...){} - - /*add this step to the array of steps*/ - a_trace.push_back(o_step); - - ofstream os( "./stackTrace.json"); - - Value v(a_trace); - os << write_string(v, true); + /*append the JSON object to the log file*/ + Value v(o_step); + ofstream os( "./stackTrace.json", ofstream::app); + os << write_string(v, true) << ","; os.close(); } }; From 8ecf06df863074e3c2009c0ed30540cb4fccc881 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Tue, 16 Dec 2014 20:17:23 +0100 Subject: [PATCH 543/641] FindCURL in out cmake folder, required to find debug curl library --- cmake/EthDependencies.cmake | 2 +- cmake/FindCURL.cmake | 49 +++++++++++++++++++++++++++++++++++++ cmake/FindGmp.cmake | 4 +-- 3 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 cmake/FindCURL.cmake diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index ee93a5311..136c86799 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -82,7 +82,7 @@ if (GMP_FOUND) endif() # curl is only requried for tests -# TODO specify min curl version, on windows we are currenly using 7.29 +# TODO specify min curl version, on windows we are currently using 7.29 find_package (CURL) message(" - curl header: ${CURL_INCLUDE_DIRS}") message(" - curl lib : ${CURL_LIBRARIES}") diff --git a/cmake/FindCURL.cmake b/cmake/FindCURL.cmake new file mode 100644 index 000000000..ba6603784 --- /dev/null +++ b/cmake/FindCURL.cmake @@ -0,0 +1,49 @@ +# Find CURL +# +# Find the curl includes and library +# +# if you nee to add a custom library search path, do it via via CMAKE_PREFIX_PATH +# +# This module defines +# CURL_INCLUDE_DIRS, where to find header, etc. +# CURL_LIBRARIES, the libraries needed to use curl. +# CURL_FOUND, If false, do not try to use curl. + +# only look in default directories +find_path( + CURL_INCLUDE_DIR + NAMES curl/curl.h + DOC "curl include dir" +) + +find_library( + CURL_LIBRARY + # names from cmake's FindCURL + NAMES curl curllib libcurl_imp curllib_static libcurl + DOC "curl library" +) + +set(CURL_INCLUDE_DIRS ${CURL_INCLUDE_DIR}) +set(CURL_LIBRARIES ${CURL_LIBRARY}) + +# debug library on windows +# same naming convention as in qt (appending debug library with d) +# boost is using the same "hack" as us with "optimized" and "debug" +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + find_library( + CURL_LIBRARY_DEBUG + NAMES curld libcurld + DOC "curl debug library" + ) + + set(CURL_LIBRARIES optimized ${CURL_LIBRARIES} debug ${CURL_LIBRARY_DEBUG}) + +endif() + +# handle the QUIETLY and REQUIRED arguments and set CURL_FOUND to TRUE +# if all listed variables are TRUE, hide their existence from configuration view +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(CURL DEFAULT_MSG + CURL_INCLUDE_DIR CURL_LIBRARY) +mark_as_advanced (CURL_INCLUDE_DIR CURL_LIBRARY) + diff --git a/cmake/FindGmp.cmake b/cmake/FindGmp.cmake index 1cffa7efa..4570b35fa 100644 --- a/cmake/FindGmp.cmake +++ b/cmake/FindGmp.cmake @@ -14,13 +14,13 @@ find_path( GMP_INCLUDE_DIR NAMES gmp.h DOC "gmp include dir" - ) +) find_library( GMP_LIBRARY NAMES gmp DOC "gmp library" - ) +) set(GMP_INCLUDE_DIRS ${GMP_INCLUDE_DIR}) set(GMP_LIBRARIES ${GMP_LIBRARY}) From 99dce392b03edc5ec5e27039fac6e039953581ed Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Tue, 16 Dec 2014 20:53:48 +0100 Subject: [PATCH 544/641] find jsonrpccpp debug libraries --- cmake/FindJsonRpcCpp.cmake | 47 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/cmake/FindJsonRpcCpp.cmake b/cmake/FindJsonRpcCpp.cmake index 3072ff244..2ca176f68 100644 --- a/cmake/FindJsonRpcCpp.cmake +++ b/cmake/FindJsonRpcCpp.cmake @@ -43,6 +43,53 @@ set (JSON_RPC_CPP_LIBRARIES ${JSON_RPC_CPP_COMMON_LIBRARY} ${JSON_RPC_CPP_SERVER set (JSON_RPC_CPP_SERVER_LIBRARIES ${JSON_RPC_CPP_COMMON_LIBRARY} ${JSON_RPC_CPP_SERVER_LIBRARY}) set (JSON_RPC_CPP_CLIENT_LIBRARIES ${JSON_RPC_CPP_COMMON_LIBRARY} ${JSON_RPC_CPP_CLIENT_LIBRARY}) +# debug library on windows +# same naming convention as in qt (appending debug library with d) +# boost is using the same "hack" as us with "optimized" and "debug" +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + find_library( + JSON_RPC_CPP_COMMON_LIBRARY_DEBUG + NAMES jsonrpccpp-commond + DOC "json-rpc-cpp common debug library" + ) + + find_library( + JSON_RPC_CPP_SERVER_LIBRARY_DEBUG + NAMES jsonrpccpp-serverd + DOC "json-rpc-cpp server debug library" + ) + + find_library( + JSON_RPC_CPP_CLIENT_LIBRARY_DEBUG + NAMES jsonrpccpp-clientd + DOC "json-rpc-cpp client debug library" + ) + + set (JSON_RPC_CPP_LIBRARIES + optimized ${JSON_RPC_CPP_COMMON_LIBRARY} + optimized ${JSON_RPC_CPP_SERVER_LIBRARY} + optimized ${JSON_RPC_CPP_CLIENT_LIBRARY} + debug ${JSON_RPC_CPP_COMMON_LIBRARY_DEBUG} + debug ${JSON_RPC_CPP_SERVER_LIBRARY_DEBUG} + debug ${JSON_RPC_CPP_CLIENT_LIBRARY_DEBUG} + ) + + set (JSON_RPC_CPP_SERVER_LIBRARIES + optimized ${JSON_RPC_CPP_COMMON_LIBRARY} + optimized ${JSON_RPC_CPP_SERVER_LIBRARY} + debug ${JSON_RPC_CPP_COMMON_LIBRARY_DEBUG} + debug ${JSON_RPC_CPP_SERVER_LIBRARY_DEBUG} + ) + + set (JSON_RPC_CPP_CLIENT_LIBRARIES + optimized ${JSON_RPC_CPP_COMMON_LIBRARY} + optimized ${JSON_RPC_CPP_CLIENT_LIBRARY} + debug ${JSON_RPC_CPP_COMMON_LIBRARY_DEBUG} + debug ${JSON_RPC_CPP_CLIENT_LIBRARY_DEBUG} + ) + +endif() + # handle the QUIETLY and REQUIRED arguments and set JSON_RPC_CPP_FOUND to TRUE # if all listed variables are TRUE, hide their existence from configuration view include(FindPackageHandleStandardArgs) From 28409ed583eda067619a36832db8866af8593ac2 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 16 Dec 2014 23:08:25 +0100 Subject: [PATCH 545/641] Fix for unhandled solc exception with opcodes argument - This should fix #631 --- solc/CommandLineInterface.cpp | 51 +++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 6ace332f7..f13423edb 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -43,6 +43,16 @@ using namespace std; namespace po = boost::program_options; +// LTODO: Maybe some argument class pairing names with +// extensions and other attributes would be a better choice here? +#define ARG_ABI_STR "abi" +#define ARG_ASM_STR "asm" +#define ARG_AST_STR "ast" +#define ARG_BINARY_STR "binary" +#define ARG_OPCODES_STR "opcodes" +#define ARG_NATSPECDEV_STR "natspec-dev" +#define ARG_NATSPECUSER_STR "natspec-user" + namespace dev { namespace solidity @@ -63,8 +73,9 @@ static inline bool argToStdout(po::variables_map const& _args, const char* _name static bool needStdout(po::variables_map const& _args) { - return argToStdout(_args, "abi") || argToStdout(_args, "natspec-user") || argToStdout(_args, "natspec-dev") || - argToStdout(_args, "asm") || argToStdout(_args, "opcodes") || argToStdout(_args, "binary"); + return argToStdout(_args, ARG_ABI_STR) || argToStdout(_args, ARG_NATSPECUSER_STR) || + argToStdout(_args, ARG_NATSPECDEV_STR) || argToStdout(_args, ARG_ASM_STR) || + argToStdout(_args, ARG_OPCODES_STR) || argToStdout(_args, ARG_BINARY_STR); } static inline bool outputToFile(OutputType type) @@ -94,7 +105,7 @@ static std::istream& operator>>(std::istream& _in, OutputType& io_output) void CommandLineInterface::handleBinary(string const& _contract) { - auto choice = m_args["binary"].as(); + auto choice = m_args[ARG_BINARY_STR].as(); if (outputToStdout(choice)) { cout << "Binary: " << endl; @@ -112,7 +123,7 @@ void CommandLineInterface::handleBinary(string const& _contract) void CommandLineInterface::handleOpcode(string const& _contract) { // TODO: Figure out why the wrong operator << (from boost) is used here - auto choice = m_args["opcode"].as(); + auto choice = m_args[ARG_OPCODES_STR].as(); if (outputToStdout(choice)) { cout << "Opcodes: " << endl; @@ -130,9 +141,9 @@ void CommandLineInterface::handleOpcode(string const& _contract) void CommandLineInterface::handleBytecode(string const& _contract) { - if (m_args.count("opcodes")) + if (m_args.count(ARG_OPCODES_STR)) handleOpcode(_contract); - if (m_args.count("binary")) + if (m_args.count(ARG_BINARY_STR)) handleBinary(_contract); } @@ -145,17 +156,17 @@ void CommandLineInterface::handleJson(DocumentationType _type, switch(_type) { case DocumentationType::ABI_INTERFACE: - argName = "abi"; + argName = ARG_ABI_STR; suffix = ".abi"; title = "Contract ABI"; break; case DocumentationType::NATSPEC_USER: - argName = "natspec-user"; + argName = "ARG_NATSPECUSER_STR"; suffix = ".docuser"; title = "User Documentation"; break; case DocumentationType::NATSPEC_DEV: - argName = "natspec-dev"; + argName = ARG_NATSPECDEV_STR; suffix = ".docdev"; title = "Developer Documentation"; break; @@ -195,19 +206,19 @@ bool CommandLineInterface::parseArguments(int argc, char** argv) ("version", "Show version and exit") ("optimize", po::value()->default_value(false), "Optimize bytecode for size") ("input-file", po::value>(), "input file") - ("ast", po::value(), + (ARG_AST_STR, po::value(), "Request to output the AST of the contract. " OUTPUT_TYPE_STR) - ("asm", po::value(), + (ARG_ASM_STR, po::value(), "Request to output the EVM assembly of the contract. " OUTPUT_TYPE_STR) - ("opcodes", po::value(), + (ARG_OPCODES_STR, po::value(), "Request to output the Opcodes of the contract. " OUTPUT_TYPE_STR) - ("binary", po::value(), + (ARG_BINARY_STR, po::value(), "Request to output the contract in binary (hexadecimal). " OUTPUT_TYPE_STR) - ("abi", po::value(), + (ARG_ABI_STR, po::value(), "Request to output the contract's ABI interface. " OUTPUT_TYPE_STR) - ("natspec-user", po::value(), + (ARG_NATSPECUSER_STR, po::value(), "Request to output the contract's Natspec user documentation. " OUTPUT_TYPE_STR) - ("natspec-dev", po::value(), + (ARG_NATSPECDEV_STR, po::value(), "Request to output the contract's Natspec developer documentation. " OUTPUT_TYPE_STR); #undef OUTPUT_TYPE_STR @@ -321,9 +332,9 @@ bool CommandLineInterface::processInput() void CommandLineInterface::actOnInput() { // do we need AST output? - if (m_args.count("ast")) + if (m_args.count(ARG_AST_STR)) { - auto choice = m_args["ast"].as(); + auto choice = m_args[ARG_AST_STR].as(); if (outputToStdout(choice)) { cout << "Syntax trees:" << endl << endl; @@ -355,9 +366,9 @@ void CommandLineInterface::actOnInput() cout << endl << "======= " << contract << " =======" << endl; // do we need EVM assembly? - if (m_args.count("asm")) + if (m_args.count(ARG_ASM_STR)) { - auto choice = m_args["asm"].as(); + auto choice = m_args[ARG_ASM_STR].as(); if (outputToStdout(choice)) { cout << "EVM assembly:" << endl; From b95b6f3b6630bce6ecb73cdf20a58059276df488 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 16 Dec 2014 23:31:22 +0100 Subject: [PATCH 546/641] Properly outputing opcodes in solc, using normal stream operator --- solc/CommandLineInterface.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index f13423edb..8aa182b5c 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -122,19 +122,18 @@ void CommandLineInterface::handleBinary(string const& _contract) void CommandLineInterface::handleOpcode(string const& _contract) { - // TODO: Figure out why the wrong operator << (from boost) is used here auto choice = m_args[ARG_OPCODES_STR].as(); if (outputToStdout(choice)) { cout << "Opcodes: " << endl; - dev::operator<<(cout, m_compiler.getBytecode(_contract)); + cout << eth::disassemble(m_compiler.getBytecode(_contract)); cout << endl; } if (outputToFile(choice)) { ofstream outFile(_contract + ".opcode"); - dev::operator<<(outFile, m_compiler.getBytecode(_contract)); + outFile << eth::disassemble(m_compiler.getBytecode(_contract)); outFile.close(); } } From 41948b13097a8fed084dbdc8ff970cf1d49c40b1 Mon Sep 17 00:00:00 2001 From: Christian Date: Tue, 16 Dec 2014 23:45:24 +0100 Subject: [PATCH 547/641] Fix: Resolve function types of all contracts before checking types inside functions. --- libsolidity/CompilerStack.cpp | 9 +++++++++ libsolidity/NameAndTypeResolver.cpp | 13 +++++++------ libsolidity/NameAndTypeResolver.h | 2 ++ test/solidityCompiler.cpp | 8 ++++++-- test/solidityExpressionCompiler.cpp | 7 ++++++- test/solidityNameAndTypeResolution.cpp | 18 ++++++++++++++++++ 6 files changed, 48 insertions(+), 9 deletions(-) diff --git a/libsolidity/CompilerStack.cpp b/libsolidity/CompilerStack.cpp index 23f5fd68f..1242c0aba 100644 --- a/libsolidity/CompilerStack.cpp +++ b/libsolidity/CompilerStack.cpp @@ -73,6 +73,15 @@ void CompilerStack::parse() resolver.resolveNamesAndTypes(*contract); m_contracts[contract->getName()].contract = contract; } + for (Source const* source: m_sourceOrder) + for (ASTPointer const& node: source->ast->getNodes()) + if (ContractDefinition* contract = dynamic_cast(node.get())) + { + m_globalContext->setCurrentContract(*contract); + resolver.updateDeclaration(*m_globalContext->getCurrentThis()); + resolver.checkTypeRequirements(*contract); + m_contracts[contract->getName()].contract = contract; + } m_parseSuccessful = true; } diff --git a/libsolidity/NameAndTypeResolver.cpp b/libsolidity/NameAndTypeResolver.cpp index 2ad276801..80732615c 100644 --- a/libsolidity/NameAndTypeResolver.cpp +++ b/libsolidity/NameAndTypeResolver.cpp @@ -49,8 +49,6 @@ void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract) m_currentScope = &m_scopes[&_contract]; for (ASTPointer const& structDef: _contract.getDefinedStructs()) ReferencesResolver resolver(*structDef, *this, nullptr); - for (ASTPointer const& structDef: _contract.getDefinedStructs()) - structDef->checkValidityOfMembers(); for (ASTPointer const& variable: _contract.getStateVariables()) ReferencesResolver resolver(*variable, *this, nullptr); for (ASTPointer const& function: _contract.getDefinedFunctions()) @@ -59,13 +57,16 @@ void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract) ReferencesResolver referencesResolver(*function, *this, function->getReturnParameterList().get()); } - // First, the parameter types of all functions need to be resolved before we can check - // the types, since it is possible to call functions that are only defined later - // in the source. - _contract.checkTypeRequirements(); m_currentScope = &m_scopes[nullptr]; } +void NameAndTypeResolver::checkTypeRequirements(ContractDefinition& _contract) +{ + for (ASTPointer const& structDef: _contract.getDefinedStructs()) + structDef->checkValidityOfMembers(); + _contract.checkTypeRequirements(); +} + void NameAndTypeResolver::updateDeclaration(Declaration const& _declaration) { m_scopes[nullptr].registerDeclaration(_declaration, true); diff --git a/libsolidity/NameAndTypeResolver.h b/libsolidity/NameAndTypeResolver.h index 1ff9febf0..23ac5fe77 100644 --- a/libsolidity/NameAndTypeResolver.h +++ b/libsolidity/NameAndTypeResolver.h @@ -46,6 +46,8 @@ public: void registerDeclarations(SourceUnit& _sourceUnit); /// Resolves all names and types referenced from the given contract. void resolveNamesAndTypes(ContractDefinition& _contract); + /// Check all type requirements in the given contract. + void checkTypeRequirements(ContractDefinition& _contract); /// Updates the given global declaration (used for "this"). Not to be used with declarations /// that create their own scope. void updateDeclaration(Declaration const& _declaration); diff --git a/test/solidityCompiler.cpp b/test/solidityCompiler.cpp index 29f61454a..9ae8ff50b 100644 --- a/test/solidityCompiler.cpp +++ b/test/solidityCompiler.cpp @@ -52,9 +52,13 @@ bytes compileContract(const string& _sourceCode) resolver.registerDeclarations(*sourceUnit); for (ASTPointer const& node: sourceUnit->getNodes()) if (ContractDefinition* contract = dynamic_cast(node.get())) - { BOOST_REQUIRE_NO_THROW(resolver.resolveNamesAndTypes(*contract)); - + for (ASTPointer const& node: sourceUnit->getNodes()) + if (ContractDefinition* contract = dynamic_cast(node.get())) + BOOST_REQUIRE_NO_THROW(resolver.checkTypeRequirements(*contract)); + for (ASTPointer const& node: sourceUnit->getNodes()) + if (ContractDefinition* contract = dynamic_cast(node.get())) + { Compiler compiler; compiler.compileContract(*contract, {}, {}); // debug diff --git a/test/solidityExpressionCompiler.cpp b/test/solidityExpressionCompiler.cpp index c05db25d4..2bdc38421 100644 --- a/test/solidityExpressionCompiler.cpp +++ b/test/solidityExpressionCompiler.cpp @@ -95,8 +95,13 @@ bytes compileFirstExpression(const string& _sourceCode, vector> _ resolver.registerDeclarations(*sourceUnit); for (ASTPointer const& node: sourceUnit->getNodes()) if (ContractDefinition* contract = dynamic_cast(node.get())) - { BOOST_REQUIRE_NO_THROW(resolver.resolveNamesAndTypes(*contract)); + for (ASTPointer const& node: sourceUnit->getNodes()) + if (ContractDefinition* contract = dynamic_cast(node.get())) + BOOST_REQUIRE_NO_THROW(resolver.checkTypeRequirements(*contract)); + for (ASTPointer const& node: sourceUnit->getNodes()) + if (ContractDefinition* contract = dynamic_cast(node.get())) + { FirstExpressionExtractor extractor(*contract); BOOST_REQUIRE(extractor.getExpression() != nullptr); diff --git a/test/solidityNameAndTypeResolution.cpp b/test/solidityNameAndTypeResolution.cpp index 0ea6e51b9..0bda0a1fd 100644 --- a/test/solidityNameAndTypeResolution.cpp +++ b/test/solidityNameAndTypeResolution.cpp @@ -47,6 +47,9 @@ void parseTextAndResolveNames(std::string const& _source) for (ASTPointer const& node: sourceUnit->getNodes()) if (ContractDefinition* contract = dynamic_cast(node.get())) resolver.resolveNamesAndTypes(*contract); + for (ASTPointer const& node: sourceUnit->getNodes()) + if (ContractDefinition* contract = dynamic_cast(node.get())) + resolver.checkTypeRequirements(*contract); } } @@ -293,6 +296,21 @@ BOOST_AUTO_TEST_CASE(returns_in_constructor) BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); } +BOOST_AUTO_TEST_CASE(forward_function_reference) +{ + char const* text = "contract First {\n" + " function fun() returns (bool ret) {\n" + " return Second(1).fun(1, true, 3) > 0;\n" + " }\n" + "}\n" + "contract Second {\n" + " function fun(uint a, bool b, uint c) returns (uint ret) {\n" + " if (First(2).fun() == true) return 1;\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + BOOST_AUTO_TEST_SUITE_END() } From 4e83ba5ae148fdcf887e813e7d1aa45ece312666 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 15 Dec 2014 22:57:39 +0100 Subject: [PATCH 548/641] Add functions needed by constructor. --- libsolidity/CallGraph.cpp | 65 ++++++++++++++++++++++ libsolidity/CallGraph.h | 53 ++++++++++++++++++ libsolidity/Compiler.cpp | 101 +++++++++++++++++++--------------- libsolidity/Compiler.h | 12 +++- test/solidityEndToEndTest.cpp | 17 ++++++ 5 files changed, 202 insertions(+), 46 deletions(-) create mode 100644 libsolidity/CallGraph.cpp create mode 100644 libsolidity/CallGraph.h diff --git a/libsolidity/CallGraph.cpp b/libsolidity/CallGraph.cpp new file mode 100644 index 000000000..48666ca7f --- /dev/null +++ b/libsolidity/CallGraph.cpp @@ -0,0 +1,65 @@ + +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** + * @author Christian + * @date 2014 + * Callgraph of functions inside a contract. + */ + +#include +#include + +using namespace std; + +namespace dev { +namespace solidity { + +void CallGraph::addFunction(FunctionDefinition const& _function) +{ + if (!m_functionsSeen.count(&_function)) + { + m_functionsSeen.insert(&_function); + m_workQueue.push(&_function); + } +} + +set const& CallGraph::getCalls() +{ + return m_functionsSeen; +} + +void CallGraph::computeCallGraph() +{ + while (!m_workQueue.empty()) + { + FunctionDefinition const* fun = m_workQueue.front(); + fun->accept(*this); + m_workQueue.pop(); + } +} + +bool CallGraph::visit(Identifier const& _identifier) +{ + FunctionDefinition const* fun = dynamic_cast(_identifier.getReferencedDeclaration()); + if (fun) + addFunction(*fun); + return true; +} + +} +} diff --git a/libsolidity/CallGraph.h b/libsolidity/CallGraph.h new file mode 100644 index 000000000..986e4dc4a --- /dev/null +++ b/libsolidity/CallGraph.h @@ -0,0 +1,53 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** + * @author Christian + * @date 2014 + * Callgraph of functions inside a contract. + */ + +#include +#include +#include +#include + +namespace dev { +namespace solidity { + +/** + * Can be used to compute the graph of calls (or rather references) between functions of the same + * contract. Current functionality is limited to computing all functions that are directly + * or indirectly called by some functions. + */ +class CallGraph: private ASTConstVisitor +{ +public: + void addFunction(FunctionDefinition const& _function); + void computeCallGraph(); + + std::set const& getCalls(); + +private: + void addFunctionToQueue(FunctionDefinition const& _function); + virtual bool visit(Identifier const& _identifier) override; + + std::set m_functionsSeen; + std::queue m_workQueue; +}; + +} +} diff --git a/libsolidity/Compiler.cpp b/libsolidity/Compiler.cpp index f2877c1ce..0f85cda38 100644 --- a/libsolidity/Compiler.cpp +++ b/libsolidity/Compiler.cpp @@ -27,6 +27,7 @@ #include #include #include +#include using namespace std; @@ -37,68 +38,82 @@ void Compiler::compileContract(ContractDefinition const& _contract, vector const& _contracts) { m_context = CompilerContext(); // clear it just in case - m_context.setCompiledContracts(_contracts); - - for (MagicVariableDeclaration const* variable: _magicGlobals) - m_context.addMagicGlobal(*variable); + initializeContext(_contract, _magicGlobals, _contracts); for (ASTPointer const& function: _contract.getDefinedFunctions()) if (function->getName() != _contract.getName()) // don't add the constructor here m_context.addFunction(*function); - registerStateVariables(_contract); appendFunctionSelector(_contract); for (ASTPointer const& function: _contract.getDefinedFunctions()) if (function->getName() != _contract.getName()) // don't add the constructor here function->accept(*this); - packIntoContractCreator(_contract, _contracts); -} - -void Compiler::packIntoContractCreator(ContractDefinition const& _contract, - map const& _contracts) -{ + // Swap the runtime context with the creation-time context CompilerContext runtimeContext; - runtimeContext.setCompiledContracts(_contracts); swap(m_context, runtimeContext); + initializeContext(_contract, _magicGlobals, _contracts); + packIntoContractCreator(_contract, runtimeContext); +} +void Compiler::initializeContext(ContractDefinition const& _contract, vector const& _magicGlobals, + map const& _contracts) +{ + m_context.setCompiledContracts(_contracts); + for (MagicVariableDeclaration const* variable: _magicGlobals) + m_context.addMagicGlobal(*variable); registerStateVariables(_contract); +} - FunctionDefinition* constructor = nullptr; - for (ASTPointer const& function: _contract.getDefinedFunctions()) - if (function->getName() == _contract.getName()) - { - constructor = function.get(); - break; - } - eth::AssemblyItem sub = m_context.addSubroutine(runtimeContext.getAssembly()); - // stack contains sub size +void Compiler::packIntoContractCreator(ContractDefinition const& _contract, CompilerContext const& _runtimeContext) +{ + set neededFunctions; + FunctionDefinition const* constructor = _contract.getConstructor(); if (constructor) - { - eth::AssemblyItem returnTag = m_context.pushNewTag(); - m_context.addFunction(*constructor); // note that it cannot be called due to syntactic reasons - // copy constructor arguments from code to memory and then to stack, they are supplied after the actual program - unsigned argumentSize = 0; - for (ASTPointer const& var: constructor->getParameters()) - argumentSize += var->getType()->getCalldataEncodedSize(); - if (argumentSize > 0) - { - m_context << u256(argumentSize); - m_context.appendProgramSize(); - m_context << u256(1); // copy it to byte one as expected for ABI calls - m_context << eth::Instruction::CODECOPY; - appendCalldataUnpacker(*constructor, true); - } - //@todo calling other functions inside the constructor should either trigger a parse error - //or we should copy them here (register them above and call "accept") - detecting which - // functions are referenced / called needs to be done in a recursive way. - m_context.appendJumpTo(m_context.getFunctionEntryLabel(*constructor)); - constructor->accept(*this); - m_context << returnTag; - } + neededFunctions = getFunctionsNeededByConstructor(*constructor); + + for (FunctionDefinition const* fun: neededFunctions) + m_context.addFunction(*fun); + if (constructor) + appendConstructorCall(*constructor); + + eth::AssemblyItem sub = m_context.addSubroutine(_runtimeContext.getAssembly()); + // stack contains sub size m_context << eth::Instruction::DUP1 << sub << u256(0) << eth::Instruction::CODECOPY; m_context << u256(0) << eth::Instruction::RETURN; + + // note that we have to explicitly include all used functions because of absolute jump + // labels + for (FunctionDefinition const* fun: neededFunctions) + fun->accept(*this); +} + +void Compiler::appendConstructorCall(FunctionDefinition const& _constructor) +{ + eth::AssemblyItem returnTag = m_context.pushNewTag(); + // copy constructor arguments from code to memory and then to stack, they are supplied after the actual program + unsigned argumentSize = 0; + for (ASTPointer const& var: _constructor.getParameters()) + argumentSize += var->getType()->getCalldataEncodedSize(); + if (argumentSize > 0) + { + m_context << u256(argumentSize); + m_context.appendProgramSize(); + m_context << u256(1); // copy it to byte one as expected for ABI calls + m_context << eth::Instruction::CODECOPY; + appendCalldataUnpacker(_constructor, true); + } + m_context.appendJumpTo(m_context.getFunctionEntryLabel(_constructor)); + m_context << returnTag; +} + +set Compiler::getFunctionsNeededByConstructor(FunctionDefinition const& _constructor) +{ + CallGraph callgraph; + callgraph.addFunction(_constructor); + callgraph.computeCallGraph(); + return callgraph.getCalls(); } void Compiler::appendFunctionSelector(ContractDefinition const& _contract) diff --git a/libsolidity/Compiler.h b/libsolidity/Compiler.h index 57e40cdae..b30e85ae4 100644 --- a/libsolidity/Compiler.h +++ b/libsolidity/Compiler.h @@ -38,10 +38,16 @@ public: void streamAssembly(std::ostream& _stream) const { m_context.streamAssembly(_stream); } private: - /// Creates a new compiler context / assembly, packs the current code into the data part and + /// Registers the global objects and the non-function objects inside the contract with the context. + void initializeContext(ContractDefinition const& _contract, std::vector const& _magicGlobals, + std::map const& _contracts); + /// Adds the code that is run at creation time. Should be run after exchanging the run-time context + /// with a new and initialized context. /// adds the constructor code. - void packIntoContractCreator(ContractDefinition const& _contract, - std::map const& _contracts); + void packIntoContractCreator(ContractDefinition const& _contract, CompilerContext const& _runtimeContext); + void appendConstructorCall(FunctionDefinition const& _constructor); + /// Recursively searches the call graph and returns all functions needed by the constructor (including itself). + std::set getFunctionsNeededByConstructor(FunctionDefinition const& _constructor); void appendFunctionSelector(ContractDefinition const& _contract); /// Creates code that unpacks the arguments for the given function, from memory if /// @a _fromMemory is true, otherwise from call data. @returns the size of the data in bytes. diff --git a/test/solidityEndToEndTest.cpp b/test/solidityEndToEndTest.cpp index b6f63aa72..78926e94a 100644 --- a/test/solidityEndToEndTest.cpp +++ b/test/solidityEndToEndTest.cpp @@ -1038,6 +1038,23 @@ BOOST_AUTO_TEST_CASE(constructor_arguments) BOOST_REQUIRE(callContractFunction(1) == bytes({'a', 'b', 'c'})); } +BOOST_AUTO_TEST_CASE(functions_called_by_constructor) +{ + char const* sourceCode = R"( + contract Test { + string3 name; + bool flag; + function Test() { + setName("abc"); + } + function getName() returns (string3 ret) { return name; } + private: + function setName(string3 _name) { name = _name; } + })"; + compileAndRun(sourceCode); + BOOST_REQUIRE(callContractFunction(0) == bytes({'a', 'b', 'c'})); +} + BOOST_AUTO_TEST_SUITE_END() } From c99b38a4ed70e578065a59e0dd332474fac6e42d Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 16 Dec 2014 23:55:38 +0100 Subject: [PATCH 549/641] Using strings instead of #defined literals in solc --- solc/CommandLineInterface.cpp | 76 +++++++++++++++++------------------ 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 8aa182b5c..fd660a0ca 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -43,21 +43,21 @@ using namespace std; namespace po = boost::program_options; -// LTODO: Maybe some argument class pairing names with -// extensions and other attributes would be a better choice here? -#define ARG_ABI_STR "abi" -#define ARG_ASM_STR "asm" -#define ARG_AST_STR "ast" -#define ARG_BINARY_STR "binary" -#define ARG_OPCODES_STR "opcodes" -#define ARG_NATSPECDEV_STR "natspec-dev" -#define ARG_NATSPECUSER_STR "natspec-user" - namespace dev { namespace solidity { +// LTODO: Maybe some argument class pairing names with +// extensions and other attributes would be a better choice here? +static string const g_argAbiStr = "abi"; +static string const g_argAsmStr = "asm"; +static string const g_argAstStr = "ast"; +static string const g_argBinaryStr = "binary"; +static string const g_argOpcodesStr = "opcodes"; +static string const g_argNatspecDevStr = "natspec-dev"; +static string const g_argNatspecUserStr = "natspec-user"; + static void version() { cout << "solc, the solidity complier commandline interface " << dev::Version << endl @@ -66,16 +66,16 @@ static void version() exit(0); } -static inline bool argToStdout(po::variables_map const& _args, const char* _name) +static inline bool argToStdout(po::variables_map const& _args, string const& _name) { return _args.count(_name) && _args[_name].as() != OutputType::FILE; } static bool needStdout(po::variables_map const& _args) { - return argToStdout(_args, ARG_ABI_STR) || argToStdout(_args, ARG_NATSPECUSER_STR) || - argToStdout(_args, ARG_NATSPECDEV_STR) || argToStdout(_args, ARG_ASM_STR) || - argToStdout(_args, ARG_OPCODES_STR) || argToStdout(_args, ARG_BINARY_STR); + return argToStdout(_args, g_argAbiStr) || argToStdout(_args, g_argNatspecUserStr) || + argToStdout(_args, g_argNatspecDevStr) || argToStdout(_args, g_argAsmStr) || + argToStdout(_args, g_argOpcodesStr) || argToStdout(_args, g_argBinaryStr); } static inline bool outputToFile(OutputType type) @@ -105,7 +105,7 @@ static std::istream& operator>>(std::istream& _in, OutputType& io_output) void CommandLineInterface::handleBinary(string const& _contract) { - auto choice = m_args[ARG_BINARY_STR].as(); + auto choice = m_args[g_argBinaryStr].as(); if (outputToStdout(choice)) { cout << "Binary: " << endl; @@ -122,7 +122,7 @@ void CommandLineInterface::handleBinary(string const& _contract) void CommandLineInterface::handleOpcode(string const& _contract) { - auto choice = m_args[ARG_OPCODES_STR].as(); + auto choice = m_args[g_argOpcodesStr].as(); if (outputToStdout(choice)) { cout << "Opcodes: " << endl; @@ -140,9 +140,9 @@ void CommandLineInterface::handleOpcode(string const& _contract) void CommandLineInterface::handleBytecode(string const& _contract) { - if (m_args.count(ARG_OPCODES_STR)) + if (m_args.count(g_argOpcodesStr)) handleOpcode(_contract); - if (m_args.count(ARG_BINARY_STR)) + if (m_args.count(g_argBinaryStr)) handleBinary(_contract); } @@ -155,17 +155,17 @@ void CommandLineInterface::handleJson(DocumentationType _type, switch(_type) { case DocumentationType::ABI_INTERFACE: - argName = ARG_ABI_STR; + argName = g_argAbiStr; suffix = ".abi"; title = "Contract ABI"; break; case DocumentationType::NATSPEC_USER: - argName = "ARG_NATSPECUSER_STR"; + argName = "g_argNatspecUserStr"; suffix = ".docuser"; title = "User Documentation"; break; case DocumentationType::NATSPEC_DEV: - argName = ARG_NATSPECDEV_STR; + argName = g_argNatspecDevStr; suffix = ".docdev"; title = "Developer Documentation"; break; @@ -205,20 +205,20 @@ bool CommandLineInterface::parseArguments(int argc, char** argv) ("version", "Show version and exit") ("optimize", po::value()->default_value(false), "Optimize bytecode for size") ("input-file", po::value>(), "input file") - (ARG_AST_STR, po::value(), + (g_argAstStr.c_str(), po::value(), "Request to output the AST of the contract. " OUTPUT_TYPE_STR) - (ARG_ASM_STR, po::value(), - "Request to output the EVM assembly of the contract. " OUTPUT_TYPE_STR) - (ARG_OPCODES_STR, po::value(), - "Request to output the Opcodes of the contract. " OUTPUT_TYPE_STR) - (ARG_BINARY_STR, po::value(), - "Request to output the contract in binary (hexadecimal). " OUTPUT_TYPE_STR) - (ARG_ABI_STR, po::value(), - "Request to output the contract's ABI interface. " OUTPUT_TYPE_STR) - (ARG_NATSPECUSER_STR, po::value(), - "Request to output the contract's Natspec user documentation. " OUTPUT_TYPE_STR) - (ARG_NATSPECDEV_STR, po::value(), - "Request to output the contract's Natspec developer documentation. " OUTPUT_TYPE_STR); + (g_argAsmStr.c_str(), po::value(), + "Request to output the EVM assembly of the contract. " OUTPUT_TYPE_STR) + (g_argOpcodesStr.c_str(), po::value(), + "Request to output the Opcodes of the contract. " OUTPUT_TYPE_STR) + (g_argBinaryStr.c_str(), po::value(), + "Request to output the contract in binary (hexadecimal). " OUTPUT_TYPE_STR) + (g_argAbiStr.c_str(), po::value(), + "Request to output the contract's ABI interface. " OUTPUT_TYPE_STR) + (g_argNatspecUserStr.c_str(), po::value(), + "Request to output the contract's Natspec user documentation. " OUTPUT_TYPE_STR) + (g_argNatspecDevStr.c_str(), po::value(), + "Request to output the contract's Natspec developer documentation. " OUTPUT_TYPE_STR); #undef OUTPUT_TYPE_STR // All positional options should be interpreted as input files @@ -331,9 +331,9 @@ bool CommandLineInterface::processInput() void CommandLineInterface::actOnInput() { // do we need AST output? - if (m_args.count(ARG_AST_STR)) + if (m_args.count(g_argAstStr)) { - auto choice = m_args[ARG_AST_STR].as(); + auto choice = m_args[g_argAstStr].as(); if (outputToStdout(choice)) { cout << "Syntax trees:" << endl << endl; @@ -365,9 +365,9 @@ void CommandLineInterface::actOnInput() cout << endl << "======= " << contract << " =======" << endl; // do we need EVM assembly? - if (m_args.count(ARG_ASM_STR)) + if (m_args.count(g_argAsmStr)) { - auto choice = m_args[ARG_ASM_STR].as(); + auto choice = m_args[g_argAsmStr].as(); if (outputToStdout(choice)) { cout << "EVM assembly:" << endl; From 30c000d121dc0132a6c5abb9d6e3da96b4dfda4a Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 15 Dec 2014 17:45:18 +0100 Subject: [PATCH 550/641] Adding a ForStatement solidity AST Node. - Adding ForStatement node - Implemented Parsing for ForStatement - A simple parsing test for the ForStatement - Work in progress --- libsolidity/AST.cpp | 7 +++++ libsolidity/AST.h | 24 +++++++++++++++++ libsolidity/ASTForward.h | 1 + libsolidity/ASTPrinter.cpp | 12 +++++++++ libsolidity/ASTPrinter.h | 2 ++ libsolidity/ASTVisitor.h | 4 +++ libsolidity/AST_accept.h | 24 +++++++++++++++++ libsolidity/Compiler.cpp | 7 +++++ libsolidity/Compiler.h | 1 + libsolidity/Parser.cpp | 54 +++++++++++++++++++++++++++++++------- libsolidity/Parser.h | 6 +++++ libsolidity/grammar.txt | 1 + test/solidityParser.cpp | 28 ++++++++++++++++++++ 13 files changed, 162 insertions(+), 9 deletions(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 5e344eadb..c286c412b 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -130,6 +130,13 @@ void WhileStatement::checkTypeRequirements() m_body->checkTypeRequirements(); } +void ForStatement::checkTypeRequirements() +{ + // LTODO + m_condExpression->expectType(BoolType()); + m_body->checkTypeRequirements(); +} + void Return::checkTypeRequirements() { if (!m_expression) diff --git a/libsolidity/AST.h b/libsolidity/AST.h index 4bb623b49..297b7f4e9 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -509,6 +509,30 @@ private: ASTPointer m_body; }; +class ForStatement: public BreakableStatement +{ +public: + ForStatement(Location const& _location, + ASTPointer const& _initExpression, + ASTPointer const& _conditionExpression, + ASTPointer const& _loopExpression, + ASTPointer const& _body): + BreakableStatement(_location), + m_initExpression(_initExpression), + m_condExpression(_conditionExpression), + m_loopExpression(_loopExpression), + m_body(_body) {} + virtual void accept(ASTVisitor& _visitor) override; + virtual void accept(ASTConstVisitor& _visitor) const override; + virtual void checkTypeRequirements() override; + +private: + ASTPointer m_initExpression; + ASTPointer m_condExpression; + ASTPointer m_loopExpression; + ASTPointer m_body; +}; + class Continue: public Statement { public: diff --git a/libsolidity/ASTForward.h b/libsolidity/ASTForward.h index d6c4c9f44..c960fc8f0 100644 --- a/libsolidity/ASTForward.h +++ b/libsolidity/ASTForward.h @@ -52,6 +52,7 @@ class Block; class IfStatement; class BreakableStatement; class WhileStatement; +class ForStatement; class Continue; class Break; class Return; diff --git a/libsolidity/ASTPrinter.cpp b/libsolidity/ASTPrinter.cpp index 970822a9a..916fca1ef 100644 --- a/libsolidity/ASTPrinter.cpp +++ b/libsolidity/ASTPrinter.cpp @@ -150,6 +150,13 @@ bool ASTPrinter::visit(WhileStatement const& _node) return goDeeper(); } +bool ASTPrinter::visit(ForStatement const& _node) +{ + writeLine("ForStatement"); + printSourcePart(_node); + return goDeeper(); +} + bool ASTPrinter::visit(Continue const& _node) { writeLine("Continue"); @@ -360,6 +367,11 @@ void ASTPrinter::endVisit(WhileStatement const&) m_indentation--; } +void ASTPrinter::endVisit(ForStatement const&) +{ + m_indentation--; +} + void ASTPrinter::endVisit(Continue const&) { m_indentation--; diff --git a/libsolidity/ASTPrinter.h b/libsolidity/ASTPrinter.h index 15b65e3f0..fc5fb4acb 100644 --- a/libsolidity/ASTPrinter.h +++ b/libsolidity/ASTPrinter.h @@ -57,6 +57,7 @@ public: bool visit(IfStatement const& _node) override; bool visit(BreakableStatement const& _node) override; bool visit(WhileStatement const& _node) override; + bool visit(ForStatement const& _node) override; bool visit(Continue const& _node) override; bool visit(Break const& _node) override; bool visit(Return const& _node) override; @@ -90,6 +91,7 @@ public: void endVisit(IfStatement const&) override; void endVisit(BreakableStatement const&) override; void endVisit(WhileStatement const&) override; + void endVisit(ForStatement const&) override; void endVisit(Continue const&) override; void endVisit(Break const&) override; void endVisit(Return const&) override; diff --git a/libsolidity/ASTVisitor.h b/libsolidity/ASTVisitor.h index 5728cd3d0..33a8a3383 100644 --- a/libsolidity/ASTVisitor.h +++ b/libsolidity/ASTVisitor.h @@ -58,6 +58,7 @@ public: virtual bool visit(IfStatement&) { return true; } virtual bool visit(BreakableStatement&) { return true; } virtual bool visit(WhileStatement&) { return true; } + virtual bool visit(ForStatement&) { return true; } virtual bool visit(Continue&) { return true; } virtual bool visit(Break&) { return true; } virtual bool visit(Return&) { return true; } @@ -93,6 +94,7 @@ public: virtual void endVisit(IfStatement&) { } virtual void endVisit(BreakableStatement&) { } virtual void endVisit(WhileStatement&) { } + virtual void endVisit(ForStatement&) { } virtual void endVisit(Continue&) { } virtual void endVisit(Break&) { } virtual void endVisit(Return&) { } @@ -132,6 +134,7 @@ public: virtual bool visit(IfStatement const&) { return true; } virtual bool visit(BreakableStatement const&) { return true; } virtual bool visit(WhileStatement const&) { return true; } + virtual bool visit(ForStatement const&) { return true; } virtual bool visit(Continue const&) { return true; } virtual bool visit(Break const&) { return true; } virtual bool visit(Return const&) { return true; } @@ -167,6 +170,7 @@ public: virtual void endVisit(IfStatement const&) { } virtual void endVisit(BreakableStatement const&) { } virtual void endVisit(WhileStatement const&) { } + virtual void endVisit(ForStatement const&) { } virtual void endVisit(Continue const&) { } virtual void endVisit(Break const&) { } virtual void endVisit(Return const&) { } diff --git a/libsolidity/AST_accept.h b/libsolidity/AST_accept.h index e0454d33e..ffef6f8b2 100644 --- a/libsolidity/AST_accept.h +++ b/libsolidity/AST_accept.h @@ -267,6 +267,30 @@ void WhileStatement::accept(ASTConstVisitor& _visitor) const _visitor.endVisit(*this); } +void ForStatement::accept(ASTVisitor& _visitor) +{ + if (_visitor.visit(*this)) + { + m_initExpression->accept(_visitor); + m_condExpression->accept(_visitor); + m_loopExpression->accept(_visitor); + m_body->accept(_visitor); + } + _visitor.endVisit(*this); +} + +void ForStatement::accept(ASTConstVisitor& _visitor) const +{ + if (_visitor.visit(*this)) + { + m_initExpression->accept(_visitor); + m_condExpression->accept(_visitor); + m_loopExpression->accept(_visitor); + m_body->accept(_visitor); + } + _visitor.endVisit(*this); +} + void Continue::accept(ASTVisitor& _visitor) { _visitor.visit(*this); diff --git a/libsolidity/Compiler.cpp b/libsolidity/Compiler.cpp index f2877c1ce..a0cad5374 100644 --- a/libsolidity/Compiler.cpp +++ b/libsolidity/Compiler.cpp @@ -287,6 +287,13 @@ bool Compiler::visit(WhileStatement const& _whileStatement) return false; } +bool Compiler::visit(ForStatement const& _forStatement) +{ + // LTODO + (void) _forStatement; + return false; +} + bool Compiler::visit(Continue const&) { if (!m_continueTags.empty()) diff --git a/libsolidity/Compiler.h b/libsolidity/Compiler.h index 57e40cdae..c4f46d10f 100644 --- a/libsolidity/Compiler.h +++ b/libsolidity/Compiler.h @@ -53,6 +53,7 @@ private: virtual bool visit(FunctionDefinition const& _function) override; virtual bool visit(IfStatement const& _ifStatement) override; virtual bool visit(WhileStatement const& _whileStatement) override; + virtual bool visit(ForStatement const& _forStatement) override; virtual bool visit(Continue const& _continue) override; virtual bool visit(Break const& _break) override; virtual bool visit(Return const& _return) override; diff --git a/libsolidity/Parser.cpp b/libsolidity/Parser.cpp index 21651eb14..9941fbf43 100644 --- a/libsolidity/Parser.cpp +++ b/libsolidity/Parser.cpp @@ -304,6 +304,8 @@ ASTPointer Parser::parseStatement() return parseIfStatement(); case Token::WHILE: return parseWhileStatement(); + case Token::FOR: + return parseForStatement(); case Token::LBRACE: return parseBlock(); // starting from here, all statements must be terminated by a semicolon @@ -328,15 +330,7 @@ ASTPointer Parser::parseStatement() } break; default: - // distinguish between variable definition (and potentially assignment) and expression statement - // (which include assignments to other expressions and pre-declared variables) - // We have a variable definition if we get a keyword that specifies a type name, or - // in the case of a user-defined type, we have two identifiers following each other. - if (m_scanner->getCurrentToken() == Token::MAPPING || - m_scanner->getCurrentToken() == Token::VAR || - ((Token::isElementaryTypeName(m_scanner->getCurrentToken()) || - m_scanner->getCurrentToken() == Token::IDENTIFIER) && - m_scanner->peekNextToken() == Token::IDENTIFIER)) + if (peekVariableDefinition()) statement = parseVariableDefinition(); else // "ordinary" expression statement statement = parseExpressionStatement(); @@ -377,6 +371,34 @@ ASTPointer Parser::parseWhileStatement() return nodeFactory.createNode(condition, body); } +ASTPointer Parser::parseForStatement() +{ + ASTNodeFactory nodeFactory(*this); + expectToken(Token::FOR); + expectToken(Token::LPAREN); + ASTPointer initExpression = parseVardefOrExprstatement(); + expectToken(Token::SEMICOLON); + ASTPointer conditionExpression = parseExpression(); + expectToken(Token::SEMICOLON); + ASTPointer loopExpression = parseExpressionStatement(); + expectToken(Token::SEMICOLON); + expectToken(Token::RPAREN); + ASTPointer body = parseStatement(); + nodeFactory.setEndPositionFromNode(body); + return nodeFactory.createNode(initExpression, + conditionExpression, + loopExpression, + body); +} + +ASTPointer Parser::parseVardefOrExprstatement() +{ + if (peekVariableDefinition()) + return parseVariableDefinition(); + else + return parseExpressionStatement(); +} + ASTPointer Parser::parseVariableDefinition() { ASTNodeFactory nodeFactory(*this); @@ -566,6 +588,20 @@ vector> Parser::parseFunctionCallArguments() return arguments; } + +// distinguish between variable definition (and potentially assignment) and expression statement +// (which include assignments to other expressions and pre-declared variables) +// We have a variable definition if we get a keyword that specifies a type name, or +// in the case of a user-defined type, we have two identifiers following each other. +bool Parser::peekVariableDefinition() +{ + return (m_scanner->getCurrentToken() == Token::MAPPING || + m_scanner->getCurrentToken() == Token::VAR || + ((Token::isElementaryTypeName(m_scanner->getCurrentToken()) || + m_scanner->getCurrentToken() == Token::IDENTIFIER) && + m_scanner->peekNextToken() == Token::IDENTIFIER)); +} + void Parser::expectToken(Token::Value _value) { if (m_scanner->getCurrentToken() != _value) diff --git a/libsolidity/Parser.h b/libsolidity/Parser.h index 52a374e03..343a85c0e 100644 --- a/libsolidity/Parser.h +++ b/libsolidity/Parser.h @@ -59,6 +59,8 @@ private: ASTPointer parseStatement(); ASTPointer parseIfStatement(); ASTPointer parseWhileStatement(); + ASTPointer parseForStatement(); + ASTPointer parseVardefOrExprstatement(); ASTPointer parseVariableDefinition(); ASTPointer parseExpressionStatement(); ASTPointer parseExpression(); @@ -72,6 +74,10 @@ private: ///@{ ///@name Helper functions + /// Peeks ahead in the scanner to determine if an expression statement + /// could be a variable definition + bool peekVariableDefinition(); + /// If current token value is not _value, throw exception otherwise advance token. void expectToken(Token::Value _value); Token::Value expectAssignmentOperator(); diff --git a/libsolidity/grammar.txt b/libsolidity/grammar.txt index a26f717a1..99a590014 100644 --- a/libsolidity/grammar.txt +++ b/libsolidity/grammar.txt @@ -20,6 +20,7 @@ Statement = IfStatement | WhileStatement | Block | IfStatement = 'if' '(' Expression ')' Statement ( 'else' Statement )? WhileStatement = 'while' '(' Expression ')' Statement +ForStatement = 'for' '(' Expressionstatement Expression Expressionstatement ')' Statement Continue = 'continue' ';' Break = 'break' ';' Return = 'return' Expression? ';' diff --git a/test/solidityParser.cpp b/test/solidityParser.cpp index a9e2d531f..8268901be 100644 --- a/test/solidityParser.cpp +++ b/test/solidityParser.cpp @@ -49,6 +49,23 @@ ASTPointer parseText(std::string const& _source) BOOST_FAIL("No contract found in source."); return ASTPointer(); } + +ASTPointer parseTextExplainError(std::string const& _source) +{ + try + { + return parseText(_source); + } + catch (Exception const& exception) + { + // LTODO: Print the error in a kind of a better way? + // In absence of CompilerStack we can't use SourceReferenceFormatter + cout << "Exception while parsing: " << diagnostic_information(exception); + // rethrow to signal test failure + throw exception; + } +} + } @@ -357,6 +374,17 @@ BOOST_AUTO_TEST_CASE(while_loop) BOOST_CHECK_NO_THROW(parseText(text)); } +BOOST_AUTO_TEST_CASE(for_loop) +{ + char const* text = "contract test {\n" + " function fun(uint256 a) {\n" + " for (uint256 i = 0; i < 10; i++;)\n" + " { uint256 x = i; break; continue; }\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseTextExplainError(text)); +} + BOOST_AUTO_TEST_CASE(if_statement) { char const* text = "contract test {\n" From e934aa0befb759ae3fafb545dd9398833a49bbe7 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 15 Dec 2014 17:54:29 +0100 Subject: [PATCH 551/641] new ForStatement parsing test and small grammar fix --- libsolidity/Parser.cpp | 1 - libsolidity/grammar.txt | 2 +- test/solidityParser.cpp | 16 ++++++++++++++-- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/libsolidity/Parser.cpp b/libsolidity/Parser.cpp index 9941fbf43..d936cfc72 100644 --- a/libsolidity/Parser.cpp +++ b/libsolidity/Parser.cpp @@ -381,7 +381,6 @@ ASTPointer Parser::parseForStatement() ASTPointer conditionExpression = parseExpression(); expectToken(Token::SEMICOLON); ASTPointer loopExpression = parseExpressionStatement(); - expectToken(Token::SEMICOLON); expectToken(Token::RPAREN); ASTPointer body = parseStatement(); nodeFactory.setEndPositionFromNode(body); diff --git a/libsolidity/grammar.txt b/libsolidity/grammar.txt index 99a590014..76e7bb6b6 100644 --- a/libsolidity/grammar.txt +++ b/libsolidity/grammar.txt @@ -20,7 +20,7 @@ Statement = IfStatement | WhileStatement | Block | IfStatement = 'if' '(' Expression ')' Statement ( 'else' Statement )? WhileStatement = 'while' '(' Expression ')' Statement -ForStatement = 'for' '(' Expressionstatement Expression Expressionstatement ')' Statement +ForStatement = 'for' '(' VardefOrExpressionstatement ';' Expression ';' Expressionstatement ')' Statement Continue = 'continue' ';' Break = 'break' ';' Return = 'return' Expression? ';' diff --git a/test/solidityParser.cpp b/test/solidityParser.cpp index 8268901be..53bd3f163 100644 --- a/test/solidityParser.cpp +++ b/test/solidityParser.cpp @@ -374,11 +374,23 @@ BOOST_AUTO_TEST_CASE(while_loop) BOOST_CHECK_NO_THROW(parseText(text)); } -BOOST_AUTO_TEST_CASE(for_loop) +BOOST_AUTO_TEST_CASE(for_loop_vardef_initexpr) { char const* text = "contract test {\n" " function fun(uint256 a) {\n" - " for (uint256 i = 0; i < 10; i++;)\n" + " for (uint256 i = 0; i < 10; i++)\n" + " { uint256 x = i; break; continue; }\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseTextExplainError(text)); +} + +BOOST_AUTO_TEST_CASE(for_loop_simple_initexpr) +{ + char const* text = "contract test {\n" + " function fun(uint256 a) {\n" + " uint256 i =0;\n" + " for (i = 0; i < 10; i++)\n" " { uint256 x = i; break; continue; }\n" " }\n" "}\n"; From b2992bd659768b0ee8f33ea24bf4e308efea3891 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 16 Dec 2014 09:51:51 +0100 Subject: [PATCH 552/641] Solidity ForStatements expressions are now optional --- libsolidity/AST_accept.h | 18 ++++++++++++------ libsolidity/Parser.cpp | 17 ++++++++++++++--- libsolidity/grammar.txt | 2 +- test/solidityParser.cpp | 12 ++++++++++++ 4 files changed, 39 insertions(+), 10 deletions(-) diff --git a/libsolidity/AST_accept.h b/libsolidity/AST_accept.h index ffef6f8b2..0e5a71b62 100644 --- a/libsolidity/AST_accept.h +++ b/libsolidity/AST_accept.h @@ -271,9 +271,12 @@ void ForStatement::accept(ASTVisitor& _visitor) { if (_visitor.visit(*this)) { - m_initExpression->accept(_visitor); - m_condExpression->accept(_visitor); - m_loopExpression->accept(_visitor); + if (m_initExpression) + m_initExpression->accept(_visitor); + if (m_condExpression) + m_condExpression->accept(_visitor); + if (m_loopExpression) + m_loopExpression->accept(_visitor); m_body->accept(_visitor); } _visitor.endVisit(*this); @@ -283,9 +286,12 @@ void ForStatement::accept(ASTConstVisitor& _visitor) const { if (_visitor.visit(*this)) { - m_initExpression->accept(_visitor); - m_condExpression->accept(_visitor); - m_loopExpression->accept(_visitor); + if (m_initExpression) + m_initExpression->accept(_visitor); + if (m_condExpression) + m_condExpression->accept(_visitor); + if (m_loopExpression) + m_loopExpression->accept(_visitor); m_body->accept(_visitor); } _visitor.endVisit(*this); diff --git a/libsolidity/Parser.cpp b/libsolidity/Parser.cpp index d936cfc72..598f5ad47 100644 --- a/libsolidity/Parser.cpp +++ b/libsolidity/Parser.cpp @@ -374,14 +374,25 @@ ASTPointer Parser::parseWhileStatement() ASTPointer Parser::parseForStatement() { ASTNodeFactory nodeFactory(*this); + ASTPointer initExpression; + ASTPointer conditionExpression; + ASTPointer loopExpression; expectToken(Token::FOR); expectToken(Token::LPAREN); - ASTPointer initExpression = parseVardefOrExprstatement(); + + // LTODO: Maybe here have some predicate like peekExpression() instead of checking for semicolon and RPAREN? + if (m_scanner->getCurrentToken() != Token::SEMICOLON) + initExpression = parseVardefOrExprstatement(); expectToken(Token::SEMICOLON); - ASTPointer conditionExpression = parseExpression(); + + if (m_scanner->getCurrentToken() != Token::SEMICOLON) + conditionExpression = parseExpression(); expectToken(Token::SEMICOLON); - ASTPointer loopExpression = parseExpressionStatement(); + + if (m_scanner->getCurrentToken() != Token::RPAREN) + loopExpression = parseExpressionStatement(); expectToken(Token::RPAREN); + ASTPointer body = parseStatement(); nodeFactory.setEndPositionFromNode(body); return nodeFactory.createNode(initExpression, diff --git a/libsolidity/grammar.txt b/libsolidity/grammar.txt index 76e7bb6b6..7c0ac3a50 100644 --- a/libsolidity/grammar.txt +++ b/libsolidity/grammar.txt @@ -20,7 +20,7 @@ Statement = IfStatement | WhileStatement | Block | IfStatement = 'if' '(' Expression ')' Statement ( 'else' Statement )? WhileStatement = 'while' '(' Expression ')' Statement -ForStatement = 'for' '(' VardefOrExpressionstatement ';' Expression ';' Expressionstatement ')' Statement +ForStatement = 'for' '(' (VardefOrExpressionstatement)? ';' (Expression)? ';' (Expressionstatement)? ')' Statement Continue = 'continue' ';' Break = 'break' ';' Return = 'return' Expression? ';' diff --git a/test/solidityParser.cpp b/test/solidityParser.cpp index 53bd3f163..d57754b61 100644 --- a/test/solidityParser.cpp +++ b/test/solidityParser.cpp @@ -397,6 +397,18 @@ BOOST_AUTO_TEST_CASE(for_loop_simple_initexpr) BOOST_CHECK_NO_THROW(parseTextExplainError(text)); } +BOOST_AUTO_TEST_CASE(for_loop_simple_noexpr) +{ + char const* text = "contract test {\n" + " function fun(uint256 a) {\n" + " uint256 i =0;\n" + " for (;;)\n" + " { uint256 x = i; break; continue; }\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseTextExplainError(text)); +} + BOOST_AUTO_TEST_CASE(if_statement) { char const* text = "contract test {\n" From 5eec2c5ac6d5a7f543a9eb33bdb3365653146fa1 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 16 Dec 2014 13:20:50 +0100 Subject: [PATCH 553/641] ForStatement typecheck and initExpression is a Statement --- libsolidity/AST.cpp | 8 ++++++-- libsolidity/AST.h | 4 ++-- libsolidity/Parser.cpp | 4 ++-- libsolidity/Parser.h | 2 +- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index c286c412b..4c042f2cf 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -132,8 +132,12 @@ void WhileStatement::checkTypeRequirements() void ForStatement::checkTypeRequirements() { - // LTODO - m_condExpression->expectType(BoolType()); + if (m_initExpression) + m_initExpression->checkTypeRequirements(); + if (m_condExpression) + m_condExpression->expectType(BoolType()); + if (m_loopExpression) + m_loopExpression->checkTypeRequirements(); m_body->checkTypeRequirements(); } diff --git a/libsolidity/AST.h b/libsolidity/AST.h index 297b7f4e9..2fb6a2e32 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -513,7 +513,7 @@ class ForStatement: public BreakableStatement { public: ForStatement(Location const& _location, - ASTPointer const& _initExpression, + ASTPointer const& _initExpression, ASTPointer const& _conditionExpression, ASTPointer const& _loopExpression, ASTPointer const& _body): @@ -527,7 +527,7 @@ public: virtual void checkTypeRequirements() override; private: - ASTPointer m_initExpression; + ASTPointer m_initExpression; ASTPointer m_condExpression; ASTPointer m_loopExpression; ASTPointer m_body; diff --git a/libsolidity/Parser.cpp b/libsolidity/Parser.cpp index 598f5ad47..2669ce209 100644 --- a/libsolidity/Parser.cpp +++ b/libsolidity/Parser.cpp @@ -374,7 +374,7 @@ ASTPointer Parser::parseWhileStatement() ASTPointer Parser::parseForStatement() { ASTNodeFactory nodeFactory(*this); - ASTPointer initExpression; + ASTPointer initExpression; ASTPointer conditionExpression; ASTPointer loopExpression; expectToken(Token::FOR); @@ -401,7 +401,7 @@ ASTPointer Parser::parseForStatement() body); } -ASTPointer Parser::parseVardefOrExprstatement() +ASTPointer Parser::parseVardefOrExprstatement() { if (peekVariableDefinition()) return parseVariableDefinition(); diff --git a/libsolidity/Parser.h b/libsolidity/Parser.h index 343a85c0e..cd3d5bab6 100644 --- a/libsolidity/Parser.h +++ b/libsolidity/Parser.h @@ -60,7 +60,7 @@ private: ASTPointer parseIfStatement(); ASTPointer parseWhileStatement(); ASTPointer parseForStatement(); - ASTPointer parseVardefOrExprstatement(); + ASTPointer parseVardefOrExprstatement(); ASTPointer parseVariableDefinition(); ASTPointer parseExpressionStatement(); ASTPointer parseExpression(); From 1f0346396ae307aa87e184f3ac8f0d7f9a97c832 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 16 Dec 2014 14:46:17 +0100 Subject: [PATCH 554/641] Minor issues, grammar update, new ForStatement test --- libsolidity/AST.h | 7 +++++++ libsolidity/Parser.cpp | 9 +++------ libsolidity/Parser.h | 5 ++--- libsolidity/grammar.txt | 6 ++++-- test/solidityParser.cpp | 12 ++++++++++++ 5 files changed, 28 insertions(+), 11 deletions(-) diff --git a/libsolidity/AST.h b/libsolidity/AST.h index 2fb6a2e32..dcbca1ee8 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -509,6 +509,9 @@ private: ASTPointer m_body; }; +/** + * For loop statement + */ class ForStatement: public BreakableStatement { public: @@ -527,9 +530,13 @@ public: virtual void checkTypeRequirements() override; private: + /// For statement's initialization expresion. for(XXX; ; ). Can be empty ASTPointer m_initExpression; + /// For statement's condition expresion. for(; XXX ; ). Can be empty ASTPointer m_condExpression; + /// For statement's loop expresion. for(;;XXX). Can be empty ASTPointer m_loopExpression; + /// The body of the loop ASTPointer m_body; }; diff --git a/libsolidity/Parser.cpp b/libsolidity/Parser.cpp index 2669ce209..732356751 100644 --- a/libsolidity/Parser.cpp +++ b/libsolidity/Parser.cpp @@ -330,10 +330,7 @@ ASTPointer Parser::parseStatement() } break; default: - if (peekVariableDefinition()) - statement = parseVariableDefinition(); - else // "ordinary" expression statement - statement = parseExpressionStatement(); + statement = parseVarDefOrExprStmt(); } expectToken(Token::SEMICOLON); return statement; @@ -382,7 +379,7 @@ ASTPointer Parser::parseForStatement() // LTODO: Maybe here have some predicate like peekExpression() instead of checking for semicolon and RPAREN? if (m_scanner->getCurrentToken() != Token::SEMICOLON) - initExpression = parseVardefOrExprstatement(); + initExpression = parseVarDefOrExprStmt(); expectToken(Token::SEMICOLON); if (m_scanner->getCurrentToken() != Token::SEMICOLON) @@ -401,7 +398,7 @@ ASTPointer Parser::parseForStatement() body); } -ASTPointer Parser::parseVardefOrExprstatement() +ASTPointer Parser::parseVarDefOrExprStmt() { if (peekVariableDefinition()) return parseVariableDefinition(); diff --git a/libsolidity/Parser.h b/libsolidity/Parser.h index cd3d5bab6..bf3a6beac 100644 --- a/libsolidity/Parser.h +++ b/libsolidity/Parser.h @@ -60,7 +60,7 @@ private: ASTPointer parseIfStatement(); ASTPointer parseWhileStatement(); ASTPointer parseForStatement(); - ASTPointer parseVardefOrExprstatement(); + ASTPointer parseVarDefOrExprStmt(); ASTPointer parseVariableDefinition(); ASTPointer parseExpressionStatement(); ASTPointer parseExpression(); @@ -74,8 +74,7 @@ private: ///@{ ///@name Helper functions - /// Peeks ahead in the scanner to determine if an expression statement - /// could be a variable definition + /// Peeks ahead in the scanner to determine if a variable definition is going to follow bool peekVariableDefinition(); /// If current token value is not _value, throw exception otherwise advance token. diff --git a/libsolidity/grammar.txt b/libsolidity/grammar.txt index 7c0ac3a50..8c34997b9 100644 --- a/libsolidity/grammar.txt +++ b/libsolidity/grammar.txt @@ -16,11 +16,13 @@ Mapping = 'mapping' '(' ElementaryTypeName '=>' TypeName ')' Block = '{' Statement* '}' Statement = IfStatement | WhileStatement | Block | - ( Continue | Break | Return | VariableDefinition | Expression ) ';' + ( Continue | Break | Return | VariableDefinition | ExpressionStatement ) ';' +ExpressionStatement = Expression IfStatement = 'if' '(' Expression ')' Statement ( 'else' Statement )? WhileStatement = 'while' '(' Expression ')' Statement -ForStatement = 'for' '(' (VardefOrExpressionstatement)? ';' (Expression)? ';' (Expressionstatement)? ')' Statement +VardefOrExprStmt = Variabledefinition | ExpressionStatement +ForStatement = 'for' '(' (VardefOrExprStmt)? ';' (Expression)? ';' (ExpressionStatement)? ')' Statement Continue = 'continue' ';' Break = 'break' ';' Return = 'return' Expression? ';' diff --git a/test/solidityParser.cpp b/test/solidityParser.cpp index d57754b61..f978cdd9b 100644 --- a/test/solidityParser.cpp +++ b/test/solidityParser.cpp @@ -409,6 +409,18 @@ BOOST_AUTO_TEST_CASE(for_loop_simple_noexpr) BOOST_CHECK_NO_THROW(parseTextExplainError(text)); } +BOOST_AUTO_TEST_CASE(for_loop_single_stmt_body) +{ + char const* text = "contract test {\n" + " function fun(uint256 a) {\n" + " uint256 i =0;\n" + " for (i = 0; i < 10; i++)\n" + " continue;\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseTextExplainError(text)); +} + BOOST_AUTO_TEST_CASE(if_statement) { char const* text = "contract test {\n" From 3c6e966160d828882d243ee37b52b23992891404 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 16 Dec 2014 16:52:47 +0100 Subject: [PATCH 555/641] Solidity ForStatement Compiler part - Work in progress --- libsolidity/AST.h | 5 +++++ libsolidity/Compiler.cpp | 31 +++++++++++++++++++++++++++++-- test/solidityEndToEndTest.cpp | 22 ++++++++++++++++++++++ 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/libsolidity/AST.h b/libsolidity/AST.h index dcbca1ee8..c83690443 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -529,6 +529,11 @@ public: virtual void accept(ASTConstVisitor& _visitor) const override; virtual void checkTypeRequirements() override; + Statement const* getInitializationExpression() const { return m_initExpression.get(); } + Expression const* getCondition() const { return m_condExpression.get(); } + ExpressionStatement const* getLoopExpression() const { return m_loopExpression.get(); } + Statement const& getBody() const { return *m_body; } + private: /// For statement's initialization expresion. for(XXX; ; ). Can be empty ASTPointer m_initExpression; diff --git a/libsolidity/Compiler.cpp b/libsolidity/Compiler.cpp index a0cad5374..8c70b2718 100644 --- a/libsolidity/Compiler.cpp +++ b/libsolidity/Compiler.cpp @@ -289,8 +289,35 @@ bool Compiler::visit(WhileStatement const& _whileStatement) bool Compiler::visit(ForStatement const& _forStatement) { - // LTODO - (void) _forStatement; + eth::AssemblyItem loopStart = m_context.newTag(); + eth::AssemblyItem loopEnd = m_context.newTag(); + m_continueTags.push_back(loopStart); + m_breakTags.push_back(loopEnd); + + if (_forStatement.getInitializationExpression()) + _forStatement.getInitializationExpression()->accept(*this); + + m_context << loopStart; + + // if there is no terminating condition in for, default is to always be true + if (_forStatement.getCondition()) + { + compileExpression(*_forStatement.getCondition()); + m_context << eth::Instruction::ISZERO; + m_context.appendConditionalJumpTo(loopEnd); + } + + _forStatement.getBody().accept(*this); + + // for's loop expression if existing + if (_forStatement.getLoopExpression()) + _forStatement.getLoopExpression()->accept(*this); + + m_context.appendJumpTo(loopStart); + m_context << loopEnd; + + m_continueTags.pop_back(); + m_breakTags.pop_back(); return false; } diff --git a/test/solidityEndToEndTest.cpp b/test/solidityEndToEndTest.cpp index b6f63aa72..32de9af46 100644 --- a/test/solidityEndToEndTest.cpp +++ b/test/solidityEndToEndTest.cpp @@ -176,6 +176,28 @@ BOOST_AUTO_TEST_CASE(nested_loops) testSolidityAgainstCppOnRange(0, nested_loops_cpp, 0, 12); } +BOOST_AUTO_TEST_CASE(for_loop) +{ + char const* sourceCode = "contract test {\n" + " function f(uint n) returns(uint nfac) {\n" + " nfac = 1;\n" + " for (var i = 2; i <= n; i++)\n" + " nfac *= 1;\n" + " }\n" + "}\n"; + compileAndRun(sourceCode); + + auto for_loop_cpp = [](u256 const& n) -> u256 + { + u256 nfac = 1; + for (auto i = 2; i <= n; i++) + nfac *= i; + return nfac; + }; + + testSolidityAgainstCppOnRange(0, for_loop_cpp, 0, 5); +} + BOOST_AUTO_TEST_CASE(calling_other_functions) { // note that the index of a function is its index in the sorted sequence of functions From 82117dc7dab431b2de6cfb73a6b17343ff71b57b Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 16 Dec 2014 17:35:00 +0100 Subject: [PATCH 556/641] Solidity: More tests for the ForStatement --- test/solidityEndToEndTest.cpp | 54 ++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/test/solidityEndToEndTest.cpp b/test/solidityEndToEndTest.cpp index 32de9af46..ecd3b63a3 100644 --- a/test/solidityEndToEndTest.cpp +++ b/test/solidityEndToEndTest.cpp @@ -182,7 +182,7 @@ BOOST_AUTO_TEST_CASE(for_loop) " function f(uint n) returns(uint nfac) {\n" " nfac = 1;\n" " for (var i = 2; i <= n; i++)\n" - " nfac *= 1;\n" + " nfac *= i;\n" " }\n" "}\n"; compileAndRun(sourceCode); @@ -198,6 +198,58 @@ BOOST_AUTO_TEST_CASE(for_loop) testSolidityAgainstCppOnRange(0, for_loop_cpp, 0, 5); } +BOOST_AUTO_TEST_CASE(for_loop_empty) +{ + char const* sourceCode = "contract test {\n" + " function f() returns(uint ret) {\n" + " ret = 1;\n" + " for (;;)\n" + " {\n" + " ret += 1;\n" + " if (ret >= 10) break;\n" + " }\n" + " }\n" + "}\n"; + compileAndRun(sourceCode); + + auto for_loop_empty_cpp = []() -> u256 + { + u256 ret = 1; + for (;;) + { + ret += 1; + if (ret >= 10) break; + } + return ret; + }; + + testSolidityAgainstCpp(0, for_loop_empty_cpp); +} + +BOOST_AUTO_TEST_CASE(for_loop_simple_init_expr) +{ + char const* sourceCode = "contract test {\n" + " function f(uint n) returns(uint nfac) {\n" + " nfac = 1;\n" + " uint256 i;\n" + " for (i = 2; i <= n; i++)\n" + " nfac *= i;\n" + " }\n" + "}\n"; + compileAndRun(sourceCode); + + auto for_loop_simple_init_expr_cpp = [](u256 const& n) -> u256 + { + u256 nfac = 1; + u256 i; + for (i = 2; i <= n; i++) + nfac *= i; + return nfac; + }; + + testSolidityAgainstCppOnRange(0, for_loop_simple_init_expr_cpp, 0, 5); +} + BOOST_AUTO_TEST_CASE(calling_other_functions) { // note that the index of a function is its index in the sorted sequence of functions From c9a032aad4f762d15f92135cd0135303de2ad43c Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 17 Dec 2014 00:17:38 +0100 Subject: [PATCH 557/641] better alignment of global string constants --- solc/CommandLineInterface.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index fd660a0ca..81dd25ec7 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -50,13 +50,13 @@ namespace solidity // LTODO: Maybe some argument class pairing names with // extensions and other attributes would be a better choice here? -static string const g_argAbiStr = "abi"; -static string const g_argAsmStr = "asm"; -static string const g_argAstStr = "ast"; -static string const g_argBinaryStr = "binary"; -static string const g_argOpcodesStr = "opcodes"; -static string const g_argNatspecDevStr = "natspec-dev"; -static string const g_argNatspecUserStr = "natspec-user"; +static string const g_argAbiStr = "abi"; +static string const g_argAsmStr = "asm"; +static string const g_argAstStr = "ast"; +static string const g_argBinaryStr = "binary"; +static string const g_argOpcodesStr = "opcodes"; +static string const g_argNatspecDevStr = "natspec-dev"; +static string const g_argNatspecUserStr = "natspec-user"; static void version() { From bcc263070b5851dfa432272d18b06ec32a6fb59c Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 17 Dec 2014 00:28:26 +0100 Subject: [PATCH 558/641] Moving comment to function body --- libsolidity/Parser.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libsolidity/Parser.cpp b/libsolidity/Parser.cpp index 732356751..e287319d2 100644 --- a/libsolidity/Parser.cpp +++ b/libsolidity/Parser.cpp @@ -596,12 +596,12 @@ vector> Parser::parseFunctionCallArguments() } -// distinguish between variable definition (and potentially assignment) and expression statement -// (which include assignments to other expressions and pre-declared variables) -// We have a variable definition if we get a keyword that specifies a type name, or -// in the case of a user-defined type, we have two identifiers following each other. bool Parser::peekVariableDefinition() { + // distinguish between variable definition (and potentially assignment) and expression statement + // (which include assignments to other expressions and pre-declared variables) + // We have a variable definition if we get a keyword that specifies a type name, or + // in the case of a user-defined type, we have two identifiers following each other. return (m_scanner->getCurrentToken() == Token::MAPPING || m_scanner->getCurrentToken() == Token::VAR || ((Token::isElementaryTypeName(m_scanner->getCurrentToken()) || From f9627b07dcb170a98f51c52da261ace8dfbebc67 Mon Sep 17 00:00:00 2001 From: ethdev Date: Wed, 17 Dec 2014 11:18:59 +0100 Subject: [PATCH 559/641] vs files added to gitignore --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ca18feb5b..c18d5a01d 100644 --- a/.gitignore +++ b/.gitignore @@ -18,11 +18,14 @@ ipch *.sdf *.opensdf *.suo +*.vcxproj +*.vcxproj.filters +*.sln # VIM stuff *.swp -#Xcode stuff +# Xcode stuff build_xc *.user From 373dbcaa5ffec342a870070c35ee01cb2993455e Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 17 Dec 2014 11:48:43 +0100 Subject: [PATCH 560/641] clang requires explicit initialization of map --- test/solidityCompiler.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/solidityCompiler.cpp b/test/solidityCompiler.cpp index 29f61454a..1bdafc599 100644 --- a/test/solidityCompiler.cpp +++ b/test/solidityCompiler.cpp @@ -56,7 +56,11 @@ bytes compileContract(const string& _sourceCode) BOOST_REQUIRE_NO_THROW(resolver.resolveNamesAndTypes(*contract)); Compiler compiler; - compiler.compileContract(*contract, {}, {}); + + // clang requires explicit initialization of map + // http://stackoverflow.com/questions/17264067/chosen-constructor-is-explicit-in-copy-initialization-error-with-clang-4-2 + compiler.compileContract(*contract, {}, map{}); + // debug //compiler.streamAssembly(cout); return compiler.getAssembledBytecode(); From edb6072cc9c8bbf9d54ee0596e24c03b1f778681 Mon Sep 17 00:00:00 2001 From: ethdev Date: Wed, 17 Dec 2014 11:57:32 +0100 Subject: [PATCH 561/641] windows fix for initializer-list cannot convert to dev::bytes --- test/solidityEndToEndTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/solidityEndToEndTest.cpp b/test/solidityEndToEndTest.cpp index ecd3b63a3..1ac480da9 100644 --- a/test/solidityEndToEndTest.cpp +++ b/test/solidityEndToEndTest.cpp @@ -1108,7 +1108,7 @@ BOOST_AUTO_TEST_CASE(constructor_arguments) function getName() returns (string3 ret) { return h.getName(); } })"; compileAndRun(sourceCode, 0, "Main"); - BOOST_REQUIRE(callContractFunction(0) == bytes({0x01})); + BOOST_REQUIRE(callContractFunction(0) == bytes{0x01}); BOOST_REQUIRE(callContractFunction(1) == bytes({'a', 'b', 'c'})); } From 2daf84f1bd122861bbc9a0b6e8f1401a6abc4ceb Mon Sep 17 00:00:00 2001 From: ethdev Date: Wed, 17 Dec 2014 12:19:10 +0100 Subject: [PATCH 562/641] initializer-list fix --- test/solidityEndToEndTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/solidityEndToEndTest.cpp b/test/solidityEndToEndTest.cpp index 1ac480da9..ad277a389 100644 --- a/test/solidityEndToEndTest.cpp +++ b/test/solidityEndToEndTest.cpp @@ -1108,7 +1108,7 @@ BOOST_AUTO_TEST_CASE(constructor_arguments) function getName() returns (string3 ret) { return h.getName(); } })"; compileAndRun(sourceCode, 0, "Main"); - BOOST_REQUIRE(callContractFunction(0) == bytes{0x01}); + BOOST_REQUIRE(callContractFunction(0) == bytes({byte(0x01)})); BOOST_REQUIRE(callContractFunction(1) == bytes({'a', 'b', 'c'})); } From d09f6e8c9756d2bf21499b80056fcb9bfcc76b1f Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 17 Dec 2014 15:15:04 +0100 Subject: [PATCH 563/641] Whitespace change. --- libsolidity/CallGraph.cpp | 6 ++++-- libsolidity/CallGraph.h | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/libsolidity/CallGraph.cpp b/libsolidity/CallGraph.cpp index 48666ca7f..b30afb612 100644 --- a/libsolidity/CallGraph.cpp +++ b/libsolidity/CallGraph.cpp @@ -26,8 +26,10 @@ using namespace std; -namespace dev { -namespace solidity { +namespace dev +{ +namespace solidity +{ void CallGraph::addFunction(FunctionDefinition const& _function) { diff --git a/libsolidity/CallGraph.h b/libsolidity/CallGraph.h index 986e4dc4a..f7af64bff 100644 --- a/libsolidity/CallGraph.h +++ b/libsolidity/CallGraph.h @@ -25,8 +25,10 @@ #include #include -namespace dev { -namespace solidity { +namespace dev +{ +namespace solidity +{ /** * Can be used to compute the graph of calls (or rather references) between functions of the same From 46664c44b368f8471d16f607d8ad6467ec5dbf89 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 17 Dec 2014 16:23:18 +0100 Subject: [PATCH 564/641] Assertions that throw InternalCompilerErrors. --- libsolidity/AST.cpp | 8 ++--- libsolidity/AST.h | 16 +++++----- libsolidity/CompilerContext.cpp | 20 +++++------- libsolidity/CompilerUtils.cpp | 6 ++-- libsolidity/ExpressionCompiler.cpp | 33 ++++++++----------- libsolidity/InterfaceHandler.cpp | 3 +- libsolidity/NameAndTypeResolver.cpp | 15 +++------ libsolidity/Scanner.cpp | 13 +++----- libsolidity/Token.h | 13 +++----- libsolidity/Types.cpp | 13 ++++---- libsolidity/Utils.h | 49 +++++++++++++++++++++++++++++ solc/CommandLineInterface.cpp | 3 +- 12 files changed, 107 insertions(+), 85 deletions(-) create mode 100644 libsolidity/Utils.h diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 4c042f2cf..1fa6d8f6f 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -21,7 +21,7 @@ */ #include - +#include #include #include #include @@ -145,8 +145,7 @@ void Return::checkTypeRequirements() { if (!m_expression) return; - if (asserts(m_returnParameters)) - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Return parameters not assigned.")); + solAssert(m_returnParameters, "Return parameters not assigned."); if (m_returnParameters->getParameters().size() != 1) BOOST_THROW_EXCEPTION(createTypeError("Different number of arguments in return statement " "than in returns declaration.")); @@ -336,8 +335,7 @@ void IndexAccess::checkTypeRequirements() void Identifier::checkTypeRequirements() { - if (asserts(m_referencedDeclaration)) - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Identifier not resolved.")); + solAssert(m_referencedDeclaration, "Identifier not resolved."); VariableDeclaration const* variable = dynamic_cast(m_referencedDeclaration); if (variable) diff --git a/libsolidity/AST.h b/libsolidity/AST.h index c83690443..b7c3dc6c0 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -364,7 +365,7 @@ public: explicit ElementaryTypeName(Location const& _location, Token::Value _type): TypeName(_location), m_type(_type) { - if (asserts(Token::isElementaryTypeName(_type))) BOOST_THROW_EXCEPTION(InternalCompilerError()); + solAssert(Token::isElementaryTypeName(_type), ""); } virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; @@ -575,8 +576,7 @@ public: void setFunctionReturnParameters(ParameterList& _parameters) { m_returnParameters = &_parameters; } ParameterList const& getFunctionReturnParameters() const { - if (asserts(m_returnParameters)) - BOOST_THROW_EXCEPTION(InternalCompilerError()); + solAssert(m_returnParameters, ""); return *m_returnParameters; } Expression const* getExpression() const { return m_expression.get(); } @@ -682,7 +682,7 @@ public: Expression(_location), m_leftHandSide(_leftHandSide), m_assigmentOperator(_assignmentOperator), m_rightHandSide(_rightHandSide) { - if (asserts(Token::isAssignmentOp(_assignmentOperator))) BOOST_THROW_EXCEPTION(InternalCompilerError()); + solAssert(Token::isAssignmentOp(_assignmentOperator), ""); } virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; @@ -710,7 +710,7 @@ public: Expression(_location), m_operator(_operator), m_subExpression(_subExpression), m_isPrefix(_isPrefix) { - if (asserts(Token::isUnaryOp(_operator))) BOOST_THROW_EXCEPTION(InternalCompilerError()); + solAssert(Token::isUnaryOp(_operator), ""); } virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; @@ -737,7 +737,7 @@ public: Token::Value _operator, ASTPointer const& _right): Expression(_location), m_left(_left), m_operator(_operator), m_right(_right) { - if (asserts(Token::isBinaryOp(_operator) || Token::isCompareOp(_operator))) BOOST_THROW_EXCEPTION(InternalCompilerError()); + solAssert(Token::isBinaryOp(_operator) || Token::isCompareOp(_operator), ""); } virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; @@ -799,7 +799,7 @@ public: std::vector> getArguments() const { return {m_arguments.begin(), m_arguments.end()}; } /// Returns the referenced contract. Can only be called after type checking. - ContractDefinition const* getContract() const { if (asserts(m_contract)) BOOST_THROW_EXCEPTION(InternalCompilerError()); else return m_contract; } + ContractDefinition const* getContract() const { solAssert(m_contract, ""); return m_contract; } private: ASTPointer m_contractName; @@ -894,7 +894,7 @@ public: ElementaryTypeNameExpression(Location const& _location, Token::Value _typeToken): PrimaryExpression(_location), m_typeToken(_typeToken) { - if (asserts(Token::isElementaryTypeName(_typeToken))) BOOST_THROW_EXCEPTION(InternalCompilerError()); + solAssert(Token::isElementaryTypeName(_typeToken), ""); } virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; diff --git a/libsolidity/CompilerContext.cpp b/libsolidity/CompilerContext.cpp index 47401436a..18357bf0c 100644 --- a/libsolidity/CompilerContext.cpp +++ b/libsolidity/CompilerContext.cpp @@ -27,8 +27,10 @@ using namespace std; -namespace dev { -namespace solidity { +namespace dev +{ +namespace solidity +{ void CompilerContext::addMagicGlobal(MagicVariableDeclaration const& _declaration) { @@ -65,8 +67,7 @@ void CompilerContext::addFunction(FunctionDefinition const& _function) bytes const& CompilerContext::getCompiledContract(const ContractDefinition& _contract) const { auto ret = m_compiledContracts.find(&_contract); - if (asserts(ret != m_compiledContracts.end())) - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Compiled contract not found.")); + solAssert(ret != m_compiledContracts.end(), "Compiled contract not found."); return *ret->second; } @@ -78,16 +79,14 @@ bool CompilerContext::isLocalVariable(Declaration const* _declaration) const eth::AssemblyItem CompilerContext::getFunctionEntryLabel(FunctionDefinition const& _function) const { auto res = m_functionEntryLabels.find(&_function); - if (asserts(res != m_functionEntryLabels.end())) - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Function entry label not found.")); + solAssert(res != m_functionEntryLabels.end(), "Function entry label not found."); return res->second.tag(); } unsigned CompilerContext::getBaseStackOffsetOfVariable(Declaration const& _declaration) const { auto res = m_localVariables.find(&_declaration); - if (asserts(res != m_localVariables.end())) - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Variable not found on stack.")); + solAssert(res != m_localVariables.end(), "Variable not found on stack."); return m_localVariablesSize - res->second - 1; } @@ -99,12 +98,9 @@ unsigned CompilerContext::baseToCurrentStackOffset(unsigned _baseOffset) const u256 CompilerContext::getStorageLocationOfVariable(const Declaration& _declaration) const { auto it = m_stateVariables.find(&_declaration); - if (it == m_stateVariables.end()) - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Variable not found in storage.")); + solAssert(it != m_stateVariables.end(), "Variable not found in storage."); return it->second; } - - } } diff --git a/libsolidity/CompilerUtils.cpp b/libsolidity/CompilerUtils.cpp index 9f474896e..680e9190b 100644 --- a/libsolidity/CompilerUtils.cpp +++ b/libsolidity/CompilerUtils.cpp @@ -39,8 +39,7 @@ void CompilerUtils::loadFromMemory(unsigned _offset, unsigned _bytes, bool _left return; } eth::Instruction load = _fromCalldata ? eth::Instruction::CALLDATALOAD : eth::Instruction::MLOAD; - if (asserts(_bytes <= 32)) - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Memory load of more than 32 bytes requested.")); + solAssert(_bytes <= 32, "Memory load of more than 32 bytes requested."); if (_bytes == 32) m_context << u256(_offset) << load; else @@ -63,8 +62,7 @@ void CompilerUtils::storeInMemory(unsigned _offset, unsigned _bytes, bool _leftA m_context << eth::Instruction::POP; return; } - if (asserts(_bytes <= 32)) - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Memory store of more than 32 bytes requested.")); + solAssert(_bytes <= 32, "Memory store of more than 32 bytes requested."); if (_bytes != 32 && !_leftAligned) // shift the value accordingly before storing m_context << (u256(1) << ((32 - _bytes) * 8)) << eth::Instruction::MUL; diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 743503bbf..f58c157d9 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -30,8 +30,10 @@ using namespace std; -namespace dev { -namespace solidity { +namespace dev +{ +namespace solidity +{ void ExpressionCompiler::compileExpression(CompilerContext& _context, Expression const& _expression, bool _optimize) { @@ -51,8 +53,7 @@ bool ExpressionCompiler::visit(Assignment const& _assignment) _assignment.getRightHandSide().accept(*this); appendTypeConversion(*_assignment.getRightHandSide().getType(), *_assignment.getType()); _assignment.getLeftHandSide().accept(*this); - if (asserts(m_currentLValue.isValid())) - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("LValue not retrieved.")); + solAssert(m_currentLValue.isValid(), "LValue not retrieved."); Token::Value op = _assignment.getAssignmentOperator(); if (op != Token::ASSIGN) // compound assignment @@ -84,8 +85,7 @@ void ExpressionCompiler::endVisit(UnaryOperation const& _unaryOperation) break; case Token::DELETE: // delete // @todo semantics change for complex types - if (asserts(m_currentLValue.isValid())) - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("LValue not retrieved.")); + solAssert(m_currentLValue.isValid(), "LValue not retrieved."); m_context << u256(0); if (m_currentLValue.storesReferenceOnStack()) @@ -95,8 +95,7 @@ void ExpressionCompiler::endVisit(UnaryOperation const& _unaryOperation) break; case Token::INC: // ++ (pre- or postfix) case Token::DEC: // -- (pre- or postfix) - if (asserts(m_currentLValue.isValid())) - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("LValue not retrieved.")); + solAssert(m_currentLValue.isValid(), "LValue not retrieved."); m_currentLValue.retrieveValue(_unaryOperation); if (!_unaryOperation.isPrefixOperation()) { @@ -179,8 +178,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) if (_functionCall.isTypeConversion()) { //@todo struct construction - if (asserts(_functionCall.getArguments().size() == 1)) - BOOST_THROW_EXCEPTION(InternalCompilerError()); + solAssert(_functionCall.getArguments().size() == 1, ""); Expression const& firstArgument = *_functionCall.getArguments().front(); firstArgument.accept(*this); if (firstArgument.getType()->getCategory() == Type::Category::CONTRACT && @@ -195,8 +193,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) { FunctionType const& function = dynamic_cast(*_functionCall.getExpression().getType()); vector> arguments = _functionCall.getArguments(); - if (asserts(arguments.size() == function.getParameterTypes().size())) - BOOST_THROW_EXCEPTION(InternalCompilerError()); + solAssert(arguments.size() == function.getParameterTypes().size(), ""); switch (function.getLocation()) { @@ -282,12 +279,10 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) bool ExpressionCompiler::visit(NewExpression const& _newExpression) { ContractType const* type = dynamic_cast(_newExpression.getType().get()); - if (asserts(type)) - BOOST_THROW_EXCEPTION(InternalCompilerError()); + solAssert(type, ""); TypePointers const& types = type->getConstructorType()->getParameterTypes(); vector> arguments = _newExpression.getArguments(); - if (asserts(arguments.size() == types.size())) - BOOST_THROW_EXCEPTION(InternalCompilerError()); + solAssert(arguments.size() == types.size(), ""); // copy the contracts code into memory bytes const& bytecode = m_context.getCompiledContract(*_newExpression.getContract()); @@ -439,8 +434,7 @@ void ExpressionCompiler::endVisit(Literal const& _literal) void ExpressionCompiler::appendAndOrOperatorCode(BinaryOperation const& _binaryOperation) { Token::Value const op = _binaryOperation.getOperator(); - if (asserts(op == Token::OR || op == Token::AND)) - BOOST_THROW_EXCEPTION(InternalCompilerError()); + solAssert(op == Token::OR || op == Token::AND, ""); _binaryOperation.getLeftExpression().accept(*this); m_context << eth::Instruction::DUP1; @@ -592,8 +586,7 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio vector> const& _arguments, FunctionCallOptions const& _options) { - if (asserts(_arguments.size() == _functionType.getParameterTypes().size())) - BOOST_THROW_EXCEPTION(InternalCompilerError()); + solAssert(_arguments.size() == _functionType.getParameterTypes().size(), ""); unsigned dataOffset = _options.bare ? 0 : 1; // reserve one byte for the function index for (unsigned i = 0; i < _arguments.size(); ++i) diff --git a/libsolidity/InterfaceHandler.cpp b/libsolidity/InterfaceHandler.cpp index 1310f504a..c734fa38c 100644 --- a/libsolidity/InterfaceHandler.cpp +++ b/libsolidity/InterfaceHandler.cpp @@ -198,8 +198,7 @@ std::string::const_iterator InterfaceHandler::appendDocTagParam(std::string::con std::string::const_iterator _end) { // Should never be called with an empty vector - if (asserts(!m_params.empty())) - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Internal: Tried to append to empty parameter")); + solAssert(!m_params.empty(), "Internal: Tried to append to empty parameter"); auto pair = m_params.back(); pair.second += " "; diff --git a/libsolidity/NameAndTypeResolver.cpp b/libsolidity/NameAndTypeResolver.cpp index 80732615c..3774537d1 100644 --- a/libsolidity/NameAndTypeResolver.cpp +++ b/libsolidity/NameAndTypeResolver.cpp @@ -70,8 +70,7 @@ void NameAndTypeResolver::checkTypeRequirements(ContractDefinition& _contract) void NameAndTypeResolver::updateDeclaration(Declaration const& _declaration) { m_scopes[nullptr].registerDeclaration(_declaration, true); - if (asserts(_declaration.getScope() == nullptr)) - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Updated declaration outside global scope.")); + solAssert(_declaration.getScope() == nullptr, "Updated declaration outside global scope."); } Declaration const* NameAndTypeResolver::resolveName(ASTString const& _name, Declaration const* _scope) const @@ -133,8 +132,7 @@ void DeclarationRegistrationHelper::endVisit(VariableDefinition& _variableDefini { // Register the local variables with the function // This does not fit here perfectly, but it saves us another AST visit. - if (asserts(m_currentFunction)) - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Variable definition without function.")); + solAssert(m_currentFunction, "Variable definition without function."); m_currentFunction->addLocalVariable(_variableDefinition.getDeclaration()); } @@ -149,15 +147,13 @@ void DeclarationRegistrationHelper::enterNewSubScope(Declaration const& _declara map::iterator iter; bool newlyAdded; tie(iter, newlyAdded) = m_scopes.emplace(&_declaration, DeclarationContainer(m_currentScope, &m_scopes[m_currentScope])); - if (asserts(newlyAdded)) - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unable to add new scope.")); + solAssert(newlyAdded, "Unable to add new scope."); m_currentScope = &_declaration; } void DeclarationRegistrationHelper::closeCurrentScope() { - if (asserts(m_currentScope)) - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Closed non-existing scope.")); + solAssert(m_currentScope, "Closed non-existing scope."); m_currentScope = m_scopes[m_currentScope].getEnclosingDeclaration(); } @@ -196,8 +192,7 @@ void ReferencesResolver::endVisit(VariableDeclaration& _variable) bool ReferencesResolver::visit(Return& _return) { - if (asserts(m_returnParameters)) - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Return parameters not set.")); + solAssert(m_returnParameters, "Return parameters not set."); _return.setFunctionReturnParameters(*m_returnParameters); return true; } diff --git a/libsolidity/Scanner.cpp b/libsolidity/Scanner.cpp index 08bf744d4..1a21149a1 100644 --- a/libsolidity/Scanner.cpp +++ b/libsolidity/Scanner.cpp @@ -52,6 +52,7 @@ #include #include +#include #include using namespace std; @@ -249,8 +250,7 @@ Token::Value Scanner::scanDocumentationComment() Token::Value Scanner::skipMultiLineComment() { - if (asserts(m_char == '*')) - BOOST_THROW_EXCEPTION(InternalCompilerError()); + solAssert(m_char == '*', ""); advance(); while (!isSourcePastEndOfInput()) { @@ -597,8 +597,7 @@ Token::Value Scanner::scanNumber(char _charSeen) // scan exponent, if any if (m_char == 'e' || m_char == 'E') { - if (asserts(kind != HEX)) // 'e'/'E' must be scanned as part of the hex number - BOOST_THROW_EXCEPTION(InternalCompilerError()); + solAssert(kind != HEX, "'e'/'E' must be scanned as part of the hex number"); if (kind != DECIMAL) return Token::ILLEGAL; // scan exponent @@ -639,8 +638,7 @@ static Token::Value keywordOrIdentifierToken(string const& _input) Token::Value Scanner::scanIdentifierOrKeyword() { - if (asserts(isIdentifierStart(m_char))) - BOOST_THROW_EXCEPTION(InternalCompilerError()); + solAssert(isIdentifierStart(m_char), ""); LiteralScope literal(this, LITERAL_TYPE_STRING); addLiteralCharAndAdvance(); // Scan the rest of the identifier characters. @@ -662,8 +660,7 @@ char CharStream::advanceAndGet(size_t _chars) char CharStream::rollback(size_t _amount) { - if (asserts(m_pos >= _amount)) - BOOST_THROW_EXCEPTION(InternalCompilerError()); + solAssert(m_pos >= _amount, ""); m_pos -= _amount; return get(); } diff --git a/libsolidity/Token.h b/libsolidity/Token.h index 22378ae07..32656096a 100644 --- a/libsolidity/Token.h +++ b/libsolidity/Token.h @@ -44,6 +44,7 @@ #include #include +#include #include namespace dev @@ -344,8 +345,7 @@ public: // (e.g. "LT" for the token LT). static char const* getName(Value tok) { - if (asserts(tok < NUM_TOKENS)) - BOOST_THROW_EXCEPTION(InternalCompilerError()); + solAssert(tok < NUM_TOKENS, ""); return m_name[tok]; } @@ -360,8 +360,7 @@ public: static Value AssignmentToBinaryOp(Value op) { - if (asserts(isAssignmentOp(op) && op != ASSIGN)) - BOOST_THROW_EXCEPTION(InternalCompilerError()); + solAssert(isAssignmentOp(op) && op != ASSIGN, ""); return Token::Value(op + (BIT_OR - ASSIGN_BIT_OR)); } @@ -375,8 +374,7 @@ public: // have a (unique) string (e.g. an IDENTIFIER). static char const* toString(Value tok) { - if (asserts(tok < NUM_TOKENS)) - BOOST_THROW_EXCEPTION(InternalCompilerError()); + solAssert(tok < NUM_TOKENS, ""); return m_string[tok]; } @@ -384,8 +382,7 @@ public: // operators; returns 0 otherwise. static int precedence(Value tok) { - if (asserts(tok < NUM_TOKENS)) - BOOST_THROW_EXCEPTION(InternalCompilerError()); + solAssert(tok < NUM_TOKENS, ""); return m_precedence[tok]; } diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index eba11cb0d..71319c3ac 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -34,8 +35,7 @@ namespace solidity shared_ptr Type::fromElementaryTypeName(Token::Value _typeToken) { - if (asserts(Token::isElementaryTypeName(_typeToken))) - BOOST_THROW_EXCEPTION(InternalCompilerError()); + solAssert(Token::isElementaryTypeName(_typeToken), ""); if (Token::INT <= _typeToken && _typeToken <= Token::HASH256) { @@ -120,8 +120,8 @@ IntegerType::IntegerType(int _bits, IntegerType::Modifier _modifier): { if (isAddress()) m_bits = 160; - if (asserts(m_bits > 0 && m_bits <= 256 && m_bits % 8 == 0)) - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid bit number for integer type: " + dev::toString(_bits))); + solAssert(m_bits > 0 && m_bits <= 256 && m_bits % 8 == 0, + "Invalid bit number for integer type: " + dev::toString(_bits)); } bool IntegerType::isImplicitlyConvertibleTo(Type const& _convertTo) const @@ -215,9 +215,8 @@ shared_ptr StaticStringType::smallestTypeForLiteral(string con StaticStringType::StaticStringType(int _bytes): m_bytes(_bytes) { - if (asserts(m_bytes >= 0 && m_bytes <= 32)) - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid byte number for static string type: " + - dev::toString(m_bytes))); + solAssert(m_bytes >= 0 && m_bytes <= 32, + "Invalid byte number for static string type: " + dev::toString(m_bytes)); } bool StaticStringType::isImplicitlyConvertibleTo(Type const& _convertTo) const diff --git a/libsolidity/Utils.h b/libsolidity/Utils.h new file mode 100644 index 000000000..8d6a3ab08 --- /dev/null +++ b/libsolidity/Utils.h @@ -0,0 +1,49 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** + * @author Christian + * @date 2014 + * Solidity Utilities. + */ + +#pragma once + +#include +#include + +namespace dev +{ +namespace solidity +{ + +/// Assertion that throws an InternalCompilerError containing the given description if it is not met. +#define solAssert(CONDITION, DESCRIPTION) \ + ::dev::solidity::solAssertAux(CONDITION, DESCRIPTION, __LINE__, __FILE__, ETH_FUNC) + +inline void solAssertAux(bool _condition, std::string const& _errorDescription, unsigned _line, + char const* _file, char const* _function) +{ + if (!_condition) + ::boost::throw_exception( InternalCompilerError() + << errinfo_comment(_errorDescription) + << ::boost::throw_function(_function) + << ::boost::throw_file(_file) + << ::boost::throw_line(_line)); +} + +} +} diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 81dd25ec7..399f52436 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -311,7 +311,8 @@ bool CommandLineInterface::processInput() } catch (InternalCompilerError const& exception) { - SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Internal compiler error", m_compiler); + cerr << "Internal compiler error during compilation:" << endl + << boost::diagnostic_information(exception); return false; } catch (Exception const& exception) From 0f75aaf6e63fd1c22ddc0eb828af8874bc2cd018 Mon Sep 17 00:00:00 2001 From: ethdev Date: Wed, 17 Dec 2014 16:25:24 +0100 Subject: [PATCH 565/641] cpack nsis windows installer --- CMakeLists.txt | 26 +++++++++++++++++++++++++- cmake/EthExecutableHelper.cmake | 15 ++++++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 02e3a1a05..1293b4427 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -156,4 +156,28 @@ add_test(NAME alltests WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/test COMMAND testet #unset(TARGET_PLATFORM CACHE) - +if (WIN32) + # packaging stuff + include(InstallRequiredSystemLibraries) + set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "ethereum") + set(CPACK_PACKAGE_VENDOR "ethereum.org") + set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.md") + set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") + set(CPACK_PACKAGE_VERSION "0.7") + set(CPACK_GENERATOR "NSIS") + + # our stuff + set(CPACK_COMPONENT_ALETHZERO_GROUP "Applications") + set(CPACK_COMPONENT_THIRD_GROUP "Applications") + set(CPACK_COMPONENT_MIX_GROUP "Applications") + set(CPACK_COMPONENTS_ALL alethzero third mix) + + # nsis specific stuff + set(CPACK_NSIS_DISPLAY_NAME "${CPACK_PACKAGE_INSTALL_DIRECTORY} ethereum") + set(CPACK_NSIS_HELP_LINK "https://github.com/ethereum/cpp-ethereum") + set(CPACK_NSIS_URL_INFO_ABOUT "https://github.com/ethereum/cpp-ethereum") + set(CPACK_NSIS_CONTACT "ethereum.org") + set(CPACK_NSIS_MODIFY_PATH ON) + + include(CPack) +endif (WIN32) diff --git a/cmake/EthExecutableHelper.cmake b/cmake/EthExecutableHelper.cmake index 9d273522e..0ec1e10d4 100644 --- a/cmake/EthExecutableHelper.cmake +++ b/cmake/EthExecutableHelper.cmake @@ -108,7 +108,20 @@ macro(eth_install_executable EXECUTABLE) $/platforms ) - install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin) + install( FILES ${DLLS} + DESTINATION bin + COMPONENT ${EXECUTABLE} + ) + + install( DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/plugins/platforms + DESTINATION bin + COMPONENT ${EXECUTABLE} + ) + + install( TARGETS ${EXECUTABLE} RUNTIME + DESTINATION bin + COMPONENT ${EXECUTABLE} + ) else() install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin) From 8468d896a73b5ea44c94ca92afe78189044d8024 Mon Sep 17 00:00:00 2001 From: ethdev Date: Wed, 17 Dec 2014 16:47:22 +0100 Subject: [PATCH 566/641] fixed msvc not expanding macros correctly --- test/CMakeLists.txt | 1 + test/solidityCompiler.cpp | 7 ++++--- test/solidityExpressionCompiler.cpp | 4 ++++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f862de24c..7cedc117b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -3,6 +3,7 @@ cmake_policy(SET CMP0015 NEW) aux_source_directory(. SRC_LIST) list(REMOVE_ITEM SRC_LIST "./createRandomTest.cpp") +include_directories(${Boost_INCLUDE_DIRS}) include_directories(${CRYPTOPP_INCLUDE_DIRS}) include_directories(${JSONCPP_INCLUDE_DIRS}) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) diff --git a/test/solidityCompiler.cpp b/test/solidityCompiler.cpp index be2c83838..385a3e577 100644 --- a/test/solidityCompiler.cpp +++ b/test/solidityCompiler.cpp @@ -52,17 +52,18 @@ bytes compileContract(const string& _sourceCode) resolver.registerDeclarations(*sourceUnit); for (ASTPointer const& node: sourceUnit->getNodes()) if (ContractDefinition* contract = dynamic_cast(node.get())) + { BOOST_REQUIRE_NO_THROW(resolver.resolveNamesAndTypes(*contract)); + } for (ASTPointer const& node: sourceUnit->getNodes()) if (ContractDefinition* contract = dynamic_cast(node.get())) + { BOOST_REQUIRE_NO_THROW(resolver.checkTypeRequirements(*contract)); + } for (ASTPointer const& node: sourceUnit->getNodes()) if (ContractDefinition* contract = dynamic_cast(node.get())) { Compiler compiler; - - // clang requires explicit initialization of map - // http://stackoverflow.com/questions/17264067/chosen-constructor-is-explicit-in-copy-initialization-error-with-clang-4-2 compiler.compileContract(*contract, {}, map{}); // debug diff --git a/test/solidityExpressionCompiler.cpp b/test/solidityExpressionCompiler.cpp index 2bdc38421..9c375418e 100644 --- a/test/solidityExpressionCompiler.cpp +++ b/test/solidityExpressionCompiler.cpp @@ -95,10 +95,14 @@ bytes compileFirstExpression(const string& _sourceCode, vector> _ resolver.registerDeclarations(*sourceUnit); for (ASTPointer const& node: sourceUnit->getNodes()) if (ContractDefinition* contract = dynamic_cast(node.get())) + { BOOST_REQUIRE_NO_THROW(resolver.resolveNamesAndTypes(*contract)); + } for (ASTPointer const& node: sourceUnit->getNodes()) if (ContractDefinition* contract = dynamic_cast(node.get())) + { BOOST_REQUIRE_NO_THROW(resolver.checkTypeRequirements(*contract)); + } for (ASTPointer const& node: sourceUnit->getNodes()) if (ContractDefinition* contract = dynamic_cast(node.get())) { From 83b218908b8220aa47a3bb1ea8b2e3cdc60474b7 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 17 Dec 2014 17:08:57 +0100 Subject: [PATCH 567/641] Format catch arguments as function parameters. --- solc/CommandLineInterface.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 399f52436..2a79521ef 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -230,9 +230,9 @@ bool CommandLineInterface::parseArguments(int argc, char** argv) { po::store(po::command_line_parser(argc, argv).options(desc).positional(p).allow_unregistered().run(), m_args); } - catch (po::error const& exception) + catch (po::error const& _exception) { - cout << exception.what() << endl; + cout << _exception.what() << endl; return false; } po::notify(m_args); @@ -289,35 +289,35 @@ bool CommandLineInterface::processInput() // TODO: Perhaps we should not compile unless requested m_compiler.compile(m_args["optimize"].as()); } - catch (ParserError const& exception) + catch (ParserError const& _exception) { - SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Parser error", m_compiler); + SourceReferenceFormatter::printExceptionInformation(cerr, _exception, "Parser error", m_compiler); return false; } - catch (DeclarationError const& exception) + catch (DeclarationError const& _exception) { - SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Declaration error", m_compiler); + SourceReferenceFormatter::printExceptionInformation(cerr, _exception, "Declaration error", m_compiler); return false; } - catch (TypeError const& exception) + catch (TypeError const& _exception) { - SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Type error", m_compiler); + SourceReferenceFormatter::printExceptionInformation(cerr, _exception, "Type error", m_compiler); return false; } - catch (CompilerError const& exception) + catch (CompilerError const& _exception) { - SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Compiler error", m_compiler); + SourceReferenceFormatter::printExceptionInformation(cerr, _exception, "Compiler error", m_compiler); return false; } - catch (InternalCompilerError const& exception) + catch (InternalCompilerError const& _exception) { cerr << "Internal compiler error during compilation:" << endl - << boost::diagnostic_information(exception); + << boost::diagnostic_information(_exception); return false; } - catch (Exception const& exception) + catch (Exception const& _exception) { - cerr << "Exception during compilation: " << boost::diagnostic_information(exception) << endl; + cerr << "Exception during compilation: " << boost::diagnostic_information(_exception) << endl; return false; } catch (...) From 6c1beee64d57b2ea8e5c5ecb9992806cb1cfe999 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 17 Dec 2014 17:55:50 +0100 Subject: [PATCH 568/641] Update evmjit submodule --- evmjit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evmjit b/evmjit index dbf8174fc..b37ce8e97 160000 --- a/evmjit +++ b/evmjit @@ -1 +1 @@ -Subproject commit dbf8174fc6f8be9e6d1e62a627388fa23eb2308f +Subproject commit b37ce8e9727683b8c7afb84520f42a908318f8d8 From 2bff39d4870a6b8c57deb53fbdba2d22cdd0d01b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 17 Dec 2014 17:56:44 +0100 Subject: [PATCH 569/641] Visual Studio project files update --- windows/LibEthereum.vcxproj | 10 ++++------ windows/LibEthereum.vcxproj.filters | 30 ++++++++++++----------------- windows/TestEthereum.vcxproj | 1 + 3 files changed, 17 insertions(+), 24 deletions(-) diff --git a/windows/LibEthereum.vcxproj b/windows/LibEthereum.vcxproj index b4624f962..30c5e8a21 100644 --- a/windows/LibEthereum.vcxproj +++ b/windows/LibEthereum.vcxproj @@ -117,13 +117,12 @@ - - + - + @@ -335,13 +334,12 @@ - - + - + diff --git a/windows/LibEthereum.vcxproj.filters b/windows/LibEthereum.vcxproj.filters index e70393706..39c3a0004 100644 --- a/windows/LibEthereum.vcxproj.filters +++ b/windows/LibEthereum.vcxproj.filters @@ -58,18 +58,12 @@ libethereum - - libethereum - libethereum libethereum - - libethereum - libethereum @@ -136,9 +130,6 @@ libethereum - - libethereum - libethereum @@ -204,6 +195,12 @@ libp2p + + libethereum + + + libethereum + @@ -272,18 +269,12 @@ libethereum - - libethereum - libethereum libethereum - - libethereum - libethereum @@ -368,9 +359,6 @@ libethereum - - libethereum - libethereum @@ -449,6 +437,12 @@ libp2p + + libethereum + + + libethereum + diff --git a/windows/TestEthereum.vcxproj b/windows/TestEthereum.vcxproj index 93bb98e23..cc737bc31 100644 --- a/windows/TestEthereum.vcxproj +++ b/windows/TestEthereum.vcxproj @@ -111,6 +111,7 @@ Console true + 33554432 From a6e8c122ea88990eb6a0f9a26bfbe81c335b07c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 17 Dec 2014 17:56:54 +0100 Subject: [PATCH 570/641] Windows fix --- test/TestHelper.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index d0100db61..ea848c7ce 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -331,9 +331,11 @@ void checkStorage(map _expectedStore, map _resultStore, } } BOOST_CHECK_EQUAL(_resultStore.size(), _expectedStore.size()); - for (auto&& resultStorePair : _resultStore) + for (auto&& resultStorePair: _resultStore) + { if (!_expectedStore.count(resultStorePair.first)) BOOST_ERROR(_expectedAddr << ": unexpected store key " << resultStorePair.first); + } } void checkLog(LogEntries _resultLogs, LogEntries _expectedLogs) From 68b9c67e9577b80cba4b8900da36e4898198bb76 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 17 Dec 2014 18:33:55 +0100 Subject: [PATCH 571/641] Return the last contract by default. --- libsolidity/CompilerStack.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libsolidity/CompilerStack.cpp b/libsolidity/CompilerStack.cpp index 1242c0aba..9fdc88baa 100644 --- a/libsolidity/CompilerStack.cpp +++ b/libsolidity/CompilerStack.cpp @@ -234,9 +234,13 @@ CompilerStack::Contract const& CompilerStack::getContract(string const& _contrac { if (m_contracts.empty()) BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("No compiled contracts found.")); + string contractName = _contractName; if (_contractName.empty()) - return m_contracts.begin()->second; - auto it = m_contracts.find(_contractName); + // try to find the "last contract" + for (ASTPointer const& node: m_sourceOrder.back()->ast->getNodes()) + if (auto contract = dynamic_cast(node.get())) + contractName = contract->getName(); + auto it = m_contracts.find(contractName); if (it == m_contracts.end()) BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Contract " + _contractName + " not found.")); return it->second; From 3f865244df4d145d8b12af9a0c95859c2608cd5a Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 17 Dec 2014 18:52:53 +0100 Subject: [PATCH 572/641] Fix warning about sequence points. --- libdevcrypto/Common.h | 2 +- libethereum/Transaction.cpp | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libdevcrypto/Common.h b/libdevcrypto/Common.h index 02d52f495..021f97de8 100644 --- a/libdevcrypto/Common.h +++ b/libdevcrypto/Common.h @@ -47,7 +47,7 @@ struct SignatureStruct { SignatureStruct() {} SignatureStruct(Signature const& _s) { *(h520*)this = _s; } - SignatureStruct(h256 _r, h256 _s, byte _v): r(_r), s(_s), v(_v) {} + SignatureStruct(h256 const& _r, h256 const& _s, byte _v): r(_r), s(_s), v(_v) {} operator Signature() const { return *(h520 const*)this; } /// @returns true if r,s,v values are valid, otherwise false diff --git a/libethereum/Transaction.cpp b/libethereum/Transaction.cpp index 1edfe3927..0c1173134 100644 --- a/libethereum/Transaction.cpp +++ b/libethereum/Transaction.cpp @@ -43,7 +43,10 @@ Transaction::Transaction(bytesConstRef _rlpData, bool _checkSender) m_receiveAddress = rlp[field = 3].toHash
(); m_value = rlp[field = 4].toInt(); m_data = rlp[field = 5].toBytes(); - m_vrs = SignatureStruct{ rlp[field = 7].toInt(), rlp[field = 8].toInt(), byte(rlp[field = 6].toInt() - 27) }; + h256 r = rlp[field = 7].toInt(); + h256 s = rlp[field = 8].toInt(); + byte v = rlp[field = 6].toInt() - 27; + m_vrs = SignatureStruct{ r, s, v }; if (_checkSender) m_sender = sender(); } From 7377e9388294b918a917691218f0b659a0d74edf Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 17 Dec 2014 19:20:36 +0100 Subject: [PATCH 573/641] Bugfix: Data reference tags can be longer than jump tags. --- libevmcore/Assembly.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/libevmcore/Assembly.cpp b/libevmcore/Assembly.cpp index 74bd015a6..5efbb9487 100644 --- a/libevmcore/Assembly.cpp +++ b/libevmcore/Assembly.cpp @@ -478,7 +478,6 @@ bytes Assembly::assemble() const bytes ret; unsigned totalBytes = bytesRequired(); - ret.reserve(totalBytes); vector tagPos(m_usedTags); map tagRef; multimap dataRef; @@ -489,6 +488,12 @@ bytes Assembly::assemble() const for (auto const& i: m_subs) m_data[i.first] = i.second.assemble(); + unsigned bytesRequiredIncludingData = bytesRequired(); + unsigned bytesPerDataRef = dev::bytesRequired(bytesRequiredIncludingData); + byte dataRefPush = (byte)Instruction::PUSH1 - 1 + bytesPerDataRef; + ret.reserve(bytesRequiredIncludingData); + // m_data must not change from here on + for (AssemblyItem const& i: m_items) switch (i.m_type) { @@ -526,9 +531,9 @@ bytes Assembly::assemble() const } case PushData: case PushSub: { - ret.push_back(tagPush); + ret.push_back(dataRefPush); dataRef.insert(make_pair((h256)i.m_data, ret.size())); - ret.resize(ret.size() + bytesPerTag); + ret.resize(ret.size() + bytesPerDataRef); break; } case PushSubSize: @@ -542,10 +547,12 @@ bytes Assembly::assemble() const break; } case PushProgramSize: - ret.push_back(tagPush); + { + ret.push_back(dataRefPush); sizeRef.push_back(ret.size()); - ret.resize(ret.size() + bytesPerTag); + ret.resize(ret.size() + bytesPerDataRef); break; + } case Tag: tagPos[(unsigned)i.m_data] = ret.size(); ret.push_back((byte)Instruction::JUMPDEST); @@ -573,7 +580,7 @@ bytes Assembly::assemble() const { for (auto it = its.first; it != its.second; ++it) { - bytesRef r(ret.data() + it->second, bytesPerTag); + bytesRef r(ret.data() + it->second, bytesPerDataRef); toBigEndian(ret.size(), r); } for (auto b: i.second) @@ -583,7 +590,7 @@ bytes Assembly::assemble() const } for (unsigned pos: sizeRef) { - bytesRef r(ret.data() + pos, bytesPerTag); + bytesRef r(ret.data() + pos, bytesPerDataRef); toBigEndian(ret.size(), r); } return ret; From 857dca6c8d4b9c35c7cb5229906c0ecf9004a069 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Thu, 18 Dec 2014 09:06:06 +0100 Subject: [PATCH 574/641] refund tests --- test/stRefundTestFiller.json | 37 ++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 test/stRefundTestFiller.json diff --git a/test/stRefundTestFiller.json b/test/stRefundTestFiller.json new file mode 100644 index 000000000..3745c8d81 --- /dev/null +++ b/test/stRefundTestFiller.json @@ -0,0 +1,37 @@ +{ + "refund0" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 1 ]] 0 }", + "storage" : { + "0x01" : "0x01" + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "850", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + } +} From 87721356e1e5c44375db9331034312152c8f4f36 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Thu, 18 Dec 2014 09:06:51 +0100 Subject: [PATCH 575/641] refund test inclusion --- test/state.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/state.cpp b/test/state.cpp index f183c4813..5bdfb419b 100644 --- a/test/state.cpp +++ b/test/state.cpp @@ -140,11 +140,22 @@ BOOST_AUTO_TEST_CASE(stInitCodeTest) dev::test::executeTests("stInitCodeTest", "/StateTests", dev::test::doStateTests); } +BOOST_AUTO_TEST_CASE(stTransactionTest) +{ + dev::test::executeTests("stTransactionTest", "/StateTests", dev::test::doStateTests); +} + BOOST_AUTO_TEST_CASE(stSpecialTest) { dev::test::executeTests("stSpecialTest", "/StateTests", dev::test::doStateTests); } +BOOST_AUTO_TEST_CASE(stRefundTest) +{ + dev::test::executeTests("stRefundTest", "/StateTests", dev::test::doStateTests); +} + + BOOST_AUTO_TEST_CASE(stCreateTest) { for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i) From 0bf7eb0670101fc2ba74e6ae276299e7bc197579 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Thu, 18 Dec 2014 09:32:24 +0100 Subject: [PATCH 576/641] more refund tests --- test/stRefundTestFiller.json | 112 ++++++++++++++++++++++++++++++++++- 1 file changed, 110 insertions(+), 2 deletions(-) diff --git a/test/stRefundTestFiller.json b/test/stRefundTestFiller.json index 3745c8d81..4060bbb72 100644 --- a/test/stRefundTestFiller.json +++ b/test/stRefundTestFiller.json @@ -1,5 +1,5 @@ { - "refund0" : { + "refund_getEtherBack" : { "env" : { "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", "currentNumber" : "0", @@ -33,5 +33,113 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - } + }, + + "refund_changeNonZeroStorage" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 1 ]] 23 }", + "storage" : { + "0x01" : "0x01" + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "850", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "refund_OOG" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 1 ]] 0 }", + "storage" : { + "0x01" : "0x01" + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "500", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "500", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "refund_NoOOG_1" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 1 ]] 0 }", + "storage" : { + "0x01" : "0x01" + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "502", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "502", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + } } From 23c46dd468f087881c89ee85ca1567f60d57ea5f Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Thu, 18 Dec 2014 09:50:45 +0100 Subject: [PATCH 577/641] style --- test/state.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/test/state.cpp b/test/state.cpp index 5bdfb419b..d8a3dd283 100644 --- a/test/state.cpp +++ b/test/state.cpp @@ -155,7 +155,6 @@ BOOST_AUTO_TEST_CASE(stRefundTest) dev::test::executeTests("stRefundTest", "/StateTests", dev::test::doStateTests); } - BOOST_AUTO_TEST_CASE(stCreateTest) { for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i) From 80368b870b55eac441e43a12b558361f04a5c1e6 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 17 Dec 2014 17:47:34 +0100 Subject: [PATCH 578/641] windows icon --- CMakeLists.txt | 4 ++++ alethzero/alethzero.ico | Bin 0 -> 370070 bytes 2 files changed, 4 insertions(+) create mode 100644 alethzero/alethzero.ico diff --git a/CMakeLists.txt b/CMakeLists.txt index 1293b4427..5763c9b85 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -165,6 +165,8 @@ if (WIN32) set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") set(CPACK_PACKAGE_VERSION "0.7") set(CPACK_GENERATOR "NSIS") + # seems to be not working + # set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/alethzero/alethzero.bmp") # our stuff set(CPACK_COMPONENT_ALETHZERO_GROUP "Applications") @@ -178,6 +180,8 @@ if (WIN32) set(CPACK_NSIS_URL_INFO_ABOUT "https://github.com/ethereum/cpp-ethereum") set(CPACK_NSIS_CONTACT "ethereum.org") set(CPACK_NSIS_MODIFY_PATH ON) + set(CPACK_NSIS_MUI_ICON "${CMAKE_CURRENT_SOURCE_DIR}/alethzero/alethzero.ico") + set(CPACK_NSIS_MUI_UNIICON "${CMAKE_CURRENT_SOURCE_DIR}/alethzero/alethzero.ico") include(CPack) endif (WIN32) diff --git a/alethzero/alethzero.ico b/alethzero/alethzero.ico new file mode 100644 index 0000000000000000000000000000000000000000..acee27751646c7054bd617e0be34ed1c4e55a1f3 GIT binary patch literal 370070 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 Date: Thu, 18 Dec 2014 14:39:16 +0100 Subject: [PATCH 579/641] Possibility to replace source and obtain ContractDefinition by name. --- libsolidity/CompilerStack.cpp | 12 ++++++++---- libsolidity/CompilerStack.h | 9 +++++++-- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/libsolidity/CompilerStack.cpp b/libsolidity/CompilerStack.cpp index 9fdc88baa..79716fdec 100644 --- a/libsolidity/CompilerStack.cpp +++ b/libsolidity/CompilerStack.cpp @@ -36,13 +36,12 @@ namespace dev namespace solidity { -void CompilerStack::addSource(string const& _name, string const& _content) +bool CompilerStack::addSource(string const& _name, string const& _content) { - if (m_sources.count(_name)) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Source by given name already exists.")); - + bool existed = m_sources.count(_name); reset(true); m_sources[_name].scanner = make_shared(CharStream(_content), _name); + return existed; } void CompilerStack::setSource(string const& _sourceCode) @@ -181,6 +180,11 @@ SourceUnit const& CompilerStack::getAST(string const& _sourceName) const return *getSource(_sourceName).ast; } +ContractDefinition const& CompilerStack::getContractDefinition(string const& _contractName) const +{ + return *getContract(_contractName).contract; +} + bytes CompilerStack::staticCompile(std::string const& _sourceCode, bool _optimize) { CompilerStack stack; diff --git a/libsolidity/CompilerStack.h b/libsolidity/CompilerStack.h index 5ad6f0a60..358c8fb77 100644 --- a/libsolidity/CompilerStack.h +++ b/libsolidity/CompilerStack.h @@ -57,7 +57,8 @@ public: CompilerStack(): m_parseSuccessful(false) {} /// Adds a source object (e.g. file) to the parser. After this, parse has to be called again. - void addSource(std::string const& _name, std::string const& _content); + /// @returns true if a source object by the name already existed and was replaced. + bool addSource(std::string const& _name, std::string const& _content); void setSource(std::string const& _sourceCode); /// Parses all source units that were added void parse(); @@ -86,9 +87,13 @@ public: /// Can be one of 3 types defined at @c DocumentationType std::string const& getJsonDocumentation(std::string const& _contractName, DocumentationType _type) const; - /// Returns the previously used scanner, useful for counting lines during error reporting. + /// @returns the previously used scanner, useful for counting lines during error reporting. Scanner const& getScanner(std::string const& _sourceName = "") const; + /// @returns the parsed source unit with the supplied name. SourceUnit const& getAST(std::string const& _sourceName = "") const; + /// @returns the parsed contract with the supplied name. Throws an exception if the contract + /// does not exist. + ContractDefinition const& getContractDefinition(std::string const& _contractName) const; /// Compile the given @a _sourceCode to bytecode. If a scanner is provided, it is used for /// scanning the source code - this is useful for printing exception information. From d19d4b29db7b6e958b473ab29278bc5ad700d9ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 18 Dec 2014 15:03:34 +0100 Subject: [PATCH 580/641] Update evmjit submodule: object cache speeds up recursive calls --- evmjit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evmjit b/evmjit index b37ce8e97..8287c6040 160000 --- a/evmjit +++ b/evmjit @@ -1 +1 @@ -Subproject commit b37ce8e9727683b8c7afb84520f42a908318f8d8 +Subproject commit 8287c6040a4900cb8b091ffbe284c7f478c60c49 From 6d48f3e98764fff270397fc00d37f9c6328294fd Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 17 Dec 2014 18:53:18 +0100 Subject: [PATCH 581/641] Work in progress for /** ... */ natspec comments - Work in progress on the scanner for recognizing the second type of doxygen comments for Natspec. --- libsolidity/Scanner.cpp | 58 +++++++++++++++++++++++++++++++++++++--- libsolidity/Scanner.h | 3 ++- test/solidityScanner.cpp | 7 +++++ 3 files changed, 63 insertions(+), 5 deletions(-) diff --git a/libsolidity/Scanner.cpp b/libsolidity/Scanner.cpp index 1a21149a1..2e9b7b454 100644 --- a/libsolidity/Scanner.cpp +++ b/libsolidity/Scanner.cpp @@ -219,7 +219,7 @@ Token::Value Scanner::skipSingleLineComment() return Token::WHITESPACE; } -Token::Value Scanner::scanDocumentationComment() +Token::Value Scanner::scanSingleLineDocComment() { LiteralScope literal(this, LITERAL_TYPE_COMMENT); advance(); //consume the last '/' @@ -250,7 +250,6 @@ Token::Value Scanner::scanDocumentationComment() Token::Value Scanner::skipMultiLineComment() { - solAssert(m_char == '*', ""); advance(); while (!isSourcePastEndOfInput()) { @@ -270,6 +269,43 @@ Token::Value Scanner::skipMultiLineComment() return Token::ILLEGAL; } +Token::Value Scanner::scanMultiLineDocComment() +{ + LiteralScope literal(this, LITERAL_TYPE_COMMENT); + bool endFound = false; + + advance(); //consume the last '*' + while (!isSourcePastEndOfInput()) + { + // skip starting '*' in multiine comments + if (isLineTerminator(m_char)) + { + skipWhitespace(); + if (!m_source.isPastEndOfInput(2) && m_source.get(1) == '*' && m_source.get(2) != '/') + { + addCommentLiteralChar('\n'); + m_char = m_source.advanceAndGet(3); + } + else + addCommentLiteralChar('\n'); + } + + if (!m_source.isPastEndOfInput(1) && m_source.get(0) == '*' && m_source.get(1) == '/') + { + m_source.advanceAndGet(2); + endFound = true; + break; + } + addCommentLiteralChar(m_char); + advance(); + } + literal.complete(); + if (!endFound) + return Token::ILLEGAL; + else + return Token::COMMENT_LITERAL; +} + void Scanner::scanToken() { m_nextToken.literal.clear(); @@ -381,7 +417,7 @@ void Scanner::scanToken() { Token::Value comment; m_nextSkippedComment.location.start = getSourcePos(); - comment = scanDocumentationComment(); + comment = scanSingleLineDocComment(); m_nextSkippedComment.location.end = getSourcePos(); m_nextSkippedComment.token = comment; token = Token::WHITESPACE; @@ -390,7 +426,21 @@ void Scanner::scanToken() token = skipSingleLineComment(); } else if (m_char == '*') - token = skipMultiLineComment(); + { + if (!advance()) /* slash star comment before EOS */ + token = Token::WHITESPACE; + else if (m_char == '*') + { + Token::Value comment; + m_nextSkippedComment.location.start = getSourcePos(); + comment = scanMultiLineDocComment(); + m_nextSkippedComment.location.end = getSourcePos(); + m_nextSkippedComment.token = comment; + token = Token::WHITESPACE; + } + else + token = skipMultiLineComment(); + } else if (m_char == '=') token = selectToken(Token::ASSIGN_DIV); else diff --git a/libsolidity/Scanner.h b/libsolidity/Scanner.h index 18b1f5d3a..7f1b18352 100644 --- a/libsolidity/Scanner.h +++ b/libsolidity/Scanner.h @@ -190,7 +190,8 @@ private: Token::Value scanIdentifierOrKeyword(); Token::Value scanString(); - Token::Value scanDocumentationComment(); + Token::Value scanSingleLineDocComment(); + Token::Value scanMultiLineDocComment(); /// Scans an escape-sequence which is part of a string and adds the /// decoded character to the current literal. Returns true if a pattern diff --git a/test/solidityScanner.cpp b/test/solidityScanner.cpp index 573affe6d..2b8c7c458 100644 --- a/test/solidityScanner.cpp +++ b/test/solidityScanner.cpp @@ -160,6 +160,13 @@ BOOST_AUTO_TEST_CASE(documentation_comments_parsed_begin) BOOST_CHECK_EQUAL(scanner.getCurrentCommentLiteral(), " Send $(value / 1000) chocolates to the user"); } +BOOST_AUTO_TEST_CASE(multiline_documentation_comments_parsed_begin) +{ + Scanner scanner(CharStream("/** Send $(value / 1000) chocolates to the user*/")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::EOS); + BOOST_CHECK_EQUAL(scanner.getCurrentCommentLiteral(), " Send $(value / 1000) chocolates to the user"); +} + BOOST_AUTO_TEST_CASE(documentation_comments_parsed) { Scanner scanner(CharStream("some other tokens /// Send $(value / 1000) chocolates to the user")); From 61a1f4436c5561a6c521b9c6009c57c76d275adb Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Thu, 18 Dec 2014 13:27:25 +0100 Subject: [PATCH 582/641] Scanner properly scans multiline natspec comments - Single and multiline natspect comments get the initial whitespace skipped now - Some rules introduced for the multiline comments. If first line is empty then no newline is added to the literal. Same thing with the last line. Finally in all lines initial '*' are skipped --- libsolidity/Scanner.cpp | 36 ++++++++++++++++++++++++++++-------- libsolidity/Scanner.h | 2 ++ test/solidityScanner.cpp | 25 ++++++++++++++++++++++--- 3 files changed, 52 insertions(+), 11 deletions(-) diff --git a/libsolidity/Scanner.cpp b/libsolidity/Scanner.cpp index 2e9b7b454..890d69494 100644 --- a/libsolidity/Scanner.cpp +++ b/libsolidity/Scanner.cpp @@ -209,6 +209,15 @@ bool Scanner::skipWhitespace() return getSourcePos() != startPosition; } +bool Scanner::skipWhitespaceExceptLF() +{ + int const startPosition = getSourcePos(); + while (m_char == ' ' || m_char == '\t') + advance(); + // Return whether or not we skipped any characters. + return getSourcePos() != startPosition; +} + Token::Value Scanner::skipSingleLineComment() { // The line terminator at the end of the line is not considered @@ -222,7 +231,8 @@ Token::Value Scanner::skipSingleLineComment() Token::Value Scanner::scanSingleLineDocComment() { LiteralScope literal(this, LITERAL_TYPE_COMMENT); - advance(); //consume the last '/' + advance(); //consume the last '/' at /// + skipWhitespaceExceptLF(); while (!isSourcePastEndOfInput()) { if (isLineTerminator(m_char)) @@ -273,18 +283,27 @@ Token::Value Scanner::scanMultiLineDocComment() { LiteralScope literal(this, LITERAL_TYPE_COMMENT); bool endFound = false; + bool charsAdded = false; - advance(); //consume the last '*' + advance(); //consume the last '*' at /** + skipWhitespaceExceptLF(); while (!isSourcePastEndOfInput()) { - // skip starting '*' in multiine comments + //handle newlines in multline comments if (isLineTerminator(m_char)) { skipWhitespace(); - if (!m_source.isPastEndOfInput(2) && m_source.get(1) == '*' && m_source.get(2) != '/') - { - addCommentLiteralChar('\n'); - m_char = m_source.advanceAndGet(3); + if (!m_source.isPastEndOfInput(1) && m_source.get(0) == '*' && m_source.get(1) != '/') + { // skip first '*' in subsequent lines + if (charsAdded) + addCommentLiteralChar('\n'); + m_char = m_source.advanceAndGet(2); + } + else if (!m_source.isPastEndOfInput(1) && m_source.get(0) == '*' && m_source.get(1) == '/') + { // if after newline the comment ends, don't insert the newline + m_char = m_source.advanceAndGet(2); + endFound = true; + break; } else addCommentLiteralChar('\n'); @@ -292,11 +311,12 @@ Token::Value Scanner::scanMultiLineDocComment() if (!m_source.isPastEndOfInput(1) && m_source.get(0) == '*' && m_source.get(1) == '/') { - m_source.advanceAndGet(2); + m_char = m_source.advanceAndGet(2); endFound = true; break; } addCommentLiteralChar(m_char); + charsAdded = true; advance(); } literal.complete(); diff --git a/libsolidity/Scanner.h b/libsolidity/Scanner.h index 7f1b18352..5e70db51d 100644 --- a/libsolidity/Scanner.h +++ b/libsolidity/Scanner.h @@ -182,6 +182,8 @@ private: /// Skips all whitespace and @returns true if something was skipped. bool skipWhitespace(); + /// Skips all whitespace except Line feeds and returns true if something was skipped + bool skipWhitespaceExceptLF(); Token::Value skipSingleLineComment(); Token::Value skipMultiLineComment(); diff --git a/test/solidityScanner.cpp b/test/solidityScanner.cpp index 2b8c7c458..159e53055 100644 --- a/test/solidityScanner.cpp +++ b/test/solidityScanner.cpp @@ -157,14 +157,14 @@ BOOST_AUTO_TEST_CASE(documentation_comments_parsed_begin) { Scanner scanner(CharStream("/// Send $(value / 1000) chocolates to the user")); BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::EOS); - BOOST_CHECK_EQUAL(scanner.getCurrentCommentLiteral(), " Send $(value / 1000) chocolates to the user"); + BOOST_CHECK_EQUAL(scanner.getCurrentCommentLiteral(), "Send $(value / 1000) chocolates to the user"); } BOOST_AUTO_TEST_CASE(multiline_documentation_comments_parsed_begin) { Scanner scanner(CharStream("/** Send $(value / 1000) chocolates to the user*/")); BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::EOS); - BOOST_CHECK_EQUAL(scanner.getCurrentCommentLiteral(), " Send $(value / 1000) chocolates to the user"); + BOOST_CHECK_EQUAL(scanner.getCurrentCommentLiteral(), "Send $(value / 1000) chocolates to the user"); } BOOST_AUTO_TEST_CASE(documentation_comments_parsed) @@ -174,7 +174,19 @@ BOOST_AUTO_TEST_CASE(documentation_comments_parsed) BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); - BOOST_CHECK_EQUAL(scanner.getCurrentCommentLiteral(), " Send $(value / 1000) chocolates to the user"); + BOOST_CHECK_EQUAL(scanner.getCurrentCommentLiteral(), "Send $(value / 1000) chocolates to the user"); +} + +BOOST_AUTO_TEST_CASE(multiline_documentation_comments_parsed) +{ + Scanner scanner(CharStream("some other tokens /**\n" + "* Send $(value / 1000) chocolates to the user\n" + "*/")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); + BOOST_CHECK_EQUAL(scanner.getCurrentCommentLiteral(), "Send $(value / 1000) chocolates to the user"); } BOOST_AUTO_TEST_CASE(comment_before_eos) @@ -191,6 +203,13 @@ BOOST_AUTO_TEST_CASE(documentation_comment_before_eos) BOOST_CHECK_EQUAL(scanner.getCurrentCommentLiteral(), ""); } +BOOST_AUTO_TEST_CASE(empty_multiline_documentation_comment_before_eos) +{ + Scanner scanner(CharStream("/***/")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::EOS); + BOOST_CHECK_EQUAL(scanner.getCurrentCommentLiteral(), ""); +} + BOOST_AUTO_TEST_CASE(comments_mixed_in_sequence) { Scanner scanner(CharStream("hello_world ///documentation comment \n" From 30beaca35955476ef07ee1f9c82735b0d63241bf Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Thu, 18 Dec 2014 14:43:35 +0100 Subject: [PATCH 583/641] Changes in InterfaceHandler to deal with multiline natspec - Also now Solidity scanner considers Carriage Return as whitespace - Tests for Natspec generation with the new multiline comments --- libsolidity/InterfaceHandler.cpp | 46 +++++++++++++------------------- libsolidity/InterfaceHandler.h | 3 ++- libsolidity/Scanner.cpp | 2 +- test/solidityNatspecJSON.cpp | 29 ++++++++++++++++++++ 4 files changed, 51 insertions(+), 29 deletions(-) diff --git a/libsolidity/InterfaceHandler.cpp b/libsolidity/InterfaceHandler.cpp index c734fa38c..9ae284b40 100644 --- a/libsolidity/InterfaceHandler.cpp +++ b/libsolidity/InterfaceHandler.cpp @@ -166,9 +166,12 @@ static inline std::string::const_iterator skipLineOrEOS(std::string::const_itera std::string::const_iterator InterfaceHandler::parseDocTagLine(std::string::const_iterator _pos, std::string::const_iterator _end, std::string& _tagString, - DocTagType _tagType) + DocTagType _tagType, + bool _appending) { auto nlPos = std::find(_pos, _end, '\n'); + if (_appending && *_pos != ' ') + _tagString += " "; std::copy(_pos, nlPos, back_inserter(_tagString)); m_lastTag = _tagType; return skipLineOrEOS(nlPos, _end); @@ -201,7 +204,8 @@ std::string::const_iterator InterfaceHandler::appendDocTagParam(std::string::con solAssert(!m_params.empty(), "Internal: Tried to append to empty parameter"); auto pair = m_params.back(); - pair.second += " "; + if (*_pos != ' ') + pair.second += " "; auto nlPos = std::find(_pos, _end, '\n'); std::copy(_pos, nlPos, back_inserter(pair.second)); @@ -221,17 +225,17 @@ std::string::const_iterator InterfaceHandler::parseDocTag(std::string::const_ite if (m_lastTag == DocTagType::NONE || _tag != "") { if (_tag == "dev") - return parseDocTagLine(_pos, _end, m_dev, DocTagType::DEV); + return parseDocTagLine(_pos, _end, m_dev, DocTagType::DEV, false); else if (_tag == "notice") - return parseDocTagLine(_pos, _end, m_notice, DocTagType::NOTICE); + return parseDocTagLine(_pos, _end, m_notice, DocTagType::NOTICE, false); else if (_tag == "return") - return parseDocTagLine(_pos, _end, m_return, DocTagType::RETURN); + return parseDocTagLine(_pos, _end, m_return, DocTagType::RETURN, false); else if (_tag == "author") { if (_owner == CommentOwner::CONTRACT) - return parseDocTagLine(_pos, _end, m_contractAuthor, DocTagType::AUTHOR); + return parseDocTagLine(_pos, _end, m_contractAuthor, DocTagType::AUTHOR, false); else if (_owner == CommentOwner::FUNCTION) - return parseDocTagLine(_pos, _end, m_author, DocTagType::AUTHOR); + return parseDocTagLine(_pos, _end, m_author, DocTagType::AUTHOR, false); else // LTODO: for now this else makes no sense but later comments will go to more language constructs BOOST_THROW_EXCEPTION(DocstringParsingError() << errinfo_comment("@author tag is legal only for contracts")); @@ -239,7 +243,7 @@ std::string::const_iterator InterfaceHandler::parseDocTag(std::string::const_ite else if (_tag == "title") { if (_owner == CommentOwner::CONTRACT) - return parseDocTagLine(_pos, _end, m_title, DocTagType::TITLE); + return parseDocTagLine(_pos, _end, m_title, DocTagType::TITLE, false); else // LTODO: Unknown tag, throw some form of warning and not just an exception BOOST_THROW_EXCEPTION(DocstringParsingError() << errinfo_comment("@title tag is legal only for contracts")); @@ -261,34 +265,22 @@ std::string::const_iterator InterfaceHandler::appendDocTag(std::string::const_it switch (m_lastTag) { case DocTagType::DEV: - m_dev += " "; - return parseDocTagLine(_pos, _end, m_dev, DocTagType::DEV); + return parseDocTagLine(_pos, _end, m_dev, DocTagType::DEV, true); case DocTagType::NOTICE: - m_notice += " "; - return parseDocTagLine(_pos, _end, m_notice, DocTagType::NOTICE); + return parseDocTagLine(_pos, _end, m_notice, DocTagType::NOTICE, true); case DocTagType::RETURN: - m_return += " "; - return parseDocTagLine(_pos, _end, m_return, DocTagType::RETURN); + return parseDocTagLine(_pos, _end, m_return, DocTagType::RETURN, true); case DocTagType::AUTHOR: if (_owner == CommentOwner::CONTRACT) - { - m_contractAuthor += " "; - return parseDocTagLine(_pos, _end, m_contractAuthor, DocTagType::AUTHOR); - } + return parseDocTagLine(_pos, _end, m_contractAuthor, DocTagType::AUTHOR, true); else if (_owner == CommentOwner::FUNCTION) - { - m_author += " "; - return parseDocTagLine(_pos, _end, m_author, DocTagType::AUTHOR); - } + return parseDocTagLine(_pos, _end, m_author, DocTagType::AUTHOR, true); else // LTODO: Unknown tag, throw some form of warning and not just an exception BOOST_THROW_EXCEPTION(DocstringParsingError() << errinfo_comment("@author tag in illegal comment")); case DocTagType::TITLE: if (_owner == CommentOwner::CONTRACT) - { - m_title += " "; - return parseDocTagLine(_pos, _end, m_title, DocTagType::TITLE); - } + return parseDocTagLine(_pos, _end, m_title, DocTagType::TITLE, true); else // LTODO: Unknown tag, throw some form of warning and not just an exception BOOST_THROW_EXCEPTION(DocstringParsingError() << errinfo_comment("@title tag in illegal comment")); @@ -329,7 +321,7 @@ void InterfaceHandler::parseDocString(std::string const& _string, CommentOwner _ currPos = parseDocTag(tagNameEndPos + 1, end, std::string(tagPos + 1, tagNameEndPos), _owner); } else if (m_lastTag != DocTagType::NONE) // continuation of the previous tag - currPos = appendDocTag(currPos + 1, end, _owner); + currPos = appendDocTag(currPos, end, _owner); else if (currPos != end) // skip the line if a newline was found currPos = nlPos + 1; } diff --git a/libsolidity/InterfaceHandler.h b/libsolidity/InterfaceHandler.h index d271a6697..c8399d71f 100644 --- a/libsolidity/InterfaceHandler.h +++ b/libsolidity/InterfaceHandler.h @@ -92,7 +92,8 @@ private: std::string::const_iterator parseDocTagLine(std::string::const_iterator _pos, std::string::const_iterator _end, std::string& _tagString, - DocTagType _tagType); + DocTagType _tagType, + bool _appending); std::string::const_iterator parseDocTagParam(std::string::const_iterator _pos, std::string::const_iterator _end); std::string::const_iterator appendDocTagParam(std::string::const_iterator _pos, diff --git a/libsolidity/Scanner.cpp b/libsolidity/Scanner.cpp index 890d69494..69b61ce4b 100644 --- a/libsolidity/Scanner.cpp +++ b/libsolidity/Scanner.cpp @@ -80,7 +80,7 @@ bool isLineTerminator(char c) } bool isWhiteSpace(char c) { - return c == ' ' || c == '\n' || c == '\t'; + return c == ' ' || c == '\n' || c == '\t' || c == '\r'; } bool isIdentifierStart(char c) { diff --git a/test/solidityNatspecJSON.cpp b/test/solidityNatspecJSON.cpp index 2c3ded08d..5b48a67ce 100644 --- a/test/solidityNatspecJSON.cpp +++ b/test/solidityNatspecJSON.cpp @@ -394,6 +394,35 @@ BOOST_AUTO_TEST_CASE(dev_multiline_return) checkNatspec(sourceCode, natspec, false); } +BOOST_AUTO_TEST_CASE(dev_multiline_comment) +{ + char const* sourceCode = "contract test {\n" + " /**\n" + " * @dev Multiplies a number by 7 and adds second parameter\n" + " * @param a Documentation for the first parameter starts here.\n" + " * Since it's a really complicated parameter we need 2 lines\n" + " * @param second Documentation for the second parameter\n" + " * @return The result of the multiplication\n" + " * and cookies with nutella\n" + " */" + " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" + "}\n"; + + char const* natspec = "{" + "\"methods\":{" + " \"mul\":{ \n" + " \"details\": \"Multiplies a number by 7 and adds second parameter\",\n" + " \"params\": {\n" + " \"a\": \"Documentation for the first parameter starts here. Since it's a really complicated parameter we need 2 lines\",\n" + " \"second\": \"Documentation for the second parameter\"\n" + " },\n" + " \"return\": \"The result of the multiplication and cookies with nutella\"\n" + " }\n" + "}}"; + + checkNatspec(sourceCode, natspec, false); +} + BOOST_AUTO_TEST_CASE(dev_contract_no_doc) { char const* sourceCode = "contract test {\n" From 8edb5b8b54f1c023f68688f6ac52d9878975b8a7 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Thu, 18 Dec 2014 15:21:03 +0100 Subject: [PATCH 584/641] Solidity Tests names are now more consistent - File names and Boost Test Suite have the same name now for every solidity Test, so that there is no need to guess or check when you want to run a specific suite from the command line --- test/{solidityJSONInterfaceTest.cpp => SolidityABIJSON.cpp} | 0 test/{solidityCompiler.cpp => SolidityCompiler.cpp} | 0 test/{solidityEndToEndTest.cpp => SolidityEndToEndTest.cpp} | 2 +- ...ityExpressionCompiler.cpp => SolidityExpressionCompiler.cpp} | 0 ...eAndTypeResolution.cpp => SolidityNameAndTypeResolution.cpp} | 0 test/{solidityNatspecJSON.cpp => SolidityNatspecJSON.cpp} | 0 test/{solidityOptimizerTest.cpp => SolidityOptimizer.cpp} | 2 +- test/{solidityParser.cpp => SolidityParser.cpp} | 0 test/{solidityScanner.cpp => SolidityScanner.cpp} | 0 9 files changed, 2 insertions(+), 2 deletions(-) rename test/{solidityJSONInterfaceTest.cpp => SolidityABIJSON.cpp} (100%) rename test/{solidityCompiler.cpp => SolidityCompiler.cpp} (100%) rename test/{solidityEndToEndTest.cpp => SolidityEndToEndTest.cpp} (99%) rename test/{solidityExpressionCompiler.cpp => SolidityExpressionCompiler.cpp} (100%) rename test/{solidityNameAndTypeResolution.cpp => SolidityNameAndTypeResolution.cpp} (100%) rename test/{solidityNatspecJSON.cpp => SolidityNatspecJSON.cpp} (100%) rename test/{solidityOptimizerTest.cpp => SolidityOptimizer.cpp} (98%) rename test/{solidityParser.cpp => SolidityParser.cpp} (100%) rename test/{solidityScanner.cpp => SolidityScanner.cpp} (100%) diff --git a/test/solidityJSONInterfaceTest.cpp b/test/SolidityABIJSON.cpp similarity index 100% rename from test/solidityJSONInterfaceTest.cpp rename to test/SolidityABIJSON.cpp diff --git a/test/solidityCompiler.cpp b/test/SolidityCompiler.cpp similarity index 100% rename from test/solidityCompiler.cpp rename to test/SolidityCompiler.cpp diff --git a/test/solidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp similarity index 99% rename from test/solidityEndToEndTest.cpp rename to test/SolidityEndToEndTest.cpp index 26f5528ab..aa74f8186 100644 --- a/test/solidityEndToEndTest.cpp +++ b/test/SolidityEndToEndTest.cpp @@ -36,7 +36,7 @@ namespace solidity namespace test { -BOOST_FIXTURE_TEST_SUITE(SolidityCompilerEndToEndTest, ExecutionFramework) +BOOST_FIXTURE_TEST_SUITE(SolidityEndToEndTest, ExecutionFramework) BOOST_AUTO_TEST_CASE(smoke_test) { diff --git a/test/solidityExpressionCompiler.cpp b/test/SolidityExpressionCompiler.cpp similarity index 100% rename from test/solidityExpressionCompiler.cpp rename to test/SolidityExpressionCompiler.cpp diff --git a/test/solidityNameAndTypeResolution.cpp b/test/SolidityNameAndTypeResolution.cpp similarity index 100% rename from test/solidityNameAndTypeResolution.cpp rename to test/SolidityNameAndTypeResolution.cpp diff --git a/test/solidityNatspecJSON.cpp b/test/SolidityNatspecJSON.cpp similarity index 100% rename from test/solidityNatspecJSON.cpp rename to test/SolidityNatspecJSON.cpp diff --git a/test/solidityOptimizerTest.cpp b/test/SolidityOptimizer.cpp similarity index 98% rename from test/solidityOptimizerTest.cpp rename to test/SolidityOptimizer.cpp index 388e0579c..ef5c6f9b5 100644 --- a/test/solidityOptimizerTest.cpp +++ b/test/SolidityOptimizer.cpp @@ -71,7 +71,7 @@ protected: Address m_nonOptimizedContract; }; -BOOST_FIXTURE_TEST_SUITE(SolidityOptimizerTest, OptimizerTestFramework) +BOOST_FIXTURE_TEST_SUITE(SolidityOptimizer, OptimizerTestFramework) BOOST_AUTO_TEST_CASE(smoke_test) { diff --git a/test/solidityParser.cpp b/test/SolidityParser.cpp similarity index 100% rename from test/solidityParser.cpp rename to test/SolidityParser.cpp diff --git a/test/solidityScanner.cpp b/test/SolidityScanner.cpp similarity index 100% rename from test/solidityScanner.cpp rename to test/SolidityScanner.cpp From 2e3d45004681407393f0742bec6d9ed463211dcf Mon Sep 17 00:00:00 2001 From: ethdev Date: Thu, 18 Dec 2014 15:39:15 +0100 Subject: [PATCH 585/641] copy qml dependencies of mix to install directory --- cmake/EthExecutableHelper.cmake | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/cmake/EthExecutableHelper.cmake b/cmake/EthExecutableHelper.cmake index 0ec1e10d4..5f4ae3c09 100644 --- a/cmake/EthExecutableHelper.cmake +++ b/cmake/EthExecutableHelper.cmake @@ -60,7 +60,11 @@ macro(eth_install_executable EXECUTABLE) cmake_parse_arguments (ETH_INSTALL_EXECUTABLE "${options}" "${one_value_args}" "${multi_value_args}" "${extra_macro_args}") if (ETH_INSTALL_EXECUTABLE_QMLDIR) - set(eth_qml_dir "-qmldir=${ETH_INSTALL_EXECUTABLE_QMLDIR}") + if (APPLE) + set(eth_qml_dir "-qmldir=${ETH_INSTALL_EXECUTABLE_QMLDIR}") + elseif (WIN32) + set(eth_qml_dir --qmldir ${ETH_INSTALL_EXECUTABLE_QMLDIR}) + endif() message(STATUS "${EXECUTABLE} qmldir: ${eth_qml_dir}") endif() @@ -68,7 +72,8 @@ macro(eth_install_executable EXECUTABLE) # First have qt5 install plugins and frameworks add_custom_command(TARGET ${EXECUTABLE} POST_BUILD COMMAND ${MACDEPLOYQT_APP} ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app ${eth_qml_dir} - WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} + ) # This tool and next will inspect linked libraries in order to determine which dependencies are required if (${CMAKE_CFG_INTDIR} STREQUAL ".") @@ -108,6 +113,13 @@ macro(eth_install_executable EXECUTABLE) $/platforms ) + # ugly way, improve that + add_custom_command(TARGET ${EXECUTABLE} POST_BUILD + COMMAND cmake -E copy_directory + "${ETH_DEPENDENCY_INSTALL_DIR}/qml" + $ + ) + install( FILES ${DLLS} DESTINATION bin COMPONENT ${EXECUTABLE} @@ -118,6 +130,14 @@ macro(eth_install_executable EXECUTABLE) COMPONENT ${EXECUTABLE} ) + file (GLOB QMLS ${ETH_DEPENDENCY_INSTALL_DIR}/qml/*) + foreach(QML ${QMLS}) + install( DIRECTORY ${QML} + DESTINATION bin + COMPONENT ${EXECUTABLE} + ) + endforeach() + install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin COMPONENT ${EXECUTABLE} From 23d4f98b744887bdc1f1952bf303651ac6573e3e Mon Sep 17 00:00:00 2001 From: ethdev Date: Thu, 18 Dec 2014 15:50:23 +0100 Subject: [PATCH 586/641] alethzero.exe icon --- alethzero/CMakeLists.txt | 1 + alethzero/alethzero.rc | 1 + cmake/EthExecutableHelper.cmake | 4 ++-- 3 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 alethzero/alethzero.rc diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index 39c02d6be..8c8a37a42 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -27,6 +27,7 @@ endif () eth_add_executable(${EXECUTABLE} ICON alethzero UI_RESOURCES alethzero.icns Main.ui + WIN_RESOURCES alethzero.rc ) add_dependencies(${EXECUTABLE} BuildInfo.h) diff --git a/alethzero/alethzero.rc b/alethzero/alethzero.rc new file mode 100644 index 000000000..29c778bd4 --- /dev/null +++ b/alethzero/alethzero.rc @@ -0,0 +1 @@ +APP_ICON ICON DISCARDABLE "alethzero.ico" \ No newline at end of file diff --git a/cmake/EthExecutableHelper.cmake b/cmake/EthExecutableHelper.cmake index 5f4ae3c09..88e2a3e16 100644 --- a/cmake/EthExecutableHelper.cmake +++ b/cmake/EthExecutableHelper.cmake @@ -18,7 +18,7 @@ macro(eth_add_executable EXECUTABLE) set (extra_macro_args ${ARGN}) set (options) set (one_value_args ICON) - set (multi_value_args UI_RESOURCES) + set (multi_value_args UI_RESOURCES WIN_RESOURCES) cmake_parse_arguments (ETH_ADD_EXECUTABLE "${options}" "${one_value_args}" "${multi_value_args}" "${extra_macro_args}") if (APPLE) @@ -38,7 +38,7 @@ macro(eth_add_executable EXECUTABLE) set_source_files_properties(${MACOSX_BUNDLE_ICON_FILE}.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources) else () - add_executable(${EXECUTABLE} ${ETH_ADD_EXECUTABLE_UI_RESOURCES} ${SRC_LIST} ${HEADERS}) + add_executable(${EXECUTABLE} ${ETH_ADD_EXECUTABLE_UI_RESOURCES} ${ETH_ADD_EXECUTABLE_WIN_RESOURCES} ${SRC_LIST} ${HEADERS}) endif() endmacro() From b657b009ef7a272d105f92fbc0d3d6e449664fd3 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 18 Dec 2014 16:03:59 +0100 Subject: [PATCH 587/641] Cleanups and YP formalism. --- libethereum/Transaction.cpp | 4 ++-- libevm/VM.h | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/libethereum/Transaction.cpp b/libethereum/Transaction.cpp index 0c1173134..24c56930e 100644 --- a/libethereum/Transaction.cpp +++ b/libethereum/Transaction.cpp @@ -43,9 +43,9 @@ Transaction::Transaction(bytesConstRef _rlpData, bool _checkSender) m_receiveAddress = rlp[field = 3].toHash
(); m_value = rlp[field = 4].toInt(); m_data = rlp[field = 5].toBytes(); + byte v = rlp[field = 6].toInt() - 27; h256 r = rlp[field = 7].toInt(); h256 s = rlp[field = 8].toInt(); - byte v = rlp[field = 6].toInt() - 27; m_vrs = SignatureStruct{ r, s, v }; if (_checkSender) m_sender = sender(); @@ -74,7 +74,7 @@ Address Transaction::sender() const { if (!m_sender) { - auto p = recover(*(Signature const*)&m_vrs, sha3(WithoutSignature)); + auto p = recover(m_vrs, sha3(WithoutSignature)); if (!p) BOOST_THROW_EXCEPTION(InvalidSignature()); m_sender = right160(dev::sha3(bytesConstRef(p.data(), sizeof(p)))); diff --git a/libevm/VM.h b/libevm/VM.h index 3eb330fcd..1f3fc17d5 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -217,6 +217,8 @@ inline bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _st require(7); runGas = (bigint)c_callGas + m_stack[m_stack.size() - 1]; newTempSize = std::max(memNeed(m_stack[m_stack.size() - 6], m_stack[m_stack.size() - 7]), memNeed(m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5])); + if (_ext.depth == 1024) + BOOST_THROW_EXCEPTION(OutOfGas()); break; case Instruction::CREATE: @@ -226,6 +228,8 @@ inline bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _st u256 inSize = m_stack[m_stack.size() - 3]; newTempSize = (bigint)inOff + inSize; runGas = c_createGas; + if (_ext.depth == 1024) + BOOST_THROW_EXCEPTION(OutOfGas()); break; } case Instruction::EXP: @@ -566,6 +570,7 @@ inline bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _st break; default: // this is unreachable, but if someone introduces a bug in the future, he may get here. + assert(false); BOOST_THROW_EXCEPTION(InvalidOpcode() << errinfo_comment("CALLDATACOPY, CODECOPY or EXTCODECOPY instruction requested.")); break; } @@ -795,8 +800,6 @@ inline bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _st if (_ext.balance(_ext.myAddress) >= endowment) { - if (_ext.depth == 1024) - BOOST_THROW_EXCEPTION(OutOfGas()); _ext.subBalance(endowment); m_stack.push_back((u160)_ext.create(endowment, m_gas, bytesConstRef(m_temp.data() + initOff, initSize), _onOp)); } @@ -825,8 +828,6 @@ inline bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _st if (_ext.balance(_ext.myAddress) >= value) { - if (_ext.depth == 1024) - BOOST_THROW_EXCEPTION(OutOfGas()); _ext.subBalance(value); m_stack.push_back(_ext.call(inst == Instruction::CALL ? receiveAddress : _ext.myAddress, value, bytesConstRef(m_temp.data() + inOff, inSize), gas, bytesRef(m_temp.data() + outOff, outSize), _onOp, {}, receiveAddress)); } From 71b267d01aaa32786dfbb3dccf520d86f2f77708 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 18 Dec 2014 16:25:44 +0100 Subject: [PATCH 588/641] Update serpent. --- libserpent/bignum.h | 3 + libserpent/compiler.cpp | 279 +++------ libserpent/opcodes.h | 123 +--- libserpent/parser.cpp | 86 +-- libserpent/rewriter.cpp | 1206 +++++++++++++++------------------------ libserpent/tokenize.cpp | 4 +- libserpent/util.cpp | 57 +- libserpent/util.h | 36 +- sc/cmdline.cpp | 13 + 9 files changed, 709 insertions(+), 1098 deletions(-) diff --git a/libserpent/bignum.h b/libserpent/bignum.h index 599365b6c..99571acd2 100644 --- a/libserpent/bignum.h +++ b/libserpent/bignum.h @@ -35,4 +35,7 @@ bool decimalGt(std::string a, std::string b, bool eqAllowed=false); unsigned decimalToUnsigned(std::string a); +#define utd unsignedToDecimal +#define dtu decimalToUnsigned + #endif diff --git a/libserpent/compiler.cpp b/libserpent/compiler.cpp index 30628fbc9..a3e5b1c60 100644 --- a/libserpent/compiler.cpp +++ b/libserpent/compiler.cpp @@ -6,6 +6,7 @@ #include "bignum.h" #include "opcodes.h" +// Auxiliary data that is gathered while compiling struct programAux { std::map vars; int nextVarMem; @@ -13,15 +14,19 @@ struct programAux { bool calldataUsed; int step; int labelLength; - int functionCount; }; +// Auxiliary data that gets passed down vertically +// but not back up struct programVerticalAux { int height; + std::string innerScopeName; std::map dupvars; std::map funvars; + std::vector scopes; }; +// Compilation result struct programData { programAux aux; Node code; @@ -34,7 +39,6 @@ programAux Aux() { o.calldataUsed = false; o.step = 0; o.nextVarMem = 32; - o.functionCount = 0; return o; } @@ -43,6 +47,7 @@ programVerticalAux verticalAux() { o.height = 0; o.dupvars = std::map(); o.funvars = std::map(); + o.scopes = std::vector(); return o; } @@ -72,29 +77,58 @@ Node popwrap(Node node) { return multiToken(nodelist, 2, node.metadata); } +// Grabs variables +mss getVariables(Node node, mss cur=mss()) { + Metadata m = node.metadata; + // Tokens don't contain any variables + if (node.type == TOKEN) + return cur; + // Don't descend into call fragments + else if (node.val == "lll") + return getVariables(node.args[1], cur); + // At global scope get/set/ref also declare + else if (node.val == "get" || node.val == "set" || node.val == "ref") { + if (node.args[0].type != TOKEN) + err("Variable name must be simple token," + " not complex expression! " + printSimple(node.args[0]), m); + if (!cur.count(node.args[0].val)) { + cur[node.args[0].val] = utd(cur.size() * 32 + 32); + //std::cerr << node.args[0].val << " " << cur[node.args[0].val] << "\n"; + } + } + // Recursively process children + for (unsigned i = 0; i < node.args.size(); i++) { + cur = getVariables(node.args[i], cur); + } + return cur; +} + // Turns LLL tree into tree of code fragments programData opcodeify(Node node, programAux aux=Aux(), programVerticalAux vaux=verticalAux()) { std::string symb = "_"+mkUniqueToken(); Metadata m = node.metadata; + // Get variables + if (!aux.vars.size()) { + aux.vars = getVariables(node); + aux.nextVarMem = aux.vars.size() * 32 + 32; + } // Numbers if (node.type == TOKEN) { return pd(aux, nodeToNumeric(node), 1); } - else if (node.val == "ref" || node.val == "get" || - node.val == "set" || node.val == "declare") { + else if (node.val == "ref" || node.val == "get" || node.val == "set") { std::string varname = node.args[0].val; - if (!aux.vars.count(varname)) { - aux.vars[varname] = unsignedToDecimal(aux.nextVarMem); - aux.nextVarMem += 32; - } - if (varname == "'msg.data") aux.calldataUsed = true; + // Determine reference to variable + Node varNode = tkn(aux.vars[varname], m); + //std::cerr << varname << " " << printSimple(varNode) << "\n"; // Set variable if (node.val == "set") { programData sub = opcodeify(node.args[1], aux, vaux); if (!sub.outs) err("Value to set variable must have nonzero arity!", m); + // What if we are setting a stack variable? if (vaux.dupvars.count(node.args[0].val)) { int h = vaux.height - vaux.dupvars[node.args[0].val]; if (h > 16) err("Too deep for stack variable (max 16)", m); @@ -105,149 +139,65 @@ programData opcodeify(Node node, }; return pd(sub.aux, multiToken(nodelist, 3, m), 0); } - Node nodelist[] = { - sub.code, - token(sub.aux.vars[varname], m), - token("MSTORE", m), - }; - return pd(sub.aux, multiToken(nodelist, 3, m), 0); + // Setting a memory variable + else { + Node nodelist[] = { + sub.code, + varNode, + token("MSTORE", m), + }; + return pd(sub.aux, multiToken(nodelist, 3, m), 0); + } } // Get variable else if (node.val == "get") { - if (vaux.dupvars.count(node.args[0].val)) { + // Getting a stack variable + if (vaux.dupvars.count(node.args[0].val)) { int h = vaux.height - vaux.dupvars[node.args[0].val]; if (h > 16) err("Too deep for stack variable (max 16)", m); return pd(aux, token("DUP"+unsignedToDecimal(h)), 1); } - Node nodelist[] = - { token(aux.vars[varname], m), token("MLOAD", m) }; - return pd(aux, multiToken(nodelist, 2, m), 1); + // Getting a memory variable + else { + Node nodelist[] = + { varNode, token("MLOAD", m) }; + return pd(aux, multiToken(nodelist, 2, m), 1); + } } // Refer variable else if (node.val == "ref") { if (vaux.dupvars.count(node.args[0].val)) err("Cannot ref stack variable!", m); - return pd(aux, token(aux.vars[varname], m), 1); - } - // Declare variable - else { - return pd(aux, multiToken(nullptr, 0, m), 0); + return pd(aux, varNode, 1); } } - // Define functions (TODO: eventually move to rewriter.cpp, keep - // compiler pure LLL) - if (node.val == "def") { - std::vector varNames; - std::vector varSizes; - bool useLt32 = false; - int totalSz = 0; - if (node.args.size() != 2) - err("Malformed def!", m); - // Collect the list of variable names and variable byte counts - for (unsigned i = 0; i < node.args[0].args.size(); i++) { - if (node.args[0].args[i].val == "kv") { - if (node.args[0].args[i].args.size() != 2) - err("Malformed def!", m); - varNames.push_back(node.args[0].args[i].args[0].val); - varSizes.push_back( - decimalToUnsigned(node.args[0].args[i].args[1].val)); - if (varSizes.back() > 32) - err("Max argument width: 32 bytes", m); - useLt32 = true; + // Comments do nothing + else if (node.val == "comment") { + Node nodelist[] = { }; + return pd(aux, multiToken(nodelist, 0, m), 0); + } + // Custom operation sequence + // eg. (ops bytez id msize swap1 msize add 0 swap1 mstore) == alloc + if (node.val == "ops") { + std::vector subs2; + int depth = 0; + for (unsigned i = 0; i < node.args.size(); i++) { + std::string op = upperCase(node.args[i].val); + if (node.args[i].type == ASTNODE || opinputs(op) == -1) { + programVerticalAux vaux2 = vaux; + vaux2.height = vaux.height - i - 1 + node.args.size(); + programData sub = opcodeify(node.args[i], aux, vaux2); + aux = sub.aux; + depth += sub.outs; + subs2.push_back(sub.code); } else { - varNames.push_back(node.args[0].args[i].val); - varSizes.push_back(32); + subs2.push_back(token(op, m)); + depth += opoutputs(op) - opinputs(op); } - aux.vars[varNames.back()] = unsignedToDecimal(aux.nextVarMem + 32 * i); - totalSz += varSizes.back(); } - int functionCount = aux.functionCount; - int nextVarMem = aux.nextVarMem; - aux.nextVarMem += 32 * varNames.size(); - aux.functionCount += 1; - programData inner; - // If we're only using 32-byte variables, then great, just copy - // over the calldata! - if (!useLt32) { - programData sub = opcodeify(node.args[1], aux, vaux); - Node nodelist[] = { - token(unsignedToDecimal(totalSz), m), - token("1", m), - token(unsignedToDecimal(nextVarMem), m), - token("CALLDATACOPY", m), - sub.code - }; - inner = pd(sub.aux, multiToken(nodelist, 5, m), 0); - } - else { - std::vector innerList; - int cum = 1; - for (unsigned i = 0; i < varNames.size();) { - // If we get a series of 32-byte values, we calldatacopy them - if (varSizes[i] == 32) { - unsigned until = i+1; - while (until < varNames.size() && varSizes[until] == 32) - until += 1; - innerList.push_back(token(unsignedToDecimal((until - i) * 32), m)); - innerList.push_back(token(unsignedToDecimal(cum), m)); - innerList.push_back(token(unsignedToDecimal(nextVarMem + i * 32), m)); - innerList.push_back(token("CALLDATACOPY", m)); - cum += (until - i) * 32; - i = until; - } - // Otherwise, we do a clever trick to extract the value - else { - innerList.push_back(token(unsignedToDecimal(32 - varSizes[i]), m)); - innerList.push_back(token("256", m)); - innerList.push_back(token("EXP", m)); - innerList.push_back(token(unsignedToDecimal(cum), m)); - innerList.push_back(token("CALLDATALOAD", m)); - innerList.push_back(token("DIV", m)); - innerList.push_back(token(unsignedToDecimal(nextVarMem + i * 32), m)); - innerList.push_back(token("MSTORE", m)); - cum += varSizes[i]; - i += 1; - } - } - // If caller == origin, then it's from a tx, so unpack, otherwise - // plain copy - programData sub = opcodeify(node.args[1], aux, vaux); - Node ilnode = astnode("", innerList, m); - Node nodelist[] = { - token(unsignedToDecimal(32 * varNames.size()), m), - token("1", m), - token(unsignedToDecimal(nextVarMem), m), - token("CALLDATACOPY", m), - token("CALLER", m), - token("ORIGIN", m), - token("EQ", m), - token("ISZERO", m), - token("$maincode"+symb, m), - token("JUMPI", m), - ilnode, - token("~maincode"+symb, m), - token("JUMPDEST", m), - sub.code - }; - inner = pd(sub.aux, multiToken(nodelist, 14, m), 0); - } - // Check if the function call byte is the same - Node nodelist2[] = { - token("0", m), - token("CALLDATALOAD", m), - token("0", m), - token("BYTE", m), - token(unsignedToDecimal(functionCount), m), - token("EQ", m), - token("ISZERO", m), - token("$endcode"+symb, m), - token("JUMPI", m), - inner.code, - token("~endcode"+symb, m), - token("JUMPDEST", m), - }; - return pd(inner.aux, multiToken(nodelist2, 12, m), 0); + if (depth < 0 || depth > 1) err("Stack depth mismatch", m); + return pd(aux, astnode("_", subs2, m), 0); } // Code blocks if (node.val == "lll" && node.args.size() == 2) { @@ -372,49 +322,14 @@ programData opcodeify(Node node, }; return pd(aux, multiToken(nodelist, 8, m), 1); } - // Array literals - else if (node.val == "array_lit") { - aux.allocUsed = true; - std::vector nodes; - if (!node.args.size()) { - nodes.push_back(token("MSIZE", m)); - return pd(aux, astnode("_", nodes, m)); - } - nodes.push_back(token("MSIZE", m)); - nodes.push_back(token("0", m)); - nodes.push_back(token("MSIZE", m)); - nodes.push_back(token(unsignedToDecimal(node.args.size() * 32 - 1), m)); - nodes.push_back(token("ADD", m)); - nodes.push_back(token("MSTORE8", m)); - for (unsigned i = 0; i < node.args.size(); i++) { - Metadata m2 = node.args[i].metadata; - nodes.push_back(token("DUP1", m2)); - programVerticalAux vaux2 = vaux; - vaux2.height += 2; - programData sub = opcodeify(node.args[i], aux, vaux2); - if (!sub.outs) - err("Array_lit item " + unsignedToDecimal(i) + " has zero arity", m2); - aux = sub.aux; - nodes.push_back(sub.code); - nodes.push_back(token("SWAP1", m2)); - if (i > 0) { - nodes.push_back(token(unsignedToDecimal(i * 32), m2)); - nodes.push_back(token("ADD", m2)); - } - nodes.push_back(token("MSTORE", m2)); - } - return pd(aux, astnode("_", nodes, m), 1); - } // All other functions/operators else { std::vector subs2; int depth = opinputs(upperCase(node.val)); - if (node.val != "debug") { - if (depth == -1) - err("Not a function or opcode: "+node.val, m); - if ((int)node.args.size() != depth) - err("Invalid arity for "+node.val, m); - } + if (depth == -1) + err("Not a function or opcode: "+node.val, m); + if ((int)node.args.size() != depth) + err("Invalid arity for "+node.val, m); for (int i = node.args.size() - 1; i >= 0; i--) { programVerticalAux vaux2 = vaux; vaux2.height = vaux.height - i - 1 + node.args.size(); @@ -424,13 +339,8 @@ programData opcodeify(Node node, err("Input "+unsignedToDecimal(i)+" has arity 0", sub.code.metadata); subs2.push_back(sub.code); } - if (node.val == "debug") { - subs2.push_back(token("DUP"+unsignedToDecimal(node.args.size()), m)); - for (int i = 0; i <= (int)node.args.size(); i++) - subs2.push_back(token("POP", m)); - } - else subs2.push_back(token(upperCase(node.val), m)); - int outdepth = node.val == "debug" ? 0 : opoutputs(upperCase(node.val)); + subs2.push_back(token(upperCase(node.val), m)); + int outdepth = opoutputs(upperCase(node.val)); return pd(aux, astnode("_", subs2, m), outdepth); } } @@ -449,15 +359,6 @@ Node finalize(programData c) { }; bottom.push_back(multiToken(nodelist, 3, m)); } - // If msg.data is being used as an array, then we need to copy it - if (c.aux.calldataUsed) { - Node nodelist[] = { - token("MSIZE", m), token("CALLDATASIZE", m), token("0", m), - token("MSIZE", m), token("CALLDATACOPY", m), - token(c.aux.vars["'msg.data"], m), token("MSTORE", m) - }; - bottom.push_back(multiToken(nodelist, 7, m)); - } // The actual code bottom.push_back(c.code); return astnode("_", bottom, m); diff --git a/libserpent/opcodes.h b/libserpent/opcodes.h index a7bcc1af9..41423c169 100644 --- a/libserpent/opcodes.h +++ b/libserpent/opcodes.h @@ -5,6 +5,7 @@ #include #include #include +#include "util.h" class Mapping { public: @@ -20,119 +21,25 @@ class Mapping { int out; }; -Mapping mapping[] = { - Mapping("STOP", 0x00, 0, 0), - Mapping("ADD", 0x01, 2, 1), - Mapping("MUL", 0x02, 2, 1), - Mapping("SUB", 0x03, 2, 1), - Mapping("DIV", 0x04, 2, 1), - Mapping("SDIV", 0x05, 2, 1), - Mapping("MOD", 0x06, 2, 1), - Mapping("SMOD", 0x07, 2, 1), - Mapping("ADDMOD", 0x08, 3, 1), - Mapping("MULMOD", 0x09, 3, 1), - Mapping("EXP", 0x0a, 2, 1), - Mapping("SIGNEXTEND", 0x0b, 2, 1), - Mapping("LT", 0x10, 2, 1), - Mapping("GT", 0x11, 2, 1), - Mapping("SLT", 0x12, 2, 1), - Mapping("SGT", 0x13, 2, 1), - Mapping("EQ", 0x14, 2, 1), - Mapping("ISZERO", 0x15, 1, 1), - Mapping("AND", 0x16, 2, 1), - Mapping("OR", 0x17, 2, 1), - Mapping("XOR", 0x18, 2, 1), - Mapping("NOT", 0x19, 1, 1), - Mapping("BYTE", 0x1a, 2, 1), - Mapping("ADDMOD", 0x14, 3, 1), - Mapping("MULMOD", 0x15, 3, 1), - Mapping("SIGNEXTEND", 0x16, 2, 1), - Mapping("SHA3", 0x20, 2, 1), - Mapping("ADDRESS", 0x30, 0, 1), - Mapping("BALANCE", 0x31, 1, 1), - Mapping("ORIGIN", 0x32, 0, 1), - Mapping("CALLER", 0x33, 0, 1), - Mapping("CALLVALUE", 0x34, 0, 1), - Mapping("CALLDATALOAD", 0x35, 1, 1), - Mapping("CALLDATASIZE", 0x36, 0, 1), - Mapping("CALLDATACOPY", 0x37, 3, 1), - Mapping("CODESIZE", 0x38, 0, 1), - Mapping("CODECOPY", 0x39, 3, 1), - Mapping("GASPRICE", 0x3a, 0, 1), - Mapping("PREVHASH", 0x40, 0, 1), - Mapping("COINBASE", 0x41, 0, 1), - Mapping("TIMESTAMP", 0x42, 0, 1), - Mapping("NUMBER", 0x43, 0, 1), - Mapping("DIFFICULTY", 0x44, 0, 1), - Mapping("GASLIMIT", 0x45, 0, 1), - Mapping("POP", 0x50, 1, 0), - Mapping("MLOAD", 0x51, 1, 1), - Mapping("MSTORE", 0x52, 2, 0), - Mapping("MSTORE8", 0x53, 2, 0), - Mapping("SLOAD", 0x54, 1, 1), - Mapping("SSTORE", 0x55, 2, 0), - Mapping("JUMP", 0x56, 1, 0), - Mapping("JUMPI", 0x57, 2, 0), - Mapping("PC", 0x58, 0, 1), - Mapping("MSIZE", 0x59, 0, 1), - Mapping("GAS", 0x5a, 0, 1), - Mapping("JUMPDEST", 0x5b, 0, 0), - Mapping("LOG0", 0xa0, 2, 0), - Mapping("LOG1", 0xa1, 3, 0), - Mapping("LOG2", 0xa2, 4, 0), - Mapping("LOG3", 0xa3, 5, 0), - Mapping("LOG4", 0xa4, 6, 0), - Mapping("CREATE", 0xf0, 3, 1), - Mapping("CALL", 0xf1, 7, 1), - Mapping("RETURN", 0xf2, 2, 0), - Mapping("CALL_CODE", 0xf3, 7, 1), - Mapping("SUICIDE", 0xff, 1, 0), - Mapping("---END---", 0x00, 0, 0), -}; +extern Mapping mapping[]; -std::map > opcodes; -std::map reverseOpcodes; +extern std::map > opcodes; +extern std::map reverseOpcodes; -// Fetches everything EXCEPT PUSH1..32 -std::pair > _opdata(std::string ops, int opi) { - if (!opcodes.size()) { - int i = 0; - while (mapping[i].op != "---END---") { - Mapping mi = mapping[i]; - opcodes[mi.op] = triple(mi.opcode, mi.in, mi.out); - i++; - } - for (i = 1; i <= 16; i++) { - opcodes["DUP"+unsignedToDecimal(i)] = triple(0x7f + i, i, i+1); - opcodes["SWAP"+unsignedToDecimal(i)] = triple(0x8f + i, i+1, i+1); - } - for (std::map >::iterator it=opcodes.begin(); - it != opcodes.end(); - it++) { - reverseOpcodes[(*it).second[0]] = (*it).first; - } - } - std::string op; - std::vector opdata; - op = reverseOpcodes.count(opi) ? reverseOpcodes[opi] : ""; - opdata = opcodes.count(ops) ? opcodes[ops] : triple(-1, -1, -1); - return std::pair >(op, opdata); -} +std::pair > _opdata(std::string ops, int opi); + +int opcode(std::string op); + +int opinputs(std::string op); + +int opoutputs(std::string op); -int opcode(std::string op) { - return _opdata(op, -1).second[0]; -} +std::string op(int opcode); -int opinputs(std::string op) { - return _opdata(op, -1).second[1]; -} +extern std::string lllSpecials[][3]; -int opoutputs(std::string op) { - return _opdata(op, -1).second[2]; -} +extern std::map > lllMap; -std::string op(int opcode) { - return _opdata("", opcode).first; -} +bool isValidLLLFunc(std::string f, int argc); #endif diff --git a/libserpent/parser.cpp b/libserpent/parser.cpp index 4ceb1d12d..2b9d73702 100644 --- a/libserpent/parser.cpp +++ b/libserpent/parser.cpp @@ -12,17 +12,15 @@ int precedence(Node tok) { if (v == ".") return -1; else if (v == "!" || v == "not") return 1; else if (v=="^" || v == "**") return 2; - else if (v=="*" || v=="/" || v=="@/" || v=="%" || v=="@%") return 3; + else if (v=="*" || v=="/" || v=="%") return 3; else if (v=="+" || v=="-") return 4; else if (v=="<" || v==">" || v=="<=" || v==">=") return 5; - else if (v=="@<" || v=="@>" || v=="@<=" || v=="@>=") return 5; else if (v=="&" || v=="|" || v=="xor" || v=="==" || v == "!=") return 6; else if (v=="&&" || v=="and") return 7; else if (v=="||" || v=="or") return 8; - else if (v==":") return 9; else if (v=="=") return 10; else if (v=="+=" || v=="-=" || v=="*=" || v=="/=" || v=="%=") return 10; - else if (v=="@/=" || v=="@%=") return 10; + else if (v==":" || v == "::") return 11; else return 0; } @@ -223,8 +221,15 @@ Node treefy(std::vector stream) { filename = filename.substr(1, filename.length() - 2); if (!exists(root + filename)) err("File does not exist: "+root + filename, tok.metadata); - oq.back().args.pop_back(); - oq.back().args.push_back(parseSerpent(root + filename)); + if (v == "inset") { + oq.pop_back(); + oq.push_back(parseSerpent(root + filename)); + } + else { + oq.back().args.pop_back(); + oq.back().args.push_back( + asn("outer", parseSerpent(root + filename), tok.metadata)); + } } //Useful for debugging //for (int i = 0; i < oq.size(); i++) { @@ -237,7 +242,7 @@ Node treefy(std::vector stream) { err("Output blank", Metadata()); } else if (oq.size() > 1) { - err("Multiple expressions or unclosed bracket", oq[1].metadata); + return asn("multi", oq, oq[0].metadata); } return oq[0]; @@ -262,15 +267,9 @@ int spaceCount(std::string s) { bool bodied(std::string tok) { return tok == "if" || tok == "elif" || tok == "while" || tok == "with" || tok == "def" || tok == "extern" - || tok == "data"; -} - -// Is this a command that takes an argument as a child block? -bool childBlocked(std::string tok) { - return tok == "if" || tok == "elif" || tok == "else" - || tok == "code" || tok == "shared" || tok == "init" - || tok == "while" || tok == "repeat" || tok == "for" - || tok == "with" || tok == "def"; + || tok == "data" || tok == "assert" || tok == "return" + || tok == "fun" || tok == "scope" || tok == "macro" + || tok == "type"; } // Are the two commands meant to continue each other? @@ -278,10 +277,7 @@ bool bodiedContinued(std::string prev, std::string tok) { return (prev == "if" && tok == "elif") || (prev == "elif" && tok == "else") || (prev == "elif" && tok == "elif") - || (prev == "if" && tok == "else") - || (prev == "init" && tok == "code") - || (prev == "shared" && tok == "code") - || (prev == "shared" && tok == "init"); + || (prev == "if" && tok == "else"); } // Is a line of code empty? @@ -310,16 +306,17 @@ Node parseLines(std::vector lines, Metadata metadata, int sp) { } // Tokenize current line std::vector tokens = tokenize(main.substr(sp), metadata); - // Remove extraneous tokens, including if / elif + // Remove comments std::vector tokens2; for (unsigned j = 0; j < tokens.size(); j++) { if (tokens[j].val == "#" || tokens[j].val == "//") break; - if (j >= 1 || !bodied(tokens[j].val)) { - tokens2.push_back(tokens[j]); - } + tokens2.push_back(tokens[j]); } - if (tokens2.size() > 0 && tokens2.back().val == ":") + bool expectingChildBlock = false; + if (tokens2.size() > 0 && tokens2.back().val == ":") { tokens2.pop_back(); + expectingChildBlock = true; + } // Parse current line Node out = parseSerpentTokenStream(tokens2); // Parse child block @@ -343,14 +340,8 @@ Node parseLines(std::vector lines, Metadata metadata, int sp) { for (unsigned i = 0; i < childBlock.size(); i++) { if (childBlock[i].length() > 0) { cbe = false; break; } } - // Bring back if / elif into AST - if (bodied(tokens[0].val)) { - std::vector args; - args.push_back(out); - out = astnode(tokens[0].val, args, out.metadata); - } // Add child block to AST - if (childBlocked(tokens[0].val)) { + if (expectingChildBlock) { if (cbe) err("Expected indented child block!", out.metadata); out.type = ASTNODE; @@ -360,6 +351,37 @@ Node parseLines(std::vector lines, Metadata metadata, int sp) { } else if (!cbe) err("Did not expect indented child block!", out.metadata); + else if (out.args.size() && out.args[out.args.size() - 1].val == ":") { + Node n = out.args[out.args.size() - 1]; + out.args.pop_back(); + out.args.push_back(n.args[0]); + out.args.push_back(n.args[1]); + } + // Bring back if / elif into AST + if (bodied(tokens[0].val)) { + if (out.val != "multi") { + // token not being used in bodied form + } + else if (out.args[0].val == "id") + out = astnode(tokens[0].val, out.args[1].args, out.metadata); + else if (out.args[0].type == TOKEN) { + std::vector out2; + for (unsigned i = 1; i < out.args.size(); i++) + out2.push_back(out.args[i]); + out = astnode(tokens[0].val, out2, out.metadata); + } + else + out = astnode("fun", out.args, out.metadata); + } + // Multi not supported + if (out.val == "multi") + err("Multiple expressions or unclosed bracket", out.metadata); + // Convert top-level colon expressions into non-colon expressions; + // makes if statements and the like equivalent indented or not + //if (out.val == ":" && out.args[0].type == TOKEN) + // out = asn(out.args[0].val, out.args[1], out.metadata); + //if (bodied(tokens[0].val) && out.args[0].val == ":") + // out = asn(tokens[0].val, out.args[0].args); if (o.size() == 0 || o.back().type == TOKEN) { o.push_back(out); continue; diff --git a/libserpent/rewriter.cpp b/libserpent/rewriter.cpp index 443457acf..294c9a0b3 100644 --- a/libserpent/rewriter.cpp +++ b/libserpent/rewriter.cpp @@ -2,37 +2,25 @@ #include #include #include -#include #include "util.h" #include "lllparser.h" #include "bignum.h" +#include "optimize.h" +#include "rewriteutils.h" +#include "preprocess.h" +#include "functions.h" +#include "opcodes.h" -std::string valid[][3] = { - { "if", "2", "3" }, - { "unless", "2", "2" }, - { "while", "2", "2" }, - { "until", "2", "2" }, - { "alloc", "1", "1" }, - { "array", "1", "1" }, - { "call", "2", tt256 }, - { "call_code", "2", tt256 }, - { "create", "1", "4" }, - { "getch", "2", "2" }, - { "setch", "3", "3" }, - { "sha3", "1", "2" }, - { "return", "1", "2" }, - { "inset", "1", "1" }, - { "min", "2", "2" }, - { "max", "2", "2" }, - { "array_lit", "0", tt256 }, - { "seq", "0", tt256 }, - { "log", "1", "6" }, - { "outer", "1", "1" }, - { "set", "2", "2" }, - { "---END---", "", "" } //Keep this line at the end of the list -}; - +// Rewrite rules std::string macros[][2] = { + { + "(seq $x)", + "$x" + }, + { + "(seq (seq) $x)", + "$x" + }, { "(+= $a $b)", "(set $a (+ $a $b))" @@ -58,24 +46,28 @@ std::string macros[][2] = { "(set $a (^ $a $b))" }, { - "(@/= $a $b)", - "(set $a (@/ $a $b))" + "(!= $a $b)", + "(iszero (eq $a $b))" }, { - "(@%= $a $b)", - "(set $a (@% $a $b))" + "(assert $x)", + "(unless $x (stop))" }, { - "(!= $a $b)", - "(iszero (eq $a $b))" + "(min $a $b)", + "(with $1 $a (with $2 $b (if (lt $1 $2) $1 $2)))" + }, + { + "(max $a $b)", + "(with $1 $a (with $2 $b (if (lt $1 $2) $2 $1)))" }, { - "(min a b)", - "(with $1 a (with $2 b (if (lt $1 $2) $1 $2)))" + "(smin $a $b)", + "(with $1 $a (with $2 $b (if (slt $1 $2) $1 $2)))" }, { - "(max a b)", - "(with $1 a (with $2 b (if (lt $1 $2) $2 $1)))" + "(smax $a $b)", + "(with $1 $a (with $2 $b (if (slt $1 $2) $2 $1)))" }, { "(if $cond $do (else $else))", @@ -85,10 +77,6 @@ std::string macros[][2] = { "(code $code)", "$code" }, - { - "(access (. msg data) $ind)", - "(calldataload (mul 32 $ind))" - }, { "(slice $arr $pos)", "(add $arr (mul 32 $pos))", @@ -125,13 +113,17 @@ std::string macros[][2] = { "(set (access (. self storage) $ind) $val)", "(sstore $ind $val)" }, + { + "(set (sload $ind) $val)", + "(sstore $ind $val)" + }, { "(set (access $var $ind) $val)", "(mstore (add $var (mul 32 $ind)) $val)" }, { "(getch $var $ind)", - "(mod (mload (add $var $ind)) 256)" + "(mod (mload (sub (add $var $ind) 31)) 256)" }, { "(setch $var $ind $val)", @@ -149,6 +141,10 @@ std::string macros[][2] = { "(sha3 $x)", "(seq (set $1 $x) (~sha3 (ref $1) 32))" }, + { + "(sha3 $mstart (= chars $msize))", + "(~sha3 $mstart $msize)" + }, { "(sha3 $mstart $msize)", "(~sha3 $mstart (mul 32 $msize))" @@ -161,6 +157,10 @@ std::string macros[][2] = { "(return $x)", "(seq (set $1 $x) (~return (ref $1) 32))" }, + { + "(return $mstart (= chars $msize))", + "(~return $mstart $msize)" + }, { "(return $start $len)", "(~return $start (mul 32 $len))" @@ -171,7 +171,7 @@ std::string macros[][2] = { }, { "(|| $x $y)", - "(with $1 $x (if (get $1) (get $1) $y))" + "(with $1 $x (if $1 $1 $y))" }, { "(>= $x $y)", @@ -181,45 +181,41 @@ std::string macros[][2] = { "(<= $x $y)", "(iszero (sgt $x $y))" }, - { - "(@>= $x $y)", - "(iszero (lt $x $y))" - }, - { - "(@<= $x $y)", - "(iszero (gt $x $y))" - }, { "(create $code)", "(create 0 $code)" }, { "(create $endowment $code)", - "(with $1 (msize) (create $endowment (get $1) (lll (outer $code) (msize))))" + "(with $1 (msize) (create $endowment (get $1) (lll $code (msize))))" }, { "(sha256 $x)", - "(seq (set $1 $x) (pop (~call 101 2 0 (ref $1) 32 (ref $2) 32)) (get $2))" + "(with $1 (alloc 64) (seq (mstore (add (get $1) 32) $x) (pop (~call 101 2 0 (add (get $1) 32) 32 (get $1) 32)) (mload (get $1))))" + }, + { + "(sha256 $arr (= chars $sz))", + "(with $1 (alloc 32) (seq (pop (~call 101 2 0 $arr $sz (get $1) 32)) (mload (get $1))))" }, { "(sha256 $arr $sz)", - "(seq (pop (~call 101 2 0 $arr (mul 32 $sz) (ref $2) 32)) (get $2))" + "(with $1 (alloc 32) (seq (pop (~call 101 2 0 $arr (mul 32 $sz) (get $1) 32)) (mload (get $1))))" }, { "(ripemd160 $x)", - "(seq (set $1 $x) (pop (~call 101 3 0 (ref $1) 32 (ref $2) 32)) (get $2))" + "(with $1 (alloc 64) (seq (mstore (add (get $1) 32) $x) (pop (~call 101 3 0 (add (get $1) 32) 32 (get $1) 32)) (mload (get $1))))" }, { - "(ripemd160 $arr $sz)", - "(seq (pop (~call 101 3 0 $arr (mul 32 $sz) (ref $2) 32)) (get $2))" + "(ripemd160 $arr (= chars $sz))", + "(with $1 (alloc 32) (seq (pop (~call 101 3 0 $arr $sz (mload $1) 32)) (mload (get $1))))" }, { - "(ecrecover $h $v $r $s)", - "(seq (declare $1) (declare $2) (declare $3) (declare $4) (set $1 $h) (set $2 $v) (set $3 $r) (set $4 $s) (pop (~call 101 1 0 (ref $1) 128 (ref $5) 32)) (get $5))" + "(ripemd160 $arr $sz)", + "(with $1 (alloc 32) (seq (pop (~call 101 3 0 $arr (mul 32 $sz) (get $1) 32)) (mload (get $1))))" }, { - "(seq (seq) $x)", - "$x" + "(ecrecover $h $v $r $s)", + "(with $1 (alloc 160) (seq (mstore (get $1) $h) (mstore (add (get $1) 32) $v) (mstore (add (get $1) 64) $r) (mstore (add (get $1) 96) $s) (pop (~call 101 1 0 (get $1) 128 (add (get $1 128)) 32)) (mload (add (get $1) 128))))" }, { "(inset $x)", @@ -235,21 +231,64 @@ std::string macros[][2] = { }, { "(log $t1)", - "(~log1 $t1 0 0)" + "(~log1 0 0 $t1)" }, { "(log $t1 $t2)", - "(~log2 $t1 $t2 0 0)" + "(~log2 0 0 $t1 $t2)" }, { "(log $t1 $t2 $t3)", - "(~log3 $t1 $t2 $t3 0 0)" + "(~log3 0 0 $t1 $t2 $t3)" }, { "(log $t1 $t2 $t3 $t4)", - "(~log4 $t1 $t2 $t3 $t4 0 0)" + "(~log4 0 0 $t1 $t2 $t3 $t4)" + }, + { + "(logarr $a $sz)", + "(~log0 $a (mul 32 $sz))" + }, + { + "(logarr $a $sz $t1)", + "(~log1 $a (mul 32 $sz) $t1)" + }, + { + "(logarr $a $sz $t1 $t2)", + "(~log2 $a (mul 32 $sz) $t1 $t2)" + }, + { + "(logarr $a $sz $t1 $t2 $t3)", + "(~log3 $a (mul 32 $sz) $t1 $t2 $t3)" + }, + { + "(logarr $a $sz $t1 $t2 $t3 $t4)", + "(~log4 $a (mul 32 $sz) $t1 $t2 $t3 $t4)" + }, + { + "(save $loc $array (= chars $count))", + "(with $location (ref $loc) (with $c $count (with $end (div $c 32) (with $i 0 (seq (while (slt $i $end) (seq (sstore (add $i $location) (access $array $i)) (set $i (add $i 1)))) (sstore (add $i $location) (~and (access $array $i) (sub 0 (exp 256 (sub 32 (mod $c 32)))))))))))" + }, + { + "(save $loc $array $count)", + "(with $location (ref $loc) (with $end $count (with $i 0 (while (slt $i $end) (seq (sstore (add $i $location) (access $array $i)) (set $i (add $i 1)))))))" + }, + { + "(load $loc (= chars $count))", + "(with $location (ref $loc) (with $c $count (with $a (alloc $c) (with $i 0 (seq (while (slt $i (div $c 32)) (seq (set (access $a $i) (sload (add $location $i))) (set $i (add $i 1)))) (set (access $a $i) (~and (sload (add $location $i)) (sub 0 (exp 256 (sub 32 (mod $c 32)))))) $a)))))" + }, + { + "(load $loc $count)", + "(with $location (ref $loc) (with $c $count (with $a (alloc $c) (with $i 0 (seq (while (slt $i $c) (seq (set (access $a $i) (sload (add $location $i))) (set $i (add $i 1)))) $a)))))" + }, + { + "(unsafe_mcopy $to $from $sz)", + "(with _sz $sz (with _from $from (with _to $to (seq (comment STARTING UNSAFE MCOPY) (with _i 0 (while (lt _i _sz) (seq (mstore (add $to _i) (mload (add _from _i))) (set _i (add _i 32)))))))))" + }, + { + "(mcopy $to $from $_sz)", + "(with _to $to (with _from $from (with _sz $sz (seq (comment STARTING MCOPY (with _i 0 (seq (while (lt (add _i 31) _sz) (seq (mstore (add _to _i) (mload (add _from _i))) (set _i (add _i 32)))) (with _mask (exp 256 (sub 32 (mod _sz 32))) (mstore (add $to _i) (add (mod (mload (add $to _i)) _mask) (and (mload (add $from _i)) (sub 0 _mask))))))))))))" }, - { "(. msg datasize)", "(div (calldatasize) 32)" }, { "(. msg sender)", "(caller)" }, { "(. msg value)", "(callvalue)" }, { "(. tx gasprice)", "(gasprice)" }, @@ -267,8 +306,7 @@ std::string macros[][2] = { { "---END---", "" } //Keep this line at the end of the list }; -std::vector > nodeMacros; - +// Token synonyms std::string synonyms[][2] = { { "or", "||" }, { "and", "&&" }, @@ -286,10 +324,6 @@ std::string synonyms[][2] = { { "^", "exp" }, { "**", "exp" }, { "%", "smod" }, - { "@/", "div" }, - { "@%", "mod" }, - { "@<", "lt" }, - { "@>", "gt" }, { "<", "slt" }, { ">", "sgt" }, { "=", "set" }, @@ -298,6 +332,10 @@ std::string synonyms[][2] = { { "---END---", "" } //Keep this line at the end of the list }; +std::map synonymMap; + +// Custom setters (need to be registered separately +// for use with managed storage) std::string setters[][2] = { { "+=", "+" }, { "-=", "-" }, @@ -305,550 +343,136 @@ std::string setters[][2] = { { "/=", "/" }, { "%=", "%" }, { "^=", "^" }, - { "!=", "!" }, { "---END---", "" } //Keep this line at the end of the list }; -// Match result storing object -struct matchResult { - bool success; - std::map map; -}; - -// Storage variable index storing object -struct svObj { - std::map offsets; - std::map indices; - std::map > coefficients; - std::map nonfinal; - std::string globalOffset; -}; - -// Preprocessing result storing object -class preprocessAux { - public: - preprocessAux() { - globalExterns = std::map(); - localExterns = std::map >(); - localExterns["self"] = std::map(); - } - std::map globalExterns; - std::map > localExterns; - svObj storageVars; -}; - -#define preprocessResult std::pair - -// Main pattern matching routine, for those patterns that can be expressed -// using our standard mini-language above -// -// Returns two values. First, a boolean to determine whether the node matches -// the pattern, second, if the node does match then a map mapping variables -// in the pattern to nodes -matchResult match(Node p, Node n) { - matchResult o; - o.success = false; - if (p.type == TOKEN) { - if (p.val == n.val && n.type == TOKEN) o.success = true; - else if (p.val[0] == '$') { - o.success = true; - o.map[p.val.substr(1)] = n; - } - } - else if (n.type==TOKEN || p.val!=n.val || p.args.size()!=n.args.size()) { - // do nothing - } - else { - for (unsigned i = 0; i < p.args.size(); i++) { - matchResult oPrime = match(p.args[i], n.args[i]); - if (!oPrime.success) { - o.success = false; - return o; - } - for (std::map::iterator it = oPrime.map.begin(); - it != oPrime.map.end(); - it++) { - o.map[(*it).first] = (*it).second; - } - } - o.success = true; - } - return o; -} - -// Fills in the pattern with a dictionary mapping variable names to -// nodes (these dicts are generated by match). Match and subst together -// create a full pattern-matching engine. -Node subst(Node pattern, - std::map dict, - std::string varflag, - Metadata metadata) { - if (pattern.type == TOKEN && pattern.val[0] == '$') { - if (dict.count(pattern.val.substr(1))) { - return dict[pattern.val.substr(1)]; - } - else { - return token(varflag + pattern.val.substr(1), metadata); - } - } - else if (pattern.type == TOKEN) { - return pattern; - } - else { - std::vector args; - for (unsigned i = 0; i < pattern.args.size(); i++) { - args.push_back(subst(pattern.args[i], dict, varflag, metadata)); - } - return astnode(pattern.val, args, metadata); - } -} +std::map setterMap; // Processes mutable array literals - Node array_lit_transform(Node node) { + std::string prefix = "_temp"+mkUniqueToken() + "_"; Metadata m = node.metadata; - std::vector o1; - o1.push_back(token(unsignedToDecimal(node.args.size() * 32), m)); - std::vector o2; - std::string symb = "_temp"+mkUniqueToken()+"_0"; - o2.push_back(token(symb, m)); - o2.push_back(astnode("alloc", o1, m)); - std::vector o3; - o3.push_back(astnode("set", o2, m)); + std::map d; + std::string o = "(seq (set $arr (alloc "+utd(node.args.size()*32)+"))"; for (unsigned i = 0; i < node.args.size(); i++) { - std::vector o5; - o5.push_back(token(symb, m)); - std::vector o6; - o6.push_back(astnode("get", o5, m)); - o6.push_back(token(unsignedToDecimal(i * 32), m)); - std::vector o7; - o7.push_back(astnode("add", o6)); - o7.push_back(node.args[i]); - o3.push_back(astnode("mstore", o7, m)); - } - std::vector o8; - o8.push_back(token(symb, m)); - o3.push_back(astnode("get", o8)); - return astnode("seq", o3, m); -} - -// Is the given node something of the form -// self.cow -// self.horse[0] -// self.a[6][7][self.storage[3]].chicken[9] -bool isNodeStorageVariable(Node node) { - std::vector nodez; - nodez.push_back(node); - while (1) { - if (nodez.back().type == TOKEN) return false; - if (nodez.back().args.size() == 0) return false; - if (nodez.back().val != "." && nodez.back().val != "access") - return false; - if (nodez.back().args[0].val == "self") return true; - nodez.push_back(nodez.back().args[0]); + o += " (mstore (add (get $arr) "+utd(i * 32)+") $"+utd(i)+")"; + d[utd(i)] = node.args[i]; } + o += " (get $arr))"; + return subst(parseLLL(o), d, prefix, m); } -Node optimize(Node inp); - -Node apply_rules(preprocessResult pr); - -// Convert: -// self.cow -> ["cow"] -// self.horse[0] -> ["horse", "0"] -// self.a[6][7][self.storage[3]].chicken[9] -> -// ["6", "7", (sload 3), "chicken", "9"] -std::vector listfyStorageAccess(Node node) { - std::vector out; - std::vector nodez; - nodez.push_back(node); - while (1) { - if (nodez.back().type == TOKEN) { - out.push_back(token("--" + nodez.back().val, node.metadata)); - std::vector outrev; - for (int i = (signed)out.size() - 1; i >= 0; i--) { - outrev.push_back(out[i]); +// Processes long text literals +Node string_transform(Node node) { + Metadata m = node.metadata; + if (!node.args.size()) + err("Empty text!", m); + if (node.args[0].val.size() < 2 + || node.args[0].val[0] != '"' + || node.args[0].val[node.args[0].val.size() - 1] != '"') + err("Text contents don't look like a string!", m); + std::string bin = node.args[0].val.substr(1, node.args[0].val.size() - 2); + unsigned sz = bin.size(); + std::vector o; + for (unsigned i = 0; i < sz; i += 32) { + std::string t = binToNumeric(bin.substr(i, 32)); + if ((sz - i) < 32 && (sz - i) > 0) { + while ((sz - i) < 32) { + t = decimalMul(t, "256"); + i--; } - return outrev; + i = sz; } - if (nodez.back().val == ".") - nodez.back().args[1].val = "--" + nodez.back().args[1].val; - if (nodez.back().args.size() == 0) - err("Error parsing storage variable statement", node.metadata); - if (nodez.back().args.size() == 1) - out.push_back(token(tt256m1, node.metadata)); - else - out.push_back(nodez.back().args[1]); - nodez.push_back(nodez.back().args[0]); + o.push_back(token(t, node.metadata)); } + node = astnode("array_lit", o, node.metadata); + return array_lit_transform(node); } -// Cool function for debug purposes (named cerrStringList to make -// all prints searchable via 'cerr') -void cerrStringList(std::vector s, std::string suffix="") { - for (unsigned i = 0; i < s.size(); i++) std::cerr << s[i] << " "; - std::cerr << suffix << "\n"; -} -// Populate an svObj with the arguments needed to determine -// the storage position of a node -svObj getStorageVars(svObj pre, Node node, std::string prefix="", int index=0) { - Metadata m = node.metadata; - if (!pre.globalOffset.size()) pre.globalOffset = "0"; - std::vector h; - std::vector coefficients; - // Array accesses or atoms - if (node.val == "access" || node.type == TOKEN) { - std::string tot = "1"; - h = listfyStorageAccess(node); - coefficients.push_back("1"); - for (unsigned i = h.size() - 1; i >= 1; i--) { - // Array sizes must be constant or at least arithmetically - // evaluable at compile time - h[i] = optimize(apply_rules(preprocessResult( - h[i], preprocessAux()))); - if (!isNumberLike(h[i])) - err("Array size must be fixed value", m); - // Create a list of the coefficient associated with each - // array index - coefficients.push_back(decimalMul(coefficients.back(), h[i].val)); - } - } - // Tuples - else { - int startc; - // Handle the (fun args...) case - if (node.val == "fun") { - startc = 1; - h = listfyStorageAccess(node.args[0]); - } - // Handle the ( args...) case, which - // the serpent parser produces when the function - // is a simple name and not a complex astnode - else { - startc = 0; - h = listfyStorageAccess(token(node.val, m)); - } - svObj sub = pre; - sub.globalOffset = "0"; - // Evaluate tuple elements recursively - for (unsigned i = startc; i < node.args.size(); i++) { - sub = getStorageVars(sub, - node.args[i], - prefix+h[0].val.substr(2)+".", - i-1); - } - coefficients.push_back(sub.globalOffset); - for (unsigned i = h.size() - 1; i >= 1; i--) { - // Array sizes must be constant or at least arithmetically - // evaluable at compile time - h[i] = optimize(apply_rules(preprocessResult( - h[i], preprocessAux()))); - if (!isNumberLike(h[i])) - err("Array size must be fixed value", m); - // Create a list of the coefficient associated with each - // array index - coefficients.push_back(decimalMul(coefficients.back(), h[i].val)); - } - pre.offsets = sub.offsets; - pre.coefficients = sub.coefficients; - pre.nonfinal = sub.nonfinal; - pre.nonfinal[prefix+h[0].val.substr(2)] = true; - } - pre.coefficients[prefix+h[0].val.substr(2)] = coefficients; - pre.offsets[prefix+h[0].val.substr(2)] = pre.globalOffset; - pre.indices[prefix+h[0].val.substr(2)] = index; - if (decimalGt(tt176, coefficients.back())) - pre.globalOffset = decimalAdd(pre.globalOffset, coefficients.back()); - return pre; -} +Node apply_rules(preprocessResult pr); -// Transform a node of the form (call to funid vars...) into +// Transform ".(args...)" into // a call - -#define psn std::pair - -Node call_transform(Node node, std::string op) { +Node dotTransform(Node node, preprocessAux aux) { Metadata m = node.metadata; // We're gonna make lots of temporary variables, // so set up a unique flag for them std::string prefix = "_temp"+mkUniqueToken()+"_"; + // Check that the function name is a token + if (node.args[0].args[1].type == ASTNODE) + err("Function name must be static", m); + + Node dotOwner = node.args[0].args[0]; + std::string dotMember = node.args[0].args[1].val; // kwargs = map of special arguments std::map kwargs; kwargs["value"] = token("0", m); - kwargs["gas"] = parseLLL("(- (gas) 25)"); - std::vector args; - for (unsigned i = 0; i < node.args.size(); i++) { - if (node.args[i].val == "=" || node.args[i].val == "set") { - if (node.args[i].args.size() != 2) - err("Malformed set", m); - kwargs[node.args[i].args[0].val] = node.args[i].args[1]; - } - else args.push_back(node.args[i]); - } - if (args.size() < 2) err("Too few arguments for call!", m); - kwargs["to"] = args[0]; - kwargs["funid"] = args[1]; - std::vector inputs; - for (unsigned i = 2; i < args.size(); i++) { - inputs.push_back(args[i]); - } - std::vector with; - std::vector precompute; - std::vector post; - if (kwargs.count("data")) { - if (!kwargs.count("datasz")) err("Required param datasz", m); - // The strategy here is, we store the function ID byte at the index - // before the start of the byte, but then we store the value that was - // there before and reinstate it once the process is over - // store data: data array start - with.push_back(psn(prefix+"data", kwargs["data"])); - // store data: prior: data array - 32 - Node prior = astnode("sub", token(prefix+"data", m), token("32", m), m); - with.push_back(psn(prefix+"prior", prior)); - // store data: priormem: data array - 32 prior memory value - Node priormem = astnode("mload", token(prefix+"prior", m), m); - with.push_back(psn(prefix+"priormem", priormem)); - // post: reinstate prior mem at data array - 32 - post.push_back(astnode("mstore", - token(prefix+"prior", m), - token(prefix+"priormem", m), - m)); - // store data: datastart: data array - 1 - Node datastart = astnode("sub", - token(prefix+"data", m), - token("1", m), - m); - with.push_back(psn(prefix+"datastart", datastart)); - // push funid byte to datastart - precompute.push_back(astnode("mstore8", - token(prefix+"datastart", m), - kwargs["funid"], - m)); - // set data array start loc - kwargs["datain"] = token(prefix+"datastart", m); - kwargs["datainsz"] = astnode("add", - token("1", m), - astnode("mul", - token("32", m), - kwargs["datasz"], - m), - m); - } - else { - // Here, there is no data array, instead there are function arguments. - // This actually lets us be much more efficient with how we set things - // up. - // Pre-declare variables; relies on declared variables being sequential - precompute.push_back(astnode("declare", - token(prefix+"prebyte", m), - m)); - for (unsigned i = 0; i < inputs.size(); i++) { - precompute.push_back(astnode("declare", - token(prefix+unsignedToDecimal(i), m), - m)); - } - // Set up variables to store the function arguments, and store the - // function ID at the byte before the start - Node datastart = astnode("add", - token("31", m), - astnode("ref", - token(prefix+"prebyte", m), - m), - m); - precompute.push_back(astnode("mstore8", - datastart, - kwargs["funid"], - m)); - for (unsigned i = 0; i < inputs.size(); i++) { - precompute.push_back(astnode("set", - token(prefix+unsignedToDecimal(i), m), - inputs[i], - m)); - - } - kwargs["datain"] = datastart; - kwargs["datainsz"] = token(unsignedToDecimal(inputs.size()*32+1), m); - } - if (!kwargs.count("outsz")) { - kwargs["dataout"] = astnode("ref", token(prefix+"dataout", m), m); - kwargs["dataoutsz"] = token("32", node.metadata); - post.push_back(astnode("get", token(prefix+"dataout", m), m)); - } - else { - kwargs["dataout"] = kwargs["out"]; - kwargs["dataoutsz"] = kwargs["outsz"]; - post.push_back(astnode("ref", token(prefix+"dataout", m), m)); - } - // Set up main call - std::vector main; - for (unsigned i = 0; i < precompute.size(); i++) { - main.push_back(precompute[i]); - } - std::vector call; - call.push_back(kwargs["gas"]); - call.push_back(kwargs["to"]); - call.push_back(kwargs["value"]); - call.push_back(kwargs["datain"]); - call.push_back(kwargs["datainsz"]); - call.push_back(kwargs["dataout"]); - call.push_back(kwargs["dataoutsz"]); - main.push_back(astnode("pop", astnode("~"+op, call, m), m)); - for (unsigned i = 0; i < post.size(); i++) { - main.push_back(post[i]); - } - Node mainNode = astnode("seq", main, node.metadata); - // Add with variables - for (int i = with.size() - 1; i >= 0; i--) { - mainNode = astnode("with", - token(with[i].first, m), - with[i].second, - mainNode, - m); - } - return mainNode; -} - -// Preprocess input containing functions -// -// localExterns is a map of the form, eg, -// -// { x: { foo: 0, bar: 1, baz: 2 }, y: { qux: 0, foo: 1 } ... } -// -// Signifying that x.foo = 0, x.baz = 2, y.foo = 1, etc -// -// globalExterns is a one-level map, eg from above -// -// { foo: 1, bar: 1, baz: 2, qux: 0 } -// -// Note that globalExterns may be ambiguous -preprocessResult preprocess(Node inp) { - inp = inp.args[0]; - Metadata m = inp.metadata; - if (inp.val != "seq") { - std::vector args; - args.push_back(inp); - inp = astnode("seq", args, m); - } - std::vector empty; - Node init = astnode("seq", empty, m); - Node shared = astnode("seq", empty, m); - std::vector any; - std::vector functions; - preprocessAux out = preprocessAux(); - out.localExterns["self"] = std::map(); - int functionCount = 0; - int storageDataCount = 0; - for (unsigned i = 0; i < inp.args.size(); i++) { - Node obj = inp.args[i]; - // Functions - if (obj.val == "def") { - if (obj.args.size() == 0) - err("Empty def", m); - std::string funName = obj.args[0].val; - // Init, shared and any are special functions - if (funName == "init" || funName == "shared" || funName == "any") { - if (obj.args[0].args.size()) - err(funName+" cannot have arguments", m); - } - if (funName == "init") init = obj.args[1]; - else if (funName == "shared") shared = obj.args[1]; - else if (funName == "any") any.push_back(obj.args[1]); - else { - // Other functions - functions.push_back(obj); - out.localExterns["self"][obj.args[0].val] = functionCount; - functionCount++; - } - } - // Extern declarations - else if (obj.val == "extern") { - std::string externName = obj.args[0].args[0].val; - Node al = obj.args[0].args[1]; - if (!out.localExterns.count(externName)) - out.localExterns[externName] = std::map(); - for (unsigned i = 0; i < al.args.size(); i++) { - out.globalExterns[al.args[i].val] = i; - out.localExterns[externName][al.args[i].val] = i; - } - } - // Storage variables/structures - else if (obj.val == "data") { - out.storageVars = getStorageVars(out.storageVars, - obj.args[0], - "", - storageDataCount); - storageDataCount += 1; - } - else any.push_back(obj); - } - std::vector main; - if (shared.args.size()) main.push_back(shared); - if (init.args.size()) main.push_back(init); - - std::vector code; - if (shared.args.size()) code.push_back(shared); - for (unsigned i = 0; i < any.size(); i++) - code.push_back(any[i]); - for (unsigned i = 0; i < functions.size(); i++) - code.push_back(functions[i]); - main.push_back(astnode("~return", - token("0", m), - astnode("lll", - astnode("seq", code, m), - token("0", m), - m), - m)); - - - - return preprocessResult(astnode("seq", main, inp.metadata), out); -} - -// Transform ".(args...)" into -// (call args...) -Node dotTransform(Node node, preprocessAux aux) { - Metadata m = node.metadata; - Node pre = node.args[0].args[0]; - std::string post = node.args[0].args[1].val; - if (node.args[0].args[1].type == ASTNODE) - err("Function name must be static", m); - // Search for as=? and call=code keywords + kwargs["gas"] = subst(parseLLL("(- (gas) 25)"), msn(), prefix, m); + // Search for as=? and call=code keywords, and isolate the actual + // function arguments + std::vector fnargs; std::string as = ""; - bool call_code = false; + std::string op = "call"; for (unsigned i = 1; i < node.args.size(); i++) { - Node arg = node.args[i]; + fnargs.push_back(node.args[i]); + Node arg = fnargs.back(); if (arg.val == "=" || arg.val == "set") { if (arg.args[0].val == "as") as = arg.args[1].val; if (arg.args[0].val == "call" && arg.args[1].val == "code") - call_code = true; + op = "callcode"; + if (arg.args[0].val == "gas") + kwargs["gas"] = arg.args[1]; + if (arg.args[0].val == "value") + kwargs["value"] = arg.args[1]; + if (arg.args[0].val == "outsz") + kwargs["outsz"] = arg.args[1]; } } - if (pre.val == "self") { + if (dotOwner.val == "self") { if (as.size()) err("Cannot use \"as\" when calling self!", m); - as = pre.val; + as = dotOwner.val; } - std::vector args; - args.push_back(pre); - // Determine the funId assuming the "as" keyword was used + // Determine the funId and sig assuming the "as" keyword was used + int funId = 0; + std::string sig; if (as.size() > 0 && aux.localExterns.count(as)) { - if (!aux.localExterns[as].count(post)) - err("Invalid call: "+printSimple(pre)+"."+post, m); - std::string funid = unsignedToDecimal(aux.localExterns[as][post]); - args.push_back(token(funid, m)); + if (!aux.localExterns[as].count(dotMember)) + err("Invalid call: "+printSimple(dotOwner)+"."+dotMember, m); + funId = aux.localExterns[as][dotMember]; + sig = aux.localExternSigs[as][dotMember]; } - // Determine the funId otherwise + // Determine the funId and sig otherwise else if (!as.size()) { - if (!aux.globalExterns.count(post)) - err("Invalid call: "+printSimple(pre)+"."+post, m); - std::string key = unsignedToDecimal(aux.globalExterns[post]); - args.push_back(token(key, m)); + if (!aux.globalExterns.count(dotMember)) + err("Invalid call: "+printSimple(dotOwner)+"."+dotMember, m); + std::string key = unsignedToDecimal(aux.globalExterns[dotMember]); + funId = aux.globalExterns[dotMember]; + sig = aux.globalExternSigs[dotMember]; + } + else err("Invalid call: "+printSimple(dotOwner)+"."+dotMember, m); + // Pack arguments + kwargs["data"] = packArguments(fnargs, sig, funId, m); + kwargs["to"] = dotOwner; + Node main; + // Pack output + if (!kwargs.count("outsz")) { + main = parseLLL( + "(with _data $data (seq " + "(pop (~"+op+" $gas $to $value (access _data 0) (access _data 1) (ref $dataout) 32))" + "(get $dataout)))"); + } + else { + main = parseLLL( + "(with _data $data (with _outsz (mul 32 $outsz) (with _out (alloc _outsz) (seq " + "(pop (~"+op+" $gas $to $value (access _data 0) (access _data 1) _out _outsz))" + "(get _out)))))"); } - else err("Invalid call: "+printSimple(pre)+"."+post, m); - for (unsigned i = 1; i < node.args.size(); i++) - args.push_back(node.args[i]); - return astnode(call_code ? "call_code" : "call", args, m); + // Set up main call + + Node o = subst(main, kwargs, prefix, m); + return o; } // Transform an access of the form self.bob, self.users[5], etc into @@ -877,7 +501,8 @@ Node dotTransform(Node node, preprocessAux aux) { // obj2[0].a -> sha3([1, 0, 0]) // obj2[5].b[1][3] -> sha3([1, 5, 1, 1, 3]) // obj2[45].c -> sha3([1, 45, 2]) -Node storageTransform(Node node, preprocessAux aux, bool mapstyle=false) { +Node storageTransform(Node node, preprocessAux aux, + bool mapstyle=false, bool ref=false) { Metadata m = node.metadata; // Get a list of all of the "access parameters" used in order // eg. self.users[5].cow[4][m[2]][woof] -> @@ -909,7 +534,7 @@ Node storageTransform(Node node, preprocessAux aux, bool mapstyle=false) { // If the size of an object exceeds 2^176, we make it an infinite // array if (decimalGt(coefficients.back(), tt176) && !mapstyle) - return storageTransform(node, aux, true); + return storageTransform(node, aux, true, ref); offset = decimalAdd(offset, aux.storageVars.offsets[tempPrefix]); c = 0; if (mapstyle) @@ -940,28 +565,29 @@ Node storageTransform(Node node, preprocessAux aux, bool mapstyle=false) { if (c > (signed)coefficients.size() - 1) { err("Too many array index lookups", m); } + Node o; if (mapstyle) { - // We pre-declare variables, relying on the idea that sequentially - // declared variables are doing to appear beside each other in - // memory - std::vector main; + std::string t = "_temp_"+mkUniqueToken(); + std::vector sub; for (unsigned i = 0; i < terms.size(); i++) - main.push_back(astnode("declare", - token(varPrefix+unsignedToDecimal(i), m), - m)); - for (unsigned i = 0; i < terms.size(); i++) - main.push_back(astnode("set", - token(varPrefix+unsignedToDecimal(i), m), - terms[i], - m)); - main.push_back(astnode("ref", token(varPrefix+"0", m), m)); - Node sz = token(unsignedToDecimal(terms.size()), m); - return astnode("sload", - astnode("sha3", - astnode("seq", main, m), - sz, - m), - m); + sub.push_back(asn("mstore", + asn("add", + tkn(utd(i * 32), m), + asn("get", tkn(t+"pos", m), m), + m), + terms[i], + m)); + sub.push_back(tkn(t+"pos", m)); + Node main = asn("with", + tkn(t+"pos", m), + asn("alloc", tkn(utd(terms.size() * 32), m), m), + asn("seq", sub, m), + m); + Node sz = token(utd(terms.size() * 32), m); + o = astnode("~sha3", + main, + sz, + m); } else { // We add up all the index*coefficients @@ -972,42 +598,92 @@ Node storageTransform(Node node, preprocessAux aux, bool mapstyle=false) { temp.push_back(terms[i]); out = astnode("add", temp, node.metadata); } - std::vector temp2; - temp2.push_back(out); - return astnode("sload", temp2, node.metadata); + o = out; + } + if (ref) return o; + else return astnode("sload", o, node.metadata); +} + +// Basic rewrite rule execution +std::pair rulesTransform(Node node, rewriteRuleSet macros) { + std::string prefix = "_temp_"+mkUniqueToken(); + bool changed = false; + if (!macros.ruleLists.count(node.val)) + return std::pair(node, false); + std::vector rules = macros.ruleLists[node.val]; + for (unsigned pos = 0; pos < rules.size(); pos++) { + rewriteRule macro = rules[pos]; + matchResult mr = match(macro.pattern, node); + if (mr.success) { + node = subst(macro.substitution, mr.map, prefix, node.metadata); + std::pair o = rulesTransform(node, macros); + o.second = true; + return o; + } + } + return std::pair(node, changed); +} + +std::pair synonymTransform(Node node) { + bool changed = false; + if (node.type == ASTNODE && synonymMap.count(node.val)) { + node.val = synonymMap[node.val]; + changed = true; } + return std::pair(node, changed); } +rewriteRuleSet nodeMacros; +rewriteRuleSet setterMacros; -// Recursively applies rewrite rules -Node apply_rules(preprocessResult pr) { +bool dontDescend(std::string s) { + return s == "macro" || s == "comment" || s == "outer"; +} + +// Recursively applies any set of rewrite rules +std::pair apply_rules_iter(preprocessResult pr, rewriteRuleSet rules) { + bool changed = false; Node node = pr.first; - // If the rewrite rules have not yet been parsed, parse them - if (!nodeMacros.size()) { - for (int i = 0; i < 9999; i++) { - std::vector o; - if (macros[i][0] == "---END---") break; - o.push_back(parseLLL(macros[i][0])); - o.push_back(parseLLL(macros[i][1])); - nodeMacros.push_back(o); + if (dontDescend(node.val)) + return std::pair(node, false); + std::pair o = rulesTransform(node, rules); + node = o.first; + changed = changed || o.second; + if (node.type == ASTNODE) { + for (unsigned i = 0; i < node.args.size(); i++) { + std::pair r = + apply_rules_iter(preprocessResult(node.args[i], pr.second), rules); + node.args[i] = r.first; + changed = changed || r.second; } } - // Assignment transformations - for (int i = 0; i < 9999; i++) { - if (setters[i][0] == "---END---") break; - if (node.val == setters[i][0]) { - node = astnode("=", - node.args[0], - astnode(setters[i][1], - node.args[0], - node.args[1], - node.metadata), - node.metadata); - } + return std::pair(node, changed); +} + +// Recursively applies rewrite rules and other primary transformations +std::pair mainTransform(preprocessResult pr) { + bool changed = false; + Node node = pr.first; + + // Anything inside "outer" should be treated as a separate program + // and thus recursively compiled in its entirety + if (node.val == "outer") { + node = apply_rules(preprocess(node.args[0])); + changed = true; } + + // Don't descend into comments, macros and inner scopes + if (dontDescend(node.val)) + return std::pair(node, changed); + // Special storage transformation if (isNodeStorageVariable(node)) { node = storageTransform(node, pr.second); + changed = true; + } + if (node.val == "ref" && isNodeStorageVariable(node.args[0])) { + node = storageTransform(node.args[0], pr.second, false, true); + changed = true; } if (node.val == "=" && isNodeStorageVariable(node.args[0])) { Node t = storageTransform(node.args[0], pr.second); @@ -1017,195 +693,213 @@ Node apply_rules(preprocessResult pr) { o.push_back(node.args[1]); node = astnode("sstore", o, node.metadata); } + changed = true; } // Main code - unsigned pos = 0; - std::string prefix = "_temp"+mkUniqueToken()+"_"; - while(1) { - if (synonyms[pos][0] == "---END---") { - break; - } - else if (node.type == ASTNODE && node.val == synonyms[pos][0]) { - node.val = synonyms[pos][1]; - } - pos++; - } - for (pos = 0; pos < nodeMacros.size(); pos++) { - Node pattern = nodeMacros[pos][0]; - matchResult mr = match(pattern, node); - if (mr.success) { - Node pattern2 = nodeMacros[pos][1]; - node = subst(pattern2, mr.map, prefix, node.metadata); - pos = 0; - } - } + std::pair pnb = synonymTransform(node); + node = pnb.first; + changed = changed || pnb.second; + // std::cerr << priority << " " << macros.size() << "\n"; + std::pair pnc = rulesTransform(node, nodeMacros); + node = pnc.first; + changed = changed || pnc.second; + + // Special transformations - if (node.val == "outer") { - pr = preprocess(node); - node = pr.first; - } - if (node.val == "array_lit") + if (node.val == "array_lit") { node = array_lit_transform(node); + changed = true; + } if (node.val == "fun" && node.args[0].val == ".") { node = dotTransform(node, pr.second); + changed = true; + } + if (node.val == "text") { + node = string_transform(node); + changed = true; } - if (node.val == "call") - node = call_transform(node, "call"); - if (node.val == "call_code") - node = call_transform(node, "call_code"); if (node.type == ASTNODE) { unsigned i = 0; + // Arg 0 of all of these is a variable, so should not be changed if (node.val == "set" || node.val == "ref" - || node.val == "get" || node.val == "with" - || node.val == "def" || node.val == "declare") { - node.args[0].val = "'" + node.args[0].val; + || node.val == "get" || node.val == "with") { + if (node.args[0].type == TOKEN && + node.args[0].val.size() > 0 && node.args[0].val[0] != '\'') { + node.args[0].val = "'" + node.args[0].val; + changed = true; + } i = 1; } - if (node.val == "def") { - for (unsigned j = 0; j < node.args[0].args.size(); j++) { - if (node.args[0].args[j].val == ":") { - node.args[0].args[j].val = "kv"; - node.args[0].args[j].args[0].val = - "'" + node.args[0].args[j].args[0].val; - } - else { - node.args[0].args[j].val = "'" + node.args[0].args[j].val; - } - } + // Convert arglen(x) to '_len_x + else if (node.val == "arglen") { + node.val = "get"; + node.args[0].val = "'_len_" + node.args[0].val; + i = 1; + changed = true; } + // Recursively process children for (; i < node.args.size(); i++) { - node.args[i] = - apply_rules(preprocessResult(node.args[i], pr.second)); + std::pair r = + mainTransform(preprocessResult(node.args[i], pr.second)); + node.args[i] = r.first; + changed = changed || r.second; } } + // Add leading ' to variable names, and wrap them inside get else if (node.type == TOKEN && !isNumberLike(node)) { - node.val = "'" + node.val; - std::vector args; - args.push_back(node); - node = astnode("get", args, node.metadata); + if (node.val.size() && node.val[0] != '\'' && node.val[0] != '$') { + Node n = astnode("get", tkn("'"+node.val), node.metadata); + node = n; + changed = true; + } } - // This allows people to use ~x as a way of having functions with the same - // name and arity as macros; the idea is that ~x is a "final" form, and - // should not be remacroed, but it is converted back at the end - if (node.type == ASTNODE && node.val[0] == '~') - node.val = node.val.substr(1); - return node; + // Convert all numbers to normalized form + else if (node.type == TOKEN && isNumberLike(node) && !isDecimal(node.val)) { + node.val = strToNumeric(node.val); + changed = true; + } + return std::pair(node, changed); } -// Compile-time arithmetic calculations -Node optimize(Node inp) { - if (inp.type == TOKEN) { - Node o = tryNumberize(inp); - if (decimalGt(o.val, tt256, true)) - err("Value too large (exceeds 32 bytes or 2^256)", inp.metadata); - return o; +// Do some preprocessing to convert all of our macro lists into compiled +// forms that can then be reused +void parseMacros() { + for (int i = 0; i < 9999; i++) { + std::vector o; + if (macros[i][0] == "---END---") break; + nodeMacros.addRule(rewriteRule( + parseLLL(macros[i][0]), + parseLLL(macros[i][1]) + )); } - for (unsigned i = 0; i < inp.args.size(); i++) { - inp.args[i] = optimize(inp.args[i]); + for (int i = 0; i < 9999; i++) { + std::vector o; + if (setters[i][0] == "---END---") break; + setterMacros.addRule(rewriteRule( + asn(setters[i][0], tkn("$x"), tkn("$y")), + asn("=", tkn("$x"), asn(setters[i][1], tkn("$x"), tkn("$y"))) + )); } - // Degenerate cases for add and mul - if (inp.args.size() == 2) { - if (inp.val == "add" && inp.args[0].type == TOKEN && - inp.args[0].val == "0") { - inp = inp.args[1]; - } - if (inp.val == "add" && inp.args[1].type == TOKEN && - inp.args[1].val == "0") { - inp = inp.args[0]; - } - if (inp.val == "mul" && inp.args[0].type == TOKEN && - inp.args[0].val == "1") { - inp = inp.args[1]; - } - if (inp.val == "mul" && inp.args[1].type == TOKEN && - inp.args[1].val == "1") { - inp = inp.args[0]; - } + for (int i = 0; i < 9999; i++) { + if (synonyms[i][0] == "---END---") break; + synonymMap[synonyms[i][0]] = synonyms[i][1]; + } +} + +Node apply_rules(preprocessResult pr) { + // If the rewrite rules have not yet been parsed, parse them + if (!nodeMacros.ruleLists.size()) parseMacros(); + // Iterate over macros by priority list + std::map::iterator it; + std::pair r; + for(it=pr.second.customMacros.begin(); + it != pr.second.customMacros.end(); it++) { + while (1) { + // std::cerr << "STARTING ARI CYCLE: " << (*it).first <<"\n"; + // std::cerr << printAST(pr.first) << "\n"; + r = apply_rules_iter(pr, (*it).second); + pr.first = r.first; + if (!r.second) break; + } + } + // Apply setter macros + while (1) { + r = apply_rules_iter(pr, setterMacros); + pr.first = r.first; + if (!r.second) break; } - // Arithmetic computation - if (inp.args.size() == 2 - && inp.args[0].type == TOKEN - && inp.args[1].type == TOKEN) { - std::string o; - if (inp.val == "add") { - o = decimalMod(decimalAdd(inp.args[0].val, inp.args[1].val), tt256); - } - else if (inp.val == "sub") { - if (decimalGt(inp.args[0].val, inp.args[1].val, true)) - o = decimalSub(inp.args[0].val, inp.args[1].val); - } - else if (inp.val == "mul") { - o = decimalMod(decimalMul(inp.args[0].val, inp.args[1].val), tt256); - } - else if (inp.val == "div" && inp.args[1].val != "0") { - o = decimalDiv(inp.args[0].val, inp.args[1].val); - } - else if (inp.val == "sdiv" && inp.args[1].val != "0" - && decimalGt(tt255, inp.args[0].val) - && decimalGt(tt255, inp.args[1].val)) { - o = decimalDiv(inp.args[0].val, inp.args[1].val); - } - else if (inp.val == "mod" && inp.args[1].val != "0") { - o = decimalMod(inp.args[0].val, inp.args[1].val); - } - else if (inp.val == "smod" && inp.args[1].val != "0" - && decimalGt(tt255, inp.args[0].val) - && decimalGt(tt255, inp.args[1].val)) { - o = decimalMod(inp.args[0].val, inp.args[1].val); - } - else if (inp.val == "exp") { - o = decimalModExp(inp.args[0].val, inp.args[1].val, tt256); - } - if (o.length()) return token(o, inp.metadata); + // Apply all other mactos + while (1) { + r = mainTransform(pr); + pr.first = r.first; + if (!r.second) break; } - return inp; + return r.first; } +// Pre-validation Node validate(Node inp) { + Metadata m = inp.metadata; if (inp.type == ASTNODE) { int i = 0; - while(valid[i][0] != "---END---") { - if (inp.val == valid[i][0]) { + while(validFunctions[i][0] != "---END---") { + if (inp.val == validFunctions[i][0]) { std::string sz = unsignedToDecimal(inp.args.size()); - if (decimalGt(valid[i][1], sz)) { + if (decimalGt(validFunctions[i][1], sz)) { err("Too few arguments for "+inp.val, inp.metadata); } - if (decimalGt(sz, valid[i][2])) { + if (decimalGt(sz, validFunctions[i][2])) { err("Too many arguments for "+inp.val, inp.metadata); } } i++; } + } + else if (inp.type == TOKEN) { + if (!inp.val.size()) err("??? empty token", m); + if (inp.val[0] == '_') err("Variables cannot start with _", m); } for (unsigned i = 0; i < inp.args.size(); i++) validate(inp.args[i]); return inp; } Node postValidate(Node inp) { + // This allows people to use ~x as a way of having functions with the same + // name and arity as macros; the idea is that ~x is a "final" form, and + // should not be remacroed, but it is converted back at the end + if (inp.val.size() > 0 && inp.val[0] == '~') { + inp.val = inp.val.substr(1); + } if (inp.type == ASTNODE) { if (inp.val == ".") err("Invalid object member (ie. a foo.bar not mapped to anything)", inp.metadata); - for (unsigned i = 0; i < inp.args.size(); i++) - postValidate(inp.args[i]); + else if (opcode(inp.val) >= 0) { + if ((signed)inp.args.size() < opinputs(inp.val)) + err("Too few arguments for "+inp.val, inp.metadata); + if ((signed)inp.args.size() > opinputs(inp.val)) + err("Too many arguments for "+inp.val, inp.metadata); + } + else if (isValidLLLFunc(inp.val, inp.args.size())) { + // do nothing + } + else err ("Invalid argument count or LLL function: "+printSimple(inp), inp.metadata); + for (unsigned i = 0; i < inp.args.size(); i++) { + inp.args[i] = postValidate(inp.args[i]); + } } return inp; } -Node outerWrap(Node inp) { - std::vector args; - args.push_back(inp); - return astnode("outer", args, inp.metadata); + +Node rewriteChunk(Node inp) { + return postValidate(optimize(apply_rules( + preprocessResult( + validate(inp), preprocessAux())))); } -Node rewrite(Node inp) { - return postValidate(optimize(apply_rules(preprocessResult( - validate(outerWrap(inp)), preprocessAux())))); +// Flatten nested sequence into flat sequence +Node flattenSeq(Node inp) { + std::vector o; + if (inp.val == "seq" && inp.type == ASTNODE) { + for (unsigned i = 0; i < inp.args.size(); i++) { + if (inp.args[i].val == "seq" && inp.args[i].type == ASTNODE) + o = extend(o, flattenSeq(inp.args[i]).args); + else + o.push_back(flattenSeq(inp.args[i])); + } + } + else if (inp.type == ASTNODE) { + for (unsigned i = 0; i < inp.args.size(); i++) { + o.push_back(flattenSeq(inp.args[i])); + } + } + else return inp; + return asn(inp.val, o, inp.metadata); } -Node rewriteChunk(Node inp) { - return postValidate(optimize(apply_rules(preprocessResult( - validate(inp), preprocessAux())))); +Node rewrite(Node inp) { + return postValidate(optimize(apply_rules(preprocess(flattenSeq(inp))))); } using namespace std; diff --git a/libserpent/tokenize.cpp b/libserpent/tokenize.cpp index c6a211593..b60cc8a44 100644 --- a/libserpent/tokenize.cpp +++ b/libserpent/tokenize.cpp @@ -13,8 +13,8 @@ int chartype(char c) { if (c >= '0' && c <= '9') return ALPHANUM; else if (c >= 'a' && c <= 'z') return ALPHANUM; else if (c >= 'A' && c <= 'Z') return ALPHANUM; - else if (std::string("~_$").find(c) != std::string::npos) return ALPHANUM; - else if (c == '\t' || c == ' ' || c == '\n') return SPACE; + else if (std::string("~_$@").find(c) != std::string::npos) return ALPHANUM; + else if (c == '\t' || c == ' ' || c == '\n' || c == '\r') return SPACE; else if (std::string("()[]{}").find(c) != std::string::npos) return BRACK; else if (c == '"') return DQUOTE; else if (c == '\'') return SQUOTE; diff --git a/libserpent/util.cpp b/libserpent/util.cpp index fbce5e8b5..5e83c0e41 100644 --- a/libserpent/util.cpp +++ b/libserpent/util.cpp @@ -2,7 +2,6 @@ #include #include #include -#include #include "util.h" #include "bignum.h" #include @@ -28,6 +27,11 @@ Node astnode(std::string val, std::vector args, Metadata met) { } //AST node constructors for a specific number of children +Node astnode(std::string val, Metadata met) { + std::vector args; + return astnode(val, args, met); +} + Node astnode(std::string val, Node a, Metadata met) { std::vector args; args.push_back(a); @@ -49,6 +53,16 @@ Node astnode(std::string val, Node a, Node b, Node c, Metadata met) { return astnode(val, args, met); } +Node astnode(std::string val, Node a, Node b, Node c, Node d, Metadata met) { + std::vector args; + args.push_back(a); + args.push_back(b); + args.push_back(c); + args.push_back(d); + return astnode(val, args, met); +} + + // Print token list std::string printTokens(std::vector tokens) { std::string s = ""; @@ -146,6 +160,15 @@ std::string indentLines(std::string inp) { return joinLines(lines); } +// Binary to hexadecimal +std::string binToNumeric(std::string inp) { + std::string o = "0"; + for (unsigned i = 0; i < inp.length(); i++) { + o = decimalAdd(decimalMul(o,"256"), unsignedToDecimal((unsigned char)inp[i])); + } + return o; +} + // Converts string to simple numeric format std::string strToNumeric(std::string inp) { std::string o = "0"; @@ -154,7 +177,7 @@ std::string strToNumeric(std::string inp) { } else if ((inp[0] == '"' && inp[inp.length()-1] == '"') || (inp[0] == '\'' && inp[inp.length()-1] == '\'')) { - for (unsigned i = 1; i < inp.length() - 1; i++) { + for (unsigned i = 1; i < inp.length() - 1; i++) { o = decimalAdd(decimalMul(o,"256"), unsignedToDecimal((unsigned char)inp[i])); } } @@ -181,6 +204,14 @@ bool isNumberLike(Node node) { return strToNumeric(node.val) != ""; } +// Is the number decimal? +bool isDecimal(std::string inp) { + for (unsigned i = 0; i < inp.length(); i++) { + if (inp[i] < '0' || inp[i] > '9') return false; + } + return true; +} + //Normalizes number representations Node nodeToNumeric(Node node) { std::string o = strToNumeric(node.val); @@ -246,6 +277,14 @@ void err(std::string errtext, Metadata met) { throw(err); } +//Report warning +void warn(std::string errtext, Metadata met) { + std::string err = "Warning (file \"" + met.file + "\", line " + + unsignedToDecimal(met.ln + 1) + ", char " + unsignedToDecimal(met.ch) + + "): " + errtext; + std::cerr << err << "\n"; +} + //Bin to hex std::string binToHex(std::string inp) { std::string o = ""; @@ -280,7 +319,15 @@ std::string upperCase(std::string inp) { //Three-int vector std::vector triple(int a, int b, int c) { - std::vector o; - o.push_back(a); o.push_back(b); o.push_back(c); - return o; + std::vector v; + v.push_back(a); + v.push_back(b); + v.push_back(c); + return v; +} + +//Extend node vector +std::vector extend(std::vector a, std::vector b) { + for (unsigned i = 0; i < b.size(); i++) a.push_back(b[i]); + return a; } diff --git a/libserpent/util.h b/libserpent/util.h index c0a2e9324..e25712d0f 100644 --- a/libserpent/util.h +++ b/libserpent/util.h @@ -28,30 +28,36 @@ const int TOKEN = 0, // Stores metadata about each token class Metadata { public: - Metadata(std::string File="main", int Ln=0, int Ch=0) { + Metadata(std::string File="main", int Ln=-1, int Ch=-1) { file = File; ln = Ln; ch = Ch; + fixed = false; } std::string file; int ln; int ch; + bool fixed; }; std::string mkUniqueToken(); // type can be TOKEN or ASTNODE -struct Node { - int type; - std::string val; - std::vector args; - Metadata metadata; +class Node { + public: + int type; + std::string val; + std::vector args; + Metadata metadata; }; Node token(std::string val, Metadata met=Metadata()); Node astnode(std::string val, std::vector args, Metadata met=Metadata()); +Node astnode(std::string val, Metadata met=Metadata()); Node astnode(std::string val, Node a, Metadata met=Metadata()); Node astnode(std::string val, Node a, Node b, Metadata met=Metadata()); Node astnode(std::string val, Node a, Node b, Node c, Metadata met=Metadata()); +Node astnode(std::string val, Node a, Node b, + Node c, Node d, Metadata met=Metadata()); // Number of tokens in a tree int treeSize(Node prog); @@ -74,6 +80,9 @@ std::string joinLines(std::vector lines); // Indent all lines by 4 spaces std::string indentLines(std::string inp); +// Converts binary to simple numeric format +std::string binToNumeric(std::string inp); + // Converts string to simple numeric format std::string strToNumeric(std::string inp); @@ -98,6 +107,9 @@ bool exists(std::string fileName); //Report error void err(std::string errtext, Metadata met); +//Report warning +void warn(std::string errtext, Metadata met); + //Bin to hex std::string binToHex(std::string inp); @@ -110,4 +122,16 @@ std::string upperCase(std::string inp); //Three-int vector std::vector triple(int a, int b, int c); +//Extend node vector +std::vector extend(std::vector a, std::vector b); + +// Is the number decimal? +bool isDecimal(std::string inp); + +#define asn astnode +#define tkn token +#define msi std::map +#define msn std::map +#define mss std::map + #endif diff --git a/sc/cmdline.cpp b/sc/cmdline.cpp index b44d2538c..a5fed37d6 100644 --- a/sc/cmdline.cpp +++ b/sc/cmdline.cpp @@ -10,6 +10,19 @@ int main(int argv, char** argc) { std::cerr << "Must provide a command and arguments! Try parse, rewrite, compile, assemble\n"; return 0; } + if (argv == 2 && (std::string(argc[1]) == "--help" || std::string(argc[1]) == "-h" )) { + std::cout << argc[1] << "\n"; + + std::cout << "serpent command input\n"; + std::cout << "where input -s for from stdin, a file, or interpreted as serpent code if does not exist as file."; + std::cout << "where command: \n"; + std::cout << " parse: Just parses and returns s-expression code.\n"; + std::cout << " rewrite: Parse, use rewrite rules print s-expressions of result.\n"; + std::cout << " compile: Return resulting compiled EVM code in hex.\n"; + std::cout << " assemble: Return result from step before compilation.\n"; + return 0; + } + std::string flag = ""; std::string command = argc[1]; std::string input; From c4ed74cc8ba923a2c15ac4f4e04962df5eec3727 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 18 Dec 2014 16:27:07 +0100 Subject: [PATCH 589/641] Additional serpent files. --- libserpent/functions.cpp | 203 ++++++++++++++++++++++ libserpent/functions.h | 39 +++++ libserpent/opcodes.cpp | 154 +++++++++++++++++ libserpent/optimize.cpp | 98 +++++++++++ libserpent/optimize.h | 19 +++ libserpent/preprocess.cpp | 327 ++++++++++++++++++++++++++++++++++++ libserpent/preprocess.h | 50 ++++++ libserpent/rewriteutils.cpp | 211 +++++++++++++++++++++++ libserpent/rewriteutils.h | 76 +++++++++ 9 files changed, 1177 insertions(+) create mode 100644 libserpent/functions.cpp create mode 100644 libserpent/functions.h create mode 100644 libserpent/opcodes.cpp create mode 100644 libserpent/optimize.cpp create mode 100644 libserpent/optimize.h create mode 100644 libserpent/preprocess.cpp create mode 100644 libserpent/preprocess.h create mode 100644 libserpent/rewriteutils.cpp create mode 100644 libserpent/rewriteutils.h diff --git a/libserpent/functions.cpp b/libserpent/functions.cpp new file mode 100644 index 000000000..78e12e84a --- /dev/null +++ b/libserpent/functions.cpp @@ -0,0 +1,203 @@ +#include +#include +#include +#include +#include "util.h" +#include "lllparser.h" +#include "bignum.h" +#include "optimize.h" +#include "rewriteutils.h" +#include "preprocess.h" +#include "functions.h" + +std::string getSignature(std::vector args) { + std::string o; + for (unsigned i = 0; i < args.size(); i++) { + if (args[i].val == ":" && args[i].args[1].val == "s") + o += "s"; + else if (args[i].val == ":" && args[i].args[1].val == "a") + o += "a"; + else + o += "i"; + } + return o; +} + +// Convert a list of arguments into a node containing a +// < datastart, datasz > pair + +Node packArguments(std::vector args, std::string sig, + int funId, Metadata m) { + // Plain old 32 byte arguments + std::vector nargs; + // Variable-sized arguments + std::vector vargs; + // Variable sizes + std::vector sizes; + // Is a variable an array? + std::vector isArray; + // Fill up above three argument lists + int argCount = 0; + for (unsigned i = 0; i < args.size(); i++) { + Metadata m = args[i].metadata; + if (args[i].val == "=") { + // do nothing + } + else { + // Determine the correct argument type + char argType; + if (sig.size() > 0) { + if (argCount >= (signed)sig.size()) + err("Too many args", m); + argType = sig[argCount]; + } + else argType = 'i'; + // Integer (also usable for short strings) + if (argType == 'i') { + if (args[i].val == ":") + err("Function asks for int, provided string or array", m); + nargs.push_back(args[i]); + } + // Long string + else if (argType == 's') { + if (args[i].val != ":") + err("Must specify string length", m); + vargs.push_back(args[i].args[0]); + sizes.push_back(args[i].args[1]); + isArray.push_back(false); + } + // Array + else if (argType == 'a') { + if (args[i].val != ":") + err("Must specify array length", m); + vargs.push_back(args[i].args[0]); + sizes.push_back(args[i].args[1]); + isArray.push_back(true); + } + else err("Invalid arg type in signature", m); + argCount++; + } + } + int static_arg_size = 1 + (vargs.size() + nargs.size()) * 32; + // Start off by saving the size variables and calculating the total + msn kwargs; + kwargs["funid"] = tkn(utd(funId), m); + std::string pattern = + "(with _sztot "+utd(static_arg_size)+" " + " (with _sizes (alloc "+utd(sizes.size() * 32)+") " + " (seq "; + for (unsigned i = 0; i < sizes.size(); i++) { + std::string sizeIncrement = + isArray[i] ? "(mul 32 _x)" : "_x"; + pattern += + "(with _x $sz"+utd(i)+"(seq " + " (mstore (add _sizes "+utd(i * 32)+") _x) " + " (set _sztot (add _sztot "+sizeIncrement+" )))) "; + kwargs["sz"+utd(i)] = sizes[i]; + } + // Allocate memory, and set first data byte + pattern += + "(with _datastart (alloc (add _sztot 32)) (seq " + " (mstore8 _datastart $funid) "; + // Copy over size variables + for (unsigned i = 0; i < sizes.size(); i++) { + int v = 1 + i * 32; + pattern += + " (mstore " + " (add _datastart "+utd(v)+") " + " (mload (add _sizes "+utd(v-1)+"))) "; + } + // Store normal arguments + for (unsigned i = 0; i < nargs.size(); i++) { + int v = 1 + (i + sizes.size()) * 32; + pattern += + " (mstore (add _datastart "+utd(v)+") $"+utd(i)+") "; + kwargs[utd(i)] = nargs[i]; + } + // Loop through variable-sized arguments, store them + pattern += + " (with _pos (add _datastart "+utd(static_arg_size)+") (seq"; + for (unsigned i = 0; i < vargs.size(); i++) { + std::string copySize = + isArray[i] ? "(mul 32 (mload (add _sizes "+utd(i * 32)+")))" + : "(mload (add _sizes "+utd(i * 32)+"))"; + pattern += + " (unsafe_mcopy _pos $vl"+utd(i)+" "+copySize+") " + " (set _pos (add _pos "+copySize+")) "; + kwargs["vl"+utd(i)] = vargs[i]; + } + // Return a 2-item array containing the start and size + pattern += " (array_lit _datastart _sztot))))))))"; + std::string prefix = "_temp_"+mkUniqueToken(); + // Fill in pattern, return triple + return subst(parseLLL(pattern), kwargs, prefix, m); +} + +// Create a node for argument unpacking +Node unpackArguments(std::vector vars, Metadata m) { + std::vector varNames; + std::vector longVarNames; + std::vector longVarIsArray; + // Fill in variable and long variable names, as well as which + // long variables are arrays and which are strings + for (unsigned i = 0; i < vars.size(); i++) { + if (vars[i].val == ":") { + if (vars[i].args.size() != 2) + err("Malformed def!", m); + longVarNames.push_back(vars[i].args[0].val); + std::string tag = vars[i].args[1].val; + if (tag == "s") + longVarIsArray.push_back(false); + else if (tag == "a") + longVarIsArray.push_back(true); + else + err("Function value can only be string or array", m); + } + else { + varNames.push_back(vars[i].val); + } + } + std::vector sub; + if (!varNames.size() && !longVarNames.size()) { + // do nothing if we have no arguments + } + else { + std::vector varNodes; + for (unsigned i = 0; i < longVarNames.size(); i++) + varNodes.push_back(token(longVarNames[i], m)); + for (unsigned i = 0; i < varNames.size(); i++) + varNodes.push_back(token(varNames[i], m)); + // Copy over variable lengths and short variables + for (unsigned i = 0; i < varNodes.size(); i++) { + int pos = 1 + i * 32; + std::string prefix = (i < longVarNames.size()) ? "_len_" : ""; + sub.push_back(asn("untyped", asn("set", + token(prefix+varNodes[i].val, m), + asn("calldataload", tkn(utd(pos), m), m), + m))); + } + // Copy over long variables + if (longVarNames.size() > 0) { + std::vector sub2; + int pos = varNodes.size() * 32 + 1; + Node tot = tkn("_tot", m); + for (unsigned i = 0; i < longVarNames.size(); i++) { + Node var = tkn(longVarNames[i], m); + Node varlen = longVarIsArray[i] + ? asn("mul", tkn("32", m), tkn("_len_"+longVarNames[i], m)) + : tkn("_len_"+longVarNames[i], m); + sub2.push_back(asn("untyped", + asn("set", var, asn("alloc", varlen)))); + sub2.push_back(asn("calldatacopy", var, tot, varlen)); + sub2.push_back(asn("set", tot, asn("add", tot, varlen))); + } + std::string prefix = "_temp_"+mkUniqueToken(); + sub.push_back(subst( + astnode("with", tot, tkn(utd(pos), m), asn("seq", sub2)), + msn(), + prefix, + m)); + } + } + return asn("seq", sub, m); +} diff --git a/libserpent/functions.h b/libserpent/functions.h new file mode 100644 index 000000000..68a1c69ce --- /dev/null +++ b/libserpent/functions.h @@ -0,0 +1,39 @@ +#ifndef ETHSERP_FUNCTIONS +#define ETHSERP_FUNCTIONS + +#include +#include +#include +#include +#include "util.h" +#include "lllparser.h" +#include "bignum.h" +#include "optimize.h" +#include "rewriteutils.h" +#include "preprocess.h" + + +class argPack { + public: + argPack(Node a, Node b, Node c) { + pre = a; + datastart = b; + datasz = c; + } + Node pre; + Node datastart; + Node datasz; +}; + +// Get a signature from a function +std::string getSignature(std::vector args); + +// Convert a list of arguments into a node +// triple, given the signature of a function +Node packArguments(std::vector args, std::string sig, + int funId, Metadata m); + +// Create a node for argument unpacking +Node unpackArguments(std::vector vars, Metadata m); + +#endif diff --git a/libserpent/opcodes.cpp b/libserpent/opcodes.cpp new file mode 100644 index 000000000..b24144e46 --- /dev/null +++ b/libserpent/opcodes.cpp @@ -0,0 +1,154 @@ +#include +#include +#include +#include +#include "opcodes.h" +#include "util.h" +#include "bignum.h" + +Mapping mapping[] = { + Mapping("STOP", 0x00, 0, 0), + Mapping("ADD", 0x01, 2, 1), + Mapping("MUL", 0x02, 2, 1), + Mapping("SUB", 0x03, 2, 1), + Mapping("DIV", 0x04, 2, 1), + Mapping("SDIV", 0x05, 2, 1), + Mapping("MOD", 0x06, 2, 1), + Mapping("SMOD", 0x07, 2, 1), + Mapping("ADDMOD", 0x08, 3, 1), + Mapping("MULMOD", 0x09, 3, 1), + Mapping("EXP", 0x0a, 2, 1), + Mapping("SIGNEXTEND", 0x0b, 2, 1), + Mapping("LT", 0x10, 2, 1), + Mapping("GT", 0x11, 2, 1), + Mapping("SLT", 0x12, 2, 1), + Mapping("SGT", 0x13, 2, 1), + Mapping("EQ", 0x14, 2, 1), + Mapping("ISZERO", 0x15, 1, 1), + Mapping("AND", 0x16, 2, 1), + Mapping("OR", 0x17, 2, 1), + Mapping("XOR", 0x18, 2, 1), + Mapping("NOT", 0x19, 1, 1), + Mapping("BYTE", 0x1a, 2, 1), + Mapping("SHA3", 0x20, 2, 1), + Mapping("ADDRESS", 0x30, 0, 1), + Mapping("BALANCE", 0x31, 1, 1), + Mapping("ORIGIN", 0x32, 0, 1), + Mapping("CALLER", 0x33, 0, 1), + Mapping("CALLVALUE", 0x34, 0, 1), + Mapping("CALLDATALOAD", 0x35, 1, 1), + Mapping("CALLDATASIZE", 0x36, 0, 1), + Mapping("CALLDATACOPY", 0x37, 3, 0), + Mapping("CODESIZE", 0x38, 0, 1), + Mapping("CODECOPY", 0x39, 3, 0), + Mapping("GASPRICE", 0x3a, 0, 1), + Mapping("EXTCODESIZE", 0x3b, 1, 1), + Mapping("EXTCODECOPY", 0x3c, 4, 0), + Mapping("PREVHASH", 0x40, 0, 1), + Mapping("COINBASE", 0x41, 0, 1), + Mapping("TIMESTAMP", 0x42, 0, 1), + Mapping("NUMBER", 0x43, 0, 1), + Mapping("DIFFICULTY", 0x44, 0, 1), + Mapping("GASLIMIT", 0x45, 0, 1), + Mapping("POP", 0x50, 1, 0), + Mapping("MLOAD", 0x51, 1, 1), + Mapping("MSTORE", 0x52, 2, 0), + Mapping("MSTORE8", 0x53, 2, 0), + Mapping("SLOAD", 0x54, 1, 1), + Mapping("SSTORE", 0x55, 2, 0), + Mapping("JUMP", 0x56, 1, 0), + Mapping("JUMPI", 0x57, 2, 0), + Mapping("PC", 0x58, 0, 1), + Mapping("MSIZE", 0x59, 0, 1), + Mapping("GAS", 0x5a, 0, 1), + Mapping("JUMPDEST", 0x5b, 0, 0), + Mapping("LOG0", 0xa0, 2, 0), + Mapping("LOG1", 0xa1, 3, 0), + Mapping("LOG2", 0xa2, 4, 0), + Mapping("LOG3", 0xa3, 5, 0), + Mapping("LOG4", 0xa4, 6, 0), + Mapping("CREATE", 0xf0, 3, 1), + Mapping("CALL", 0xf1, 7, 1), + Mapping("CALLCODE", 0xf2, 7, 1), + Mapping("RETURN", 0xf3, 2, 0), + Mapping("SUICIDE", 0xff, 1, 0), + Mapping("---END---", 0x00, 0, 0), +}; + +std::map > opcodes; +std::map reverseOpcodes; + +// Fetches everything EXCEPT PUSH1..32 +std::pair > _opdata(std::string ops, int opi) { + if (!opcodes.size()) { + int i = 0; + while (mapping[i].op != "---END---") { + Mapping mi = mapping[i]; + opcodes[mi.op] = triple(mi.opcode, mi.in, mi.out); + i++; + } + for (i = 1; i <= 16; i++) { + opcodes["DUP"+unsignedToDecimal(i)] = triple(0x7f + i, i, i+1); + opcodes["SWAP"+unsignedToDecimal(i)] = triple(0x8f + i, i+1, i+1); + } + for (std::map >::iterator it=opcodes.begin(); + it != opcodes.end(); + it++) { + reverseOpcodes[(*it).second[0]] = (*it).first; + } + } + ops = upperCase(ops); + std::string op; + std::vector opdata; + op = reverseOpcodes.count(opi) ? reverseOpcodes[opi] : ""; + opdata = opcodes.count(ops) ? opcodes[ops] : triple(-1, -1, -1); + return std::pair >(op, opdata); +} + +int opcode(std::string op) { + return _opdata(op, -1).second[0]; +} + +int opinputs(std::string op) { + return _opdata(op, -1).second[1]; +} + +int opoutputs(std::string op) { + return _opdata(op, -1).second[2]; +} + +std::string op(int opcode) { + return _opdata("", opcode).first; +} + +std::string lllSpecials[][3] = { + { "ref", "1", "1" }, + { "get", "1", "1" }, + { "set", "2", "2" }, + { "with", "3", "3" }, + { "comment", "0", "2147483647" }, + { "ops", "0", "2147483647" }, + { "lll", "2", "2" }, + { "seq", "0", "2147483647" }, + { "if", "3", "3" }, + { "unless", "2", "2" }, + { "until", "2", "2" }, + { "alloc", "1", "1" }, + { "---END---", "0", "0" }, +}; + +std::map > lllMap; + +// Is a function name one of the valid functions above? +bool isValidLLLFunc(std::string f, int argc) { + if (lllMap.size() == 0) { + for (int i = 0; ; i++) { + if (lllSpecials[i][0] == "---END---") break; + lllMap[lllSpecials[i][0]] = std::pair( + dtu(lllSpecials[i][1]), dtu(lllSpecials[i][2])); + } + } + return lllMap.count(f) + && argc >= lllMap[f].first + && argc <= lllMap[f].second; +} diff --git a/libserpent/optimize.cpp b/libserpent/optimize.cpp new file mode 100644 index 000000000..e689fcb69 --- /dev/null +++ b/libserpent/optimize.cpp @@ -0,0 +1,98 @@ +#include +#include +#include +#include +#include "util.h" +#include "lllparser.h" +#include "bignum.h" + +// Compile-time arithmetic calculations +Node optimize(Node inp) { + if (inp.type == TOKEN) { + Node o = tryNumberize(inp); + if (decimalGt(o.val, tt256, true)) + err("Value too large (exceeds 32 bytes or 2^256)", inp.metadata); + return o; + } + for (unsigned i = 0; i < inp.args.size(); i++) { + inp.args[i] = optimize(inp.args[i]); + } + // Arithmetic-specific transform + if (inp.val == "+") inp.val = "add"; + if (inp.val == "*") inp.val = "mul"; + if (inp.val == "-") inp.val = "sub"; + if (inp.val == "/") inp.val = "sdiv"; + if (inp.val == "^") inp.val = "exp"; + if (inp.val == "**") inp.val = "exp"; + if (inp.val == "%") inp.val = "smod"; + // Degenerate cases for add and mul + if (inp.args.size() == 2) { + if (inp.val == "add" && inp.args[0].type == TOKEN && + inp.args[0].val == "0") { + Node x = inp.args[1]; + inp = x; + } + if (inp.val == "add" && inp.args[1].type == TOKEN && + inp.args[1].val == "0") { + Node x = inp.args[0]; + inp = x; + } + if (inp.val == "mul" && inp.args[0].type == TOKEN && + inp.args[0].val == "1") { + Node x = inp.args[1]; + inp = x; + } + if (inp.val == "mul" && inp.args[1].type == TOKEN && + inp.args[1].val == "1") { + Node x = inp.args[0]; + inp = x; + } + } + // Arithmetic computation + if (inp.args.size() == 2 + && inp.args[0].type == TOKEN + && inp.args[1].type == TOKEN) { + std::string o; + if (inp.val == "add") { + o = decimalMod(decimalAdd(inp.args[0].val, inp.args[1].val), tt256); + } + else if (inp.val == "sub") { + if (decimalGt(inp.args[0].val, inp.args[1].val, true)) + o = decimalSub(inp.args[0].val, inp.args[1].val); + } + else if (inp.val == "mul") { + o = decimalMod(decimalMul(inp.args[0].val, inp.args[1].val), tt256); + } + else if (inp.val == "div" && inp.args[1].val != "0") { + o = decimalDiv(inp.args[0].val, inp.args[1].val); + } + else if (inp.val == "sdiv" && inp.args[1].val != "0" + && decimalGt(tt255, inp.args[0].val) + && decimalGt(tt255, inp.args[1].val)) { + o = decimalDiv(inp.args[0].val, inp.args[1].val); + } + else if (inp.val == "mod" && inp.args[1].val != "0") { + o = decimalMod(inp.args[0].val, inp.args[1].val); + } + else if (inp.val == "smod" && inp.args[1].val != "0" + && decimalGt(tt255, inp.args[0].val) + && decimalGt(tt255, inp.args[1].val)) { + o = decimalMod(inp.args[0].val, inp.args[1].val); + } + else if (inp.val == "exp") { + o = decimalModExp(inp.args[0].val, inp.args[1].val, tt256); + } + if (o.length()) return token(o, inp.metadata); + } + return inp; +} + +// Is a node degenerate (ie. trivial to calculate) ? +bool isDegenerate(Node n) { + return optimize(n).type == TOKEN; +} + +// Is a node purely arithmetic? +bool isPureArithmetic(Node n) { + return isNumberLike(optimize(n)); +} diff --git a/libserpent/optimize.h b/libserpent/optimize.h new file mode 100644 index 000000000..06ea3bba1 --- /dev/null +++ b/libserpent/optimize.h @@ -0,0 +1,19 @@ +#ifndef ETHSERP_OPTIMIZER +#define ETHSERP_OPTIMIZER + +#include +#include +#include +#include +#include "util.h" + +// Compile-time arithmetic calculations +Node optimize(Node inp); + +// Is a node degenerate (ie. trivial to calculate) ? +bool isDegenerate(Node n); + +// Is a node purely arithmetic? +bool isPureArithmetic(Node n); + +#endif diff --git a/libserpent/preprocess.cpp b/libserpent/preprocess.cpp new file mode 100644 index 000000000..2df149945 --- /dev/null +++ b/libserpent/preprocess.cpp @@ -0,0 +1,327 @@ +#include +#include +#include +#include +#include "util.h" +#include "lllparser.h" +#include "bignum.h" +#include "rewriteutils.h" +#include "optimize.h" +#include "preprocess.h" +#include "functions.h" +#include "opcodes.h" + +// Convert a function of the form (def (f x y z) (do stuff)) into +// (if (first byte of ABI is correct) (seq (setup x y z) (do stuff))) +Node convFunction(Node node, int functionCount) { + std::string prefix = "_temp"+mkUniqueToken()+"_"; + Metadata m = node.metadata; + + if (node.args.size() != 2) + err("Malformed def!", m); + // Collect the list of variable names and variable byte counts + Node unpack = unpackArguments(node.args[0].args, m); + // And the actual code + Node body = node.args[1]; + // Main LLL-based function body + return astnode("if", + astnode("eq", + astnode("get", token("__funid", m), m), + token(unsignedToDecimal(functionCount), m), + m), + astnode("seq", unpack, body, m)); +} + +// Populate an svObj with the arguments needed to determine +// the storage position of a node +svObj getStorageVars(svObj pre, Node node, std::string prefix, + int index) { + Metadata m = node.metadata; + if (!pre.globalOffset.size()) pre.globalOffset = "0"; + std::vector h; + std::vector coefficients; + // Array accesses or atoms + if (node.val == "access" || node.type == TOKEN) { + std::string tot = "1"; + h = listfyStorageAccess(node); + coefficients.push_back("1"); + for (unsigned i = h.size() - 1; i >= 1; i--) { + // Array sizes must be constant or at least arithmetically + // evaluable at compile time + if (!isPureArithmetic(h[i])) + err("Array size must be fixed value", m); + // Create a list of the coefficient associated with each + // array index + coefficients.push_back(decimalMul(coefficients.back(), h[i].val)); + } + } + // Tuples + else { + int startc; + // Handle the (fun args...) case + if (node.val == "fun") { + startc = 1; + h = listfyStorageAccess(node.args[0]); + } + // Handle the ( args...) case, which + // the serpent parser produces when the function + // is a simple name and not a complex astnode + else { + startc = 0; + h = listfyStorageAccess(token(node.val, m)); + } + svObj sub = pre; + sub.globalOffset = "0"; + // Evaluate tuple elements recursively + for (unsigned i = startc; i < node.args.size(); i++) { + sub = getStorageVars(sub, + node.args[i], + prefix+h[0].val.substr(2)+".", + i-startc); + } + coefficients.push_back(sub.globalOffset); + for (unsigned i = h.size() - 1; i >= 1; i--) { + // Array sizes must be constant or at least arithmetically + // evaluable at compile time + if (!isPureArithmetic(h[i])) + err("Array size must be fixed value", m); + // Create a list of the coefficient associated with each + // array index + coefficients.push_back(decimalMul(coefficients.back(), h[i].val)); + } + pre.offsets = sub.offsets; + pre.coefficients = sub.coefficients; + pre.nonfinal = sub.nonfinal; + pre.nonfinal[prefix+h[0].val.substr(2)] = true; + } + pre.coefficients[prefix+h[0].val.substr(2)] = coefficients; + pre.offsets[prefix+h[0].val.substr(2)] = pre.globalOffset; + pre.indices[prefix+h[0].val.substr(2)] = index; + if (decimalGt(tt176, coefficients.back())) + pre.globalOffset = decimalAdd(pre.globalOffset, coefficients.back()); + return pre; +} + +// Preprocess input containing functions +// +// localExterns is a map of the form, eg, +// +// { x: { foo: 0, bar: 1, baz: 2 }, y: { qux: 0, foo: 1 } ... } +// +// localExternSigs is a map of the form, eg, +// +// { x : { foo: iii, bar: iis, baz: ia }, y: { qux: i, foo: as } ... } +// +// Signifying that x.foo = 0, x.baz = 2, y.foo = 1, etc +// and that x.foo has three integers as arguments, x.bar has two +// integers and a variable-length string, and baz has an integer +// and an array +// +// globalExterns is a one-level map, eg from above +// +// { foo: 1, bar: 1, baz: 2, qux: 0 } +// +// globalExternSigs is a one-level map, eg from above +// +// { foo: as, bar: iis, baz: ia, qux: i} +// +// Note that globalExterns and globalExternSigs may be ambiguous +// Also, a null signature implies an infinite tail of integers +preprocessResult preprocessInit(Node inp) { + Metadata m = inp.metadata; + if (inp.val != "seq") + inp = astnode("seq", inp, m); + std::vector empty = std::vector(); + Node init = astnode("seq", empty, m); + Node shared = astnode("seq", empty, m); + std::vector any; + std::vector functions; + preprocessAux out = preprocessAux(); + out.localExterns["self"] = std::map(); + int functionCount = 0; + int storageDataCount = 0; + for (unsigned i = 0; i < inp.args.size(); i++) { + Node obj = inp.args[i]; + // Functions + if (obj.val == "def") { + if (obj.args.size() == 0) + err("Empty def", m); + std::string funName = obj.args[0].val; + // Init, shared and any are special functions + if (funName == "init" || funName == "shared" || funName == "any") { + if (obj.args[0].args.size()) + err(funName+" cannot have arguments", m); + } + if (funName == "init") init = obj.args[1]; + else if (funName == "shared") shared = obj.args[1]; + else if (funName == "any") any.push_back(obj.args[1]); + else { + // Other functions + functions.push_back(convFunction(obj, functionCount)); + out.localExterns["self"][obj.args[0].val] = functionCount; + out.localExternSigs["self"][obj.args[0].val] + = getSignature(obj.args[0].args); + functionCount++; + } + } + // Extern declarations + else if (obj.val == "extern") { + std::string externName = obj.args[0].val; + Node al = obj.args[1]; + if (!out.localExterns.count(externName)) + out.localExterns[externName] = std::map(); + for (unsigned i = 0; i < al.args.size(); i++) { + if (al.args[i].val == ":") { + std::string v = al.args[i].args[0].val; + std::string sig = al.args[i].args[1].val; + out.globalExterns[v] = i; + out.globalExternSigs[v] = sig; + out.localExterns[externName][v] = i; + out.localExternSigs[externName][v] = sig; + } + else { + std::string v = al.args[i].val; + out.globalExterns[v] = i; + out.globalExternSigs[v] = ""; + out.localExterns[externName][v] = i; + out.localExternSigs[externName][v] = ""; + } + } + } + // Custom macros + else if (obj.val == "macro" || (obj.val == "fun" && obj.args[0].val == "macro")) { + // Rules for valid macros: + // + // There are only four categories of valid macros: + // + // 1. a macro where the outer function is something + // which is NOT an existing valid function/extern/datum + // 2. a macro of the form set(c(x), d) where c must NOT + // be an existing valid function/extern/datum + // 3. something of the form access(c(x)), where c must NOT + // be an existing valid function/extern/datum + // 4. something of the form set(access(c(x)), d) where c must + // NOT be an existing valid function/extern/datum + // 5. something of the form with(c(x), d, e) where c must + // NOT be an existing valid function/extern/datum + bool valid = false; + Node pattern; + Node substitution; + int priority; + // Priority not set: default zero + if (obj.val == "macro") { + pattern = obj.args[0]; + substitution = obj.args[1]; + priority = 0; + } + // Specified priority + else { + pattern = obj.args[1]; + substitution = obj.args[2]; + if (obj.args[0].args.size()) + priority = dtu(obj.args[0].args[0].val); + else + priority = 0; + } + if (opcode(pattern.val) < 0 && !isValidFunctionName(pattern.val)) + valid = true; + if (pattern.val == "set" && + opcode(pattern.args[0].val) < 0 && + !isValidFunctionName(pattern.args[0].val)) + valid = true; + if (pattern.val == "access" && + opcode(pattern.args[0].val) < 0 && + !isValidFunctionName(pattern.args[0].val)) + if (pattern.val == "set" && + pattern.args[0].val == "access" && + opcode(pattern.args[0].args[0].val) < 0 && + !isValidFunctionName(pattern.args[0].args[0].val)) + valid = true; + if (pattern.val == "with" && + opcode(pattern.args[0].val) < 0 && + !isValidFunctionName(pattern.args[0].val)) + valid = true; + if (valid) { + if (!out.customMacros.count(priority)) + out.customMacros[priority] = rewriteRuleSet(); + out.customMacros[priority].addRule + (rewriteRule(pattern, substitution)); + } + else warn("Macro does not fit valid template: "+printSimple(pattern), m); + } + // Variable types + else if (obj.val == "type") { + std::string typeName = obj.args[0].val; + std::vector vars = obj.args[1].args; + for (unsigned i = 0; i < vars.size(); i++) + out.types[vars[i].val] = typeName; + } + // Storage variables/structures + else if (obj.val == "data") { + out.storageVars = getStorageVars(out.storageVars, + obj.args[0], + "", + storageDataCount); + storageDataCount += 1; + } + else any.push_back(obj); + } + // Set up top-level AST structure + std::vector main; + if (shared.args.size()) main.push_back(shared); + if (init.args.size()) main.push_back(init); + + std::vector code; + if (shared.args.size()) code.push_back(shared); + for (unsigned i = 0; i < any.size(); i++) + code.push_back(any[i]); + for (unsigned i = 0; i < functions.size(); i++) + code.push_back(functions[i]); + Node codeNode; + if (functions.size() > 0) { + codeNode = astnode("with", + token("__funid", m), + astnode("byte", + token("0", m), + astnode("calldataload", token("0", m), m), + m), + astnode("seq", code, m), + m); + } + else codeNode = astnode("seq", code, m); + main.push_back(astnode("~return", + token("0", m), + astnode("lll", + codeNode, + token("0", m), + m), + m)); + + + Node result; + if (main.size() == 1) result = main[0]; + else result = astnode("seq", main, inp.metadata); + return preprocessResult(result, out); +} + +preprocessResult processTypes (preprocessResult pr) { + preprocessAux aux = pr.second; + Node node = pr.first; + if (node.type == TOKEN && aux.types.count(node.val)) + node = asn(aux.types[node.val], node, node.metadata); + else if (node.val == "untyped") + return preprocessResult(node.args[0], aux); + else if (node.val == "outer") + return preprocessResult(node, aux); + else { + for (unsigned i = 0; i < node.args.size(); i++) { + node.args[i] = + processTypes(preprocessResult(node.args[i], aux)).first; + } + } + return preprocessResult(node, aux); +} + +preprocessResult preprocess(Node n) { + return processTypes(preprocessInit(n)); +} diff --git a/libserpent/preprocess.h b/libserpent/preprocess.h new file mode 100644 index 000000000..321fb8527 --- /dev/null +++ b/libserpent/preprocess.h @@ -0,0 +1,50 @@ +#ifndef ETHSERP_PREPROCESSOR +#define ETHSERP_PREPROCESSOR + +#include +#include +#include +#include +#include "util.h" +#include "rewriteutils.h" + +// Storage variable index storing object +struct svObj { + std::map offsets; + std::map indices; + std::map > coefficients; + std::map nonfinal; + std::string globalOffset; +}; + + + +// Preprocessing result storing object +class preprocessAux { + public: + preprocessAux() { + globalExterns = std::map(); + localExterns = std::map >(); + localExterns["self"] = std::map(); + } + std::map globalExterns; + std::map globalExternSigs; + std::map > localExterns; + std::map > localExternSigs; + std::map customMacros; + std::map types; + svObj storageVars; +}; + +#define preprocessResult std::pair + +// Populate an svObj with the arguments needed to determine +// the storage position of a node +svObj getStorageVars(svObj pre, Node node, std::string prefix="", + int index=0); + +// Preprocess a function (see cpp for details) +preprocessResult preprocess(Node inp); + + +#endif diff --git a/libserpent/rewriteutils.cpp b/libserpent/rewriteutils.cpp new file mode 100644 index 000000000..0d810bdbc --- /dev/null +++ b/libserpent/rewriteutils.cpp @@ -0,0 +1,211 @@ +#include +#include +#include +#include +#include "util.h" +#include "lllparser.h" +#include "bignum.h" +#include "rewriteutils.h" +#include "optimize.h" + +// Valid functions and their min and max argument counts +std::string validFunctions[][3] = { + { "if", "2", "3" }, + { "unless", "2", "2" }, + { "while", "2", "2" }, + { "until", "2", "2" }, + { "alloc", "1", "1" }, + { "array", "1", "1" }, + { "call", "2", tt256 }, + { "callcode", "2", tt256 }, + { "create", "1", "4" }, + { "getch", "2", "2" }, + { "setch", "3", "3" }, + { "sha3", "1", "2" }, + { "return", "1", "2" }, + { "inset", "1", "1" }, + { "min", "2", "2" }, + { "max", "2", "2" }, + { "array_lit", "0", tt256 }, + { "seq", "0", tt256 }, + { "log", "1", "6" }, + { "outer", "1", "1" }, + { "set", "2", "2" }, + { "get", "1", "1" }, + { "ref", "1", "1" }, + { "declare", "1", tt256 }, + { "with", "3", "3" }, + { "outer", "1", "1" }, + { "mcopy", "3", "3" }, + { "unsafe_mcopy", "3", "3" }, + { "save", "3", "3" }, + { "load", "2", "2" }, + { "---END---", "", "" } //Keep this line at the end of the list +}; + +std::map vfMap; + +// Is a function name one of the valid functions above? +bool isValidFunctionName(std::string f) { + if (vfMap.size() == 0) { + for (int i = 0; ; i++) { + if (validFunctions[i][0] == "---END---") break; + vfMap[validFunctions[i][0]] = true; + } + } + return vfMap.count(f); +} + +// Cool function for debug purposes (named cerrStringList to make +// all prints searchable via 'cerr') +void cerrStringList(std::vector s, std::string suffix) { + for (unsigned i = 0; i < s.size(); i++) std::cerr << s[i] << " "; + std::cerr << suffix << "\n"; +} + +// Convert: +// self.cow -> ["cow"] +// self.horse[0] -> ["horse", "0"] +// self.a[6][7][self.storage[3]].chicken[9] -> +// ["6", "7", (sload 3), "chicken", "9"] +std::vector listfyStorageAccess(Node node) { + std::vector out; + std::vector nodez; + nodez.push_back(node); + while (1) { + if (nodez.back().type == TOKEN) { + out.push_back(token("--" + nodez.back().val, node.metadata)); + std::vector outrev; + for (int i = (signed)out.size() - 1; i >= 0; i--) { + outrev.push_back(out[i]); + } + return outrev; + } + if (nodez.back().val == ".") + nodez.back().args[1].val = "--" + nodez.back().args[1].val; + if (nodez.back().args.size() == 0) + err("Error parsing storage variable statement", node.metadata); + if (nodez.back().args.size() == 1) + out.push_back(token(tt256m1, node.metadata)); + else + out.push_back(nodez.back().args[1]); + nodez.push_back(nodez.back().args[0]); + } +} + +// Is the given node something of the form +// self.cow +// self.horse[0] +// self.a[6][7][self.storage[3]].chicken[9] +bool isNodeStorageVariable(Node node) { + std::vector nodez; + nodez.push_back(node); + while (1) { + if (nodez.back().type == TOKEN) return false; + if (nodez.back().args.size() == 0) return false; + if (nodez.back().val != "." && nodez.back().val != "access") + return false; + if (nodez.back().args[0].val == "self") return true; + nodez.push_back(nodez.back().args[0]); + } +} + +// Main pattern matching routine, for those patterns that can be expressed +// using our standard mini-language above +// +// Returns two values. First, a boolean to determine whether the node matches +// the pattern, second, if the node does match then a map mapping variables +// in the pattern to nodes +matchResult match(Node p, Node n) { + matchResult o; + o.success = false; + if (p.type == TOKEN) { + if (p.val == n.val && n.type == TOKEN) o.success = true; + else if (p.val[0] == '$' || p.val[0] == '@') { + o.success = true; + o.map[p.val.substr(1)] = n; + } + } + else if (n.type==TOKEN || p.val!=n.val || p.args.size()!=n.args.size()) { + // do nothing + } + else { + for (unsigned i = 0; i < p.args.size(); i++) { + matchResult oPrime = match(p.args[i], n.args[i]); + if (!oPrime.success) { + o.success = false; + return o; + } + for (std::map::iterator it = oPrime.map.begin(); + it != oPrime.map.end(); + it++) { + o.map[(*it).first] = (*it).second; + } + } + o.success = true; + } + return o; +} + + +// Fills in the pattern with a dictionary mapping variable names to +// nodes (these dicts are generated by match). Match and subst together +// create a full pattern-matching engine. +Node subst(Node pattern, + std::map dict, + std::string varflag, + Metadata m) { + // Swap out patterns at the token level + if (pattern.metadata.ln == -1) + pattern.metadata = m; + if (pattern.type == TOKEN && + pattern.val[0] == '$') { + if (dict.count(pattern.val.substr(1))) { + return dict[pattern.val.substr(1)]; + } + else { + return token(varflag + pattern.val.substr(1), m); + } + } + // Other tokens are untouched + else if (pattern.type == TOKEN) { + return pattern; + } + // Substitute recursively for ASTs + else { + std::vector args; + for (unsigned i = 0; i < pattern.args.size(); i++) { + args.push_back(subst(pattern.args[i], dict, varflag, m)); + } + return asn(pattern.val, args, m); + } +} + +// Transforms a sequence containing two-argument with statements +// into a statement containing those statements in nested form +Node withTransform (Node source) { + Node o = token("--"); + Metadata m = source.metadata; + std::vector args; + for (int i = source.args.size() - 1; i >= 0; i--) { + Node a = source.args[i]; + if (a.val == "with" && a.args.size() == 2) { + std::vector flipargs; + for (int j = args.size() - 1; j >= 0; j--) + flipargs.push_back(args[i]); + if (o.val != "--") + flipargs.push_back(o); + o = asn("with", a.args[0], a.args[1], asn("seq", flipargs, m), m); + args = std::vector(); + } + else { + args.push_back(a); + } + } + std::vector flipargs; + for (int j = args.size() - 1; j >= 0; j--) + flipargs.push_back(args[j]); + if (o.val != "--") + flipargs.push_back(o); + return asn("seq", flipargs, m); +} diff --git a/libserpent/rewriteutils.h b/libserpent/rewriteutils.h new file mode 100644 index 000000000..3a9a837ad --- /dev/null +++ b/libserpent/rewriteutils.h @@ -0,0 +1,76 @@ +#ifndef ETHSERP_REWRITEUTILS +#define ETHSERP_REWRITEUTILS + +#include +#include +#include +#include +#include "util.h" + +// Valid functions and their min and max argument counts +extern std::string validFunctions[][3]; + +extern std::map vfMap; + +bool isValidFunctionName(std::string f); + +// Converts deep array access into ordered list of the arguments +// along the descent +std::vector listfyStorageAccess(Node node); + +// Cool function for debug purposes (named cerrStringList to make +// all prints searchable via 'cerr') +void cerrStringList(std::vector s, std::string suffix=""); + +// Is the given node something of the form +// self.cow +// self.horse[0] +// self.a[6][7][self.storage[3]].chicken[9] +bool isNodeStorageVariable(Node node); + +// Applies rewrite rules adding without wrapper +Node rewriteChunk(Node inp); + +// Match result storing object +struct matchResult { + bool success; + std::map map; +}; + +// Match node to pattern +matchResult match(Node p, Node n); + +// Substitute node using pattern +Node subst(Node pattern, + std::map dict, + std::string varflag, + Metadata m); + +Node withTransform(Node source); + +class rewriteRule { + public: + rewriteRule(Node p, Node s) { + pattern = p; + substitution = s; + } + Node pattern; + Node substitution; +}; + +class rewriteRuleSet { + public: + rewriteRuleSet() { + ruleLists = std::map >(); + } + void addRule(rewriteRule r) { + if (!ruleLists.count(r.pattern.val)) + ruleLists[r.pattern.val] = std::vector(); + ruleLists[r.pattern.val].push_back(r); + } + std::map > ruleLists; +}; + + + +#endif From 0b5b6c7cd40adc20944067bca42a9434c70a51d1 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Thu, 18 Dec 2014 16:27:17 +0100 Subject: [PATCH 590/641] Adressing some natspec issues --- libsolidity/InterfaceHandler.cpp | 4 ++-- libsolidity/Scanner.cpp | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/libsolidity/InterfaceHandler.cpp b/libsolidity/InterfaceHandler.cpp index 9ae284b40..5b5682ff1 100644 --- a/libsolidity/InterfaceHandler.cpp +++ b/libsolidity/InterfaceHandler.cpp @@ -170,7 +170,7 @@ std::string::const_iterator InterfaceHandler::parseDocTagLine(std::string::const bool _appending) { auto nlPos = std::find(_pos, _end, '\n'); - if (_appending && *_pos != ' ') + if (_appending && _pos < _end && *_pos != ' ') _tagString += " "; std::copy(_pos, nlPos, back_inserter(_tagString)); m_lastTag = _tagType; @@ -204,7 +204,7 @@ std::string::const_iterator InterfaceHandler::appendDocTagParam(std::string::con solAssert(!m_params.empty(), "Internal: Tried to append to empty parameter"); auto pair = m_params.back(); - if (*_pos != ' ') + if (_pos < _end && *_pos != ' ') pair.second += " "; auto nlPos = std::find(_pos, _end, '\n'); std::copy(_pos, nlPos, back_inserter(pair.second)); diff --git a/libsolidity/Scanner.cpp b/libsolidity/Scanner.cpp index 69b61ce4b..90a3b4545 100644 --- a/libsolidity/Scanner.cpp +++ b/libsolidity/Scanner.cpp @@ -328,6 +328,7 @@ Token::Value Scanner::scanMultiLineDocComment() void Scanner::scanToken() { + int savedPosition; m_nextToken.literal.clear(); m_nextSkippedComment.literal.clear(); Token::Value token; @@ -428,6 +429,7 @@ void Scanner::scanToken() break; case '/': // / // /* /= + savedPosition = getSourcePos(); advance(); if (m_char == '/') { @@ -436,7 +438,7 @@ void Scanner::scanToken() else if (m_char == '/') { Token::Value comment; - m_nextSkippedComment.location.start = getSourcePos(); + m_nextSkippedComment.location.start = savedPosition; comment = scanSingleLineDocComment(); m_nextSkippedComment.location.end = getSourcePos(); m_nextSkippedComment.token = comment; @@ -447,12 +449,13 @@ void Scanner::scanToken() } else if (m_char == '*') { + // /** doxygent style natspec comment if (!advance()) /* slash star comment before EOS */ token = Token::WHITESPACE; else if (m_char == '*') { Token::Value comment; - m_nextSkippedComment.location.start = getSourcePos(); + m_nextSkippedComment.location.start = savedPosition; comment = scanMultiLineDocComment(); m_nextSkippedComment.location.end = getSourcePos(); m_nextSkippedComment.token = comment; From 73593674419a4c2e2aea7a03a554b5577aa31405 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Thu, 18 Dec 2014 16:48:25 +0100 Subject: [PATCH 591/641] More multiline natspec tests and small issue fix --- libsolidity/Scanner.cpp | 4 ++-- test/solidityScanner.cpp | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/libsolidity/Scanner.cpp b/libsolidity/Scanner.cpp index 90a3b4545..124c88d92 100644 --- a/libsolidity/Scanner.cpp +++ b/libsolidity/Scanner.cpp @@ -212,7 +212,7 @@ bool Scanner::skipWhitespace() bool Scanner::skipWhitespaceExceptLF() { int const startPosition = getSourcePos(); - while (m_char == ' ' || m_char == '\t') + while (isWhiteSpace(m_char) && !isLineTerminator(m_char)) advance(); // Return whether or not we skipped any characters. return getSourcePos() != startPosition; @@ -305,7 +305,7 @@ Token::Value Scanner::scanMultiLineDocComment() endFound = true; break; } - else + else if (charsAdded) addCommentLiteralChar('\n'); } diff --git a/test/solidityScanner.cpp b/test/solidityScanner.cpp index 159e53055..355ea9e22 100644 --- a/test/solidityScanner.cpp +++ b/test/solidityScanner.cpp @@ -189,6 +189,30 @@ BOOST_AUTO_TEST_CASE(multiline_documentation_comments_parsed) BOOST_CHECK_EQUAL(scanner.getCurrentCommentLiteral(), "Send $(value / 1000) chocolates to the user"); } +BOOST_AUTO_TEST_CASE(multiline_documentation_no_stars) +{ + Scanner scanner(CharStream("some other tokens /**\n" + " Send $(value / 1000) chocolates to the user\n" + "*/")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); + BOOST_CHECK_EQUAL(scanner.getCurrentCommentLiteral(), "Send $(value / 1000) chocolates to the user"); +} + +BOOST_AUTO_TEST_CASE(multiline_documentation_whitespace_hell) +{ + Scanner scanner(CharStream("some other tokens /** \t \r \n" + "\t \r * Send $(value / 1000) chocolates to the user\n" + "*/")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); + BOOST_CHECK_EQUAL(scanner.getCurrentCommentLiteral(), "Send $(value / 1000) chocolates to the user"); +} + BOOST_AUTO_TEST_CASE(comment_before_eos) { Scanner scanner(CharStream("//")); From b162e267acee2654e000a71af05b5d93db0d613f Mon Sep 17 00:00:00 2001 From: ethdev Date: Thu, 18 Dec 2014 17:10:00 +0100 Subject: [PATCH 592/641] windows fixes --- libserpent/compiler.cpp | 2 +- libserpent/rewriteutils.cpp | 1 + libserpent/util.cpp | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libserpent/compiler.cpp b/libserpent/compiler.cpp index a3e5b1c60..886eee6df 100644 --- a/libserpent/compiler.cpp +++ b/libserpent/compiler.cpp @@ -173,7 +173,7 @@ programData opcodeify(Node node, } // Comments do nothing else if (node.val == "comment") { - Node nodelist[] = { }; + Node* nodelist = nullptr; return pd(aux, multiToken(nodelist, 0, m), 0); } // Custom operation sequence diff --git a/libserpent/rewriteutils.cpp b/libserpent/rewriteutils.cpp index 0d810bdbc..e6429434a 100644 --- a/libserpent/rewriteutils.cpp +++ b/libserpent/rewriteutils.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include "util.h" #include "lllparser.h" #include "bignum.h" diff --git a/libserpent/util.cpp b/libserpent/util.cpp index 5e83c0e41..4b99a5ea5 100644 --- a/libserpent/util.cpp +++ b/libserpent/util.cpp @@ -5,6 +5,7 @@ #include "util.h" #include "bignum.h" #include +#include #include //Token or value node constructor From d14ed2d4dc29afcce8c16a0173d7a4e87b2c5974 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 18 Dec 2014 17:04:20 +0100 Subject: [PATCH 593/641] Bit operators should bind more strongly than comparison operators. --- libsolidity/Token.h | 20 ++++++++++---------- test/SolidityNameAndTypeResolution.cpp | 10 ++++++++++ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/libsolidity/Token.h b/libsolidity/Token.h index 32656096a..897d6eaaa 100644 --- a/libsolidity/Token.h +++ b/libsolidity/Token.h @@ -107,9 +107,9 @@ namespace solidity T(COMMA, ",", 1) \ T(OR, "||", 4) \ T(AND, "&&", 5) \ - T(BIT_OR, "|", 6) \ - T(BIT_XOR, "^", 7) \ - T(BIT_AND, "&", 8) \ + T(BIT_OR, "|", 8) \ + T(BIT_XOR, "^", 9) \ + T(BIT_AND, "&", 10) \ T(SHL, "<<", 11) \ T(SAR, ">>", 11) \ T(SHR, ">>>", 11) \ @@ -122,13 +122,13 @@ namespace solidity /* Compare operators sorted by precedence. */ \ /* IsCompareOp() relies on this block of enum values */ \ /* being contiguous and sorted in the same order! */ \ - T(EQ, "==", 9) \ - T(NE, "!=", 9) \ - T(LT, "<", 10) \ - T(GT, ">", 10) \ - T(LTE, "<=", 10) \ - T(GTE, ">=", 10) \ - K(IN, "in", 10) \ + T(EQ, "==", 6) \ + T(NE, "!=", 6) \ + T(LT, "<", 7) \ + T(GT, ">", 7) \ + T(LTE, "<=", 7) \ + T(GTE, ">=", 7) \ + K(IN, "in", 7) \ \ /* Unary operators. */ \ /* IsUnaryOp() relies on this block of enum values */ \ diff --git a/test/SolidityNameAndTypeResolution.cpp b/test/SolidityNameAndTypeResolution.cpp index 0bda0a1fd..c7f0b3ab8 100644 --- a/test/SolidityNameAndTypeResolution.cpp +++ b/test/SolidityNameAndTypeResolution.cpp @@ -311,6 +311,16 @@ BOOST_AUTO_TEST_CASE(forward_function_reference) BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); } +BOOST_AUTO_TEST_CASE(comparison_bitop_precedence) +{ + char const* text = "contract First {\n" + " function fun() returns (bool ret) {\n" + " return 1 & 2 == 8 & 9;\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + BOOST_AUTO_TEST_SUITE_END() } From 49f60a1d6d0b93fad28cea57e03beb261d9f09b1 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Thu, 18 Dec 2014 17:30:10 +0100 Subject: [PATCH 594/641] Factoring forward slash scanning out to its own function --- libsolidity/Scanner.cpp | 85 ++++++++++++++++++++++------------------- libsolidity/Scanner.h | 2 + 2 files changed, 47 insertions(+), 40 deletions(-) diff --git a/libsolidity/Scanner.cpp b/libsolidity/Scanner.cpp index 124c88d92..f22e69bc8 100644 --- a/libsolidity/Scanner.cpp +++ b/libsolidity/Scanner.cpp @@ -326,9 +326,52 @@ Token::Value Scanner::scanMultiLineDocComment() return Token::COMMENT_LITERAL; } +Token::Value Scanner::scanSlash() +{ + int firstSlashPosition = getSourcePos(); + advance(); + if (m_char == '/') + { + if (!advance()) /* double slash comment directly before EOS */ + return Token::WHITESPACE; + else if (m_char == '/') + { + // doxygen style /// comment + Token::Value comment; + m_nextSkippedComment.location.start = firstSlashPosition; + comment = scanSingleLineDocComment(); + m_nextSkippedComment.location.end = getSourcePos(); + m_nextSkippedComment.token = comment; + return Token::WHITESPACE; + } + else + return skipSingleLineComment(); + } + else if (m_char == '*') + { + // doxygen style /** natspec comment + if (!advance()) /* slash star comment before EOS */ + return Token::WHITESPACE; + else if (m_char == '*') + { + Token::Value comment; + m_nextSkippedComment.location.start = firstSlashPosition; + comment = scanMultiLineDocComment(); + m_nextSkippedComment.location.end = getSourcePos(); + m_nextSkippedComment.token = comment; + return Token::WHITESPACE; + } + else + return skipMultiLineComment(); + } + else if (m_char == '=') + return selectToken(Token::ASSIGN_DIV); + else + return Token::DIV; +} + void Scanner::scanToken() { - int savedPosition; m_nextToken.literal.clear(); m_nextSkippedComment.literal.clear(); Token::Value token; @@ -429,45 +472,7 @@ void Scanner::scanToken() break; case '/': // / // /* /= - savedPosition = getSourcePos(); - advance(); - if (m_char == '/') - { - if (!advance()) /* double slash comment directly before EOS */ - token = Token::WHITESPACE; - else if (m_char == '/') - { - Token::Value comment; - m_nextSkippedComment.location.start = savedPosition; - comment = scanSingleLineDocComment(); - m_nextSkippedComment.location.end = getSourcePos(); - m_nextSkippedComment.token = comment; - token = Token::WHITESPACE; - } - else - token = skipSingleLineComment(); - } - else if (m_char == '*') - { - // /** doxygent style natspec comment - if (!advance()) /* slash star comment before EOS */ - token = Token::WHITESPACE; - else if (m_char == '*') - { - Token::Value comment; - m_nextSkippedComment.location.start = savedPosition; - comment = scanMultiLineDocComment(); - m_nextSkippedComment.location.end = getSourcePos(); - m_nextSkippedComment.token = comment; - token = Token::WHITESPACE; - } - else - token = skipMultiLineComment(); - } - else if (m_char == '=') - token = selectToken(Token::ASSIGN_DIV); - else - token = Token::DIV; + token = scanSlash(); break; case '&': // & && &= diff --git a/libsolidity/Scanner.h b/libsolidity/Scanner.h index 5e70db51d..5b90a94eb 100644 --- a/libsolidity/Scanner.h +++ b/libsolidity/Scanner.h @@ -194,6 +194,8 @@ private: Token::Value scanString(); Token::Value scanSingleLineDocComment(); Token::Value scanMultiLineDocComment(); + /// Scans a slash '/' and depending on the characters returns the appropriate token + Token::Value scanSlash(); /// Scans an escape-sequence which is part of a string and adds the /// decoded character to the current literal. Returns true if a pattern From ae994f28043065ef9ff8c3a2835a69389a495029 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 18 Dec 2014 17:49:11 +0100 Subject: [PATCH 595/641] Also test non-equality comparison operator. --- test/SolidityNameAndTypeResolution.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/SolidityNameAndTypeResolution.cpp b/test/SolidityNameAndTypeResolution.cpp index c7f0b3ab8..25bff71f7 100644 --- a/test/SolidityNameAndTypeResolution.cpp +++ b/test/SolidityNameAndTypeResolution.cpp @@ -315,7 +315,7 @@ BOOST_AUTO_TEST_CASE(comparison_bitop_precedence) { char const* text = "contract First {\n" " function fun() returns (bool ret) {\n" - " return 1 & 2 == 8 & 9;\n" + " return 1 & 2 == 8 & 9 && 1 ^ 2 < 4 | 6;\n" " }\n" "}\n"; BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); From 4165e45464eaec9ed8f62d2571f2a10111599376 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Thu, 18 Dec 2014 18:16:43 +0100 Subject: [PATCH 596/641] updating solidity parser natspec tests to comply with recent changes --- test/SolidityParser.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/SolidityParser.cpp b/test/SolidityParser.cpp index f978cdd9b..c14c05122 100644 --- a/test/SolidityParser.cpp +++ b/test/SolidityParser.cpp @@ -128,7 +128,7 @@ BOOST_AUTO_TEST_CASE(function_natspec_documentation) BOOST_REQUIRE_NO_THROW(contract = parseText(text)); auto functions = contract->getDefinedFunctions(); BOOST_REQUIRE_NO_THROW(function = functions.at(0)); - BOOST_CHECK_EQUAL(*function->getDocumentation(), " This is a test function"); + BOOST_CHECK_EQUAL(*function->getDocumentation(), "This is a test function"); } BOOST_AUTO_TEST_CASE(function_normal_comments) @@ -166,17 +166,17 @@ BOOST_AUTO_TEST_CASE(multiple_functions_natspec_documentation) auto functions = contract->getDefinedFunctions(); BOOST_REQUIRE_NO_THROW(function = functions.at(0)); - BOOST_CHECK_EQUAL(*function->getDocumentation(), " This is test function 1"); + BOOST_CHECK_EQUAL(*function->getDocumentation(), "This is test function 1"); BOOST_REQUIRE_NO_THROW(function = functions.at(1)); - BOOST_CHECK_EQUAL(*function->getDocumentation(), " This is test function 2"); + BOOST_CHECK_EQUAL(*function->getDocumentation(), "This is test function 2"); BOOST_REQUIRE_NO_THROW(function = functions.at(2)); BOOST_CHECK_MESSAGE(function->getDocumentation() == nullptr, "Should not have gotten natspec comment for functionName3()"); BOOST_REQUIRE_NO_THROW(function = functions.at(3)); - BOOST_CHECK_EQUAL(*function->getDocumentation(), " This is test function 4"); + BOOST_CHECK_EQUAL(*function->getDocumentation(), "This is test function 4"); } BOOST_AUTO_TEST_CASE(multiline_function_documentation) @@ -194,7 +194,7 @@ BOOST_AUTO_TEST_CASE(multiline_function_documentation) BOOST_REQUIRE_NO_THROW(function = functions.at(0)); BOOST_CHECK_EQUAL(*function->getDocumentation(), - " This is a test function\n" + "This is a test function\n" " and it has 2 lines"); } @@ -220,11 +220,11 @@ BOOST_AUTO_TEST_CASE(natspec_comment_in_function_body) auto functions = contract->getDefinedFunctions(); BOOST_REQUIRE_NO_THROW(function = functions.at(0)); - BOOST_CHECK_EQUAL(*function->getDocumentation(), " fun1 description"); + BOOST_CHECK_EQUAL(*function->getDocumentation(), "fun1 description"); BOOST_REQUIRE_NO_THROW(function = functions.at(1)); BOOST_CHECK_EQUAL(*function->getDocumentation(), - " This is a test function\n" + "This is a test function\n" " and it has 2 lines"); } From 672c1ca15b5d749609ef8c68267fe58e9a69e6e8 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 18 Dec 2014 18:44:55 +0100 Subject: [PATCH 597/641] Version bump. --- libdevcore/Common.cpp | 2 +- libethcore/CommonEth.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libdevcore/Common.cpp b/libdevcore/Common.cpp index 55250b418..1de7ef957 100644 --- a/libdevcore/Common.cpp +++ b/libdevcore/Common.cpp @@ -27,7 +27,7 @@ using namespace dev; namespace dev { -char const* Version = "0.7.12"; +char const* Version = "0.7.13"; } diff --git a/libethcore/CommonEth.cpp b/libethcore/CommonEth.cpp index 5e510572e..ff5e6aed0 100644 --- a/libethcore/CommonEth.cpp +++ b/libethcore/CommonEth.cpp @@ -32,7 +32,7 @@ namespace dev namespace eth { -const unsigned c_protocolVersion = 49; +const unsigned c_protocolVersion = 50; const unsigned c_databaseVersion = 5; static const vector> g_units = From fce7f1712d32bb3f3c0c56078201adda4541be2b Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Thu, 18 Dec 2014 21:43:40 +0100 Subject: [PATCH 598/641] more refunds tests --- test/stRefundTestFiller.json | 163 +++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) diff --git a/test/stRefundTestFiller.json b/test/stRefundTestFiller.json index 4060bbb72..6b2b2fc15 100644 --- a/test/stRefundTestFiller.json +++ b/test/stRefundTestFiller.json @@ -141,5 +141,168 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } + }, + + "refund50_1" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 1 ]] 0 [[ 2 ]] 0 [[ 3 ]] 0 [[ 4 ]] 0 [[ 5 ]] 0 }", + "storage" : { + "0x01" : "0x01", + "0x02" : "0x01", + "0x03" : "0x01", + "0x04" : "0x01", + "0x05" : "0x01" + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "10000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "refund50_2" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 10 ]] 1 [[ 11 ]] 1 [[ 1 ]] 0 [[ 2 ]] 0 [[ 3 ]] 0 [[ 4 ]] 0 [[ 5 ]] 0 }", + "storage" : { + "0x01" : "0x01", + "0x02" : "0x01", + "0x03" : "0x01", + "0x04" : "0x01", + "0x05" : "0x01" + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "10000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "refund500" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ @@1 @@2 [[ 10 ]] (EXP 2 0xff) [[ 11 ]] (BALANCE (ADDRESS)) [[ 1 ]] 0 [[ 2 ]] 0 [[ 3 ]] 0 [[ 4 ]] 0 [[ 5 ]] 0 [[ 6 ]] 0 }", + "storage" : { + "0x01" : "0x01", + "0x02" : "0x01", + "0x03" : "0x01", + "0x04" : "0x01", + "0x05" : "0x01", + "0x06" : "0x01" + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "10000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "refund600" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ @@1 @@2 [[ 10 ]] (EXP 2 0xffff) [[ 11 ]] (BALANCE (ADDRESS)) [[ 1 ]] 0 [[ 2 ]] 0 [[ 3 ]] 0 [[ 4 ]] 0 [[ 5 ]] 0 [[ 6 ]] 0 }", + "storage" : { + "0x01" : "0x01", + "0x02" : "0x01", + "0x03" : "0x01", + "0x04" : "0x01", + "0x05" : "0x01", + "0x06" : "0x01" + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "10000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } } + } From e427a0a2cafa5ecd4ea3872aadd2b5f19eb705cb Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 18 Dec 2014 22:15:11 +0100 Subject: [PATCH 599/641] Bugfix: Additional swap for compound assignment. --- libsolidity/ExpressionCompiler.cpp | 2 ++ test/SolidityEndToEndTest.cpp | 35 ++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index f58c157d9..cf641935a 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -62,6 +62,8 @@ bool ExpressionCompiler::visit(Assignment const& _assignment) m_context << eth::Instruction::SWAP1 << eth::Instruction::DUP2; m_currentLValue.retrieveValue(_assignment, true); appendOrdinaryBinaryOperatorCode(Token::AssignmentToBinaryOp(op), *_assignment.getType()); + if (m_currentLValue.storesReferenceOnStack()) + m_context << eth::Instruction::SWAP1; } m_currentLValue.storeValue(_assignment); m_currentLValue.reset(); diff --git a/test/SolidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp index aa74f8186..9559e3702 100644 --- a/test/SolidityEndToEndTest.cpp +++ b/test/SolidityEndToEndTest.cpp @@ -504,6 +504,41 @@ BOOST_AUTO_TEST_CASE(state_smoke_test) BOOST_CHECK(callContractFunction(0, bytes(1, 0x00)) == toBigEndian(u256(0x3))); } +BOOST_AUTO_TEST_CASE(compound_assign) +{ + char const* sourceCode = "contract test {\n" + " uint value1;\n" + " uint value2;\n" + " function f(uint x, uint y) returns (uint w) {\n" + " uint value3 = y;" + " value1 += x;\n" + " value3 *= x;" + " value2 *= value3 + value1;\n" + " return value2 += 7;" + " }\n" + "}\n"; + compileAndRun(sourceCode); + + u256 value1; + u256 value2; + auto f = [&](u256 const& _x, u256 const& _y) -> u256 + { + u256 value3 = _y; + value1 += _x; + value3 *= _x; + value2 *= value3 + value1; + return value2 += 7; + }; + testSolidityAgainstCpp(0, f, u256(0), u256(6)); + testSolidityAgainstCpp(0, f, u256(1), u256(3)); + testSolidityAgainstCpp(0, f, u256(2), u256(25)); + testSolidityAgainstCpp(0, f, u256(3), u256(69)); + testSolidityAgainstCpp(0, f, u256(4), u256(84)); + testSolidityAgainstCpp(0, f, u256(5), u256(2)); + testSolidityAgainstCpp(0, f, u256(6), u256(51)); + testSolidityAgainstCpp(0, f, u256(7), u256(48)); +} + BOOST_AUTO_TEST_CASE(simple_mapping) { char const* sourceCode = "contract test {\n" From f3f5d9ea745bef9455de82fcd57ab9d1dc0b350d Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Thu, 18 Dec 2014 23:02:41 +0100 Subject: [PATCH 600/641] correct VMTrace define --- libethereum/State.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libethereum/State.cpp b/libethereum/State.cpp index fd00761e1..e02b06bcd 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -1017,7 +1017,7 @@ u256 State::execute(bytesConstRef _rlp, bytes* o_output, bool _commit) ctrace << "Executing" << e.t() << "on" << h; ctrace << toHex(e.t().rlp()); #endif -#if ETH_TRACE +#if ETH_VMTRACE e.go(e.simpleTrace()); #else e.go(); From 31f1c73a188d649760d0075bd008bcb082e56e1c Mon Sep 17 00:00:00 2001 From: winsvega Date: Fri, 19 Dec 2014 01:57:21 +0300 Subject: [PATCH 601/641] Cteate Contract From Contract Init Code Test --- test/stInitCodeTestFiller.json | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/test/stInitCodeTestFiller.json b/test/stInitCodeTestFiller.json index 76d8f7957..1ac0a11ad 100644 --- a/test/stInitCodeTestFiller.json +++ b/test/stInitCodeTestFiller.json @@ -276,20 +276,19 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87": { "balance": "10000", "nonce": 0, - "code": "{[[ 2 ]](ADDRESS)(CODECOPY 0 0 32)(CREATE 0 0 32)}", + "code": "{(MSTORE 0 0x601080600c6000396000f20060003554156009570060203560003555) [[ 0 ]] (CREATE 23 4 28)}", "storage": {} - }, + }, - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "100000", - "code" : "", - "nonce" : "0", - "storage" : { - } - } + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "balance" : "100000", + "code" : "", + "nonce" : "0", + "storage" : {} + } }, "transaction" : - { + { "data" : "0x00", "gasLimit" : "10000", "gasPrice" : "1", From 29261206b9293c2e07b2b879aff059bc57e5d1cb Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Fri, 19 Dec 2014 10:48:59 +0100 Subject: [PATCH 602/641] Adding const attribute to ABI output --- libsolidity/InterfaceHandler.cpp | 1 + test/SolidityABIJSON.cpp | 53 ++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/libsolidity/InterfaceHandler.cpp b/libsolidity/InterfaceHandler.cpp index 5b5682ff1..60971fbb9 100644 --- a/libsolidity/InterfaceHandler.cpp +++ b/libsolidity/InterfaceHandler.cpp @@ -56,6 +56,7 @@ std::unique_ptr InterfaceHandler::getABIInterface(ContractDefinitio }; method["name"] = f->getName(); + method["const"] = f->isDeclaredConst(); method["inputs"] = populateParameters(f->getParameters()); method["outputs"] = populateParameters(f->getReturnParameters()); methods.append(method); diff --git a/test/SolidityABIJSON.cpp b/test/SolidityABIJSON.cpp index c734009c3..62ab0458c 100644 --- a/test/SolidityABIJSON.cpp +++ b/test/SolidityABIJSON.cpp @@ -76,6 +76,7 @@ BOOST_AUTO_TEST_CASE(basic_test) char const* interface = R"([ { "name": "f", + "const": false, "inputs": [ { "name": "a", @@ -114,6 +115,7 @@ BOOST_AUTO_TEST_CASE(multiple_methods) char const* interface = R"([ { "name": "f", + "const": false, "inputs": [ { "name": "a", @@ -129,6 +131,7 @@ BOOST_AUTO_TEST_CASE(multiple_methods) }, { "name": "g", + "const": false, "inputs": [ { "name": "b", @@ -156,6 +159,7 @@ BOOST_AUTO_TEST_CASE(multiple_params) char const* interface = R"([ { "name": "f", + "const": false, "inputs": [ { "name": "a", @@ -189,6 +193,7 @@ BOOST_AUTO_TEST_CASE(multiple_methods_order) char const* interface = R"([ { "name": "c", + "const": false, "inputs": [ { "name": "b", @@ -204,6 +209,7 @@ BOOST_AUTO_TEST_CASE(multiple_methods_order) }, { "name": "f", + "const": false, "inputs": [ { "name": "a", @@ -222,6 +228,53 @@ BOOST_AUTO_TEST_CASE(multiple_methods_order) checkInterface(sourceCode, interface); } +BOOST_AUTO_TEST_CASE(const_function) +{ + char const* sourceCode = "contract test {\n" + " function foo(uint a, uint b) returns(uint d) { return a + b; }\n" + " function boo(uint32 a) const returns(uint b) { return a * 4; }\n" + "}\n"; + + char const* interface = R"([ + { + "name": "boo", + "const": true, + "inputs": [{ + "name": "a", + "type": "uint32" + }], + "outputs": [ + { + "name": "b", + "type": "uint256" + } + ] + }, + { + "name": "foo", + "const": false, + "inputs": [ + { + "name": "a", + "type": "uint256" + }, + { + "name": "b", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "d", + "type": "uint256" + } + ] + } + ])"; + + checkInterface(sourceCode, interface); +} + BOOST_AUTO_TEST_SUITE_END() } From e80dffeec5fb54e80e4c0ee3c90be4843db0c101 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 19 Dec 2014 12:32:36 +0100 Subject: [PATCH 603/641] Clean up and remove some explicit dependencies in cmake files --- alethzero/CMakeLists.txt | 3 --- evmjit | 2 +- libethereum/CMakeLists.txt | 3 --- libevm/CMakeLists.txt | 3 +++ test/CMakeLists.txt | 3 --- 5 files changed, 4 insertions(+), 10 deletions(-) diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index 4e4e4a93c..39c02d6be 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -46,9 +46,6 @@ target_link_libraries(${EXECUTABLE} evmcore) target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} web3jsonrpc) target_link_libraries(${EXECUTABLE} jsqrc) -if (EVMJIT) - target_link_libraries(${EXECUTEABLE} evmjit) -endif() # eth_install_executable is defined in cmake/EthExecutableHelper.cmake eth_install_executable(${EXECUTABLE}) diff --git a/evmjit b/evmjit index 8287c6040..232f9fee5 160000 --- a/evmjit +++ b/evmjit @@ -1 +1 @@ -Subproject commit 8287c6040a4900cb8b091ffbe284c7f478c60c49 +Subproject commit 232f9fee527e454f4008c2c03a9c7dac1c5c85ff diff --git a/libethereum/CMakeLists.txt b/libethereum/CMakeLists.txt index e00637dad..3906074fd 100644 --- a/libethereum/CMakeLists.txt +++ b/libethereum/CMakeLists.txt @@ -34,9 +34,6 @@ target_link_libraries(${EXECUTABLE} p2p) target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} secp256k1) -if (EVMJIT) - target_link_libraries(${EXECUTABLE} evmjit-cpp) -endif() install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libevm/CMakeLists.txt b/libevm/CMakeLists.txt index 96b8f9ade..4af5eb175 100644 --- a/libevm/CMakeLists.txt +++ b/libevm/CMakeLists.txt @@ -30,6 +30,9 @@ target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} evmcore) target_link_libraries(${EXECUTABLE} devcore) +if (EVMJIT) + target_link_libraries(${EXECUTABLE} evmjit-cpp) +endif() install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 441200fe4..7cedc117b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -25,9 +25,6 @@ if (JSONRPC) target_link_libraries(testeth web3jsonrpc) target_link_libraries(testeth ${JSON_RPC_CPP_CLIENT_LIBRARIES}) endif() -if (EVMJIT) - target_link_libraries(testeth evmjit-cpp) -endif() target_link_libraries(createRandomTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) target_link_libraries(createRandomTest ethereum) From 6be33f7d8f6dc99b4d32c6538d183ce1af89a8da Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 19 Dec 2014 13:45:12 +0100 Subject: [PATCH 604/641] Revert to 49. --- libethcore/CommonEth.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libethcore/CommonEth.cpp b/libethcore/CommonEth.cpp index ff5e6aed0..5e510572e 100644 --- a/libethcore/CommonEth.cpp +++ b/libethcore/CommonEth.cpp @@ -32,7 +32,7 @@ namespace dev namespace eth { -const unsigned c_protocolVersion = 50; +const unsigned c_protocolVersion = 49; const unsigned c_databaseVersion = 5; static const vector> g_units = From 44e55fb928f8ab45b593194d57e4fa81e695b949 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 19 Dec 2014 14:22:29 +0100 Subject: [PATCH 605/641] Remove old handcrafted Visual Studio project files --- windows/LLVM.props | 44 ------- windows/LibEvmJit.vcxproj | 174 ------------------------- windows/LibEvmJit.vcxproj.filters | 44 ------- windows/LibEvmJitCpp.vcxproj | 143 -------------------- windows/LibEvmJitCpp.vcxproj.filters | 13 -- windows/evmcc.vcxproj | 187 --------------------------- windows/evmcc.vcxproj.filters | 9 -- 7 files changed, 614 deletions(-) delete mode 100644 windows/LLVM.props delete mode 100644 windows/LibEvmJit.vcxproj delete mode 100644 windows/LibEvmJit.vcxproj.filters delete mode 100644 windows/LibEvmJitCpp.vcxproj delete mode 100644 windows/LibEvmJitCpp.vcxproj.filters delete mode 100644 windows/evmcc.vcxproj delete mode 100644 windows/evmcc.vcxproj.filters diff --git a/windows/LLVM.props b/windows/LLVM.props deleted file mode 100644 index a1537ac7e..000000000 --- a/windows/LLVM.props +++ /dev/null @@ -1,44 +0,0 @@ - - - - - 0 - ../../llvm - ../../_build/llvm/$(Platform) - $(LLVMSrcDir)\include;$(LLVMBuildDir)\include - $(LLVMBuildDir)\$(Configuration)\lib - LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMBitWriter.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib - - - - - $(LLVMIncludeDir);%(AdditionalIncludeDirectories) - 4800;%(DisableSpecificWarnings) - ETH_EVMJIT=$(LLVMEnabled);%(PreprocessorDefinitions) - - - $(LLVMLibDir);%(AdditionalLibraryDirectories) - $(LLVMLibs);%(AdditionalDependencies) - - - - - $(LLVMEnabled) - - - $(LLVMSrcDir) - - - $(LLVMBuildDir) - - - $(LLVMIncludeDir) - - - $(LLVMLibDir) - - - $(LLVMLibs) - - - \ No newline at end of file diff --git a/windows/LibEvmJit.vcxproj b/windows/LibEvmJit.vcxproj deleted file mode 100644 index c3b1f65a7..000000000 --- a/windows/LibEvmJit.vcxproj +++ /dev/null @@ -1,174 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {9C816740-5C11-4377-A3A7-46BE12F35FA0} - LibEvmJit - - - - StaticLibrary - true - v120 - - - StaticLibrary - true - v120 - - - StaticLibrary - false - v120 - true - - - StaticLibrary - false - v120 - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Level3 - Disabled - true - - - true - - - - - Level3 - Disabled - true - - - true - - - - - Level3 - MaxSpeed - true - true - true - - - true - true - true - - - - - Level3 - MaxSpeed - true - true - true - - - true - true - true - - - - - {826e68cb-d3ee-4a8a-b540-59a8c3f38d4f} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/windows/LibEvmJit.vcxproj.filters b/windows/LibEvmJit.vcxproj.filters deleted file mode 100644 index 88dc8d329..000000000 --- a/windows/LibEvmJit.vcxproj.filters +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/windows/LibEvmJitCpp.vcxproj b/windows/LibEvmJitCpp.vcxproj deleted file mode 100644 index d72bcd981..000000000 --- a/windows/LibEvmJitCpp.vcxproj +++ /dev/null @@ -1,143 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {A5D8764C-FD17-4364-AFCF-5BAF78777569} - LibEvmJitCpp - - - - StaticLibrary - true - v120 - - - StaticLibrary - true - v120 - - - StaticLibrary - false - v120 - true - - - StaticLibrary - false - v120 - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Level3 - Disabled - true - - - true - - - - - Level3 - Disabled - true - - - true - - - - - Level3 - MaxSpeed - true - true - true - - - true - true - true - - - - - Level3 - MaxSpeed - true - true - true - - - true - true - true - - - - - - - - - - - - - - - {9c816740-5c11-4377-a3a7-46be12f35fa0} - - - - - - \ No newline at end of file diff --git a/windows/LibEvmJitCpp.vcxproj.filters b/windows/LibEvmJitCpp.vcxproj.filters deleted file mode 100644 index 4bf360cbe..000000000 --- a/windows/LibEvmJitCpp.vcxproj.filters +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/windows/evmcc.vcxproj b/windows/evmcc.vcxproj deleted file mode 100644 index 6cd0ece89..000000000 --- a/windows/evmcc.vcxproj +++ /dev/null @@ -1,187 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - {a5d8764c-fd17-4364-afcf-5baf78777569} - - - - - - - - - - {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D} - Win32Proj - evmcc - - - - Application - true - v120 - Unicode - - - Application - true - v120 - - - Application - false - v120 - true - Unicode - - - Application - false - v120 - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - ..\..\_build\$(ProjectName)\$(Platform)_$(Configuration)\ - ..\..\_build\$(ProjectName)\$(Platform)_$(Configuration)\ - false - - - true - false - - - false - ..\..\_build\$(ProjectName)\$(Platform)_$(Configuration)\ - ..\..\_build\$(ProjectName)\$(Platform)_$(Configuration)\ - false - - - false - false - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) - true - ../../llvm-3.5.0/include;../../builds/llvm3.5/include;%(AdditionalIncludeDirectories) - false - false - - - Console - true - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) - true - ../../llvm-3.5.0/include;../../builds/llvm3.5/include;%(AdditionalIncludeDirectories) - 4068;4244;4267;4800 - false - false - - - Console - true - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) - true - false - - - Console - true - true - true - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) - true - 4068;4244;4267;4800 - false - - - Console - true - true - true - - - - - - \ No newline at end of file diff --git a/windows/evmcc.vcxproj.filters b/windows/evmcc.vcxproj.filters deleted file mode 100644 index f70c861ba..000000000 --- a/windows/evmcc.vcxproj.filters +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file From acec80d8f1cc27f4b86e970b03b3dd425097cbc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 19 Dec 2014 14:38:03 +0100 Subject: [PATCH 606/641] Remove unnecessary changes --- libethereum/State.h | 1 - libevm/VM.h | 2 +- test/vm.cpp | 40 ++++++++++++++++++++-------------------- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/libethereum/State.h b/libethereum/State.h index bea299e6c..763a67451 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -32,7 +32,6 @@ #include #include #include -#include #include "TransactionQueue.h" #include "Account.h" #include "Transaction.h" diff --git a/libevm/VM.h b/libevm/VM.h index 306b1ce63..1f3fc17d5 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -478,7 +478,7 @@ inline bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _st break; case Instruction::SIGNEXTEND: if (m_stack.back() < 31) - { + { unsigned const testBit(m_stack.back() * 8 + 7); u256& number = m_stack[m_stack.size() - 2]; u256 mask = ((u256(1) << testBit) - 1); diff --git a/test/vm.cpp b/test/vm.cpp index 5b53bc371..920f0582c 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -422,29 +422,29 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) test.importCallCreates(o["callcreates"].get_array()); test.sub.logs = importLog(o["logs"].get_array()); - checkOutput(output, o); + checkOutput(output, o); - BOOST_CHECK_EQUAL(toInt(o["gas"]), gas); - - auto& expectedAddrs = test.addresses; - auto& resultAddrs = fev.addresses; - for (auto&& expectedPair : expectedAddrs) - { - auto& expectedAddr = expectedPair.first; - auto resultAddrIt = resultAddrs.find(expectedAddr); - if (resultAddrIt == resultAddrs.end()) - BOOST_ERROR("Missing expected address " << expectedAddr); - else - { - auto& expectedState = expectedPair.second; - auto& resultState = resultAddrIt->second; - BOOST_CHECK_MESSAGE(std::get<0>(expectedState) == std::get<0>(resultState), expectedAddr << ": incorrect balance " << std::get<0>(resultState) << ", expected " << std::get<0>(expectedState)); - BOOST_CHECK_MESSAGE(std::get<1>(expectedState) == std::get<1>(resultState), expectedAddr << ": incorrect txCount " << std::get<1>(resultState) << ", expected " << std::get<1>(expectedState)); - BOOST_CHECK_MESSAGE(std::get<3>(expectedState) == std::get<3>(resultState), expectedAddr << ": incorrect code"); + BOOST_CHECK_EQUAL(toInt(o["gas"]), gas); - checkStorage(std::get<2>(expectedState), std::get<2>(resultState), expectedAddr); + auto& expectedAddrs = test.addresses; + auto& resultAddrs = fev.addresses; + for (auto&& expectedPair : expectedAddrs) + { + auto& expectedAddr = expectedPair.first; + auto resultAddrIt = resultAddrs.find(expectedAddr); + if (resultAddrIt == resultAddrs.end()) + BOOST_ERROR("Missing expected address " << expectedAddr); + else + { + auto& expectedState = expectedPair.second; + auto& resultState = resultAddrIt->second; + BOOST_CHECK_MESSAGE(std::get<0>(expectedState) == std::get<0>(resultState), expectedAddr << ": incorrect balance " << std::get<0>(resultState) << ", expected " << std::get<0>(expectedState)); + BOOST_CHECK_MESSAGE(std::get<1>(expectedState) == std::get<1>(resultState), expectedAddr << ": incorrect txCount " << std::get<1>(resultState) << ", expected " << std::get<1>(expectedState)); + BOOST_CHECK_MESSAGE(std::get<3>(expectedState) == std::get<3>(resultState), expectedAddr << ": incorrect code"); + + checkStorage(std::get<2>(expectedState), std::get<2>(resultState), expectedAddr); + } } - } checkAddresses, bytes> > >(test.addresses, fev.addresses); BOOST_CHECK(test.callcreates == fev.callcreates); From 22535d527b46cc831acee3792b72c98ff53649b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Sat, 20 Dec 2014 10:41:16 +0100 Subject: [PATCH 607/641] Update evmjit submodule --- evmjit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evmjit b/evmjit index 232f9fee5..ed63ced24 160000 --- a/evmjit +++ b/evmjit @@ -1 +1 @@ -Subproject commit 232f9fee527e454f4008c2c03a9c7dac1c5c85ff +Subproject commit ed63ced24456c28b6dba345b8fc61e680ed406d7 From d6aee23642688031479c9badb65c9c1b60b3e7cc Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 20 Dec 2014 14:25:26 +0100 Subject: [PATCH 608/641] Blocktime targets 12s. --- libethcore/BlockInfo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libethcore/BlockInfo.cpp b/libethcore/BlockInfo.cpp index 6c08bb346..1ad016fa3 100644 --- a/libethcore/BlockInfo.cpp +++ b/libethcore/BlockInfo.cpp @@ -190,7 +190,7 @@ u256 BlockInfo::calculateDifficulty(BlockInfo const& _parent) const if (!parentHash) return c_genesisDifficulty; else - return timestamp >= _parent.timestamp + 5 ? _parent.difficulty - (_parent.difficulty >> 10) : (_parent.difficulty + (_parent.difficulty >> 10)); + return timestamp >= _parent.timestamp + 8 ? _parent.difficulty - (_parent.difficulty >> 10) : (_parent.difficulty + (_parent.difficulty >> 10)); } void BlockInfo::verifyParent(BlockInfo const& _parent) const From fe34eae4698c9b2f99bf70f141edc3ff0f162b50 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 20 Dec 2014 14:26:20 +0100 Subject: [PATCH 609/641] Versions bump. --- libdevcore/Common.cpp | 2 +- libethcore/CommonEth.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libdevcore/Common.cpp b/libdevcore/Common.cpp index 1de7ef957..428c86d66 100644 --- a/libdevcore/Common.cpp +++ b/libdevcore/Common.cpp @@ -27,7 +27,7 @@ using namespace dev; namespace dev { -char const* Version = "0.7.13"; +char const* Version = "0.8.0"; } diff --git a/libethcore/CommonEth.cpp b/libethcore/CommonEth.cpp index 5e510572e..9862ee488 100644 --- a/libethcore/CommonEth.cpp +++ b/libethcore/CommonEth.cpp @@ -32,7 +32,7 @@ namespace dev namespace eth { -const unsigned c_protocolVersion = 49; +const unsigned c_protocolVersion = 51; const unsigned c_databaseVersion = 5; static const vector> g_units = From c15da67ba6cc5707f94c6e796eabd3d97ceb8491 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 20 Dec 2014 15:46:33 +0100 Subject: [PATCH 610/641] Documentation, repotting. --- libdevcore/Diff.h | 52 +++++++++++++++++++++++++++++++++++ libethereum/AccountDiff.cpp | 16 ++++++++--- libethereum/AccountDiff.h | 55 +++++++++++++++++++++---------------- 3 files changed, 96 insertions(+), 27 deletions(-) create mode 100644 libdevcore/Diff.h diff --git a/libdevcore/Diff.h b/libdevcore/Diff.h new file mode 100644 index 000000000..fa5f6be2d --- /dev/null +++ b/libdevcore/Diff.h @@ -0,0 +1,52 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file Diff.h + * @author Gav Wood + * @date 2014 + */ + +#pragma once + +namespace dev +{ + +enum class ExistDiff +{ + Same, + New, + Dead +}; + +template +class Diff +{ +public: + Diff() {} + Diff(T _from, T _to): m_from(_from), m_to(_to) {} + + T const& from() const { return m_from; } + T const& to() const { return m_to; } + + explicit operator bool() const { return m_from != m_to; } + +private: + T m_from; + T m_to; +}; + +} + diff --git a/libethereum/AccountDiff.cpp b/libethereum/AccountDiff.cpp index c434086fa..ae82e18d9 100644 --- a/libethereum/AccountDiff.cpp +++ b/libethereum/AccountDiff.cpp @@ -33,11 +33,19 @@ AccountChange AccountDiff::changeType() const return exist ? exist.from() ? AccountChange::Deletion : AccountChange::Creation : (bn && sc) ? AccountChange::All : bn ? AccountChange::Intrinsic: sc ? AccountChange::CodeStorage : AccountChange::None; } -char const* AccountDiff::lead() const +char const* dev::lead(AccountChange _c) const { - bool bn = (balance || nonce); - bool sc = (!storage.empty() || code); - return exist ? exist.from() ? "XXX" : "+++" : (bn && sc) ? "***" : bn ? " * " : sc ? "* *" : " "; + switch (_c) + { + case AccountChange::None: return " "; + case AccountChange::Creation: return "+++"; + case AccountChange::Deletion: return "XXX"; + case AccountChange::Intrinsic: return " * "; + case AccountChange::CodeStorage: return "* *"; + case AccountChange::All: return "***"; + } + assert(false); + return ""; } namespace dev { diff --git a/libethereum/AccountDiff.h b/libethereum/AccountDiff.h index d4c30ead5..0c0ede4ae 100644 --- a/libethereum/AccountDiff.h +++ b/libethereum/AccountDiff.h @@ -22,6 +22,7 @@ #pragma once #include +#include #include namespace dev @@ -29,47 +30,55 @@ namespace dev namespace eth { -enum class ExistDiff { Same, New, Dead }; -template -class Diff +/// Type of change that an account can have from state to state. +enum class AccountChange { -public: - Diff() {} - Diff(T _from, T _to): m_from(_from), m_to(_to) {} - - T const& from() const { return m_from; } - T const& to() const { return m_to; } - - explicit operator bool() const { return m_from != m_to; } - -private: - T m_from; - T m_to; + None, ///< Nothing changed at all. + Creation, ///< Account came into existance. + Deletion, ///< Account was deleted. + Intrinsic, ///< Account was already in existance and some internal aspect of the account altered such as balance, nonce or storage. + CodeStorage, ///< Account was already in existance and the code of the account changed. + All ///< Account was already in existance and all aspects of the account changed. }; -enum class AccountChange { None, Creation, Deletion, Intrinsic, CodeStorage, All }; +/// @returns a three-character code that expresses the type of change. +char const* lead(AccountChange _c); +/** + * @brief Stores the difference between two accounts (typically the same account at two times). + * + * In order to determine what about an account has altered, this struct can be used to specify + * alterations. Use changed() and changeType() to determine what, if anything, is different. + * + * Five members are accessible: to determine the nature of the changes. + */ struct AccountDiff { + /// @returns true if the account has changed at all. inline bool changed() const { return storage.size() || code || nonce || balance || exist; } - char const* lead() const; + /// @returns a three-character code that expresses the change. AccountChange changeType() const; - Diff exist; - Diff balance; - Diff nonce; - std::map> storage; - Diff code; + Diff exist; ///< The account's existance; was it created/deleted or not? + Diff balance; ///< The account's balance; did it alter? + Diff nonce; ///< The account's nonce; did it alter? + std::map> storage; ///< The account's storage addresses; each has its own Diff. + Diff code; ///< The account's code; in general this should only have changed if exist also changed. }; +/** + * @brief Stores the difference between two states; this is just their encumbent accounts. + */ struct StateDiff { - std::map accounts; + std::map accounts; ///< The state's account changes; each has its own AccountDiff. }; } +/// Simple stream output for the StateDiff. std::ostream& operator<<(std::ostream& _out, dev::eth::StateDiff const& _s); +/// Simple stream output for the AccountDiff. std::ostream& operator<<(std::ostream& _out, dev::eth::AccountDiff const& _s); } From 176b682ce12fb42fe47ccf29796da3f18bfab054 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 20 Dec 2014 16:28:28 +0100 Subject: [PATCH 611/641] Use new lead() API. --- libethereum/AccountDiff.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libethereum/AccountDiff.cpp b/libethereum/AccountDiff.cpp index ae82e18d9..efef0c05e 100644 --- a/libethereum/AccountDiff.cpp +++ b/libethereum/AccountDiff.cpp @@ -85,7 +85,7 @@ std::ostream& operator<<(std::ostream& _out, dev::eth::StateDiff const& _s) dev::eth::AccountDiff d; _out << d; for (auto const& i: _s.accounts) - _out << i.second.lead() << " " << i.first << ": " << i.second << endl; + _out << lead(i.second.changeType()) << " " << i.first << ": " << i.second << endl; return _out; } From 0119bfca43e06d0a1b7ac29c75e1281564eec20b Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 20 Dec 2014 16:44:57 +0100 Subject: [PATCH 612/641] Kill unneeded rubbish. Add docs. --- boost/process.hpp | 50 - boost/process/child.hpp | 200 --- boost/process/config.hpp | 41 - boost/process/context.hpp | 209 --- boost/process/detail/file_handle.hpp | 406 ----- boost/process/detail/pipe.hpp | 187 -- boost/process/detail/posix_ops.hpp | 495 ------ boost/process/detail/stream_info.hpp | 176 -- boost/process/detail/systembuf.hpp | 231 --- boost/process/detail/win32_ops.hpp | 355 ---- boost/process/environment.hpp | 50 - boost/process/operations.hpp | 583 ------- boost/process/pistream.hpp | 116 -- boost/process/posix_child.hpp | 178 -- boost/process/posix_context.hpp | 118 -- boost/process/posix_operations.hpp | 81 - boost/process/posix_status.hpp | 128 -- boost/process/postream.hpp | 117 -- boost/process/process.hpp | 130 -- boost/process/self.hpp | 134 -- boost/process/status.hpp | 105 -- boost/process/stream_behavior.hpp | 234 --- boost/process/win32_child.hpp | 128 -- boost/process/win32_context.hpp | 61 - boost/process/win32_operations.hpp | 77 - doc/Doxyfile | 2364 ++++++++++++++++++++++++++ libethereum/AccountDiff.cpp | 2 +- 27 files changed, 2365 insertions(+), 4591 deletions(-) delete mode 100644 boost/process.hpp delete mode 100644 boost/process/child.hpp delete mode 100644 boost/process/config.hpp delete mode 100644 boost/process/context.hpp delete mode 100644 boost/process/detail/file_handle.hpp delete mode 100644 boost/process/detail/pipe.hpp delete mode 100644 boost/process/detail/posix_ops.hpp delete mode 100644 boost/process/detail/stream_info.hpp delete mode 100644 boost/process/detail/systembuf.hpp delete mode 100644 boost/process/detail/win32_ops.hpp delete mode 100644 boost/process/environment.hpp delete mode 100644 boost/process/operations.hpp delete mode 100644 boost/process/pistream.hpp delete mode 100644 boost/process/posix_child.hpp delete mode 100644 boost/process/posix_context.hpp delete mode 100644 boost/process/posix_operations.hpp delete mode 100644 boost/process/posix_status.hpp delete mode 100644 boost/process/postream.hpp delete mode 100644 boost/process/process.hpp delete mode 100644 boost/process/self.hpp delete mode 100644 boost/process/status.hpp delete mode 100644 boost/process/stream_behavior.hpp delete mode 100644 boost/process/win32_child.hpp delete mode 100644 boost/process/win32_context.hpp delete mode 100644 boost/process/win32_operations.hpp create mode 100644 doc/Doxyfile diff --git a/boost/process.hpp b/boost/process.hpp deleted file mode 100644 index 60511ef57..000000000 --- a/boost/process.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008, 2009 Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process.hpp - * - * Convenience header that includes all other Boost.Process public header - * files. It is important to note that those headers that are specific to - * a given platform are only included if the library is being used in that - * same platform. - */ - -#ifndef BOOST_PROCESS_HPP -#define BOOST_PROCESS_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -# include -# include -# include -#elif defined(BOOST_WINDOWS_API) -# include -# include -# include -#else -# error "Unsupported platform." -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#endif diff --git a/boost/process/child.hpp b/boost/process/child.hpp deleted file mode 100644 index 1419b7ea7..000000000 --- a/boost/process/child.hpp +++ /dev/null @@ -1,200 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008, 2009 Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/child.hpp - * - * Includes the declaration of the child class. - */ - -#ifndef BOOST_PROCESS_CHILD_HPP -#define BOOST_PROCESS_CHILD_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -# include -# include -#elif defined(BOOST_WINDOWS_API) -# include -#else -# error "Unsupported platform." -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace process { - -/** - * Generic implementation of the Child concept. - * - * The child class implements the Child concept in an operating system - * agnostic way. - */ -class child : public process -{ -public: - /** - * Gets a reference to the child's standard input stream. - * - * Returns a reference to a postream object that represents the - * standard input communication channel with the child process. - */ - postream &get_stdin() const - { - BOOST_ASSERT(stdin_); - - return *stdin_; - } - - /** - * Gets a reference to the child's standard output stream. - * - * Returns a reference to a pistream object that represents the - * standard output communication channel with the child process. - */ - pistream &get_stdout() const - { - BOOST_ASSERT(stdout_); - - return *stdout_; - } - - /** - * Gets a reference to the child's standard error stream. - * - * Returns a reference to a pistream object that represents the - * standard error communication channel with the child process. - */ - pistream &get_stderr() const - { - BOOST_ASSERT(stderr_); - - return *stderr_; - } - - /** - * Blocks and waits for the child process to terminate. - * - * Returns a status object that represents the child process' - * finalization condition. The child process object ceases to be - * valid after this call. - * - * \remark Blocking remarks: This call blocks if the child - * process has not finalized execution and waits until - * it terminates. - */ - status wait() - { -#if defined(BOOST_POSIX_API) - int s; - if (::waitpid(get_id(), &s, 0) == -1) - boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::child::wait: waitpid(2) failed")); - return status(s); -#elif defined(BOOST_WINDOWS_API) - ::WaitForSingleObject(process_handle_.get(), INFINITE); - DWORD code; - if (!::GetExitCodeProcess(process_handle_.get(), &code)) - boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::child::wait: GetExitCodeProcess failed")); - return status(code); -#endif - } - - /** - * Creates a new child object that represents the just spawned child - * process \a id. - * - * The \a fhstdin, \a fhstdout and \a fhstderr file handles represent - * the parent's handles used to communicate with the corresponding - * data streams. They needn't be valid but their availability must - * match the redirections configured by the launcher that spawned this - * process. - * - * The \a fhprocess handle represents a handle to the child process. - * It is only used on Windows as the implementation of wait() needs a - * process handle. - */ - child(id_type id, detail::file_handle fhstdin, detail::file_handle fhstdout, detail::file_handle fhstderr, detail::file_handle fhprocess = detail::file_handle()) - : process(id) -#if defined(BOOST_WINDOWS_API) - , process_handle_(fhprocess.release(), ::CloseHandle) -#endif - { - if (fhstdin.valid()) - stdin_.reset(new postream(fhstdin)); - if (fhstdout.valid()) - stdout_.reset(new pistream(fhstdout)); - if (fhstderr.valid()) - stderr_.reset(new pistream(fhstderr)); - } - -private: - /** - * The standard input stream attached to the child process. - * - * This postream object holds the communication channel with the - * child's process standard input. It is stored in a pointer because - * this field is only valid when the user requested to redirect this - * data stream. - */ - boost::shared_ptr stdin_; - - /** - * The standard output stream attached to the child process. - * - * This postream object holds the communication channel with the - * child's process standard output. It is stored in a pointer because - * this field is only valid when the user requested to redirect this - * data stream. - */ - boost::shared_ptr stdout_; - - /** - * The standard error stream attached to the child process. - * - * This postream object holds the communication channel with the - * child's process standard error. It is stored in a pointer because - * this field is only valid when the user requested to redirect this - * data stream. - */ - boost::shared_ptr stderr_; - -#if defined(BOOST_WINDOWS_API) - /** - * Process handle owned by RAII object. - */ - boost::shared_ptr process_handle_; -#endif -}; - -/** - * Collection of child objects. - * - * This convenience type represents a collection of child objects backed - * by a vector. - */ -typedef std::vector children; - -} -} - -#endif diff --git a/boost/process/config.hpp b/boost/process/config.hpp deleted file mode 100644 index f240f86b5..000000000 --- a/boost/process/config.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008, 2009 Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/config.hpp - * - * Defines macros that are used by the library's code to determine the - * operating system it is running under and the features it supports. - */ - -#ifndef BOOST_PROCESS_CONFIG_HPP -#define BOOST_PROCESS_CONFIG_HPP - -#include -#include - -#if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN) -# if !defined(BOOST_PROCESS_POSIX_PATH_MAX) -/** - * The macro BOOST_PROCESS_POSIX_PATH_MAX is set to a positive integer - * value which specifies the system's maximal supported path length. - * By default it is set to 259. You should set the macro to PATH_MAX - * which should be defined in limits.h provided by your operating system - * if you experience problems when instantiating a context. The - * constructor of basic_work_directory_context tries to find out - * dynamically the maximal supported path length but uses - * BOOST_PROCESS_POSIX_PATH_MAX if it fails. - */ -# define BOOST_PROCESS_POSIX_PATH_MAX 259 -# endif -#endif - -#endif diff --git a/boost/process/context.hpp b/boost/process/context.hpp deleted file mode 100644 index 51acd35bc..000000000 --- a/boost/process/context.hpp +++ /dev/null @@ -1,209 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008, 2009 Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/context.hpp - * - * Includes the declaration of the context class and several accessory - * base classes. - */ - -#ifndef BOOST_PROCESS_CONTEXT_HPP -#define BOOST_PROCESS_CONTEXT_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -# include -# include -#elif defined(BOOST_WINDOWS_API) -# include -#else -# error "Unsupported platform." -#endif - -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace process { - -/** - * Base context class that defines the child's work directory. - * - * Base context class that defines the necessary fields to configure a - * child's work directory. This class is useless on its own because no - * function in the library will accept it as a valid Context - * implementation. - */ -template -class basic_work_directory_context -{ -public: - /** - * Constructs a new work directory context. - * - * Constructs a new work directory context making the work directory - * described by the new object point to the caller's current working - * directory. - */ - basic_work_directory_context() - { -#if defined(BOOST_POSIX_API) - errno = 0; - long size = ::pathconf(".", _PC_PATH_MAX); - if (size == -1 && errno) - boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::basic_work_directory_context::basic_work_directory_context: pathconf(2) failed")); - else if (size == -1) - size = BOOST_PROCESS_POSIX_PATH_MAX; - boost::scoped_array cwd(new char[size]); - if (!::getcwd(cwd.get(), size)) - boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::basic_work_directory_context::basic_work_directory_context: getcwd(2) failed")); - work_directory = cwd.get(); -#elif defined(BOOST_WINDOWS_API) - char cwd[MAX_PATH]; - if (!::GetCurrentDirectoryA(sizeof(cwd), cwd)) - boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::basic_work_directory_context::basic_work_directory_context: GetCurrentDirectory failed")); - work_directory = cwd; -#endif - BOOST_ASSERT(!work_directory.empty()); - } - - /** - * The process' initial work directory. - * - * The work directory is the directory in which the process starts - * execution. - */ - Path work_directory; -}; - -/** - * Base context class that defines the child's environment. - * - * Base context class that defines the necessary fields to configure a - * child's environment variables. This class is useless on its own - * because no function in the library will accept it as a valid Context - * implementation. - */ -class environment_context -{ -public: - /** - * The process' environment. - * - * Contains the list of environment variables, alongside with their - * values, that will be passed to the spawned child process. - */ - boost::process::environment environment; -}; - -/** - * Process startup execution context. - * - * The context class groups all the parameters needed to configure a - * process' environment during its creation. - */ -template -class basic_context : public basic_work_directory_context, public environment_context -{ -public: - /** - * Child's stdin behavior. - */ - stream_behavior stdin_behavior; - - /** - * Child's stdout behavior. - */ - stream_behavior stdout_behavior; - - /** - * Child's stderr behavior. - */ - stream_behavior stderr_behavior; -}; - -typedef basic_context context; - -/** - * Represents a child process in a pipeline. - * - * This convenience class is a triplet that holds all the data required - * to spawn a new child process in a pipeline. - */ -template -class basic_pipeline_entry -{ -public: - /** - * The executable to launch. - */ - Executable executable; - - /** - * The set of arguments to pass to the executable. - */ - Arguments arguments; - - /** - * The child's execution context. - */ - Context context; - - /** - * The type of the Executable concept used in this template - * instantiation. - */ - typedef Executable executable_type; - - /** - * The type of the Arguments concept used in this template - * instantiation. - */ - typedef Arguments arguments_type; - - /** - * The type of the Context concept used in this template - * instantiation. - */ - typedef Context context_type; - - /** - * Constructs a new pipeline_entry object. - * - * Given the executable, set of arguments and execution triplet, - * constructs a new pipeline_entry object that holds the three - * values. - */ - basic_pipeline_entry(const Executable &exe, const Arguments &args, const Context &ctx) - : executable(exe), - arguments(args), - context(ctx) - { - } -}; - -/** - * Default instantiation of basic_pipeline_entry. - */ -typedef basic_pipeline_entry, context> pipeline_entry; - -} -} - -#endif diff --git a/boost/process/detail/file_handle.hpp b/boost/process/detail/file_handle.hpp deleted file mode 100644 index 33f21d9b6..000000000 --- a/boost/process/detail/file_handle.hpp +++ /dev/null @@ -1,406 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008, 2009 Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/detail/file_handle.hpp - * - * Includes the declaration of the file_handle class. This file is for - * internal usage only and must not be included by the library user. - */ - -#ifndef BOOST_PROCESS_DETAIL_FILE_HANDLE_HPP -#define BOOST_PROCESS_DETAIL_FILE_HANDLE_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -# include -#elif defined(BOOST_WINDOWS_API) -# include -#else -# error "Unsupported platform." -#endif - -#include -#include -#include - -namespace boost { -namespace process { -namespace detail { - -/** - * Simple RAII model for system file handles. - * - * The \a file_handle class is a simple RAII model for native system file - * handles. This class wraps one of such handles grabbing its ownership, - * and automaticaly closes it upon destruction. It is basically used - * inside the library to avoid leaking open file handles, shall an - * unexpected execution trace occur. - * - * A \a file_handle object can be copied but doing so invalidates the - * source object. There can only be a single valid \a file_handle object - * for a given system file handle. This is similar to std::auto_ptr's - * semantics. - * - * This class also provides some convenience methods to issue special file - * operations under their respective platforms. - */ -class file_handle -{ -public: -#if defined(BOOST_PROCESS_DOXYGEN) - /** - * Opaque name for the native handle type. - * - * Each operating system identifies file handles using a specific type. - * The \a handle_type type is used to transparently refer to file - * handles regarless of the operating system in which this class is - * used. - * - * If this class is used on a POSIX system, \a NativeSystemHandle is - * an integer type while it is a \a HANDLE on a Windows system. - */ - typedef NativeSystemHandle handle_type; -#elif defined(BOOST_POSIX_API) - typedef int handle_type; -#elif defined(BOOST_WINDOWS_API) - typedef HANDLE handle_type; -#endif - - /** - * Constructs an invalid file handle. - * - * This constructor creates a new \a file_handle object that represents - * an invalid file handle. An invalid file handle can be copied but - * cannot be manipulated in any way (except checking for its validity). - * - * \see valid() - */ - file_handle() - : handle_(invalid_value()) - { - } - - /** - * Constructs a new file handle from a native file handle. - * - * This constructor creates a new \a file_handle object that takes - * ownership of the given \a h native file handle. The user must not - * close \a h on his own during the lifetime of the new object. - * Ownership can be reclaimed using release(). - * - * \pre The native file handle must be valid; a close operation must - * succeed on it. - * \see release() - */ - file_handle(handle_type h) - : handle_(h) - { - BOOST_ASSERT(handle_ != invalid_value()); - } - - /** - * Copy constructor; invalidates the source handle. - * - * This copy constructor creates a new file handle from a given one. - * Ownership of the native file handle is transferred to the new - * object, effectively invalidating the source file handle. This - * avoids having two live \a file_handle objects referring to the - * same native file handle. The source file handle needs not be - * valid in the name of simplicity. - * - * \post The source file handle is invalid. - * \post The new file handle owns the source's native file handle. - */ - file_handle(const file_handle &fh) - : handle_(fh.handle_) - { - fh.handle_ = invalid_value(); - } - - /** - * Releases resources if the handle is valid. - * - * If the file handle is valid, the destructor closes it. - * - * \see valid() - */ - ~file_handle() - { - if (valid()) - close(); - } - - /** - * Assignment operator; invalidates the source handle. - * - * This assignment operator transfers ownership of the RHS file - * handle to the LHS one, effectively invalidating the source file - * handle. This avoids having two live \a file_handle objects - * referring to the same native file handle. The source file - * handle needs not be valid in the name of simplicity. - * - * \post The RHS file handle is invalid. - * \post The LHS file handle owns RHS' native file handle. - * \return A reference to the LHS file handle. - */ - file_handle &operator=(const file_handle &fh) - { - handle_ = fh.handle_; - fh.handle_ = invalid_value(); - return *this; - } - - /** - * Checks whether the file handle is valid or not. - * - * Returns a boolean indicating whether the file handle is valid or - * not. If the file handle is invalid, no other methods can be - * executed other than the destructor. - * - * \return true if the file handle is valid; false otherwise. - */ - bool valid() const - { - return handle_ != invalid_value(); - } - - /** - * Closes the file handle. - * - * Explicitly closes the file handle, which must be valid. Upon - * exit, the handle is not valid any more. - * - * \pre The file handle is valid. - * \post The file handle is invalid. - * \post The native file handle is closed. - */ - void close() - { - BOOST_ASSERT(valid()); - -#if defined(BOOST_POSIX_API) - ::close(handle_); -#elif defined(BOOST_WINDOWS_API) - ::CloseHandle(handle_); -#endif - - handle_ = invalid_value(); - } - - /** - * Reclaims ownership of the native file handle. - * - * Explicitly reclaims ownership of the native file handle contained - * in the \a file_handle object, returning the native file handle. - * The caller is responsible of closing it later on. - * - * \pre The file handle is valid. - * \post The file handle is invalid. - * \return The native file handle. - */ - handle_type release() - { - BOOST_ASSERT(valid()); - - handle_type h = handle_; - handle_ = invalid_value(); - return h; - } - - /** - * Gets the native file handle. - * - * Returns the native file handle for the \a file_handle object. - * The caller can issue any operation on it except closing it. - * If closing is required, release() shall be used. - * - * \pre The file handle is valid. - * \post The file handle is valid. - * \return The native file handle. - */ - handle_type get() const - { - BOOST_ASSERT(valid()); - - return handle_; - } - -#if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN) - /** - * Changes the native file handle to the given one. - * - * Given a new native file handle \a h, this operation assigns this - * handle to the current object, closing its old native file handle. - * In other words, it first calls dup2() to remap the old handle to - * the new one and then closes the old handle. - * - * If \a h is open, it is automatically closed by dup2(). - * - * This operation is only available in POSIX systems. - * - * \pre The file handle is valid. - * \pre The native file handle \a h is valid; i.e., it must be - * closeable. - * \post The file handle's native file handle is \a h. - * \throw boost::system::system_error If the internal remapping - * operation fails. - */ - void posix_remap(handle_type h) - { - BOOST_ASSERT(valid()); - - if (::dup2(handle_, h) == -1) - boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::detail::file_handle::posix_remap: dup2(2) failed")); - - if (::close(handle_) == -1) - { - ::close(h); - boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::detail::file_handle::posix_remap: close(2) failed")); - } - - handle_ = h; - } - - /** - * Duplicates an open native file handle. - * - * Given a native file handle \a h1, this routine duplicates it so - * that it ends up being identified by the native file handle \a h2 - * and returns a new \a file_handle owning \a h2. - * - * This operation is only available in POSIX systems. - * - * \pre The native file handle \a h1 is open. - * \pre The native file handle \a h2 is valid (non-negative). - * \post The native file handle \a h1 is closed. - * \post The native file handle \a h2 is the same as the old \a h1 - * from the operating system's point of view. - * \return A new \a file_handle object that owns \a h2. - * \throw boost::system::system_error If dup2() fails. - */ - static file_handle posix_dup(int h1, int h2) - { - if (::dup2(h1, h2) == -1) - boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::detail::file_handle::posix_dup: dup2(2) failed")); - - return file_handle(h2); - } -#endif - -#if defined(BOOST_WINDOWS_API) || defined(BOOST_PROCESS_DOXYGEN) - /** - * Duplicates the \a h native file handle. - * - * Given a native file handle \a h, this routine constructs a new - * \a file_handle object that owns a new duplicate of \a h. The - * duplicate's inheritable flag is set to the value of \a inheritable. - * - * This operation is only available in Windows systems. - * - * \pre The native file handle \a h is valid. - * \return A file handle owning a duplicate of \a h. - * \throw boost::system::system_error If DuplicateHandle() fails. - */ - static file_handle win32_dup(HANDLE h, bool inheritable) - { - HANDLE h2; - if (!::DuplicateHandle(::GetCurrentProcess(), h, ::GetCurrentProcess(), &h2, 0, inheritable ? TRUE : FALSE, DUPLICATE_SAME_ACCESS)) - boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::detail::file_handle::win32_dup: DuplicateHandle failed")); - - return file_handle(h2); - } - - /** - * Creates a new duplicate of a standard file handle. - * - * Constructs a new \a file_handle object that owns a duplicate of a - * standard file handle. The \a d parameter specifies which standard - * file handle to duplicate and can be one of \a STD_INPUT_HANDLE, - * \a STD_OUTPUT_HANDLE or \a STD_ERROR_HANDLE. The duplicate's - * inheritable flag is set to the value of \a inheritable. - * - * This operation is only available in Windows systems. - * - * \pre \a d refers to one of the standard handles as described above. - * \return A file handle owning a duplicate of the standard handle - * referred to by \a d. - * \throw boost::system::system_error If GetStdHandle() or - * DuplicateHandle() fails. - */ - static file_handle win32_std(DWORD d, bool inheritable) - { - BOOST_ASSERT(d == STD_INPUT_HANDLE || d == STD_OUTPUT_HANDLE || d == STD_ERROR_HANDLE); - - HANDLE h = ::GetStdHandle(d); - if (h == INVALID_HANDLE_VALUE) - boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::detail::file_handle::win32_std: GetStdHandle failed")); - - return win32_dup(h, inheritable); - } - - /** - * Changes the file handle's inheritable flag. - * - * Changes the file handle's inheritable flag to \a i. It is not - * necessary for the file handle's flag to be different than \a i. - * - * This operation is only available in Windows systems. - * - * \pre The file handle is valid. - * \post The native file handle's inheritable flag is set to \a i. - * \throw boost::system::system_error If the property change fails. - */ - void win32_set_inheritable(bool i) - { - BOOST_ASSERT(valid()); - - if (!::SetHandleInformation(handle_, HANDLE_FLAG_INHERIT, i ? HANDLE_FLAG_INHERIT : 0)) - boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::detail::file_handle::win32_set_inheritable: SetHandleInformation failed")); - } -#endif - -private: - /** - * Internal handle value. - * - * This variable holds the native handle value for the file handle - * hold by this object. It is interesting to note that this needs - * to be mutable because the copy constructor and the assignment - * operator invalidate the source object. - */ - mutable handle_type handle_; - - /** - * Constant function representing an invalid handle value. - * - * Returns the platform-specific handle value that represents an - * invalid handle. This is a constant function rather than a regular - * constant because, in the latter case, we cannot define it under - * Windows due to the value being of a complex type. - */ - static handle_type invalid_value() - { -#if defined(BOOST_POSIX_API) - return -1; -#elif defined(BOOST_WINDOWS_API) - return INVALID_HANDLE_VALUE; -#endif - } -}; - -} -} -} - -#endif diff --git a/boost/process/detail/pipe.hpp b/boost/process/detail/pipe.hpp deleted file mode 100644 index 3c839c228..000000000 --- a/boost/process/detail/pipe.hpp +++ /dev/null @@ -1,187 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008, 2009 Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/detail/pipe.hpp - * - * Includes the declaration of the pipe class. This file is for - * internal usage only and must not be included by the library user. - */ - -#ifndef BOOST_PROCESS_DETAIL_PIPE_HPP -#define BOOST_PROCESS_DETAIL_PIPE_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -# include -#elif defined(BOOST_WINDOWS_API) -# if defined(BOOST_PROCESS_WINDOWS_USE_NAMED_PIPE) -# include -# include -# endif -# include -#else -# error "Unsupported platform." -#endif - -#include -#include -#include - -namespace boost { -namespace process { -namespace detail { - -/** - * Simple RAII model for anonymous pipes. - * - * The pipe class is a simple RAII model for anonymous pipes. It - * provides a portable constructor that allocates a new %pipe and creates - * a pipe object that owns the two file handles associated to it: the - * read end and the write end. - * - * These handles can be retrieved for modification according to - * file_handle semantics. Optionally, their ownership can be transferred - * to external \a file_handle objects which comes handy when the two - * ends need to be used in different places (i.e. after a POSIX fork() - * system call). - * - * Pipes can be copied following the same semantics as file handles. - * In other words, copying a %pipe object invalidates the source one. - * - * \see file_handle - */ -class pipe -{ -public: - /** - * Creates a new %pipe. - * - * The default pipe constructor allocates a new anonymous %pipe - * and assigns its ownership to the created pipe object. On Windows - * when the macro BOOST_PROCESS_WINDOWS_USE_NAMED_PIPE is defined - * a named pipe is created. This is required if asynchronous I/O - * should be used as asynchronous I/O is only supported by named - * pipes on Windows. - * - * \throw boost::system::system_error If the anonymous %pipe - * creation fails. - */ - pipe() - { - file_handle::handle_type hs[2]; - -#if defined(BOOST_POSIX_API) - if (::pipe(hs) == -1) - boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::detail::pipe::pipe: pipe(2) failed")); -#elif defined(BOOST_WINDOWS_API) - SECURITY_ATTRIBUTES sa; - ZeroMemory(&sa, sizeof(sa)); - sa.nLength = sizeof(sa); - sa.lpSecurityDescriptor = NULL; - sa.bInheritHandle = FALSE; - -# if defined(BOOST_PROCESS_WINDOWS_USE_NAMED_PIPE) - static unsigned int nextid = 0; - std::string pipe = "\\\\.\\pipe\\boost_process_" + boost::lexical_cast(::GetCurrentProcessId()) + "_" + boost::lexical_cast(nextid++); - hs[0] = ::CreateNamedPipeA(pipe.c_str(), PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, 0, 1, 8192, 8192, 0, &sa); - if (hs[0] == INVALID_HANDLE_VALUE) - boost::throw_exception(boost::system::system_error(::GetLastError(), boost::system::system_category(), "boost::process::detail::pipe::pipe: CreateNamedPipe failed")); - hs[1] = ::CreateFileA(pipe.c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); - if (hs[1] == INVALID_HANDLE_VALUE) - boost::throw_exception(boost::system::system_error(::GetLastError(), boost::system::system_category(), "boost::process::detail::pipe::pipe: CreateFile failed")); - - OVERLAPPED overlapped; - ZeroMemory(&overlapped, sizeof(overlapped)); - overlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL); - if (!overlapped.hEvent) - boost::throw_exception(boost::system::system_error(::GetLastError(), boost::system::system_category(), "boost::process::detail::pipe::pipe: CreateEvent failed")); - BOOL b = ::ConnectNamedPipe(hs[0], &overlapped); - if (!b) - { - if (::GetLastError() == ERROR_IO_PENDING) - { - if (::WaitForSingleObject(overlapped.hEvent, INFINITE) == WAIT_FAILED) - { - ::CloseHandle(overlapped.hEvent); - boost::throw_exception(boost::system::system_error(::GetLastError(), boost::system::system_category(), "boost::process::detail::pipe::pipe: WaitForSingleObject failed")); - } - } - else if (::GetLastError() != ERROR_PIPE_CONNECTED) - { - ::CloseHandle(overlapped.hEvent); - boost::throw_exception(boost::system::system_error(::GetLastError(), boost::system::system_category(), "boost::process::detail::pipe::pipe: ConnectNamedPipe failed")); - } - } - ::CloseHandle(overlapped.hEvent); -# else - if (!::CreatePipe(&hs[0], &hs[1], &sa, 0)) - boost::throw_exception(boost::system::system_error(::GetLastError(), boost::system::system_category(), "boost::process::detail::pipe::pipe: CreatePipe failed")); -# endif -#endif - - read_end_ = file_handle(hs[0]); - write_end_ = file_handle(hs[1]); - } - - /** - * Returns the %pipe's read end file handle. - * - * Obtains a reference to the %pipe's read end file handle. Care - * should be taken to not duplicate the returned object if ownership - * shall remain to the %pipe. - * - * Duplicating the returned object invalidates its corresponding file - * handle in the %pipe. - * - * \return A reference to the %pipe's read end file handle. - */ - file_handle &rend() - { - return read_end_; - } - - /** - * Returns the %pipe's write end file handle. - * - * Obtains a reference to the %pipe's write end file handle. Care - * should be taken to not duplicate the returned object if ownership - * shall remain to the %pipe. - * - * Duplicating the returned object invalidates its corresponding file - * handle in the %pipe. - * - * \return A reference to the %pipe's write end file handle. - */ - file_handle &wend() - { - return write_end_; - } - -private: - /** - * The %pipe's read end file handle. - */ - file_handle read_end_; - - /** - * The %pipe's write end file handle. - */ - file_handle write_end_; -}; - -} -} -} - -#endif diff --git a/boost/process/detail/posix_ops.hpp b/boost/process/detail/posix_ops.hpp deleted file mode 100644 index 8c39e0ebf..000000000 --- a/boost/process/detail/posix_ops.hpp +++ /dev/null @@ -1,495 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008, 2009 Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/detail/posix_ops.hpp - * - * Provides some convenience functions to start processes under POSIX - * operating systems. - */ - -#ifndef BOOST_PROCESS_DETAIL_POSIX_OPS_HPP -#define BOOST_PROCESS_DETAIL_POSIX_OPS_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace process { -namespace detail { - -/** - * Converts the command line to an array of C strings. - * - * Converts the command line's list of arguments to the format expected - * by the \a argv parameter in the POSIX execve() system call. - * - * This operation is only available on POSIX systems. - * - * \return The first argument of the pair is an integer that indicates - * how many strings are stored in the second argument. The - * second argument is a NULL-terminated, dynamically allocated - * array of dynamically allocated strings holding the arguments - * to the executable. The caller is responsible of freeing them. - */ -template -inline std::pair collection_to_posix_argv(const Arguments &args) -{ - std::size_t nargs = args.size(); - BOOST_ASSERT(nargs > 0); - - char **argv = new char*[nargs + 1]; - typename Arguments::size_type i = 0; - for (typename Arguments::const_iterator it = args.begin(); it != args.end(); ++it) - { - argv[i] = new char[it->size() + 1]; - std::strncpy(argv[i], it->c_str(), it->size() + 1); - ++i; - } - argv[nargs] = 0; - - return std::pair(nargs, argv); -} - -/** - * Converts an environment to a char** table as used by execve(). - * - * Converts the environment's contents to the format used by the - * execve() system call. The returned char** array is allocated - * in dynamic memory; the caller must free it when not used any - * more. Each entry is also allocated in dynamic memory and is a - * NULL-terminated string of the form var=value; these must also be - * released by the caller. - * - * \return A dynamically allocated char** array that represents - * the environment's content. Each array entry is a - * NULL-terminated string of the form var=value. - */ -inline char **environment_to_envp(const environment &env) -{ - char **envp = new char*[env.size() + 1]; - - environment::size_type i = 0; - for (environment::const_iterator it = env.begin(); it != env.end(); ++it) - { - std::string s = it->first + "=" + it->second; - envp[i] = new char[s.size() + 1]; - std::strncpy(envp[i], s.c_str(), s.size() + 1); - ++i; - } - envp[i] = 0; - - return envp; -} - -/** - * Holds a mapping between native file descriptors and their corresponding - * pipes to set up communication between the parent and the %child process. - */ -typedef std::map info_map; - -/** - * Helper class to configure a POSIX %child. - * - * This helper class is used to hold all the attributes that configure a - * new POSIX %child process and to centralize all the actions needed to - * make them effective. - * - * All its fields are public for simplicity. It is only intended for - * internal use and it is heavily coupled with the Context - * implementations. - */ -struct posix_setup -{ - /** - * The work directory. - * - * This string specifies the directory in which the %child process - * starts execution. It cannot be empty. - */ - std::string work_directory; - - /** - * The chroot directory, if any. - * - * Specifies the directory in which the %child process is chrooted - * before execution. Empty if this feature is not desired. - */ - std::string chroot; - - /** - * The user credentials. - * - * UID that specifies the user credentials to use to run the %child - * process. Defaults to the current UID. - */ - uid_t uid; - - /** - * The effective user credentials. - * - * EUID that specifies the effective user credentials to use to run - * the %child process. Defaults to the current EUID. - */ - uid_t euid; - - /** - * The group credentials. - * - * GID that specifies the group credentials to use to run the %child - * process. Defaults to the current GID. - */ - gid_t gid; - - /** - * The effective group credentials. - * - * EGID that specifies the effective group credentials to use to run - * the %child process. Defaults to the current EGID. - */ - gid_t egid; - - /** - * Creates a new properties set. - * - * Creates a new object that has sensible default values for all the - * properties. - */ - posix_setup() - : uid(::getuid()), - euid(::geteuid()), - gid(::getgid()), - egid(::getegid()) - { - } - - /** - * Sets up the execution environment. - * - * Modifies the current execution environment (that of the %child) so - * that the properties become effective. - * - * \throw boost::system::system_error If any error ocurred during - * environment configuration. The child process should abort - * execution if this happens because its start conditions - * cannot be met. - */ - void operator()() const - { - if (!chroot.empty() && ::chroot(chroot.c_str()) == -1) - boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::detail::posix_setup: chroot(2) failed")); - - if (gid != ::getgid() && ::setgid(gid) == -1) - boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::detail::posix_setup: setgid(2) failed")); - - if (egid != ::getegid() && ::setegid(egid) == -1) - boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::detail::posix_setup: setegid(2) failed")); - - if (uid != ::getuid() && ::setuid(uid) == -1) - boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::detail::posix_setup: setuid(2) failed")); - - if (euid != ::geteuid() && ::seteuid(euid) == -1) - boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::detail::posix_setup: seteuid(2) failed")); - - BOOST_ASSERT(!work_directory.empty()); - if (::chdir(work_directory.c_str()) == -1) - boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::detail::posix_setup: chdir(2) failed")); - } -}; - -/** - * Configures child process' input streams. - * - * Sets up the current process' input streams to behave according to the - * information in the \a info map. \a closeflags is modified to reflect - * those descriptors that should not be closed because they where modified - * by the function. - * - * Modifies the current execution environment, so this should only be run - * on the child process after the fork(2) has happened. - * - * \throw boost::system::system_error If any error occurs during the - * configuration. - */ -inline void setup_input(info_map &info, bool *closeflags, int maxdescs) -{ - for (info_map::iterator it = info.begin(); it != info.end(); ++it) - { - int d = it->first; - stream_info &si = it->second; - - BOOST_ASSERT(d < maxdescs); - closeflags[d] = false; - - switch (si.type_) - { - case stream_info::use_file: - { - int fd = ::open(si.file_.c_str(), O_RDONLY); - if (fd == -1) - boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::detail::setup_input: open(2) of " + si.file_ + " failed")); - if (fd != d) - { - file_handle h(fd); - h.posix_remap(d); - h.release(); - } - break; - } - case stream_info::use_handle: - { - if (si.handle_.get() != d) - si.handle_.posix_remap(d); - break; - } - case stream_info::use_pipe: - { - si.pipe_->wend().close(); - if (d != si.pipe_->rend().get()) - si.pipe_->rend().posix_remap(d); - break; - } - default: - { - BOOST_ASSERT(si.type_ == stream_info::inherit); - break; - } - } - } -} - -/** - * Configures child process' output streams. - * - * Sets up the current process' output streams to behave according to the - * information in the \a info map. \a closeflags is modified to reflect - * those descriptors that should not be closed because they where - * modified by the function. - * - * Modifies the current execution environment, so this should only be run - * on the child process after the fork(2) has happened. - * - * \throw boost::system::system_error If any error occurs during the - * configuration. - */ -inline void setup_output(info_map &info, bool *closeflags, int maxdescs) -{ - for (info_map::iterator it = info.begin(); it != info.end(); ++it) - { - int d = it->first; - stream_info &si = it->second; - - BOOST_ASSERT(d < maxdescs); - closeflags[d] = false; - - switch (si.type_) - { - case stream_info::redirect: - { - break; - } - case stream_info::use_file: - { - int fd = ::open(si.file_.c_str(), O_WRONLY); - if (fd == -1) - boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::detail::setup_output: open(2) of " + si.file_ + " failed")); - if (fd != d) - { - file_handle h(fd); - h.posix_remap(d); - h.release(); - } - break; - } - case stream_info::use_handle: - { - if (si.handle_.get() != d) - si.handle_.posix_remap(d); - break; - } - case stream_info::use_pipe: - { - si.pipe_->rend().close(); - if (d != si.pipe_->wend().get()) - si.pipe_->wend().posix_remap(d); - break; - } - default: - { - BOOST_ASSERT(si.type_ == stream_info::inherit); - break; - } - } - } - - for (info_map::const_iterator it = info.begin(); it != info.end(); ++it) - { - int d = it->first; - const stream_info &si = it->second; - - if (si.type_ == stream_info::redirect) - file_handle::posix_dup(si.desc_to_, d).release(); - } -} - -/** - * Starts a new child process in a POSIX operating system. - * - * This helper functions is provided to simplify the Context's task when - * it comes to starting up a new process in a POSIX operating system. - * The function hides all the details of the fork/exec pair of calls as - * well as all the setup of communication pipes and execution environment. - * - * \param exe The executable to spawn the child process. - * \param args The arguments for the executable. - * \param env The environment variables that the new child process - * receives. - * \param infoin A map describing all input file descriptors to be - * redirected. - * \param infoout A map describing all output file descriptors to be - * redirected. - * \param setup A helper object used to configure the child's execution - * environment. - * \return The new process' PID. The caller is responsible of creating - * an appropriate Child representation for it. - */ -template -inline pid_t posix_start(const Executable &exe, const Arguments &args, const environment &env, info_map &infoin, info_map &infoout, const posix_setup &setup) -{ - pid_t pid = ::fork(); - if (pid == -1) - boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::detail::posix_start: fork(2) failed")); - else if (pid == 0) - { -#if defined(F_MAXFD) - int maxdescs = ::fcntl(-1, F_MAXFD, 0); - if (maxdescs == -1) - maxdescs = ::sysconf(_SC_OPEN_MAX); -#else - int maxdescs = ::sysconf(_SC_OPEN_MAX); -#endif - if (maxdescs == -1) - maxdescs = 1024; - try - { - boost::scoped_array closeflags(new bool[maxdescs]); - for (int i = 0; i < maxdescs; ++i) - closeflags[i] = true; - - setup_input(infoin, closeflags.get(), maxdescs); - setup_output(infoout, closeflags.get(), maxdescs); - - for (int i = 0; i < maxdescs; ++i) - { - if (closeflags[i]) - ::close(i); - } - - setup(); - } - catch (const boost::system::system_error &e) - { - ::write(STDERR_FILENO, e.what(), std::strlen(e.what())); - ::write(STDERR_FILENO, "\n", 1); - std::exit(EXIT_FAILURE); - } - - std::pair argcv = collection_to_posix_argv(args); - char **envp = environment_to_envp(env); - - ::execve(exe.c_str(), argcv.second, envp); - boost::system::system_error e(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::detail::posix_start: execve(2) failed"); - - for (std::size_t i = 0; i < argcv.first; ++i) - delete[] argcv.second[i]; - delete[] argcv.second; - - for (std::size_t i = 0; i < env.size(); ++i) - delete[] envp[i]; - delete[] envp; - - ::write(STDERR_FILENO, e.what(), std::strlen(e.what())); - ::write(STDERR_FILENO, "\n", 1); - std::exit(EXIT_FAILURE); - } - - BOOST_ASSERT(pid > 0); - - for (info_map::iterator it = infoin.begin(); it != infoin.end(); ++it) - { - stream_info &si = it->second; - if (si.type_ == stream_info::use_pipe) - si.pipe_->rend().close(); - } - - for (info_map::iterator it = infoout.begin(); it != infoout.end(); ++it) - { - stream_info &si = it->second; - if (si.type_ == stream_info::use_pipe) - si.pipe_->wend().close(); - } - - return pid; -} - -/** - * Locates a communication pipe and returns one of its endpoints. - * - * Given a \a info map, and a file descriptor \a desc, searches for its - * communicataion pipe in the map and returns one of its endpoints as - * indicated by the \a out flag. This is intended to be used by a - * parent process after a fork(2) call. - * - * \pre If the info map contains the given descriptor, it is configured - * to use a pipe. - * \post The info map does not contain the given descriptor. - * \return If the file descriptor is found in the map, returns the pipe's - * read end if out is true; otherwise its write end. If the - * descriptor is not found returns an invalid file handle. - */ -inline file_handle posix_info_locate_pipe(info_map &info, int desc, bool out) -{ - file_handle fh; - - info_map::iterator it = info.find(desc); - if (it != info.end()) - { - stream_info &si = it->second; - if (si.type_ == stream_info::use_pipe) - { - fh = out ? si.pipe_->rend().release() : si.pipe_->wend().release(); - BOOST_ASSERT(fh.valid()); - } - info.erase(it); - } - - return fh; -} - -} -} -} - -#endif diff --git a/boost/process/detail/stream_info.hpp b/boost/process/detail/stream_info.hpp deleted file mode 100644 index 89f4b361d..000000000 --- a/boost/process/detail/stream_info.hpp +++ /dev/null @@ -1,176 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008, 2009 Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/detail/stream_info.hpp - * - * Provides the definition of the stream_info structure. - */ - -#ifndef BOOST_PROCESS_DETAIL_STREAM_INFO_HPP -#define BOOST_PROCESS_DETAIL_STREAM_INFO_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -#elif defined(BOOST_WINDOWS_API) -#else -# error "Unsupported platform." -#endif - -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace process { -namespace detail { - -/** - * Configuration data for a file descriptor. - * - * This convenience structure provides a compact way to pass information - * around on how to configure a file descriptor. It is a lower-level - * representation of stream_behavior, as it can hold the same information - * but in a way that can be used by the underlying operating system. - */ -struct stream_info -{ - /** - * Supported stream types. - */ - enum type - { - /** - * Matches stream_behavior::close. - */ - close, - - /** - * Matches stream_behavior::inherit. - */ - inherit, - - /** - * Matches stream_behavior::redirect_to_stdout and - * stream_behavior::posix_redirect. - */ - redirect, - - /** - * Matches stream_behavior::silence. - */ - use_file, - - /** - * TODO: Matches nothing yet ... - */ - use_handle, - - /** - * Matches stream_behavior::capture. - */ - use_pipe - }; - - /** - * Stream type. - */ - type type_; - - /** - * Descriptor to use when stream type is set to \a redirect. - */ - int desc_to_; - - /** - * File to use when stream type is set to \a use_file. - */ - std::string file_; - - /** - * Handle to use when stream type is set to \a use_handle. - */ - file_handle handle_; - - /** - * Pipe to use when stream type is set to \a use_pipe. - */ - boost::optional pipe_; - - /** - * Constructs a new stream_info object. - */ - stream_info(const stream_behavior &sb, bool out) - { - switch (sb.type_) - { - case stream_behavior::close: - { - type_ = close; - break; - } - case stream_behavior::inherit: - { - type_ = inherit; - break; - } - case stream_behavior::redirect_to_stdout: - { - type_ = redirect; -#if defined(BOOST_POSIX_API) - desc_to_ = STDOUT_FILENO; -#elif defined(BOOST_WINDOWS_API) - desc_to_ = 1; -#endif - break; - } -#if defined(BOOST_POSIX_API) - case stream_behavior::posix_redirect: - { - type_ = redirect; - desc_to_ = sb.desc_to_; - break; - } -#endif - case stream_behavior::silence: - { - type_ = use_file; -#if defined(BOOST_POSIX_API) - file_ = out ? "/dev/null" : "/dev/zero"; -#elif defined(BOOST_WINDOWS_API) - file_ = "NUL"; -#endif - break; - } - case stream_behavior::capture: - { - type_ = use_pipe; - pipe_ = pipe(); - break; - } - default: - { - BOOST_ASSERT(false); - } - } - } -}; - -} -} -} - -#endif diff --git a/boost/process/detail/systembuf.hpp b/boost/process/detail/systembuf.hpp deleted file mode 100644 index 332e864f2..000000000 --- a/boost/process/detail/systembuf.hpp +++ /dev/null @@ -1,231 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008, 2009 Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/detail/systembuf.hpp - * - * Includes the declaration of the systembuf class. This file is for - * internal usage only and must not be included by the library user. - */ - -#ifndef BOOST_PROCESS_DETAIL_SYSTEMBUF_HPP -#define BOOST_PROCESS_DETAIL_SYSTEMBUF_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -# include -#elif defined(BOOST_WINDOWS_API) -# include -#else -# error "Unsupported platform." -#endif - -#include -#include -#include -#include -#include - -namespace boost { -namespace process { - -class postream; - -namespace detail { - -/** - * std::streambuf implementation for system file handles. - * - * systembuf provides a std::streambuf implementation for system file - * handles. Contrarywise to file_handle, this class does \b not take - * ownership of the native file handle; this should be taken care of - * somewhere else. - * - * This class follows the expected semantics of a std::streambuf object. - * However, it is not copyable to avoid introducing inconsistences with - * the on-disk file and the in-memory buffers. - */ -class systembuf : public std::streambuf, public boost::noncopyable -{ - friend class ::boost::process::postream; - -public: -#if defined(BOOST_PROCESS_DOXYGEN) - /** - * Opaque name for the native handle type. - */ - typedef NativeHandleType handle_type; -#elif defined(BOOST_POSIX_API) - typedef int handle_type; -#elif defined(BOOST_WINDOWS_API) - typedef HANDLE handle_type; -#endif - - /** - * Constructs a new systembuf for the given file handle. - * - * This constructor creates a new systembuf object that reads or - * writes data from/to the \a h native file handle. This handle - * is \b not owned by the created systembuf object; the code - * should take care of it externally. - * - * This class buffers input and output; the buffer size may be - * tuned through the \a bufsize parameter, which defaults to 8192 - * bytes. - * - * \see pistream and postream - */ - explicit systembuf(handle_type h, std::size_t bufsize = 8192) - : handle_(h), - bufsize_(bufsize), - read_buf_(new char[bufsize]), - write_buf_(new char[bufsize]) - { -#if defined(BOOST_POSIX_API) - BOOST_ASSERT(handle_ >= 0); -#elif defined(BOOST_WINDOWS_API) - BOOST_ASSERT(handle_ != INVALID_HANDLE_VALUE); -#endif - BOOST_ASSERT(bufsize_ > 0); - - setp(write_buf_.get(), write_buf_.get() + bufsize_); - } - -protected: - /** - * Reads new data from the native file handle. - * - * This operation is called by input methods when there is no more - * data in the input buffer. The function fills the buffer with new - * data, if available. - * - * \pre All input positions are exhausted (gptr() >= egptr()). - * \post The input buffer has new data, if available. - * \returns traits_type::eof() if a read error occurrs or there are - * no more data to be read. Otherwise returns - * traits_type::to_int_type(*gptr()). - */ - virtual int_type underflow() - { - BOOST_ASSERT(gptr() >= egptr()); - - bool ok; -#if defined(BOOST_POSIX_API) - ssize_t cnt = ::read(handle_, read_buf_.get(), bufsize_); - ok = (cnt != -1 && cnt != 0); -#elif defined(BOOST_WINDOWS_API) - DWORD cnt; - BOOL res = ::ReadFile(handle_, read_buf_.get(), bufsize_, &cnt, NULL); - ok = (res && cnt > 0); -#endif - - if (!ok) - return traits_type::eof(); - else - { - setg(read_buf_.get(), read_buf_.get(), read_buf_.get() + cnt); - return traits_type::to_int_type(*gptr()); - } - } - - /** - * Makes room in the write buffer for additional data. - * - * This operation is called by output methods when there is no more - * space in the output buffer to hold a new element. The function - * first flushes the buffer's contents to disk and then clears it to - * leave room for more characters. The given \a c character is - * stored at the beginning of the new space. - * - * \pre All output positions are exhausted (pptr() >= epptr()). - * \post The output buffer has more space if no errors occurred - * during the write to disk. - * \post *(pptr() - 1) is \a c. - * \returns traits_type::eof() if a write error occurrs. Otherwise - * returns traits_type::not_eof(c). - */ - virtual int_type overflow(int c) - { - BOOST_ASSERT(pptr() >= epptr()); - - if (sync() == -1) - return traits_type::eof(); - - if (!traits_type::eq_int_type(c, traits_type::eof())) - { - traits_type::assign(*pptr(), c); - pbump(1); - } - - return traits_type::not_eof(c); - } - - /** - * Flushes the output buffer to disk. - * - * Synchronizes the systembuf buffers with the contents of the file - * associated to this object through the native file handle. The - * output buffer is flushed to disk and cleared to leave new room - * for more data. - * - * \returns 0 on success, -1 if an error occurred. - */ - virtual int sync() - { -#if defined(BOOST_POSIX_API) - ssize_t cnt = pptr() - pbase(); -#elif defined(BOOST_WINDOWS_API) - long cnt = pptr() - pbase(); -#endif - - bool ok; -#if defined(BOOST_POSIX_API) - ok = ::write(handle_, pbase(), cnt) == cnt; -#elif defined(BOOST_WINDOWS_API) - DWORD rcnt; - BOOL res = ::WriteFile(handle_, pbase(), cnt, &rcnt, NULL); - ok = (res && static_cast(rcnt) == cnt); -#endif - - if (ok) - pbump(-cnt); - return ok ? 0 : -1; - } - -private: - /** - * Native file handle used by the systembuf object. - */ - handle_type handle_; - - /** - * Internal buffer size used during read and write operations. - */ - std::size_t bufsize_; - - /** - * Internal buffer used during read operations. - */ - boost::scoped_array read_buf_; - - /** - * Internal buffer used during write operations. - */ - boost::scoped_array write_buf_; -}; - -} -} -} - -#endif diff --git a/boost/process/detail/win32_ops.hpp b/boost/process/detail/win32_ops.hpp deleted file mode 100644 index d84de9b71..000000000 --- a/boost/process/detail/win32_ops.hpp +++ /dev/null @@ -1,355 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008, 2009 Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/detail/win32_ops.hpp - * - * Provides some convenience functions to start processes under - * Windows-compatible operating systems. - */ - -#ifndef BOOST_PROCESS_DETAIL_WIN32_OPS_HPP -#define BOOST_PROCESS_DETAIL_WIN32_OPS_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace process { -namespace detail { - -/** - * Converts the command line to a plain string. Converts the command line's - * list of arguments to the format expected by the \a lpCommandLine parameter - * in the CreateProcess() system call. - * - * This operation is only available on Windows systems. - * - * \return A dynamically allocated string holding the command line - * to be passed to the executable. It is returned in a - * shared_array object to ensure its release at some point. - */ -template -inline boost::shared_array collection_to_win32_cmdline(const Arguments &args) -{ - typedef std::vector arguments_t; - arguments_t args2; - typename Arguments::size_type i = 0; - std::size_t size = 0; - for (typename Arguments::const_iterator it = args.begin(); it != args.end(); ++it) - { - std::string arg = *it; - - std::string::size_type pos = 0; - while ( (pos = arg.find('"', pos)) != std::string::npos) - { - arg.replace(pos, 1, "\\\""); - pos += 2; - } - - if (arg.find(' ') != std::string::npos) - arg = '\"' + arg + '\"'; - - if (i++ != args.size() - 1) - arg += ' '; - - args2.push_back(arg); - size += arg.size() + 1; - } - - boost::shared_array cmdline(new char[size]); - cmdline.get()[0] = '\0'; - for (arguments_t::size_type i = 0; i < args.size(); ++i) -#if defined(__CYGWIN__) - ::strncat(cmdline.get(), args2[i].c_str(), args2[i].size()); -#else - ::strcat_s(cmdline.get(), size, args2[i].c_str()); -#endif - - return cmdline; -} - -/** - * Converts an environment to a string used by CreateProcess(). - * - * Converts the environment's contents to the format used by the - * CreateProcess() system call. The returned char* string is - * allocated in dynamic memory; the caller must free it when not - * used any more. This is enforced by the use of a shared pointer. - * - * \return A dynamically allocated char* string that represents - * the environment's content. This string is of the form - * var1=value1\\0var2=value2\\0\\0. - */ -inline boost::shared_array environment_to_win32_strings(const environment &env) -{ - boost::shared_array envp; - - if (env.empty()) - { - envp.reset(new char[2]); - ::ZeroMemory(envp.get(), 2); - } - else - { - std::string s; - for (environment::const_iterator it = env.begin(); it != env.end(); ++it) - { - s += it->first + "=" + it->second; - s.push_back(0); - } - - envp.reset(new char[s.size() + 1]); -#if defined(__CYGWIN__) - ::memcpy(envp.get(), s.c_str(), s.size() + 1); -#else - ::memcpy_s(envp.get(), s.size() + 1, s.c_str(), s.size() + 1); -#endif - } - - return envp; -} - -/** - * Helper class to configure a Win32 %child. - * - * This helper class is used to hold all the attributes that configure a - * new Win32 %child process. - * - * All its fields are public for simplicity. It is only intended for - * internal use and it is heavily coupled with the Context - * implementations. - */ -struct win32_setup -{ - /** - * The work directory. - * - * This string specifies the directory in which the %child process - * starts execution. It cannot be empty. - */ - std::string work_directory; - - /** - * The process startup properties. - * - * This Win32-specific object holds a list of properties that describe - * how the new process should be started. The \a STARTF_USESTDHANDLES - * flag should not be set in it because it is automatically configured - * by win32_start(). - */ - STARTUPINFOA *startupinfo; -}; - -/** - * Starts a new child process in a Win32 operating system. - * - * This helper functions is provided to simplify the Context's task when - * it comes to starting up a new process in a Win32 operating system. - * - * \param exe The executable to spawn the child process. - * \param args The arguments for the executable. - * \param env The environment variables that the new child process - * receives. - * \param infoin Information that describes stdin's behavior. - * \param infoout Information that describes stdout's behavior. - * \param infoerr Information that describes stderr's behavior. - * \param setup A helper object holding extra child information. - * \return The new process' information as returned by the CreateProcess() - * system call. The caller is responsible of creating an - * appropriate Child representation for it. - * \pre \a setup.startupinfo_ cannot have the \a STARTF_USESTDHANDLES set - * in the \a dwFlags field. - */ -template -inline PROCESS_INFORMATION win32_start(const Executable &exe, const Arguments &args, const environment &env, stream_info &infoin, stream_info &infoout, stream_info &infoerr, const win32_setup &setup) -{ - file_handle chin, chout, cherr; - - BOOST_ASSERT(setup.startupinfo->cb >= sizeof(STARTUPINFOA)); - BOOST_ASSERT(!(setup.startupinfo->dwFlags & STARTF_USESTDHANDLES)); - - boost::scoped_ptr si(new STARTUPINFOA); - ::CopyMemory(si.get(), setup.startupinfo, sizeof(*setup.startupinfo)); - si->dwFlags |= STARTF_USESTDHANDLES; - - switch (infoin.type_) - { - case stream_info::close: - { - break; - } - case stream_info::inherit: - { - chin = file_handle::win32_std(STD_INPUT_HANDLE, true); - break; - } - case stream_info::use_file: - { - HANDLE h = ::CreateFileA(infoin.file_.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (h == INVALID_HANDLE_VALUE) - boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::detail::win32_start: CreateFile failed")); - chin = file_handle(h); - break; - } - case stream_info::use_handle: - { - chin = infoin.handle_; - chin.win32_set_inheritable(true); - break; - } - case stream_info::use_pipe: - { - infoin.pipe_->rend().win32_set_inheritable(true); - chin = infoin.pipe_->rend(); - break; - } - default: - { - BOOST_ASSERT(false); - break; - } - } - - si->hStdInput = chin.valid() ? chin.get() : INVALID_HANDLE_VALUE; - - switch (infoout.type_) - { - case stream_info::close: - { - break; - } - case stream_info::inherit: - { - chout = file_handle::win32_std(STD_OUTPUT_HANDLE, true); - break; - } - case stream_info::use_file: - { - HANDLE h = ::CreateFileA(infoout.file_.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (h == INVALID_HANDLE_VALUE) - boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::detail::win32_start: CreateFile failed")); - chout = file_handle(h); - break; - } - case stream_info::use_handle: - { - chout = infoout.handle_; - chout.win32_set_inheritable(true); - break; - } - case stream_info::use_pipe: - { - infoout.pipe_->wend().win32_set_inheritable(true); - chout = infoout.pipe_->wend(); - break; - } - default: - { - BOOST_ASSERT(false); - break; - } - } - - si->hStdOutput = chout.valid() ? chout.get() : INVALID_HANDLE_VALUE; - - switch (infoerr.type_) - { - case stream_info::close: - { - break; - } - case stream_info::inherit: - { - cherr = file_handle::win32_std(STD_ERROR_HANDLE, true); - break; - } - case stream_info::redirect: - { - BOOST_ASSERT(infoerr.desc_to_ == 1); - BOOST_ASSERT(chout.valid()); - cherr = file_handle::win32_dup(chout.get(), true); - break; - } - case stream_info::use_file: - { - HANDLE h = ::CreateFileA(infoerr.file_.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (h == INVALID_HANDLE_VALUE) - boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::detail::win32_start: CreateFile failed")); - cherr = file_handle(h); - break; - } - case stream_info::use_handle: - { - cherr = infoerr.handle_; - cherr.win32_set_inheritable(true); - break; - } - case stream_info::use_pipe: - { - infoerr.pipe_->wend().win32_set_inheritable(true); - cherr = infoerr.pipe_->wend(); - break; - } - default: - { - BOOST_ASSERT(false); - break; - } - } - - si->hStdError = cherr.valid() ? cherr.get() : INVALID_HANDLE_VALUE; - - PROCESS_INFORMATION pi; - ::ZeroMemory(&pi, sizeof(pi)); - - boost::shared_array cmdline = collection_to_win32_cmdline(args); - - boost::scoped_array executable(new char[exe.size() + 1]); -#if defined(__CYGWIN__) - ::strcpy(executable.get(), exe.c_str()); -#else - ::strcpy_s(executable.get(), exe.size() + 1, exe.c_str()); -#endif - - boost::scoped_array workdir(new char[setup.work_directory.size() + 1]); -#if defined(__CYGWIN__) - ::strcpy(workdir.get(), setup.work_directory.c_str()); -#else - ::strcpy_s(workdir.get(), setup.work_directory.size() + 1, setup.work_directory.c_str()); -#endif - - boost::shared_array envstrs = environment_to_win32_strings(env); - - if (!::CreateProcessA(executable.get()[0] ? executable.get() : NULL, cmdline.get(), NULL, NULL, TRUE, CREATE_NO_WINDOW, envstrs.get(), workdir.get(), si.get(), &pi)) - boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::detail::win32_start: CreateProcess failed")); - - return pi; -} - -} -} -} - -#endif diff --git a/boost/process/environment.hpp b/boost/process/environment.hpp deleted file mode 100644 index be73ed390..000000000 --- a/boost/process/environment.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008, 2009 Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/environment.hpp - * - * Includes the declaration of the environment class. - */ - -#ifndef BOOST_PROCESS_ENVIRONMENT_HPP -#define BOOST_PROCESS_ENVIRONMENT_HPP - -#include -#include - -namespace boost { -namespace process { - -/** - * Representation of a process' environment variables. - * - * The environment is a map that stablishes an unidirectional - * association between variable names and their values and is - * represented by a string to string map. - * - * Variables may be defined to the empty string. Be aware that doing so - * is not portable: POSIX systems will treat such variables as being - * defined to the empty value, but Windows systems are not able to - * distinguish them from undefined variables. - * - * Neither POSIX nor Windows systems support a variable with no name. - * - * It is worthy to note that the environment is sorted alphabetically. - * This is provided for-free by the map container used to implement this - * type, and this behavior is required by Windows systems. - */ -typedef std::map environment; - -} -} - -#endif diff --git a/boost/process/operations.hpp b/boost/process/operations.hpp deleted file mode 100644 index f11d3b423..000000000 --- a/boost/process/operations.hpp +++ /dev/null @@ -1,583 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008, 2009 Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/operations.hpp - * - * Provides miscellaneous free functions. - */ - -#ifndef BOOST_PROCESS_OPERATIONS_HPP -#define BOOST_PROCESS_OPERATIONS_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -# include -# include -# if defined(__CYGWIN__) -# include -# include -# endif -#elif defined(BOOST_WINDOWS_API) -# include -# include -# include -#else -# error "Unsupported platform." -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace process { - -/** - * Locates the executable program \a file in all the directory components - * specified in \a path. If \a path is empty, the value of the PATH - * environment variable is used. - * - * The path variable is interpreted following the same conventions used - * to parse the PATH environment variable in the underlying platform. - * - * \throw boost::filesystem::filesystem_error If the file cannot be found - * in the path. - */ -inline std::string find_executable_in_path(const std::string &file, std::string path = "") -{ -#if defined(BOOST_POSIX_API) - BOOST_ASSERT(file.find('/') == std::string::npos); -#elif defined(BOOST_WINDOWS_API) - BOOST_ASSERT(file.find_first_of("\\/") == std::string::npos); -#endif - - std::string result; - -#if defined(BOOST_POSIX_API) - if (path.empty()) - { - const char *envpath = ::getenv("PATH"); -// if (!envpath) - // boost::throw_exception(boost::filesystem::filesystem_error("boost::process::find_executable_in_path: retrieving PATH failed", file, boost::system::errc::make_error_code(boost::system::errc::no_such_file_or_directory))); - - path = envpath; - } - BOOST_ASSERT(!path.empty()); - -#if defined(__CYGWIN__) - if (!::cygwin_posix_path_list_p(path.c_str())) - { - int size = ::cygwin_win32_to_posix_path_list_buf_size(path.c_str()); - boost::scoped_array cygpath(new char[size]); - ::cygwin_win32_to_posix_path_list(path.c_str(), cygpath.get()); - path = cygpath.get(); - } -#endif - - std::string::size_type pos1 = 0, pos2; - do - { - pos2 = path.find(':', pos1); - std::string dir = (pos2 != std::string::npos) ? path.substr(pos1, pos2 - pos1) : path.substr(pos1); - std::string f = dir + (boost::algorithm::ends_with(dir, "/") ? "" : "/") + file; - if (!::access(f.c_str(), X_OK)) - result = f; - pos1 = pos2 + 1; - } while (pos2 != std::string::npos && result.empty()); -#elif defined(BOOST_WINDOWS_API) - const char *exts[] = { "", ".exe", ".com", ".bat", NULL }; - const char **ext = exts; - while (*ext) - { - char buf[MAX_PATH]; - char *dummy; - DWORD size = ::SearchPathA(path.empty() ? NULL : path.c_str(), file.c_str(), *ext, MAX_PATH, buf, &dummy); - BOOST_ASSERT(size < MAX_PATH); - if (size > 0) - { - result = buf; - break; - } - ++ext; - } -#endif - - // if (result.empty()) -// boost::throw_exception(boost::filesystem::filesystem_error("boost::process::find_executable_in_path: file not found", file, boost::system::errc::make_error_code(boost::system::errc::no_such_file_or_directory))); - - return result; -} - -/** - * Extracts the program name from a given executable. - * - * \return The program name. On Windows the program name - * is returned without a file extension. - */ -inline std::string executable_to_progname(const std::string &exe) -{ - std::string::size_type begin = 0; - std::string::size_type end = std::string::npos; - -#if defined(BOOST_POSIX_API) - std::string::size_type slash = exe.rfind('/'); -#elif defined(BOOST_WINDOWS_API) - std::string::size_type slash = exe.find_last_of("/\\"); -#endif - if (slash != std::string::npos) - begin = slash + 1; - -#if defined(BOOST_WINDOWS_API) - if (exe.size() > 4 && - (boost::algorithm::iends_with(exe, ".exe") || boost::algorithm::iends_with(exe, ".com") || boost::algorithm::iends_with(exe, ".bat"))) - end = exe.size() - 4; -#endif - - return exe.substr(begin, end - begin); -} - -/** - * Starts a new child process. - * - * Launches a new process based on the binary image specified by the - * executable, the set of arguments to be passed to it and several - * parameters that describe the execution context. - * - * \remark Blocking remarks: This function may block if the device - * holding the executable blocks when loading the image. This might - * happen if, e.g., the binary is being loaded from a network share. - * - * \return A handle to the new child process. - */ -template -inline child launch(const Executable &exe, const Arguments &args, const Context &ctx) -{ - detail::file_handle fhstdin, fhstdout, fhstderr; - - BOOST_ASSERT(!args.empty()); - BOOST_ASSERT(!ctx.work_directory.empty()); - -#if defined(BOOST_POSIX_API) - detail::info_map infoin, infoout; - - if (ctx.stdin_behavior.get_type() != stream_behavior::close) - { - detail::stream_info si = detail::stream_info(ctx.stdin_behavior, false); - infoin.insert(detail::info_map::value_type(STDIN_FILENO, si)); - } - - if (ctx.stdout_behavior.get_type() != stream_behavior::close) - { - detail::stream_info si = detail::stream_info(ctx.stdout_behavior, true); - infoout.insert(detail::info_map::value_type(STDOUT_FILENO, si)); - } - - if (ctx.stderr_behavior.get_type() != stream_behavior::close) - { - detail::stream_info si = detail::stream_info(ctx.stderr_behavior, true); - infoout.insert(detail::info_map::value_type(STDERR_FILENO, si)); - } - - detail::posix_setup s; - s.work_directory = ctx.work_directory; - - child::id_type pid = detail::posix_start(exe, args, ctx.environment, infoin, infoout, s); - - if (ctx.stdin_behavior.get_type() == stream_behavior::capture) - { - fhstdin = detail::posix_info_locate_pipe(infoin, STDIN_FILENO, false); - BOOST_ASSERT(fhstdin.valid()); - } - - if (ctx.stdout_behavior.get_type() == stream_behavior::capture) - { - fhstdout = detail::posix_info_locate_pipe(infoout, STDOUT_FILENO, true); - BOOST_ASSERT(fhstdout.valid()); - } - - if (ctx.stderr_behavior.get_type() == stream_behavior::capture) - { - fhstderr = detail::posix_info_locate_pipe(infoout, STDERR_FILENO, true); - BOOST_ASSERT(fhstderr.valid()); - } - - return child(pid, fhstdin, fhstdout, fhstderr); -#elif defined(BOOST_WINDOWS_API) - detail::stream_info behin = detail::stream_info(ctx.stdin_behavior, false); - if (behin.type_ == detail::stream_info::use_pipe) - fhstdin = behin.pipe_->wend(); - detail::stream_info behout = detail::stream_info(ctx.stdout_behavior, true); - if (behout.type_ == detail::stream_info::use_pipe) - fhstdout = behout.pipe_->rend(); - detail::stream_info beherr = detail::stream_info(ctx.stderr_behavior, true); - if (beherr.type_ == detail::stream_info::use_pipe) - fhstderr = beherr.pipe_->rend(); - - STARTUPINFOA si; - ::ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - - detail::win32_setup s; - s.work_directory = ctx.work_directory; - s.startupinfo = &si; - - PROCESS_INFORMATION pi = detail::win32_start(exe, args, ctx.environment, behin, behout, beherr, s); - - if (!::CloseHandle(pi.hThread)) - boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::launch: CloseHandle failed")); - - return child(pi.dwProcessId, fhstdin, fhstdout, fhstderr, detail::file_handle(pi.hProcess)); -#endif -} - -/** - * Launches a shell-based command. - * - * Executes the given command through the default system shell. The - * command is subject to pattern expansion, redirection and pipelining. - * The shell is launched as described by the parameters in the execution - * context. - * - * This function behaves similarly to the system(3) system call. In a - * POSIX system, the command is fed to /bin/sh whereas under a Windows - * system, it is fed to cmd.exe. It is difficult to write portable - * commands as the first parameter, but this function comes in handy in - * multiple situations. - */ -template -inline child launch_shell(const std::string &command, const Context &ctx) -{ - std::string exe; - std::vector args; - -#if defined(BOOST_POSIX_API) - exe = "/bin/sh"; - args.push_back("sh"); - args.push_back("-c"); - args.push_back(command); -#elif defined(BOOST_WINDOWS_API) - char sysdir[MAX_PATH]; - UINT size = ::GetSystemDirectoryA(sysdir, sizeof(sysdir)); - if (!size) - boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::launch_shell: GetWindowsDirectory failed")); - BOOST_ASSERT(size < MAX_PATH); - - exe = std::string(sysdir) + (sysdir[size - 1] != '\\' ? "\\cmd.exe" : "cmd.exe"); - args.push_back("cmd"); - args.push_back("/c"); - args.push_back(command); -#endif - - return launch(exe, args, ctx); -} - -/** - * Launches a pipelined set of child processes. - * - * Given a collection of pipeline_entry objects describing how to launch - * a set of child processes, spawns them all and connects their inputs and - * outputs in a way that permits pipelined communication. - * - * \pre Let 1..N be the processes in the collection: the input behavior of - * the 2..N processes must be set to close_stream(). - * \pre Let 1..N be the processes in the collection: the output behavior of - * the 1..N-1 processes must be set to close_stream(). - * \remark Blocking remarks: This function may block if the device holding - * the executable of one of the entries blocks when loading the - * image. This might happen if, e.g., the binary is being loaded - * from a network share. - * \return A set of Child objects that represent all the processes spawned - * by this call. You should use wait_children() to wait for their - * termination. - */ -template -inline children launch_pipeline(const Entries &entries) -{ - BOOST_ASSERT(entries.size() >= 2); - - children cs; - detail::file_handle fhinvalid; - - boost::scoped_array pipes(new detail::pipe[entries.size() - 1]); - -#if defined(BOOST_POSIX_API) - { - typename Entries::size_type i = 0; - const typename Entries::value_type::context_type &ctx = entries[i].context; - - detail::info_map infoin, infoout; - - if (ctx.stdin_behavior.get_type() != stream_behavior::close) - { - detail::stream_info si = detail::stream_info(ctx.stdin_behavior, false); - infoin.insert(detail::info_map::value_type(STDIN_FILENO, si)); - } - - BOOST_ASSERT(ctx.stdout_behavior.get_type() == stream_behavior::close); - detail::stream_info si2(close_stream(), true); - si2.type_ = detail::stream_info::use_handle; - si2.handle_ = pipes[i].wend().release(); - infoout.insert(detail::info_map::value_type(STDOUT_FILENO, si2)); - - if (ctx.stderr_behavior.get_type() != stream_behavior::close) - { - detail::stream_info si = detail::stream_info(ctx.stderr_behavior, true); - infoout.insert(detail::info_map::value_type(STDERR_FILENO, si)); - } - - detail::posix_setup s; - s.work_directory = ctx.work_directory; - - pid_t pid = detail::posix_start(entries[i].executable, entries[i].arguments, ctx.environment, infoin, infoout, s); - - detail::file_handle fhstdin; - - if (ctx.stdin_behavior.get_type() == stream_behavior::capture) - { - fhstdin = detail::posix_info_locate_pipe(infoin, STDIN_FILENO, false); - BOOST_ASSERT(fhstdin.valid()); - } - - cs.push_back(child(pid, fhstdin, fhinvalid, fhinvalid)); - } - - for (typename Entries::size_type i = 1; i < entries.size() - 1; ++i) - { - const typename Entries::value_type::context_type &ctx = entries[i].context; - detail::info_map infoin, infoout; - - BOOST_ASSERT(ctx.stdin_behavior.get_type() == stream_behavior::close); - detail::stream_info si1(close_stream(), false); - si1.type_ = detail::stream_info::use_handle; - si1.handle_ = pipes[i - 1].rend().release(); - infoin.insert(detail::info_map::value_type(STDIN_FILENO, si1)); - - BOOST_ASSERT(ctx.stdout_behavior.get_type() == stream_behavior::close); - detail::stream_info si2(close_stream(), true); - si2.type_ = detail::stream_info::use_handle; - si2.handle_ = pipes[i].wend().release(); - infoout.insert(detail::info_map::value_type(STDOUT_FILENO, si2)); - - if (ctx.stderr_behavior.get_type() != stream_behavior::close) - { - detail::stream_info si = detail::stream_info(ctx.stderr_behavior, true); - infoout.insert(detail::info_map::value_type(STDERR_FILENO, si)); - } - - detail::posix_setup s; - s.work_directory = ctx.work_directory; - - pid_t pid = detail::posix_start(entries[i].executable, entries[i].arguments, ctx.environment, infoin, infoout, s); - - cs.push_back(child(pid, fhinvalid, fhinvalid, fhinvalid)); - } - - { - typename Entries::size_type i = entries.size() - 1; - const typename Entries::value_type::context_type &ctx = entries[i].context; - - detail::info_map infoin, infoout; - - BOOST_ASSERT(ctx.stdin_behavior.get_type() == stream_behavior::close); - detail::stream_info si1(close_stream(), false); - si1.type_ = detail::stream_info::use_handle; - si1.handle_ = pipes[i - 1].rend().release(); - infoin.insert(detail::info_map::value_type(STDIN_FILENO, si1)); - - if (ctx.stdout_behavior.get_type() != stream_behavior::close) - { - detail::stream_info si = detail::stream_info(ctx.stdout_behavior, true); - infoout.insert(detail::info_map::value_type(STDOUT_FILENO, si)); - } - - if (ctx.stderr_behavior.get_type() != stream_behavior::close) - { - detail::stream_info si = detail::stream_info(ctx.stderr_behavior, true); - infoout.insert(detail::info_map::value_type(STDERR_FILENO, si)); - } - - detail::posix_setup s; - s.work_directory = ctx.work_directory; - - pid_t pid = detail::posix_start(entries[i].executable, entries[i].arguments, ctx.environment, infoin, infoout, s); - - detail::file_handle fhstdout, fhstderr; - - if (ctx.stdout_behavior.get_type() == stream_behavior::capture) - { - fhstdout = detail::posix_info_locate_pipe(infoout, STDOUT_FILENO, true); - BOOST_ASSERT(fhstdout.valid()); - } - - if (ctx.stderr_behavior.get_type() == stream_behavior::capture) - { - fhstderr = detail::posix_info_locate_pipe(infoout, STDERR_FILENO, true); - BOOST_ASSERT(fhstderr.valid()); - } - - cs.push_back(child(pid, fhinvalid, fhstdout, fhstderr)); - } -#elif defined(BOOST_WINDOWS_API) - STARTUPINFOA si; - detail::win32_setup s; - s.startupinfo = &si; - - { - typename Entries::size_type i = 0; - const typename Entries::value_type::context_type &ctx = entries[i].context; - - detail::stream_info sii = detail::stream_info(ctx.stdin_behavior, false); - detail::file_handle fhstdin; - if (sii.type_ == detail::stream_info::use_pipe) - fhstdin = sii.pipe_->wend(); - - BOOST_ASSERT(ctx.stdout_behavior.get_type() == stream_behavior::close); - detail::stream_info sio(close_stream(), true); - sio.type_ = detail::stream_info::use_handle; - sio.handle_ = pipes[i].wend().release(); - - detail::stream_info sie(ctx.stderr_behavior, true); - - s.work_directory = ctx.work_directory; - - ::ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - PROCESS_INFORMATION pi = detail::win32_start(entries[i].executable, entries[i].arguments, ctx.environment, sii, sio, sie, s); - - if (!::CloseHandle(pi.hThread)) - boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::launch_pipeline: CloseHandle failed")); - - cs.push_back(child(pi.dwProcessId, fhstdin, fhinvalid, fhinvalid, detail::file_handle(pi.hProcess))); - } - - for (typename Entries::size_type i = 1; i < entries.size() - 1; ++i) - { - const typename Entries::value_type::context_type &ctx = entries[i].context; - - BOOST_ASSERT(ctx.stdin_behavior.get_type() == stream_behavior::close); - detail::stream_info sii(close_stream(), false); - sii.type_ = detail::stream_info::use_handle; - sii.handle_ = pipes[i - 1].rend().release(); - - detail::stream_info sio(close_stream(), true); - sio.type_ = detail::stream_info::use_handle; - sio.handle_ = pipes[i].wend().release(); - - detail::stream_info sie(ctx.stderr_behavior, true); - - s.work_directory = ctx.work_directory; - - ::ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - PROCESS_INFORMATION pi = detail::win32_start(entries[i].executable, entries[i].arguments, ctx.environment, sii, sio, sie, s); - - if (!::CloseHandle(pi.hThread)) - boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::launch_pipeline: CloseHandle failed")); - - cs.push_back(child(pi.dwProcessId, fhinvalid, fhinvalid, fhinvalid, detail::file_handle(pi.hProcess))); - } - - { - typename Entries::size_type i = entries.size() - 1; - const typename Entries::value_type::context_type &ctx = entries[i].context; - - BOOST_ASSERT(ctx.stdin_behavior.get_type() == stream_behavior::close); - detail::stream_info sii(close_stream(), false); - sii.type_ = detail::stream_info::use_handle; - sii.handle_ = pipes[i - 1].rend().release(); - - detail::file_handle fhstdout, fhstderr; - - detail::stream_info sio(ctx.stdout_behavior, true); - if (sio.type_ == detail::stream_info::use_pipe) - fhstdout = sio.pipe_->rend(); - detail::stream_info sie(ctx.stderr_behavior, true); - if (sie.type_ == detail::stream_info::use_pipe) - fhstderr = sie.pipe_->rend(); - - s.work_directory = ctx.work_directory; - - ::ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - PROCESS_INFORMATION pi = detail::win32_start(entries[i].executable, entries[i].arguments, ctx.environment, sii, sio, sie, s); - - if (!::CloseHandle(pi.hThread)) - boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::launch_pipeline: CloseHandle failed")); - - cs.push_back(child(pi.dwProcessId, fhinvalid, fhstdout, fhstderr, detail::file_handle(pi.hProcess))); - } -#endif - - return cs; -} - -/** - * Waits for a collection of children to terminate. - * - * Given a collection of Child objects (such as std::vector or - * the convenience children type), waits for the termination of all of - * them. - * - * \remark Blocking remarks: This call blocks if any of the children - * processes in the collection has not finalized execution and - * waits until it terminates. - * - * \return The exit status of the first process that returns an error - * code or, if all of them executed correctly, the exit status - * of the last process in the collection. - */ -template -inline status wait_children(Children &cs) -{ - BOOST_ASSERT(cs.size() >= 2); - - typename Children::iterator it = cs.begin(); - while (it != cs.end()) - { - const status s = it->wait(); - ++it; - if (it == cs.end()) - return s; - else if (!s.exited() || s.exit_status() != EXIT_SUCCESS) - { - while (it != cs.end()) - { - it->wait(); - ++it; - } - return s; - } - } - - BOOST_ASSERT(false); - return cs.begin()->wait(); -} - -} -} - -#endif diff --git a/boost/process/pistream.hpp b/boost/process/pistream.hpp deleted file mode 100644 index 958a222d8..000000000 --- a/boost/process/pistream.hpp +++ /dev/null @@ -1,116 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008, 2009 Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/pistream.hpp - * - * Includes the declaration of the pistream class. - */ - -#ifndef BOOST_PROCESS_PISTREAM_HPP -#define BOOST_PROCESS_PISTREAM_HPP - -#include -#include -#include -#include - -namespace boost { -namespace process { - -/** - * Child process' output stream. - * - * The pistream class represents an output communication channel with the - * child process. The child process writes data to this stream and the - * parent process can read it through the pistream object. In other - * words, from the child's point of view, the communication channel is an - * output one, but from the parent's point of view it is an input one; - * hence the confusing pistream name. - * - * pistream objects cannot be copied because they own the file handle - * they use to communicate with the child and because they buffer data - * that flows through the communication channel. - * - * A pistream object behaves as a std::istream stream in all senses. - * The class is only provided because it must provide a method to let - * the caller explicitly close the communication channel. - * - * \remark Blocking remarks: Functions that read data from this - * stream can block if the associated file handle blocks during - * the read. As this class is used to communicate with child - * processes through anonymous pipes, the most typical blocking - * condition happens when the child has no more data to send to - * the pipe's system buffer. When this happens, the buffer - * eventually empties and the system blocks until the writer - * generates some data. - */ -class pistream : public std::istream, public boost::noncopyable -{ -public: - /** - * Creates a new process' output stream. - * - * Given a file handle, this constructor creates a new pistream - * object that owns the given file handle \a fh. Ownership of - * \a fh is transferred to the created pistream object. - * - * \pre \a fh is valid. - * \post \a fh is invalid. - * \post The new pistream object owns \a fh. - */ - explicit pistream(detail::file_handle &fh) - : std::istream(0), - handle_(fh), - systembuf_(handle_.get()) - { - rdbuf(&systembuf_); - } - - /** - * Returns the file handle managed by this stream. - * - * The file handle must not be copied. Copying invalidates - * the source file handle making the pistream unusable. - */ - detail::file_handle &handle() - { - return handle_; - } - - /** - * Closes the file handle managed by this stream. - * - * Explicitly closes the file handle managed by this stream. This - * function can be used by the user to tell the child process it's - * not willing to receive more data. - */ - void close() - { - handle_.close(); - } - -private: - /** - * The file handle managed by this stream. - */ - detail::file_handle handle_; - - /** - * The systembuf object used to manage this stream's data. - */ - detail::systembuf systembuf_; -}; - -} -} - -#endif diff --git a/boost/process/posix_child.hpp b/boost/process/posix_child.hpp deleted file mode 100644 index 62bdc3180..000000000 --- a/boost/process/posix_child.hpp +++ /dev/null @@ -1,178 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008, 2009 Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/posix_child.hpp - * - * Includes the declaration of the posix_child class. - */ - -#ifndef BOOST_PROCESS_POSIX_CHILD_HPP -#define BOOST_PROCESS_POSIX_CHILD_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace process { - -/** - * POSIX implementation of the Child concept. - * - * The posix_child class implements the Child concept in a POSIX - * operating system. - * - * A POSIX child differs from a regular child (represented by a - * child object) in that it supports more than three communication - * channels with its parent. These channels are identified by regular - * file descriptors (integers). - * - * This class is built on top of the generic child so as to allow its - * trivial adoption. When a program is changed to use the POSIX-specific - * context (posix_context), it will most certainly need to migrate its - * use of the child class to posix_child. Doing so is only a matter of - * redefining the appropriate object and later using the required extra - * features: there should be no need to modify the existing code (e.g. - * method calls) in any other way. - */ -class posix_child : public child -{ -public: - /** - * Gets a reference to the child's input stream \a desc. - * - * Returns a reference to a postream object that represents one of - * the multiple input communication channels with the child process. - * The channel is identified by \a desc as seen from the child's - * point of view. The parent can use the returned stream to send - * data to the child. - * - * Giving this function the STDIN_FILENO constant (defined in - * unistd.h) is a synonym for the get_stdin() call inherited from - * child. - */ - postream &get_input(int desc) const - { - if (desc == STDIN_FILENO) - return posix_child::get_stdin(); - else - { - input_map_t::const_iterator it = input_map_.find(desc); - BOOST_ASSERT(it != input_map_.end()); - return *it->second; - } - } - - /** - * Gets a reference to the child's output stream \a desc. - * - * Returns a reference to a pistream object that represents one of - * the multiple output communication channels with the child process. - * The channel is identified by \a desc as seen from the child's - * point of view. The parent can use the returned stream to retrieve - * data from the child. - * - * Giving this function the STDOUT_FILENO or STDERR_FILENO constants - * (both defined in unistd.h) are synonyms for the get_stdout() and - * get_stderr() calls inherited from child, respectively. - */ - pistream &get_output(int desc) const - { - if (desc == STDOUT_FILENO) - return posix_child::get_stdout(); - else if (desc == STDERR_FILENO) - return posix_child::get_stderr(); - else - { - output_map_t::const_iterator it = output_map_.find(desc); - BOOST_ASSERT(it != output_map_.end()); - return *it->second; - } - } - - /** - * Constructs a new POSIX child object representing a just - * spawned child process. - * - * Creates a new child object that represents the just spawned process - * \a id. - * - * The \a infoin and \a infoout maps contain the pipes used to handle - * the redirections of the child process; at the moment, no other - * stream_info types are supported. If the launcher was asked to - * redirect any of the three standard flows, their pipes must be - * present in these maps. - */ - posix_child(id_type id, detail::info_map &infoin, detail::info_map &infoout) - : child(id, - detail::posix_info_locate_pipe(infoin, STDIN_FILENO, false), - detail::posix_info_locate_pipe(infoout, STDOUT_FILENO, true), - detail::posix_info_locate_pipe(infoout, STDERR_FILENO, true)) - { - for (detail::info_map::iterator it = infoin.begin(); it != infoin.end(); ++it) - { - detail::stream_info &si = it->second; - if (si.type_ == detail::stream_info::use_pipe) - { - BOOST_ASSERT(si.pipe_->wend().valid()); - boost::shared_ptr st(new postream(si.pipe_->wend())); - input_map_.insert(input_map_t::value_type(it->first, st)); - } - } - - for (detail::info_map::iterator it = infoout.begin(); it != infoout.end(); ++it) - { - detail::stream_info &si = it->second; - if (si.type_ == detail::stream_info::use_pipe) - { - BOOST_ASSERT(si.pipe_->rend().valid()); - boost::shared_ptr st(new pistream(si.pipe_->rend())); - output_map_.insert(output_map_t::value_type(it->first, st)); - } - } - } - -private: - /** - * Maps child's file descriptors to postream objects. - */ - typedef std::map > input_map_t; - - /** - * Contains all relationships between child's input file - * descriptors and their corresponding postream objects. - */ - input_map_t input_map_; - - /** - * Maps child's file descriptors to pistream objects. - */ - typedef std::map > output_map_t; - - /** - * Contains all relationships between child's output file - * descriptors and their corresponding pistream objects. - */ - output_map_t output_map_; -}; - -} -} - -#endif diff --git a/boost/process/posix_context.hpp b/boost/process/posix_context.hpp deleted file mode 100644 index 3ca4cf49f..000000000 --- a/boost/process/posix_context.hpp +++ /dev/null @@ -1,118 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008, 2009 Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/posix_context.hpp - * - * Includes the declaration of the posix_context class. - */ - -#ifndef BOOST_PROCESS_POSIX_CONTEXT_HPP -#define BOOST_PROCESS_POSIX_CONTEXT_HPP - -#include -#include -#include -#include -#include - -namespace boost { -namespace process { - -/** - * Holds a mapping between native file descriptors and their corresponding - * pipes to set up communication between the parent and the %child process. - */ -typedef std::map behavior_map; - -template -class posix_basic_context : public basic_work_directory_context, public environment_context -{ -public: - /** - * Constructs a new POSIX-specific context. - * - * Constructs a new context. It is configured as follows: - * * All communcation channels with the child process are closed. - * * There are no channel mergings. - * * The initial work directory of the child processes is set to the - * current working directory. - * * The environment variables table is empty. - * * The credentials are the same as those of the current process. - */ - posix_basic_context() - : uid(::getuid()), - euid(::geteuid()), - gid(::getgid()), - egid(::getegid()) - { - } - - /** - * List of input streams that will be redirected. - */ - behavior_map input_behavior; - - /** - * List of output streams that will be redirected. - */ - behavior_map output_behavior; - - /** - * The user credentials. - * - * UID that specifies the user credentials to use to run the %child - * process. Defaults to the current UID. - */ - uid_t uid; - - /** - * The effective user credentials. - * - * EUID that specifies the effective user credentials to use to run - * the %child process. Defaults to the current EUID. - */ - uid_t euid; - - /** - * The group credentials. - * - * GID that specifies the group credentials to use to run the %child - * process. Defaults to the current GID. - */ - gid_t gid; - - /** - * The effective group credentials. - * - * EGID that specifies the effective group credentials to use to run - * the %child process. Defaults to the current EGID. - */ - gid_t egid; - - /** - * The chroot directory, if any. - * - * Specifies the directory in which the %child process is chrooted - * before execution. Empty if this feature is not desired. - */ - Path chroot; -}; - -/** - * Default instantiation of posix_basic_context. - */ -typedef posix_basic_context posix_context; - -} -} - -#endif diff --git a/boost/process/posix_operations.hpp b/boost/process/posix_operations.hpp deleted file mode 100644 index 78de54a91..000000000 --- a/boost/process/posix_operations.hpp +++ /dev/null @@ -1,81 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008, 2009 Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/posix_operations.hpp - * - * Provides miscellaneous free functions specific to POSIX operating - * systems. - */ - -#ifndef BOOST_PROCESS_POSIX_OPERATIONS_HPP -#define BOOST_PROCESS_POSIX_OPERATIONS_HPP - -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace process { - -/** - * Starts a new child process. - * - * Given an executable and the set of arguments passed to it, starts - * a new process with all the parameters configured in the context. - * The context can be reused afterwards to launch other different - * processes. - * - * \return A handle to the new child process. - */ -template -inline posix_child posix_launch(const Executable &exe, const Arguments &args, const Posix_Context &ctx) -{ - detail::info_map input_info; - for (behavior_map::const_iterator it = ctx.input_behavior.begin(); it != ctx.input_behavior.end(); ++it) - { - if (it->second.get_type() != stream_behavior::close) - { - detail::stream_info si = detail::stream_info(it->second, false); - input_info.insert(detail::info_map::value_type(it->first, si)); - } - } - - detail::info_map output_info; - for (behavior_map::const_iterator it = ctx.output_behavior.begin(); it != ctx.output_behavior.end(); ++it) - { - if (it->second.get_type() != stream_behavior::close) - { - detail::stream_info si = detail::stream_info(it->second, true); - output_info.insert(detail::info_map::value_type(it->first, si)); - } - } - - detail::posix_setup s; - s.work_directory = ctx.work_directory; - s.uid = ctx.uid; - s.euid = ctx.euid; - s.gid = ctx.gid; - s.egid = ctx.egid; - s.chroot = ctx.chroot; - - pid_t pid = detail::posix_start(exe, args, ctx.environment, input_info, output_info, s); - - return posix_child(pid, input_info, output_info); -} - -} -} - -#endif diff --git a/boost/process/posix_status.hpp b/boost/process/posix_status.hpp deleted file mode 100644 index eefb144eb..000000000 --- a/boost/process/posix_status.hpp +++ /dev/null @@ -1,128 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008, 2009 Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/posix_status.hpp - * - * Includes the declaration of the posix_status class. - */ - -#ifndef BOOST_PROCESS_POSIX_STATUS_HPP -#define BOOST_PROCESS_POSIX_STATUS_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -#elif defined(BOOST_WINDOWS_API) -#else -# error "Unsupported platform." -#endif - -#include -#include - -namespace boost { -namespace process { - -/** - * Status returned by a finalized %child process on a POSIX system. - * - * This class represents the %status returned by a child process after it - * has terminated. It contains some methods not available in the status - * class that provide information only available in POSIX systems. - */ -class posix_status : public status -{ -public: - /** - * Creates a posix_status object from an existing status object. - * - * Creates a new status object representing the exit status of a - * child process. The construction is done based on an existing - * status object which already contains all the available - * information: this class only provides controlled access to it. - */ - posix_status(const status &s) - : status(s) - { - } - - /** - * Returns whether the process exited due to an external - * signal. - */ - bool signaled() const - { - return WIFSIGNALED(flags_); - } - - /** - * If signaled, returns the terminating signal code. - * - * If the process was signaled, returns the terminating signal code. - * - * \pre signaled() is true. - */ - int term_signal() const - { - BOOST_ASSERT(signaled()); - - return WTERMSIG(flags_); - } - - /** - * If signaled, returns whether the process dumped core. - * - * If the process was signaled, returns whether the process - * produced a core dump. - * - * \pre signaled() is true. - */ - bool dumped_core() const - { - BOOST_ASSERT(signaled()); - -#ifdef WCOREDUMP - return WCOREDUMP(flags_); -#else - return false; -#endif - } - - /** - * Returns whether the process was stopped by an external - * signal. - */ - bool stopped() const - { - return WIFSTOPPED(flags_); - } - - /** - * If stopped, returns the stop signal code. - * - * If the process was stopped, returns the stop signal code. - * - * \pre stopped() is true. - */ - int stop_signal() const - { - BOOST_ASSERT(stopped()); - - return WSTOPSIG(flags_); - } -}; - -} -} - -#endif diff --git a/boost/process/postream.hpp b/boost/process/postream.hpp deleted file mode 100644 index 3bb894377..000000000 --- a/boost/process/postream.hpp +++ /dev/null @@ -1,117 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008, 2009 Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/postream.hpp - * - * Includes the declaration of the postream class. - */ - -#ifndef BOOST_PROCESS_POSTREAM_HPP -#define BOOST_PROCESS_POSTREAM_HPP - -#include -#include -#include -#include - -namespace boost { -namespace process { - -/** - * Child process' input stream. - * - * The postream class represents an input communication channel with the - * child process. The child process reads data from this stream and the - * parent process can write to it through the postream object. In other - * words, from the child's point of view, the communication channel is an - * input one, but from the parent's point of view it is an output one; - * hence the confusing postream name. - * - * postream objects cannot be copied because they own the file handle - * they use to communicate with the child and because they buffer data - * that flows through the communication channel. - * - * A postream object behaves as a std::ostream stream in all senses. - * The class is only provided because it must provide a method to let - * the caller explicitly close the communication channel. - * - * \remark Blocking remarks: Functions that write data to this - * stream can block if the associated file handle blocks during - * the write. As this class is used to communicate with child - * processes through anonymous pipes, the most typical blocking - * condition happens when the child is not processing the data - * in the pipe's system buffer. When this happens, the buffer - * eventually fills up and the system blocks until the reader - * consumes some data, leaving some new room. - */ -class postream : public std::ostream, public boost::noncopyable -{ -public: - /** - * Creates a new process' input stream. - * - * Given a file handle, this constructor creates a new postream - * object that owns the given file handle \a fh. Ownership of - * \a fh is transferred to the created postream object. - * - * \pre \a fh is valid. - * \post \a fh is invalid. - * \post The new postream object owns \a fh. - */ - explicit postream(detail::file_handle &fh) - : std::ostream(0), - handle_(fh), - systembuf_(handle_.get()) - { - rdbuf(&systembuf_); - } - - /** - * Returns the file handle managed by this stream. - * - * The file handle must not be copied. Copying invalidates - * the source file handle making the postream unusable. - */ - detail::file_handle &handle() - { - return handle_; - } - - /** - * Closes the file handle managed by this stream. - * - * Explicitly closes the file handle managed by this stream. This - * function can be used by the user to tell the child process there - * is no more data to send. - */ - void close() - { - systembuf_.sync(); - handle_.close(); - } - -private: - /** - * The file handle managed by this stream. - */ - detail::file_handle handle_; - - /** - * The systembuf object used to manage this stream's data. - */ - detail::systembuf systembuf_; -}; - -} -} - -#endif diff --git a/boost/process/process.hpp b/boost/process/process.hpp deleted file mode 100644 index 4a4825d25..000000000 --- a/boost/process/process.hpp +++ /dev/null @@ -1,130 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008, 2009 Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/process.hpp - * - * Includes the declaration of the process class. - */ - -#ifndef BOOST_PROCESS_PROCESS_HPP -#define BOOST_PROCESS_PROCESS_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -# include -#elif defined(BOOST_WINDOWS_API) -# include -# include -#else -# error "Unsupported platform." -#endif - -#include -#include - -namespace boost { -namespace process { - -/** - * Generic implementation of the Process concept. - * - * The process class implements the Process concept in an operating system - * agnostic way. - */ -class process -{ -public: -#if defined(BOOST_PROCESS_DOXYGEN) - /** - * Opaque name for the native process' identifier type. - * - * Each operating system identifies processes using a specific type. - * The \a id_type type is used to transparently refer to a process - * regardless of the operating system in which this class is used. - * - * This type is guaranteed to be an integral type on all supported - * platforms. - */ - typedef NativeProcessId id_type; -#elif defined(BOOST_POSIX_API) - typedef pid_t id_type; -#elif defined(BOOST_WINDOWS_API) - typedef DWORD id_type; -#endif - - /** - * Constructs a new process object. - * - * Creates a new process object that represents a running process - * within the system. - */ - process(id_type id) - : id_(id) - { - } - - /** - * Returns the process' identifier. - */ - id_type get_id() const - { - return id_; - } - - /** - * Terminates the process execution. - * - * Forces the termination of the process execution. Some platforms - * allow processes to ignore some external termination notifications - * or to capture them for a proper exit cleanup. You can set the - * \a force flag to true in them to force their termination regardless - * of any exit handler. - * - * After this call, accessing this object can be dangerous because the - * process identifier may have been reused by a different process. It - * might still be valid, though, if the process has refused to die. - * - * \throw boost::system::system_error If the system call used to - * terminate the process fails. - */ - void terminate(bool force = false) const - { -#if defined(BOOST_POSIX_API) - if (::kill(id_, force ? SIGKILL : SIGTERM) == -1) - boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::process::terminate: kill(2) failed")); -#elif defined(BOOST_WINDOWS_API) - HANDLE h = ::OpenProcess(PROCESS_TERMINATE, FALSE, id_); - if (h == NULL) - boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::process::terminate: OpenProcess failed")); - if (!::TerminateProcess(h, EXIT_FAILURE)) - { - ::CloseHandle(h); - boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::process::terminate: TerminateProcess failed")); - } - if (!::CloseHandle(h)) - boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::process::terminate: CloseHandle failed")); -#endif - } - -private: - /** - * The process' identifier. - */ - id_type id_; -}; - -} -} - -#endif diff --git a/boost/process/self.hpp b/boost/process/self.hpp deleted file mode 100644 index 8a5e85437..000000000 --- a/boost/process/self.hpp +++ /dev/null @@ -1,134 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008, 2009 Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/self.hpp - * - * Includes the declaration of the self class. - */ - -#ifndef BOOST_PROCESS_SELF_HPP -#define BOOST_PROCESS_SELF_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -#elif defined(BOOST_WINDOWS_API) -# include -#else -# error "Unsupported platform." -#endif - -#include -#include -#include -#include -#include -#include - -#if defined(BOOST_POSIX_API) -extern "C" -{ - extern char **environ; -} -#endif - -namespace boost { -namespace process { - -/** - * Generic implementation of the Process concept. - * - * The self singleton provides access to the current process. - */ -class self : public process, boost::noncopyable -{ -public: - /** - * Returns the self instance representing the caller's process. - */ - static self &get_instance() - { - static self *instance = 0; - if (!instance) - instance = new self; - return *instance; - } - - /** - * Returns the current environment. - * - * Returns the current process' environment variables. Modifying the - * returned object has no effect on the current environment. - */ - static environment get_environment() - { - environment e; - -#if defined(BOOST_POSIX_API) - char **env = ::environ; - while (*env) - { - std::string s = *env; - std::string::size_type pos = s.find('='); - e.insert(boost::process::environment::value_type(s.substr(0, pos), s.substr(pos + 1))); - ++env; - } -#elif defined(BOOST_WINDOWS_API) -#ifdef GetEnvironmentStrings -#undef GetEnvironmentStrings -#endif - char *environ = ::GetEnvironmentStrings(); - if (!environ) - boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::self::get_environment: GetEnvironmentStrings failed")); - try - { - char *env = environ; - while (*env) - { - std::string s = env; - std::string::size_type pos = s.find('='); - e.insert(boost::process::environment::value_type(s.substr(0, pos), s.substr(pos + 1))); - env += s.size() + 1; - } - } - catch (...) - { - ::FreeEnvironmentStringsA(environ); - throw; - } - ::FreeEnvironmentStringsA(environ); -#endif - - return e; - } - -private: - /** - * Constructs a new self object. - * - * Creates a new self object that represents the current process. - */ - self() : -#if defined(BOOST_POSIX_API) - process(::getpid()) -#elif defined(BOOST_WINDOWS_API) - process(::GetCurrentProcessId()) -#endif - { - } -}; - -} -} - -#endif diff --git a/boost/process/status.hpp b/boost/process/status.hpp deleted file mode 100644 index 533757a3c..000000000 --- a/boost/process/status.hpp +++ /dev/null @@ -1,105 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008, 2009 Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/status.hpp - * - * Includes the declaration of the status class. - */ - -#ifndef BOOST_PROCESS_STATUS_HPP -#define BOOST_PROCESS_STATUS_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -#elif defined(BOOST_WINDOWS_API) -#else -# error "Unsupported platform." -#endif - -#include - -namespace boost { -namespace process { - -class child; - -/** - * Status returned by a finalized %child process. - * - * This class represents the %status returned by a child process after it - * has terminated. It only provides that information available under all - * supported platforms. - * - * \see posix_status - */ -class status -{ - friend class child; - -public: - /** - * Returns whether the process exited gracefully or not. - */ - bool exited() const - { -#if defined(BOOST_POSIX_API) - return WIFEXITED(flags_); -#elif defined(BOOST_WINDOWS_API) - return true; -#endif - } - - /** - * If exited, returns the exit code. - * - * If the process exited, returns the exit code it returned. - * - * \pre exited() is true. - */ - int exit_status() const - { - BOOST_ASSERT(exited()); -#if defined(BOOST_POSIX_API) - return WEXITSTATUS(flags_); -#elif defined(BOOST_WINDOWS_API) - return flags_; -#endif - } - -protected: - /** - * Creates a status object based on exit information. - * - * Creates a new status object representing the exit status of a - * child process. - * - * \param flags In a POSIX system this parameter contains the - * flags returned by the ::waitpid() call. In a - * Windows system it contains the exit code only. - */ - status(int flags) - : flags_(flags) - { - } - - /** - * OS-specific codification of exit status. - */ - int flags_; -}; - -} -} - -#endif diff --git a/boost/process/stream_behavior.hpp b/boost/process/stream_behavior.hpp deleted file mode 100644 index 0681a7424..000000000 --- a/boost/process/stream_behavior.hpp +++ /dev/null @@ -1,234 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008, 2009 Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/stream_behavior.hpp - * - * Includes the declaration of the stream_behavior class and associated - * free functions. - */ - -#ifndef BOOST_PROCESS_STREAM_BEHAVIOR_HPP -#define BOOST_PROCESS_STREAM_BEHAVIOR_HPP - -#include - -namespace boost { -namespace process { - -namespace detail { - struct stream_info; -} - -/** - * Describes the possible states for a communication stream. - */ -class stream_behavior -{ -public: - friend struct detail::stream_info; - friend stream_behavior capture_stream(); - friend stream_behavior close_stream(); - friend stream_behavior inherit_stream(); - friend stream_behavior redirect_stream_to_stdout(); - friend stream_behavior silence_stream(); -#if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN) - friend stream_behavior posix_redirect_stream(int to); -#endif - - /** - * Describes the possible states for a communication stream. - */ - enum type - { - /** - * The child's stream is connected to the parent by using an - * anonymous pipe so that they can send and receive data to/from - * each other. - */ - capture, - - /** - * The child's stream is closed upon startup so that it will not - * have any access to it. - */ - close, - - /** - * The child's stream is connected to the same stream used by the - * parent. In other words, the corresponding parent's stream is - * inherited. - */ - inherit, - - /** - * The child's stream is connected to child's standard output. - * This is typically used when configuring the standard error - * stream. - */ - redirect_to_stdout, - - /** - * The child's stream is redirected to a null device so that its - * input is always zero or its output is lost, depending on - * whether the stream is an input or an output one. It is - * important to notice that this is different from close because - * the child is still able to write data. If we closed, e.g. - * stdout, the child might not work at all! - */ - silence, - -#if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN) - /** - * The child redirects the stream's output to the provided file - * descriptor. This is a generalization of the portable - * redirect_to_stdout behavior. - */ - posix_redirect -#endif - }; - - /** - * Constructs a new stream behavior of type close. - * - * The public constructor creates a new stream behavior that defaults - * to the close behavior. In general, you will want to use the - * available free functions to construct a stream behavior (including - * the close one). - */ - stream_behavior() - : type_(stream_behavior::close) - { - } - - /** - * Returns this stream's behavior type. - */ - type get_type() const - { - return type_; - } - -private: - /** - * Constructs a new stream behavior of type \a t. - * - * Constructs a new stream behavior of type \a t. It is the - * responsibility of the caller to fill in any other attributes - * required by the specified type, if any. - */ - stream_behavior(type t) - : type_(t) - { - } - - /** - * This stream's behavior type. - */ - type type_; - -#if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN) - /** - * File descriptor the stream is redirected to. - */ - int desc_to_; -#endif -}; - -/** - * Creates a new stream_behavior of type stream_behavior::capture. - * - * Creates a new stream_behavior of type stream_behavior::capture, - * meaning that the child's stream is connected to the parent by using an - * anonymous pipe so that they can send and receive data to/from each - * other. - */ -inline stream_behavior capture_stream() -{ - return stream_behavior(stream_behavior::capture); -} - -/** - * Creates a new stream_behavior of type stream_behavior::close. - * - * Creates a new stream_behavior of type stream_behavior::close, - * meaning that the child's stream is closed upon startup so that it - * will not have any access to it. - */ -inline stream_behavior close_stream() -{ - return stream_behavior(stream_behavior::close); -} - -/** - * Creates a new stream_behavior of type stream_behavior::inherit. - * - * Creates a new stream_behavior of type stream_behavior::inherit, - * meaning that the child's stream is connected to the same stream used - * by the parent. In other words, the corresponding parent's stream is - * inherited. - */ -inline stream_behavior inherit_stream() -{ - return stream_behavior(stream_behavior::inherit); -} - -/** - * Creates a new stream_behavior of type - * stream_behavior::redirect_to_stdout. - * - * Creates a new stream_behavior of type - * stream_behavior::redirect_to_stdout, meaning that the child's stream is - * connected to child's standard output. This is typically used when - * configuring the standard error stream. - */ -inline stream_behavior redirect_stream_to_stdout() -{ - return stream_behavior(stream_behavior::redirect_to_stdout); -} - -/** - * Creates a new stream_behavior of type stream_behavior::silence. - * - * Creates a new stream_behavior of type stream_behavior::silence, - * meaning that the child's stream is redirected to a null device so that - * its input is always zero or its output is lost, depending on whether - * the stream is an input or an output one. It is important to notice - * that this is different from close because the child is still able to - * write data. If we closed, e.g. stdout, the child might not work at - * all! - */ -inline stream_behavior silence_stream() -{ - return stream_behavior(stream_behavior::silence); -} - -#if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN) -/** - * Creates a new stream_behavior of type stream_behavior::posix_redirect. - * - * Creates a new stream_behavior of type stream_behavior::posix_redirect, - * meaning that the child's stream is redirected to the \a to child's - * file descriptor. This is a generalization of the portable - * redirect_stream_to_stdout() behavior. - */ -inline stream_behavior posix_redirect_stream(int to) -{ - stream_behavior sb(stream_behavior::posix_redirect); - sb.desc_to_ = to; - return sb; -} -#endif - -} -} - -#endif diff --git a/boost/process/win32_child.hpp b/boost/process/win32_child.hpp deleted file mode 100644 index e4f0ed7e3..000000000 --- a/boost/process/win32_child.hpp +++ /dev/null @@ -1,128 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008, 2009 Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/win32_child.hpp - * - * Includes the declaration of the win32_child class. - */ - -#ifndef BOOST_PROCESS_WIN32_CHILD_HPP -#define BOOST_PROCESS_WIN32_CHILD_HPP - -#include -#include -#include - -namespace boost { -namespace process { - -/** - * Windows implementation of the Child concept. - * - * The win32_child class implements the Child concept in a Windows - * operating system. - * - * A Windows child differs from a regular %child (represented by a - * child object) in that it holds additional information about a process. - * Aside from the standard handle, it also includes a handle to the - * process' main thread, together with identifiers to both entities. - * - * This class is built on top of the generic child so as to allow its - * trivial adoption. When a program is changed to use the - * Windows-specific context (win32_context), it will most certainly need - * to migrate its use of the child class to win32_child. Doing so is only - * a matter of redefining the appropriate object and later using the - * required extra features: there should be no need to modify the existing - * code (e.g. method calls) in any other way. - */ -class win32_child : public child -{ -public: - /** - * Constructs a new Windows child object representing a just - * spawned %child process. - * - * Creates a new %child object that represents the process described by - * the \a pi structure. - * - * The \a fhstdin, \a fhstdout and \a fhstderr parameters hold the - * communication streams used to interact with the %child process if - * the launcher configured redirections. See the parent class' - * constructor for more details on these. - * - * \see child - */ - win32_child(const PROCESS_INFORMATION &pi, detail::file_handle fhstdin, detail::file_handle fhstdout, detail::file_handle fhstderr) - : child(pi.dwProcessId, fhstdin, fhstdout, fhstderr, pi.hProcess), - process_information_(pi), - thread_handle_(process_information_.hThread) - { - } - - /** - * Returns the process handle. - * - * Returns a process-specific handle that can be used to access the - * process. This is the value of the \a hProcess field in the - * PROCESS_INFORMATION structure returned by CreateProcess(). - * - * \see get_id() - */ - HANDLE get_handle() const - { - return process_information_.hProcess; - } - - /** - * Returns the primary thread's handle. - * - * Returns a handle to the primary thread of the new process. This is - * the value of the \a hThread field in the PROCESS_INFORMATION - * structure returned by CreateProcess(). - * - * \see get_primary_thread_id() - */ - HANDLE get_primary_thread_handle() const - { - return process_information_.hThread; - } - - /** - * Returns the primary thread's identifier. - * - * Returns a system-wide value that identifies the process's primary - * thread. This is the value of the \a dwThreadId field in the - * PROCESS_INFORMATION structure returned by CreateProcess(). - * - * \see get_primary_thread_handle() - */ - DWORD get_primary_thread_id() const - { - return process_information_.dwThreadId; - } - -private: - /** - * Windows-specific process information. - */ - PROCESS_INFORMATION process_information_; - - /** - * Thread handle owned by RAII object. - */ - detail::file_handle thread_handle_; -}; - -} -} - -#endif diff --git a/boost/process/win32_context.hpp b/boost/process/win32_context.hpp deleted file mode 100644 index 630fd305f..000000000 --- a/boost/process/win32_context.hpp +++ /dev/null @@ -1,61 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008, 2009 Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/win_32context.hpp - * - * Includes the declaration of the win32_context class. - */ - -#ifndef BOOST_PROCESS_WIN32_CONTEXT_HPP -#define BOOST_PROCESS_WIN32_CONTEXT_HPP - -#include -#include -#include - -namespace boost { -namespace process { - -/** - * Generic implementation of the Context concept. - * - * The context class implements the Context concept in an operating - * system agnostic way; it allows spawning new child processes using - * a single and common interface across different systems. - */ -template -class win32_basic_context : public basic_context -{ -public: - /** - * Initializes the Win32-specific process startup information with NULL. - */ - win32_basic_context() - : startupinfo(NULL) - { - } - - /** - * Win32-specific process startup information. - */ - STARTUPINFOA *startupinfo; -}; - -/** - * Default instantiation of win32_basic_context. - */ -typedef win32_basic_context win32_context; - -} -} - -#endif diff --git a/boost/process/win32_operations.hpp b/boost/process/win32_operations.hpp deleted file mode 100644 index 092e9a368..000000000 --- a/boost/process/win32_operations.hpp +++ /dev/null @@ -1,77 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008, 2009 Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/win32_operations.hpp - * - * Provides miscellaneous free functions specific to Windows operating - * systems. - */ - -#ifndef BOOST_PROCESS_WIN32_OPERATIONS_HPP -#define BOOST_PROCESS_WIN32_OPERATIONS_HPP - -#include -#include -#include -#include -#include - -namespace boost { -namespace process { - -/** - * Starts a new child process. - * - * Given an executable and the set of arguments passed to it, starts - * a new process with all the parameters configured in the context. - * The context can be reused afterwards to launch other different - * processes. - * - * \return A handle to the new child process. - */ -template -inline win32_child win32_launch(const Executable &exe, const Arguments &args, const Win32_Context &ctx) -{ - detail::file_handle fhstdin, fhstdout, fhstderr; - - detail::stream_info behin = detail::stream_info(ctx.stdin_behavior, false); - if (behin.type_ == detail::stream_info::use_pipe) - fhstdin = behin.pipe_->wend(); - detail::stream_info behout = detail::stream_info(ctx.stdout_behavior, true); - if (behout.type_ == detail::stream_info::use_pipe) - fhstdout = behout.pipe_->rend(); - detail::stream_info beherr = detail::stream_info(ctx.stderr_behavior, true); - if (beherr.type_ == detail::stream_info::use_pipe) - fhstderr = beherr.pipe_->rend(); - - detail::win32_setup s; - s.work_directory = ctx.work_directory; - - STARTUPINFOA si; - if (!ctx.startupinfo) - { - ::ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - s.startupinfo = &si; - } - else - s.startupinfo = ctx.startupinfo; - - PROCESS_INFORMATION pi = detail::win32_start(exe, args, ctx.environment, behin, behout, beherr, s); - - return win32_child(pi, fhstdin, fhstdout, fhstderr); -} - -} -} - -#endif diff --git a/doc/Doxyfile b/doc/Doxyfile new file mode 100644 index 000000000..71ca04136 --- /dev/null +++ b/doc/Doxyfile @@ -0,0 +1,2364 @@ +# Doxyfile 1.8.6 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = Ethereum + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = PoC-8 + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = "The C++ Implementation of Ethereum" + +# With the PROJECT_LOGO tag one can specify an logo or icon that is included in +# the documentation. The maximum height of the logo should not exceed 55 pixels +# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo +# to the output directory. + +PROJECT_LOGO = gavcoin.png + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = . + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a +# new page for each member. If set to NO, the documentation of a member will be +# part of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. +# +# Note For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by by putting a % sign in front of the word +# or globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO these classes will be included in the various overviews. This option has +# no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the +# todo list. This list is created by putting \todo commands in the +# documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the +# test list. This list is created by putting \test commands in the +# documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES the list +# will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. Do not use file names with spaces, bibtex cannot handle them. See +# also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO doxygen will only warn about wrong or incomplete parameter +# documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. +# Note: If this tag is empty the current directory is searched. + +INPUT = ../libdevcore \ + ../libdevcrypto \ + ../libethcore \ + ../libethereum \ + ../libevmface \ + ../libevm \ + ../liblll \ + ../libsolidity \ + ../mix \ + ../libwhisper \ + ../libwebthree + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank the +# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, +# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, +# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, +# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, +# *.qsf, *.as and *.js. + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.idl \ + *.ddl \ + *.odl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.cs \ + *.d \ + *.php \ + *.php4 \ + *.php5 \ + *.phtml \ + *.inc \ + *.m \ + *.markdown \ + *.md \ + *.mm \ + *.dox \ + *.py \ + *.f90 \ + *.f \ + *.for \ + *.tcl \ + *.vhd \ + *.vhdl \ + *.ucf \ + *.qsf \ + *.as \ + *.js + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER ) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES, then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- +# defined cascading style sheet that is included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefor more robust against future updates. +# Doxygen will copy the style sheet file to the output directory. For an example +# see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the stylesheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler ( hhc.exe). If non-empty +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated ( +# YES) or that it should be included in the master .chm file ( NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated ( +# YES) or a normal table of contents ( NO) in the .chm file. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = YES + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using prerendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /