[llvm] bdf5f9c - [ORC] Introduce SetUpExecutorNativePlatform utility.

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Sun Mar 19 15:29:53 PDT 2023


Author: Lang Hames
Date: 2023-03-19T15:29:46-07:00
New Revision: bdf5f9c3228d6ed1d7c6f87b3828a7d573b34c03

URL: https://github.com/llvm/llvm-project/commit/bdf5f9c3228d6ed1d7c6f87b3828a7d573b34c03
DIFF: https://github.com/llvm/llvm-project/commit/bdf5f9c3228d6ed1d7c6f87b3828a7d573b34c03.diff

LOG: [ORC] Introduce SetUpExecutorNativePlatform utility.

Simplifies the process of building an LLJIT instance that supports the native
platform features (initializers, TLV, etc.).

SetUpExecutorNativePlatform can be passed to LLJITBuilder::setPlatformSetUp
method. It takes a reference to the ORC runtime (as a path or an in-memory
archive) and automatically sets the platform for LLJIT's ExecutionSession based
on the executor process's triple.

Differential Revision: https://reviews.llvm.org/D144276

Added: 
    

Modified: 
    llvm/include/llvm/ExecutionEngine/Orc/COFFPlatform.h
    llvm/include/llvm/ExecutionEngine/Orc/Core.h
    llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h
    llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp
    llvm/lib/ExecutionEngine/Orc/Core.cpp
    llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
    llvm/test/ExecutionEngine/OrcLazy/emulated-tls.ll
    llvm/tools/lli/lli.cpp

Removed: 
    


################################################################################
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<std::unique_ptr<COFFPlatform>>
+  Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
+         JITDylib &PlatformJD,
+         std::unique_ptr<MemoryBuffer> OrcRuntimeArchiveBuffer,
+         LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime = false,
+         const char *VCRuntimePath = nullptr,
+         std::optional<SymbolAliasMap> RuntimeAliases = std::nullopt);
+
   static Expected<std::unique_ptr<COFFPlatform>>
   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<StaticLibraryDefinitionGenerator> OrcRuntimeGenerator,
+      std::unique_ptr<MemoryBuffer> OrcRuntimeArchiveBuffer,
+      std::unique_ptr<object::Archive> 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
index adab75d3aaf15..ff391e1671cf4 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/Core.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Core.h
@@ -1054,6 +1054,10 @@ class JITDylib : public ThreadSafeRefCountedBase<JITDylib>,
   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
index 2982a7af09b05..e347c5de71882 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 <typename, typename, typename> friend class LLJITBuilderSetters;
 
