llvm-project/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp

210 lines
7.4 KiB
C++

//===--------- LLJIT.cpp - An ORC-based JIT for compiling LLVM IR ---------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
#include "llvm/ExecutionEngine/Orc/OrcError.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/IR/Mangler.h"
namespace {
// A SimpleCompiler that owns its TargetMachine.
class TMOwningSimpleCompiler : public llvm::orc::SimpleCompiler {
public:
TMOwningSimpleCompiler(std::unique_ptr<llvm::TargetMachine> TM)
: llvm::orc::SimpleCompiler(*TM), TM(std::move(TM)) {}
private:
// FIXME: shared because std::functions (and thus
// IRCompileLayer::CompileFunction) are not moveable.
std::shared_ptr<llvm::TargetMachine> TM;
};
} // end anonymous namespace
namespace llvm {
namespace orc {
LLJIT::~LLJIT() {
if (CompileThreads)
CompileThreads->wait();
}
Expected<std::unique_ptr<LLJIT>>
LLJIT::Create(JITTargetMachineBuilder JTMB, DataLayout DL,
unsigned NumCompileThreads) {
if (NumCompileThreads == 0) {
// If NumCompileThreads == 0 then create a single-threaded LLJIT instance.
auto TM = JTMB.createTargetMachine();
if (!TM)
return TM.takeError();
return std::unique_ptr<LLJIT>(new LLJIT(llvm::make_unique<ExecutionSession>(),
std::move(*TM), std::move(DL)));
}
return std::unique_ptr<LLJIT>(new LLJIT(llvm::make_unique<ExecutionSession>(),
std::move(JTMB), std::move(DL),
NumCompileThreads));
}
Error LLJIT::defineAbsolute(StringRef Name, JITEvaluatedSymbol Sym) {
auto InternedName = ES->intern(Name);
SymbolMap Symbols({{InternedName, Sym}});
return Main.define(absoluteSymbols(std::move(Symbols)));
}
Error LLJIT::addIRModule(JITDylib &JD, ThreadSafeModule TSM) {
assert(TSM && "Can not add null module");
if (auto Err = applyDataLayout(*TSM.getModule()))
return Err;
return CompileLayer.add(JD, std::move(TSM), ES->allocateVModule());
}
Error LLJIT::addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj) {
assert(Obj && "Can not add null object");
return ObjLinkingLayer.add(JD, std::move(Obj), ES->allocateVModule());
}
Expected<JITEvaluatedSymbol> LLJIT::lookupLinkerMangled(JITDylib &JD,
StringRef Name) {
return ES->lookup(JITDylibSearchList({{&JD, true}}), ES->intern(Name));
}
LLJIT::LLJIT(std::unique_ptr<ExecutionSession> ES,
std::unique_ptr<TargetMachine> TM, DataLayout DL)
: ES(std::move(ES)), Main(this->ES->getMainJITDylib()), DL(std::move(DL)),
ObjLinkingLayer(
*this->ES,
[]() { return llvm::make_unique<SectionMemoryManager>(); }),
CompileLayer(*this->ES, ObjLinkingLayer,
TMOwningSimpleCompiler(std::move(TM))),
CtorRunner(Main), DtorRunner(Main) {}
LLJIT::LLJIT(std::unique_ptr<ExecutionSession> ES, JITTargetMachineBuilder JTMB,
DataLayout DL, unsigned NumCompileThreads)
: ES(std::move(ES)), Main(this->ES->getMainJITDylib()), DL(std::move(DL)),
ObjLinkingLayer(
*this->ES,
[]() { return llvm::make_unique<SectionMemoryManager>(); }),
CompileLayer(*this->ES, ObjLinkingLayer,
ConcurrentIRCompiler(std::move(JTMB))),
CtorRunner(Main), DtorRunner(Main) {
assert(NumCompileThreads != 0 &&
"Multithreaded LLJIT instance can not be created with 0 threads");
// Move modules to new contexts when they're emitted so that we can compile
// them in parallel.
CompileLayer.setCloneToNewContextOnEmit(true);
// Create a thread pool to compile on and set the execution session
// dispatcher to use the thread pool.
CompileThreads = llvm::make_unique<ThreadPool>(NumCompileThreads);
this->ES->setDispatchMaterialization(
[this](JITDylib &JD, std::unique_ptr<MaterializationUnit> MU) {
// FIXME: Switch to move capture once we have c++14.
auto SharedMU = std::shared_ptr<MaterializationUnit>(std::move(MU));
auto Work = [SharedMU, &JD]() { SharedMU->doMaterialize(JD); };
CompileThreads->async(std::move(Work));
});
}
std::string LLJIT::mangle(StringRef UnmangledName) {
std::string MangledName;
{
raw_string_ostream MangledNameStream(MangledName);
Mangler::getNameWithPrefix(MangledNameStream, UnmangledName, DL);
}
return MangledName;
}
Error LLJIT::applyDataLayout(Module &M) {
if (M.getDataLayout().isDefault())
M.setDataLayout(DL);
if (M.getDataLayout() != DL)
return make_error<StringError>(
"Added modules have incompatible data layouts",
inconvertibleErrorCode());
return Error::success();
}
void LLJIT::recordCtorDtors(Module &M) {
CtorRunner.add(getConstructors(M));
DtorRunner.add(getDestructors(M));
}
Expected<std::unique_ptr<LLLazyJIT>>
LLLazyJIT::Create(JITTargetMachineBuilder JTMB, DataLayout DL,
JITTargetAddress ErrorAddr, unsigned NumCompileThreads) {
auto ES = llvm::make_unique<ExecutionSession>();
const Triple &TT = JTMB.getTargetTriple();
auto LCTMgr = createLocalLazyCallThroughManager(TT, *ES, ErrorAddr);
if (!LCTMgr)
return LCTMgr.takeError();
auto ISMBuilder = createLocalIndirectStubsManagerBuilder(TT);
if (!ISMBuilder)
return make_error<StringError>(
std::string("No indirect stubs manager builder for ") + TT.str(),
inconvertibleErrorCode());
if (NumCompileThreads == 0) {
auto TM = JTMB.createTargetMachine();
if (!TM)
return TM.takeError();
return std::unique_ptr<LLLazyJIT>(
new LLLazyJIT(std::move(ES), std::move(*TM), std::move(DL),
std::move(*LCTMgr), std::move(ISMBuilder)));
}
return std::unique_ptr<LLLazyJIT>(new LLLazyJIT(
std::move(ES), std::move(JTMB), std::move(DL), NumCompileThreads,
std::move(*LCTMgr), std::move(ISMBuilder)));
}
Error LLLazyJIT::addLazyIRModule(JITDylib &JD, ThreadSafeModule TSM) {
assert(TSM && "Can not add null module");
if (auto Err = applyDataLayout(*TSM.getModule()))
return Err;
recordCtorDtors(*TSM.getModule());
return CODLayer.add(JD, std::move(TSM), ES->allocateVModule());
}
LLLazyJIT::LLLazyJIT(
std::unique_ptr<ExecutionSession> ES, std::unique_ptr<TargetMachine> TM,
DataLayout DL, std::unique_ptr<LazyCallThroughManager> LCTMgr,
std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder)
: LLJIT(std::move(ES), std::move(TM), std::move(DL)),
LCTMgr(std::move(LCTMgr)), TransformLayer(*this->ES, CompileLayer),
CODLayer(*this->ES, TransformLayer, *this->LCTMgr,
std::move(ISMBuilder)) {}
LLLazyJIT::LLLazyJIT(
std::unique_ptr<ExecutionSession> ES, JITTargetMachineBuilder JTMB,
DataLayout DL, unsigned NumCompileThreads,
std::unique_ptr<LazyCallThroughManager> LCTMgr,
std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder)
: LLJIT(std::move(ES), std::move(JTMB), std::move(DL), NumCompileThreads),
LCTMgr(std::move(LCTMgr)), TransformLayer(*this->ES, CompileLayer),
CODLayer(*this->ES, TransformLayer, *this->LCTMgr,
std::move(ISMBuilder)) {
CODLayer.setCloneToNewContextOnEmit(true);
}
} // End namespace orc.
} // End namespace llvm.