Browse Source

Implementation of ExecutionEngine with LLVM MCJIT

cl-refactor
Paweł Bylica 11 years ago
parent
commit
f124be65b7
  1. 13
      evmcc/Compiler.cpp
  2. 4
      evmcc/Compiler.h
  3. 67
      evmcc/ExecutionEngine.cpp
  4. 4
      evmcc/ExecutionEngine.h
  5. 6
      evmcc/evmcc.cpp

13
evmcc/Compiler.cpp

@ -2,7 +2,6 @@
#include "Compiler.h" #include "Compiler.h"
#include <llvm/IR/IRBuilder.h> #include <llvm/IR/IRBuilder.h>
#include <llvm/IR/Module.h>
namespace evmcc namespace evmcc
{ {
@ -29,13 +28,13 @@ Compiler::Compiler()
} }
void Compiler::compile(const dev::bytes& bytecode) std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
{ {
using namespace llvm; using namespace llvm;
auto& context = getGlobalContext(); auto& context = getGlobalContext();
Module* module = new Module("main", context); auto module = std::make_unique<Module>("main", context);
IRBuilder<> builder(context); IRBuilder<> builder(context);
// Create globals for memory, memory size, stack and stack top // 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) // Create value for void* malloc(size_t)
std::vector<Type*> mallocArgTypes = { Types.size }; std::vector<Type*> mallocArgTypes = { Types.size };
Value* mallocVal = Function::Create(FunctionType::get(Types.word8ptr, mallocArgTypes, false), Value* mallocVal = Function::Create(FunctionType::get(Types.word8ptr, mallocArgTypes, false),
GlobalValue::LinkageTypes::ExternalLinkage, "malloc", module); GlobalValue::LinkageTypes::ExternalLinkage, "malloc", module.get());
// Create main function // Create main function
FunctionType* funcType = FunctionType::get(llvm::Type::getInt32Ty(context), false); 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); BasicBlock* entryBlock = BasicBlock::Create(context, "entry", mainFunc);
builder.SetInsertPoint(entryBlock); builder.SetInsertPoint(entryBlock);
@ -77,9 +76,9 @@ void Compiler::compile(const dev::bytes& bytecode)
builder.CreateStore(mallocCast, stackVal); builder.CreateStore(mallocCast, stackVal);
*/ */
builder.CreateRet(ConstantInt::get(Type::getInt32Ty(context), 0)); builder.CreateRet(ConstantInt::get(Type::getInt32Ty(context), 13));
module->dump(); return module;
} }
} }

4
evmcc/Compiler.h

@ -1,6 +1,8 @@
#pragma once #pragma once
#include <llvm/IR/Module.h>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
namespace evmcc namespace evmcc
@ -12,7 +14,7 @@ public:
Compiler(); Compiler();
void compile(const dev::bytes& bytecode); std::unique_ptr<llvm::Module> compile(const dev::bytes& bytecode);
}; };

67
evmcc/ExecutionEngine.cpp

@ -1,6 +1,18 @@
#include "ExecutionEngine.h" #include "ExecutionEngine.h"
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/ADT/Triple.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/ExecutionEngine/SectionMemoryManager.h>
#include <llvm/ExecutionEngine/GenericValue.h>
#include <llvm/ExecutionEngine/MCJIT.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Support/Signals.h>
#include <llvm/Support/PrettyStackTrace.h>
#include <llvm/Support/Host.h>
namespace evmcc namespace evmcc
{ {
@ -10,9 +22,60 @@ ExecutionEngine::ExecutionEngine()
} }
int ExecutionEngine::run(const dev::bytes& bytecode) int ExecutionEngine::run(std::unique_ptr<llvm::Module> _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<llvm::ExecutionEngine>(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;
} }
} }

4
evmcc/ExecutionEngine.h

@ -1,6 +1,8 @@
#pragma once #pragma once
#include <llvm/IR/Module.h>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
namespace evmcc namespace evmcc
@ -11,7 +13,7 @@ class ExecutionEngine
public: public:
ExecutionEngine(); ExecutionEngine();
int run(const dev::bytes& bytecode); int run(std::unique_ptr<llvm::Module> module);
}; };
} }

6
evmcc/evmcc.cpp

@ -87,13 +87,15 @@ int main(int argc, char** argv)
if (opt_compile) if (opt_compile)
{ {
evmcc::Compiler().compile(bytecode); evmcc::Compiler().compile(bytecode)->dump();
} }
if (opt_interpret) if (opt_interpret)
{ {
auto engine = evmcc::ExecutionEngine(); 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; return result;
} }

Loading…
Cancel
Save