-  friend void setUpGenericLLVMIRPlatform(LLJIT &J);
+  friend Expected<JITDylibSP> 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) {
@@ -82,9 +96,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<JITDylib &> createJITDylib(std::string Name) {
-    return ES->createJITDylib(std::move(Name));
-  }
+  Expected<JITDylib &> 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 @@ class LLJIT {
   std::unique_ptr<PlatformSupport> PS;
 
   JITDylib *Main = nullptr;
+  JITDylib *ProcessSymbols = nullptr;
+  JITDylib *Platform = nullptr;
+
+  JITDylibSearchOrder DefaultLinks;
 
   DataLayout DL;
   Triple TT;
@@ -258,12 +279,17 @@ class LLJITBuilderState {
       std::function<Expected<std::unique_ptr<IRCompileLayer::IRCompiler>>(
           JITTargetMachineBuilder JTMB)>;
 
-  using PlatformSetupFunction = std::function<Error(LLJIT &J)>;
+  using ProcessSymbolsJITDylibSetupFunction =
+      std::function<Error(JITDylib &JD)>;
+
+  using PlatformSetupFunction = unique_function<Expected<JITDylibSP>(LLJIT &J)>;
 
   std::unique_ptr<ExecutorProcessControl> EPC;
   std::unique_ptr<ExecutionSession> ES;
   std::optional<JITTargetMachineBuilder> JTMB;
   std::optional<DataLayout> DL;
+  bool LinkProcessSymbolsJITDylibByDefault = true;
+  ProcessSymbolsJITDylibSetupFunction SetupProcessSymbolsJITDylib;
   ObjectLinkingLayerCreator CreateObjectLinkingLayer;
   CompileFunctionCreator CreateCompileFunction;
   PlatformSetupFunction SetUpPlatform;
@@ -316,6 +342,29 @@ class LLJITBuilderSetters {
     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 @@ class LLLazyJITBuilder
       public LLLazyJITBuilderSetters<LLLazyJIT, LLLazyJITBuilder,
                                      LLLazyJITBuilderState> {};
 
-/// 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<MemoryBuffer> 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<JITDylibSP> operator()(LLJIT &J);
+
+private:
+  std::variant<std::string, std::unique_ptr<MemoryBuffer>> OrcRuntime;
+  std::optional<std::pair<std::string, bool>> 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<JITDylibSP> 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<JITDylibSP> 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 dfafc429843fb..91ae61be888fa 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<std::unique_ptr<COFFPlatform>>
-COFFPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
-                     JITDylib &PlatformJD, const char *OrcRuntimePath,
-                     LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime,
-                     const char *VCRuntimePath,
-                     std::optional<SymbolAliasMap> RuntimeAliases) {
+Expected<std::unique_ptr<COFFPlatform>> COFFPlatform::Create(
+    ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
+    JITDylib &PlatformJD, std::unique_ptr<MemoryBuffer> OrcRuntimeArchiveBuffer,
+    LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime,
+    const char *VCRuntimePath, std::optional<SymbolAliasMap> 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<COFFPlatform>(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<std::unique_ptr<COFFPlatform>>
+COFFPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
+                     JITDylib &PlatformJD, const char *OrcRuntimePath,
+                     LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime,
+                     const char *VCRuntimePath,
+                     std::optional<SymbolAliasMap> 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<MemoryBufferRef> 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<StaticLibraryDefinitionGenerator> OrcRuntimeGenerator,
+    std::unique_ptr<MemoryBuffer> OrcRuntimeArchiveBuffer,
+    std::unique_ptr<object::Archive> 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<object::Archive>(*OrcRuntimeArchiveBuffer, Err);
-  if (Err)
-    return;
-
   Bootstrapping.store(true);
   ObjLinkingLayer.addPlugin(std::make_unique<COFFPlatformPlugin>(*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/Core.cpp b/llvm/lib/ExecutionEngine/Orc/Core.cpp
index f85719195532d..ad218317d7ab6 100644
--- a/llvm/lib/ExecutionEngine/Orc/Core.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Core.cpp
@@ -1329,6 +1329,13 @@ void JITDylib::setLinkOrder(JITDylibSearchOrder NewLinkOrder,
   });
 }
 
+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
index a9cc6680c9eb4..fabbfcd2651a9 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/EPCEHFrameRegistrar.h"
 #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
 #include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
@@ -176,7 +178,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.")) {
 
@@ -195,10 +197,9 @@ class GenericLLVMIRPlatformSupport : public LLJIT::PlatformSupport {
         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 @@ LLJIT::~LLJIT() {
     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;
+}
+
 Error LLJIT::addIRModule(ResourceTrackerSP RT, ThreadSafeModule TSM) {
   assert(TSM && "Can not add null module");
 
@@ -862,13 +876,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())
@@ -916,10 +923,47 @@ LLJIT::LLJIT(LLJITBuilderState &S, Error &Err)
     });
   }
 
-  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("<Process Symbols>");
+    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 @@ 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<ORCPlatformSupport>(J));
+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.endswith_insensitive(".dll"))
+      return make_error<StringError>("DLLName not ending with .dll",
+                                     inconvertibleErrorCode());
+    // TODO: Actually load library.
+    (void)J;
     return Error::success();
+  }
+
+private:
+  LLJIT &J;
+};
+
+Expected<JITDylibSP> SetUpExecutorNativePlatform::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>(
+        "SetUpTargetPlatform 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(
+            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<StringError>("Unsupported object format in triple " +
+                                       TT.str(),
+                                   inconvertibleErrorCode());
+  }
+
+  return &PlatformJD;
 }
 
-void setUpGenericLLVMIRPlatform(LLJIT &J) {
+Expected<JITDylibSP> setUpGenericLLVMIRPlatform(LLJIT &J) {
   LLVM_DEBUG(
       { dbgs() << "Setting up GenericLLVMIRPlatform support for LLJIT\n"; });
-  J.setPlatformSupport(std::make_unique<GenericLLVMIRPlatformSupport>(J));
+  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);
+
+  J.setPlatformSupport(
+      std::make_unique<GenericLLVMIRPlatformSupport>(J, PlatformJD));
+
+  return &PlatformJD;
 }
 
-Error setUpInactivePlatform(LLJIT &J) {
+Expected<JITDylibSP> setUpInactivePlatform(LLJIT &J) {
   LLVM_DEBUG(
       { dbgs() << "Explicitly deactivated platform support for LLJIT\n"; });
   J.setPlatformSupport(std::make_unique<InactivePlatformSupport>());
-  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..6310be47d3c4c 100644
--- 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
index ff73ac18f5eee..33270c6276943 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<LLJITPlatform>
-      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<LLJITPlatform> 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.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 @@ 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::SetUpExecutorNativePlatform(OrcRuntime));
     break;
+  }
   case LLJITPlatform::GenericIR:
     // Nothing to do: LLJITBuilder will use this by default.
     break;
@@ -933,7 +934,7 @@ int runOrcJIT(const char *ProgName) {
     Builder.setObjectLinkingLayerCreator([&EPC, &P](orc::ExecutionSession &ES,
                                                     const Triple &TT) {
       auto L = std::make_unique<orc::ObjectLinkingLayer>(ES, EPC->getMemMgr());
-      if (P != LLJITPlatform::ORC) {
+      if (P != LLJITPlatform::ExecutorNative) {
         L->addPlugin(std::make_unique<orc::EHFrameRegistrationPlugin>(
             ES, ExitOnErr(orc::EPCEHFrameRegistrar::Create(ES))));
         L->addPlugin(std::make_unique<orc::DebugObjectManagerPlugin>(
@@ -981,46 +982,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<LLIBuiltinFunctionGenerator>(GenerateBuiltinFunctions,
                                                       Mangle));
-
-  if (P == LLJITPlatform::ORC) {
-    if (auto *OLL = llvm::dyn_cast<llvm::orc::ObjectLinkingLayer>(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


        


More information about the llvm-commits mailing list