diff --git a/llvm/include/llvm/ExecutionEngine/Orc/COFFPlatform.h b/llvm/include/llvm/ExecutionEngine/Orc/COFFPlatform.h index 969c6f0b15afc..4ef208dbbca22 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/COFFPlatform.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/COFFPlatform.h @@ -39,6 +39,14 @@ class COFFPlatform : public Platform { /// 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 @@ class COFFPlatform : public Platform { 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/LLJIT.h b/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h index b61947efcc1dc..c7efeedcb78e4 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h @@ -37,7 +37,7 @@ class ExecutorProcessControl; 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 @@ class LLJIT { /// 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) { @@ -108,9 +122,12 @@ class LLJIT { /// 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); @@ -229,6 +246,10 @@ class LLJIT { std::unique_ptr PS; JITDylib *Main = nullptr; + JITDylib *ProcessSymbols = nullptr; + JITDylib *Platform = nullptr; + + JITDylibSearchOrder DefaultLinks; DataLayout DL; Triple TT; @@ -284,12 +305,17 @@ class LLJITBuilderState { 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 LinkProcessSymbolsByDefault = true; + ProcessSymbolsJITDylibSetupFunction SetupProcessSymbolsJITDylib; ObjectLinkingLayerCreator CreateObjectLinkingLayer; CompileFunctionCreator CreateCompileFunction; PlatformSetupFunction SetUpPlatform; @@ -342,6 +368,28 @@ class LLJITBuilderSetters { return impl(); } + /// The LinkProcessSymbolsDyDefault 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 &setLinkProcessSymbolsByDefault(bool LinkProcessSymbolsByDefault) { + impl().LinkProcessSymbolsByDefault = LinkProcessSymbolsByDefault; + 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 @@ -473,20 +521,49 @@ class LLLazyJITBuilder 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 ExecutorNativePlatform { +public: + /// Set up using path to Orc runtime. + ExecutorNativePlatform(std::string OrcRuntimePath) + : OrcRuntime(std::move(OrcRuntimePath)) {} + + /// Set up using the given memory buffer. + ExecutorNativePlatform(std::unique_ptr OrcRuntimeMB) + : OrcRuntime(std::move(OrcRuntimeMB)) {} + + // TODO: add compiler-rt. + + /// Add a path to the VC runtime. + ExecutorNativePlatform &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 index 06144bd5b1826..7c869bead0b00 100644 --- a/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp +++ b/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp @@ -159,12 +159,11 @@ class COFFHeaderMaterializationUnit : public MaterializationUnit { 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 @@ COFFPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, 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 @@ COFFPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, // 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 @@ bool COFFPlatform::supportedTarget(const Triple &TT) { } } -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 @@ COFFPlatform::COFFPlatform(ExecutionSession &ES, } VCRuntimeBootstrap = std::move(*VCRT); - for (auto &Lib : (*OrcRuntimeArchiveGenerator)->getImportedDynamicLibraries()) + for (auto &Lib : OrcRuntimeGenerator->getImportedDynamicLibraries()) DylibsToPreload.insert(Lib); auto ImportedLibs = @@ -406,7 +423,7 @@ COFFPlatform::COFFPlatform(ExecutionSession &ES, 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 @@ COFFPlatform::COFFPlatform(ExecutionSession &ES, } 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/LLJIT.cpp b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp index 65e63eb2d932b..fd106f9dc3ef8 100644 --- 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/EPCDynamicLibrarySearchGenerator.h" #include "llvm/ExecutionEngine/Orc/EPCEHFrameRegistrar.h" #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h" @@ -99,10 +101,16 @@ class ORCPlatformSupport : public LLJIT::PlatformSupport { ORC_RT_RTLD_GLOBAL = 0x8 }; - if (auto WrapperAddr = J.lookup("__orc_rt_jit_dlopen_wrapper")) { - return J.getExecutionSession().callSPSWrapper( - *WrapperAddr, DSOHandles[&JD], JD.getName(), - int32_t(ORC_RT_RTLD_LAZY)); + 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_dlopen_wrapper"))) { + return ES.callSPSWrapper(WrapperAddr->getAddress(), + DSOHandles[&JD], JD.getName(), + int32_t(ORC_RT_RTLD_LAZY)); } else return WrapperAddr.takeError(); } @@ -111,10 +119,16 @@ class ORCPlatformSupport : public LLJIT::PlatformSupport { using llvm::orc::shared::SPSExecutorAddr; using SPSDLCloseSig = int32_t(SPSExecutorAddr); - if (auto WrapperAddr = J.lookup("__orc_rt_jit_dlclose_wrapper")) { + 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( - *WrapperAddr, result, DSOHandles[&JD]); + WrapperAddr->getAddress(), result, DSOHandles[&JD]); if (E) return E; else if (result) @@ -177,7 +191,7 @@ class GlobalCtorDtorScraper { /// 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.")) { @@ -194,10 +208,9 @@ class GenericLLVMIRPlatformSupport : public LLJIT::PlatformSupport { StdInterposes[J.mangleAndIntern("__lljit.cxa_atexit_helper")] = { ExecutorAddr::fromPtr(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(); } @@ -754,6 +767,19 @@ LLJIT::~LLJIT() { 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; +} + Expected LLJIT::loadPlatformDynamicLibrary(const char *Path) { auto G = EPCDynamicLibrarySearchGenerator::Load(*ES, Path); if (!G) @@ -893,13 +919,6 @@ LLJIT::LLJIT(LLJITBuilderState &S, Error &Err) } } - 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()) @@ -947,10 +966,47 @@ LLJIT::LLJIT(LLJITBuilderState &S, Error &Err) }); } - if (S.SetUpPlatform) - Err = S.SetUpPlatform(*this); - else - setUpGenericLLVMIRPlatform(*this); + if (S.LinkProcessSymbolsByDefault && !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.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 { @@ -976,24 +1032,136 @@ Error LLJIT::applyDataLayout(Module &M) { 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()); + 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 ExecutorNativePlatform::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 index 51a5905feefa9..a70bc5f4ceb42 100644 --- a/llvm/test/ExecutionEngine/OrcLazy/emulated-tls.ll +++ b/llvm/test/ExecutionEngine/OrcLazy/emulated-tls.ll @@ -1,8 +1,8 @@ ; 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: | FileCheck %s +; RUN: not lli -no-process-syms -lljit-platform=Inactive -emulated-tls \ +; RUN: -jit-kind=orc-lazy %s 2>&1 | 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 index 464db8f99457a..368a8baca07da 100644 --- 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 @@ namespace { 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 @@ int runOrcJIT(const char *ProgName) { .setRelocationModel(codegen::getExplicitRelocModel()) .setCodeModel(codegen::getExplicitCodeModel()); + // Link process symbols unless NoProcessSymbols is set. + Builder.setLinkProcessSymbolsByDefault(!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). @@ -905,17 +908,15 @@ int runOrcJIT(const char *ProgName) { // 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::ExecutorNativePlatform(OrcRuntime)); break; + } case LLJITPlatform::GenericIR: // Nothing to do: LLJITBuilder will use this by default. break; @@ -934,7 +935,7 @@ int runOrcJIT(const char *ProgName) { 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( @@ -982,46 +983,12 @@ int runOrcJIT(const char *ProgName) { 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