From f124be65b7774d3945288281c8a1b3f98010183d 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] 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 ++-- 5 files changed, 81 insertions(+), 13 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 6ef70d4fea..fa3349ea29 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 6801a89d4a..ae7033ac0d 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 2fe56f3731..e59d6024a8 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 e0c2693fa9..1bdf8c5647 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 a7ed341a0d..bdc3681db3 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; }