mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-19 19:30:44 +00:00
Implementation of ExecutionEngine with LLVM MCJIT
This commit is contained in:
parent
e33fdeab21
commit
f124be65b7
5 changed files with 81 additions and 13 deletions
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -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…
Reference in a new issue