From f5eda1f1b32e97f62b5f80b38fe974ccaf4c5a0b 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] Moving Compiler to separated files --- evmcc/CMakeLists.txt | 49 ++++++++++++++++++++++ evmcc/Compiler.cpp | 75 +++++++++++++++++++++++++++++++++ evmcc/Compiler.h | 34 +++++++++++++++ evmcc/bytecode/kv.evm | 1 + evmcc/evmcc.cpp | 98 +++++++++++++++++++++++++++++++++++++++++++ evmcc/lll/kv.lll | 10 +++++ 6 files changed, 267 insertions(+) create mode 100644 evmcc/CMakeLists.txt create mode 100644 evmcc/Compiler.cpp create mode 100644 evmcc/Compiler.h create mode 100644 evmcc/bytecode/kv.evm create mode 100644 evmcc/evmcc.cpp create mode 100644 evmcc/lll/kv.lll diff --git a/evmcc/CMakeLists.txt b/evmcc/CMakeLists.txt new file mode 100644 index 000000000..550492583 --- /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(evmcc ${llvm_libs}) + +# end of LLVM specific commands + + + +install( TARGETS ${EXECUTABLE} DESTINATION bin ) + +cmake_policy(SET CMP0015 NEW) 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/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..fc0b03a99 --- /dev/null +++ b/evmcc/evmcc.cpp @@ -0,0 +1,98 @@ + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "Compiler.h" + +using namespace dev; + + +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) + { + evmcc::Compiler().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)) +}