Browse Source

Do not compile LLVM module if machine code available in memory

cl-refactor
Paweł Bylica 10 years ago
parent
commit
3df5a125fa
  1. 5
      evmcc/evmcc.cpp
  2. 11
      libevmjit/Compiler.cpp
  3. 2
      libevmjit/Compiler.h
  4. 34
      libevmjit/ExecutionEngine.cpp
  5. 7
      libevmjit/ExecutionEngine.h

5
evmcc/evmcc.cpp

@ -132,7 +132,7 @@ int main(int argc, char** argv)
compilerOptions.rewriteSwitchToBranches = optimize || options.count("rewrite-switch") > 0;
auto compiler = eth::jit::Compiler(compilerOptions);
auto module = compiler.compile(bytecode);
auto module = compiler.compile(bytecode, "main");
auto compilationEndTime = std::chrono::high_resolution_clock::now();
@ -201,7 +201,8 @@ int main(int argc, char** argv)
data.code = bytecode.data();
// BROKEN: env_* functions must be implemented & RuntimeData struct created
auto result = engine.run(std::move(module), &data, nullptr, bytecode);
// TODO: Do not compile module again
auto result = engine.run(bytecode, &data, nullptr);
return static_cast<int>(result);
}
}

11
libevmjit/Compiler.cpp

@ -152,19 +152,14 @@ void Compiler::createBasicBlocks(bytes const& _bytecode)
m_indirectJumpTargets.push_back(&basicBlocks.find(*it)->second);
}
std::unique_ptr<llvm::Module> Compiler::compile(bytes const& _bytecode)
std::unique_ptr<llvm::Module> Compiler::compile(bytes const& _bytecode, std::string const& _id)
{
// TODO: Better hash of code needed, probably SHA3
std::string code{reinterpret_cast<char const*>(_bytecode.data()), _bytecode.size()};
auto hash = std::hash<std::string>{}(code);
auto strHash = std::to_string(hash);
auto compilationStartTime = std::chrono::high_resolution_clock::now();
auto module = std::unique_ptr<llvm::Module>(new llvm::Module(strHash, m_builder.getContext()));
auto module = std::unique_ptr<llvm::Module>(new llvm::Module(_id, m_builder.getContext()));
// Create main function
auto mainFuncType = llvm::FunctionType::get(Type::MainReturn, Type::RuntimePtr, false);
m_mainFunc = llvm::Function::Create(mainFuncType, llvm::Function::ExternalLinkage, strHash, module.get());
m_mainFunc = llvm::Function::Create(mainFuncType, llvm::Function::ExternalLinkage, _id, module.get());
m_mainFunc->getArgumentList().front().setName("rt");
// Create the basic blocks.

2
libevmjit/Compiler.h

@ -39,7 +39,7 @@ public:
Compiler(Options const& _options);
std::unique_ptr<llvm::Module> compile(bytes const& _bytecode);
std::unique_ptr<llvm::Module> compile(bytes const& _bytecode, std::string const& _id);
private:

34
libevmjit/ExecutionEngine.cpp

@ -21,13 +21,6 @@ namespace eth
namespace jit
{
ReturnCode ExecutionEngine::run(bytes const& _code, RuntimeData* _data, Env* _env)
{
auto module = Compiler({}).compile(_code);
//module->dump();
return run(std::move(module), _data, _env, _code);
}
namespace
{
typedef ReturnCode(*EntryFuncPtr)(Runtime*);
@ -48,20 +41,31 @@ ReturnCode runEntryFunc(EntryFuncPtr _mainFunc, Runtime* _runtime)
}
}
ReturnCode ExecutionEngine::run(std::unique_ptr<llvm::Module> _module, RuntimeData* _data, Env* _env, bytes const& _code)
ReturnCode ExecutionEngine::run(bytes const& _code, RuntimeData* _data, Env* _env)
{
static std::unique_ptr<llvm::ExecutionEngine> ee; // TODO: Use Managed Objects from LLVM?
// TODO: Better hash of code needed, probably SHA3
std::string code{reinterpret_cast<char const*>(_code.data()), _code.size()};
auto hash = std::hash<std::string>{}(code);
auto mainFuncName = std::to_string(hash);
EntryFuncPtr entryFuncPtr{};
auto&& mainFuncName = _module->getModuleIdentifier();
Runtime runtime(_data, _env); // TODO: I don't know why but it must be created before getFunctionAddress() calls
if (ee && (entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName)))
{
}
else
{
auto module = Compiler({}).compile(_code, mainFuncName);
if (!ee)
{
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
llvm::EngineBuilder builder(_module.get());
llvm::EngineBuilder builder(module.get());
builder.setEngineKind(llvm::EngineKind::JIT);
builder.setUseMCJIT(true);
std::unique_ptr<llvm::SectionMemoryManager> memoryManager(new llvm::SectionMemoryManager);
@ -71,13 +75,13 @@ ReturnCode ExecutionEngine::run(std::unique_ptr<llvm::Module> _module, RuntimeDa
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());
module->setTargetTriple(triple.str());
ee.reset(builder.create());
if (!ee)
return ReturnCode::LLVMConfigError;
_module.release(); // Successfully created llvm::ExecutionEngine takes ownership of the module
module.release(); // Successfully created llvm::ExecutionEngine takes ownership of the module
memoryManager.release(); // and memory manager
//ee->setObjectCache(Cache::getObjectCache());
@ -85,14 +89,14 @@ ReturnCode ExecutionEngine::run(std::unique_ptr<llvm::Module> _module, RuntimeDa
}
else
{
entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName);
if (!entryFuncPtr)
{
ee->addModule(_module.get());
_module.release();
ee->addModule(module.get());
module.release();
entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName);
}
}
}
assert(entryFuncPtr);
auto executionStartTime = std::chrono::high_resolution_clock::now();

7
libevmjit/ExecutionEngine.h

@ -1,10 +1,5 @@
#pragma once
namespace llvm
{
class Module;
}
#include "RuntimeData.h"
namespace dev
@ -13,7 +8,6 @@ namespace eth
{
namespace jit
{
class ExecBundle;
class ExecutionEngine
{
@ -23,7 +17,6 @@ public:
void operator=(ExecutionEngine) = delete;
ReturnCode run(bytes const& _code, RuntimeData* _data, Env* _env);
ReturnCode run(std::unique_ptr<llvm::Module> module, RuntimeData* _data, Env* _env, bytes const& _code);
bytes returnData;
};

Loading…
Cancel
Save