[clang] [llvm] [ORC] Move JITLinkMemoryManager ownership out of ExecutorProcessControl. (PR #192665)

Lang Hames via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 17 07:06:17 PDT 2026


https://github.com/lhames created https://github.com/llvm/llvm-project/pull/192665

Removes the JITLinkMemoryManager pointer and getMemMgr() accessor from ExecutorProcessControl, replacing them with a createDefaultMemoryManager() virtual factory method. This follows the same decoupling pattern applied to DylibManager and MemoryAccess in earlier patches.

JITLinkMemoryManager ownership moves to the client:
- LLJIT gains a MemMgr member and a MemoryManagerCreator builder hook.
- EPCIndirectionUtils takes a JITLinkMemoryManager& parameter.
- LinkGraphLinkingLayer and ObjectLinkingLayer lose their no-arg constructors (MemMgr is now required).
- SimpleRemoteEPC::Setup is removed; custom memory manager selection now happens at the client level rather than during EPC setup.

>From 51b54f12fcc407249e0359e0c42bf5f6ca0680c4 Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at gmail.com>
Date: Sat, 11 Apr 2026 16:27:52 +1000
Subject: [PATCH] [ORC] Move JITLinkMemoryManager ownership out of
 ExecutorProcessControl.

Removes the JITLinkMemoryManager pointer and getMemMgr() accessor from
ExecutorProcessControl, replacing them with a createDefaultMemoryManager()
virtual factory method. This follows the same decoupling pattern applied
to DylibManager and MemoryAccess in earlier patches.

JITLinkMemoryManager ownership moves to the client:
- LLJIT gains a MemMgr member and a MemoryManagerCreator builder hook.
- EPCIndirectionUtils takes a JITLinkMemoryManager& parameter.
- LinkGraphLinkingLayer and ObjectLinkingLayer lose their no-arg
  constructors (MemMgr is now required).
- SimpleRemoteEPC::Setup is removed; custom memory manager selection
  now happens at the client level rather than during EPC setup.
---
 clang/lib/Interpreter/IncrementalExecutor.cpp | 45 +++++-------
 .../BuildingAJIT/Chapter3/KaleidoscopeJIT.h   | 16 +++--
 .../BuildingAJIT/Chapter4/KaleidoscopeJIT.h   | 16 +++--
 .../LLJITWithExecutorProcessControl.cpp       |  3 +-
 .../RemoteJITUtils.cpp                        |  4 +-
 .../ExecutionEngine/Orc/EPCIndirectionUtils.h | 19 +++--
 .../Orc/ExecutorProcessControl.h              | 16 +++--
 llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h | 24 +++++++
 .../Orc/LinkGraphLinkingLayer.h               |  6 +-
 .../llvm/ExecutionEngine/Orc/MemoryMapper.h   |  4 ++
 .../ExecutionEngine/Orc/ObjectLinkingLayer.h  |  7 +-
 .../Orc/SelfExecutorProcessControl.h          | 14 ++--
 .../ExecutionEngine/Orc/SimpleRemoteEPC.h     | 20 ++----
 .../Orc/EPCIndirectionUtils.cpp               | 43 ++++++------
 llvm/lib/ExecutionEngine/Orc/LLJIT.cpp        | 19 ++++-
 .../Orc/LinkGraphLinkingLayer.cpp             |  5 --
 llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp |  1 +
 .../Orc/SelfExecutorProcessControl.cpp        | 24 +++----
 .../ExecutionEngine/Orc/SimpleRemoteEPC.cpp   | 17 ++---
 llvm/tools/lli/lli.cpp                        |  4 +-
 llvm/tools/llvm-jitlink/llvm-jitlink.cpp      | 69 ++++++++++---------
 llvm/tools/llvm-jitlink/llvm-jitlink.h        |  1 +
 .../ExecutionEngine/Orc/OrcTestCommon.h       |  5 ++
 23 files changed, 207 insertions(+), 175 deletions(-)

diff --git a/clang/lib/Interpreter/IncrementalExecutor.cpp b/clang/lib/Interpreter/IncrementalExecutor.cpp
index 246b844183411..65cb29a2f441a 100644
--- a/clang/lib/Interpreter/IncrementalExecutor.cpp
+++ b/clang/lib/Interpreter/IncrementalExecutor.cpp
@@ -87,10 +87,10 @@ createDefaultJITBuilder(llvm::orc::JITTargetMachineBuilder JTMB) {
 }
 
 Expected<std::unique_ptr<llvm::jitlink::JITLinkMemoryManager>>
-createSharedMemoryManager(llvm::orc::SimpleRemoteEPC &SREPC,
+createSharedMemoryManager(llvm::orc::ExecutorProcessControl &EPC,
                           unsigned SlabAllocateSize) {
   llvm::orc::SharedMemoryMapper::SymbolAddrs SAs;
-  if (auto Err = SREPC.getBootstrapSymbols(
+  if (auto Err = EPC.getBootstrapSymbols(
           {{SAs.Instance,
             llvm::orc::rt::ExecutorSharedMemoryMapperServiceInstanceName},
            {SAs.Reserve,
@@ -116,13 +116,13 @@ createSharedMemoryManager(llvm::orc::SimpleRemoteEPC &SREPC,
     SlabSize = SlabAllocateSize;
 
   return llvm::orc::MapperJITLinkMemoryManager::CreateWithMapper<
-      llvm::orc::SharedMemoryMapper>(SlabSize, SREPC, SAs);
+      llvm::orc::SharedMemoryMapper>(SlabSize, EPC, SAs);
 }
 
 static llvm::Expected<
     std::pair<std::unique_ptr<llvm::orc::SimpleRemoteEPC>, uint32_t>>
-launchExecutor(llvm::StringRef ExecutablePath, bool UseSharedMemory,
-               unsigned SlabAllocateSize, std::function<void()> CustomizeFork) {
+launchExecutor(llvm::StringRef ExecutablePath,
+               std::function<void()> CustomizeFork) {
 #ifndef LLVM_ON_UNIX
   // FIXME: Add support for Windows.
   return llvm::make_error<llvm::StringError>(
@@ -196,18 +196,11 @@ launchExecutor(llvm::StringRef ExecutablePath, bool UseSharedMemory,
   close(ToExecutor[ReadEnd]);
   close(FromExecutor[WriteEnd]);
 
-  llvm::orc::SimpleRemoteEPC::Setup S = llvm::orc::SimpleRemoteEPC::Setup();
-  if (UseSharedMemory)
-    S.CreateMemoryManager =
-        [SlabAllocateSize](llvm::orc::SimpleRemoteEPC &EPC) {
-          return createSharedMemoryManager(EPC, SlabAllocateSize);
-        };
-
   auto EPCOrErr =
       llvm::orc::SimpleRemoteEPC::Create<llvm::orc::FDSimpleRemoteEPCTransport>(
           std::make_unique<llvm::orc::DynamicThreadPoolTaskDispatcher>(
               std::nullopt),
-          std::move(S), FromExecutor[ReadEnd], ToExecutor[WriteEnd]);
+          FromExecutor[ReadEnd], ToExecutor[WriteEnd]);
   if (!EPCOrErr)
     return EPCOrErr.takeError();
   return std::make_pair(std::move(*EPCOrErr), ChildPID);
@@ -256,8 +249,7 @@ static Expected<int> connectTCPSocketImpl(std::string Host,
 }
 
 static llvm::Expected<std::unique_ptr<llvm::orc::SimpleRemoteEPC>>
-connectTCPSocket(llvm::StringRef NetworkAddress, bool UseSharedMemory,
-                 unsigned SlabAllocateSize) {
+connectTCPSocket(llvm::StringRef NetworkAddress) {
 #ifndef LLVM_ON_UNIX
   // FIXME: Add TCP support for Windows.
   return llvm::make_error<llvm::StringError>(
@@ -293,18 +285,11 @@ connectTCPSocket(llvm::StringRef NetworkAddress, bool UseSharedMemory,
   if (!SockFD)
     return SockFD.takeError();
 
-  llvm::orc::SimpleRemoteEPC::Setup S = llvm::orc::SimpleRemoteEPC::Setup();
-  if (UseSharedMemory)
-    S.CreateMemoryManager =
-        [SlabAllocateSize](llvm::orc::SimpleRemoteEPC &EPC) {
-          return createSharedMemoryManager(EPC, SlabAllocateSize);
-        };
-
   return llvm::orc::SimpleRemoteEPC::Create<
       llvm::orc::FDSimpleRemoteEPCTransport>(
       std::make_unique<llvm::orc::DynamicThreadPoolTaskDispatcher>(
           std::nullopt),
-      std::move(S), *SockFD, *SockFD);
+      *SockFD, *SockFD);
 #endif
 }
 #endif // _WIN32
@@ -334,8 +319,6 @@ outOfProcessJITBuilder(const IncrementalExecutorBuilder &IncrExecutorBuilder) {
   if (!IncrExecutorBuilder.OOPExecutor.empty()) {
     // Launch an out-of-process executor locally in a child process.
     auto ResultOrErr = launchExecutor(IncrExecutorBuilder.OOPExecutor,
-                                      IncrExecutorBuilder.UseSharedMemory,
-                                      IncrExecutorBuilder.SlabAllocateSize,
                                       IncrExecutorBuilder.CustomizeFork);
     if (!ResultOrErr)
       return ResultOrErr.takeError();
@@ -344,9 +327,7 @@ outOfProcessJITBuilder(const IncrementalExecutorBuilder &IncrExecutorBuilder) {
     EPC = std::move(EPCOrErr);
   } else if (IncrExecutorBuilder.OOPExecutorConnect != "") {
 #if LLVM_ON_UNIX && LLVM_ENABLE_THREADS
-    auto EPCOrErr = connectTCPSocket(IncrExecutorBuilder.OOPExecutorConnect,
-                                     IncrExecutorBuilder.UseSharedMemory,
-                                     IncrExecutorBuilder.SlabAllocateSize);
+    auto EPCOrErr = connectTCPSocket(IncrExecutorBuilder.OOPExecutorConnect);
     if (!EPCOrErr)
       return EPCOrErr.takeError();
     EPC = std::move(*EPCOrErr);
@@ -364,6 +345,14 @@ outOfProcessJITBuilder(const IncrementalExecutorBuilder &IncrExecutorBuilder) {
     if (!JBOrErr)
       return JBOrErr.takeError();
     JB = std::move(*JBOrErr);
+
+    if (IncrExecutorBuilder.UseSharedMemory)
+      JB->setMemoryManagerCreator(
+          [SlabAllocateSize = IncrExecutorBuilder.SlabAllocateSize](
+              llvm::orc::ExecutionSession &ES) {
+            return createSharedMemoryManager(ES.getExecutorProcessControl(),
+                                             SlabAllocateSize);
+          });
   }
 
   return std::make_pair(std::move(JB), childPid);
diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h
index 2bb3c4bf94fd1..028c3afe8e9c6 100644
--- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h
+++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h
@@ -44,6 +44,7 @@ class KaleidoscopeJIT {
 private:
   std::unique_ptr<ExecutionSession> ES;
   std::unique_ptr<EPCIndirectionUtils> EPCIU;
+  std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr;
   std::unique_ptr<MemoryAccess> MemAccess;
 
   DataLayout DL;
@@ -65,9 +66,10 @@ class KaleidoscopeJIT {
 public:
   KaleidoscopeJIT(std::unique_ptr<ExecutionSession> ES,
                   std::unique_ptr<EPCIndirectionUtils> EPCIU,
+                  std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr,
                   std::unique_ptr<MemoryAccess> MemAccess,
                   JITTargetMachineBuilder JTMB, DataLayout DL)
-      : ES(std::move(ES)), EPCIU(std::move(EPCIU)),
+      : ES(std::move(ES)), EPCIU(std::move(EPCIU)), MemMgr(std::move(MemMgr)),
         MemAccess(std::move(MemAccess)), DL(std::move(DL)),
         Mangle(*this->ES, this->DL),
         ObjectLayer(*this->ES,
@@ -100,13 +102,17 @@ class KaleidoscopeJIT {
 
     auto ES = std::make_unique<ExecutionSession>(std::move(*EPC));
 
+    auto MemMgr = ES->getExecutorProcessControl().createDefaultMemoryManager();
+    if (!MemMgr)
+      return MemMgr.takeError();
+
     auto MemAccess =
         ES->getExecutorProcessControl().createDefaultMemoryAccess();
     if (!MemAccess)
       return MemAccess.takeError();
 
     auto EPCIU = EPCIndirectionUtils::Create(ES->getExecutorProcessControl(),
-                                             **MemAccess);
+                                             **MemMgr, **MemAccess);
     if (!EPCIU)
       return EPCIU.takeError();
 
@@ -123,9 +129,9 @@ class KaleidoscopeJIT {
     if (!DL)
       return DL.takeError();
 
-    return std::make_unique<KaleidoscopeJIT>(std::move(ES), std::move(*EPCIU),
-                                             std::move(*MemAccess),
-                                             std::move(JTMB), std::move(*DL));
+    return std::make_unique<KaleidoscopeJIT>(
+        std::move(ES), std::move(*EPCIU), std::move(*MemMgr),
+        std::move(*MemAccess), std::move(JTMB), std::move(*DL));
   }
 
   const DataLayout &getDataLayout() const { return DL; }
diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h
index 34e3d3f031db4..e4933c0ef6870 100644
--- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h
+++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h
@@ -130,6 +130,7 @@ class KaleidoscopeJIT {
 private:
   std::unique_ptr<ExecutionSession> ES;
   std::unique_ptr<EPCIndirectionUtils> EPCIU;
+  std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr;
   std::unique_ptr<MemoryAccess> MemAccess;
 
   DataLayout DL;
@@ -150,9 +151,10 @@ class KaleidoscopeJIT {
 public:
   KaleidoscopeJIT(std::unique_ptr<ExecutionSession> ES,
                   std::unique_ptr<EPCIndirectionUtils> EPCIU,
+                  std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr,
                   std::unique_ptr<MemoryAccess> MemAccess,
                   JITTargetMachineBuilder JTMB, DataLayout DL)
-      : ES(std::move(ES)), EPCIU(std::move(EPCIU)),
+      : ES(std::move(ES)), EPCIU(std::move(EPCIU)), MemMgr(std::move(MemMgr)),
         MemAccess(std::move(MemAccess)), DL(std::move(DL)),
         Mangle(*this->ES, this->DL),
         ObjectLayer(*this->ES,
@@ -183,13 +185,17 @@ class KaleidoscopeJIT {
 
     auto ES = std::make_unique<ExecutionSession>(std::move(*EPC));
 
+    auto MemMgr = ES->getExecutorProcessControl().createDefaultMemoryManager();
+    if (!MemMgr)
+      return MemMgr.takeError();
+
     auto MemAccess =
         ES->getExecutorProcessControl().createDefaultMemoryAccess();
     if (!MemAccess)
       return MemAccess.takeError();
 
     auto EPCIU = EPCIndirectionUtils::Create(ES->getExecutorProcessControl(),
-                                             **MemAccess);
+                                             **MemMgr, **MemAccess);
     if (!EPCIU)
       return EPCIU.takeError();
 
@@ -206,9 +212,9 @@ class KaleidoscopeJIT {
     if (!DL)
       return DL.takeError();
 
-    return std::make_unique<KaleidoscopeJIT>(std::move(ES), std::move(*EPCIU),
-                                             std::move(*MemAccess),
-                                             std::move(JTMB), std::move(*DL));
+    return std::make_unique<KaleidoscopeJIT>(
+        std::move(ES), std::move(*EPCIU), std::move(*MemMgr),
+        std::move(*MemAccess), std::move(JTMB), std::move(*DL));
   }
 
   const DataLayout &getDataLayout() const { return DL; }
diff --git a/llvm/examples/OrcV2Examples/LLJITWithExecutorProcessControl/LLJITWithExecutorProcessControl.cpp b/llvm/examples/OrcV2Examples/LLJITWithExecutorProcessControl/LLJITWithExecutorProcessControl.cpp
index f7af2b8a4586e..508991c208f45 100644
--- a/llvm/examples/OrcV2Examples/LLJITWithExecutorProcessControl/LLJITWithExecutorProcessControl.cpp
+++ b/llvm/examples/OrcV2Examples/LLJITWithExecutorProcessControl/LLJITWithExecutorProcessControl.cpp
@@ -150,7 +150,8 @@ int main(int argc, char *argv[]) {
                                  .getExecutorProcessControl()
                                  .createDefaultMemoryAccess());
   auto EPCIU = ExitOnErr(EPCIndirectionUtils::Create(
-      J->getExecutionSession().getExecutorProcessControl(), *MemAccess));
+      J->getExecutionSession().getExecutorProcessControl(),
+      J->getMemoryManager(), *MemAccess));
   ExitOnErr(EPCIU->writeResolverBlock(ExecutorAddr::fromPtr(&reenter),
                                       ExecutorAddr::fromPtr(EPCIU.get())));
   EPCIU->createLazyCallThroughManager(
diff --git a/llvm/examples/OrcV2Examples/LLJITWithRemoteDebugging/RemoteJITUtils.cpp b/llvm/examples/OrcV2Examples/LLJITWithRemoteDebugging/RemoteJITUtils.cpp
index 511b568e36bd4..9673a4d817fba 100644
--- a/llvm/examples/OrcV2Examples/LLJITWithRemoteDebugging/RemoteJITUtils.cpp
+++ b/llvm/examples/OrcV2Examples/LLJITWithRemoteDebugging/RemoteJITUtils.cpp
@@ -130,7 +130,6 @@ launchLocalExecutor(StringRef ExecutablePath) {
 
   auto EPC = SimpleRemoteEPC::Create<FDSimpleRemoteEPCTransport>(
       std::make_unique<DynamicThreadPoolTaskDispatcher>(std::nullopt),
-      SimpleRemoteEPC::Setup(),
       FromExecutor[ReadEnd], ToExecutor[WriteEnd]);
   if (!EPC)
     return EPC.takeError();
@@ -201,8 +200,7 @@ connectTCPSocket(StringRef NetworkAddress) {
     return CreateErr(toString(SockFD.takeError()));
 
   return SimpleRemoteEPC::Create<FDSimpleRemoteEPCTransport>(
-      std::make_unique<DynamicThreadPoolTaskDispatcher>(std::nullopt),
-      SimpleRemoteEPC::Setup(), *SockFD);
+      std::make_unique<DynamicThreadPoolTaskDispatcher>(std::nullopt), *SockFD);
 }
 
 #endif
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/EPCIndirectionUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/EPCIndirectionUtils.h
index 287f720a79b2f..063e958ddfc9d 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/EPCIndirectionUtils.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/EPCIndirectionUtils.h
@@ -80,11 +80,13 @@ class EPCIndirectionUtils {
   /// Create using the given ABI class.
   template <typename ORCABI>
   static std::unique_ptr<EPCIndirectionUtils>
-  CreateWithABI(ExecutorProcessControl &EPC, MemoryAccess &MemAccess);
+  CreateWithABI(ExecutorProcessControl &EPC,
+                jitlink::JITLinkMemoryManager &MemMgr, MemoryAccess &MemAccess);
 
   /// Create based on the ExecutorProcessControl triple.
   LLVM_ABI static Expected<std::unique_ptr<EPCIndirectionUtils>>
-  Create(ExecutorProcessControl &EPC, MemoryAccess &MemAccess);
+  Create(ExecutorProcessControl &EPC, jitlink::JITLinkMemoryManager &MemMgr,
+         MemoryAccess &MemAccess);
 
   /// Return a reference to the ExecutorProcessControl object.
   ExecutorProcessControl &getExecutorProcessControl() const { return EPC; }
@@ -92,6 +94,9 @@ class EPCIndirectionUtils {
   /// Return a reference to the MemoryAccess object for this instance.
   MemoryAccess &getMemoryAccess() const { return MemAccess; }
 
+  /// Return a reference to the JITLinkMemoryManager object for this instance.
+  jitlink::JITLinkMemoryManager &getMemManager() const { return MemMgr; }
+
   /// Return a reference to the ABISupport object for this instance.
   ABISupport &getABISupport() const { return *ABI; }
 
@@ -141,13 +146,15 @@ class EPCIndirectionUtils {
   using IndirectStubInfoVector = std::vector<IndirectStubInfo>;
 
   /// Create an EPCIndirectionUtils instance.
-  EPCIndirectionUtils(ExecutorProcessControl &EPC, MemoryAccess &MemAccess,
-                      std::unique_ptr<ABISupport> ABI);
+  EPCIndirectionUtils(ExecutorProcessControl &EPC,
+                      jitlink::JITLinkMemoryManager &MemMgr,
+                      MemoryAccess &MemAccess, std::unique_ptr<ABISupport> ABI);
 
   Expected<IndirectStubInfoVector> getIndirectStubs(unsigned NumStubs);
 
   std::mutex EPCUIMutex;
   ExecutorProcessControl &EPC;
+  jitlink::JITLinkMemoryManager &MemMgr;
   MemoryAccess &MemAccess;
   std::unique_ptr<ABISupport> ABI;
   ExecutorAddr ResolverBlockAddr;
@@ -214,9 +221,11 @@ class ABISupportImpl : public EPCIndirectionUtils::ABISupport {
 template <typename ORCABI>
 std::unique_ptr<EPCIndirectionUtils>
 EPCIndirectionUtils::CreateWithABI(ExecutorProcessControl &EPC,
+                                   jitlink::JITLinkMemoryManager &MemMgr,
                                    MemoryAccess &MemAccess) {
   return std::unique_ptr<EPCIndirectionUtils>(new EPCIndirectionUtils(
-      EPC, MemAccess, std::make_unique<detail::ABISupportImpl<ORCABI>>()));
+      EPC, MemMgr, MemAccess,
+      std::make_unique<detail::ABISupportImpl<ORCABI>>()));
 }
 
 } // end namespace orc
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h b/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h
index 7495a8253ed1c..92770333b33c5 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h
@@ -14,7 +14,6 @@
 #define LLVM_EXECUTIONENGINE_ORC_EXECUTORPROCESSCONTROL_H
 
 #include "llvm/ADT/StringRef.h"
-#include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
 #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
 #include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
 #include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h"
@@ -28,6 +27,12 @@
 #include <mutex>
 #include <vector>
 
+namespace llvm::jitlink {
+
+class JITLinkMemoryManager;
+
+} // namespace llvm::jitlink
+
 namespace llvm::orc {
 
 class DylibManager;
@@ -134,11 +139,9 @@ class LLVM_ABI ExecutorProcessControl {
   /// Get the JIT dispatch function and context address for the executor.
   const JITDispatchInfo &getJITDispatchInfo() const { return JDI; }
 
-  /// Return a JITLinkMemoryManager for the target process.
-  jitlink::JITLinkMemoryManager &getMemMgr() const {
-    assert(MemMgr && "No MemMgr object set");
-    return *MemMgr;
-  }
+  /// Create a default JITLinkMemoryManager for the target process.
+  virtual Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
+  createDefaultMemoryManager() = 0;
 
   /// Create a default DylibManager for the target process.
   virtual Expected<std::unique_ptr<DylibManager>> createDefaultDylibMgr() = 0;
@@ -310,7 +313,6 @@ class LLVM_ABI ExecutorProcessControl {
   Triple TargetTriple;
   unsigned PageSize = 0;
   JITDispatchInfo JDI;
-  jitlink::JITLinkMemoryManager *MemMgr = nullptr;
   StringMap<std::vector<char>> BootstrapMap;
   StringMap<ExecutorAddr> BootstrapSymbols;
 };
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h b/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h
index 29732d51965f4..3ba472305066d 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h
@@ -30,6 +30,7 @@
 #include <variant>
 
 namespace llvm {
+
 namespace orc {
 
 class LLJITBuilderState;
@@ -220,6 +221,12 @@ class LLVM_ABI LLJIT {
     return *DylibMgr;
   }
 
+  /// Returns a reference to the JITLinkMemoryManager for this instance.
+  jitlink::JITLinkMemoryManager &getMemoryManager() {
+    assert(MemMgr && "No MemMgr set");
+    return *MemMgr;
+  }
+
   /// Returns a reference to the ObjLinkingLayer
   ObjectLayer &getObjLinkingLayer() { return *ObjLinkingLayer; }
 
@@ -241,6 +248,9 @@ class LLVM_ABI LLJIT {
   }
 
 protected:
+  static Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
+  createMemoryManager(LLJITBuilderState &S, ExecutionSession &ES);
+
   static Expected<std::unique_ptr<ObjectLayer>>
   createObjectLinkingLayer(LLJITBuilderState &S, ExecutionSession &ES,
                            jitlink::JITLinkMemoryManager &MemMgr);
@@ -254,6 +264,7 @@ class LLVM_ABI LLJIT {
   Error applyDataLayout(Module &M);
 
   std::unique_ptr<ExecutionSession> ES;
+  std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr;
   std::unique_ptr<PlatformSupport> PS;
   std::unique_ptr<DylibManager> DylibMgr;
 
@@ -308,6 +319,10 @@ class LLLazyJIT : public LLJIT {
 
 class LLJITBuilderState {
 public:
+  using MemoryManagerCreator =
+      std::function<Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>(
+          ExecutionSession &)>;
+
   using ObjectLinkingLayerCreator =
       std::function<Expected<std::unique_ptr<ObjectLayer>>(
           ExecutionSession &, jitlink::JITLinkMemoryManager &)>;
@@ -329,6 +344,7 @@ class LLJITBuilderState {
   std::optional<DataLayout> DL;
   bool LinkProcessSymbolsByDefault = true;
   ProcessSymbolsJITDylibSetupFunction SetupProcessSymbolsJITDylib;
+  MemoryManagerCreator CreateMemoryManager;
   ObjectLinkingLayerCreator CreateObjectLinkingLayer;
   CompileFunctionCreator CreateCompileFunction;
   unique_function<Error(LLJIT &)> PrePlatformSetup;
@@ -399,6 +415,14 @@ class LLJITBuilderSetters {
     return impl();
   }
 
+  /// Set a memory manager creation function. If not provided then the
+  /// ExecutorProcessControl's createDefaultMemoryManager method will be used.
+  SetterImpl &setMemoryManagerCreator(
+      LLJITBuilderState::MemoryManagerCreator CreateMemoryManager) {
+    impl().CreateMemoryManager = std::move(CreateMemoryManager);
+    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
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/LinkGraphLinkingLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/LinkGraphLinkingLayer.h
index 4413c71145fef..6fa4af1a5ca45 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/LinkGraphLinkingLayer.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/LinkGraphLinkingLayer.h
@@ -75,11 +75,7 @@ class LLVM_ABI LinkGraphLinkingLayer : public LinkGraphLayer,
                                              ResourceKey SrcKey) = 0;
   };
 
-  /// Construct a LinkGraphLinkingLayer using the ExecutorProcessControl
-  /// instance's memory manager.
-  LinkGraphLinkingLayer(ExecutionSession &ES);
-
-  /// Construct a LinkGraphLinkingLayer using a custom memory manager.
+  /// Construct a LinkGraphLinkingLayer.
   LinkGraphLinkingLayer(ExecutionSession &ES,
                         jitlink::JITLinkMemoryManager &MemMgr);
 
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/MemoryMapper.h b/llvm/include/llvm/ExecutionEngine/Orc/MemoryMapper.h
index 41c3089265a23..3768d1c22fcfe 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/MemoryMapper.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/MemoryMapper.h
@@ -21,6 +21,10 @@
 #include <mutex>
 
 namespace llvm {
+namespace jitlink {
+class LinkGraph;
+} // namespace jitlink
+
 namespace orc {
 
 /// Manages mapping, content transfer and protections for JIT memory
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
index 52361ec223873..4c4420aec7ee1 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
@@ -51,12 +51,7 @@ class LLVM_ABI ObjectLinkingLayer
   using ReturnObjectBufferFunction =
       std::function<void(std::unique_ptr<MemoryBuffer>)>;
 
-  /// Construct an ObjectLinkingLayer using the ExecutorProcessControl
-  /// instance's memory manager.
-  ObjectLinkingLayer(ExecutionSession &ES)
-      : LinkGraphLinkingLayer(ES), BaseObjectLayer(ES) {}
-
-  /// Construct an ObjectLinkingLayer using a custom memory manager.
+  /// Construct an ObjectLinkingLayer.
   ObjectLinkingLayer(ExecutionSession &ES,
                      jitlink::JITLinkMemoryManager &MemMgr)
       : LinkGraphLinkingLayer(ES, MemMgr), BaseObjectLayer(ES) {}
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/SelfExecutorProcessControl.h b/llvm/include/llvm/ExecutionEngine/Orc/SelfExecutorProcessControl.h
index f741d665c2421..0cce7e4f37c78 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/SelfExecutorProcessControl.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/SelfExecutorProcessControl.h
@@ -23,10 +23,9 @@ namespace llvm::orc {
 /// A ExecutorProcessControl implementation targeting the current process.
 class LLVM_ABI SelfExecutorProcessControl : public ExecutorProcessControl {
 public:
-  SelfExecutorProcessControl(
-      std::shared_ptr<SymbolStringPool> SSP, std::unique_ptr<TaskDispatcher> D,
-      Triple TargetTriple, unsigned PageSize,
-      std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr);
+  SelfExecutorProcessControl(std::shared_ptr<SymbolStringPool> SSP,
+                             std::unique_ptr<TaskDispatcher> D,
+                             Triple TargetTriple, unsigned PageSize);
 
   /// Create a SelfExecutorProcessControl with the given symbol string pool and
   /// memory manager.
@@ -35,8 +34,7 @@ class LLVM_ABI SelfExecutorProcessControl : public ExecutorProcessControl {
   /// be created and used by default.
   static Expected<std::unique_ptr<SelfExecutorProcessControl>>
   Create(std::shared_ptr<SymbolStringPool> SSP = nullptr,
-         std::unique_ptr<TaskDispatcher> D = nullptr,
-         std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr = nullptr);
+         std::unique_ptr<TaskDispatcher> D = nullptr);
 
   Expected<int32_t> runAsMain(ExecutorAddr MainFnAddr,
                               ArrayRef<std::string> Args) override;
@@ -49,6 +47,9 @@ class LLVM_ABI SelfExecutorProcessControl : public ExecutorProcessControl {
                         IncomingWFRHandler OnComplete,
                         ArrayRef<char> ArgBuffer) override;
 
+  Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
+  createDefaultMemoryManager() override;
+
   Expected<std::unique_ptr<DylibManager>> createDefaultDylibMgr() override;
 
   Expected<std::unique_ptr<MemoryAccess>> createDefaultMemoryAccess() override;
@@ -62,7 +63,6 @@ class LLVM_ABI SelfExecutorProcessControl : public ExecutorProcessControl {
   jitDispatchViaWrapperFunctionManager(void *Ctx, const void *FnTag,
                                        const char *Data, size_t Size);
 
-  std::unique_ptr<jitlink::JITLinkMemoryManager> OwnedMemMgr;
 #ifdef __APPLE__
   std::unique_ptr<UnwindInfoManager> UnwindInfoMgr;
 #endif // __APPLE__
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h b/llvm/include/llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h
index 250d60706729a..6527771fa34db 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h
@@ -29,20 +29,10 @@ namespace orc {
 class LLVM_ABI SimpleRemoteEPC : public ExecutorProcessControl,
                                  public SimpleRemoteEPCTransportClient {
 public:
-  /// A setup object containing a callback to construct a memory manager.
-  /// If not specified, EPCGenericJITLinkMemoryManager will be used.
-  struct Setup {
-    using CreateMemoryManagerFn =
-        Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>(
-            SimpleRemoteEPC &);
-
-    unique_function<CreateMemoryManagerFn> CreateMemoryManager;
-  };
-
   /// Create a SimpleRemoteEPC using the given transport type and args.
   template <typename TransportT, typename... TransportTCtorArgTs>
   static Expected<std::unique_ptr<SimpleRemoteEPC>>
-  Create(std::unique_ptr<TaskDispatcher> D, Setup S,
+  Create(std::unique_ptr<TaskDispatcher> D,
          TransportTCtorArgTs &&...TransportTCtorArgs) {
     std::unique_ptr<SimpleRemoteEPC> SREPC(
         new SimpleRemoteEPC(std::make_shared<SymbolStringPool>(),
@@ -52,7 +42,7 @@ class LLVM_ABI SimpleRemoteEPC : public ExecutorProcessControl,
     if (!T)
       return T.takeError();
     SREPC->T = std::move(*T);
-    if (auto Err = SREPC->setup(std::move(S)))
+    if (auto Err = SREPC->setup())
       return joinErrors(std::move(Err), SREPC->disconnect());
     return std::move(SREPC);
   }
@@ -74,6 +64,9 @@ class LLVM_ABI SimpleRemoteEPC : public ExecutorProcessControl,
                         IncomingWFRHandler OnComplete,
                         ArrayRef<char> ArgBuffer) override;
 
+  Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
+  createDefaultMemoryManager() override;
+
   Expected<std::unique_ptr<DylibManager>> createDefaultDylibMgr() override;
 
   Expected<std::unique_ptr<MemoryAccess>> createDefaultMemoryAccess() override;
@@ -99,7 +92,7 @@ class LLVM_ABI SimpleRemoteEPC : public ExecutorProcessControl,
 
   Error handleSetup(uint64_t SeqNo, ExecutorAddr TagAddr,
                     shared::WrapperFunctionBuffer ArgBytes);
-  Error setup(Setup S);
+  Error setup();
 
   Error handleResult(uint64_t SeqNo, ExecutorAddr TagAddr,
                      shared::WrapperFunctionBuffer ArgBytes);
@@ -119,7 +112,6 @@ class LLVM_ABI SimpleRemoteEPC : public ExecutorProcessControl,
   Error DisconnectErr = Error::success();
 
   std::unique_ptr<SimpleRemoteEPCTransport> T;
-  std::unique_ptr<jitlink::JITLinkMemoryManager> OwnedMemMgr;
 
   ExecutorAddr RunAsMainAddr;
   ExecutorAddr RunAsVoidFunctionAddr;
diff --git a/llvm/lib/ExecutionEngine/Orc/EPCIndirectionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/EPCIndirectionUtils.cpp
index b4e9fada83857..8bdfdc5ed44bb 100644
--- a/llvm/lib/ExecutionEngine/Orc/EPCIndirectionUtils.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/EPCIndirectionUtils.cpp
@@ -92,9 +92,9 @@ Error EPCTrampolinePool::deallocatePool() {
   std::promise<MSVCPError> DeallocResultP;
   auto DeallocResultF = DeallocResultP.get_future();
 
-  EPCIU.getExecutorProcessControl().getMemMgr().deallocate(
-      std::move(TrampolineBlocks),
-      [&](Error Err) { DeallocResultP.set_value(std::move(Err)); });
+  EPCIU.getMemManager().deallocate(std::move(TrampolineBlocks), [&](Error Err) {
+    DeallocResultP.set_value(std::move(Err));
+  });
 
   return DeallocResultF.get();
 }
@@ -111,7 +111,7 @@ Error EPCTrampolinePool::grow() {
   auto &EPC = EPCIU.getExecutorProcessControl();
   auto PageSize = EPC.getPageSize();
   auto Alloc = SimpleSegmentAlloc::Create(
-      EPC.getMemMgr(), EPC.getSymbolStringPool(), EPC.getTargetTriple(),
+      EPCIU.getMemManager(), EPC.getSymbolStringPool(), EPC.getTargetTriple(),
       nullptr, {{MemProt::Read | MemProt::Exec, {PageSize, Align(PageSize)}}});
   if (!Alloc)
     return Alloc.takeError();
@@ -234,6 +234,7 @@ EPCIndirectionUtils::ABISupport::~ABISupport() = default;
 
 Expected<std::unique_ptr<EPCIndirectionUtils>>
 EPCIndirectionUtils::Create(ExecutorProcessControl &EPC,
+                            jitlink::JITLinkMemoryManager &MemMgr,
                             MemoryAccess &MemAccess) {
   const auto &TT = EPC.getTargetTriple();
   switch (TT.getArch()) {
@@ -243,38 +244,37 @@ EPCIndirectionUtils::Create(ExecutorProcessControl &EPC,
         inconvertibleErrorCode());
   case Triple::aarch64:
   case Triple::aarch64_32:
-    return CreateWithABI<OrcAArch64>(EPC, MemAccess);
+    return CreateWithABI<OrcAArch64>(EPC, MemMgr, MemAccess);
 
   case Triple::x86:
-    return CreateWithABI<OrcI386>(EPC, MemAccess);
+    return CreateWithABI<OrcI386>(EPC, MemMgr, MemAccess);
 
   case Triple::loongarch64:
-    return CreateWithABI<OrcLoongArch64>(EPC, MemAccess);
+    return CreateWithABI<OrcLoongArch64>(EPC, MemMgr, MemAccess);
 
   case Triple::mips:
-    return CreateWithABI<OrcMips32Be>(EPC, MemAccess);
+    return CreateWithABI<OrcMips32Be>(EPC, MemMgr, MemAccess);
 
   case Triple::mipsel:
-    return CreateWithABI<OrcMips32Le>(EPC, MemAccess);
+    return CreateWithABI<OrcMips32Le>(EPC, MemMgr, MemAccess);
 
   case Triple::mips64:
   case Triple::mips64el:
-    return CreateWithABI<OrcMips64>(EPC, MemAccess);
+    return CreateWithABI<OrcMips64>(EPC, MemMgr, MemAccess);
 
   case Triple::riscv64:
-    return CreateWithABI<OrcRiscv64>(EPC, MemAccess);
+    return CreateWithABI<OrcRiscv64>(EPC, MemMgr, MemAccess);
 
   case Triple::x86_64:
     if (TT.getOS() == Triple::OSType::Win32)
-      return CreateWithABI<OrcX86_64_Win32>(EPC, MemAccess);
+      return CreateWithABI<OrcX86_64_Win32>(EPC, MemMgr, MemAccess);
     else
-      return CreateWithABI<OrcX86_64_SysV>(EPC, MemAccess);
+      return CreateWithABI<OrcX86_64_SysV>(EPC, MemMgr, MemAccess);
   }
 }
 
 Error EPCIndirectionUtils::cleanup() {
 
-  auto &MemMgr = EPC.getMemMgr();
   auto Err = MemMgr.deallocate(std::move(IndirectStubAllocs));
 
   if (TP)
@@ -296,11 +296,10 @@ EPCIndirectionUtils::writeResolverBlock(ExecutorAddr ReentryFnAddr,
   assert(ABI && "ABI can not be null");
   auto ResolverSize = ABI->getResolverCodeSize();
 
-  auto Alloc =
-      SimpleSegmentAlloc::Create(EPC.getMemMgr(), EPC.getSymbolStringPool(),
-                                 EPC.getTargetTriple(), nullptr,
-                                 {{MemProt::Read | MemProt::Exec,
-                                   {ResolverSize, Align(EPC.getPageSize())}}});
+  auto Alloc = SimpleSegmentAlloc::Create(
+      MemMgr, EPC.getSymbolStringPool(), EPC.getTargetTriple(), nullptr,
+      {{MemProt::Read | MemProt::Exec,
+        {ResolverSize, Align(EPC.getPageSize())}}});
 
   if (!Alloc)
     return Alloc.takeError();
@@ -339,9 +338,10 @@ LazyCallThroughManager &EPCIndirectionUtils::createLazyCallThroughManager(
 }
 
 EPCIndirectionUtils::EPCIndirectionUtils(ExecutorProcessControl &EPC,
+                                         jitlink::JITLinkMemoryManager &MemMgr,
                                          MemoryAccess &MemAccess,
                                          std::unique_ptr<ABISupport> ABI)
-    : EPC(EPC), MemAccess(MemAccess), ABI(std::move(ABI)) {
+    : EPC(EPC), MemMgr(MemMgr), MemAccess(MemAccess), ABI(std::move(ABI)) {
   assert(this->ABI && "ABI can not be null");
 
   assert(EPC.getPageSize() > getABISupport().getStubSize() &&
@@ -367,8 +367,7 @@ EPCIndirectionUtils::getIndirectStubs(unsigned NumStubs) {
     auto PtrProt = MemProt::Read | MemProt::Write;
 
     auto Alloc = SimpleSegmentAlloc::Create(
-        EPC.getMemMgr(), EPC.getSymbolStringPool(), EPC.getTargetTriple(),
-        nullptr,
+        MemMgr, EPC.getSymbolStringPool(), EPC.getTargetTriple(), nullptr,
         {{StubProt, {static_cast<size_t>(StubBytes), Align(PageSize)}},
          {PtrProt, {static_cast<size_t>(PtrBytes), Align(PageSize)}}});
 
diff --git a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
index 5d8d1b0bb83a0..18db7d24a8262 100644
--- a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
@@ -777,7 +777,7 @@ Error LLJITBuilderState::prepareForConstruction() {
       D = std::make_unique<InPlaceTaskDispatcher>();
 #endif // LLVM_ENABLE_THREADS
     if (auto EPCOrErr =
-            SelfExecutorProcessControl::Create(nullptr, std::move(D), nullptr))
+            SelfExecutorProcessControl::Create(nullptr, std::move(D)))
       EPC = std::move(*EPCOrErr);
     else
       return EPCOrErr.takeError();
@@ -943,6 +943,13 @@ Expected<ExecutorAddr> LLJIT::lookupLinkerMangled(JITDylib &JD,
     return Sym.takeError();
 }
 
+Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
+LLJIT::createMemoryManager(LLJITBuilderState &S, ExecutionSession &ES) {
+  if (S.CreateMemoryManager)
+    return S.CreateMemoryManager(ES);
+  return ES.getExecutorProcessControl().createDefaultMemoryManager();
+}
+
 Expected<std::unique_ptr<ObjectLayer>>
 LLJIT::createObjectLinkingLayer(LLJITBuilderState &S, ExecutionSession &ES,
                                 jitlink::JITLinkMemoryManager &MemMgr) {
@@ -1014,6 +1021,13 @@ LLJIT::LLJIT(LLJITBuilderState &S, Error &Err)
     }
   }
 
+  if (auto MM = createMemoryManager(S, *ES))
+    MemMgr = std::move(*MM);
+  else {
+    Err = MM.takeError();
+    return;
+  }
+
   if (auto DM = ES->getExecutorProcessControl().createDefaultDylibMgr())
     DylibMgr = std::move(*DM);
   else {
@@ -1021,8 +1035,7 @@ LLJIT::LLJIT(LLJITBuilderState &S, Error &Err)
     return;
   }
 
-  auto ObjLayer = createObjectLinkingLayer(
-      S, *ES, ES->getExecutorProcessControl().getMemMgr());
+  auto ObjLayer = createObjectLinkingLayer(S, *ES, *MemMgr);
   if (!ObjLayer) {
     Err = ObjLayer.takeError();
     return;
diff --git a/llvm/lib/ExecutionEngine/Orc/LinkGraphLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/LinkGraphLinkingLayer.cpp
index c6aee74c6dc10..f076114a76548 100644
--- a/llvm/lib/ExecutionEngine/Orc/LinkGraphLinkingLayer.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/LinkGraphLinkingLayer.cpp
@@ -412,11 +412,6 @@ class LinkGraphLinkingLayer::JITLinkCtx final : public JITLinkContext {
 
 LinkGraphLinkingLayer::Plugin::~Plugin() = default;
 
-LinkGraphLinkingLayer::LinkGraphLinkingLayer(ExecutionSession &ES)
-    : LinkGraphLayer(ES), MemMgr(ES.getExecutorProcessControl().getMemMgr()) {
-  ES.registerResourceManager(*this);
-}
-
 LinkGraphLinkingLayer::LinkGraphLinkingLayer(ExecutionSession &ES,
                                              JITLinkMemoryManager &MemMgr)
     : LinkGraphLayer(ES), MemMgr(MemMgr) {
diff --git a/llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp b/llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp
index 4e7db822776cc..77768886f72a8 100644
--- a/llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp
@@ -10,6 +10,7 @@
 
 #include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX
 #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
+#include "llvm/Support/MSVCErrorWorkarounds.h"
 #include "llvm/Support/WindowsError.h"
 
 #if defined(LLVM_ON_UNIX) && !defined(__ANDROID__)
diff --git a/llvm/lib/ExecutionEngine/Orc/SelfExecutorProcessControl.cpp b/llvm/lib/ExecutionEngine/Orc/SelfExecutorProcessControl.cpp
index b24abafa82895..7c8a6054f03ae 100644
--- a/llvm/lib/ExecutionEngine/Orc/SelfExecutorProcessControl.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/SelfExecutorProcessControl.cpp
@@ -8,6 +8,7 @@
 
 #include "llvm/ExecutionEngine/Orc/SelfExecutorProcessControl.h"
 
+#include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
 #include "llvm/ExecutionEngine/Orc/Core.h"
 #include "llvm/ExecutionEngine/Orc/DylibManager.h"
 #include "llvm/ExecutionEngine/Orc/InProcessMemoryAccess.h"
@@ -35,18 +36,11 @@ class SelfExecutorProcessControl::InProcessDylibManager : public DylibManager {
 
 SelfExecutorProcessControl::SelfExecutorProcessControl(
     std::shared_ptr<SymbolStringPool> SSP, std::unique_ptr<TaskDispatcher> D,
-    Triple TargetTriple, unsigned PageSize,
-    std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr)
+    Triple TargetTriple, unsigned PageSize)
     : ExecutorProcessControl(std::move(SSP), std::move(D)) {
 
-  OwnedMemMgr = std::move(MemMgr);
-  if (!OwnedMemMgr)
-    OwnedMemMgr = std::make_unique<jitlink::InProcessMemoryManager>(
-        sys::Process::getPageSizeEstimate());
-
   this->TargetTriple = std::move(TargetTriple);
   this->PageSize = PageSize;
-  this->MemMgr = OwnedMemMgr.get();
   this->JDI = {ExecutorAddr::fromPtr(jitDispatchViaWrapperFunctionManager),
                ExecutorAddr::fromPtr(this)};
 
@@ -62,9 +56,8 @@ SelfExecutorProcessControl::SelfExecutorProcessControl(
 }
 
 Expected<std::unique_ptr<SelfExecutorProcessControl>>
-SelfExecutorProcessControl::Create(
-    std::shared_ptr<SymbolStringPool> SSP, std::unique_ptr<TaskDispatcher> D,
-    std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) {
+SelfExecutorProcessControl::Create(std::shared_ptr<SymbolStringPool> SSP,
+                                   std::unique_ptr<TaskDispatcher> D) {
 
   if (!SSP)
     SSP = std::make_shared<SymbolStringPool>();
@@ -79,8 +72,7 @@ SelfExecutorProcessControl::Create(
   Triple TT(sys::getProcessTriple());
 
   return std::make_unique<SelfExecutorProcessControl>(
-      std::move(SSP), std::move(D), std::move(TT), *PageSize,
-      std::move(MemMgr));
+      std::move(SSP), std::move(D), std::move(TT), *PageSize);
 }
 
 Expected<int32_t>
@@ -117,6 +109,12 @@ Error SelfExecutorProcessControl::disconnect() {
   return Error::success();
 }
 
+Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
+SelfExecutorProcessControl::createDefaultMemoryManager() {
+  return std::make_unique<jitlink::InProcessMemoryManager>(
+      sys::Process::getPageSizeEstimate());
+}
+
 Expected<std::unique_ptr<DylibManager>>
 SelfExecutorProcessControl::createDefaultDylibMgr() {
   char Prefix = TargetTriple.isOSBinFormatMachO() ? '_' : '\0';
diff --git a/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp b/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp
index 6cc262c0ed44d..f2cd479a91113 100644
--- a/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp
@@ -87,6 +87,11 @@ void SimpleRemoteEPC::callWrapperAsync(ExecutorAddr WrapperFnAddr,
   }
 }
 
+Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
+SimpleRemoteEPC::createDefaultMemoryManager() {
+  return EPCGenericJITLinkMemoryManager::Create(getExecutionSession());
+}
+
 Expected<std::unique_ptr<DylibManager>>
 SimpleRemoteEPC::createDefaultDylibMgr() {
   auto DM = EPCGenericDylibManager::CreateWithDefaultBootstrapSymbols(*this);
@@ -278,7 +283,7 @@ Error SimpleRemoteEPC::handleSetup(uint64_t SeqNo, ExecutorAddr TagAddr,
   return Error::success();
 }
 
-Error SimpleRemoteEPC::setup(Setup S) {
+Error SimpleRemoteEPC::setup() {
   using namespace SimpleRemoteEPCDefaultBootstrapSymbolNames;
 
   std::promise<MSVCPExpected<SimpleRemoteEPCExecutorInfo>> EIP;
@@ -342,16 +347,6 @@ Error SimpleRemoteEPC::setup(Setup S) {
            {RunAsIntFunctionAddr, rt::RunAsIntFunctionWrapperName}}))
     return Err;
 
-  // Set a default CreateMemoryManager if none is specified.
-  if (!S.CreateMemoryManager)
-    S.CreateMemoryManager = createDefaultMemoryManager;
-
-  if (auto MemMgr = S.CreateMemoryManager(*this)) {
-    OwnedMemMgr = std::move(*MemMgr);
-    this->MemMgr = OwnedMemMgr.get();
-  } else
-    return MemMgr.takeError();
-
   return Error::success();
 }
 
diff --git a/llvm/tools/lli/lli.cpp b/llvm/tools/lli/lli.cpp
index 3047addb0aae2..38496cbd5ff77 100644
--- a/llvm/tools/lli/lli.cpp
+++ b/llvm/tools/lli/lli.cpp
@@ -1254,8 +1254,8 @@ static Expected<std::unique_ptr<orc::ExecutorProcessControl>> launchRemote() {
 
   // Return a SimpleRemoteEPC instance connected to our end of the pipes.
   return orc::SimpleRemoteEPC::Create<orc::FDSimpleRemoteEPCTransport>(
-      std::make_unique<llvm::orc::InPlaceTaskDispatcher>(),
-      llvm::orc::SimpleRemoteEPC::Setup(), PipeFD[1][0], PipeFD[0][1]);
+      std::make_unique<llvm::orc::InPlaceTaskDispatcher>(), PipeFD[1][0],
+      PipeFD[0][1]);
 #endif
 }
 
diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
index 945939967087a..c360e47de7907 100644
--- a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
+++ b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
@@ -753,9 +753,9 @@ static std::unique_ptr<JITLinkMemoryManager> createInProcessMemoryManager() {
 }
 
 Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
-createSimpleRemoteMemoryManager(SimpleRemoteEPC &SREPC) {
+createSimpleRemoteMemoryManager(ExecutorProcessControl &EPC) {
   SimpleRemoteMemoryMapper::SymbolAddrs SAs;
-  if (auto Err = SREPC.getBootstrapSymbols(
+  if (auto Err = EPC.getBootstrapSymbols(
           {{SAs.Instance, rt::SimpleExecutorMemoryManagerInstanceName},
            {SAs.Reserve, rt::SimpleExecutorMemoryManagerReserveWrapperName},
            {SAs.Initialize,
@@ -770,13 +770,13 @@ createSimpleRemoteMemoryManager(SimpleRemoteEPC &SREPC) {
   size_t SlabSize = 1024 * 1024 * 1024;
 #endif
   return MapperJITLinkMemoryManager::CreateWithMapper<SimpleRemoteMemoryMapper>(
-      SlabSize, SREPC, SAs);
+      SlabSize, EPC, SAs);
 }
 
 Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
-createSharedMemoryManager(SimpleRemoteEPC &SREPC) {
+createSharedMemoryManager(ExecutorProcessControl &EPC) {
   SharedMemoryMapper::SymbolAddrs SAs;
-  if (auto Err = SREPC.getBootstrapSymbols(
+  if (auto Err = EPC.getBootstrapSymbols(
           {{SAs.Instance, rt::ExecutorSharedMemoryMapperServiceInstanceName},
            {SAs.Reserve,
             rt::ExecutorSharedMemoryMapperServiceReserveWrapperName},
@@ -798,24 +798,27 @@ createSharedMemoryManager(SimpleRemoteEPC &SREPC) {
     SlabSize = ExitOnErr(getSlabAllocSize(SlabAllocateSizeString));
 
   return MapperJITLinkMemoryManager::CreateWithMapper<SharedMemoryMapper>(
-      SlabSize, SREPC, SAs);
-}
-
-#if LLVM_ON_UNIX && LLVM_ENABLE_THREADS
-static void setupEPCRemoteMemoryManager(SimpleRemoteEPC::Setup &S) {
-  switch (UseMemMgr) {
-  case MemMgr::Default:
-  case MemMgr::Generic:
-    break;
-  case MemMgr::SimpleRemote:
-    S.CreateMemoryManager = createSimpleRemoteMemoryManager;
-    break;
-  case MemMgr::Shared:
-    S.CreateMemoryManager = createSharedMemoryManager;
-    break;
+      SlabSize, EPC, SAs);
+}
+
+static Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
+createMemoryManager(ExecutorProcessControl &EPC) {
+  if (OutOfProcessExecutor.getNumOccurrences() ||
+      OutOfProcessExecutorConnect.getNumOccurrences()) {
+
+    switch (UseMemMgr) {
+    case MemMgr::Default:
+    case MemMgr::Generic:
+      return EPC.createDefaultMemoryManager();
+    case MemMgr::SimpleRemote:
+      return createSimpleRemoteMemoryManager(EPC);
+    case MemMgr::Shared:
+      return createSharedMemoryManager(EPC);
+    }
   }
+
+  return createInProcessMemoryManager();
 }
-#endif
 
 static Expected<MaterializationUnit::Interface>
 getTestObjectFileInterface(Session &S, MemoryBufferRef O) {
@@ -974,12 +977,9 @@ static Expected<std::unique_ptr<ExecutorProcessControl>> launchExecutor() {
   close(ToExecutor[ReadEnd]);
   close(FromExecutor[WriteEnd]);
 
-  auto S = SimpleRemoteEPC::Setup();
-  setupEPCRemoteMemoryManager(S);
-
   return SimpleRemoteEPC::Create<FDSimpleRemoteEPCTransport>(
       std::make_unique<DynamicThreadPoolTaskDispatcher>(MaterializationThreads),
-      std::move(S), FromExecutor[ReadEnd], ToExecutor[WriteEnd]);
+      FromExecutor[ReadEnd], ToExecutor[WriteEnd]);
 #endif
 }
 
@@ -1063,12 +1063,9 @@ static Expected<std::unique_ptr<ExecutorProcessControl>> connectToExecutor() {
   if (!SockFD)
     return SockFD.takeError();
 
-  auto S = SimpleRemoteEPC::Setup();
-  setupEPCRemoteMemoryManager(S);
-
   return SimpleRemoteEPC::Create<FDSimpleRemoteEPCTransport>(
-      std::make_unique<DynamicThreadPoolTaskDispatcher>(std::nullopt),
-      std::move(S), *SockFD, *SockFD);
+      std::make_unique<DynamicThreadPoolTaskDispatcher>(std::nullopt), *SockFD,
+      *SockFD);
 #endif
 }
 
@@ -1172,7 +1169,7 @@ Expected<std::unique_ptr<Session>> Session::Create(Triple TT,
 
     EPC = std::make_unique<SelfExecutorProcessControl>(
         std::make_shared<SymbolStringPool>(), std::move(Dispatcher),
-        std::move(TT), *PageSize, createInProcessMemoryManager());
+        std::move(TT), *PageSize);
   }
 
   Error Err = Error::success();
@@ -1225,10 +1222,16 @@ Session::Session(std::unique_ptr<ExecutorProcessControl> EPC, Error &Err)
     Session &S;
   };
 
-  ObjLayer = std::make_unique<ObjectLinkingLayer>(
-      ES, ES.getExecutorProcessControl().getMemMgr());
   ErrorAsOutParameter _(&Err);
 
+  if (auto MM = createMemoryManager(ES.getExecutorProcessControl())) {
+    MemoryMgr = std::move(*MM);
+    ObjLayer = std::make_unique<orc::ObjectLinkingLayer>(ES, *MemoryMgr);
+  } else {
+    Err = MM.takeError();
+    return;
+  }
+
   if (auto DM = ES.getExecutorProcessControl().createDefaultDylibMgr())
     DylibMgr = std::move(*DM);
   else {
diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink.h b/llvm/tools/llvm-jitlink/llvm-jitlink.h
index d131e78073d0d..1be4df684b9b3 100644
--- a/llvm/tools/llvm-jitlink/llvm-jitlink.h
+++ b/llvm/tools/llvm-jitlink/llvm-jitlink.h
@@ -78,6 +78,7 @@ struct Session {
   };
 
   orc::ExecutionSession ES;
+  std::unique_ptr<jitlink::JITLinkMemoryManager> MemoryMgr;
   std::unique_ptr<orc::DylibManager> DylibMgr;
   orc::JITDylib *MainJD = nullptr;
   orc::JITDylib *ProcessSymsJD = nullptr;
diff --git a/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h b/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h
index 044d8b37f3baa..10145b5b546df 100644
--- a/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h
+++ b/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h
@@ -120,6 +120,11 @@ class UnsupportedExecutorProcessControl : public ExecutorProcessControl,
     llvm_unreachable("Unsupported");
   }
 
+  Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
+  createDefaultMemoryManager() override {
+    llvm_unreachable("Unsupported");
+  }
+
   Expected<std::unique_ptr<DylibManager>> createDefaultDylibMgr() override {
     llvm_unreachable("Unsupported");
   }



More information about the cfe-commits mailing list