diff --git a/llvm/include/llvm/ExecutionEngine/Orc/COFFPlatform.h b/llvm/include/llvm/ExecutionEngine/Orc/COFFPlatform.h --- a/llvm/include/llvm/ExecutionEngine/Orc/COFFPlatform.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/COFFPlatform.h @@ -39,6 +39,14 @@ /// Try to create a COFFPlatform instance, adding the ORC runtime to the /// given JITDylib. + static Expected> + Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, + JITDylib &PlatformJD, + std::unique_ptr OrcRuntimeArchiveBuffer, + LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime = false, + const char *VCRuntimePath = nullptr, + std::optional RuntimeAliases = std::nullopt); + static Expected> Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, JITDylib &PlatformJD, const char *OrcRuntimePath, @@ -136,10 +144,14 @@ static bool supportedTarget(const Triple &TT); - COFFPlatform(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, - JITDylib &PlatformJD, const char *OrcRuntimePath, - LoadDynamicLibrary LoadDynamicLibrary, bool StaticVCRuntime, - const char *VCRuntimePath, Error &Err); + COFFPlatform( + ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, + JITDylib &PlatformJD, + std::unique_ptr OrcRuntimeGenerator, + std::unique_ptr OrcRuntimeArchiveBuffer, + std::unique_ptr OrcRuntimeArchive, + LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime, + const char *VCRuntimePath, Error &Err); // Associate COFFPlatform JIT-side runtime support functions with handlers. Error associateRuntimeSupportFunctions(JITDylib &PlatformJD); diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Core.h b/llvm/include/llvm/ExecutionEngine/Orc/Core.h --- a/llvm/include/llvm/ExecutionEngine/Orc/Core.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/Core.h @@ -1054,6 +1054,10 @@ void setLinkOrder(JITDylibSearchOrder NewSearchOrder, bool LinkAgainstThisJITDylibFirst = true); + /// Append the given JITDylibSearchOrder to the link order for this + /// JITDylib. + void addToLinkOrder(const JITDylibSearchOrder &NewLinks); + /// Add the given JITDylib to the link order for definitions in this /// JITDylib. /// diff --git a/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h b/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h --- a/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h @@ -37,7 +37,7 @@ class LLJIT { template friend class LLJITBuilderSetters; - friend void setUpGenericLLVMIRPlatform(LLJIT &J); + friend Expected setUpGenericLLVMIRPlatform(LLJIT &J); public: /// Initializer support for LLJIT. @@ -70,6 +70,20 @@ /// Returns a reference to the JITDylib representing the JIT'd main program. JITDylib &getMainJITDylib() { return *Main; } + /// Returns the ProcessSymbols JITDylib, which by default reflects non-JIT'd + /// symbols in the host process. + /// + /// Note: JIT'd code should not be added to the ProcessSymbols JITDylib. Use + /// the main JITDylib or a custom JITDylib instead. + JITDylibSP getProcessSymbolsJITDylib(); + + /// Returns the Platform JITDylib, which will contain the ORC runtime (if + /// given) and any platform symbols. + /// + /// Note: JIT'd code should not be added to the Platform JITDylib. Use the + /// main JITDylib or a custom JITDylib instead. + JITDylibSP getPlatformJITDylib(); + /// Returns the JITDylib with the given name, or nullptr if no JITDylib with /// that name exists. JITDylib *getJITDylibByName(StringRef Name) { @@ -82,9 +96,12 @@ /// input or elsewhere in the environment then the client should check /// (e.g. by calling getJITDylibByName) that the given name is not already in /// use. - Expected createJITDylib(std::string Name) { - return ES->createJITDylib(std::move(Name)); - } + Expected createJITDylib(std::string Name); + + /// Returns the default link order for this LLJIT instance. This link order + /// will be appended to the link order of JITDylibs created by LLJIT's + /// createJITDylib method. + JITDylibSearchOrder defaultLinkOrder() { return DefaultLinks; } /// Adds an IR module with the given ResourceTracker. Error addIRModule(ResourceTrackerSP RT, ThreadSafeModule TSM); @@ -203,6 +220,10 @@ std::unique_ptr PS; JITDylib *Main = nullptr; + JITDylib *ProcessSymbols = nullptr; + JITDylib *Platform = nullptr; + + JITDylibSearchOrder DefaultLinks; DataLayout DL; Triple TT; @@ -258,12 +279,17 @@ std::function>( JITTargetMachineBuilder JTMB)>; - using PlatformSetupFunction = std::function; + using ProcessSymbolsJITDylibSetupFunction = + std::function; + + using PlatformSetupFunction = unique_function(LLJIT &J)>; std::unique_ptr EPC; std::unique_ptr ES; std::optional JTMB; std::optional DL; + bool LinkProcessSymbolsJITDylibByDefault = true; + ProcessSymbolsJITDylibSetupFunction SetupProcessSymbolsJITDylib; ObjectLinkingLayerCreator CreateObjectLinkingLayer; CompileFunctionCreator CreateCompileFunction; PlatformSetupFunction SetUpPlatform; @@ -316,6 +342,29 @@ return impl(); } + /// The LinkProcessSymbolsJITDylibDyDefault flag determines whether the + /// "Process" JITDylib will be added to the default link order at LLJIT + /// construction time. If true, the Process JITDylib will be added as the last + /// item in the default link order. If false (or if the Process JITDylib is + /// disabled via setProcessSymbolsJITDylibSetup) then the Process JITDylib + /// will not appear in the default link order. + SetterImpl & + setLinkProcessSymbolsJITDylibByDefault(bool LinkProcessSymsByDefault) { + impl().LinkProcessSymbolsJITDylibByDefault = LinkProcessSymsByDefault; + return impl(); + } + + /// Set a setup function for the process symbols dylib. If not provided, + /// but LinkProcessSymbolsJITDylibByDefault is true, then the process-symbols + /// JITDylib will be configured with a DynamicLibrarySearchGenerator with a + /// default symbol filter. + SetterImpl &setProcessSymbolsJITDylibSetup( + LLJITBuilderState::ProcessSymbolsJITDylibSetupFunction + SetupProcessSymbolsJITDylib) { + impl().SetupProcessSymbolsJITDylib = std::move(SetupProcessSymbolsJITDylib); + return impl(); + } + /// Set an ObjectLinkingLayer creation function. /// /// If this method is not called, a default creation function will be used @@ -447,20 +496,52 @@ public LLLazyJITBuilderSetters {}; -/// Configure the LLJIT instance to use orc runtime support. -Error setUpOrcPlatform(LLJIT& J); +/// Configure the LLJIT instance to use orc runtime support. This overload +/// assumes that the client has manually configured a Platform object. +Error setUpOrcPlatformManually(LLJIT &J); + +/// Configure the LLJIT instance to use the ORC runtime and the detected +/// native target for the executor. +class SetUpExecutorNativePlatform { +public: + /// Set up using path to Orc runtime. CreatePlatformJD will be run before + /// attempting to construct the platform instance. It should be used (if + /// needed) to provide the offers an opportunity + /// to load process symbols. + SetUpExecutorNativePlatform(std::string OrcRuntimePath) + : OrcRuntime(std::move(OrcRuntimePath)) {} + + /// Set up using the given memory buffer. + SetUpExecutorNativePlatform(std::unique_ptr OrcRuntimeMB) + : OrcRuntime(std::move(OrcRuntimeMB)) {} + + // TODO: add compiler-rt. + + /// Add a path to the VC runtime. + SetUpExecutorNativePlatform &addVCRuntime(std::string VCRuntimePath, + bool StaticVCRuntime) { + VCRuntime = {std::move(VCRuntimePath), StaticVCRuntime}; + return *this; + } + + Expected operator()(LLJIT &J); + +private: + std::variant> OrcRuntime; + std::optional> VCRuntime; +}; /// Configure the LLJIT instance to scrape modules for llvm.global_ctors and /// llvm.global_dtors variables and (if present) build initialization and /// deinitialization functions. Platform specific initialization configurations /// should be preferred where available. -void setUpGenericLLVMIRPlatform(LLJIT &J); +Expected setUpGenericLLVMIRPlatform(LLJIT &J); /// Configure the LLJIT instance to disable platform support explicitly. This is /// useful in two cases: for platforms that don't have such requirements and for /// platforms, that we have no explicit support yet and that don't work well /// with the generic IR platform. -Error setUpInactivePlatform(LLJIT &J); +Expected setUpInactivePlatform(LLJIT &J); } // End namespace orc } // End namespace llvm diff --git a/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp --- a/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp +++ b/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp @@ -159,12 +159,11 @@ namespace llvm { namespace orc { -Expected> -COFFPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, - JITDylib &PlatformJD, const char *OrcRuntimePath, - LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime, - const char *VCRuntimePath, - std::optional RuntimeAliases) { +Expected> COFFPlatform::Create( + ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, + JITDylib &PlatformJD, std::unique_ptr OrcRuntimeArchiveBuffer, + LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime, + const char *VCRuntimePath, std::optional RuntimeAliases) { // If the target is not supported then bail out immediately. if (!supportedTarget(ES.getTargetTriple())) @@ -174,6 +173,22 @@ auto &EPC = ES.getExecutorProcessControl(); + auto GeneratorArchive = + object::Archive::create(OrcRuntimeArchiveBuffer->getMemBufferRef()); + if (!GeneratorArchive) + return GeneratorArchive.takeError(); + + auto OrcRuntimeArchiveGenerator = StaticLibraryDefinitionGenerator::Create( + ObjLinkingLayer, nullptr, std::move(*GeneratorArchive)); + if (!OrcRuntimeArchiveGenerator) + return OrcRuntimeArchiveGenerator.takeError(); + + // We need a second instance of the archive (for now) for the Platform. We + // can `cantFail` this call, since if it were going to fail it would have + // failed above. + auto RuntimeArchive = cantFail( + object::Archive::create(OrcRuntimeArchiveBuffer->getMemBufferRef())); + // Create default aliases if the caller didn't supply any. if (!RuntimeAliases) RuntimeAliases = standardPlatformAliases(ES); @@ -199,13 +214,30 @@ // Create the instance. Error Err = Error::success(); auto P = std::unique_ptr(new COFFPlatform( - ES, ObjLinkingLayer, PlatformJD, OrcRuntimePath, + ES, ObjLinkingLayer, PlatformJD, std::move(*OrcRuntimeArchiveGenerator), + std::move(OrcRuntimeArchiveBuffer), std::move(RuntimeArchive), std::move(LoadDynLibrary), StaticVCRuntime, VCRuntimePath, Err)); if (Err) return std::move(Err); return std::move(P); } +Expected> +COFFPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, + JITDylib &PlatformJD, const char *OrcRuntimePath, + LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime, + const char *VCRuntimePath, + std::optional RuntimeAliases) { + + auto ArchiveBuffer = MemoryBuffer::getFile(OrcRuntimePath); + if (!ArchiveBuffer) + return createFileError(OrcRuntimePath, ArchiveBuffer.getError()); + + return Create(ES, ObjLinkingLayer, PlatformJD, std::move(*ArchiveBuffer), + std::move(LoadDynLibrary), StaticVCRuntime, VCRuntimePath, + std::move(RuntimeAliases)); +} + Expected COFFPlatform::getPerJDObjectFile() { auto PerJDObj = OrcRuntimeArchive->findSym("__orc_rt_coff_per_jd_marker"); if (!PerJDObj) @@ -349,37 +381,22 @@ } } -COFFPlatform::COFFPlatform(ExecutionSession &ES, - ObjectLinkingLayer &ObjLinkingLayer, - JITDylib &PlatformJD, const char *OrcRuntimePath, - LoadDynamicLibrary LoadDynamicLibrary, - bool StaticVCRuntime, const char *VCRuntimePath, - Error &Err) +COFFPlatform::COFFPlatform( + ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, + JITDylib &PlatformJD, + std::unique_ptr OrcRuntimeGenerator, + std::unique_ptr OrcRuntimeArchiveBuffer, + std::unique_ptr OrcRuntimeArchive, + LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime, + const char *VCRuntimePath, Error &Err) : ES(ES), ObjLinkingLayer(ObjLinkingLayer), - LoadDynLibrary(std::move(LoadDynamicLibrary)), + LoadDynLibrary(std::move(LoadDynLibrary)), + OrcRuntimeArchiveBuffer(std::move(OrcRuntimeArchiveBuffer)), + OrcRuntimeArchive(std::move(OrcRuntimeArchive)), StaticVCRuntime(StaticVCRuntime), COFFHeaderStartSymbol(ES.intern("__ImageBase")) { ErrorAsOutParameter _(&Err); - // Create a generator for the ORC runtime archive. - auto OrcRuntimeArchiveGenerator = - StaticLibraryDefinitionGenerator::Load(ObjLinkingLayer, OrcRuntimePath); - if (!OrcRuntimeArchiveGenerator) { - Err = OrcRuntimeArchiveGenerator.takeError(); - return; - } - - auto ArchiveBuffer = MemoryBuffer::getFile(OrcRuntimePath); - if (!ArchiveBuffer) { - Err = createFileError(OrcRuntimePath, ArchiveBuffer.getError()); - return; - } - OrcRuntimeArchiveBuffer = std::move(*ArchiveBuffer); - OrcRuntimeArchive = - std::make_unique(*OrcRuntimeArchiveBuffer, Err); - if (Err) - return; - Bootstrapping.store(true); ObjLinkingLayer.addPlugin(std::make_unique(*this)); @@ -392,7 +409,7 @@ } VCRuntimeBootstrap = std::move(*VCRT); - for (auto &Lib : (*OrcRuntimeArchiveGenerator)->getImportedDynamicLibraries()) + for (auto &Lib : OrcRuntimeGenerator->getImportedDynamicLibraries()) DylibsToPreload.insert(Lib); auto ImportedLibs = @@ -406,7 +423,7 @@ for (auto &Lib : *ImportedLibs) DylibsToPreload.insert(Lib); - PlatformJD.addGenerator(std::move(*OrcRuntimeArchiveGenerator)); + PlatformJD.addGenerator(std::move(OrcRuntimeGenerator)); // PlatformJD hasn't been set up by the platform yet (since we're creating // the platform now), so set it up. @@ -416,10 +433,10 @@ } for (auto& Lib : DylibsToPreload) - if (auto E2 = LoadDynLibrary(PlatformJD, Lib)) { - Err = std::move(E2); - return; - } + if (auto E2 = this->LoadDynLibrary(PlatformJD, Lib)) { + Err = std::move(E2); + return; + } if (StaticVCRuntime) if (auto E2 = VCRuntimeBootstrap->initializeStaticVCRuntime(PlatformJD)) { diff --git a/llvm/lib/ExecutionEngine/Orc/Core.cpp b/llvm/lib/ExecutionEngine/Orc/Core.cpp --- a/llvm/lib/ExecutionEngine/Orc/Core.cpp +++ b/llvm/lib/ExecutionEngine/Orc/Core.cpp @@ -1329,6 +1329,13 @@ }); } +void JITDylib::addToLinkOrder(const JITDylibSearchOrder &NewLinks) { + ES.runSessionLocked([&]() { + LinkOrder.reserve(LinkOrder.size() + NewLinks.size()); + llvm::append_range(LinkOrder, NewLinks); + }); +} + void JITDylib::addToLinkOrder(JITDylib &JD, JITDylibLookupFlags JDLookupFlags) { ES.runSessionLocked([&]() { LinkOrder.push_back({&JD, JDLookupFlags}); }); } diff --git a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp --- a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp +++ b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp @@ -9,6 +9,8 @@ #include "llvm/ExecutionEngine/Orc/LLJIT.h" #include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h" #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h" +#include "llvm/ExecutionEngine/Orc/COFFPlatform.h" +#include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h" #include "llvm/ExecutionEngine/Orc/EPCEHFrameRegistrar.h" #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h" #include "llvm/ExecutionEngine/Orc/MachOPlatform.h" @@ -176,7 +178,7 @@ /// some runtime API, including __cxa_atexit, dlopen, and dlclose. class GenericLLVMIRPlatformSupport : public LLJIT::PlatformSupport { public: - GenericLLVMIRPlatformSupport(LLJIT &J) + GenericLLVMIRPlatformSupport(LLJIT &J, JITDylib &PlatformJD) : J(J), InitFunctionPrefix(J.mangle("__orc_init_func.")), DeInitFunctionPrefix(J.mangle("__orc_deinit_func.")) { @@ -195,10 +197,9 @@ JITEvaluatedSymbol(pointerToJITTargetAddress(registerCxaAtExitHelper), JITSymbolFlags()); - cantFail( - J.getMainJITDylib().define(absoluteSymbols(std::move(StdInterposes)))); - cantFail(setupJITDylib(J.getMainJITDylib())); - cantFail(J.addIRModule(J.getMainJITDylib(), createPlatformRuntimeModule())); + cantFail(PlatformJD.define(absoluteSymbols(std::move(StdInterposes)))); + cantFail(setupJITDylib(PlatformJD)); + cantFail(J.addIRModule(PlatformJD, createPlatformRuntimeModule())); } ExecutionSession &getExecutionSession() { return J.getExecutionSession(); } @@ -758,6 +759,19 @@ ES->reportError(std::move(Err)); } +JITDylibSP LLJIT::getProcessSymbolsJITDylib() { return ProcessSymbols; } + +JITDylibSP LLJIT::getPlatformJITDylib() { return Platform; } + +Expected LLJIT::createJITDylib(std::string Name) { + auto JD = ES->createJITDylib(std::move(Name)); + if (!JD) + return JD.takeError(); + + JD->addToLinkOrder(DefaultLinks); + return JD; +} + Error LLJIT::addIRModule(ResourceTrackerSP RT, ThreadSafeModule TSM) { assert(TSM && "Can not add null module"); @@ -862,13 +876,6 @@ } } - if (auto MainOrErr = this->ES->createJITDylib("main")) - Main = &*MainOrErr; - else { - Err = MainOrErr.takeError(); - return; - } - if (S.DL) DL = std::move(*S.DL); else if (auto DLOrErr = S.JTMB->getDefaultDataLayoutForTarget()) @@ -916,10 +923,47 @@ }); } - if (S.SetUpPlatform) - Err = S.SetUpPlatform(*this); - else - setUpGenericLLVMIRPlatform(*this); + if (S.LinkProcessSymbolsJITDylibByDefault && !S.SetupProcessSymbolsJITDylib) + S.SetupProcessSymbolsJITDylib = [this](JITDylib &JD) -> Error { + auto G = orc::DynamicLibrarySearchGenerator::GetForCurrentProcess( + DL.getGlobalPrefix()); + if (!G) + return G.takeError(); + JD.addGenerator(std::move(*G)); + return Error::success(); + }; + + if (S.SetupProcessSymbolsJITDylib) { + ProcessSymbols = &ES->createBareJITDylib(""); + if (auto Err2 = S.SetupProcessSymbolsJITDylib(*ProcessSymbols)) { + Err = std::move(Err2); + 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.LinkProcessSymbolsJITDylibByDefault) + 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 { @@ -945,24 +989,133 @@ return Error::success(); } -Error setUpOrcPlatform(LLJIT& J) { - LLVM_DEBUG( - { dbgs() << "Setting up orc platform support for LLJIT\n"; }); - J.setPlatformSupport(std::make_unique(J)); +Error setUpOrcPlatformManually(LLJIT &J) { + LLVM_DEBUG({ dbgs() << "Setting up orc platform support for LLJIT\n"; }); + J.setPlatformSupport(std::make_unique(J)); + return Error::success(); +} + +class LoadAndLinkDynLibrary { +public: + LoadAndLinkDynLibrary(LLJIT &J) : J(J) {} + Error operator()(JITDylib &JD, StringRef DLLName) { + if (!DLLName.endswith_insensitive(".dll")) + return make_error("DLLName not ending with .dll", + inconvertibleErrorCode()); + // TODO: Actually load library. + (void)J; return Error::success(); + } + +private: + LLJIT &J; +}; + +Expected SetUpExecutorNativePlatform::operator()(LLJIT &J) { + auto ProcessSymbolsJD = J.getProcessSymbolsJITDylib(); + if (!ProcessSymbolsJD) + return make_error( + "Native platforms require a process symbols JITDylib", + inconvertibleErrorCode()); + + const Triple &TT = J.getTargetTriple(); + ObjectLinkingLayer *ObjLinkingLayer = + dyn_cast(&J.getObjLinkingLayer()); + + if (!ObjLinkingLayer) + return make_error( + "SetUpTargetPlatform requires ObjectLinkingLayer", + inconvertibleErrorCode()); + + std::unique_ptr 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(""); + PlatformJD.addToLinkOrder(*ProcessSymbolsJD); + + J.setPlatformSupport(std::make_unique(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( + ES, *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(ES, *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(ES, *ObjLinkingLayer, PlatformJD, + std::move(*G))) + ES.setPlatform(std::move(*P)); + else + return P.takeError(); + break; + } + default: + return make_error("Unsupported object format in triple " + + TT.str(), + inconvertibleErrorCode()); + } + + return &PlatformJD; } -void setUpGenericLLVMIRPlatform(LLJIT &J) { +Expected setUpGenericLLVMIRPlatform(LLJIT &J) { LLVM_DEBUG( { dbgs() << "Setting up GenericLLVMIRPlatform support for LLJIT\n"; }); - J.setPlatformSupport(std::make_unique(J)); + auto ProcessSymbolsJD = J.getProcessSymbolsJITDylib(); + if (!ProcessSymbolsJD) + return make_error( + "Native platforms require a process symbols JITDylib", + inconvertibleErrorCode()); + + auto &PlatformJD = J.getExecutionSession().createBareJITDylib(""); + PlatformJD.addToLinkOrder(*ProcessSymbolsJD); + + J.setPlatformSupport( + std::make_unique(J, PlatformJD)); + + return &PlatformJD; } -Error setUpInactivePlatform(LLJIT &J) { +Expected setUpInactivePlatform(LLJIT &J) { LLVM_DEBUG( { dbgs() << "Explicitly deactivated platform support for LLJIT\n"; }); J.setPlatformSupport(std::make_unique()); - return Error::success(); + return nullptr; } Error LLLazyJITBuilderState::prepareForConstruction() { diff --git a/llvm/test/ExecutionEngine/OrcLazy/emulated-tls.ll b/llvm/test/ExecutionEngine/OrcLazy/emulated-tls.ll --- a/llvm/test/ExecutionEngine/OrcLazy/emulated-tls.ll +++ b/llvm/test/ExecutionEngine/OrcLazy/emulated-tls.ll @@ -1,7 +1,7 @@ ; LoongArch does not support emulated tls. ; UNSUPPORTED: target=loongarch{{.*}} -; RUN: not lli -no-process-syms -emulated-tls -jit-kind=orc-lazy %s 2>&1 \ +; RUN: not lli -emulated-tls -jit-kind=orc-lazy %s 2>&1 \ ; RUN: | FileCheck %s ; ; Test that emulated-tls does not generate any unexpected errors. diff --git a/llvm/tools/lli/lli.cpp b/llvm/tools/lli/lli.cpp --- a/llvm/tools/lli/lli.cpp +++ b/llvm/tools/lli/lli.cpp @@ -27,7 +27,6 @@ #include "llvm/ExecutionEngine/ObjectCache.h" #include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h" #include "llvm/ExecutionEngine/Orc/DebugUtils.h" -#include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h" #include "llvm/ExecutionEngine/Orc/EPCDebugObjectRegistrar.h" #include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h" #include "llvm/ExecutionEngine/Orc/EPCEHFrameRegistrar.h" @@ -35,7 +34,6 @@ #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" #include "llvm/ExecutionEngine/Orc/LLJIT.h" -#include "llvm/ExecutionEngine/Orc/MachOPlatform.h" #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" #include "llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h" #include "llvm/ExecutionEngine/Orc/SymbolStringPool.h" @@ -236,20 +234,22 @@ cl::desc("Do not resolve lli process symbols in JIT'd code"), cl::init(false)); - enum class LLJITPlatform { Inactive, DetectHost, ORC, GenericIR }; - - cl::opt - Platform("lljit-platform", cl::desc("Platform to use with LLJIT"), - cl::init(LLJITPlatform::DetectHost), - cl::values(clEnumValN(LLJITPlatform::DetectHost, "DetectHost", - "Select based on JIT target triple"), - clEnumValN(LLJITPlatform::ORC, "ORC", - "Use ORCPlatform with the ORC runtime"), - clEnumValN(LLJITPlatform::GenericIR, "GenericIR", - "Use LLJITGenericIRPlatform"), - clEnumValN(LLJITPlatform::Inactive, "Inactive", - "Disable platform support explicitly")), - cl::Hidden); + enum class LLJITPlatform { Inactive, Auto, ExecutorNative, GenericIR }; + + cl::opt Platform( + "lljit-platform", cl::desc("Platform to use with LLJIT"), + cl::init(LLJITPlatform::Auto), + cl::values(clEnumValN(LLJITPlatform::Auto, "Auto", + "Like 'ExecutorNative' if ORC runtime " + "provided, otherwise like 'GenericIR'"), + clEnumValN(LLJITPlatform::ExecutorNative, "ExecutorNative", + "Use the native platform for the executor." + "Requires -orc-runtime"), + clEnumValN(LLJITPlatform::GenericIR, "GenericIR", + "Use LLJITGenericIRPlatform"), + clEnumValN(LLJITPlatform::Inactive, "Inactive", + "Disable platform support explicitly")), + cl::Hidden); enum class DumpKind { NoDump, @@ -864,6 +864,9 @@ .setRelocationModel(codegen::getExplicitRelocModel()) .setCodeModel(codegen::getExplicitCodeModel()); + // Link process symbols unless NoProcessSymbols is set. + Builder.setLinkProcessSymbolsJITDylibByDefault(!NoProcessSymbols); + // FIXME: Setting a dummy call-through manager in non-lazy mode prevents the // JIT builder to instantiate a default (which would fail with an error for // unsupported architectures). @@ -904,17 +907,15 @@ // Set up LLJIT platform. LLJITPlatform P = Platform; - if (P == LLJITPlatform::DetectHost) { - if (JITLinker == JITLinkerKind::JITLink && !OrcRuntime.empty() && - (TT->isOSBinFormatMachO() || TT->isOSBinFormatELF())) - P = LLJITPlatform::ORC; - else - P = LLJITPlatform::GenericIR; - } + if (P == LLJITPlatform::Auto) + P = OrcRuntime.empty() ? LLJITPlatform::GenericIR + : LLJITPlatform::ExecutorNative; + switch (P) { - case LLJITPlatform::ORC: - Builder.setPlatformSetUp(orc::setUpOrcPlatform); + case LLJITPlatform::ExecutorNative: { + Builder.setPlatformSetUp(orc::SetUpExecutorNativePlatform(OrcRuntime)); break; + } case LLJITPlatform::GenericIR: // Nothing to do: LLJITBuilder will use this by default. break; @@ -933,7 +934,7 @@ Builder.setObjectLinkingLayerCreator([&EPC, &P](orc::ExecutionSession &ES, const Triple &TT) { auto L = std::make_unique(ES, EPC->getMemMgr()); - if (P != LLJITPlatform::ORC) { + if (P != LLJITPlatform::ExecutorNative) { L->addPlugin(std::make_unique( ES, ExitOnErr(orc::EPCEHFrameRegistrar::Create(ES)))); L->addPlugin(std::make_unique( @@ -981,46 +982,12 @@ return TSM; }); - orc::MangleAndInterner Mangle(J->getExecutionSession(), J->getDataLayout()); - - // Unless they've been explicitly disabled, make process symbols available to - // JIT'd code. - if (!NoProcessSymbols) - J->getMainJITDylib().addGenerator( - ExitOnErr(orc::DynamicLibrarySearchGenerator::GetForCurrentProcess( - J->getDataLayout().getGlobalPrefix(), - [MainName = Mangle("main")](const orc::SymbolStringPtr &Name) { - return Name != MainName; - }))); - - if (GenerateBuiltinFunctions.size() > 0) + if (GenerateBuiltinFunctions.size() > 0) { + // Add LLI builtins. + orc::MangleAndInterner Mangle(J->getExecutionSession(), J->getDataLayout()); J->getMainJITDylib().addGenerator( std::make_unique(GenerateBuiltinFunctions, Mangle)); - - if (P == LLJITPlatform::ORC) { - if (auto *OLL = llvm::dyn_cast(ObjLayer)) { - auto &ES = J->getExecutionSession(); - if (TT->isOSBinFormatMachO()) { - if (auto P = llvm::orc::MachOPlatform::Create( - ES, *OLL, J->getMainJITDylib(), OrcRuntime.c_str())) - ES.setPlatform(std::move(*P)); - else - ExitOnErr(P.takeError()); - } else if (TT->isOSBinFormatELF()) { - if (auto P = llvm::orc::ELFNixPlatform::Create( - ES, *OLL, J->getMainJITDylib(), OrcRuntime.c_str())) - ES.setPlatform(std::move(*P)); - else - ExitOnErr(P.takeError()); - } else { - errs() << "No ORC platform support\n"; - exit(1); - } - } else { - errs() << "ORC platform requires JITLink\n"; - exit(1); - } } // Regular modules are greedy: They materialize as a whole and trigger