16a94134bSLang Hames //===--------- LLJIT.cpp - An ORC-based JIT for compiling LLVM IR ---------===//
26a94134bSLang Hames //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66a94134bSLang Hames //
76a94134bSLang Hames //===----------------------------------------------------------------------===//
86a94134bSLang Hames
96a94134bSLang Hames #include "llvm/ExecutionEngine/Orc/LLJIT.h"
107266a8bfSLang Hames #include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
1167a1b7f0SLang Hames #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
12662c5544SLang Hames #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
1385fb9976SLang Hames #include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
1467a1b7f0SLang Hames #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
15a5eb9df1SStefan Gränitz #include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
16eb14dc75SLang Hames #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
1724672ddeSLang Hames #include "llvm/ExecutionEngine/Orc/Shared/OrcError.h"
186a94134bSLang Hames #include "llvm/ExecutionEngine/SectionMemoryManager.h"
1985fb9976SLang Hames #include "llvm/IR/GlobalVariable.h"
2085fb9976SLang Hames #include "llvm/IR/IRBuilder.h"
216a94134bSLang Hames #include "llvm/IR/Mangler.h"
2285fb9976SLang Hames #include "llvm/IR/Module.h"
2385fb9976SLang Hames #include "llvm/Support/DynamicLibrary.h"
2485fb9976SLang Hames
2585fb9976SLang Hames #include <map>
2685fb9976SLang Hames
278363ff04SLang Hames #define DEBUG_TYPE "orc"
288363ff04SLang Hames
2985fb9976SLang Hames using namespace llvm;
3085fb9976SLang Hames using namespace llvm::orc;
3185fb9976SLang Hames
3285fb9976SLang Hames namespace {
3385fb9976SLang Hames
3485fb9976SLang Hames /// Adds helper function decls and wrapper functions that call the helper with
3585fb9976SLang Hames /// some additional prefix arguments.
3685fb9976SLang Hames ///
3785fb9976SLang Hames /// E.g. For wrapper "foo" with type i8(i8, i64), helper "bar", and prefix
3885fb9976SLang Hames /// args i32 4 and i16 12345, this function will add:
3985fb9976SLang Hames ///
4085fb9976SLang Hames /// declare i8 @bar(i32, i16, i8, i64)
4185fb9976SLang Hames ///
4285fb9976SLang Hames /// define i8 @foo(i8, i64) {
4385fb9976SLang Hames /// entry:
4485fb9976SLang Hames /// %2 = call i8 @bar(i32 4, i16 12345, i8 %0, i64 %1)
4585fb9976SLang Hames /// ret i8 %2
4685fb9976SLang Hames /// }
4785fb9976SLang Hames ///
addHelperAndWrapper(Module & M,StringRef WrapperName,FunctionType * WrapperFnType,GlobalValue::VisibilityTypes WrapperVisibility,StringRef HelperName,ArrayRef<Value * > HelperPrefixArgs)4885fb9976SLang Hames Function *addHelperAndWrapper(Module &M, StringRef WrapperName,
4985fb9976SLang Hames FunctionType *WrapperFnType,
5085fb9976SLang Hames GlobalValue::VisibilityTypes WrapperVisibility,
5185fb9976SLang Hames StringRef HelperName,
5285fb9976SLang Hames ArrayRef<Value *> HelperPrefixArgs) {
5385fb9976SLang Hames std::vector<Type *> HelperArgTypes;
5485fb9976SLang Hames for (auto *Arg : HelperPrefixArgs)
5585fb9976SLang Hames HelperArgTypes.push_back(Arg->getType());
5685fb9976SLang Hames for (auto *T : WrapperFnType->params())
5785fb9976SLang Hames HelperArgTypes.push_back(T);
5885fb9976SLang Hames auto *HelperFnType =
5985fb9976SLang Hames FunctionType::get(WrapperFnType->getReturnType(), HelperArgTypes, false);
6085fb9976SLang Hames auto *HelperFn = Function::Create(HelperFnType, GlobalValue::ExternalLinkage,
6185fb9976SLang Hames HelperName, M);
6285fb9976SLang Hames
6385fb9976SLang Hames auto *WrapperFn = Function::Create(
6485fb9976SLang Hames WrapperFnType, GlobalValue::ExternalLinkage, WrapperName, M);
6585fb9976SLang Hames WrapperFn->setVisibility(WrapperVisibility);
6685fb9976SLang Hames
6785fb9976SLang Hames auto *EntryBlock = BasicBlock::Create(M.getContext(), "entry", WrapperFn);
6885fb9976SLang Hames IRBuilder<> IB(EntryBlock);
6985fb9976SLang Hames
7085fb9976SLang Hames std::vector<Value *> HelperArgs;
7185fb9976SLang Hames for (auto *Arg : HelperPrefixArgs)
7285fb9976SLang Hames HelperArgs.push_back(Arg);
7385fb9976SLang Hames for (auto &Arg : WrapperFn->args())
7485fb9976SLang Hames HelperArgs.push_back(&Arg);
7585fb9976SLang Hames auto *HelperResult = IB.CreateCall(HelperFn, HelperArgs);
7685fb9976SLang Hames if (HelperFn->getReturnType()->isVoidTy())
7785fb9976SLang Hames IB.CreateRetVoid();
7885fb9976SLang Hames else
7985fb9976SLang Hames IB.CreateRet(HelperResult);
8085fb9976SLang Hames
8185fb9976SLang Hames return WrapperFn;
8285fb9976SLang Hames }
8385fb9976SLang Hames
8485fb9976SLang Hames class GenericLLVMIRPlatformSupport;
8585fb9976SLang Hames
8685fb9976SLang Hames /// orc::Platform component of Generic LLVM IR Platform support.
8785fb9976SLang Hames /// Just forwards calls to the GenericLLVMIRPlatformSupport class below.
8885fb9976SLang Hames class GenericLLVMIRPlatform : public Platform {
8985fb9976SLang Hames public:
GenericLLVMIRPlatform(GenericLLVMIRPlatformSupport & S)9085fb9976SLang Hames GenericLLVMIRPlatform(GenericLLVMIRPlatformSupport &S) : S(S) {}
9185fb9976SLang Hames Error setupJITDylib(JITDylib &JD) override;
92ade71641SLang Hames Error teardownJITDylib(JITDylib &JD) override;
930aec49c8SLang Hames Error notifyAdding(ResourceTracker &RT,
940aec49c8SLang Hames const MaterializationUnit &MU) override;
notifyRemoving(ResourceTracker & RT)950aec49c8SLang Hames Error notifyRemoving(ResourceTracker &RT) override {
9685fb9976SLang Hames // Noop -- Nothing to do (yet).
9785fb9976SLang Hames return Error::success();
9885fb9976SLang Hames }
9985fb9976SLang Hames
10085fb9976SLang Hames private:
10185fb9976SLang Hames GenericLLVMIRPlatformSupport &S;
10285fb9976SLang Hames };
10385fb9976SLang Hames
10485fb9976SLang Hames /// This transform parses llvm.global_ctors to produce a single initialization
10585fb9976SLang Hames /// function for the module, records the function, then deletes
10685fb9976SLang Hames /// llvm.global_ctors.
10785fb9976SLang Hames class GlobalCtorDtorScraper {
10885fb9976SLang Hames public:
GlobalCtorDtorScraper(GenericLLVMIRPlatformSupport & PS,StringRef InitFunctionPrefix,StringRef DeInitFunctionPrefix)1091df947abSLang Hames GlobalCtorDtorScraper(GenericLLVMIRPlatformSupport &PS,
11002ac5e5cSluxufan StringRef InitFunctionPrefix,
11102ac5e5cSluxufan StringRef DeInitFunctionPrefix)
11202ac5e5cSluxufan : PS(PS), InitFunctionPrefix(InitFunctionPrefix),
11302ac5e5cSluxufan DeInitFunctionPrefix(DeInitFunctionPrefix) {}
11485fb9976SLang Hames Expected<ThreadSafeModule> operator()(ThreadSafeModule TSM,
11585fb9976SLang Hames MaterializationResponsibility &R);
11685fb9976SLang Hames
11785fb9976SLang Hames private:
11885fb9976SLang Hames GenericLLVMIRPlatformSupport &PS;
1191df947abSLang Hames StringRef InitFunctionPrefix;
12002ac5e5cSluxufan StringRef DeInitFunctionPrefix;
12185fb9976SLang Hames };
12285fb9976SLang Hames
12385fb9976SLang Hames /// Generic IR Platform Support
12485fb9976SLang Hames ///
12585fb9976SLang Hames /// Scrapes llvm.global_ctors and llvm.global_dtors and replaces them with
12685fb9976SLang Hames /// specially named 'init' and 'deinit'. Injects definitions / interposes for
12785fb9976SLang Hames /// some runtime API, including __cxa_atexit, dlopen, and dlclose.
12885fb9976SLang Hames class GenericLLVMIRPlatformSupport : public LLJIT::PlatformSupport {
12985fb9976SLang Hames public:
GenericLLVMIRPlatformSupport(LLJIT & J)1305877d6f5SLang Hames GenericLLVMIRPlatformSupport(LLJIT &J)
13102ac5e5cSluxufan : J(J), InitFunctionPrefix(J.mangle("__orc_init_func.")),
13202ac5e5cSluxufan DeInitFunctionPrefix(J.mangle("__orc_deinit_func.")) {
1331df947abSLang Hames
13485fb9976SLang Hames getExecutionSession().setPlatform(
13585fb9976SLang Hames std::make_unique<GenericLLVMIRPlatform>(*this));
13685fb9976SLang Hames
13702ac5e5cSluxufan setInitTransform(J, GlobalCtorDtorScraper(*this, InitFunctionPrefix,
13802ac5e5cSluxufan DeInitFunctionPrefix));
13985fb9976SLang Hames
14085fb9976SLang Hames SymbolMap StdInterposes;
14185fb9976SLang Hames
1425877d6f5SLang Hames StdInterposes[J.mangleAndIntern("__lljit.platform_support_instance")] =
14305598441SLang Hames JITEvaluatedSymbol(pointerToJITTargetAddress(this),
14405598441SLang Hames JITSymbolFlags::Exported);
1455877d6f5SLang Hames StdInterposes[J.mangleAndIntern("__lljit.cxa_atexit_helper")] =
1467d101e43SSunho Kim JITEvaluatedSymbol(pointerToJITTargetAddress(registerCxaAtExitHelper),
1475877d6f5SLang Hames JITSymbolFlags());
14885fb9976SLang Hames
14985fb9976SLang Hames cantFail(
15085fb9976SLang Hames J.getMainJITDylib().define(absoluteSymbols(std::move(StdInterposes))));
15185fb9976SLang Hames cantFail(setupJITDylib(J.getMainJITDylib()));
15285fb9976SLang Hames cantFail(J.addIRModule(J.getMainJITDylib(), createPlatformRuntimeModule()));
15385fb9976SLang Hames }
15485fb9976SLang Hames
getExecutionSession()15585fb9976SLang Hames ExecutionSession &getExecutionSession() { return J.getExecutionSession(); }
15685fb9976SLang Hames
15785fb9976SLang Hames /// Adds a module that defines the __dso_handle global.
setupJITDylib(JITDylib & JD)15885fb9976SLang Hames Error setupJITDylib(JITDylib &JD) {
15905598441SLang Hames
16005598441SLang Hames // Add per-jitdylib standard interposes.
16105598441SLang Hames SymbolMap PerJDInterposes;
1625877d6f5SLang Hames PerJDInterposes[J.mangleAndIntern("__lljit.run_atexits_helper")] =
1635877d6f5SLang Hames JITEvaluatedSymbol(pointerToJITTargetAddress(runAtExitsHelper),
1645877d6f5SLang Hames JITSymbolFlags());
1657d101e43SSunho Kim PerJDInterposes[J.mangleAndIntern("__lljit.atexit_helper")] =
1667d101e43SSunho Kim JITEvaluatedSymbol(pointerToJITTargetAddress(registerAtExitHelper),
1677d101e43SSunho Kim JITSymbolFlags());
16805598441SLang Hames cantFail(JD.define(absoluteSymbols(std::move(PerJDInterposes))));
16905598441SLang Hames
17085fb9976SLang Hames auto Ctx = std::make_unique<LLVMContext>();
17185fb9976SLang Hames auto M = std::make_unique<Module>("__standard_lib", *Ctx);
17285fb9976SLang Hames M->setDataLayout(J.getDataLayout());
17385fb9976SLang Hames
17485fb9976SLang Hames auto *Int64Ty = Type::getInt64Ty(*Ctx);
17585fb9976SLang Hames auto *DSOHandle = new GlobalVariable(
17685fb9976SLang Hames *M, Int64Ty, true, GlobalValue::ExternalLinkage,
17785fb9976SLang Hames ConstantInt::get(Int64Ty, reinterpret_cast<uintptr_t>(&JD)),
17885fb9976SLang Hames "__dso_handle");
17905598441SLang Hames DSOHandle->setVisibility(GlobalValue::DefaultVisibility);
18085fb9976SLang Hames DSOHandle->setInitializer(
18185fb9976SLang Hames ConstantInt::get(Int64Ty, pointerToJITTargetAddress(&JD)));
18205598441SLang Hames
18305598441SLang Hames auto *GenericIRPlatformSupportTy =
18405598441SLang Hames StructType::create(*Ctx, "lljit.GenericLLJITIRPlatformSupport");
18505598441SLang Hames
18605598441SLang Hames auto *PlatformInstanceDecl = new GlobalVariable(
18705598441SLang Hames *M, GenericIRPlatformSupportTy, true, GlobalValue::ExternalLinkage,
18805598441SLang Hames nullptr, "__lljit.platform_support_instance");
18905598441SLang Hames
19005598441SLang Hames auto *VoidTy = Type::getVoidTy(*Ctx);
19105598441SLang Hames addHelperAndWrapper(
19205598441SLang Hames *M, "__lljit_run_atexits", FunctionType::get(VoidTy, {}, false),
19305598441SLang Hames GlobalValue::HiddenVisibility, "__lljit.run_atexits_helper",
19405598441SLang Hames {PlatformInstanceDecl, DSOHandle});
19505598441SLang Hames
1967d101e43SSunho Kim auto *IntTy = Type::getIntNTy(*Ctx, sizeof(int) * CHAR_BIT);
1977d101e43SSunho Kim auto *AtExitCallbackTy = FunctionType::get(VoidTy, {}, false);
1987d101e43SSunho Kim auto *AtExitCallbackPtrTy = PointerType::getUnqual(AtExitCallbackTy);
1997d101e43SSunho Kim addHelperAndWrapper(*M, "atexit",
2007d101e43SSunho Kim FunctionType::get(IntTy, {AtExitCallbackPtrTy}, false),
2017d101e43SSunho Kim GlobalValue::HiddenVisibility, "__lljit.atexit_helper",
2027d101e43SSunho Kim {PlatformInstanceDecl, DSOHandle});
2037d101e43SSunho Kim
20485fb9976SLang Hames return J.addIRModule(JD, ThreadSafeModule(std::move(M), std::move(Ctx)));
20585fb9976SLang Hames }
20685fb9976SLang Hames
notifyAdding(ResourceTracker & RT,const MaterializationUnit & MU)2070aec49c8SLang Hames Error notifyAdding(ResourceTracker &RT, const MaterializationUnit &MU) {
2080aec49c8SLang Hames auto &JD = RT.getJITDylib();
20985fb9976SLang Hames if (auto &InitSym = MU.getInitializerSymbol())
210cb84e482SLang Hames InitSymbols[&JD].add(InitSym, SymbolLookupFlags::WeaklyReferencedSymbol);
2111df947abSLang Hames else {
2121df947abSLang Hames // If there's no identified init symbol attached, but there is a symbol
2131df947abSLang Hames // with the GenericIRPlatform::InitFunctionPrefix, then treat that as
2141df947abSLang Hames // an init function. Add the symbol to both the InitSymbols map (which
2151df947abSLang Hames // will trigger a lookup to materialize the module) and the InitFunctions
2161df947abSLang Hames // map (which holds the names of the symbols to execute).
2171df947abSLang Hames for (auto &KV : MU.getSymbols())
2185877d6f5SLang Hames if ((*KV.first).startswith(InitFunctionPrefix)) {
219cb84e482SLang Hames InitSymbols[&JD].add(KV.first,
220cb84e482SLang Hames SymbolLookupFlags::WeaklyReferencedSymbol);
2211df947abSLang Hames InitFunctions[&JD].add(KV.first);
22202ac5e5cSluxufan } else if ((*KV.first).startswith(DeInitFunctionPrefix)) {
22302ac5e5cSluxufan DeInitFunctions[&JD].add(KV.first);
2241df947abSLang Hames }
2251df947abSLang Hames }
22685fb9976SLang Hames return Error::success();
22785fb9976SLang Hames }
22885fb9976SLang Hames
initialize(JITDylib & JD)22985fb9976SLang Hames Error initialize(JITDylib &JD) override {
2308363ff04SLang Hames LLVM_DEBUG({
2318363ff04SLang Hames dbgs() << "GenericLLVMIRPlatformSupport getting initializers to run\n";
2328363ff04SLang Hames });
23385fb9976SLang Hames if (auto Initializers = getInitializers(JD)) {
2348363ff04SLang Hames LLVM_DEBUG(
2358363ff04SLang Hames { dbgs() << "GenericLLVMIRPlatformSupport running initializers\n"; });
23685fb9976SLang Hames for (auto InitFnAddr : *Initializers) {
2378363ff04SLang Hames LLVM_DEBUG({
2388363ff04SLang Hames dbgs() << " Running init " << formatv("{0:x16}", InitFnAddr)
2398363ff04SLang Hames << "...\n";
2408363ff04SLang Hames });
24185fb9976SLang Hames auto *InitFn = jitTargetAddressToFunction<void (*)()>(InitFnAddr);
24285fb9976SLang Hames InitFn();
24385fb9976SLang Hames }
24485fb9976SLang Hames } else
24585fb9976SLang Hames return Initializers.takeError();
24685fb9976SLang Hames return Error::success();
24785fb9976SLang Hames }
24885fb9976SLang Hames
deinitialize(JITDylib & JD)24985fb9976SLang Hames Error deinitialize(JITDylib &JD) override {
2508363ff04SLang Hames LLVM_DEBUG({
2518363ff04SLang Hames dbgs() << "GenericLLVMIRPlatformSupport getting deinitializers to run\n";
2528363ff04SLang Hames });
25385fb9976SLang Hames if (auto Deinitializers = getDeinitializers(JD)) {
2548363ff04SLang Hames LLVM_DEBUG({
2558363ff04SLang Hames dbgs() << "GenericLLVMIRPlatformSupport running deinitializers\n";
2568363ff04SLang Hames });
25785fb9976SLang Hames for (auto DeinitFnAddr : *Deinitializers) {
2588363ff04SLang Hames LLVM_DEBUG({
259476abdb5SLang Hames dbgs() << " Running deinit " << formatv("{0:x16}", DeinitFnAddr)
2608363ff04SLang Hames << "...\n";
2618363ff04SLang Hames });
26285fb9976SLang Hames auto *DeinitFn = jitTargetAddressToFunction<void (*)()>(DeinitFnAddr);
26385fb9976SLang Hames DeinitFn();
26485fb9976SLang Hames }
26585fb9976SLang Hames } else
26685fb9976SLang Hames return Deinitializers.takeError();
26785fb9976SLang Hames
26885fb9976SLang Hames return Error::success();
26985fb9976SLang Hames }
27085fb9976SLang Hames
registerInitFunc(JITDylib & JD,SymbolStringPtr InitName)27185fb9976SLang Hames void registerInitFunc(JITDylib &JD, SymbolStringPtr InitName) {
27254aec178SLang Hames getExecutionSession().runSessionLocked([&]() {
27385fb9976SLang Hames InitFunctions[&JD].add(InitName);
27454aec178SLang Hames });
27585fb9976SLang Hames }
27685fb9976SLang Hames
registerDeInitFunc(JITDylib & JD,SymbolStringPtr DeInitName)27702ac5e5cSluxufan void registerDeInitFunc(JITDylib &JD, SymbolStringPtr DeInitName) {
27802ac5e5cSluxufan getExecutionSession().runSessionLocked(
27902ac5e5cSluxufan [&]() { DeInitFunctions[&JD].add(DeInitName); });
28002ac5e5cSluxufan }
28102ac5e5cSluxufan
28285fb9976SLang Hames private:
28354aec178SLang Hames
getInitializers(JITDylib & JD)28485fb9976SLang Hames Expected<std::vector<JITTargetAddress>> getInitializers(JITDylib &JD) {
28585fb9976SLang Hames if (auto Err = issueInitLookups(JD))
28685fb9976SLang Hames return std::move(Err);
28785fb9976SLang Hames
28885fb9976SLang Hames DenseMap<JITDylib *, SymbolLookupSet> LookupSymbols;
2890aec49c8SLang Hames std::vector<JITDylibSP> DFSLinkOrder;
29085fb9976SLang Hames
2919eb4939bSLang Hames if (auto Err = getExecutionSession().runSessionLocked([&]() -> Error {
2929eb4939bSLang Hames if (auto DFSLinkOrderOrErr = JD.getDFSLinkOrder())
2939eb4939bSLang Hames DFSLinkOrder = std::move(*DFSLinkOrderOrErr);
2949eb4939bSLang Hames else
2959eb4939bSLang Hames return DFSLinkOrderOrErr.takeError();
29685fb9976SLang Hames
297e1d5f7d0SLang Hames for (auto &NextJD : DFSLinkOrder) {
298e1d5f7d0SLang Hames auto IFItr = InitFunctions.find(NextJD.get());
29985fb9976SLang Hames if (IFItr != InitFunctions.end()) {
300e1d5f7d0SLang Hames LookupSymbols[NextJD.get()] = std::move(IFItr->second);
30185fb9976SLang Hames InitFunctions.erase(IFItr);
30285fb9976SLang Hames }
30385fb9976SLang Hames }
3049eb4939bSLang Hames return Error::success();
3059eb4939bSLang Hames }))
306f8752e28SLang Hames return std::move(Err);
30785fb9976SLang Hames
3088363ff04SLang Hames LLVM_DEBUG({
3098363ff04SLang Hames dbgs() << "JITDylib init order is [ ";
310e1d5f7d0SLang Hames for (auto &JD : llvm::reverse(DFSLinkOrder))
3118363ff04SLang Hames dbgs() << "\"" << JD->getName() << "\" ";
3128363ff04SLang Hames dbgs() << "]\n";
3138363ff04SLang Hames dbgs() << "Looking up init functions:\n";
3148363ff04SLang Hames for (auto &KV : LookupSymbols)
3158363ff04SLang Hames dbgs() << " \"" << KV.first->getName() << "\": " << KV.second << "\n";
3168363ff04SLang Hames });
3178363ff04SLang Hames
31885fb9976SLang Hames auto &ES = getExecutionSession();
31985fb9976SLang Hames auto LookupResult = Platform::lookupInitSymbols(ES, LookupSymbols);
32085fb9976SLang Hames
32185fb9976SLang Hames if (!LookupResult)
32285fb9976SLang Hames return LookupResult.takeError();
32385fb9976SLang Hames
32485fb9976SLang Hames std::vector<JITTargetAddress> Initializers;
32585fb9976SLang Hames while (!DFSLinkOrder.empty()) {
32685fb9976SLang Hames auto &NextJD = *DFSLinkOrder.back();
32785fb9976SLang Hames DFSLinkOrder.pop_back();
32885fb9976SLang Hames auto InitsItr = LookupResult->find(&NextJD);
32985fb9976SLang Hames if (InitsItr == LookupResult->end())
33085fb9976SLang Hames continue;
33185fb9976SLang Hames for (auto &KV : InitsItr->second)
33285fb9976SLang Hames Initializers.push_back(KV.second.getAddress());
33385fb9976SLang Hames }
33485fb9976SLang Hames
33585fb9976SLang Hames return Initializers;
33685fb9976SLang Hames }
33785fb9976SLang Hames
getDeinitializers(JITDylib & JD)33885fb9976SLang Hames Expected<std::vector<JITTargetAddress>> getDeinitializers(JITDylib &JD) {
33985fb9976SLang Hames auto &ES = getExecutionSession();
34085fb9976SLang Hames
3415877d6f5SLang Hames auto LLJITRunAtExits = J.mangleAndIntern("__lljit_run_atexits");
34285fb9976SLang Hames
34385fb9976SLang Hames DenseMap<JITDylib *, SymbolLookupSet> LookupSymbols;
3440aec49c8SLang Hames std::vector<JITDylibSP> DFSLinkOrder;
34585fb9976SLang Hames
3469eb4939bSLang Hames if (auto Err = ES.runSessionLocked([&]() -> Error {
3479eb4939bSLang Hames if (auto DFSLinkOrderOrErr = JD.getDFSLinkOrder())
3489eb4939bSLang Hames DFSLinkOrder = std::move(*DFSLinkOrderOrErr);
3499eb4939bSLang Hames else
3509eb4939bSLang Hames return DFSLinkOrderOrErr.takeError();
35185fb9976SLang Hames
352e1d5f7d0SLang Hames for (auto &NextJD : DFSLinkOrder) {
353e1d5f7d0SLang Hames auto &JDLookupSymbols = LookupSymbols[NextJD.get()];
354e1d5f7d0SLang Hames auto DIFItr = DeInitFunctions.find(NextJD.get());
35585fb9976SLang Hames if (DIFItr != DeInitFunctions.end()) {
356e1d5f7d0SLang Hames LookupSymbols[NextJD.get()] = std::move(DIFItr->second);
35785fb9976SLang Hames DeInitFunctions.erase(DIFItr);
35885fb9976SLang Hames }
35985fb9976SLang Hames JDLookupSymbols.add(LLJITRunAtExits,
36085fb9976SLang Hames SymbolLookupFlags::WeaklyReferencedSymbol);
36185fb9976SLang Hames }
3629eb4939bSLang Hames return Error::success();
3639eb4939bSLang Hames }))
364d5ae7a99SLang Hames return std::move(Err);
36585fb9976SLang Hames
36605598441SLang Hames LLVM_DEBUG({
36705598441SLang Hames dbgs() << "JITDylib deinit order is [ ";
368e1d5f7d0SLang Hames for (auto &JD : DFSLinkOrder)
36905598441SLang Hames dbgs() << "\"" << JD->getName() << "\" ";
37005598441SLang Hames dbgs() << "]\n";
37105598441SLang Hames dbgs() << "Looking up deinit functions:\n";
37205598441SLang Hames for (auto &KV : LookupSymbols)
37305598441SLang Hames dbgs() << " \"" << KV.first->getName() << "\": " << KV.second << "\n";
37405598441SLang Hames });
37505598441SLang Hames
37685fb9976SLang Hames auto LookupResult = Platform::lookupInitSymbols(ES, LookupSymbols);
37785fb9976SLang Hames
37885fb9976SLang Hames if (!LookupResult)
37985fb9976SLang Hames return LookupResult.takeError();
38085fb9976SLang Hames
38185fb9976SLang Hames std::vector<JITTargetAddress> DeInitializers;
382e1d5f7d0SLang Hames for (auto &NextJD : DFSLinkOrder) {
383e1d5f7d0SLang Hames auto DeInitsItr = LookupResult->find(NextJD.get());
38485fb9976SLang Hames assert(DeInitsItr != LookupResult->end() &&
38585fb9976SLang Hames "Every JD should have at least __lljit_run_atexits");
38685fb9976SLang Hames
38785fb9976SLang Hames auto RunAtExitsItr = DeInitsItr->second.find(LLJITRunAtExits);
38885fb9976SLang Hames if (RunAtExitsItr != DeInitsItr->second.end())
38985fb9976SLang Hames DeInitializers.push_back(RunAtExitsItr->second.getAddress());
39085fb9976SLang Hames
39185fb9976SLang Hames for (auto &KV : DeInitsItr->second)
39285fb9976SLang Hames if (KV.first != LLJITRunAtExits)
39385fb9976SLang Hames DeInitializers.push_back(KV.second.getAddress());
39485fb9976SLang Hames }
39585fb9976SLang Hames
39685fb9976SLang Hames return DeInitializers;
39785fb9976SLang Hames }
39885fb9976SLang Hames
39985fb9976SLang Hames /// Issue lookups for all init symbols required to initialize JD (and any
40085fb9976SLang Hames /// JITDylibs that it depends on).
issueInitLookups(JITDylib & JD)40185fb9976SLang Hames Error issueInitLookups(JITDylib &JD) {
40285fb9976SLang Hames DenseMap<JITDylib *, SymbolLookupSet> RequiredInitSymbols;
4030aec49c8SLang Hames std::vector<JITDylibSP> DFSLinkOrder;
40485fb9976SLang Hames
4059eb4939bSLang Hames if (auto Err = getExecutionSession().runSessionLocked([&]() -> Error {
4069eb4939bSLang Hames if (auto DFSLinkOrderOrErr = JD.getDFSLinkOrder())
4079eb4939bSLang Hames DFSLinkOrder = std::move(*DFSLinkOrderOrErr);
4089eb4939bSLang Hames else
4099eb4939bSLang Hames return DFSLinkOrderOrErr.takeError();
41085fb9976SLang Hames
411e1d5f7d0SLang Hames for (auto &NextJD : DFSLinkOrder) {
412e1d5f7d0SLang Hames auto ISItr = InitSymbols.find(NextJD.get());
41385fb9976SLang Hames if (ISItr != InitSymbols.end()) {
414e1d5f7d0SLang Hames RequiredInitSymbols[NextJD.get()] = std::move(ISItr->second);
41585fb9976SLang Hames InitSymbols.erase(ISItr);
41685fb9976SLang Hames }
41785fb9976SLang Hames }
4189eb4939bSLang Hames return Error::success();
4199eb4939bSLang Hames }))
4209eb4939bSLang Hames return Err;
42185fb9976SLang Hames
42285fb9976SLang Hames return Platform::lookupInitSymbols(getExecutionSession(),
42385fb9976SLang Hames RequiredInitSymbols)
42485fb9976SLang Hames .takeError();
42585fb9976SLang Hames }
42685fb9976SLang Hames
registerCxaAtExitHelper(void * Self,void (* F)(void *),void * Ctx,void * DSOHandle)4277d101e43SSunho Kim static void registerCxaAtExitHelper(void *Self, void (*F)(void *), void *Ctx,
42885fb9976SLang Hames void *DSOHandle) {
42905598441SLang Hames LLVM_DEBUG({
4307d101e43SSunho Kim dbgs() << "Registering cxa atexit function " << (void *)F << " for JD "
4317d101e43SSunho Kim << (*static_cast<JITDylib **>(DSOHandle))->getName() << "\n";
4327d101e43SSunho Kim });
4337d101e43SSunho Kim static_cast<GenericLLVMIRPlatformSupport *>(Self)->AtExitMgr.registerAtExit(
4347d101e43SSunho Kim F, Ctx, DSOHandle);
4357d101e43SSunho Kim }
4367d101e43SSunho Kim
registerAtExitHelper(void * Self,void * DSOHandle,void (* F)())4377d101e43SSunho Kim static void registerAtExitHelper(void *Self, void *DSOHandle, void (*F)()) {
4387d101e43SSunho Kim LLVM_DEBUG({
43905598441SLang Hames dbgs() << "Registering atexit function " << (void *)F << " for JD "
44005598441SLang Hames << (*static_cast<JITDylib **>(DSOHandle))->getName() << "\n";
44105598441SLang Hames });
44285fb9976SLang Hames static_cast<GenericLLVMIRPlatformSupport *>(Self)->AtExitMgr.registerAtExit(
4437d101e43SSunho Kim reinterpret_cast<void (*)(void *)>(F), nullptr, DSOHandle);
44485fb9976SLang Hames }
44585fb9976SLang Hames
runAtExitsHelper(void * Self,void * DSOHandle)44685fb9976SLang Hames static void runAtExitsHelper(void *Self, void *DSOHandle) {
44705598441SLang Hames LLVM_DEBUG({
44805598441SLang Hames dbgs() << "Running atexit functions for JD "
44905598441SLang Hames << (*static_cast<JITDylib **>(DSOHandle))->getName() << "\n";
45005598441SLang Hames });
45185fb9976SLang Hames static_cast<GenericLLVMIRPlatformSupport *>(Self)->AtExitMgr.runAtExits(
45285fb9976SLang Hames DSOHandle);
45385fb9976SLang Hames }
45485fb9976SLang Hames
45585fb9976SLang Hames // Constructs an LLVM IR module containing platform runtime globals,
45685fb9976SLang Hames // functions, and interposes.
createPlatformRuntimeModule()45785fb9976SLang Hames ThreadSafeModule createPlatformRuntimeModule() {
45885fb9976SLang Hames auto Ctx = std::make_unique<LLVMContext>();
45985fb9976SLang Hames auto M = std::make_unique<Module>("__standard_lib", *Ctx);
46085fb9976SLang Hames M->setDataLayout(J.getDataLayout());
46185fb9976SLang Hames
46285fb9976SLang Hames auto *GenericIRPlatformSupportTy =
46385fb9976SLang Hames StructType::create(*Ctx, "lljit.GenericLLJITIRPlatformSupport");
46485fb9976SLang Hames
46585fb9976SLang Hames auto *PlatformInstanceDecl = new GlobalVariable(
46685fb9976SLang Hames *M, GenericIRPlatformSupportTy, true, GlobalValue::ExternalLinkage,
46785fb9976SLang Hames nullptr, "__lljit.platform_support_instance");
46885fb9976SLang Hames
46985fb9976SLang Hames auto *Int8Ty = Type::getInt8Ty(*Ctx);
47085fb9976SLang Hames auto *IntTy = Type::getIntNTy(*Ctx, sizeof(int) * CHAR_BIT);
47185fb9976SLang Hames auto *VoidTy = Type::getVoidTy(*Ctx);
47285fb9976SLang Hames auto *BytePtrTy = PointerType::getUnqual(Int8Ty);
4737d101e43SSunho Kim auto *CxaAtExitCallbackTy = FunctionType::get(VoidTy, {BytePtrTy}, false);
4747d101e43SSunho Kim auto *CxaAtExitCallbackPtrTy = PointerType::getUnqual(CxaAtExitCallbackTy);
47585fb9976SLang Hames
47685fb9976SLang Hames addHelperAndWrapper(
47785fb9976SLang Hames *M, "__cxa_atexit",
4787d101e43SSunho Kim FunctionType::get(IntTy, {CxaAtExitCallbackPtrTy, BytePtrTy, BytePtrTy},
47985fb9976SLang Hames false),
48005598441SLang Hames GlobalValue::DefaultVisibility, "__lljit.cxa_atexit_helper",
48185fb9976SLang Hames {PlatformInstanceDecl});
48285fb9976SLang Hames
48385fb9976SLang Hames return ThreadSafeModule(std::move(M), std::move(Ctx));
48485fb9976SLang Hames }
48585fb9976SLang Hames
48685fb9976SLang Hames LLJIT &J;
4875877d6f5SLang Hames std::string InitFunctionPrefix;
48802ac5e5cSluxufan std::string DeInitFunctionPrefix;
48985fb9976SLang Hames DenseMap<JITDylib *, SymbolLookupSet> InitSymbols;
49085fb9976SLang Hames DenseMap<JITDylib *, SymbolLookupSet> InitFunctions;
49185fb9976SLang Hames DenseMap<JITDylib *, SymbolLookupSet> DeInitFunctions;
49285fb9976SLang Hames ItaniumCXAAtExitSupport AtExitMgr;
49385fb9976SLang Hames };
49485fb9976SLang Hames
setupJITDylib(JITDylib & JD)49585fb9976SLang Hames Error GenericLLVMIRPlatform::setupJITDylib(JITDylib &JD) {
49685fb9976SLang Hames return S.setupJITDylib(JD);
49785fb9976SLang Hames }
49885fb9976SLang Hames
teardownJITDylib(JITDylib & JD)499ade71641SLang Hames Error GenericLLVMIRPlatform::teardownJITDylib(JITDylib &JD) {
500ade71641SLang Hames return Error::success();
501ade71641SLang Hames }
502ade71641SLang Hames
notifyAdding(ResourceTracker & RT,const MaterializationUnit & MU)5030aec49c8SLang Hames Error GenericLLVMIRPlatform::notifyAdding(ResourceTracker &RT,
50485fb9976SLang Hames const MaterializationUnit &MU) {
5050aec49c8SLang Hames return S.notifyAdding(RT, MU);
50685fb9976SLang Hames }
50785fb9976SLang Hames
50885fb9976SLang Hames Expected<ThreadSafeModule>
operator ()(ThreadSafeModule TSM,MaterializationResponsibility & R)50985fb9976SLang Hames GlobalCtorDtorScraper::operator()(ThreadSafeModule TSM,
51085fb9976SLang Hames MaterializationResponsibility &R) {
51185fb9976SLang Hames auto Err = TSM.withModuleDo([&](Module &M) -> Error {
51285fb9976SLang Hames auto &Ctx = M.getContext();
51385fb9976SLang Hames auto *GlobalCtors = M.getNamedGlobal("llvm.global_ctors");
51402ac5e5cSluxufan auto *GlobalDtors = M.getNamedGlobal("llvm.global_dtors");
51585fb9976SLang Hames
51602ac5e5cSluxufan auto RegisterCOrDtors = [&](GlobalVariable *GlobalCOrDtors,
51702ac5e5cSluxufan bool isCtor) -> Error {
51802ac5e5cSluxufan // If there's no llvm.global_c/dtor or it's just a decl then skip.
51902ac5e5cSluxufan if (!GlobalCOrDtors || GlobalCOrDtors->isDeclaration())
52085fb9976SLang Hames return Error::success();
52102ac5e5cSluxufan std::string InitOrDeInitFunctionName;
52202ac5e5cSluxufan if (isCtor)
52302ac5e5cSluxufan raw_string_ostream(InitOrDeInitFunctionName)
5241df947abSLang Hames << InitFunctionPrefix << M.getModuleIdentifier();
52502ac5e5cSluxufan else
52602ac5e5cSluxufan raw_string_ostream(InitOrDeInitFunctionName)
52702ac5e5cSluxufan << DeInitFunctionPrefix << M.getModuleIdentifier();
52885fb9976SLang Hames
52985fb9976SLang Hames MangleAndInterner Mangle(PS.getExecutionSession(), M.getDataLayout());
53002ac5e5cSluxufan auto InternedInitOrDeInitName = Mangle(InitOrDeInitFunctionName);
53102ac5e5cSluxufan if (auto Err = R.defineMaterializing(
53202ac5e5cSluxufan {{InternedInitOrDeInitName, JITSymbolFlags::Callable}}))
53385fb9976SLang Hames return Err;
53485fb9976SLang Hames
53502ac5e5cSluxufan auto *InitOrDeInitFunc = Function::Create(
53602ac5e5cSluxufan FunctionType::get(Type::getVoidTy(Ctx), {}, false),
53702ac5e5cSluxufan GlobalValue::ExternalLinkage, InitOrDeInitFunctionName, &M);
53802ac5e5cSluxufan InitOrDeInitFunc->setVisibility(GlobalValue::HiddenVisibility);
53902ac5e5cSluxufan std::vector<std::pair<Function *, unsigned>> InitsOrDeInits;
54002ac5e5cSluxufan auto COrDtors = isCtor ? getConstructors(M) : getDestructors(M);
54102ac5e5cSluxufan
54202ac5e5cSluxufan for (auto E : COrDtors)
54302ac5e5cSluxufan InitsOrDeInits.push_back(std::make_pair(E.Func, E.Priority));
544e0039b8dSKazu Hirata llvm::sort(InitsOrDeInits, llvm::less_second());
54502ac5e5cSluxufan
54602ac5e5cSluxufan auto *InitOrDeInitFuncEntryBlock =
54702ac5e5cSluxufan BasicBlock::Create(Ctx, "entry", InitOrDeInitFunc);
54802ac5e5cSluxufan IRBuilder<> IB(InitOrDeInitFuncEntryBlock);
54902ac5e5cSluxufan for (auto &KV : InitsOrDeInits)
55085fb9976SLang Hames IB.CreateCall(KV.first);
55185fb9976SLang Hames IB.CreateRetVoid();
55285fb9976SLang Hames
55302ac5e5cSluxufan if (isCtor)
55402ac5e5cSluxufan PS.registerInitFunc(R.getTargetJITDylib(), InternedInitOrDeInitName);
55502ac5e5cSluxufan else
55602ac5e5cSluxufan PS.registerDeInitFunc(R.getTargetJITDylib(), InternedInitOrDeInitName);
55702ac5e5cSluxufan
55802ac5e5cSluxufan GlobalCOrDtors->eraseFromParent();
55902ac5e5cSluxufan return Error::success();
56002ac5e5cSluxufan };
56102ac5e5cSluxufan
56202ac5e5cSluxufan if (auto Err = RegisterCOrDtors(GlobalCtors, true))
56302ac5e5cSluxufan return Err;
56402ac5e5cSluxufan if (auto Err = RegisterCOrDtors(GlobalDtors, false))
56502ac5e5cSluxufan return Err;
56602ac5e5cSluxufan
56785fb9976SLang Hames return Error::success();
56885fb9976SLang Hames });
56985fb9976SLang Hames
57085fb9976SLang Hames if (Err)
57185fb9976SLang Hames return std::move(Err);
57285fb9976SLang Hames
57363d0932cSLang Hames return std::move(TSM);
57485fb9976SLang Hames }
57585fb9976SLang Hames
576c352a2b8SStefan Gränitz /// Inactive Platform Support
577c352a2b8SStefan Gränitz ///
578c352a2b8SStefan Gränitz /// Explicitly disables platform support. JITDylibs are not scanned for special
579c352a2b8SStefan Gränitz /// init/deinit symbols. No runtime API interposes are injected.
580c352a2b8SStefan Gränitz class InactivePlatformSupport : public LLJIT::PlatformSupport {
581c352a2b8SStefan Gränitz public:
582c352a2b8SStefan Gränitz InactivePlatformSupport() = default;
583c352a2b8SStefan Gränitz
initialize(JITDylib & JD)584c352a2b8SStefan Gränitz Error initialize(JITDylib &JD) override {
585c352a2b8SStefan Gränitz LLVM_DEBUG(dbgs() << "InactivePlatformSupport: no initializers running for "
586c352a2b8SStefan Gränitz << JD.getName() << "\n");
587c352a2b8SStefan Gränitz return Error::success();
588c352a2b8SStefan Gränitz }
589c352a2b8SStefan Gränitz
deinitialize(JITDylib & JD)590c352a2b8SStefan Gränitz Error deinitialize(JITDylib &JD) override {
591c352a2b8SStefan Gränitz LLVM_DEBUG(
592c352a2b8SStefan Gränitz dbgs() << "InactivePlatformSupport: no deinitializers running for "
593c352a2b8SStefan Gränitz << JD.getName() << "\n");
594c352a2b8SStefan Gränitz return Error::success();
595c352a2b8SStefan Gränitz }
596c352a2b8SStefan Gränitz };
597c352a2b8SStefan Gränitz
59885fb9976SLang Hames } // end anonymous namespace
5996a94134bSLang Hames
6006a94134bSLang Hames namespace llvm {
6016a94134bSLang Hames namespace orc {
6026a94134bSLang Hames
setInitTransform(LLJIT & J,IRTransformLayer::TransformFunction T)60385fb9976SLang Hames void LLJIT::PlatformSupport::setInitTransform(
60485fb9976SLang Hames LLJIT &J, IRTransformLayer::TransformFunction T) {
60585fb9976SLang Hames J.InitHelperTransformLayer->setTransform(std::move(T));
60685fb9976SLang Hames }
60785fb9976SLang Hames
6083a3cb929SKazu Hirata LLJIT::PlatformSupport::~PlatformSupport() = default;
60985fb9976SLang Hames
prepareForConstruction()610eb14dc75SLang Hames Error LLJITBuilderState::prepareForConstruction() {
611eb14dc75SLang Hames
6125bcd32b7SStefan Gränitz LLVM_DEBUG(dbgs() << "Preparing to create LLJIT instance...\n");
613ff92d3c6SLang Hames
614eb14dc75SLang Hames if (!JTMB) {
615ff92d3c6SLang Hames LLVM_DEBUG({
616ff92d3c6SLang Hames dbgs() << " No explicitly set JITTargetMachineBuilder. "
617ff92d3c6SLang Hames "Detecting host...\n";
618ff92d3c6SLang Hames });
619eb14dc75SLang Hames if (auto JTMBOrErr = JITTargetMachineBuilder::detectHost())
620eb14dc75SLang Hames JTMB = std::move(*JTMBOrErr);
621eb14dc75SLang Hames else
622eb14dc75SLang Hames return JTMBOrErr.takeError();
62307ac3145SLang Hames }
62467a1b7f0SLang Hames
625ff92d3c6SLang Hames LLVM_DEBUG({
6260469256dSLang Hames dbgs() << " JITTargetMachineBuilder is "
6270469256dSLang Hames << JITTargetMachineBuilderPrinter(*JTMB, " ")
628ff92d3c6SLang Hames << " Pre-constructed ExecutionSession: " << (ES ? "Yes" : "No")
629ff92d3c6SLang Hames << "\n"
630ff92d3c6SLang Hames << " DataLayout: ";
631ff92d3c6SLang Hames if (DL)
632ff92d3c6SLang Hames dbgs() << DL->getStringRepresentation() << "\n";
633ff92d3c6SLang Hames else
634ff92d3c6SLang Hames dbgs() << "None (will be created by JITTargetMachineBuilder)\n";
635ff92d3c6SLang Hames
636ff92d3c6SLang Hames dbgs() << " Custom object-linking-layer creator: "
637ff92d3c6SLang Hames << (CreateObjectLinkingLayer ? "Yes" : "No") << "\n"
638ff92d3c6SLang Hames << " Custom compile-function creator: "
639ff92d3c6SLang Hames << (CreateCompileFunction ? "Yes" : "No") << "\n"
640ff92d3c6SLang Hames << " Custom platform-setup function: "
641ff92d3c6SLang Hames << (SetUpPlatform ? "Yes" : "No") << "\n"
642ff92d3c6SLang Hames << " Number of compile threads: " << NumCompileThreads;
643ff92d3c6SLang Hames if (!NumCompileThreads)
644ff92d3c6SLang Hames dbgs() << " (code will be compiled on the execution thread)\n";
645ff92d3c6SLang Hames else
646ff92d3c6SLang Hames dbgs() << "\n";
647ff92d3c6SLang Hames });
648ff92d3c6SLang Hames
6492487db1fSLang Hames // If neither ES nor EPC has been set then create an EPC instance.
6502487db1fSLang Hames if (!ES && !EPC) {
6512487db1fSLang Hames LLVM_DEBUG({
6522487db1fSLang Hames dbgs() << "ExecutorProcessControl not specified, "
6532487db1fSLang Hames "Creating SelfExecutorProcessControl instance\n";
6542487db1fSLang Hames });
6552487db1fSLang Hames if (auto EPCOrErr = SelfExecutorProcessControl::Create())
6562487db1fSLang Hames EPC = std::move(*EPCOrErr);
6572487db1fSLang Hames else
6582487db1fSLang Hames return EPCOrErr.takeError();
6592487db1fSLang Hames } else
6602487db1fSLang Hames LLVM_DEBUG({
6612487db1fSLang Hames dbgs() << "Using explicitly specified ExecutorProcessControl instance "
6622487db1fSLang Hames << EPC.get() << "\n";
6632487db1fSLang Hames });
6642487db1fSLang Hames
66507ac3145SLang Hames // If the client didn't configure any linker options then auto-configure the
66607ac3145SLang Hames // JIT linker.
667e429cffdSLang Hames if (!CreateObjectLinkingLayer) {
66867a1b7f0SLang Hames auto &TT = JTMB->getTargetTriple();
669*a4e2c1f7SJonas Hahnfeld if (TT.getArch() == Triple::riscv64 ||
670*a4e2c1f7SJonas Hahnfeld (TT.isOSBinFormatMachO() &&
671*a4e2c1f7SJonas Hahnfeld (TT.getArch() == Triple::aarch64 || TT.getArch() == Triple::x86_64))) {
67267a1b7f0SLang Hames
67367a1b7f0SLang Hames JTMB->setRelocationModel(Reloc::PIC_);
67467a1b7f0SLang Hames JTMB->setCodeModel(CodeModel::Small);
67567a1b7f0SLang Hames CreateObjectLinkingLayer =
6762487db1fSLang Hames [](ExecutionSession &ES,
677cf905274SStefan Gränitz const Triple &) -> Expected<std::unique_ptr<ObjectLayer>> {
6782487db1fSLang Hames auto ObjLinkingLayer = std::make_unique<ObjectLinkingLayer>(ES);
6797266a8bfSLang Hames ObjLinkingLayer->addPlugin(std::make_unique<EHFrameRegistrationPlugin>(
6800aec49c8SLang Hames ES, std::make_unique<jitlink::InProcessEHFrameRegistrar>()));
681b7ce8fa9SJan Korous return std::move(ObjLinkingLayer);
68267a1b7f0SLang Hames };
68367a1b7f0SLang Hames }
684eb14dc75SLang Hames }
685eb14dc75SLang Hames
686eb14dc75SLang Hames return Error::success();
687eb14dc75SLang Hames }
688eb14dc75SLang Hames
~LLJIT()689f0a3fd88SLang Hames LLJIT::~LLJIT() {
690f0a3fd88SLang Hames if (CompileThreads)
691f0a3fd88SLang Hames CompileThreads->wait();
6920aec49c8SLang Hames if (auto Err = ES->endSession())
6930aec49c8SLang Hames ES->reportError(std::move(Err));
694f0a3fd88SLang Hames }
695f0a3fd88SLang Hames
addIRModule(ResourceTrackerSP RT,ThreadSafeModule TSM)69691d1f417SLang Hames Error LLJIT::addIRModule(ResourceTrackerSP RT, ThreadSafeModule TSM) {
6978d76c711SLang Hames assert(TSM && "Can not add null module");
6986a94134bSLang Hames
699809e9d1eSLang Hames if (auto Err =
700809e9d1eSLang Hames TSM.withModuleDo([&](Module &M) { return applyDataLayout(M); }))
7016a94134bSLang Hames return Err;
7026a94134bSLang Hames
70391d1f417SLang Hames return InitHelperTransformLayer->add(std::move(RT), std::move(TSM));
70491d1f417SLang Hames }
70591d1f417SLang Hames
addIRModule(JITDylib & JD,ThreadSafeModule TSM)70691d1f417SLang Hames Error LLJIT::addIRModule(JITDylib &JD, ThreadSafeModule TSM) {
70791d1f417SLang Hames return addIRModule(JD.getDefaultResourceTracker(), std::move(TSM));
70891d1f417SLang Hames }
70991d1f417SLang Hames
addObjectFile(ResourceTrackerSP RT,std::unique_ptr<MemoryBuffer> Obj)71091d1f417SLang Hames Error LLJIT::addObjectFile(ResourceTrackerSP RT,
71191d1f417SLang Hames std::unique_ptr<MemoryBuffer> Obj) {
71291d1f417SLang Hames assert(Obj && "Can not add null object");
71391d1f417SLang Hames
714a5eb9df1SStefan Gränitz return ObjTransformLayer->add(std::move(RT), std::move(Obj));
7156a94134bSLang Hames }
7166a94134bSLang Hames
addObjectFile(JITDylib & JD,std::unique_ptr<MemoryBuffer> Obj)71737a66413SLang Hames Error LLJIT::addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj) {
71891d1f417SLang Hames return addObjectFile(JD.getDefaultResourceTracker(), std::move(Obj));
71937a66413SLang Hames }
72037a66413SLang Hames
lookupLinkerMangled(JITDylib & JD,SymbolStringPtr Name)72116dcbb53SLang Hames Expected<ExecutorAddr> LLJIT::lookupLinkerMangled(JITDylib &JD,
7225877d6f5SLang Hames SymbolStringPtr Name) {
72316dcbb53SLang Hames if (auto Sym = ES->lookup(
72416dcbb53SLang Hames makeJITDylibSearchOrder(&JD, JITDylibLookupFlags::MatchAllSymbols),
72516dcbb53SLang Hames Name))
72616dcbb53SLang Hames return ExecutorAddr(Sym->getAddress());
72716dcbb53SLang Hames else
72816dcbb53SLang Hames return Sym.takeError();
7296a94134bSLang Hames }
7306a94134bSLang Hames
731cf905274SStefan Gränitz Expected<std::unique_ptr<ObjectLayer>>
createObjectLinkingLayer(LLJITBuilderState & S,ExecutionSession & ES)732eb14dc75SLang Hames LLJIT::createObjectLinkingLayer(LLJITBuilderState &S, ExecutionSession &ES) {
7336a94134bSLang Hames
734eb14dc75SLang Hames // If the config state provided an ObjectLinkingLayer factory then use it.
735eb14dc75SLang Hames if (S.CreateObjectLinkingLayer)
736cb391279SLang Hames return S.CreateObjectLinkingLayer(ES, S.JTMB->getTargetTriple());
737f0a3fd88SLang Hames
738eb14dc75SLang Hames // Otherwise default to creating an RTDyldObjectLinkingLayer that constructs
739eb14dc75SLang Hames // a new SectionMemoryManager for each object.
7400eaee545SJonas Devlieghere auto GetMemMgr = []() { return std::make_unique<SectionMemoryManager>(); };
741171849c2SStefan Gränitz auto Layer =
7420eaee545SJonas Devlieghere std::make_unique<RTDyldObjectLinkingLayer>(ES, std::move(GetMemMgr));
743cb391279SLang Hames
74484217ad6SLang Hames if (S.JTMB->getTargetTriple().isOSBinFormatCOFF()) {
745171849c2SStefan Gränitz Layer->setOverrideObjectFlagsWithResponsibilityFlags(true);
746171849c2SStefan Gränitz Layer->setAutoClaimResponsibilityForObjectSymbols(true);
74784217ad6SLang Hames }
748cb391279SLang Hames
7491707735fSLang Hames // FIXME: Explicit conversion to std::unique_ptr<ObjectLayer> added to silence
7501707735fSLang Hames // errors from some GCC / libstdc++ bots. Remove this conversion (i.e.
7511707735fSLang Hames // just return ObjLinkingLayer) once those bots are upgraded.
752171849c2SStefan Gränitz return std::unique_ptr<ObjectLayer>(std::move(Layer));
753eb14dc75SLang Hames }
7548b81395dSLang Hames
755ce2207abSLang Hames Expected<std::unique_ptr<IRCompileLayer::IRCompiler>>
createCompileFunction(LLJITBuilderState & S,JITTargetMachineBuilder JTMB)756843f198aSLang Hames LLJIT::createCompileFunction(LLJITBuilderState &S,
757843f198aSLang Hames JITTargetMachineBuilder JTMB) {
758843f198aSLang Hames
759843f198aSLang Hames /// If there is a custom compile function creator set then use it.
760843f198aSLang Hames if (S.CreateCompileFunction)
761843f198aSLang Hames return S.CreateCompileFunction(std::move(JTMB));
762843f198aSLang Hames
763843f198aSLang Hames // Otherwise default to creating a SimpleCompiler, or ConcurrentIRCompiler,
764843f198aSLang Hames // depending on the number of threads requested.
765843f198aSLang Hames if (S.NumCompileThreads > 0)
766ce2207abSLang Hames return std::make_unique<ConcurrentIRCompiler>(std::move(JTMB));
767843f198aSLang Hames
768843f198aSLang Hames auto TM = JTMB.createTargetMachine();
769843f198aSLang Hames if (!TM)
770843f198aSLang Hames return TM.takeError();
771843f198aSLang Hames
772ce2207abSLang Hames return std::make_unique<TMOwningSimpleCompiler>(std::move(*TM));
773843f198aSLang Hames }
774843f198aSLang Hames
LLJIT(LLJITBuilderState & S,Error & Err)775eb14dc75SLang Hames LLJIT::LLJIT(LLJITBuilderState &S, Error &Err)
7762487db1fSLang Hames : DL(""), TT(S.JTMB->getTargetTriple()) {
777eb14dc75SLang Hames
778eb14dc75SLang Hames ErrorAsOutParameter _(&Err);
779eb14dc75SLang Hames
7802487db1fSLang Hames assert(!(S.EPC && S.ES) && "EPC and ES should not both be set");
7812487db1fSLang Hames
7822487db1fSLang Hames if (S.EPC) {
7832487db1fSLang Hames ES = std::make_unique<ExecutionSession>(std::move(S.EPC));
7842487db1fSLang Hames } else if (S.ES)
7852487db1fSLang Hames ES = std::move(S.ES);
7862487db1fSLang Hames else {
7872487db1fSLang Hames if (auto EPC = SelfExecutorProcessControl::Create()) {
7882487db1fSLang Hames ES = std::make_unique<ExecutionSession>(std::move(*EPC));
7892487db1fSLang Hames } else {
7902487db1fSLang Hames Err = EPC.takeError();
7912487db1fSLang Hames return;
7922487db1fSLang Hames }
7932487db1fSLang Hames }
7942487db1fSLang Hames
79585fb9976SLang Hames if (auto MainOrErr = this->ES->createJITDylib("main"))
79685fb9976SLang Hames Main = &*MainOrErr;
79785fb9976SLang Hames else {
79885fb9976SLang Hames Err = MainOrErr.takeError();
79985fb9976SLang Hames return;
80085fb9976SLang Hames }
80185fb9976SLang Hames
80285fb9976SLang Hames if (S.DL)
80385fb9976SLang Hames DL = std::move(*S.DL);
80485fb9976SLang Hames else if (auto DLOrErr = S.JTMB->getDefaultDataLayoutForTarget())
805eb14dc75SLang Hames DL = std::move(*DLOrErr);
806eb14dc75SLang Hames else {
807eb14dc75SLang Hames Err = DLOrErr.takeError();
808eb14dc75SLang Hames return;
809eb14dc75SLang Hames }
810eb14dc75SLang Hames
811cf905274SStefan Gränitz auto ObjLayer = createObjectLinkingLayer(S, *ES);
812cf905274SStefan Gränitz if (!ObjLayer) {
813cf905274SStefan Gränitz Err = ObjLayer.takeError();
814cf905274SStefan Gränitz return;
815cf905274SStefan Gränitz }
816cf905274SStefan Gränitz ObjLinkingLayer = std::move(*ObjLayer);
817a5eb9df1SStefan Gränitz ObjTransformLayer =
818a5eb9df1SStefan Gränitz std::make_unique<ObjectTransformLayer>(*ES, *ObjLinkingLayer);
819a5eb9df1SStefan Gränitz
820eb14dc75SLang Hames {
821843f198aSLang Hames auto CompileFunction = createCompileFunction(S, std::move(*S.JTMB));
822843f198aSLang Hames if (!CompileFunction) {
823843f198aSLang Hames Err = CompileFunction.takeError();
824843f198aSLang Hames return;
825843f198aSLang Hames }
8260eaee545SJonas Devlieghere CompileLayer = std::make_unique<IRCompileLayer>(
827a5eb9df1SStefan Gränitz *ES, *ObjTransformLayer, std::move(*CompileFunction));
828c7518025SLang Hames TransformLayer = std::make_unique<IRTransformLayer>(*ES, *CompileLayer);
82985fb9976SLang Hames InitHelperTransformLayer =
83085fb9976SLang Hames std::make_unique<IRTransformLayer>(*ES, *TransformLayer);
831eb14dc75SLang Hames }
832eb14dc75SLang Hames
833843f198aSLang Hames if (S.NumCompileThreads > 0) {
83485fb9976SLang Hames InitHelperTransformLayer->setCloneToNewContextOnEmit(true);
8358404aeb5SAlexandre Ganea CompileThreads =
8368404aeb5SAlexandre Ganea std::make_unique<ThreadPool>(hardware_concurrency(S.NumCompileThreads));
8375344c88dSLang Hames ES->setDispatchTask([this](std::unique_ptr<Task> T) {
8387dcd0042SLang Hames // FIXME: We should be able to use move-capture here, but ThreadPool's
8397dcd0042SLang Hames // AsyncTaskTys are std::functions rather than unique_functions
8407dcd0042SLang Hames // (because MSVC's std::packaged_tasks don't support move-only types).
8417dcd0042SLang Hames // Fix this when all the above gets sorted out.
8425344c88dSLang Hames CompileThreads->async([UnownedT = T.release()]() mutable {
8435344c88dSLang Hames std::unique_ptr<Task> T(UnownedT);
8445344c88dSLang Hames T->run();
8457dcd0042SLang Hames });
846f0a3fd88SLang Hames });
847eb14dc75SLang Hames }
84885fb9976SLang Hames
84985fb9976SLang Hames if (S.SetUpPlatform)
85085fb9976SLang Hames Err = S.SetUpPlatform(*this);
85185fb9976SLang Hames else
85285fb9976SLang Hames setUpGenericLLVMIRPlatform(*this);
853f0a3fd88SLang Hames }
854f0a3fd88SLang Hames
mangle(StringRef UnmangledName) const8555877d6f5SLang Hames std::string LLJIT::mangle(StringRef UnmangledName) const {
8566a94134bSLang Hames std::string MangledName;
8576a94134bSLang Hames {
8586a94134bSLang Hames raw_string_ostream MangledNameStream(MangledName);
8596a94134bSLang Hames Mangler::getNameWithPrefix(MangledNameStream, UnmangledName, DL);
8606a94134bSLang Hames }
8616a94134bSLang Hames return MangledName;
8626a94134bSLang Hames }
8636a94134bSLang Hames
applyDataLayout(Module & M)8646a94134bSLang Hames Error LLJIT::applyDataLayout(Module &M) {
8656a94134bSLang Hames if (M.getDataLayout().isDefault())
8666a94134bSLang Hames M.setDataLayout(DL);
8676a94134bSLang Hames
8686a94134bSLang Hames if (M.getDataLayout() != DL)
8696a94134bSLang Hames return make_error<StringError>(
87085fb9976SLang Hames "Added modules have incompatible data layouts: " +
87185fb9976SLang Hames M.getDataLayout().getStringRepresentation() + " (module) vs " +
87285fb9976SLang Hames DL.getStringRepresentation() + " (jit)",
8736a94134bSLang Hames inconvertibleErrorCode());
8746a94134bSLang Hames
8756a94134bSLang Hames return Error::success();
8766a94134bSLang Hames }
8776a94134bSLang Hames
setUpGenericLLVMIRPlatform(LLJIT & J)87885fb9976SLang Hames void setUpGenericLLVMIRPlatform(LLJIT &J) {
8798363ff04SLang Hames LLVM_DEBUG(
8808363ff04SLang Hames { dbgs() << "Setting up GenericLLVMIRPlatform support for LLJIT\n"; });
88185fb9976SLang Hames J.setPlatformSupport(std::make_unique<GenericLLVMIRPlatformSupport>(J));
88285fb9976SLang Hames }
88385fb9976SLang Hames
setUpInactivePlatform(LLJIT & J)884c352a2b8SStefan Gränitz Error setUpInactivePlatform(LLJIT &J) {
885c352a2b8SStefan Gränitz LLVM_DEBUG(
886c352a2b8SStefan Gränitz { dbgs() << "Explicitly deactivated platform support for LLJIT\n"; });
887c352a2b8SStefan Gränitz J.setPlatformSupport(std::make_unique<InactivePlatformSupport>());
888c352a2b8SStefan Gränitz return Error::success();
889c352a2b8SStefan Gränitz }
890c352a2b8SStefan Gränitz
prepareForConstruction()891eb14dc75SLang Hames Error LLLazyJITBuilderState::prepareForConstruction() {
892eb14dc75SLang Hames if (auto Err = LLJITBuilderState::prepareForConstruction())
893eb14dc75SLang Hames return Err;
894eb14dc75SLang Hames TT = JTMB->getTargetTriple();
895eb14dc75SLang Hames return Error::success();
896225a32afSLang Hames }
897225a32afSLang Hames
addLazyIRModule(JITDylib & JD,ThreadSafeModule TSM)8988d76c711SLang Hames Error LLLazyJIT::addLazyIRModule(JITDylib &JD, ThreadSafeModule TSM) {
8998d76c711SLang Hames assert(TSM && "Can not add null module");
9006a94134bSLang Hames
90185fb9976SLang Hames if (auto Err = TSM.withModuleDo(
90285fb9976SLang Hames [&](Module &M) -> Error { return applyDataLayout(M); }))
903809e9d1eSLang Hames return Err;
9046a94134bSLang Hames
9050aec49c8SLang Hames return CODLayer->add(JD, std::move(TSM));
9066a94134bSLang Hames }
9076a94134bSLang Hames
LLLazyJIT(LLLazyJITBuilderState & S,Error & Err)908eb14dc75SLang Hames LLLazyJIT::LLLazyJIT(LLLazyJITBuilderState &S, Error &Err) : LLJIT(S, Err) {
9096a94134bSLang Hames
910eb14dc75SLang Hames // If LLJIT construction failed then bail out.
911eb14dc75SLang Hames if (Err)
912eb14dc75SLang Hames return;
913eb14dc75SLang Hames
914eb14dc75SLang Hames ErrorAsOutParameter _(&Err);
915eb14dc75SLang Hames
916eb14dc75SLang Hames /// Take/Create the lazy-compile callthrough manager.
917eb14dc75SLang Hames if (S.LCTMgr)
918eb14dc75SLang Hames LCTMgr = std::move(S.LCTMgr);
919eb14dc75SLang Hames else {
920eb14dc75SLang Hames if (auto LCTMgrOrErr = createLocalLazyCallThroughManager(
92116dcbb53SLang Hames S.TT, *ES, S.LazyCompileFailureAddr.getValue()))
922eb14dc75SLang Hames LCTMgr = std::move(*LCTMgrOrErr);
923eb14dc75SLang Hames else {
924eb14dc75SLang Hames Err = LCTMgrOrErr.takeError();
925eb14dc75SLang Hames return;
926eb14dc75SLang Hames }
927eb14dc75SLang Hames }
928eb14dc75SLang Hames
929eb14dc75SLang Hames // Take/Create the indirect stubs manager builder.
930eb14dc75SLang Hames auto ISMBuilder = std::move(S.ISMBuilder);
931eb14dc75SLang Hames
932eb14dc75SLang Hames // If none was provided, try to build one.
933eb14dc75SLang Hames if (!ISMBuilder)
934eb14dc75SLang Hames ISMBuilder = createLocalIndirectStubsManagerBuilder(S.TT);
935eb14dc75SLang Hames
936eb14dc75SLang Hames // No luck. Bail out.
937eb14dc75SLang Hames if (!ISMBuilder) {
938eb14dc75SLang Hames Err = make_error<StringError>("Could not construct "
939eb14dc75SLang Hames "IndirectStubsManagerBuilder for target " +
940eb14dc75SLang Hames S.TT.str(),
941eb14dc75SLang Hames inconvertibleErrorCode());
942eb14dc75SLang Hames return;
943eb14dc75SLang Hames }
944eb14dc75SLang Hames
945eb14dc75SLang Hames // Create the COD layer.
9460eaee545SJonas Devlieghere CODLayer = std::make_unique<CompileOnDemandLayer>(
94785fb9976SLang Hames *ES, *InitHelperTransformLayer, *LCTMgr, std::move(ISMBuilder));
948eb14dc75SLang Hames
949eb14dc75SLang Hames if (S.NumCompileThreads > 0)
950eb14dc75SLang Hames CODLayer->setCloneToNewContextOnEmit(true);
9518b81395dSLang Hames }
952f0a3fd88SLang Hames
9536a94134bSLang Hames } // End namespace orc.
9546a94134bSLang Hames } // End namespace llvm.
955