|  | //===--------- 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/Analysis/TargetLibraryInfo.h" | 
|  | #include "llvm/Config/llvm-config.h" // for LLVM_ENABLE_THREADS | 
|  | #include "llvm/ExecutionEngine/Orc/COFFPlatform.h" | 
|  | #include "llvm/ExecutionEngine/Orc/EHFrameRegistrationPlugin.h" | 
|  | #include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h" | 
|  | #include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h" | 
|  | #include "llvm/ExecutionEngine/Orc/EPCEHFrameRegistrar.h" | 
|  | #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h" | 
|  | #include "llvm/ExecutionEngine/Orc/MachOPlatform.h" | 
|  | #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" | 
|  | #include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h" | 
|  | #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" | 
|  | #include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h" | 
|  | #include "llvm/ExecutionEngine/Orc/UnwindInfoRegistrationPlugin.h" | 
|  | #include "llvm/ExecutionEngine/SectionMemoryManager.h" | 
|  | #include "llvm/IR/GlobalVariable.h" | 
|  | #include "llvm/IR/IRBuilder.h" | 
|  | #include "llvm/IR/Mangler.h" | 
|  | #include "llvm/IR/Module.h" | 
|  | #include "llvm/Support/DynamicLibrary.h" | 
|  |  | 
|  | #define DEBUG_TYPE "orc" | 
|  |  | 
|  | using namespace llvm; | 
|  | using namespace llvm::orc; | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | /// Adds helper function decls and wrapper functions that call the helper with | 
|  | /// some additional prefix arguments. | 
|  | /// | 
|  | /// E.g. For wrapper "foo" with type i8(i8, i64), helper "bar", and prefix | 
|  | /// args i32 4 and i16 12345, this function will add: | 
|  | /// | 
|  | /// declare i8 @bar(i32, i16, i8, i64) | 
|  | /// | 
|  | /// define i8 @foo(i8, i64) { | 
|  | /// entry: | 
|  | ///   %2 = call i8 @bar(i32 4, i16 12345, i8 %0, i64 %1) | 
|  | ///   ret i8 %2 | 
|  | /// } | 
|  | /// | 
|  | Function *addHelperAndWrapper(Module &M, StringRef WrapperName, | 
|  | FunctionType *WrapperFnType, | 
|  | GlobalValue::VisibilityTypes WrapperVisibility, | 
|  | StringRef HelperName, | 
|  | ArrayRef<Value *> HelperPrefixArgs) { | 
|  | std::vector<Type *> HelperArgTypes; | 
|  | for (auto *Arg : HelperPrefixArgs) | 
|  | HelperArgTypes.push_back(Arg->getType()); | 
|  | for (auto *T : WrapperFnType->params()) | 
|  | HelperArgTypes.push_back(T); | 
|  | auto *HelperFnType = | 
|  | FunctionType::get(WrapperFnType->getReturnType(), HelperArgTypes, false); | 
|  | auto *HelperFn = Function::Create(HelperFnType, GlobalValue::ExternalLinkage, | 
|  | HelperName, M); | 
|  |  | 
|  | auto *WrapperFn = Function::Create( | 
|  | WrapperFnType, GlobalValue::ExternalLinkage, WrapperName, M); | 
|  | WrapperFn->setVisibility(WrapperVisibility); | 
|  |  | 
|  | auto *EntryBlock = BasicBlock::Create(M.getContext(), "entry", WrapperFn); | 
|  | IRBuilder<> IB(EntryBlock); | 
|  |  | 
|  | std::vector<Value *> HelperArgs; | 
|  | for (auto *Arg : HelperPrefixArgs) | 
|  | HelperArgs.push_back(Arg); | 
|  | for (auto &Arg : WrapperFn->args()) | 
|  | HelperArgs.push_back(&Arg); | 
|  | auto *HelperResult = IB.CreateCall(HelperFn, HelperArgs); | 
|  | if (HelperFn->getReturnType()->isVoidTy()) | 
|  | IB.CreateRetVoid(); | 
|  | else | 
|  | IB.CreateRet(HelperResult); | 
|  |  | 
|  | return WrapperFn; | 
|  | } | 
|  |  | 
|  | class GenericLLVMIRPlatformSupport; | 
|  |  | 
|  | /// orc::Platform component of Generic LLVM IR Platform support. | 
|  | /// Just forwards calls to the GenericLLVMIRPlatformSupport class below. | 
|  | class GenericLLVMIRPlatform : public Platform { | 
|  | public: | 
|  | GenericLLVMIRPlatform(GenericLLVMIRPlatformSupport &S) : S(S) {} | 
|  | Error setupJITDylib(JITDylib &JD) override; | 
|  | Error teardownJITDylib(JITDylib &JD) override; | 
|  | Error notifyAdding(ResourceTracker &RT, | 
|  | const MaterializationUnit &MU) override; | 
|  | Error notifyRemoving(ResourceTracker &RT) override { | 
|  | // Noop -- Nothing to do (yet). | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | private: | 
|  | GenericLLVMIRPlatformSupport &S; | 
|  | }; | 
|  |  | 
|  | /// This transform parses llvm.global_ctors to produce a single initialization | 
|  | /// function for the module, records the function, then deletes | 
|  | /// llvm.global_ctors. | 
|  | class GlobalCtorDtorScraper { | 
|  | public: | 
|  | GlobalCtorDtorScraper(GenericLLVMIRPlatformSupport &PS, | 
|  | StringRef InitFunctionPrefix, | 
|  | StringRef DeInitFunctionPrefix) | 
|  | : PS(PS), InitFunctionPrefix(InitFunctionPrefix), | 
|  | DeInitFunctionPrefix(DeInitFunctionPrefix) {} | 
|  | Expected<ThreadSafeModule> operator()(ThreadSafeModule TSM, | 
|  | MaterializationResponsibility &R); | 
|  |  | 
|  | private: | 
|  | GenericLLVMIRPlatformSupport &PS; | 
|  | StringRef InitFunctionPrefix; | 
|  | StringRef DeInitFunctionPrefix; | 
|  | }; | 
|  |  | 
|  | /// Generic IR Platform Support | 
|  | /// | 
|  | /// Scrapes llvm.global_ctors and llvm.global_dtors and replaces them with | 
|  | /// specially named 'init' and 'deinit'. Injects definitions / interposes for | 
|  | /// some runtime API, including __cxa_atexit, dlopen, and dlclose. | 
|  | class GenericLLVMIRPlatformSupport : public LLJIT::PlatformSupport { | 
|  | public: | 
|  | GenericLLVMIRPlatformSupport(LLJIT &J, JITDylib &PlatformJD) | 
|  | : J(J), InitFunctionPrefix(J.mangle("__orc_init_func.")), | 
|  | DeInitFunctionPrefix(J.mangle("__orc_deinit_func.")) { | 
|  |  | 
|  | getExecutionSession().setPlatform( | 
|  | std::make_unique<GenericLLVMIRPlatform>(*this)); | 
|  |  | 
|  | setInitTransform(J, GlobalCtorDtorScraper(*this, InitFunctionPrefix, | 
|  | DeInitFunctionPrefix)); | 
|  |  | 
|  | SymbolMap StdInterposes; | 
|  |  | 
|  | StdInterposes[J.mangleAndIntern("__lljit.platform_support_instance")] = { | 
|  | ExecutorAddr::fromPtr(this), JITSymbolFlags::Exported}; | 
|  | StdInterposes[J.mangleAndIntern("__lljit.cxa_atexit_helper")] = { | 
|  | ExecutorAddr::fromPtr(registerCxaAtExitHelper), JITSymbolFlags()}; | 
|  |  | 
|  | cantFail(PlatformJD.define(absoluteSymbols(std::move(StdInterposes)))); | 
|  | cantFail(setupJITDylib(PlatformJD)); | 
|  | cantFail(J.addIRModule(PlatformJD, createPlatformRuntimeModule())); | 
|  | } | 
|  |  | 
|  | ExecutionSession &getExecutionSession() { return J.getExecutionSession(); } | 
|  |  | 
|  | /// Adds a module that defines the __dso_handle global. | 
|  | Error setupJITDylib(JITDylib &JD) { | 
|  |  | 
|  | // Add per-jitdylib standard interposes. | 
|  | SymbolMap PerJDInterposes; | 
|  | PerJDInterposes[J.mangleAndIntern("__lljit.run_atexits_helper")] = { | 
|  | ExecutorAddr::fromPtr(runAtExitsHelper), JITSymbolFlags()}; | 
|  | PerJDInterposes[J.mangleAndIntern("__lljit.atexit_helper")] = { | 
|  | ExecutorAddr::fromPtr(registerAtExitHelper), JITSymbolFlags()}; | 
|  | cantFail(JD.define(absoluteSymbols(std::move(PerJDInterposes)))); | 
|  |  | 
|  | auto Ctx = std::make_unique<LLVMContext>(); | 
|  | auto M = std::make_unique<Module>("__standard_lib", *Ctx); | 
|  | M->setDataLayout(J.getDataLayout()); | 
|  |  | 
|  | auto *Int64Ty = Type::getInt64Ty(*Ctx); | 
|  | auto *DSOHandle = new GlobalVariable( | 
|  | *M, Int64Ty, true, GlobalValue::ExternalLinkage, | 
|  | ConstantInt::get(Int64Ty, reinterpret_cast<uintptr_t>(&JD)), | 
|  | "__dso_handle"); | 
|  | DSOHandle->setVisibility(GlobalValue::DefaultVisibility); | 
|  | DSOHandle->setInitializer( | 
|  | ConstantInt::get(Int64Ty, ExecutorAddr::fromPtr(&JD).getValue())); | 
|  |  | 
|  | auto *GenericIRPlatformSupportTy = | 
|  | StructType::create(*Ctx, "lljit.GenericLLJITIRPlatformSupport"); | 
|  |  | 
|  | auto *PlatformInstanceDecl = new GlobalVariable( | 
|  | *M, GenericIRPlatformSupportTy, true, GlobalValue::ExternalLinkage, | 
|  | nullptr, "__lljit.platform_support_instance"); | 
|  |  | 
|  | auto *VoidTy = Type::getVoidTy(*Ctx); | 
|  | addHelperAndWrapper( | 
|  | *M, "__lljit_run_atexits", FunctionType::get(VoidTy, {}, false), | 
|  | GlobalValue::HiddenVisibility, "__lljit.run_atexits_helper", | 
|  | {PlatformInstanceDecl, DSOHandle}); | 
|  |  | 
|  | auto *IntTy = Type::getIntNTy(*Ctx, sizeof(int) * CHAR_BIT); | 
|  | auto *AtExitCallbackPtrTy = PointerType::getUnqual(*Ctx); | 
|  | auto *AtExit = addHelperAndWrapper( | 
|  | *M, "atexit", FunctionType::get(IntTy, {AtExitCallbackPtrTy}, false), | 
|  | GlobalValue::HiddenVisibility, "__lljit.atexit_helper", | 
|  | {PlatformInstanceDecl, DSOHandle}); | 
|  | Attribute::AttrKind AtExitExtAttr = | 
|  | TargetLibraryInfo::getExtAttrForI32Return(J.getTargetTriple()); | 
|  | if (AtExitExtAttr != Attribute::None) | 
|  | AtExit->addRetAttr(AtExitExtAttr); | 
|  |  | 
|  | return J.addIRModule(JD, ThreadSafeModule(std::move(M), std::move(Ctx))); | 
|  | } | 
|  |  | 
|  | Error notifyAdding(ResourceTracker &RT, const MaterializationUnit &MU) { | 
|  | auto &JD = RT.getJITDylib(); | 
|  | if (auto &InitSym = MU.getInitializerSymbol()) | 
|  | InitSymbols[&JD].add(InitSym, SymbolLookupFlags::WeaklyReferencedSymbol); | 
|  | else { | 
|  | // If there's no identified init symbol attached, but there is a symbol | 
|  | // with the GenericIRPlatform::InitFunctionPrefix, then treat that as | 
|  | // an init function. Add the symbol to both the InitSymbols map (which | 
|  | // will trigger a lookup to materialize the module) and the InitFunctions | 
|  | // map (which holds the names of the symbols to execute). | 
|  | for (auto &KV : MU.getSymbols()) | 
|  | if ((*KV.first).starts_with(InitFunctionPrefix)) { | 
|  | InitSymbols[&JD].add(KV.first, | 
|  | SymbolLookupFlags::WeaklyReferencedSymbol); | 
|  | InitFunctions[&JD].add(KV.first); | 
|  | } else if ((*KV.first).starts_with(DeInitFunctionPrefix)) { | 
|  | DeInitFunctions[&JD].add(KV.first); | 
|  | } | 
|  | } | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error initialize(JITDylib &JD) override { | 
|  | LLVM_DEBUG({ | 
|  | dbgs() << "GenericLLVMIRPlatformSupport getting initializers to run\n"; | 
|  | }); | 
|  | if (auto Initializers = getInitializers(JD)) { | 
|  | LLVM_DEBUG( | 
|  | { dbgs() << "GenericLLVMIRPlatformSupport running initializers\n"; }); | 
|  | for (auto InitFnAddr : *Initializers) { | 
|  | LLVM_DEBUG({ | 
|  | dbgs() << "  Running init " << formatv("{0:x16}", InitFnAddr) | 
|  | << "...\n"; | 
|  | }); | 
|  | auto *InitFn = InitFnAddr.toPtr<void (*)()>(); | 
|  | InitFn(); | 
|  | } | 
|  | } else | 
|  | return Initializers.takeError(); | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error deinitialize(JITDylib &JD) override { | 
|  | LLVM_DEBUG({ | 
|  | dbgs() << "GenericLLVMIRPlatformSupport getting deinitializers to run\n"; | 
|  | }); | 
|  | if (auto Deinitializers = getDeinitializers(JD)) { | 
|  | LLVM_DEBUG({ | 
|  | dbgs() << "GenericLLVMIRPlatformSupport running deinitializers\n"; | 
|  | }); | 
|  | for (auto DeinitFnAddr : *Deinitializers) { | 
|  | LLVM_DEBUG({ | 
|  | dbgs() << "  Running deinit " << formatv("{0:x16}", DeinitFnAddr) | 
|  | << "...\n"; | 
|  | }); | 
|  | auto *DeinitFn = DeinitFnAddr.toPtr<void (*)()>(); | 
|  | DeinitFn(); | 
|  | } | 
|  | } else | 
|  | return Deinitializers.takeError(); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | void registerInitFunc(JITDylib &JD, SymbolStringPtr InitName) { | 
|  | getExecutionSession().runSessionLocked([&]() { | 
|  | InitFunctions[&JD].add(InitName); | 
|  | }); | 
|  | } | 
|  |  | 
|  | void registerDeInitFunc(JITDylib &JD, SymbolStringPtr DeInitName) { | 
|  | getExecutionSession().runSessionLocked( | 
|  | [&]() { DeInitFunctions[&JD].add(DeInitName); }); | 
|  | } | 
|  |  | 
|  | private: | 
|  | Expected<std::vector<ExecutorAddr>> getInitializers(JITDylib &JD) { | 
|  | if (auto Err = issueInitLookups(JD)) | 
|  | return std::move(Err); | 
|  |  | 
|  | DenseMap<JITDylib *, SymbolLookupSet> LookupSymbols; | 
|  | std::vector<JITDylibSP> DFSLinkOrder; | 
|  |  | 
|  | if (auto Err = getExecutionSession().runSessionLocked([&]() -> Error { | 
|  | if (auto DFSLinkOrderOrErr = JD.getDFSLinkOrder()) | 
|  | DFSLinkOrder = std::move(*DFSLinkOrderOrErr); | 
|  | else | 
|  | return DFSLinkOrderOrErr.takeError(); | 
|  |  | 
|  | for (auto &NextJD : DFSLinkOrder) { | 
|  | auto IFItr = InitFunctions.find(NextJD.get()); | 
|  | if (IFItr != InitFunctions.end()) { | 
|  | LookupSymbols[NextJD.get()] = std::move(IFItr->second); | 
|  | InitFunctions.erase(IFItr); | 
|  | } | 
|  | } | 
|  | return Error::success(); | 
|  | })) | 
|  | return std::move(Err); | 
|  |  | 
|  | LLVM_DEBUG({ | 
|  | dbgs() << "JITDylib init order is [ "; | 
|  | for (auto &JD : llvm::reverse(DFSLinkOrder)) | 
|  | dbgs() << "\"" << JD->getName() << "\" "; | 
|  | dbgs() << "]\n"; | 
|  | dbgs() << "Looking up init functions:\n"; | 
|  | for (auto &KV : LookupSymbols) | 
|  | dbgs() << "  \"" << KV.first->getName() << "\": " << KV.second << "\n"; | 
|  | }); | 
|  |  | 
|  | auto &ES = getExecutionSession(); | 
|  | auto LookupResult = Platform::lookupInitSymbols(ES, LookupSymbols); | 
|  |  | 
|  | if (!LookupResult) | 
|  | return LookupResult.takeError(); | 
|  |  | 
|  | std::vector<ExecutorAddr> Initializers; | 
|  | while (!DFSLinkOrder.empty()) { | 
|  | auto &NextJD = *DFSLinkOrder.back(); | 
|  | DFSLinkOrder.pop_back(); | 
|  | auto InitsItr = LookupResult->find(&NextJD); | 
|  | if (InitsItr == LookupResult->end()) | 
|  | continue; | 
|  | for (auto &KV : InitsItr->second) | 
|  | Initializers.push_back(KV.second.getAddress()); | 
|  | } | 
|  |  | 
|  | return Initializers; | 
|  | } | 
|  |  | 
|  | Expected<std::vector<ExecutorAddr>> getDeinitializers(JITDylib &JD) { | 
|  | auto &ES = getExecutionSession(); | 
|  |  | 
|  | auto LLJITRunAtExits = J.mangleAndIntern("__lljit_run_atexits"); | 
|  |  | 
|  | DenseMap<JITDylib *, SymbolLookupSet> LookupSymbols; | 
|  | std::vector<JITDylibSP> DFSLinkOrder; | 
|  |  | 
|  | if (auto Err = ES.runSessionLocked([&]() -> Error { | 
|  | if (auto DFSLinkOrderOrErr = JD.getDFSLinkOrder()) | 
|  | DFSLinkOrder = std::move(*DFSLinkOrderOrErr); | 
|  | else | 
|  | return DFSLinkOrderOrErr.takeError(); | 
|  |  | 
|  | for (auto &NextJD : DFSLinkOrder) { | 
|  | auto &JDLookupSymbols = LookupSymbols[NextJD.get()]; | 
|  | auto DIFItr = DeInitFunctions.find(NextJD.get()); | 
|  | if (DIFItr != DeInitFunctions.end()) { | 
|  | LookupSymbols[NextJD.get()] = std::move(DIFItr->second); | 
|  | DeInitFunctions.erase(DIFItr); | 
|  | } | 
|  | JDLookupSymbols.add(LLJITRunAtExits, | 
|  | SymbolLookupFlags::WeaklyReferencedSymbol); | 
|  | } | 
|  | return Error::success(); | 
|  | })) | 
|  | return std::move(Err); | 
|  |  | 
|  | LLVM_DEBUG({ | 
|  | dbgs() << "JITDylib deinit order is [ "; | 
|  | for (auto &JD : DFSLinkOrder) | 
|  | dbgs() << "\"" << JD->getName() << "\" "; | 
|  | dbgs() << "]\n"; | 
|  | dbgs() << "Looking up deinit functions:\n"; | 
|  | for (auto &KV : LookupSymbols) | 
|  | dbgs() << "  \"" << KV.first->getName() << "\": " << KV.second << "\n"; | 
|  | }); | 
|  |  | 
|  | auto LookupResult = Platform::lookupInitSymbols(ES, LookupSymbols); | 
|  |  | 
|  | if (!LookupResult) | 
|  | return LookupResult.takeError(); | 
|  |  | 
|  | std::vector<ExecutorAddr> DeInitializers; | 
|  | for (auto &NextJD : DFSLinkOrder) { | 
|  | auto DeInitsItr = LookupResult->find(NextJD.get()); | 
|  | assert(DeInitsItr != LookupResult->end() && | 
|  | "Every JD should have at least __lljit_run_atexits"); | 
|  |  | 
|  | auto RunAtExitsItr = DeInitsItr->second.find(LLJITRunAtExits); | 
|  | if (RunAtExitsItr != DeInitsItr->second.end()) | 
|  | DeInitializers.push_back(RunAtExitsItr->second.getAddress()); | 
|  |  | 
|  | for (auto &KV : DeInitsItr->second) | 
|  | if (KV.first != LLJITRunAtExits) | 
|  | DeInitializers.push_back(KV.second.getAddress()); | 
|  | } | 
|  |  | 
|  | return DeInitializers; | 
|  | } | 
|  |  | 
|  | /// Issue lookups for all init symbols required to initialize JD (and any | 
|  | /// JITDylibs that it depends on). | 
|  | Error issueInitLookups(JITDylib &JD) { | 
|  | DenseMap<JITDylib *, SymbolLookupSet> RequiredInitSymbols; | 
|  | std::vector<JITDylibSP> DFSLinkOrder; | 
|  |  | 
|  | if (auto Err = getExecutionSession().runSessionLocked([&]() -> Error { | 
|  | if (auto DFSLinkOrderOrErr = JD.getDFSLinkOrder()) | 
|  | DFSLinkOrder = std::move(*DFSLinkOrderOrErr); | 
|  | else | 
|  | return DFSLinkOrderOrErr.takeError(); | 
|  |  | 
|  | for (auto &NextJD : DFSLinkOrder) { | 
|  | auto ISItr = InitSymbols.find(NextJD.get()); | 
|  | if (ISItr != InitSymbols.end()) { | 
|  | RequiredInitSymbols[NextJD.get()] = std::move(ISItr->second); | 
|  | InitSymbols.erase(ISItr); | 
|  | } | 
|  | } | 
|  | return Error::success(); | 
|  | })) | 
|  | return Err; | 
|  |  | 
|  | return Platform::lookupInitSymbols(getExecutionSession(), | 
|  | RequiredInitSymbols) | 
|  | .takeError(); | 
|  | } | 
|  |  | 
|  | static void registerCxaAtExitHelper(void *Self, void (*F)(void *), void *Ctx, | 
|  | void *DSOHandle) { | 
|  | LLVM_DEBUG({ | 
|  | dbgs() << "Registering cxa atexit function " << (void *)F << " for JD " | 
|  | << (*static_cast<JITDylib **>(DSOHandle))->getName() << "\n"; | 
|  | }); | 
|  | static_cast<GenericLLVMIRPlatformSupport *>(Self)->AtExitMgr.registerAtExit( | 
|  | F, Ctx, DSOHandle); | 
|  | } | 
|  |  | 
|  | static void registerAtExitHelper(void *Self, void *DSOHandle, void (*F)()) { | 
|  | LLVM_DEBUG({ | 
|  | dbgs() << "Registering atexit function " << (void *)F << " for JD " | 
|  | << (*static_cast<JITDylib **>(DSOHandle))->getName() << "\n"; | 
|  | }); | 
|  | static_cast<GenericLLVMIRPlatformSupport *>(Self)->AtExitMgr.registerAtExit( | 
|  | reinterpret_cast<void (*)(void *)>(F), nullptr, DSOHandle); | 
|  | } | 
|  |  | 
|  | static void runAtExitsHelper(void *Self, void *DSOHandle) { | 
|  | LLVM_DEBUG({ | 
|  | dbgs() << "Running atexit functions for JD " | 
|  | << (*static_cast<JITDylib **>(DSOHandle))->getName() << "\n"; | 
|  | }); | 
|  | static_cast<GenericLLVMIRPlatformSupport *>(Self)->AtExitMgr.runAtExits( | 
|  | DSOHandle); | 
|  | } | 
|  |  | 
|  | // Constructs an LLVM IR module containing platform runtime globals, | 
|  | // functions, and interposes. | 
|  | ThreadSafeModule createPlatformRuntimeModule() { | 
|  | auto Ctx = std::make_unique<LLVMContext>(); | 
|  | auto M = std::make_unique<Module>("__standard_lib", *Ctx); | 
|  | M->setDataLayout(J.getDataLayout()); | 
|  |  | 
|  | auto *GenericIRPlatformSupportTy = | 
|  | StructType::create(*Ctx, "lljit.GenericLLJITIRPlatformSupport"); | 
|  |  | 
|  | auto *PlatformInstanceDecl = new GlobalVariable( | 
|  | *M, GenericIRPlatformSupportTy, true, GlobalValue::ExternalLinkage, | 
|  | nullptr, "__lljit.platform_support_instance"); | 
|  |  | 
|  | auto *IntTy = Type::getIntNTy(*Ctx, sizeof(int) * CHAR_BIT); | 
|  | auto *BytePtrTy = PointerType::getUnqual(*Ctx); | 
|  | auto *CxaAtExitCallbackPtrTy = PointerType::getUnqual(*Ctx); | 
|  |  | 
|  | auto *CxaAtExit = addHelperAndWrapper( | 
|  | *M, "__cxa_atexit", | 
|  | FunctionType::get(IntTy, {CxaAtExitCallbackPtrTy, BytePtrTy, BytePtrTy}, | 
|  | false), | 
|  | GlobalValue::DefaultVisibility, "__lljit.cxa_atexit_helper", | 
|  | {PlatformInstanceDecl}); | 
|  | Attribute::AttrKind CxaAtExitExtAttr = | 
|  | TargetLibraryInfo::getExtAttrForI32Return(J.getTargetTriple()); | 
|  | if (CxaAtExitExtAttr != Attribute::None) | 
|  | CxaAtExit->addRetAttr(CxaAtExitExtAttr); | 
|  |  | 
|  | return ThreadSafeModule(std::move(M), std::move(Ctx)); | 
|  | } | 
|  |  | 
|  | LLJIT &J; | 
|  | std::string InitFunctionPrefix; | 
|  | std::string DeInitFunctionPrefix; | 
|  | DenseMap<JITDylib *, SymbolLookupSet> InitSymbols; | 
|  | DenseMap<JITDylib *, SymbolLookupSet> InitFunctions; | 
|  | DenseMap<JITDylib *, SymbolLookupSet> DeInitFunctions; | 
|  | ItaniumCXAAtExitSupport AtExitMgr; | 
|  | }; | 
|  |  | 
|  | Error GenericLLVMIRPlatform::setupJITDylib(JITDylib &JD) { | 
|  | return S.setupJITDylib(JD); | 
|  | } | 
|  |  | 
|  | Error GenericLLVMIRPlatform::teardownJITDylib(JITDylib &JD) { | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error GenericLLVMIRPlatform::notifyAdding(ResourceTracker &RT, | 
|  | const MaterializationUnit &MU) { | 
|  | return S.notifyAdding(RT, MU); | 
|  | } | 
|  |  | 
|  | Expected<ThreadSafeModule> | 
|  | GlobalCtorDtorScraper::operator()(ThreadSafeModule TSM, | 
|  | MaterializationResponsibility &R) { | 
|  | auto Err = TSM.withModuleDo([&](Module &M) -> Error { | 
|  | auto &Ctx = M.getContext(); | 
|  | auto *GlobalCtors = M.getNamedGlobal("llvm.global_ctors"); | 
|  | auto *GlobalDtors = M.getNamedGlobal("llvm.global_dtors"); | 
|  |  | 
|  | auto RegisterCOrDtors = [&](GlobalVariable *GlobalCOrDtors, | 
|  | bool isCtor) -> Error { | 
|  | // If there's no llvm.global_c/dtor or it's just a decl then skip. | 
|  | if (!GlobalCOrDtors || GlobalCOrDtors->isDeclaration()) | 
|  | return Error::success(); | 
|  | std::string InitOrDeInitFunctionName; | 
|  | if (isCtor) | 
|  | raw_string_ostream(InitOrDeInitFunctionName) | 
|  | << InitFunctionPrefix << M.getModuleIdentifier(); | 
|  | else | 
|  | raw_string_ostream(InitOrDeInitFunctionName) | 
|  | << DeInitFunctionPrefix << M.getModuleIdentifier(); | 
|  |  | 
|  | MangleAndInterner Mangle(PS.getExecutionSession(), M.getDataLayout()); | 
|  | auto InternedInitOrDeInitName = Mangle(InitOrDeInitFunctionName); | 
|  | if (auto Err = R.defineMaterializing( | 
|  | {{InternedInitOrDeInitName, JITSymbolFlags::Callable}})) | 
|  | return Err; | 
|  |  | 
|  | auto *InitOrDeInitFunc = Function::Create( | 
|  | FunctionType::get(Type::getVoidTy(Ctx), {}, false), | 
|  | GlobalValue::ExternalLinkage, InitOrDeInitFunctionName, &M); | 
|  | InitOrDeInitFunc->setVisibility(GlobalValue::HiddenVisibility); | 
|  | std::vector<std::pair<Function *, unsigned>> InitsOrDeInits; | 
|  | auto COrDtors = isCtor ? getConstructors(M) : getDestructors(M); | 
|  |  | 
|  | for (auto E : COrDtors) | 
|  | InitsOrDeInits.push_back(std::make_pair(E.Func, E.Priority)); | 
|  | llvm::stable_sort(InitsOrDeInits, llvm::less_second()); | 
|  |  | 
|  | auto *InitOrDeInitFuncEntryBlock = | 
|  | BasicBlock::Create(Ctx, "entry", InitOrDeInitFunc); | 
|  | IRBuilder<> IB(InitOrDeInitFuncEntryBlock); | 
|  | for (auto &KV : InitsOrDeInits) | 
|  | IB.CreateCall(KV.first); | 
|  | IB.CreateRetVoid(); | 
|  |  | 
|  | if (isCtor) | 
|  | PS.registerInitFunc(R.getTargetJITDylib(), InternedInitOrDeInitName); | 
|  | else | 
|  | PS.registerDeInitFunc(R.getTargetJITDylib(), InternedInitOrDeInitName); | 
|  |  | 
|  | GlobalCOrDtors->eraseFromParent(); | 
|  | return Error::success(); | 
|  | }; | 
|  |  | 
|  | if (auto Err = RegisterCOrDtors(GlobalCtors, true)) | 
|  | return Err; | 
|  | if (auto Err = RegisterCOrDtors(GlobalDtors, false)) | 
|  | return Err; | 
|  |  | 
|  | return Error::success(); | 
|  | }); | 
|  |  | 
|  | if (Err) | 
|  | return std::move(Err); | 
|  |  | 
|  | return std::move(TSM); | 
|  | } | 
|  |  | 
|  | /// Inactive Platform Support | 
|  | /// | 
|  | /// Explicitly disables platform support. JITDylibs are not scanned for special | 
|  | /// init/deinit symbols. No runtime API interposes are injected. | 
|  | class InactivePlatformSupport : public LLJIT::PlatformSupport { | 
|  | public: | 
|  | InactivePlatformSupport() = default; | 
|  |  | 
|  | Error initialize(JITDylib &JD) override { | 
|  | LLVM_DEBUG(dbgs() << "InactivePlatformSupport: no initializers running for " | 
|  | << JD.getName() << "\n"); | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error deinitialize(JITDylib &JD) override { | 
|  | LLVM_DEBUG( | 
|  | dbgs() << "InactivePlatformSupport: no deinitializers running for " | 
|  | << JD.getName() << "\n"); | 
|  | return Error::success(); | 
|  | } | 
|  | }; | 
|  |  | 
|  | } // end anonymous namespace | 
|  |  | 
|  | namespace llvm { | 
|  | namespace orc { | 
|  |  | 
|  | Error ORCPlatformSupport::initialize(orc::JITDylib &JD) { | 
|  | using llvm::orc::shared::SPSExecutorAddr; | 
|  | using llvm::orc::shared::SPSString; | 
|  | using SPSDLOpenSig = SPSExecutorAddr(SPSString, int32_t); | 
|  | using SPSDLUpdateSig = int32_t(SPSExecutorAddr); | 
|  | enum dlopen_mode : int32_t { | 
|  | ORC_RT_RTLD_LAZY = 0x1, | 
|  | ORC_RT_RTLD_NOW = 0x2, | 
|  | ORC_RT_RTLD_LOCAL = 0x4, | 
|  | ORC_RT_RTLD_GLOBAL = 0x8 | 
|  | }; | 
|  |  | 
|  | auto &ES = J.getExecutionSession(); | 
|  | auto MainSearchOrder = J.getMainJITDylib().withLinkOrderDo( | 
|  | [](const JITDylibSearchOrder &SO) { return SO; }); | 
|  | StringRef WrapperToCall = "__orc_rt_jit_dlopen_wrapper"; | 
|  | bool dlupdate = false; | 
|  | const Triple &TT = ES.getTargetTriple(); | 
|  | if (TT.isOSBinFormatMachO() || TT.isOSBinFormatELF()) { | 
|  | if (InitializedDylib.contains(&JD)) { | 
|  | WrapperToCall = "__orc_rt_jit_dlupdate_wrapper"; | 
|  | dlupdate = true; | 
|  | } else | 
|  | InitializedDylib.insert(&JD); | 
|  | } | 
|  |  | 
|  | if (auto WrapperAddr = | 
|  | ES.lookup(MainSearchOrder, J.mangleAndIntern(WrapperToCall))) { | 
|  | if (dlupdate) { | 
|  | int32_t result; | 
|  | auto E = ES.callSPSWrapper<SPSDLUpdateSig>(WrapperAddr->getAddress(), | 
|  | result, DSOHandles[&JD]); | 
|  | if (result) | 
|  | return make_error<StringError>("dlupdate failed", | 
|  | inconvertibleErrorCode()); | 
|  | return E; | 
|  | } | 
|  | return ES.callSPSWrapper<SPSDLOpenSig>(WrapperAddr->getAddress(), | 
|  | DSOHandles[&JD], JD.getName(), | 
|  | int32_t(ORC_RT_RTLD_LAZY)); | 
|  | } else | 
|  | return WrapperAddr.takeError(); | 
|  | } | 
|  |  | 
|  | Error ORCPlatformSupport::deinitialize(orc::JITDylib &JD) { | 
|  | using llvm::orc::shared::SPSExecutorAddr; | 
|  | using SPSDLCloseSig = int32_t(SPSExecutorAddr); | 
|  |  | 
|  | auto &ES = J.getExecutionSession(); | 
|  | auto MainSearchOrder = J.getMainJITDylib().withLinkOrderDo( | 
|  | [](const JITDylibSearchOrder &SO) { return SO; }); | 
|  |  | 
|  | if (auto WrapperAddr = ES.lookup( | 
|  | MainSearchOrder, J.mangleAndIntern("__orc_rt_jit_dlclose_wrapper"))) { | 
|  | int32_t result; | 
|  | auto E = J.getExecutionSession().callSPSWrapper<SPSDLCloseSig>( | 
|  | WrapperAddr->getAddress(), result, DSOHandles[&JD]); | 
|  | if (E) | 
|  | return E; | 
|  | else if (result) | 
|  | return make_error<StringError>("dlclose failed", | 
|  | inconvertibleErrorCode()); | 
|  | DSOHandles.erase(&JD); | 
|  | InitializedDylib.erase(&JD); | 
|  | } else | 
|  | return WrapperAddr.takeError(); | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | void LLJIT::PlatformSupport::setInitTransform( | 
|  | LLJIT &J, IRTransformLayer::TransformFunction T) { | 
|  | J.InitHelperTransformLayer->setTransform(std::move(T)); | 
|  | } | 
|  |  | 
|  | LLJIT::PlatformSupport::~PlatformSupport() = default; | 
|  |  | 
|  | Error LLJITBuilderState::prepareForConstruction() { | 
|  |  | 
|  | LLVM_DEBUG(dbgs() << "Preparing to create LLJIT instance...\n"); | 
|  |  | 
|  | if (!JTMB) { | 
|  | LLVM_DEBUG({ | 
|  | dbgs() << "  No explicitly set JITTargetMachineBuilder. " | 
|  | "Detecting host...\n"; | 
|  | }); | 
|  | if (auto JTMBOrErr = JITTargetMachineBuilder::detectHost()) | 
|  | JTMB = std::move(*JTMBOrErr); | 
|  | else | 
|  | return JTMBOrErr.takeError(); | 
|  | } | 
|  |  | 
|  | if ((ES || EPC) && NumCompileThreads) | 
|  | return make_error<StringError>( | 
|  | "NumCompileThreads cannot be used with a custom ExecutionSession or " | 
|  | "ExecutorProcessControl", | 
|  | inconvertibleErrorCode()); | 
|  |  | 
|  | #if !LLVM_ENABLE_THREADS | 
|  | if (NumCompileThreads) | 
|  | return make_error<StringError>( | 
|  | "LLJIT num-compile-threads is " + Twine(NumCompileThreads) + | 
|  | " but LLVM was compiled with LLVM_ENABLE_THREADS=Off", | 
|  | inconvertibleErrorCode()); | 
|  | #endif // !LLVM_ENABLE_THREADS | 
|  |  | 
|  | // Only used in debug builds. | 
|  | [[maybe_unused]] bool ConcurrentCompilationSettingDefaulted = | 
|  | !SupportConcurrentCompilation; | 
|  |  | 
|  | if (!SupportConcurrentCompilation) { | 
|  | #if LLVM_ENABLE_THREADS | 
|  | SupportConcurrentCompilation = NumCompileThreads || ES || EPC; | 
|  | #else | 
|  | SupportConcurrentCompilation = false; | 
|  | #endif // LLVM_ENABLE_THREADS | 
|  | } else { | 
|  | #if !LLVM_ENABLE_THREADS | 
|  | if (*SupportConcurrentCompilation) | 
|  | return make_error<StringError>( | 
|  | "LLJIT concurrent compilation support requested, but LLVM was built " | 
|  | "with LLVM_ENABLE_THREADS=Off", | 
|  | inconvertibleErrorCode()); | 
|  | #endif // !LLVM_ENABLE_THREADS | 
|  | } | 
|  |  | 
|  | LLVM_DEBUG({ | 
|  | dbgs() << "  JITTargetMachineBuilder is " | 
|  | << JITTargetMachineBuilderPrinter(*JTMB, "  ") | 
|  | << "  Pre-constructed ExecutionSession: " << (ES ? "Yes" : "No") | 
|  | << "\n" | 
|  | << "  DataLayout: "; | 
|  | if (DL) | 
|  | dbgs() << DL->getStringRepresentation() << "\n"; | 
|  | else | 
|  | dbgs() << "None (will be created by JITTargetMachineBuilder)\n"; | 
|  |  | 
|  | dbgs() << "  Custom object-linking-layer creator: " | 
|  | << (CreateObjectLinkingLayer ? "Yes" : "No") << "\n" | 
|  | << "  Custom compile-function creator: " | 
|  | << (CreateCompileFunction ? "Yes" : "No") << "\n" | 
|  | << "  Custom platform-setup function: " | 
|  | << (SetUpPlatform ? "Yes" : "No") << "\n" | 
|  | << "  Support concurrent compilation: " | 
|  | << (*SupportConcurrentCompilation ? "Yes" : "No"); | 
|  | if (ConcurrentCompilationSettingDefaulted) | 
|  | dbgs() << " (defaulted based on ES / EPC / NumCompileThreads)\n"; | 
|  | else | 
|  | dbgs() << "\n"; | 
|  | dbgs() << "  Number of compile threads: " << NumCompileThreads << "\n"; | 
|  | }); | 
|  |  | 
|  | // Create DL if not specified. | 
|  | if (!DL) { | 
|  | if (auto DLOrErr = JTMB->getDefaultDataLayoutForTarget()) | 
|  | DL = std::move(*DLOrErr); | 
|  | else | 
|  | return DLOrErr.takeError(); | 
|  | } | 
|  |  | 
|  | // If neither ES nor EPC has been set then create an EPC instance. | 
|  | if (!ES && !EPC) { | 
|  | LLVM_DEBUG({ | 
|  | dbgs() << "ExecutorProcessControl not specified, " | 
|  | "Creating SelfExecutorProcessControl instance\n"; | 
|  | }); | 
|  |  | 
|  | std::unique_ptr<TaskDispatcher> D = nullptr; | 
|  | #if LLVM_ENABLE_THREADS | 
|  | if (*SupportConcurrentCompilation) { | 
|  | std::optional<size_t> NumThreads = std ::nullopt; | 
|  | if (NumCompileThreads) | 
|  | NumThreads = NumCompileThreads; | 
|  | D = std::make_unique<DynamicThreadPoolTaskDispatcher>(NumThreads); | 
|  | } else | 
|  | D = std::make_unique<InPlaceTaskDispatcher>(); | 
|  | #endif // LLVM_ENABLE_THREADS | 
|  | if (auto EPCOrErr = | 
|  | SelfExecutorProcessControl::Create(nullptr, std::move(D), nullptr)) | 
|  | EPC = std::move(*EPCOrErr); | 
|  | else | 
|  | return EPCOrErr.takeError(); | 
|  | } else if (EPC) { | 
|  | LLVM_DEBUG({ | 
|  | dbgs() << "Using explicitly specified ExecutorProcessControl instance " | 
|  | << EPC.get() << "\n"; | 
|  | }); | 
|  | } else { | 
|  | LLVM_DEBUG({ | 
|  | dbgs() << "Using explicitly specified ExecutionSession instance " | 
|  | << ES.get() << "\n"; | 
|  | }); | 
|  | } | 
|  |  | 
|  | // If the client didn't configure any linker options then auto-configure the | 
|  | // JIT linker. | 
|  | if (!CreateObjectLinkingLayer) { | 
|  | auto &TT = JTMB->getTargetTriple(); | 
|  | bool UseJITLink = false; | 
|  | switch (TT.getArch()) { | 
|  | case Triple::riscv64: | 
|  | case Triple::loongarch64: | 
|  | UseJITLink = true; | 
|  | break; | 
|  | case Triple::aarch64: | 
|  | UseJITLink = !TT.isOSBinFormatCOFF(); | 
|  | break; | 
|  | case Triple::arm: | 
|  | case Triple::armeb: | 
|  | case Triple::thumb: | 
|  | case Triple::thumbeb: | 
|  | UseJITLink = TT.isOSBinFormatELF(); | 
|  | break; | 
|  | case Triple::x86_64: | 
|  | UseJITLink = !TT.isOSBinFormatCOFF(); | 
|  | break; | 
|  | case Triple::ppc64: | 
|  | UseJITLink = TT.isPPC64ELFv2ABI(); | 
|  | break; | 
|  | case Triple::ppc64le: | 
|  | UseJITLink = TT.isOSBinFormatELF(); | 
|  | break; | 
|  | default: | 
|  | break; | 
|  | } | 
|  | if (UseJITLink) { | 
|  | if (!JTMB->getCodeModel()) | 
|  | JTMB->setCodeModel(CodeModel::Small); | 
|  | JTMB->setRelocationModel(Reloc::PIC_); | 
|  | CreateObjectLinkingLayer = | 
|  | [](ExecutionSession &ES, | 
|  | const Triple &) -> Expected<std::unique_ptr<ObjectLayer>> { | 
|  | return std::make_unique<ObjectLinkingLayer>(ES); | 
|  | }; | 
|  | } | 
|  | } | 
|  |  | 
|  | // If we need a process JITDylib but no setup function has been given then | 
|  | // create a default one. | 
|  | if (!SetupProcessSymbolsJITDylib && LinkProcessSymbolsByDefault) { | 
|  | LLVM_DEBUG(dbgs() << "Creating default Process JD setup function\n"); | 
|  | SetupProcessSymbolsJITDylib = [](LLJIT &J) -> Expected<JITDylibSP> { | 
|  | auto &JD = | 
|  | J.getExecutionSession().createBareJITDylib("<Process Symbols>"); | 
|  | auto G = EPCDynamicLibrarySearchGenerator::GetForTargetProcess( | 
|  | J.getExecutionSession()); | 
|  | if (!G) | 
|  | return G.takeError(); | 
|  | JD.addGenerator(std::move(*G)); | 
|  | return &JD; | 
|  | }; | 
|  | } | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | LLJIT::~LLJIT() { | 
|  | if (auto Err = ES->endSession()) | 
|  | ES->reportError(std::move(Err)); | 
|  | } | 
|  |  | 
|  | JITDylibSP LLJIT::getProcessSymbolsJITDylib() { return ProcessSymbols; } | 
|  |  | 
|  | JITDylibSP LLJIT::getPlatformJITDylib() { return Platform; } | 
|  |  | 
|  | Expected<JITDylib &> LLJIT::createJITDylib(std::string Name) { | 
|  | auto JD = ES->createJITDylib(std::move(Name)); | 
|  | if (!JD) | 
|  | return JD.takeError(); | 
|  |  | 
|  | JD->addToLinkOrder(DefaultLinks); | 
|  | return JD; | 
|  | } | 
|  |  | 
|  | Expected<JITDylib &> LLJIT::loadPlatformDynamicLibrary(const char *Path) { | 
|  | auto G = EPCDynamicLibrarySearchGenerator::Load(*ES, Path); | 
|  | if (!G) | 
|  | return G.takeError(); | 
|  |  | 
|  | if (auto *ExistingJD = ES->getJITDylibByName(Path)) | 
|  | return *ExistingJD; | 
|  |  | 
|  | auto &JD = ES->createBareJITDylib(Path); | 
|  | JD.addGenerator(std::move(*G)); | 
|  | return JD; | 
|  | } | 
|  |  | 
|  | Error LLJIT::linkStaticLibraryInto(JITDylib &JD, | 
|  | std::unique_ptr<MemoryBuffer> LibBuffer) { | 
|  | auto G = StaticLibraryDefinitionGenerator::Create(*ObjLinkingLayer, | 
|  | std::move(LibBuffer)); | 
|  | if (!G) | 
|  | return G.takeError(); | 
|  |  | 
|  | JD.addGenerator(std::move(*G)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error LLJIT::linkStaticLibraryInto(JITDylib &JD, const char *Path) { | 
|  | auto G = StaticLibraryDefinitionGenerator::Load(*ObjLinkingLayer, Path); | 
|  | if (!G) | 
|  | return G.takeError(); | 
|  |  | 
|  | JD.addGenerator(std::move(*G)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error LLJIT::addIRModule(ResourceTrackerSP RT, ThreadSafeModule TSM) { | 
|  | assert(TSM && "Can not add null module"); | 
|  |  | 
|  | if (auto Err = | 
|  | TSM.withModuleDo([&](Module &M) { return applyDataLayout(M); })) | 
|  | return Err; | 
|  |  | 
|  | return InitHelperTransformLayer->add(std::move(RT), std::move(TSM)); | 
|  | } | 
|  |  | 
|  | Error LLJIT::addIRModule(JITDylib &JD, ThreadSafeModule TSM) { | 
|  | return addIRModule(JD.getDefaultResourceTracker(), std::move(TSM)); | 
|  | } | 
|  |  | 
|  | Error LLJIT::addObjectFile(ResourceTrackerSP RT, | 
|  | std::unique_ptr<MemoryBuffer> Obj) { | 
|  | assert(Obj && "Can not add null object"); | 
|  |  | 
|  | return ObjTransformLayer->add(std::move(RT), std::move(Obj)); | 
|  | } | 
|  |  | 
|  | Error LLJIT::addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj) { | 
|  | return addObjectFile(JD.getDefaultResourceTracker(), std::move(Obj)); | 
|  | } | 
|  |  | 
|  | Expected<ExecutorAddr> LLJIT::lookupLinkerMangled(JITDylib &JD, | 
|  | SymbolStringPtr Name) { | 
|  | if (auto Sym = ES->lookup( | 
|  | makeJITDylibSearchOrder(&JD, JITDylibLookupFlags::MatchAllSymbols), | 
|  | Name)) | 
|  | return Sym->getAddress(); | 
|  | else | 
|  | return Sym.takeError(); | 
|  | } | 
|  |  | 
|  | Expected<std::unique_ptr<ObjectLayer>> | 
|  | LLJIT::createObjectLinkingLayer(LLJITBuilderState &S, ExecutionSession &ES) { | 
|  |  | 
|  | // If the config state provided an ObjectLinkingLayer factory then use it. | 
|  | if (S.CreateObjectLinkingLayer) | 
|  | return S.CreateObjectLinkingLayer(ES, S.JTMB->getTargetTriple()); | 
|  |  | 
|  | // Otherwise default to creating an RTDyldObjectLinkingLayer that constructs | 
|  | // a new SectionMemoryManager for each object. | 
|  | auto GetMemMgr = []() { return std::make_unique<SectionMemoryManager>(); }; | 
|  | auto Layer = | 
|  | std::make_unique<RTDyldObjectLinkingLayer>(ES, std::move(GetMemMgr)); | 
|  |  | 
|  | if (S.JTMB->getTargetTriple().isOSBinFormatCOFF()) { | 
|  | Layer->setOverrideObjectFlagsWithResponsibilityFlags(true); | 
|  | Layer->setAutoClaimResponsibilityForObjectSymbols(true); | 
|  | } | 
|  |  | 
|  | if (S.JTMB->getTargetTriple().isOSBinFormatELF() && | 
|  | (S.JTMB->getTargetTriple().getArch() == Triple::ArchType::ppc64 || | 
|  | S.JTMB->getTargetTriple().getArch() == Triple::ArchType::ppc64le)) | 
|  | Layer->setAutoClaimResponsibilityForObjectSymbols(true); | 
|  |  | 
|  | // 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(Layer)); | 
|  | } | 
|  |  | 
|  | Expected<std::unique_ptr<IRCompileLayer::IRCompiler>> | 
|  | 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)); | 
|  |  | 
|  | // If using a custom EPC then use a ConcurrentIRCompiler by default. | 
|  | if (*S.SupportConcurrentCompilation) | 
|  | return std::make_unique<ConcurrentIRCompiler>(std::move(JTMB)); | 
|  |  | 
|  | auto TM = JTMB.createTargetMachine(); | 
|  | if (!TM) | 
|  | return TM.takeError(); | 
|  |  | 
|  | return std::make_unique<TMOwningSimpleCompiler>(std::move(*TM)); | 
|  | } | 
|  |  | 
|  | LLJIT::LLJIT(LLJITBuilderState &S, Error &Err) | 
|  | : DL(std::move(*S.DL)), TT(S.JTMB->getTargetTriple()) { | 
|  |  | 
|  | ErrorAsOutParameter _(Err); | 
|  |  | 
|  | assert(!(S.EPC && S.ES) && "EPC and ES should not both be set"); | 
|  |  | 
|  | if (S.EPC) { | 
|  | ES = std::make_unique<ExecutionSession>(std::move(S.EPC)); | 
|  | } else if (S.ES) | 
|  | ES = std::move(S.ES); | 
|  | else { | 
|  | if (auto EPC = SelfExecutorProcessControl::Create()) { | 
|  | ES = std::make_unique<ExecutionSession>(std::move(*EPC)); | 
|  | } else { | 
|  | Err = EPC.takeError(); | 
|  | return; | 
|  | } | 
|  | } | 
|  |  | 
|  | auto ObjLayer = createObjectLinkingLayer(S, *ES); | 
|  | if (!ObjLayer) { | 
|  | Err = ObjLayer.takeError(); | 
|  | return; | 
|  | } | 
|  | ObjLinkingLayer = std::move(*ObjLayer); | 
|  | ObjTransformLayer = | 
|  | std::make_unique<ObjectTransformLayer>(*ES, *ObjLinkingLayer); | 
|  |  | 
|  | { | 
|  | auto CompileFunction = createCompileFunction(S, std::move(*S.JTMB)); | 
|  | if (!CompileFunction) { | 
|  | Err = CompileFunction.takeError(); | 
|  | return; | 
|  | } | 
|  | CompileLayer = std::make_unique<IRCompileLayer>( | 
|  | *ES, *ObjTransformLayer, std::move(*CompileFunction)); | 
|  | TransformLayer = std::make_unique<IRTransformLayer>(*ES, *CompileLayer); | 
|  | InitHelperTransformLayer = | 
|  | std::make_unique<IRTransformLayer>(*ES, *TransformLayer); | 
|  | } | 
|  |  | 
|  | if (*S.SupportConcurrentCompilation) | 
|  | InitHelperTransformLayer->setCloneToNewContextOnEmit(true); | 
|  |  | 
|  | if (S.SetupProcessSymbolsJITDylib) { | 
|  | if (auto ProcSymsJD = S.SetupProcessSymbolsJITDylib(*this)) { | 
|  | ProcessSymbols = ProcSymsJD->get(); | 
|  | } else { | 
|  | Err = ProcSymsJD.takeError(); | 
|  | return; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (S.PrePlatformSetup) | 
|  | if ((Err = S.PrePlatformSetup(*this))) | 
|  | return; | 
|  |  | 
|  | if (!S.SetUpPlatform) | 
|  | S.SetUpPlatform = setUpGenericLLVMIRPlatform; | 
|  |  | 
|  | if (auto PlatformJDOrErr = S.SetUpPlatform(*this)) { | 
|  | Platform = PlatformJDOrErr->get(); | 
|  | if (Platform) | 
|  | DefaultLinks.push_back( | 
|  | {Platform, JITDylibLookupFlags::MatchExportedSymbolsOnly}); | 
|  | } else { | 
|  | Err = PlatformJDOrErr.takeError(); | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (S.LinkProcessSymbolsByDefault) | 
|  | DefaultLinks.push_back( | 
|  | {ProcessSymbols, JITDylibLookupFlags::MatchExportedSymbolsOnly}); | 
|  |  | 
|  | if (auto MainOrErr = createJITDylib("main")) | 
|  | Main = &*MainOrErr; | 
|  | else { | 
|  | Err = MainOrErr.takeError(); | 
|  | return; | 
|  | } | 
|  | } | 
|  |  | 
|  | std::string LLJIT::mangle(StringRef UnmangledName) const { | 
|  | 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: " + | 
|  | M.getDataLayout().getStringRepresentation() + " (module) vs " + | 
|  | DL.getStringRepresentation() + " (jit)", | 
|  | inconvertibleErrorCode()); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error setUpOrcPlatformManually(LLJIT &J) { | 
|  | LLVM_DEBUG({ dbgs() << "Setting up orc platform support for LLJIT\n"; }); | 
|  | J.setPlatformSupport(std::make_unique<ORCPlatformSupport>(J)); | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | class LoadAndLinkDynLibrary { | 
|  | public: | 
|  | LoadAndLinkDynLibrary(LLJIT &J) : J(J) {} | 
|  | Error operator()(JITDylib &JD, StringRef DLLName) { | 
|  | if (!DLLName.ends_with_insensitive(".dll")) | 
|  | return make_error<StringError>("DLLName not ending with .dll", | 
|  | inconvertibleErrorCode()); | 
|  | auto DLLNameStr = DLLName.str(); // Guarantees null-termination. | 
|  | auto DLLJD = J.loadPlatformDynamicLibrary(DLLNameStr.c_str()); | 
|  | if (!DLLJD) | 
|  | return DLLJD.takeError(); | 
|  | JD.addToLinkOrder(*DLLJD); | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | private: | 
|  | LLJIT &J; | 
|  | }; | 
|  |  | 
|  | Expected<JITDylibSP> ExecutorNativePlatform::operator()(LLJIT &J) { | 
|  | auto ProcessSymbolsJD = J.getProcessSymbolsJITDylib(); | 
|  | if (!ProcessSymbolsJD) | 
|  | return make_error<StringError>( | 
|  | "Native platforms require a process symbols JITDylib", | 
|  | inconvertibleErrorCode()); | 
|  |  | 
|  | const Triple &TT = J.getTargetTriple(); | 
|  | ObjectLinkingLayer *ObjLinkingLayer = | 
|  | dyn_cast<ObjectLinkingLayer>(&J.getObjLinkingLayer()); | 
|  |  | 
|  | if (!ObjLinkingLayer) | 
|  | return make_error<StringError>( | 
|  | "ExecutorNativePlatform requires ObjectLinkingLayer", | 
|  | inconvertibleErrorCode()); | 
|  |  | 
|  | std::unique_ptr<MemoryBuffer> RuntimeArchiveBuffer; | 
|  | if (OrcRuntime.index() == 0) { | 
|  | auto A = errorOrToExpected(MemoryBuffer::getFile(std::get<0>(OrcRuntime))); | 
|  | if (!A) | 
|  | return A.takeError(); | 
|  | RuntimeArchiveBuffer = std::move(*A); | 
|  | } else | 
|  | RuntimeArchiveBuffer = std::move(std::get<1>(OrcRuntime)); | 
|  |  | 
|  | auto &ES = J.getExecutionSession(); | 
|  | auto &PlatformJD = ES.createBareJITDylib("<Platform>"); | 
|  | PlatformJD.addToLinkOrder(*ProcessSymbolsJD); | 
|  |  | 
|  | J.setPlatformSupport(std::make_unique<ORCPlatformSupport>(J)); | 
|  |  | 
|  | switch (TT.getObjectFormat()) { | 
|  | case Triple::COFF: { | 
|  | const char *VCRuntimePath = nullptr; | 
|  | bool StaticVCRuntime = false; | 
|  | if (VCRuntime) { | 
|  | VCRuntimePath = VCRuntime->first.c_str(); | 
|  | StaticVCRuntime = VCRuntime->second; | 
|  | } | 
|  | if (auto P = COFFPlatform::Create( | 
|  | *ObjLinkingLayer, PlatformJD, std::move(RuntimeArchiveBuffer), | 
|  | LoadAndLinkDynLibrary(J), StaticVCRuntime, VCRuntimePath)) | 
|  | J.getExecutionSession().setPlatform(std::move(*P)); | 
|  | else | 
|  | return P.takeError(); | 
|  | break; | 
|  | } | 
|  | case Triple::ELF: { | 
|  | auto G = StaticLibraryDefinitionGenerator::Create( | 
|  | *ObjLinkingLayer, std::move(RuntimeArchiveBuffer)); | 
|  | if (!G) | 
|  | return G.takeError(); | 
|  |  | 
|  | if (auto P = | 
|  | ELFNixPlatform::Create(*ObjLinkingLayer, PlatformJD, std::move(*G))) | 
|  | J.getExecutionSession().setPlatform(std::move(*P)); | 
|  | else | 
|  | return P.takeError(); | 
|  | break; | 
|  | } | 
|  | case Triple::MachO: { | 
|  | auto G = StaticLibraryDefinitionGenerator::Create( | 
|  | *ObjLinkingLayer, std::move(RuntimeArchiveBuffer)); | 
|  | if (!G) | 
|  | return G.takeError(); | 
|  |  | 
|  | if (auto P = | 
|  | MachOPlatform::Create(*ObjLinkingLayer, PlatformJD, std::move(*G))) | 
|  | ES.setPlatform(std::move(*P)); | 
|  | else | 
|  | return P.takeError(); | 
|  | break; | 
|  | } | 
|  | default: | 
|  | return make_error<StringError>("Unsupported object format in triple " + | 
|  | TT.str(), | 
|  | inconvertibleErrorCode()); | 
|  | } | 
|  |  | 
|  | return &PlatformJD; | 
|  | } | 
|  |  | 
|  | Expected<JITDylibSP> setUpGenericLLVMIRPlatform(LLJIT &J) { | 
|  | LLVM_DEBUG( | 
|  | { dbgs() << "Setting up GenericLLVMIRPlatform support for LLJIT\n"; }); | 
|  | auto ProcessSymbolsJD = J.getProcessSymbolsJITDylib(); | 
|  | if (!ProcessSymbolsJD) | 
|  | return make_error<StringError>( | 
|  | "Native platforms require a process symbols JITDylib", | 
|  | inconvertibleErrorCode()); | 
|  |  | 
|  | auto &PlatformJD = J.getExecutionSession().createBareJITDylib("<Platform>"); | 
|  | PlatformJD.addToLinkOrder(*ProcessSymbolsJD); | 
|  |  | 
|  | if (auto *OLL = dyn_cast<ObjectLinkingLayer>(&J.getObjLinkingLayer())) { | 
|  |  | 
|  | bool UseEHFrames = true; | 
|  |  | 
|  | // Enable compact-unwind support if possible. | 
|  | if (J.getTargetTriple().isOSDarwin() || | 
|  | J.getTargetTriple().isOSBinFormatMachO()) { | 
|  |  | 
|  | // Check if the bootstrap map says that we should force eh-frames: | 
|  | // Older libunwinds require this as they don't have a dynamic | 
|  | // registration API for compact-unwind. | 
|  | std::optional<bool> ForceEHFrames; | 
|  | if (auto Err = J.getExecutionSession().getBootstrapMapValue<bool, bool>( | 
|  | "darwin-use-ehframes-only", ForceEHFrames)) | 
|  | return Err; | 
|  | if (ForceEHFrames.has_value()) | 
|  | UseEHFrames = *ForceEHFrames; | 
|  | else | 
|  | UseEHFrames = false; | 
|  |  | 
|  | // If UseEHFrames hasn't been set then we're good to use compact-unwind. | 
|  | if (!UseEHFrames) { | 
|  | if (auto UIRP = UnwindInfoRegistrationPlugin::Create( | 
|  | J.getIRCompileLayer(), PlatformJD)) { | 
|  | OLL->addPlugin(std::move(*UIRP)); | 
|  | LLVM_DEBUG(dbgs() << "Enabled compact-unwind support.\n"); | 
|  | } else | 
|  | return UIRP.takeError(); | 
|  | } | 
|  | } | 
|  |  | 
|  | // Otherwise fall back to standard unwind registration. | 
|  | if (UseEHFrames) { | 
|  | auto &ES = J.getExecutionSession(); | 
|  | if (auto EHFrameRegistrar = EPCEHFrameRegistrar::Create(ES)) { | 
|  | OLL->addPlugin(std::make_unique<EHFrameRegistrationPlugin>( | 
|  | ES, std::move(*EHFrameRegistrar))); | 
|  | LLVM_DEBUG(dbgs() << "Enabled eh-frame support.\n"); | 
|  | } else | 
|  | return EHFrameRegistrar.takeError(); | 
|  | } | 
|  | } | 
|  |  | 
|  | J.setPlatformSupport( | 
|  | std::make_unique<GenericLLVMIRPlatformSupport>(J, PlatformJD)); | 
|  |  | 
|  | return &PlatformJD; | 
|  | } | 
|  |  | 
|  | Expected<JITDylibSP> setUpInactivePlatform(LLJIT &J) { | 
|  | LLVM_DEBUG( | 
|  | { dbgs() << "Explicitly deactivated platform support for LLJIT\n"; }); | 
|  | J.setPlatformSupport(std::make_unique<InactivePlatformSupport>()); | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | Error LLLazyJITBuilderState::prepareForConstruction() { | 
|  | if (auto Err = LLJITBuilderState::prepareForConstruction()) | 
|  | return Err; | 
|  | TT = JTMB->getTargetTriple(); | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error LLLazyJIT::addLazyIRModule(JITDylib &JD, ThreadSafeModule TSM) { | 
|  | assert(TSM && "Can not add null module"); | 
|  |  | 
|  | if (auto Err = TSM.withModuleDo( | 
|  | [&](Module &M) -> Error { return applyDataLayout(M); })) | 
|  | return Err; | 
|  |  | 
|  | return CODLayer->add(JD, std::move(TSM)); | 
|  | } | 
|  |  | 
|  | 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 IP Layer. | 
|  | IPLayer = std::make_unique<IRPartitionLayer>(*ES, *InitHelperTransformLayer); | 
|  |  | 
|  | // Create the COD layer. | 
|  | CODLayer = std::make_unique<CompileOnDemandLayer>(*ES, *IPLayer, *LCTMgr, | 
|  | std::move(ISMBuilder)); | 
|  |  | 
|  | if (*S.SupportConcurrentCompilation) | 
|  | CODLayer->setCloneToNewContextOnEmit(true); | 
|  | } | 
|  |  | 
|  | // In-process LLJIT uses eh-frame section wrappers via EPC, so we need to force | 
|  | // them to be linked in. | 
|  | LLVM_ATTRIBUTE_USED void linkComponents() { | 
|  | errs() << (void *)&llvm_orc_registerEHFrameSectionWrapper | 
|  | << (void *)&llvm_orc_deregisterEHFrameSectionWrapper; | 
|  | } | 
|  |  | 
|  | } // End namespace orc. | 
|  | } // End namespace llvm. |