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 "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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -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…
Reference in a new issue