Lang Hames bf6603e918 [ORC] Promote and rename private symbols inside the CompileOnDemand layer,
rather than require them to have been promoted before being passed in.

Dropping this precondition is better for layer composition (CompileOnDemandLayer
was the only one that placed pre-conditions on the modules that could be added).
It also means that the promoted private symbols do not show up in the target
JITDylib's symbol table. Instead, they are confined to the hidden implementation
dylib that contains the actual definitions.

For the 403.gcc testcase this cut down the public symbol table size from ~15,000
symbols to ~4000, substantially reducing symbol dependence tracking costs.

llvm-svn: 344078
2018-10-09 20:44:32 +00:00

217 lines
7.5 KiB
C++

//===--------- LLJIT.cpp - An ORC-based JIT for compiling LLVM IR ---------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#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
// IRCompileLayer2::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;
auto K = ES->allocateVModule();
return CompileLayer.add(JD, K, std::move(TSM));
}
Error LLJIT::addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj) {
assert(Obj && "Can not add null object");
auto K = ES->allocateVModule();
return ObjLinkingLayer.add(JD, K, std::move(Obj));
}
Expected<JITEvaluatedSymbol> LLJIT::lookupLinkerMangled(JITDylib &JD,
StringRef Name) {
return llvm::orc::lookup({&JD}, 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,
[this](VModuleKey K) { return getMemoryManager(K); }),
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,
[this](VModuleKey K) { return getMemoryManager(K); }),
CompileLayer(*this->ES, ObjLinkingLayer,
MultiThreadedSimpleCompiler(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::unique_ptr<RuntimeDyld::MemoryManager>
LLJIT::getMemoryManager(VModuleKey K) {
return llvm::make_unique<SectionMemoryManager>();
}
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,
unsigned NumCompileThreads) {
auto ES = llvm::make_unique<ExecutionSession>();
const Triple &TT = JTMB.getTargetTriple();
auto LCTMgr = createLocalLazyCallThroughManager(TT, *ES, 0);
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());
auto K = ES->allocateVModule();
return CODLayer.add(JD, K, std::move(TSM));
}
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.