2018-06-27 05:35:48 +08:00
|
|
|
//===--------- LLJIT.cpp - An ORC-based JIT for compiling LLVM IR ---------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// 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
|
2018-06-27 05:35:48 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
|
|
|
|
#include "llvm/ExecutionEngine/Orc/OrcError.h"
|
2019-04-30 06:37:27 +08:00
|
|
|
#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
|
2018-06-27 05:35:48 +08:00
|
|
|
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
|
|
|
|
#include "llvm/IR/Mangler.h"
|
|
|
|
|
|
|
|
namespace llvm {
|
|
|
|
namespace orc {
|
|
|
|
|
2019-04-30 06:37:27 +08:00
|
|
|
Error LLJITBuilderState::prepareForConstruction() {
|
2018-09-27 00:26:59 +08:00
|
|
|
|
2019-04-30 06:37:27 +08:00
|
|
|
if (!JTMB) {
|
|
|
|
if (auto JTMBOrErr = JITTargetMachineBuilder::detectHost())
|
|
|
|
JTMB = std::move(*JTMBOrErr);
|
|
|
|
else
|
|
|
|
return JTMBOrErr.takeError();
|
2018-09-27 00:26:59 +08:00
|
|
|
}
|
|
|
|
|
2019-04-30 06:37:27 +08:00
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
|
|
|
|
LLJIT::~LLJIT() {
|
|
|
|
if (CompileThreads)
|
|
|
|
CompileThreads->wait();
|
2018-06-27 05:35:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Error LLJIT::defineAbsolute(StringRef Name, JITEvaluatedSymbol Sym) {
|
2018-10-01 07:18:24 +08:00
|
|
|
auto InternedName = ES->intern(Name);
|
2018-06-27 05:35:48 +08:00
|
|
|
SymbolMap Symbols({{InternedName, Sym}});
|
|
|
|
return Main.define(absoluteSymbols(std::move(Symbols)));
|
|
|
|
}
|
|
|
|
|
2018-09-26 09:24:12 +08:00
|
|
|
Error LLJIT::addIRModule(JITDylib &JD, ThreadSafeModule TSM) {
|
|
|
|
assert(TSM && "Can not add null module");
|
2018-06-27 05:35:48 +08:00
|
|
|
|
2019-08-02 23:21:37 +08:00
|
|
|
if (auto Err =
|
|
|
|
TSM.withModuleDo([&](Module &M) { return applyDataLayout(M); }))
|
2018-06-27 05:35:48 +08:00
|
|
|
return Err;
|
|
|
|
|
2019-04-30 06:37:27 +08:00
|
|
|
return CompileLayer->add(JD, std::move(TSM), ES->allocateVModule());
|
2018-06-27 05:35:48 +08:00
|
|
|
}
|
|
|
|
|
2018-08-29 04:20:31 +08:00
|
|
|
Error LLJIT::addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj) {
|
|
|
|
assert(Obj && "Can not add null object");
|
|
|
|
|
2019-04-30 06:37:27 +08:00
|
|
|
return ObjLinkingLayer->add(JD, std::move(Obj), ES->allocateVModule());
|
2018-08-29 04:20:31 +08:00
|
|
|
}
|
|
|
|
|
2018-08-18 05:18:18 +08:00
|
|
|
Expected<JITEvaluatedSymbol> LLJIT::lookupLinkerMangled(JITDylib &JD,
|
2018-06-27 05:35:48 +08:00
|
|
|
StringRef Name) {
|
2018-10-24 07:01:39 +08:00
|
|
|
return ES->lookup(JITDylibSearchList({{&JD, true}}), ES->intern(Name));
|
2018-06-27 05:35:48 +08:00
|
|
|
}
|
|
|
|
|
2019-04-30 06:37:27 +08:00
|
|
|
std::unique_ptr<ObjectLayer>
|
|
|
|
LLJIT::createObjectLinkingLayer(LLJITBuilderState &S, ExecutionSession &ES) {
|
|
|
|
|
|
|
|
// If the config state provided an ObjectLinkingLayer factory then use it.
|
|
|
|
if (S.CreateObjectLinkingLayer)
|
2019-08-03 03:43:20 +08:00
|
|
|
return S.CreateObjectLinkingLayer(ES, S.JTMB->getTargetTriple());
|
2019-04-30 06:37:27 +08:00
|
|
|
|
|
|
|
// Otherwise default to creating an RTDyldObjectLinkingLayer that constructs
|
|
|
|
// a new SectionMemoryManager for each object.
|
2019-08-15 23:54:37 +08:00
|
|
|
auto GetMemMgr = []() { return std::make_unique<SectionMemoryManager>(); };
|
2019-08-03 03:43:20 +08:00
|
|
|
auto ObjLinkingLayer =
|
2019-08-15 23:54:37 +08:00
|
|
|
std::make_unique<RTDyldObjectLinkingLayer>(ES, std::move(GetMemMgr));
|
2019-08-03 03:43:20 +08:00
|
|
|
|
|
|
|
if (S.JTMB->getTargetTriple().isOSBinFormatCOFF())
|
|
|
|
ObjLinkingLayer->setOverrideObjectFlagsWithResponsibilityFlags(true);
|
|
|
|
|
2019-08-06 04:30:35 +08:00
|
|
|
// FIXME: Explicit conversion to std::unique_ptr<ObjectLayer> added to silence
|
|
|
|
// errors from some GCC / libstdc++ bots. Remove this conversion (i.e.
|
|
|
|
// just return ObjLinkingLayer) once those bots are upgraded.
|
|
|
|
return std::unique_ptr<ObjectLayer>(std::move(ObjLinkingLayer));
|
2019-04-30 06:37:27 +08:00
|
|
|
}
|
|
|
|
|
2019-07-11 01:24:24 +08:00
|
|
|
Expected<IRCompileLayer::CompileFunction>
|
|
|
|
LLJIT::createCompileFunction(LLJITBuilderState &S,
|
|
|
|
JITTargetMachineBuilder JTMB) {
|
|
|
|
|
|
|
|
/// If there is a custom compile function creator set then use it.
|
|
|
|
if (S.CreateCompileFunction)
|
|
|
|
return S.CreateCompileFunction(std::move(JTMB));
|
|
|
|
|
|
|
|
// Otherwise default to creating a SimpleCompiler, or ConcurrentIRCompiler,
|
|
|
|
// depending on the number of threads requested.
|
|
|
|
if (S.NumCompileThreads > 0)
|
|
|
|
return ConcurrentIRCompiler(std::move(JTMB));
|
|
|
|
|
|
|
|
auto TM = JTMB.createTargetMachine();
|
|
|
|
if (!TM)
|
|
|
|
return TM.takeError();
|
|
|
|
|
|
|
|
return TMOwningSimpleCompiler(std::move(*TM));
|
|
|
|
}
|
|
|
|
|
2019-04-30 06:37:27 +08:00
|
|
|
LLJIT::LLJIT(LLJITBuilderState &S, Error &Err)
|
2019-08-15 23:54:37 +08:00
|
|
|
: ES(S.ES ? std::move(S.ES) : std::make_unique<ExecutionSession>()),
|
2019-04-30 06:37:27 +08:00
|
|
|
Main(this->ES->getMainJITDylib()), DL(""), CtorRunner(Main),
|
|
|
|
DtorRunner(Main) {
|
|
|
|
|
|
|
|
ErrorAsOutParameter _(&Err);
|
|
|
|
|
|
|
|
ObjLinkingLayer = createObjectLinkingLayer(S, *ES);
|
|
|
|
|
2019-07-11 01:24:24 +08:00
|
|
|
if (auto DLOrErr = S.JTMB->getDefaultDataLayoutForTarget())
|
|
|
|
DL = std::move(*DLOrErr);
|
|
|
|
else {
|
|
|
|
Err = DLOrErr.takeError();
|
|
|
|
return;
|
|
|
|
}
|
2019-04-30 06:37:27 +08:00
|
|
|
|
2019-07-11 01:24:24 +08:00
|
|
|
{
|
|
|
|
auto CompileFunction = createCompileFunction(S, std::move(*S.JTMB));
|
|
|
|
if (!CompileFunction) {
|
|
|
|
Err = CompileFunction.takeError();
|
2019-04-30 06:37:27 +08:00
|
|
|
return;
|
|
|
|
}
|
2019-08-15 23:54:37 +08:00
|
|
|
CompileLayer = std::make_unique<IRCompileLayer>(
|
2019-07-11 01:24:24 +08:00
|
|
|
*ES, *ObjLinkingLayer, std::move(*CompileFunction));
|
|
|
|
}
|
2019-04-30 06:37:27 +08:00
|
|
|
|
2019-07-11 01:24:24 +08:00
|
|
|
if (S.NumCompileThreads > 0) {
|
|
|
|
CompileLayer->setCloneToNewContextOnEmit(true);
|
2019-08-15 23:54:37 +08:00
|
|
|
CompileThreads = std::make_unique<ThreadPool>(S.NumCompileThreads);
|
2019-04-30 06:37:27 +08:00
|
|
|
ES->setDispatchMaterialization(
|
|
|
|
[this](JITDylib &JD, std::unique_ptr<MaterializationUnit> MU) {
|
2019-09-13 19:35:33 +08:00
|
|
|
auto Work = [MU = std::move(MU), &JD] { MU->doMaterialize(JD); };
|
2019-04-30 06:37:27 +08:00
|
|
|
CompileThreads->async(std::move(Work));
|
|
|
|
});
|
|
|
|
}
|
2018-09-27 00:26:59 +08:00
|
|
|
}
|
|
|
|
|
2018-06-27 05:35:48 +08:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2019-04-30 06:37:27 +08:00
|
|
|
Error LLLazyJITBuilderState::prepareForConstruction() {
|
|
|
|
if (auto Err = LLJITBuilderState::prepareForConstruction())
|
|
|
|
return Err;
|
|
|
|
TT = JTMB->getTargetTriple();
|
|
|
|
return Error::success();
|
2018-06-27 05:35:48 +08:00
|
|
|
}
|
|
|
|
|
2018-09-26 09:24:12 +08:00
|
|
|
Error LLLazyJIT::addLazyIRModule(JITDylib &JD, ThreadSafeModule TSM) {
|
|
|
|
assert(TSM && "Can not add null module");
|
2018-06-27 05:35:48 +08:00
|
|
|
|
2019-08-02 23:21:37 +08:00
|
|
|
if (auto Err = TSM.withModuleDo([&](Module &M) -> Error {
|
|
|
|
if (auto Err = applyDataLayout(M))
|
|
|
|
return Err;
|
2018-06-27 05:35:48 +08:00
|
|
|
|
2019-08-02 23:21:37 +08:00
|
|
|
recordCtorDtors(M);
|
|
|
|
return Error::success();
|
|
|
|
}))
|
|
|
|
return Err;
|
2018-06-27 05:35:48 +08:00
|
|
|
|
2019-04-30 06:37:27 +08:00
|
|
|
return CODLayer->add(JD, std::move(TSM), ES->allocateVModule());
|
2018-06-27 05:35:48 +08:00
|
|
|
}
|
|
|
|
|
2019-04-30 06:37:27 +08:00
|
|
|
LLLazyJIT::LLLazyJIT(LLLazyJITBuilderState &S, Error &Err) : LLJIT(S, Err) {
|
|
|
|
|
|
|
|
// If LLJIT construction failed then bail out.
|
|
|
|
if (Err)
|
|
|
|
return;
|
|
|
|
|
|
|
|
ErrorAsOutParameter _(&Err);
|
|
|
|
|
|
|
|
/// Take/Create the lazy-compile callthrough manager.
|
|
|
|
if (S.LCTMgr)
|
|
|
|
LCTMgr = std::move(S.LCTMgr);
|
|
|
|
else {
|
|
|
|
if (auto LCTMgrOrErr = createLocalLazyCallThroughManager(
|
|
|
|
S.TT, *ES, S.LazyCompileFailureAddr))
|
|
|
|
LCTMgr = std::move(*LCTMgrOrErr);
|
|
|
|
else {
|
|
|
|
Err = LCTMgrOrErr.takeError();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Take/Create the indirect stubs manager builder.
|
|
|
|
auto ISMBuilder = std::move(S.ISMBuilder);
|
|
|
|
|
|
|
|
// If none was provided, try to build one.
|
|
|
|
if (!ISMBuilder)
|
|
|
|
ISMBuilder = createLocalIndirectStubsManagerBuilder(S.TT);
|
|
|
|
|
|
|
|
// No luck. Bail out.
|
|
|
|
if (!ISMBuilder) {
|
|
|
|
Err = make_error<StringError>("Could not construct "
|
|
|
|
"IndirectStubsManagerBuilder for target " +
|
|
|
|
S.TT.str(),
|
|
|
|
inconvertibleErrorCode());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create the transform layer.
|
2019-08-15 23:54:37 +08:00
|
|
|
TransformLayer = std::make_unique<IRTransformLayer>(*ES, *CompileLayer);
|
2019-04-30 06:37:27 +08:00
|
|
|
|
|
|
|
// Create the COD layer.
|
2019-08-15 23:54:37 +08:00
|
|
|
CODLayer = std::make_unique<CompileOnDemandLayer>(
|
2019-04-30 06:37:27 +08:00
|
|
|
*ES, *TransformLayer, *LCTMgr, std::move(ISMBuilder));
|
|
|
|
|
|
|
|
if (S.NumCompileThreads > 0)
|
|
|
|
CODLayer->setCloneToNewContextOnEmit(true);
|
2018-09-28 05:13:07 +08:00
|
|
|
}
|
2018-09-27 00:26:59 +08:00
|
|
|
|
2018-06-27 05:35:48 +08:00
|
|
|
} // End namespace orc.
|
|
|
|
} // End namespace llvm.
|