Browse Source

Implementation of ExecutionEngine with LLVM MCJIT

cl-refactor
Paweł Bylica 10 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 <llvm/IR/IRBuilder.h>
#include <llvm/IR/Module.h>
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;
auto& context = getGlobalContext();
Module* module = new Module("main", context);
auto module = std::make_unique<Module>("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<Type*> 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;
}
}

4
evmcc/Compiler.h

@ -1,6 +1,8 @@
#pragma once
#include <llvm/IR/Module.h>
#include <libdevcore/Common.h>
namespace evmcc
@ -12,7 +14,7 @@ public:
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 <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
{
@ -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
#include <llvm/IR/Module.h>
#include <libdevcore/Common.h>
namespace evmcc
@ -11,7 +13,7 @@ class ExecutionEngine
public:
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)
{
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;
}

Loading…
Cancel
Save