[llvm] [ORC] Share memory-map bindings between their two clients (PR #216911)

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 17 21:46:09 PDT 2026


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

SimpleMemoryMapBindings holds an executor-side memory manager's instance address and a Proxy per operation: reserve, initialize, deinitialize, release. EPCGenericJITLinkMemoryManager and SimpleRemoteMemoryMapper both take one, so the operations are described once rather than per client.

SimpleRemoteMemoryMapper previously held a SymbolAddrs struct and made raw EPC.callSPSWrapperAsync calls. Going through proxies drops the per-call serialization-error plumbing, since Proxy already folds that into the result.

sps::createSimpleMemoryMapBindings resolves the bindings with a single lookup, under the specs' default (SimpleNativeMemoryMap) names. The specs move out of EPCGenericJITLinkMemoryManagerSPS.h alongside the bindings, as they describe the interface rather than either client.

llvm-jitlink's simple-remote memory manager uses that instead of reading the legacy SimpleExecutorMemoryManager* names out of the bootstrap symbol map.

>From cbec68ecf821fe8ac94c973c83b918234b2706bc Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at gmail.com>
Date: Tue, 18 Aug 2026 14:32:37 +1000
Subject: [PATCH] [ORC] Share memory-map bindings between their two clients

SimpleMemoryMapBindings holds an executor-side memory manager's instance
address and a Proxy per operation: reserve, initialize, deinitialize,
release. EPCGenericJITLinkMemoryManager and SimpleRemoteMemoryMapper
both take one, so the operations are described once rather than per
client.

SimpleRemoteMemoryMapper previously held a SymbolAddrs struct and made
raw EPC.callSPSWrapperAsync calls. Going through proxies drops the
per-call serialization-error plumbing, since Proxy already folds that
into the result.

sps::createSimpleMemoryMapBindings resolves the bindings with a single
lookup, under the specs' default (SimpleNativeMemoryMap) names. The
specs move out of EPCGenericJITLinkMemoryManagerSPS.h alongside the
bindings, as they describe the interface rather than either client.

llvm-jitlink's simple-remote memory manager uses that instead of reading
the legacy SimpleExecutorMemoryManager* names out of the bootstrap
symbol map.
---
 .../Orc/EPCGenericJITLinkMemoryManager.h      | 39 ++---------
 .../Orc/EPCGenericJITLinkMemoryManagerSPS.h   | 28 ++------
 .../ExecutionEngine/Orc/SimpleMemoryMap.h     | 68 +++++++++++++++++++
 .../ExecutionEngine/Orc/SimpleMemoryMapSPS.h  | 57 ++++++++++++++++
 .../Orc/SimpleRemoteMemoryMapper.h            | 63 +++++++----------
 llvm/lib/ExecutionEngine/Orc/CMakeLists.txt   |  1 +
 .../Orc/EPCGenericJITLinkMemoryManagerSPS.cpp | 21 ++----
 .../Orc/SimpleMemoryMapSPS.cpp                | 37 ++++++++++
 .../Orc/SimpleRemoteMemoryMapper.cpp          | 65 ++++--------------
 llvm/tools/llvm-jitlink/llvm-jitlink.cpp      | 17 ++---
 .../llvm/lib/ExecutionEngine/Orc/BUILD.gn     |  1 +
 11 files changed, 220 insertions(+), 177 deletions(-)
 create mode 100644 llvm/include/llvm/ExecutionEngine/Orc/SimpleMemoryMap.h
 create mode 100644 llvm/include/llvm/ExecutionEngine/Orc/SimpleMemoryMapSPS.h
 create mode 100644 llvm/lib/ExecutionEngine/Orc/SimpleMemoryMapSPS.cpp

diff --git a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h
index 9ce09cf089401..69e5f47f18fc4 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h
@@ -23,8 +23,8 @@
 
 #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
 #include "llvm/ExecutionEngine/Orc/Core.h"
-#include "llvm/ExecutionEngine/Orc/Proxy.h"
 #include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
+#include "llvm/ExecutionEngine/Orc/SimpleMemoryMap.h"
 #include "llvm/Support/Compiler.h"
 
 #include <cstdint>
@@ -35,41 +35,10 @@ namespace orc {
 class LLVM_ABI EPCGenericJITLinkMemoryManager
     : public jitlink::JITLinkMemoryManager {
 public:
-  /// Reserve an address range of the given size; returns its base.
-  using ReserveProxy = Proxy<Expected<ExecutorAddr>(ExecutorAddr, uint64_t)>;
-
-  /// Apply a finalize request; returns a key for the initialized allocation.
-  using InitializeProxy =
-      Proxy<Expected<ExecutorAddr>(ExecutorAddr, tpctypes::FinalizeRequest)>;
-
-  /// Deinitialize the allocations with the given base addresses (running their
-  /// deallocation actions) without releasing their memory.
-  using DeinitializeProxy = Proxy<Error(ExecutorAddr, ArrayRef<ExecutorAddr>)>;
-
-  /// Release the allocations with the given base addresses.
-  using ReleaseProxy = Proxy<Error(ExecutorAddr, ArrayRef<ExecutorAddr>)>;
-
-  /// The resolved controller-side handle to an executor-side memory manager:
-  /// the address of the allocator instance (passed as the first argument to
-  /// each call) plus the proxies for its functions. These are
-  /// protocol-agnostic: sps::createEPCGenericJITLinkMemoryManager populates
-  /// them for the runtime's SPS controller interface, but a client targeting a
-  /// different protocol can build its own Bindings and pass them to the
-  /// constructor.
-  ///
-  /// Deinitialize is part of the interface but is not currently used by this
-  /// manager.
-  struct Bindings {
-    ExecutorAddr Instance;
-    ReserveProxy Reserve;
-    InitializeProxy Initialize;
-    DeinitializeProxy Deinitialize;
-    ReleaseProxy Release;
-  };
-
   /// Create an EPCGenericJITLinkMemoryManager instance from a given set of
   /// memory-manager bindings.
-  EPCGenericJITLinkMemoryManager(ExecutionSession &ES, Bindings B)
+  EPCGenericJITLinkMemoryManager(ExecutionSession &ES,
+                                 SimpleMemoryMapBindings B)
       : ES(ES), B(std::move(B)) {}
 
   void allocate(const jitlink::JITLinkDylib *JD, jitlink::LinkGraph &G,
@@ -91,7 +60,7 @@ class LLVM_ABI EPCGenericJITLinkMemoryManager
                           OnAllocatedFunction OnAllocated);
 
   ExecutionSession &ES;
-  Bindings B;
+  SimpleMemoryMapBindings B;
 };
 
 } // end namespace orc
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerSPS.h b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerSPS.h
index 1da5bc0e5c186..b23e5e37b1749 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerSPS.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerSPS.h
@@ -6,15 +6,11 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// Binds EPCGenericJITLinkMemoryManager to the ORC runtime's SPS controller
-// interface: a ProxySpec per operation, plus factories that resolve them and
-// construct an instance.
+// Factories that build an EPCGenericJITLinkMemoryManager over the ORC runtime's
+// SPS controller interface.
 //
-// Each spec pairs one of EPCGenericJITLinkMemoryManager's proxies with its
-// controller-interface descriptor in Shared/SPSCI/SimpleNativeMemoryMapSPSCI.h,
-// which supplies the wrapper name and wire signature. The specs are public so
-// that clients can resolve the operations under non-default names, using
-// recordProxy<Spec>(&P, Name) with lookupAndApply.
+// The bindings and their ProxySpecs are shared with the other drivers of the
+// runtime's memory manager; see SimpleMemoryMapSPS.h.
 //
 //===----------------------------------------------------------------------===//
 
@@ -22,27 +18,13 @@
 #define LLVM_EXECUTIONENGINE_ORC_EPCGENERICJITLINKMEMORYMANAGERSPS_H
 
 #include "llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h"
-#include "llvm/ExecutionEngine/Orc/SPSProxySpec.h"
-#include "llvm/ExecutionEngine/Orc/Shared/SPSCI/SimpleNativeMemoryMapSPSCI.h"
+#include "llvm/ExecutionEngine/Orc/SimpleMemoryMapSPS.h"
 #include "llvm/Support/Compiler.h"
 
 #include <memory>
 
 namespace llvm::orc::sps {
 
-using MemMgrReserveProxySpec =
-    ProxySpec<EPCGenericJITLinkMemoryManager::ReserveProxy,
-              rt::sps_ci::MemMgrReserve>;
-using MemMgrInitializeProxySpec =
-    ProxySpec<EPCGenericJITLinkMemoryManager::InitializeProxy,
-              rt::sps_ci::MemMgrInitialize>;
-using MemMgrDeinitializeProxySpec =
-    ProxySpec<EPCGenericJITLinkMemoryManager::DeinitializeProxy,
-              rt::sps_ci::MemMgrDeinitialize>;
-using MemMgrReleaseProxySpec =
-    ProxySpec<EPCGenericJITLinkMemoryManager::ReleaseProxy,
-              rt::sps_ci::MemMgrRelease>;
-
 /// Create an EPCGenericJITLinkMemoryManager for the ORC runtime's
 /// SimpleNativeMemoryMap interface, resolving its symbols in the given
 /// JITDylib.
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/SimpleMemoryMap.h b/llvm/include/llvm/ExecutionEngine/Orc/SimpleMemoryMap.h
new file mode 100644
index 0000000000000..27d638870ce19
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/Orc/SimpleMemoryMap.h
@@ -0,0 +1,68 @@
+//===- SimpleMemoryMap.h - Memory-map bindings ------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// A controller-side handle to an executor-side memory manager implementing the
+// simple memory-map interface -- reserve, initialize, deinitialize, release --
+// plus the address of the manager instance those calls operate on.
+//
+// Utilities that drive such a manager share this handle:
+// EPCGenericJITLinkMemoryManager and SimpleRemoteMemoryMapper both hold one, so
+// the operations are described once rather than per client.
+//
+// This header is protocol-agnostic, and says nothing about which executor-side
+// implementation is on the other end. See SimpleMemoryMapSPS.h to bind a handle
+// over the ORC runtime's SPS controller interface; that resolves the runtime's
+// SimpleNativeMemoryMap by default, but any implementation exporting the same
+// operations can be bound by resolving them under its own names.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_SIMPLEMEMORYMAP_H
+#define LLVM_EXECUTIONENGINE_ORC_SIMPLEMEMORYMAP_H
+
+#include "llvm/ExecutionEngine/Orc/Proxy.h"
+#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
+
+#include <cstdint>
+
+namespace llvm::orc {
+
+/// The resolved controller-side handle to an executor-side memory manager: the
+/// address of the manager instance, which is passed as the first argument to
+/// each call, plus the proxies for its operations.
+///
+/// These are protocol-agnostic: sps::createSimpleMemoryMapBindings populates
+/// them over the runtime's SPS controller interface, but a client targeting a
+/// different protocol -- or a different executor-side implementation of these
+/// operations -- can build its own and pass them to the utility that will use
+/// them.
+struct SimpleMemoryMapBindings {
+  /// Reserve an address range of the given size; returns its base.
+  using ReserveProxy = Proxy<Expected<ExecutorAddr>(ExecutorAddr, uint64_t)>;
+
+  /// Apply a finalize request; returns a key for the initialized allocation.
+  using InitializeProxy =
+      Proxy<Expected<ExecutorAddr>(ExecutorAddr, tpctypes::FinalizeRequest)>;
+
+  /// Deinitialize the allocations with the given keys (running their
+  /// deallocation actions) without releasing their memory.
+  using DeinitializeProxy = Proxy<Error(ExecutorAddr, ArrayRef<ExecutorAddr>)>;
+
+  /// Release the reservations with the given base addresses.
+  using ReleaseProxy = Proxy<Error(ExecutorAddr, ArrayRef<ExecutorAddr>)>;
+
+  ExecutorAddr Instance;
+  ReserveProxy Reserve;
+  InitializeProxy Initialize;
+  DeinitializeProxy Deinitialize;
+  ReleaseProxy Release;
+};
+
+} // namespace llvm::orc
+
+#endif // LLVM_EXECUTIONENGINE_ORC_SIMPLEMEMORYMAP_H
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/SimpleMemoryMapSPS.h b/llvm/include/llvm/ExecutionEngine/Orc/SimpleMemoryMapSPS.h
new file mode 100644
index 0000000000000..f3bf906d1cdca
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/Orc/SimpleMemoryMapSPS.h
@@ -0,0 +1,57 @@
+//===- SimpleMemoryMapSPS.h - SPS memory-map bindings -----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Binds SimpleMemoryMapBindings to the ORC runtime's SPS controller
+// interface: a ProxySpec per operation, plus operations that resolve them.
+//
+// Each spec pairs one of the bindings' proxies with its controller-interface
+// descriptor in Shared/SPSCI/SimpleNativeMemoryMapSPSCI.h, which supplies the
+// wrapper name and wire signature. The specs are public so that clients can
+// resolve the operations under non-default names, using
+// recordProxy<Spec>(&P, Name) with lookupAndApply.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_SIMPLEMEMORYMAPSPS_H
+#define LLVM_EXECUTIONENGINE_ORC_SIMPLEMEMORYMAPSPS_H
+
+#include "llvm/ExecutionEngine/Orc/LookupAndApply.h"
+#include "llvm/ExecutionEngine/Orc/SPSProxySpec.h"
+#include "llvm/ExecutionEngine/Orc/Shared/SPSCI/SimpleNativeMemoryMapSPSCI.h"
+#include "llvm/ExecutionEngine/Orc/SimpleMemoryMap.h"
+#include "llvm/Support/Compiler.h"
+
+namespace llvm::orc::sps {
+
+using MemMgrReserveProxySpec =
+    ProxySpec<SimpleMemoryMapBindings::ReserveProxy, rt::sps_ci::MemMgrReserve>;
+using MemMgrInitializeProxySpec =
+    ProxySpec<SimpleMemoryMapBindings::InitializeProxy,
+              rt::sps_ci::MemMgrInitialize>;
+using MemMgrDeinitializeProxySpec =
+    ProxySpec<SimpleMemoryMapBindings::DeinitializeProxy,
+              rt::sps_ci::MemMgrDeinitialize>;
+using MemMgrReleaseProxySpec =
+    ProxySpec<SimpleMemoryMapBindings::ReleaseProxy, rt::sps_ci::MemMgrRelease>;
+
+/// Build bindings over the SPS controller interface, resolving the operations
+/// in the given JITDylib under the specs' default (SimpleNativeMemoryMap)
+/// names.
+///
+/// To bind a different executor-side implementation, use the specs above with
+/// recordProxy<Spec>(&P, Name) to resolve its own names instead.
+LLVM_ABI Expected<SimpleMemoryMapBindings>
+createSimpleMemoryMapBindings(JITDylib &JD);
+
+/// As above, resolving the operations in ES's bootstrap JITDylib.
+LLVM_ABI Expected<SimpleMemoryMapBindings>
+createSimpleMemoryMapBindings(ExecutionSession &ES);
+
+} // namespace llvm::orc::sps
+
+#endif // LLVM_EXECUTIONENGINE_ORC_SIMPLEMEMORYMAPSPS_H
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/SimpleRemoteMemoryMapper.h b/llvm/include/llvm/ExecutionEngine/Orc/SimpleRemoteMemoryMapper.h
index 644c4f614108e..b1a0e19677692 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/SimpleRemoteMemoryMapper.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/SimpleRemoteMemoryMapper.h
@@ -6,8 +6,11 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// A simple memory mapper that uses EPC calls to implement reserve, initialize,
-// deinitialize, and release.
+// A simple memory mapper that implements reserve, initialize, deinitialize and
+// release by driving an executor-side memory manager through Proxy objects.
+//
+// This header is protocol-agnostic. To build the bindings for the ORC runtime's
+// SPS controller interface, see SimpleMemoryMapSPS.h.
 //
 //===----------------------------------------------------------------------===//
 
@@ -15,71 +18,53 @@
 #define LLVM_EXECUTIONENGINE_ORC_SIMPLEREMOTEMEMORYMAPPER_H
 
 #include "llvm/ExecutionEngine/Orc/MemoryMapper.h"
+#include "llvm/ExecutionEngine/Orc/SimpleMemoryMap.h"
 
 namespace llvm::orc {
 
-/// Manages remote memory by making SPS-based EPC calls.
+/// Manages remote memory by driving an executor-side memory manager.
 class LLVM_ABI SimpleRemoteMemoryMapper final : public MemoryMapper {
 public:
-  struct SymbolAddrs {
-    ExecutorAddr Instance;
-    ExecutorAddr Reserve;
-    ExecutorAddr Initialize;
-    ExecutorAddr Deinitialize;
-    ExecutorAddr Release;
-  };
-
-  SimpleRemoteMemoryMapper(ExecutorProcessControl &EPC, SymbolAddrs SAs);
+  /// Create a SimpleRemoteMemoryMapper from a given set of memory-manager
+  /// bindings.
+  SimpleRemoteMemoryMapper(ExecutionSession &ES, SimpleMemoryMapBindings B);
 
   static Expected<std::unique_ptr<SimpleRemoteMemoryMapper>>
-  Create(ExecutorProcessControl &EPC, SymbolAddrs SAs) {
-    return std::make_unique<SimpleRemoteMemoryMapper>(EPC, SAs);
+  Create(ExecutionSession &ES, SimpleMemoryMapBindings B) {
+    return std::make_unique<SimpleRemoteMemoryMapper>(ES, std::move(B));
   }
 
-  unsigned int getPageSize() override { return EPC.getPageSize(); }
+  unsigned int getPageSize() override {
+    return ES.getExecutorProcessControl().getPageSize();
+  }
 
-  /// Reserves memory in the remote process by calling a remote
-  /// SPS-wrapper-function with signature
-  ///
-  ///   SPSExpected<SPSExecutorAddr>(uint64_t Size).
-  ///
-  /// On success, returns the base address of the reserved range.
+  /// Reserves memory in the executor, returning the base address of the
+  /// reserved range on success.
   void reserve(size_t NumBytes, OnReservedFunction OnReserved) override;
 
   char *prepare(jitlink::LinkGraph &G, ExecutorAddr Addr,
                 size_t ContentSize) override;
 
-  /// Initializes memory within a previously reserved region (applying
-  /// protections and running any finalization actions) by calling a remote
-  /// SPS-wrapper-function with signature
-  ///
-  ///   SPSExpected<SPSExecutorAddr>(SPSFinalizeRequest)
+  /// Initializes memory within a previously reserved region, applying
+  /// protections and running any finalization actions.
   ///
   /// On success, returns a key that can be used to deinitialize the region.
   void initialize(AllocInfo &AI, OnInitializedFunction OnInitialized) override;
 
   /// Given a series of keys from previous initialize calls, deinitialize
-  /// previously initialized memory regions (running dealloc actions, resetting
-  /// permissions and decommitting if possible) by calling a remote
-  /// SPS-wrapper-function with signature
-  ///
-  ///   SPSError(SPSSequence<SPSExecutorAddr> Keys)
-  ///
+  /// previously initialized memory regions: run their dealloc actions, reset
+  /// permissions, and decommit if possible.
   void deinitialize(ArrayRef<ExecutorAddr> Allocations,
                     OnDeinitializedFunction OnDeInitialized) override;
 
   /// Given a sequence of base addresses from previous reserve calls, release
-  /// the underlying ranges (deinitializing any remaining regions within them)
-  /// by calling a remote SPS-wrapper-function with signature
-  ///
-  ///   SPSError(SPSSequence<SPSExecutorAddr> Bases)
-  ///
+  /// the underlying ranges, deinitializing any remaining regions within them.
   void release(ArrayRef<ExecutorAddr> Reservations,
                OnReleasedFunction OnRelease) override;
 
 private:
-  ExecutorProcessControl &EPC;
-  SymbolAddrs SAs;
+  ExecutionSession &ES;
+  SimpleMemoryMapBindings B;
 };
 
 } // namespace llvm::orc
diff --git a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
index 134a4ebea2b1c..2af7f7b73d8c8 100644
--- a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
+++ b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
@@ -59,6 +59,7 @@ add_llvm_component_library(LLVMOrcJIT
   RTDyldObjectLinkingLayer.cpp
   SectCreate.cpp
   SelfExecutorProcessControl.cpp
+  SimpleMemoryMapSPS.cpp
   SimpleRemoteEPC.cpp
   SimpleRemoteMemoryMapper.cpp
   Speculation.cpp
diff --git a/llvm/lib/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerSPS.cpp b/llvm/lib/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerSPS.cpp
index a36b756e2403d..77a4335176348 100644
--- a/llvm/lib/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerSPS.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerSPS.cpp
@@ -9,27 +9,16 @@
 #include "llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerSPS.h"
 
 #include "llvm/ExecutionEngine/Orc/Core.h"
-#include "llvm/ExecutionEngine/Orc/LookupAndApply.h"
-#include "llvm/ExecutionEngine/Orc/RecordProxy.h"
 
 namespace llvm::orc::sps {
 
 Expected<std::unique_ptr<EPCGenericJITLinkMemoryManager>>
 createEPCGenericJITLinkMemoryManager(JITDylib &JD) {
-  auto &ES = JD.getExecutionSession();
-  EPCGenericJITLinkMemoryManager::Bindings B;
-  // Instance is the executor-side allocator object -- a data symbol passed as
-  // the first argument to each call, not a wrapper to proxy. The proxies
-  // resolve to the specs' default (SimpleNativeMemoryMap) names.
-  if (auto Err = lookupAndApply(
-          JD, {recordAddr(rt::sps_ci::SimpleNativeMemoryMapInstanceName,
-                          &B.Instance),
-               recordProxy<MemMgrReserveProxySpec>(&B.Reserve),
-               recordProxy<MemMgrInitializeProxySpec>(&B.Initialize),
-               recordProxy<MemMgrDeinitializeProxySpec>(&B.Deinitialize),
-               recordProxy<MemMgrReleaseProxySpec>(&B.Release)}))
-    return std::move(Err);
-  return std::make_unique<EPCGenericJITLinkMemoryManager>(ES, std::move(B));
+  auto B = createSimpleMemoryMapBindings(JD);
+  if (!B)
+    return B.takeError();
+  return std::make_unique<EPCGenericJITLinkMemoryManager>(
+      JD.getExecutionSession(), std::move(*B));
 }
 
 Expected<std::unique_ptr<EPCGenericJITLinkMemoryManager>>
diff --git a/llvm/lib/ExecutionEngine/Orc/SimpleMemoryMapSPS.cpp b/llvm/lib/ExecutionEngine/Orc/SimpleMemoryMapSPS.cpp
new file mode 100644
index 0000000000000..3b47a904e19bb
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/SimpleMemoryMapSPS.cpp
@@ -0,0 +1,37 @@
+//===- SimpleMemoryMapSPS.cpp - SPS memory-map bindings -------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/Orc/SimpleMemoryMapSPS.h"
+
+#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/RecordProxy.h"
+
+namespace llvm::orc::sps {
+
+Expected<SimpleMemoryMapBindings> createSimpleMemoryMapBindings(JITDylib &JD) {
+  SimpleMemoryMapBindings B;
+  // Instance is the executor-side manager object -- a data symbol passed as the
+  // first argument to each call, not a wrapper to proxy. The proxies resolve to
+  // the specs' default (SimpleNativeMemoryMap) names.
+  if (auto Err = lookupAndApply(
+          JD, {recordAddr(rt::sps_ci::SimpleNativeMemoryMapInstanceName,
+                          &B.Instance),
+               recordProxy<MemMgrReserveProxySpec>(&B.Reserve),
+               recordProxy<MemMgrInitializeProxySpec>(&B.Initialize),
+               recordProxy<MemMgrDeinitializeProxySpec>(&B.Deinitialize),
+               recordProxy<MemMgrReleaseProxySpec>(&B.Release)}))
+    return std::move(Err);
+  return std::move(B);
+}
+
+Expected<SimpleMemoryMapBindings>
+createSimpleMemoryMapBindings(ExecutionSession &ES) {
+  return createSimpleMemoryMapBindings(ES.getBootstrapJITDylib());
+}
+
+} // namespace llvm::orc::sps
diff --git a/llvm/lib/ExecutionEngine/Orc/SimpleRemoteMemoryMapper.cpp b/llvm/lib/ExecutionEngine/Orc/SimpleRemoteMemoryMapper.cpp
index d0cc9489061b5..46654682dad26 100644
--- a/llvm/lib/ExecutionEngine/Orc/SimpleRemoteMemoryMapper.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/SimpleRemoteMemoryMapper.cpp
@@ -9,31 +9,23 @@
 #include "llvm/ExecutionEngine/Orc/SimpleRemoteMemoryMapper.h"
 
 #include "llvm/ExecutionEngine/JITLink/JITLink.h"
-#include "llvm/ExecutionEngine/Orc/Shared/SPSCI/SimpleNativeMemoryMapSPSCI.h"
 
 namespace llvm::orc {
 
-SimpleRemoteMemoryMapper::SimpleRemoteMemoryMapper(ExecutorProcessControl &EPC,
-                                                   SymbolAddrs SAs)
-    : EPC(EPC), SAs(SAs) {}
+SimpleRemoteMemoryMapper::SimpleRemoteMemoryMapper(ExecutionSession &ES,
+                                                   SimpleMemoryMapBindings B)
+    : ES(ES), B(std::move(B)) {}
 
 void SimpleRemoteMemoryMapper::reserve(size_t NumBytes,
                                        OnReservedFunction OnReserved) {
-  EPC.callSPSWrapperAsync<rt::sps_ci::MemMgrReserve::SPSSig>(
-      SAs.Reserve,
+  B.Reserve(
       [NumBytes, OnReserved = std::move(OnReserved)](
-          Error SerializationErr, Expected<ExecutorAddr> Result) mutable {
-        if (SerializationErr) {
-          cantFail(Result.takeError());
-          return OnReserved(std::move(SerializationErr));
-        }
-
-        if (Result)
-          OnReserved(ExecutorAddrRange(*Result, NumBytes));
-        else
-          OnReserved(Result.takeError());
+          Expected<ExecutorAddr> Result) mutable {
+        if (!Result)
+          return OnReserved(Result.takeError());
+        OnReserved(ExecutorAddrRange(*Result, NumBytes));
       },
-      SAs.Instance, static_cast<uint64_t>(NumBytes));
+      ES, B.Instance, static_cast<uint64_t>(NumBytes));
 }
 
 char *SimpleRemoteMemoryMapper::prepare(jitlink::LinkGraph &G,
@@ -54,51 +46,18 @@ void SimpleRemoteMemoryMapper::initialize(MemoryMapper::AllocInfo &AI,
                            Seg.ContentSize + Seg.ZeroFillSize,
                            ArrayRef<char>(Seg.WorkingMem, Seg.ContentSize)});
 
-  EPC.callSPSWrapperAsync<rt::sps_ci::MemMgrInitialize::SPSSig>(
-      SAs.Initialize,
-      [OnInitialized = std::move(OnInitialized)](
-          Error SerializationErr, Expected<ExecutorAddr> Result) mutable {
-        if (SerializationErr) {
-          cantFail(Result.takeError());
-          return OnInitialized(std::move(SerializationErr));
-        }
-
-        OnInitialized(std::move(Result));
-      },
-      SAs.Instance, std::move(FR));
+  B.Initialize(std::move(OnInitialized), ES, B.Instance, std::move(FR));
 }
 
 void SimpleRemoteMemoryMapper::deinitialize(
     ArrayRef<ExecutorAddr> Allocations,
     MemoryMapper::OnDeinitializedFunction OnDeinitialized) {
-  EPC.callSPSWrapperAsync<rt::sps_ci::MemMgrDeinitialize::SPSSig>(
-      SAs.Deinitialize,
-      [OnDeinitialized = std::move(OnDeinitialized)](Error SerializationErr,
-                                                     Error Result) mutable {
-        if (SerializationErr) {
-          cantFail(std::move(Result));
-          return OnDeinitialized(std::move(SerializationErr));
-        }
-
-        OnDeinitialized(std::move(Result));
-      },
-      SAs.Instance, Allocations);
+  B.Deinitialize(std::move(OnDeinitialized), ES, B.Instance, Allocations);
 }
 
 void SimpleRemoteMemoryMapper::release(ArrayRef<ExecutorAddr> Bases,
                                        OnReleasedFunction OnReleased) {
-  EPC.callSPSWrapperAsync<rt::sps_ci::MemMgrRelease::SPSSig>(
-      SAs.Release,
-      [OnReleased = std::move(OnReleased)](Error SerializationErr,
-                                           Error Result) mutable {
-        if (SerializationErr) {
-          cantFail(std::move(Result));
-          return OnReleased(std::move(SerializationErr));
-        }
-
-        return OnReleased(std::move(Result));
-      },
-      SAs.Instance, Bases);
+  B.Release(std::move(OnReleased), ES, B.Instance, Bases);
 }
 
 } // namespace llvm::orc
diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
index 64d2f6edb1ac3..da99e17f12df1 100644
--- a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
+++ b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
@@ -40,6 +40,7 @@
 #include "llvm/ExecutionEngine/Orc/SectCreate.h"
 #include "llvm/ExecutionEngine/Orc/SelfExecutorProcessControl.h"
 #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
+#include "llvm/ExecutionEngine/Orc/SimpleMemoryMapSPS.h"
 #include "llvm/ExecutionEngine/Orc/SimpleRemoteMemoryMapper.h"
 #include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
 #include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderPerf.h"
@@ -761,23 +762,17 @@ static std::unique_ptr<JITLinkMemoryManager> createInProcessMemoryManager() {
 
 Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
 createSimpleRemoteMemoryManager(ExecutorProcessControl &EPC) {
-  SimpleRemoteMemoryMapper::SymbolAddrs SAs;
-  if (auto Err = EPC.getBootstrapSymbols(
-          {{SAs.Instance, rt::SimpleExecutorMemoryManagerInstanceName},
-           {SAs.Reserve, rt::SimpleExecutorMemoryManagerReserveWrapperName},
-           {SAs.Initialize,
-            rt::SimpleExecutorMemoryManagerInitializeWrapperName},
-           {SAs.Deinitialize,
-            rt::SimpleExecutorMemoryManagerDeinitializeWrapperName},
-           {SAs.Release, rt::SimpleExecutorMemoryManagerReleaseWrapperName}}))
-    return std::move(Err);
+  auto &ES = EPC.getExecutionSession();
+  auto B = sps::createSimpleMemoryMapBindings(ES);
+  if (!B)
+    return B.takeError();
 #ifdef _WIN32
   size_t SlabSize = 1024 * 1024;
 #else
   size_t SlabSize = 1024 * 1024 * 1024;
 #endif
   return MapperJITLinkMemoryManager::CreateWithMapper<SimpleRemoteMemoryMapper>(
-      SlabSize, EPC, SAs);
+      SlabSize, ES, std::move(*B));
 }
 
 Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
diff --git a/llvm/utils/gn/secondary/llvm/lib/ExecutionEngine/Orc/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/ExecutionEngine/Orc/BUILD.gn
index c1e51983f8950..55f6ad1d31c39 100644
--- a/llvm/utils/gn/secondary/llvm/lib/ExecutionEngine/Orc/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/lib/ExecutionEngine/Orc/BUILD.gn
@@ -71,6 +71,7 @@ static_library("Orc") {
     "RedirectionManager.cpp",
     "SectCreate.cpp",
     "SelfExecutorProcessControl.cpp",
+    "SimpleMemoryMapSPS.cpp",
     "SimpleRemoteEPC.cpp",
     "SimpleRemoteMemoryMapper.cpp",
     "SpeculateAnalyses.cpp",



More information about the llvm-commits mailing list