[llvm] [ORC] Remove Orc/RTBridge, split utilities from SPS bindings (PR #216473)

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Sat Aug 15 02:07:25 PDT 2026


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

RTBridge was a holding pen for the new proxy APIs, and its name collided confusingly with Shared/OrcRTBridge.h. Move its contents into Orc/ and delete it:

  RTBridge/Proxy.h              -> Proxy.h
  RTBridge/SPS/ProxySpec.h      -> SPSProxySpec.h
  RTBridge/CallProxies.h        -> CallProxies.h
  RTBridge/SPS/CallProxySpecs.h -> CallProxiesSPS.h

Drop rt:: from the proxy machinery: Proxy is not runtime specific, but a general-purpose utility for calling code in the executor (it abstracts over dispatch mechanism and serialization).

SPS dispatch becomes llvm::orc::sps::ProxySpec. Controller-interface descriptors keep llvm::orc::rt::sps_ci -- those really are runtime-specific.

Each EPCGeneric* utility now splits in two: a protocol-agnostic header with the class, its proxy typedefs and its Funcs/Bindings struct, plus a companion holding the ProxySpecs and a factory:

  EPCGenericMemoryAccessSPS.h
  EPCGenericDylibManagerSPS.h
  EPCGenericJITLinkMemoryManagerSPS.h

The class headers previously claimed to be protocol-agnostic while including the SPS specs and instantiating them inline in Create; they now pull in neither SPSProxySpec.h nor any SPSCI descriptor. The specs stay public so clients can still resolve operations under non-default names via proxyInit<Spec>(&P, Name).

The static Create methods become sps::createEPCGeneric* free functions returning Expected<std::unique_ptr<Concrete>>.  EPCGenericDylibManager previously returned by value, so its callers no longer wrap the result in make_unique. The SymbolLookupSet SPS serialization specialization moves to EPCGenericDylibManagerSPS.cpp, its only user.

>From 8fdf02d4ef493653602a8eb6538ce01f1ebb1a30 Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at gmail.com>
Date: Sat, 15 Aug 2026 18:43:51 +1000
Subject: [PATCH] [ORC] Remove Orc/RTBridge, split utilities from SPS bindings

RTBridge was a holding pen for the new proxy APIs, and its name
collided confusingly with Shared/OrcRTBridge.h. Move its contents
into Orc/ and delete it:

  RTBridge/Proxy.h              -> Proxy.h
  RTBridge/SPS/ProxySpec.h      -> SPSProxySpec.h
  RTBridge/CallProxies.h        -> CallProxies.h
  RTBridge/SPS/CallProxySpecs.h -> CallProxiesSPS.h

Drop rt:: from the proxy machinery: Proxy is not runtime specific, but a
general-purpose utility for calling code in the executor (it abstracts
over dispatch mechanism and serialization).

SPS dispatch becomes llvm::orc::sps::ProxySpec. Controller-interface
descriptors keep llvm::orc::rt::sps_ci -- those really are
runtime-specific.

Each EPCGeneric* utility now splits in two: a protocol-agnostic header
with the class, its proxy typedefs and its Funcs/Bindings struct, plus a
companion holding the ProxySpecs and a factory:

  EPCGenericMemoryAccessSPS.h
  EPCGenericDylibManagerSPS.h
  EPCGenericJITLinkMemoryManagerSPS.h

The class headers previously claimed to be protocol-agnostic while
including the SPS specs and instantiating them inline in Create; they
now pull in neither SPSProxySpec.h nor any SPSCI descriptor. The specs
stay public so clients can still resolve operations under non-default
names via proxyInit<Spec>(&P, Name).

The static Create methods become sps::createEPCGeneric* free functions
returning Expected<std::unique_ptr<Concrete>>.  EPCGenericDylibManager
previously returned by value, so its callers no longer wrap the result
in make_unique. The SymbolLookupSet SPS serialization specialization
moves to EPCGenericDylibManagerSPS.cpp, its only user.
---
 .../Orc/{RTBridge => }/CallProxies.h          | 22 ++---
 .../SPS/CallProxySpecs.h => CallProxiesSPS.h} | 32 +++----
 .../Orc/EPCGenericDylibManager.h              | 32 +++----
 .../Orc/EPCGenericDylibManagerSPS.h           | 51 +++++++++++
 .../Orc/EPCGenericJITLinkMemoryManager.h      | 51 ++++++-----
 .../Orc/EPCGenericJITLinkMemoryManagerSPS.h   | 60 +++++++++++++
 .../Orc/EPCGenericMemoryAccess.h              | 85 +++++++++----------
 .../Orc/EPCGenericMemoryAccessSPS.h           | 85 +++++++++++++++++++
 .../Orc/{RTBridge => }/Proxy.h                | 29 ++++---
 .../RTBridge/GenericMemoryManagerProxies.h    | 44 ----------
 .../Orc/RTBridge/MemoryAccessProxies.h        | 50 -----------
 .../SPS/GenericMemoryManagerProxySpecs.h      | 37 --------
 .../Orc/RTBridge/SPS/MemoryAccessProxySpecs.h | 53 ------------
 .../SPS/ProxySpec.h => SPSProxySpec.h}        | 23 ++---
 llvm/lib/ExecutionEngine/Orc/CMakeLists.txt   |  3 +
 llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp | 14 +--
 .../Orc/COFFVCRuntimeSupport.cpp              | 10 +--
 .../Orc/EPCGenericDylibManager.cpp            | 63 --------------
 .../Orc/EPCGenericDylibManagerSPS.cpp         | 69 +++++++++++++++
 .../Orc/EPCGenericJITLinkMemoryManager.cpp    | 31 -------
 .../Orc/EPCGenericJITLinkMemoryManagerSPS.cpp | 42 +++++++++
 .../Orc/EPCGenericMemoryAccessSPS.cpp         | 43 ++++++++++
 llvm/lib/ExecutionEngine/Orc/InProcessEPC.cpp | 15 ++--
 .../ExecutionEngine/Orc/SimpleRemoteEPC.cpp   | 17 ++--
 llvm/tools/lli/ForwardingMemoryManager.h      | 12 +--
 .../ExecutionEngine/Orc/CMakeLists.txt        |  2 +-
 .../Orc/EPCGenericDylibManagerTest.cpp        |  4 +-
 .../EPCGenericJITLinkMemoryManagerTest.cpp    | 10 +--
 .../Orc/EPCGenericMemoryAccessTest.cpp        |  6 +-
 .../ExecutionEngine/Orc/ProxyTest.cpp         | 42 +++++----
 ...PSProxiesTest.cpp => SPSProxySpecTest.cpp} | 36 ++++----
 .../llvm/lib/ExecutionEngine/Orc/BUILD.gn     |  3 +
 .../unittests/ExecutionEngine/Orc/BUILD.gn    |  2 +-
 33 files changed, 575 insertions(+), 503 deletions(-)
 rename llvm/include/llvm/ExecutionEngine/Orc/{RTBridge => }/CallProxies.h (68%)
 rename llvm/include/llvm/ExecutionEngine/Orc/{RTBridge/SPS/CallProxySpecs.h => CallProxiesSPS.h} (50%)
 create mode 100644 llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManagerSPS.h
 create mode 100644 llvm/include/llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerSPS.h
 create mode 100644 llvm/include/llvm/ExecutionEngine/Orc/EPCGenericMemoryAccessSPS.h
 rename llvm/include/llvm/ExecutionEngine/Orc/{RTBridge => }/Proxy.h (88%)
 delete mode 100644 llvm/include/llvm/ExecutionEngine/Orc/RTBridge/GenericMemoryManagerProxies.h
 delete mode 100644 llvm/include/llvm/ExecutionEngine/Orc/RTBridge/MemoryAccessProxies.h
 delete mode 100644 llvm/include/llvm/ExecutionEngine/Orc/RTBridge/SPS/GenericMemoryManagerProxySpecs.h
 delete mode 100644 llvm/include/llvm/ExecutionEngine/Orc/RTBridge/SPS/MemoryAccessProxySpecs.h
 rename llvm/include/llvm/ExecutionEngine/Orc/{RTBridge/SPS/ProxySpec.h => SPSProxySpec.h} (77%)
 create mode 100644 llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManagerSPS.cpp
 create mode 100644 llvm/lib/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerSPS.cpp
 create mode 100644 llvm/lib/ExecutionEngine/Orc/EPCGenericMemoryAccessSPS.cpp
 rename llvm/unittests/ExecutionEngine/Orc/{SPSProxiesTest.cpp => SPSProxySpecTest.cpp} (92%)

diff --git a/llvm/include/llvm/ExecutionEngine/Orc/RTBridge/CallProxies.h b/llvm/include/llvm/ExecutionEngine/Orc/CallProxies.h
similarity index 68%
rename from llvm/include/llvm/ExecutionEngine/Orc/RTBridge/CallProxies.h
rename to llvm/include/llvm/ExecutionEngine/Orc/CallProxies.h
index 6f10b1503b6bd..cdb3740a555d1 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/RTBridge/CallProxies.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/CallProxies.h
@@ -6,37 +6,37 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// Named rt::Proxy types for running functions in the executor. Each takes the
+// Named Proxy types for running functions in the executor. Each takes the
 // target function's ExecutorAddr (plus any arguments) and runs it.
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_EXECUTIONENGINE_ORC_RTBRIDGE_CALLPROXIES_H
-#define LLVM_EXECUTIONENGINE_ORC_RTBRIDGE_CALLPROXIES_H
+#ifndef LLVM_EXECUTIONENGINE_ORC_CALLPROXIES_H
+#define LLVM_EXECUTIONENGINE_ORC_CALLPROXIES_H
 
 #include "llvm/ADT/ArrayRef.h"
-#include "llvm/ExecutionEngine/Orc/RTBridge/Proxy.h"
+#include "llvm/ExecutionEngine/Orc/Proxy.h"
 
 #include <cstdint>
 #include <string>
 
-namespace llvm::orc::rt {
+namespace llvm::orc {
 
-/// Runtime-agnostic interface for running a main-like function
+/// Protocol-agnostic interface for running a main-like function
 /// (int(int argc, char *argv[])) in the executor.
 ///
 /// The function to run is given by its ExecutorAddr, its arguments as an
 /// argument vector, and its int64_t result is returned.
 using CallMainProxy = Proxy<int64_t(ExecutorAddr, ArrayRef<std::string>)>;
 
-/// Runtime-agnostic interface for running a void() function in the executor.
+/// Protocol-agnostic interface for running a void() function in the executor.
 ///
 /// The function to run is given by its ExecutorAddr.
 ///
 /// WARNING: This Proxy is experimental and may be removed.
 using CallVoidVoidProxy = Proxy<void(ExecutorAddr)>;
 
-/// Runtime-agnostic interface for running an int32_t() function in the
+/// Protocol-agnostic interface for running an int32_t() function in the
 /// executor.
 ///
 /// The function to run is given by its ExecutorAddr.
@@ -44,7 +44,7 @@ using CallVoidVoidProxy = Proxy<void(ExecutorAddr)>;
 /// WARNING: This Proxy is experimental and may be removed.
 using CallInt32VoidProxy = Proxy<int32_t(ExecutorAddr)>;
 
-/// Runtime-agnostic interface for running an int32_t(int32_t) function in the
+/// Protocol-agnostic interface for running an int32_t(int32_t) function in the
 /// executor.
 ///
 /// The function to run is given by its ExecutorAddr.
@@ -52,6 +52,6 @@ using CallInt32VoidProxy = Proxy<int32_t(ExecutorAddr)>;
 /// WARNING: This Proxy is experimental and may be removed.
 using CallInt32Int32Proxy = Proxy<int32_t(ExecutorAddr, int32_t)>;
 
-} // namespace llvm::orc::rt
+} // namespace llvm::orc
 
-#endif // LLVM_EXECUTIONENGINE_ORC_RTBRIDGE_CALLPROXIES_H
+#endif // LLVM_EXECUTIONENGINE_ORC_CALLPROXIES_H
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/RTBridge/SPS/CallProxySpecs.h b/llvm/include/llvm/ExecutionEngine/Orc/CallProxiesSPS.h
similarity index 50%
rename from llvm/include/llvm/ExecutionEngine/Orc/RTBridge/SPS/CallProxySpecs.h
rename to llvm/include/llvm/ExecutionEngine/Orc/CallProxiesSPS.h
index dd70f58cf6e68..496fe6b4c8129 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/RTBridge/SPS/CallProxySpecs.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/CallProxiesSPS.h
@@ -1,4 +1,4 @@
-//===----- CallProxySpecs.h - SPS specs for CallProxies ---------*- C++ -*-===//
+//===----- CallProxiesSPS.h - SPS specs for CallProxies ---------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -12,36 +12,36 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_EXECUTIONENGINE_ORC_RTBRIDGE_SPS_CALLPROXYSPECS_H
-#define LLVM_EXECUTIONENGINE_ORC_RTBRIDGE_SPS_CALLPROXYSPECS_H
+#ifndef LLVM_EXECUTIONENGINE_ORC_CALLPROXIESSPS_H
+#define LLVM_EXECUTIONENGINE_ORC_CALLPROXIESSPS_H
 
-#include "llvm/ExecutionEngine/Orc/RTBridge/CallProxies.h"
-#include "llvm/ExecutionEngine/Orc/RTBridge/SPS/ProxySpec.h"
+#include "llvm/ExecutionEngine/Orc/CallProxies.h"
+#include "llvm/ExecutionEngine/Orc/SPSProxySpec.h"
 #include "llvm/ExecutionEngine/Orc/Shared/SPSCI/CallSPSCI.h"
 
-namespace llvm::orc::rt::sps {
+namespace llvm::orc::sps {
 
-/// SPS proxy for rt::CallMainProxy: runs a main-like function
+/// SPS proxy for CallMainProxy: runs a main-like function
 /// (int(int argc, char *argv[])) in the executor.
-using CallMainProxySpec = ProxySpec<rt::CallMainProxy, sps_ci::CallMain>;
+using CallMainProxySpec = ProxySpec<CallMainProxy, rt::sps_ci::CallMain>;
 
-/// SPS proxy for rt::CallVoidVoidProxy: runs a void() function in the executor.
+/// SPS proxy for CallVoidVoidProxy: runs a void() function in the executor.
 /// WARNING: This Proxy is experimental and may be removed.
 using CallVoidVoidProxySpec =
-    ProxySpec<rt::CallVoidVoidProxy, sps_ci::CallVoidVoid>;
+    ProxySpec<CallVoidVoidProxy, rt::sps_ci::CallVoidVoid>;
 
-/// SPS proxy for rt::CallInt32VoidProxy: runs an int32_t() function in the
+/// SPS proxy for CallInt32VoidProxy: runs an int32_t() function in the
 /// executor.
 /// WARNING: This Proxy is experimental and may be removed.
 using CallInt32VoidProxySpec =
-    ProxySpec<rt::CallInt32VoidProxy, sps_ci::CallInt32Void>;
+    ProxySpec<CallInt32VoidProxy, rt::sps_ci::CallInt32Void>;
 
-/// SPS proxy for rt::CallInt32Int32Proxy: runs an int32_t(int32_t) function in
+/// SPS proxy for CallInt32Int32Proxy: runs an int32_t(int32_t) function in
 /// the executor.
 /// WARNING: This Proxy is experimental and may be removed.
 using CallInt32Int32ProxySpec =
-    ProxySpec<rt::CallInt32Int32Proxy, sps_ci::CallInt32Int32>;
+    ProxySpec<CallInt32Int32Proxy, rt::sps_ci::CallInt32Int32>;
 
-} // namespace llvm::orc::rt::sps
+} // namespace llvm::orc::sps
 
-#endif // LLVM_EXECUTIONENGINE_ORC_RTBRIDGE_SPS_CALLPROXYSPECS_H
+#endif // LLVM_EXECUTIONENGINE_ORC_CALLPROXIESSPS_H
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h
index dfa831710a2bb..1de4cfd9aaa4e 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h
@@ -7,12 +7,15 @@
 //===----------------------------------------------------------------------===//
 //
 // Implements dylib loading and searching by calling executor-side wrapper
-// functions through rt::Proxy objects.
+// functions through Proxy objects.
 //
 // This simplifies the implementaton of new ExecutorProcessControl instances,
 // as this implementation will always work (at the cost of some performance
 // overhead for the calls).
 //
+// This header is protocol-agnostic. To build an instance that targets the ORC
+// runtime's SPS controller interface, see EPCGenericDylibManagerSPS.h.
+//
 //===----------------------------------------------------------------------===//
 
 #ifndef LLVM_EXECUTIONENGINE_ORC_EPCGENERICDYLIBMANAGER_H
@@ -20,10 +23,8 @@
 
 #include "llvm/ExecutionEngine/Orc/DylibManager.h"
 #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
-#include "llvm/ExecutionEngine/Orc/RTBridge/Proxy.h"
+#include "llvm/ExecutionEngine/Orc/Proxy.h"
 #include "llvm/ExecutionEngine/Orc/Shared/ExecutorSymbolDef.h"
-#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
-#include "llvm/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.h"
 #include "llvm/Support/Compiler.h"
 
 namespace llvm {
@@ -37,36 +38,27 @@ class LLVM_ABI EPCGenericDylibManager : public DylibManager {
   /// Proxy for the executor-side dylib-open function. Given the manager
   /// instance address, a path and mode flags it returns a handle to the opened
   /// dylib.
-  using OpenProxy = rt::Proxy<Expected<tpctypes::DylibHandle>(
-      ExecutorAddr, StringRef, uint64_t)>;
+  using OpenProxy =
+      Proxy<Expected<tpctypes::DylibHandle>(ExecutorAddr, StringRef, uint64_t)>;
 
   /// Proxy for the executor-side symbol-resolution function. Given the manager
   /// instance address, a dylib handle and a lookup set it returns the resolved
   /// addresses.
-  using ResolveProxy = rt::Proxy<Expected<tpctypes::LookupResult>(
+  using ResolveProxy = Proxy<Expected<tpctypes::LookupResult>(
       ExecutorAddr, ExecutorAddr, SymbolLookupSet)>;
 
   /// The resolved controller-side handle to an executor-side dylib manager: the
   /// address of the manager instance (passed as the first argument to each
-  /// call) plus the proxies for its functions. These are protocol-agnostic: the
-  /// Create methods populate 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.
+  /// call) plus the proxies for its functions. These are protocol-agnostic:
+  /// sps::createEPCGenericDylibManager 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.
   struct Bindings {
     ExecutorAddr Instance;
     OpenProxy Open;
     ResolveProxy Resolve;
   };
 
-  /// Create an EPCGenericDylibManager for the ORC runtime's NativeDylibManager
-  /// interface, resolving its symbols in the given JITDylib.
-  static Expected<EPCGenericDylibManager> Create(JITDylib &JD);
-
-  /// Create an EPCGenericDylibManager for the ORC runtime's NativeDylibManager
-  /// interface, resolving its symbols in the given ExecutionSession's bootstrap
-  /// JITDylib.
-  static Expected<EPCGenericDylibManager> Create(ExecutionSession &ES);
-
   /// Create an EPCGenericDylibManager instance from a given set of
   /// dylib-manager bindings.
   EPCGenericDylibManager(ExecutionSession &ES, Bindings B)
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManagerSPS.h b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManagerSPS.h
new file mode 100644
index 0000000000000..46c180eda17e5
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManagerSPS.h
@@ -0,0 +1,51 @@
+//===- EPCGenericDylibManagerSPS.h - SPS dylib management -------*- 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 EPCGenericDylibManager to the ORC runtime's SPS controller interface:
+// a ProxySpec per operation, plus factories that resolve them and construct an
+// instance.
+//
+// Each spec pairs one of EPCGenericDylibManager's proxies with its
+// controller-interface descriptor in Shared/SPSCI/NativeDylibManagerSPSCI.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
+// proxyInit<Spec>(&P, Name) with buildProxies.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_EPCGENERICDYLIBMANAGERSPS_H
+#define LLVM_EXECUTIONENGINE_ORC_EPCGENERICDYLIBMANAGERSPS_H
+
+#include "llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h"
+#include "llvm/ExecutionEngine/Orc/SPSProxySpec.h"
+#include "llvm/ExecutionEngine/Orc/Shared/SPSCI/NativeDylibManagerSPSCI.h"
+#include "llvm/Support/Compiler.h"
+
+#include <memory>
+
+namespace llvm::orc::sps {
+
+using DylibMgrOpenProxySpec =
+    ProxySpec<EPCGenericDylibManager::OpenProxy, rt::sps_ci::DylibMgrOpen>;
+using DylibMgrResolveProxySpec = ProxySpec<EPCGenericDylibManager::ResolveProxy,
+                                           rt::sps_ci::DylibMgrResolve>;
+
+/// Create an EPCGenericDylibManager for the ORC runtime's NativeDylibManager
+/// interface, resolving its symbols in the given JITDylib.
+LLVM_ABI Expected<std::unique_ptr<EPCGenericDylibManager>>
+createEPCGenericDylibManager(JITDylib &JD);
+
+/// Create an EPCGenericDylibManager for the ORC runtime's NativeDylibManager
+/// interface, resolving its symbols in the given ExecutionSession's bootstrap
+/// JITDylib.
+LLVM_ABI Expected<std::unique_ptr<EPCGenericDylibManager>>
+createEPCGenericDylibManager(ExecutionSession &ES);
+
+} // namespace llvm::orc::sps
+
+#endif // LLVM_EXECUTIONENGINE_ORC_EPCGENERICDYLIBMANAGERSPS_H
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h
index c8546a3d21edd..9ce09cf089401 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h
@@ -7,12 +7,15 @@
 //===----------------------------------------------------------------------===//
 //
 // Implements JITLinkMemoryManager by calling executor-side wrapper functions
-// through rt::Proxy objects.
+// through Proxy objects.
 //
 // This simplifies the implementaton of new ExecutorProcessControl instances,
 // as this implementation will always work (at the cost of some performance
 // overhead for the calls).
 //
+// This header is protocol-agnostic. To build an instance that targets the ORC
+// runtime's SPS controller interface, see EPCGenericJITLinkMemoryManagerSPS.h.
+//
 //===----------------------------------------------------------------------===//
 
 #ifndef LLVM_EXECUTIONENGINE_ORC_EPCGENERICJITLINKMEMORYMANAGER_H
@@ -20,30 +23,48 @@
 
 #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
 #include "llvm/ExecutionEngine/Orc/Core.h"
-#include "llvm/ExecutionEngine/Orc/RTBridge/GenericMemoryManagerProxies.h"
+#include "llvm/ExecutionEngine/Orc/Proxy.h"
+#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
 #include "llvm/Support/Compiler.h"
 
+#include <cstdint>
+
 namespace llvm {
 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: the Create methods populate 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.
+  /// 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;
-    rt::MemMgrReserveProxy Reserve;
-    rt::MemMgrInitializeProxy Initialize;
-    rt::MemMgrDeinitializeProxy Deinitialize;
-    rt::MemMgrReleaseProxy Release;
+    ReserveProxy Reserve;
+    InitializeProxy Initialize;
+    DeinitializeProxy Deinitialize;
+    ReleaseProxy Release;
   };
 
   /// Create an EPCGenericJITLinkMemoryManager instance from a given set of
@@ -51,18 +72,6 @@ class LLVM_ABI EPCGenericJITLinkMemoryManager
   EPCGenericJITLinkMemoryManager(ExecutionSession &ES, Bindings B)
       : ES(ES), B(std::move(B)) {}
 
-  /// Create an EPCGenericJITLinkMemoryManager for the ORC runtime's
-  /// SimpleNativeMemoryMap interface, resolving its symbols in the given
-  /// JITDylib.
-  static Expected<std::unique_ptr<EPCGenericJITLinkMemoryManager>>
-  Create(JITDylib &JD);
-
-  /// Create an EPCGenericJITLinkMemoryManager for the ORC runtime's
-  /// SimpleNativeMemoryMap interface, resolving its symbols in the given
-  /// ExecutionSession's bootstrap JITDylib.
-  static Expected<std::unique_ptr<EPCGenericJITLinkMemoryManager>>
-  Create(ExecutionSession &ES);
-
   void allocate(const jitlink::JITLinkDylib *JD, jitlink::LinkGraph &G,
                 OnAllocatedFunction OnAllocated) override;
 
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerSPS.h b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerSPS.h
new file mode 100644
index 0000000000000..c6978f5765616
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerSPS.h
@@ -0,0 +1,60 @@
+//===- EPCGenericJITLinkMemoryManagerSPS.h - SPS mem manager ----*- 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 EPCGenericJITLinkMemoryManager to the ORC runtime's SPS controller
+// interface: a ProxySpec per operation, plus factories that resolve them and
+// construct an instance.
+//
+// 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
+// proxyInit<Spec>(&P, Name) with buildProxies.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_EPCGENERICJITLINKMEMORYMANAGERSPS_H
+#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/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.
+LLVM_ABI Expected<std::unique_ptr<EPCGenericJITLinkMemoryManager>>
+createEPCGenericJITLinkMemoryManager(JITDylib &JD);
+
+/// Create an EPCGenericJITLinkMemoryManager for the ORC runtime's
+/// SimpleNativeMemoryMap interface, resolving its symbols in the given
+/// ExecutionSession's bootstrap JITDylib.
+LLVM_ABI Expected<std::unique_ptr<EPCGenericJITLinkMemoryManager>>
+createEPCGenericJITLinkMemoryManager(ExecutionSession &ES);
+
+} // namespace llvm::orc::sps
+
+#endif // LLVM_EXECUTIONENGINE_ORC_EPCGENERICJITLINKMEMORYMANAGERSPS_H
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h
index dd7fd62714edd..19e03e9661609 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h
@@ -7,12 +7,15 @@
 //===----------------------------------------------------------------------===//
 //
 // Implements the MemoryAccess interface by calling executor-side wrapper
-// functions through rt::Proxy objects.
+// functions through Proxy objects.
 //
 // This simplifies the implementaton of new ExecutorProcessControl instances,
 // as this implementation will always work (at the cost of some performance
 // overhead for the calls).
 //
+// This header is protocol-agnostic. To build an instance that targets the ORC
+// runtime's SPS controller interface, see EPCGenericMemoryAccessSPS.h.
+//
 //===----------------------------------------------------------------------===//
 
 #ifndef LLVM_EXECUTIONENGINE_ORC_EPCGENERICMEMORYACCESS_H
@@ -20,59 +23,55 @@
 
 #include "llvm/ExecutionEngine/Orc/Core.h"
 #include "llvm/ExecutionEngine/Orc/MemoryAccess.h"
-#include "llvm/ExecutionEngine/Orc/RTBridge/MemoryAccessProxies.h"
-#include "llvm/ExecutionEngine/Orc/RTBridge/Proxy.h"
-#include "llvm/ExecutionEngine/Orc/RTBridge/SPS/MemoryAccessProxySpecs.h"
+#include "llvm/ExecutionEngine/Orc/Proxy.h"
+#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
+
+#include <cstdint>
+#include <string>
+#include <vector>
 
 namespace llvm {
 namespace orc {
 
 class EPCGenericMemoryAccess : public MemoryAccess {
 public:
+  using WriteUInt8sProxy = Proxy<void(ArrayRef<tpctypes::UInt8Write>)>;
+  using WriteUInt16sProxy = Proxy<void(ArrayRef<tpctypes::UInt16Write>)>;
+  using WriteUInt32sProxy = Proxy<void(ArrayRef<tpctypes::UInt32Write>)>;
+  using WriteUInt64sProxy = Proxy<void(ArrayRef<tpctypes::UInt64Write>)>;
+  using WritePointersProxy = Proxy<void(ArrayRef<tpctypes::PointerWrite>)>;
+  using WriteBuffersProxy = Proxy<void(ArrayRef<tpctypes::BufferWrite>)>;
+  using ReadUInt8sProxy = Proxy<std::vector<uint8_t>(ArrayRef<ExecutorAddr>)>;
+  using ReadUInt16sProxy = Proxy<std::vector<uint16_t>(ArrayRef<ExecutorAddr>)>;
+  using ReadUInt32sProxy = Proxy<std::vector<uint32_t>(ArrayRef<ExecutorAddr>)>;
+  using ReadUInt64sProxy = Proxy<std::vector<uint64_t>(ArrayRef<ExecutorAddr>)>;
+  using ReadPointersProxy =
+      Proxy<std::vector<ExecutorAddr>(ArrayRef<ExecutorAddr>)>;
+  using ReadBuffersProxy =
+      Proxy<std::vector<std::vector<uint8_t>>(ArrayRef<ExecutorAddrRange>)>;
+  using ReadStringsProxy =
+      Proxy<std::vector<std::string>(ArrayRef<ExecutorAddr>)>;
+
   /// Proxies for the executor-side memory-access functions. These are
-  /// protocol-agnostic: EPCGenericMemoryAccess::Create populates them for the
-  /// runtime's SPS controller interface, but a client targeting a different
+  /// protocol-agnostic: sps::createEPCGenericMemoryAccess populates them for
+  /// the runtime's SPS controller interface, but a client targeting a different
   /// protocol can build its own Funcs and pass them to the constructor.
   struct Funcs {
-    rt::MemWriteUInt8sProxy WriteUInt8s;
-    rt::MemWriteUInt16sProxy WriteUInt16s;
-    rt::MemWriteUInt32sProxy WriteUInt32s;
-    rt::MemWriteUInt64sProxy WriteUInt64s;
-    rt::MemWritePointersProxy WritePointers;
-    rt::MemWriteBuffersProxy WriteBuffers;
-    rt::MemReadUInt8sProxy ReadUInt8s;
-    rt::MemReadUInt16sProxy ReadUInt16s;
-    rt::MemReadUInt32sProxy ReadUInt32s;
-    rt::MemReadUInt64sProxy ReadUInt64s;
-    rt::MemReadPointersProxy ReadPointers;
-    rt::MemReadBuffersProxy ReadBuffers;
-    rt::MemReadStringsProxy ReadStrings;
+    WriteUInt8sProxy WriteUInt8s;
+    WriteUInt16sProxy WriteUInt16s;
+    WriteUInt32sProxy WriteUInt32s;
+    WriteUInt64sProxy WriteUInt64s;
+    WritePointersProxy WritePointers;
+    WriteBuffersProxy WriteBuffers;
+    ReadUInt8sProxy ReadUInt8s;
+    ReadUInt16sProxy ReadUInt16s;
+    ReadUInt32sProxy ReadUInt32s;
+    ReadUInt64sProxy ReadUInt64s;
+    ReadPointersProxy ReadPointers;
+    ReadBuffersProxy ReadBuffers;
+    ReadStringsProxy ReadStrings;
   };
 
-  /// Create an EPCGenericMemoryAccess instance that reaches the memory-access
-  /// wrappers in ES's bootstrap JITDylib via the runtime's SPS controller
-  /// interface.
-  static Expected<std::unique_ptr<MemoryAccess>> Create(ExecutionSession &ES) {
-    namespace sps = rt::sps;
-    Funcs Fns;
-    if (auto Err = rt::buildProxies(
-            ES, rt::proxyInit<sps::MemWriteUInt8sProxySpec>(&Fns.WriteUInt8s),
-            rt::proxyInit<sps::MemWriteUInt16sProxySpec>(&Fns.WriteUInt16s),
-            rt::proxyInit<sps::MemWriteUInt32sProxySpec>(&Fns.WriteUInt32s),
-            rt::proxyInit<sps::MemWriteUInt64sProxySpec>(&Fns.WriteUInt64s),
-            rt::proxyInit<sps::MemWritePointersProxySpec>(&Fns.WritePointers),
-            rt::proxyInit<sps::MemWriteBuffersProxySpec>(&Fns.WriteBuffers),
-            rt::proxyInit<sps::MemReadUInt8sProxySpec>(&Fns.ReadUInt8s),
-            rt::proxyInit<sps::MemReadUInt16sProxySpec>(&Fns.ReadUInt16s),
-            rt::proxyInit<sps::MemReadUInt32sProxySpec>(&Fns.ReadUInt32s),
-            rt::proxyInit<sps::MemReadUInt64sProxySpec>(&Fns.ReadUInt64s),
-            rt::proxyInit<sps::MemReadPointersProxySpec>(&Fns.ReadPointers),
-            rt::proxyInit<sps::MemReadBuffersProxySpec>(&Fns.ReadBuffers),
-            rt::proxyInit<sps::MemReadStringsProxySpec>(&Fns.ReadStrings)))
-      return std::move(Err);
-    return std::make_unique<EPCGenericMemoryAccess>(ES, std::move(Fns));
-  }
-
   /// Create an EPCGenericMemoryAccess instance from a given set of memory
   /// access proxies.
   EPCGenericMemoryAccess(ExecutionSession &ES, Funcs Fns)
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericMemoryAccessSPS.h b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericMemoryAccessSPS.h
new file mode 100644
index 0000000000000..21d0efa539360
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericMemoryAccessSPS.h
@@ -0,0 +1,85 @@
+//===- EPCGenericMemoryAccessSPS.h - SPS memory access ----------*- 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 EPCGenericMemoryAccess to the ORC runtime's SPS controller interface:
+// a ProxySpec per operation, plus factories that resolve them and construct an
+// instance.
+//
+// Each spec pairs one of EPCGenericMemoryAccess's proxies with its
+// controller-interface descriptor in Shared/SPSCI/MemoryAccessSPSCI.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
+// proxyInit<Spec>(&P, Name) with buildProxies.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_EPCGENERICMEMORYACCESSSPS_H
+#define LLVM_EXECUTIONENGINE_ORC_EPCGENERICMEMORYACCESSSPS_H
+
+#include "llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h"
+#include "llvm/ExecutionEngine/Orc/SPSProxySpec.h"
+#include "llvm/ExecutionEngine/Orc/Shared/SPSCI/MemoryAccessSPSCI.h"
+#include "llvm/Support/Compiler.h"
+
+#include <memory>
+
+namespace llvm::orc::sps {
+
+using MemWriteUInt8sProxySpec =
+    ProxySpec<EPCGenericMemoryAccess::WriteUInt8sProxy,
+              rt::sps_ci::MemWriteUInt8s>;
+using MemWriteUInt16sProxySpec =
+    ProxySpec<EPCGenericMemoryAccess::WriteUInt16sProxy,
+              rt::sps_ci::MemWriteUInt16s>;
+using MemWriteUInt32sProxySpec =
+    ProxySpec<EPCGenericMemoryAccess::WriteUInt32sProxy,
+              rt::sps_ci::MemWriteUInt32s>;
+using MemWriteUInt64sProxySpec =
+    ProxySpec<EPCGenericMemoryAccess::WriteUInt64sProxy,
+              rt::sps_ci::MemWriteUInt64s>;
+using MemWritePointersProxySpec =
+    ProxySpec<EPCGenericMemoryAccess::WritePointersProxy,
+              rt::sps_ci::MemWritePointers>;
+using MemWriteBuffersProxySpec =
+    ProxySpec<EPCGenericMemoryAccess::WriteBuffersProxy,
+              rt::sps_ci::MemWriteBuffers>;
+using MemReadUInt8sProxySpec =
+    ProxySpec<EPCGenericMemoryAccess::ReadUInt8sProxy,
+              rt::sps_ci::MemReadUInt8s>;
+using MemReadUInt16sProxySpec =
+    ProxySpec<EPCGenericMemoryAccess::ReadUInt16sProxy,
+              rt::sps_ci::MemReadUInt16s>;
+using MemReadUInt32sProxySpec =
+    ProxySpec<EPCGenericMemoryAccess::ReadUInt32sProxy,
+              rt::sps_ci::MemReadUInt32s>;
+using MemReadUInt64sProxySpec =
+    ProxySpec<EPCGenericMemoryAccess::ReadUInt64sProxy,
+              rt::sps_ci::MemReadUInt64s>;
+using MemReadPointersProxySpec =
+    ProxySpec<EPCGenericMemoryAccess::ReadPointersProxy,
+              rt::sps_ci::MemReadPointers>;
+using MemReadBuffersProxySpec =
+    ProxySpec<EPCGenericMemoryAccess::ReadBuffersProxy,
+              rt::sps_ci::MemReadBuffers>;
+using MemReadStringsProxySpec =
+    ProxySpec<EPCGenericMemoryAccess::ReadStringsProxy,
+              rt::sps_ci::MemReadStrings>;
+
+/// Create an EPCGenericMemoryAccess that reaches the memory-access wrappers in
+/// the given JITDylib via the runtime's SPS controller interface.
+LLVM_ABI Expected<std::unique_ptr<EPCGenericMemoryAccess>>
+createEPCGenericMemoryAccess(JITDylib &JD);
+
+/// Create an EPCGenericMemoryAccess that reaches the memory-access wrappers in
+/// ES's bootstrap JITDylib via the runtime's SPS controller interface.
+LLVM_ABI Expected<std::unique_ptr<EPCGenericMemoryAccess>>
+createEPCGenericMemoryAccess(ExecutionSession &ES);
+
+} // namespace llvm::orc::sps
+
+#endif // LLVM_EXECUTIONENGINE_ORC_EPCGENERICMEMORYACCESSSPS_H
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/RTBridge/Proxy.h b/llvm/include/llvm/ExecutionEngine/Orc/Proxy.h
similarity index 88%
rename from llvm/include/llvm/ExecutionEngine/Orc/RTBridge/Proxy.h
rename to llvm/include/llvm/ExecutionEngine/Orc/Proxy.h
index c6b47ff0d022e..2504f6217620c 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/RTBridge/Proxy.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Proxy.h
@@ -1,4 +1,4 @@
-//===------- Proxy.h - Runtime-agnostic executor call APIs ------*- C++ -*-===//
+//===------- Proxy.h - Protocol-agnostic executor call APIs -----*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,20 +6,21 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// Runtime-agnostic interfaces for invoking executor-side operations. These
+// Protocol-agnostic interfaces for invoking executor-side operations. These
 // abstract over how a call reaches the executor, so clients can be written
 // once and used whether the operation is provided by a full ORC runtime or by
-// LLVM's own ORC-runtime-lite. Concrete implementations live in subdirectories
-// (e.g. RTBridge/SPS).
+// LLVM's own ORC-runtime-lite.
 //
-// This header provides only the core Proxy machinery. Named proxies for
-// specific operation families live in sibling headers (e.g. CallProxies.h,
-// MemoryAccessProxies.h).
+// This header provides only the core Proxy machinery. A Proxy's dispatch
+// function is supplied by a spec for some concrete protocol -- see
+// SPSProxySpec.h for the Simple Packed Serialization implementation. Named
+// proxies for specific operation families live alongside the utilities that use
+// them (e.g. CallProxies.h, EPCGenericMemoryAccess.h).
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_EXECUTIONENGINE_ORC_RTBRIDGE_PROXY_H
-#define LLVM_EXECUTIONENGINE_ORC_RTBRIDGE_PROXY_H
+#ifndef LLVM_EXECUTIONENGINE_ORC_PROXY_H
+#define LLVM_EXECUTIONENGINE_ORC_PROXY_H
 
 #include "llvm/ADT/FunctionExtras.h"
 #include "llvm/ExecutionEngine/Orc/Core.h"
@@ -30,7 +31,7 @@
 #include <future>
 #include <type_traits>
 
-namespace llvm::orc::rt {
+namespace llvm::orc {
 
 class ProxyBase {
 public:
@@ -83,7 +84,7 @@ template <typename T> struct ProxyRetPromise<Expected<T>> {
 
 } // namespace detail
 
-/// Runtime-agnostic interface for invoking an executor-side operation with the
+/// Protocol-agnostic interface for invoking an executor-side operation with the
 /// signature RetT(ArgTs...).
 ///
 /// Two call operators are provided: an asynchronous form that delivers the
@@ -91,7 +92,7 @@ template <typename T> struct ProxyRetPromise<Expected<T>> {
 /// until the result is available.
 ///
 /// A Proxy abstracts over how the operation is dispatched to the executor. Its
-/// dispatch function is supplied by a spec (e.g. rt::sps::ProxySpec).
+/// dispatch function is supplied by a spec (e.g. sps::ProxySpec).
 template <typename RetT, typename... ArgTs>
 class Proxy<RetT(ArgTs...)> : public ProxyBase {
 public:
@@ -204,6 +205,6 @@ Error buildProxies(JITDylib &JD, ProxyInit<FnT> PI, ProxyInit<FnTs>... PIs) {
   return buildProxies(JD, PIs...);
 }
 
-} // namespace llvm::orc::rt
+} // namespace llvm::orc
 
-#endif // LLVM_EXECUTIONENGINE_ORC_RTBRIDGE_PROXY_H
+#endif // LLVM_EXECUTIONENGINE_ORC_PROXY_H
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/RTBridge/GenericMemoryManagerProxies.h b/llvm/include/llvm/ExecutionEngine/Orc/RTBridge/GenericMemoryManagerProxies.h
deleted file mode 100644
index 506346e212346..0000000000000
--- a/llvm/include/llvm/ExecutionEngine/Orc/RTBridge/GenericMemoryManagerProxies.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//===- GenericMemoryManagerProxies.h - Proxies for mem mgmt -----*- 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
-//
-//===----------------------------------------------------------------------===//
-//
-// Named rt::Proxy types for the executor's memory-manager operations. The
-// instance address of the executor-side manager is passed as the first
-// argument to each call.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_EXECUTIONENGINE_ORC_RTBRIDGE_GENERICMEMORYMANAGERPROXIES_H
-#define LLVM_EXECUTIONENGINE_ORC_RTBRIDGE_GENERICMEMORYMANAGERPROXIES_H
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ExecutionEngine/Orc/RTBridge/Proxy.h"
-#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
-
-#include <cstdint>
-
-namespace llvm::orc::rt {
-
-/// Reserve an address range of the given size; returns its base.
-using MemMgrReserveProxy =
-    Proxy<Expected<ExecutorAddr>(ExecutorAddr, uint64_t)>;
-
-/// Apply a finalize request; returns a key for the initialized allocation.
-using MemMgrInitializeProxy =
-    Proxy<Expected<ExecutorAddr>(ExecutorAddr, tpctypes::FinalizeRequest)>;
-
-/// Deinitialize the allocations with the given base addresses (running their
-/// deallocation actions) without releasing their memory.
-using MemMgrDeinitializeProxy =
-    Proxy<Error(ExecutorAddr, ArrayRef<ExecutorAddr>)>;
-
-/// Release the allocations with the given base addresses.
-using MemMgrReleaseProxy = Proxy<Error(ExecutorAddr, ArrayRef<ExecutorAddr>)>;
-
-} // namespace llvm::orc::rt
-
-#endif // LLVM_EXECUTIONENGINE_ORC_RTBRIDGE_GENERICMEMORYMANAGERPROXIES_H
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/RTBridge/MemoryAccessProxies.h b/llvm/include/llvm/ExecutionEngine/Orc/RTBridge/MemoryAccessProxies.h
deleted file mode 100644
index 2b9cad857879b..0000000000000
--- a/llvm/include/llvm/ExecutionEngine/Orc/RTBridge/MemoryAccessProxies.h
+++ /dev/null
@@ -1,50 +0,0 @@
-//===--- MemoryAccessProxies.h - Proxies for memory access ------*- 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
-//
-//===----------------------------------------------------------------------===//
-//
-// Named rt::Proxy types for the executor's memory-access operations. Unlike the
-// Call proxies, these target wrappers that perform the operation directly, so
-// they take the operation's data arguments rather than a callee address.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_EXECUTIONENGINE_ORC_RTBRIDGE_MEMORYACCESSPROXIES_H
-#define LLVM_EXECUTIONENGINE_ORC_RTBRIDGE_MEMORYACCESSPROXIES_H
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ExecutionEngine/Orc/RTBridge/Proxy.h"
-#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
-
-#include <cstdint>
-#include <string>
-#include <vector>
-
-namespace llvm::orc::rt {
-
-using MemWriteUInt8sProxy = Proxy<void(ArrayRef<tpctypes::UInt8Write>)>;
-using MemWriteUInt16sProxy = Proxy<void(ArrayRef<tpctypes::UInt16Write>)>;
-using MemWriteUInt32sProxy = Proxy<void(ArrayRef<tpctypes::UInt32Write>)>;
-using MemWriteUInt64sProxy = Proxy<void(ArrayRef<tpctypes::UInt64Write>)>;
-using MemWritePointersProxy = Proxy<void(ArrayRef<tpctypes::PointerWrite>)>;
-using MemWriteBuffersProxy = Proxy<void(ArrayRef<tpctypes::BufferWrite>)>;
-using MemReadUInt8sProxy = Proxy<std::vector<uint8_t>(ArrayRef<ExecutorAddr>)>;
-using MemReadUInt16sProxy =
-    Proxy<std::vector<uint16_t>(ArrayRef<ExecutorAddr>)>;
-using MemReadUInt32sProxy =
-    Proxy<std::vector<uint32_t>(ArrayRef<ExecutorAddr>)>;
-using MemReadUInt64sProxy =
-    Proxy<std::vector<uint64_t>(ArrayRef<ExecutorAddr>)>;
-using MemReadPointersProxy =
-    Proxy<std::vector<ExecutorAddr>(ArrayRef<ExecutorAddr>)>;
-using MemReadBuffersProxy =
-    Proxy<std::vector<std::vector<uint8_t>>(ArrayRef<ExecutorAddrRange>)>;
-using MemReadStringsProxy =
-    Proxy<std::vector<std::string>(ArrayRef<ExecutorAddr>)>;
-
-} // namespace llvm::orc::rt
-
-#endif // LLVM_EXECUTIONENGINE_ORC_RTBRIDGE_MEMORYACCESSPROXIES_H
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/RTBridge/SPS/GenericMemoryManagerProxySpecs.h b/llvm/include/llvm/ExecutionEngine/Orc/RTBridge/SPS/GenericMemoryManagerProxySpecs.h
deleted file mode 100644
index 95b6974b239d0..0000000000000
--- a/llvm/include/llvm/ExecutionEngine/Orc/RTBridge/SPS/GenericMemoryManagerProxySpecs.h
+++ /dev/null
@@ -1,37 +0,0 @@
-//===- GenericMemoryManagerProxySpecs.h - SPS specs for mem mgmt -*- 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
-//
-//===----------------------------------------------------------------------===//
-//
-// SPS ProxySpecs for the GenericMemoryManagerProxies: each binds a Proxy to
-// its controller-interface descriptor in
-// Shared/SPSCI/SimpleNativeMemoryMapSPSCI.h, which supplies the wrapper name
-// and wire signature. The names are the runtime's SimpleNativeMemoryMap
-// defaults (the Create methods look symbols up under caller-supplied names).
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_EXECUTIONENGINE_ORC_RTBRIDGE_SPS_GENERICMEMORYMANAGERPROXYSPECS_H
-#define LLVM_EXECUTIONENGINE_ORC_RTBRIDGE_SPS_GENERICMEMORYMANAGERPROXYSPECS_H
-
-#include "llvm/ExecutionEngine/Orc/RTBridge/GenericMemoryManagerProxies.h"
-#include "llvm/ExecutionEngine/Orc/RTBridge/SPS/ProxySpec.h"
-#include "llvm/ExecutionEngine/Orc/Shared/SPSCI/SimpleNativeMemoryMapSPSCI.h"
-
-namespace llvm::orc::rt::sps {
-
-using MemMgrReserveProxySpec =
-    ProxySpec<rt::MemMgrReserveProxy, sps_ci::MemMgrReserve>;
-using MemMgrInitializeProxySpec =
-    ProxySpec<rt::MemMgrInitializeProxy, sps_ci::MemMgrInitialize>;
-using MemMgrDeinitializeProxySpec =
-    ProxySpec<rt::MemMgrDeinitializeProxy, sps_ci::MemMgrDeinitialize>;
-using MemMgrReleaseProxySpec =
-    ProxySpec<rt::MemMgrReleaseProxy, sps_ci::MemMgrRelease>;
-
-} // namespace llvm::orc::rt::sps
-
-#endif // LLVM_EXECUTIONENGINE_ORC_RTBRIDGE_SPS_GENERICMEMORYMANAGERPROXYSPECS_H
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/RTBridge/SPS/MemoryAccessProxySpecs.h b/llvm/include/llvm/ExecutionEngine/Orc/RTBridge/SPS/MemoryAccessProxySpecs.h
deleted file mode 100644
index 107bc5469adb1..0000000000000
--- a/llvm/include/llvm/ExecutionEngine/Orc/RTBridge/SPS/MemoryAccessProxySpecs.h
+++ /dev/null
@@ -1,53 +0,0 @@
-//===-- MemoryAccessProxySpecs.h - SPS specs for mem access -----*- 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
-//
-//===----------------------------------------------------------------------===//
-//
-// SPS ProxySpecs for the MemoryAccessProxies: each binds a Proxy to its
-// controller-interface descriptor in Shared/SPSCI/MemoryAccessSPSCI.h, which
-// supplies the wrapper name and wire signature.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_EXECUTIONENGINE_ORC_RTBRIDGE_SPS_MEMORYACCESSPROXYSPECS_H
-#define LLVM_EXECUTIONENGINE_ORC_RTBRIDGE_SPS_MEMORYACCESSPROXYSPECS_H
-
-#include "llvm/ExecutionEngine/Orc/RTBridge/MemoryAccessProxies.h"
-#include "llvm/ExecutionEngine/Orc/RTBridge/SPS/ProxySpec.h"
-#include "llvm/ExecutionEngine/Orc/Shared/SPSCI/MemoryAccessSPSCI.h"
-
-namespace llvm::orc::rt::sps {
-
-using MemWriteUInt8sProxySpec =
-    ProxySpec<rt::MemWriteUInt8sProxy, sps_ci::MemWriteUInt8s>;
-using MemWriteUInt16sProxySpec =
-    ProxySpec<rt::MemWriteUInt16sProxy, sps_ci::MemWriteUInt16s>;
-using MemWriteUInt32sProxySpec =
-    ProxySpec<rt::MemWriteUInt32sProxy, sps_ci::MemWriteUInt32s>;
-using MemWriteUInt64sProxySpec =
-    ProxySpec<rt::MemWriteUInt64sProxy, sps_ci::MemWriteUInt64s>;
-using MemWritePointersProxySpec =
-    ProxySpec<rt::MemWritePointersProxy, sps_ci::MemWritePointers>;
-using MemWriteBuffersProxySpec =
-    ProxySpec<rt::MemWriteBuffersProxy, sps_ci::MemWriteBuffers>;
-using MemReadUInt8sProxySpec =
-    ProxySpec<rt::MemReadUInt8sProxy, sps_ci::MemReadUInt8s>;
-using MemReadUInt16sProxySpec =
-    ProxySpec<rt::MemReadUInt16sProxy, sps_ci::MemReadUInt16s>;
-using MemReadUInt32sProxySpec =
-    ProxySpec<rt::MemReadUInt32sProxy, sps_ci::MemReadUInt32s>;
-using MemReadUInt64sProxySpec =
-    ProxySpec<rt::MemReadUInt64sProxy, sps_ci::MemReadUInt64s>;
-using MemReadPointersProxySpec =
-    ProxySpec<rt::MemReadPointersProxy, sps_ci::MemReadPointers>;
-using MemReadBuffersProxySpec =
-    ProxySpec<rt::MemReadBuffersProxy, sps_ci::MemReadBuffers>;
-using MemReadStringsProxySpec =
-    ProxySpec<rt::MemReadStringsProxy, sps_ci::MemReadStrings>;
-
-} // namespace llvm::orc::rt::sps
-
-#endif // LLVM_EXECUTIONENGINE_ORC_RTBRIDGE_SPS_MEMORYACCESSPROXYSPECS_H
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/RTBridge/SPS/ProxySpec.h b/llvm/include/llvm/ExecutionEngine/Orc/SPSProxySpec.h
similarity index 77%
rename from llvm/include/llvm/ExecutionEngine/Orc/RTBridge/SPS/ProxySpec.h
rename to llvm/include/llvm/ExecutionEngine/Orc/SPSProxySpec.h
index 66c7b6b0654f0..130bfce45f866 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/RTBridge/SPS/ProxySpec.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/SPSProxySpec.h
@@ -1,4 +1,4 @@
-//===------- ProxySpec.h - SPS dispatch for rt::Proxy -----------*- C++ -*-===//
+//===------- SPSProxySpec.h - SPS dispatch for orc::Proxy -------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,23 +6,24 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// ProxySpec implements an rt::Proxy's dispatch by invoking an executor-side
+// ProxySpec implements an orc::Proxy's dispatch by invoking an executor-side
 // wrapper function in the runtime's controller interface, using Simple Packed
 // Serialization to encode arguments and decode results.
 //
-// Specs for specific operation families live in sibling headers whose specs
-// only need Shared/SPS vocabulary types (e.g. CallProxySpecs.h,
-// MemoryAccessProxySpecs.h).
+// A ProxySpec pairs a Proxy with a controller-interface descriptor from
+// Shared/SPSCI, which supplies the wrapper name and wire signature. Specs for
+// specific operation families live alongside the utilities that use them (e.g.
+// CallProxiesSPS.h, EPCGenericMemoryAccessSPS.h).
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_EXECUTIONENGINE_ORC_RTBRIDGE_SPS_PROXYSPEC_H
-#define LLVM_EXECUTIONENGINE_ORC_RTBRIDGE_SPS_PROXYSPEC_H
+#ifndef LLVM_EXECUTIONENGINE_ORC_SPSPROXYSPEC_H
+#define LLVM_EXECUTIONENGINE_ORC_SPSPROXYSPEC_H
 
 #include "llvm/ExecutionEngine/Orc/Core.h"
-#include "llvm/ExecutionEngine/Orc/RTBridge/Proxy.h"
+#include "llvm/ExecutionEngine/Orc/Proxy.h"
 
-namespace llvm::orc::rt::sps {
+namespace llvm::orc::sps {
 
 template <typename ProxyT, typename CI,
           typename FnType = typename ProxyT::FnType>
@@ -72,6 +73,6 @@ class ProxySpec<ProxyT, CI, RetT(ArgTs...)> {
   }
 };
 
-} // namespace llvm::orc::rt::sps
+} // namespace llvm::orc::sps
 
-#endif // LLVM_EXECUTIONENGINE_ORC_RTBRIDGE_SPS_PROXYSPEC_H
+#endif // LLVM_EXECUTIONENGINE_ORC_SPSPROXYSPEC_H
diff --git a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
index e3cf6cfae3ad6..26306f36fbdaf 100644
--- a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
+++ b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
@@ -20,7 +20,10 @@ add_llvm_component_library(LLVMOrcJIT
   EHFrameRegistrationPlugin.cpp
   EPCDynamicLibrarySearchGenerator.cpp
   EPCGenericDylibManager.cpp
+  EPCGenericDylibManagerSPS.cpp
   EPCGenericJITLinkMemoryManager.cpp
+  EPCGenericJITLinkMemoryManagerSPS.cpp
+  EPCGenericMemoryAccessSPS.cpp
   EPCGenericRTDyldMemoryManager.cpp
   EPCIndirectionUtils.cpp
   ExecutionUtils.cpp
diff --git a/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp
index 5612e8976ab5b..ca62be4bb44ad 100644
--- a/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp
@@ -10,10 +10,10 @@
 
 #include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"
 #include "llvm/ExecutionEngine/Orc/COFF.h"
+#include "llvm/ExecutionEngine/Orc/CallProxiesSPS.h"
 #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
 #include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
 #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
-#include "llvm/ExecutionEngine/Orc/RTBridge/SPS/CallProxySpecs.h"
 #include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"
 #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
 #include "llvm/Object/COFF.h"
@@ -663,9 +663,9 @@ Error COFFPlatform::runBootstrapInitializers(JDBootstrapState &BState) {
 Error COFFPlatform::runBootstrapSubsectionInitializers(JDBootstrapState &BState,
                                                        StringRef Start,
                                                        StringRef End) {
-  rt::CallInt32VoidProxy CallInitializer;
-  if (auto Err = rt::buildProxies(
-          ES, rt::proxyInit<rt::sps::CallInt32VoidProxySpec>(&CallInitializer)))
+  CallInt32VoidProxy CallInitializer;
+  if (auto Err = buildProxies(
+          ES, proxyInit<sps::CallInt32VoidProxySpec>(&CallInitializer)))
     return Err;
   for (auto &Initializer : BState.Initializers)
     if (Initializer.first >= Start && Initializer.first <= End &&
@@ -736,9 +736,9 @@ Error COFFPlatform::runSymbolIfExists(JITDylib &PlatformJD,
       ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD),
       {{ES.intern(SymbolName), &jit_function}});
   if (!AfterCLookupErr) {
-    rt::CallInt32VoidProxy CallFn;
-    if (auto Err = rt::buildProxies(
-            ES, rt::proxyInit<rt::sps::CallInt32VoidProxySpec>(&CallFn)))
+    CallInt32VoidProxy CallFn;
+    if (auto Err =
+            buildProxies(ES, proxyInit<sps::CallInt32VoidProxySpec>(&CallFn)))
       return Err;
     auto Res = CallFn(ES, jit_function);
     if (!Res)
diff --git a/llvm/lib/ExecutionEngine/Orc/COFFVCRuntimeSupport.cpp b/llvm/lib/ExecutionEngine/Orc/COFFVCRuntimeSupport.cpp
index 9a70f15278257..a9010a3fc76f7 100644
--- a/llvm/lib/ExecutionEngine/Orc/COFFVCRuntimeSupport.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/COFFVCRuntimeSupport.cpp
@@ -9,9 +9,9 @@
 #include "llvm/ExecutionEngine/Orc/COFFVCRuntimeSupport.h"
 
 #include "llvm/ExecutionEngine/Orc/COFF.h"
+#include "llvm/ExecutionEngine/Orc/CallProxiesSPS.h"
 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
 #include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
-#include "llvm/ExecutionEngine/Orc/RTBridge/SPS/CallProxySpecs.h"
 #include "llvm/Support/VirtualFileSystem.h"
 #include "llvm/WindowsDriver/MSVCPaths.h"
 
@@ -124,11 +124,11 @@ Error COFFVCRuntimeBootstrapper::initializeStaticVCRuntime(JITDylib &JD) {
             &jit_scrt_initialize_default_local_stdio_options}}))
     return Err;
 
-  rt::CallInt32VoidProxy CallInt32Void;
-  rt::CallInt32Int32Proxy CallInt32Int32;
+  CallInt32VoidProxy CallInt32Void;
+  CallInt32Int32Proxy CallInt32Int32;
   if (auto Err = buildProxies(
-          ES, rt::proxyInit<rt::sps::CallInt32VoidProxySpec>(&CallInt32Void),
-          rt::proxyInit<rt::sps::CallInt32Int32ProxySpec>(&CallInt32Int32)))
+          ES, proxyInit<sps::CallInt32VoidProxySpec>(&CallInt32Void),
+          proxyInit<sps::CallInt32Int32ProxySpec>(&CallInt32Int32)))
     return Err;
 
   auto R = CallInt32Int32(ES, jit_scrt_initialize, 0);
diff --git a/llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManager.cpp b/llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManager.cpp
index d98ec834d6f55..73f9a586470ad 100644
--- a/llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManager.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManager.cpp
@@ -9,72 +9,9 @@
 #include "llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h"
 
 #include "llvm/ExecutionEngine/Orc/Core.h"
-#include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
-#include "llvm/ExecutionEngine/Orc/RTBridge/SPS/ProxySpec.h"
-#include "llvm/ExecutionEngine/Orc/Shared/SPSCI/NativeDylibManagerSPSCI.h"
-#include "llvm/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.h"
 
 namespace llvm {
 namespace orc {
-namespace shared {
-
-// Serialize a local SymbolLookupSet directly as an SPSRemoteSymbolLookupSet,
-// avoiding a std::string copy of each (potentially large) symbol name.
-template <>
-class SPSSerializationTraits<SPSRemoteSymbolLookupSetElement,
-                             SymbolLookupSet::value_type> {
-public:
-  static size_t size(const SymbolLookupSet::value_type &V) {
-    return SPSArgList<SPSString, bool>::size(
-        *V.first, V.second == SymbolLookupFlags::RequiredSymbol);
-  }
-
-  static bool serialize(SPSOutputBuffer &OB,
-                        const SymbolLookupSet::value_type &V) {
-    return SPSArgList<SPSString, bool>::serialize(
-        OB, *V.first, V.second == SymbolLookupFlags::RequiredSymbol);
-  }
-};
-
-template <>
-class TrivialSPSSequenceSerialization<SPSRemoteSymbolLookupSetElement,
-                                      SymbolLookupSet> {
-public:
-  static constexpr bool available = true;
-};
-
-} // end namespace shared
-
-namespace {
-
-using OpenSpec = rt::sps::ProxySpec<EPCGenericDylibManager::OpenProxy,
-                                    rt::sps_ci::DylibMgrOpen>;
-using ResolveSpec = rt::sps::ProxySpec<EPCGenericDylibManager::ResolveProxy,
-                                       rt::sps_ci::DylibMgrResolve>;
-
-} // namespace
-
-Expected<EPCGenericDylibManager> EPCGenericDylibManager::Create(JITDylib &JD) {
-  auto &ES = JD.getExecutionSession();
-  Bindings B;
-  // Instance is the executor-side manager object -- a data symbol passed as the
-  // first argument to each call, not a wrapper to proxy.
-  if (auto Err = lookupAndRecordAddrs(
-          ES, LookupKind::Static, makeJITDylibSearchOrder({&JD}),
-          {{ES.intern(rt::sps_ci::NativeDylibManagerInstanceName),
-            &B.Instance}}))
-    return std::move(Err);
-  // The proxies resolve to the specs' default (NativeDylibManager) names.
-  if (auto Err = rt::buildProxies(JD, rt::proxyInit<OpenSpec>(&B.Open),
-                                  rt::proxyInit<ResolveSpec>(&B.Resolve)))
-    return std::move(Err);
-  return EPCGenericDylibManager(ES, std::move(B));
-}
-
-Expected<EPCGenericDylibManager>
-EPCGenericDylibManager::Create(ExecutionSession &ES) {
-  return Create(ES.getBootstrapJITDylib());
-}
 
 Expected<tpctypes::DylibHandle> EPCGenericDylibManager::open(StringRef Path,
                                                              uint64_t Mode) {
diff --git a/llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManagerSPS.cpp b/llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManagerSPS.cpp
new file mode 100644
index 0000000000000..c9c44998bdcb3
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManagerSPS.cpp
@@ -0,0 +1,69 @@
+//===- EPCGenericDylibManagerSPS.cpp - SPS dylib management ---------------===//
+//
+// 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/EPCGenericDylibManagerSPS.h"
+
+#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
+#include "llvm/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.h"
+
+namespace llvm::orc::shared {
+
+// Serialize a local SymbolLookupSet directly as an SPSRemoteSymbolLookupSet,
+// avoiding a std::string copy of each (potentially large) symbol name.
+template <>
+class SPSSerializationTraits<SPSRemoteSymbolLookupSetElement,
+                             SymbolLookupSet::value_type> {
+public:
+  static size_t size(const SymbolLookupSet::value_type &V) {
+    return SPSArgList<SPSString, bool>::size(
+        *V.first, V.second == SymbolLookupFlags::RequiredSymbol);
+  }
+
+  static bool serialize(SPSOutputBuffer &OB,
+                        const SymbolLookupSet::value_type &V) {
+    return SPSArgList<SPSString, bool>::serialize(
+        OB, *V.first, V.second == SymbolLookupFlags::RequiredSymbol);
+  }
+};
+
+template <>
+class TrivialSPSSequenceSerialization<SPSRemoteSymbolLookupSetElement,
+                                      SymbolLookupSet> {
+public:
+  static constexpr bool available = true;
+};
+
+} // namespace llvm::orc::shared
+
+namespace llvm::orc::sps {
+
+Expected<std::unique_ptr<EPCGenericDylibManager>>
+createEPCGenericDylibManager(JITDylib &JD) {
+  auto &ES = JD.getExecutionSession();
+  EPCGenericDylibManager::Bindings B;
+  // Instance is the executor-side manager object -- a data symbol passed as the
+  // first argument to each call, not a wrapper to proxy.
+  if (auto Err = lookupAndRecordAddrs(
+          ES, LookupKind::Static, makeJITDylibSearchOrder({&JD}),
+          {{ES.intern(rt::sps_ci::NativeDylibManagerInstanceName),
+            &B.Instance}}))
+    return std::move(Err);
+  // The proxies resolve to the specs' default (NativeDylibManager) names.
+  if (auto Err = buildProxies(JD, proxyInit<DylibMgrOpenProxySpec>(&B.Open),
+                              proxyInit<DylibMgrResolveProxySpec>(&B.Resolve)))
+    return std::move(Err);
+  return std::make_unique<EPCGenericDylibManager>(ES, std::move(B));
+}
+
+Expected<std::unique_ptr<EPCGenericDylibManager>>
+createEPCGenericDylibManager(ExecutionSession &ES) {
+  return createEPCGenericDylibManager(ES.getBootstrapJITDylib());
+}
+
+} // namespace llvm::orc::sps
diff --git a/llvm/lib/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.cpp b/llvm/lib/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.cpp
index bf9c774082697..a80059f540288 100644
--- a/llvm/lib/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.cpp
@@ -9,9 +9,6 @@
 #include "llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h"
 
 #include "llvm/ExecutionEngine/JITLink/JITLink.h"
-#include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
-#include "llvm/ExecutionEngine/Orc/RTBridge/SPS/GenericMemoryManagerProxySpecs.h"
-#include "llvm/ExecutionEngine/Orc/Shared/SPSCI/SimpleNativeMemoryMapSPSCI.h"
 
 #include <limits>
 
@@ -82,34 +79,6 @@ class EPCGenericJITLinkMemoryManager::InFlightAlloc
   SegInfoMap Segs;
 };
 
-Expected<std::unique_ptr<EPCGenericJITLinkMemoryManager>>
-EPCGenericJITLinkMemoryManager::Create(JITDylib &JD) {
-  namespace sps = rt::sps;
-  namespace sps_ci = rt::sps_ci;
-  auto &ES = JD.getExecutionSession();
-  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.
-  if (auto Err = lookupAndRecordAddrs(
-          ES, LookupKind::Static, makeJITDylibSearchOrder({&JD}),
-          {{ES.intern(sps_ci::SimpleNativeMemoryMapInstanceName),
-            &B.Instance}}))
-    return std::move(Err);
-  // The proxies resolve to the specs' default (SimpleNativeMemoryMap) names.
-  if (auto Err = rt::buildProxies(
-          JD, rt::proxyInit<sps::MemMgrReserveProxySpec>(&B.Reserve),
-          rt::proxyInit<sps::MemMgrInitializeProxySpec>(&B.Initialize),
-          rt::proxyInit<sps::MemMgrDeinitializeProxySpec>(&B.Deinitialize),
-          rt::proxyInit<sps::MemMgrReleaseProxySpec>(&B.Release)))
-    return std::move(Err);
-  return std::make_unique<EPCGenericJITLinkMemoryManager>(ES, std::move(B));
-}
-
-Expected<std::unique_ptr<EPCGenericJITLinkMemoryManager>>
-EPCGenericJITLinkMemoryManager::Create(ExecutionSession &ES) {
-  return Create(ES.getBootstrapJITDylib());
-}
-
 void EPCGenericJITLinkMemoryManager::allocate(const JITLinkDylib *JD,
                                               LinkGraph &G,
                                               OnAllocatedFunction OnAllocated) {
diff --git a/llvm/lib/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerSPS.cpp b/llvm/lib/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerSPS.cpp
new file mode 100644
index 0000000000000..e57d704ebafd6
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerSPS.cpp
@@ -0,0 +1,42 @@
+//===- EPCGenericJITLinkMemoryManagerSPS.cpp - SPS mem manager ------------===//
+//
+// 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/EPCGenericJITLinkMemoryManagerSPS.h"
+
+#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.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.
+  if (auto Err = lookupAndRecordAddrs(
+          ES, LookupKind::Static, makeJITDylibSearchOrder({&JD}),
+          {{ES.intern(rt::sps_ci::SimpleNativeMemoryMapInstanceName),
+            &B.Instance}}))
+    return std::move(Err);
+  // The proxies resolve to the specs' default (SimpleNativeMemoryMap) names.
+  if (auto Err =
+          buildProxies(JD, proxyInit<MemMgrReserveProxySpec>(&B.Reserve),
+                       proxyInit<MemMgrInitializeProxySpec>(&B.Initialize),
+                       proxyInit<MemMgrDeinitializeProxySpec>(&B.Deinitialize),
+                       proxyInit<MemMgrReleaseProxySpec>(&B.Release)))
+    return std::move(Err);
+  return std::make_unique<EPCGenericJITLinkMemoryManager>(ES, std::move(B));
+}
+
+Expected<std::unique_ptr<EPCGenericJITLinkMemoryManager>>
+createEPCGenericJITLinkMemoryManager(ExecutionSession &ES) {
+  return createEPCGenericJITLinkMemoryManager(ES.getBootstrapJITDylib());
+}
+
+} // namespace llvm::orc::sps
diff --git a/llvm/lib/ExecutionEngine/Orc/EPCGenericMemoryAccessSPS.cpp b/llvm/lib/ExecutionEngine/Orc/EPCGenericMemoryAccessSPS.cpp
new file mode 100644
index 0000000000000..8c5f305c78e94
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/EPCGenericMemoryAccessSPS.cpp
@@ -0,0 +1,43 @@
+//===- EPCGenericMemoryAccessSPS.cpp - SPS memory access ------------------===//
+//
+// 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/EPCGenericMemoryAccessSPS.h"
+
+#include "llvm/ExecutionEngine/Orc/Core.h"
+
+namespace llvm::orc::sps {
+
+Expected<std::unique_ptr<EPCGenericMemoryAccess>>
+createEPCGenericMemoryAccess(JITDylib &JD) {
+  auto &ES = JD.getExecutionSession();
+  EPCGenericMemoryAccess::Funcs Fns;
+  // The proxies resolve to the specs' default controller-interface names.
+  if (auto Err =
+          buildProxies(JD, proxyInit<MemWriteUInt8sProxySpec>(&Fns.WriteUInt8s),
+                       proxyInit<MemWriteUInt16sProxySpec>(&Fns.WriteUInt16s),
+                       proxyInit<MemWriteUInt32sProxySpec>(&Fns.WriteUInt32s),
+                       proxyInit<MemWriteUInt64sProxySpec>(&Fns.WriteUInt64s),
+                       proxyInit<MemWritePointersProxySpec>(&Fns.WritePointers),
+                       proxyInit<MemWriteBuffersProxySpec>(&Fns.WriteBuffers),
+                       proxyInit<MemReadUInt8sProxySpec>(&Fns.ReadUInt8s),
+                       proxyInit<MemReadUInt16sProxySpec>(&Fns.ReadUInt16s),
+                       proxyInit<MemReadUInt32sProxySpec>(&Fns.ReadUInt32s),
+                       proxyInit<MemReadUInt64sProxySpec>(&Fns.ReadUInt64s),
+                       proxyInit<MemReadPointersProxySpec>(&Fns.ReadPointers),
+                       proxyInit<MemReadBuffersProxySpec>(&Fns.ReadBuffers),
+                       proxyInit<MemReadStringsProxySpec>(&Fns.ReadStrings)))
+    return std::move(Err);
+  return std::make_unique<EPCGenericMemoryAccess>(ES, std::move(Fns));
+}
+
+Expected<std::unique_ptr<EPCGenericMemoryAccess>>
+createEPCGenericMemoryAccess(ExecutionSession &ES) {
+  return createEPCGenericMemoryAccess(ES.getBootstrapJITDylib());
+}
+
+} // namespace llvm::orc::sps
diff --git a/llvm/lib/ExecutionEngine/Orc/InProcessEPC.cpp b/llvm/lib/ExecutionEngine/Orc/InProcessEPC.cpp
index 291ee51a28fce..3f1a0621d8a31 100644
--- a/llvm/lib/ExecutionEngine/Orc/InProcessEPC.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/InProcessEPC.cpp
@@ -9,9 +9,9 @@
 #include "llvm/ExecutionEngine/Orc/InProcessEPC.h"
 
 #include "llvm/ExecutionEngine/Orc/Core.h"
-#include "llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h"
-#include "llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h"
-#include "llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h"
+#include "llvm/ExecutionEngine/Orc/EPCGenericDylibManagerSPS.h"
+#include "llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerSPS.h"
+#include "llvm/ExecutionEngine/Orc/EPCGenericMemoryAccessSPS.h"
 #include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h"
 #include "llvm/Support/DynamicLibrary.h"
 #include "llvm/Support/Process.h"
@@ -156,21 +156,18 @@ void InProcessEPC::callWrapperAsync(ExecutorAddr WrapperFnAddr,
 Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
 InProcessEPC::createDefaultMemoryManager() {
   // FIXME: Should actually use InProcessMemoryManager for this.
-  return EPCGenericJITLinkMemoryManager::Create(getExecutionSession());
+  return sps::createEPCGenericJITLinkMemoryManager(getExecutionSession());
 }
 
 Expected<std::unique_ptr<DylibManager>> InProcessEPC::createDefaultDylibMgr() {
   // FIXME: Should actually use in-process for this.
-  auto DM = EPCGenericDylibManager::Create(getExecutionSession());
-  if (!DM)
-    return DM.takeError();
-  return std::make_unique<EPCGenericDylibManager>(std::move(*DM));
+  return sps::createEPCGenericDylibManager(getExecutionSession());
 }
 
 Expected<std::unique_ptr<MemoryAccess>>
 InProcessEPC::createDefaultMemoryAccess() {
   // FIXME: Should actually use in-process for this.
-  return EPCGenericMemoryAccess::Create(getExecutionSession());
+  return sps::createEPCGenericMemoryAccess(getExecutionSession());
 }
 
 Error InProcessEPC::disconnect() {
diff --git a/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp b/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp
index e18ae7cc48a71..0d4e889de202f 100644
--- a/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp
@@ -7,10 +7,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h"
-#include "llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h"
-#include "llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h"
-#include "llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h"
-#include "llvm/ExecutionEngine/Orc/RTBridge/SPS/CallProxySpecs.h"
+#include "llvm/ExecutionEngine/Orc/CallProxiesSPS.h"
+#include "llvm/ExecutionEngine/Orc/EPCGenericDylibManagerSPS.h"
+#include "llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerSPS.h"
+#include "llvm/ExecutionEngine/Orc/EPCGenericMemoryAccessSPS.h"
 #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
 #include "llvm/Support/FormatVariadic.h"
 
@@ -73,20 +73,17 @@ void SimpleRemoteEPC::callWrapperAsync(ExecutorAddr WrapperFnAddr,
 
 Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
 SimpleRemoteEPC::createDefaultMemoryManager() {
-  return EPCGenericJITLinkMemoryManager::Create(getExecutionSession());
+  return sps::createEPCGenericJITLinkMemoryManager(getExecutionSession());
 }
 
 Expected<std::unique_ptr<DylibManager>>
 SimpleRemoteEPC::createDefaultDylibMgr() {
-  auto DM = EPCGenericDylibManager::Create(getExecutionSession());
-  if (!DM)
-    return DM.takeError();
-  return std::make_unique<EPCGenericDylibManager>(std::move(*DM));
+  return sps::createEPCGenericDylibManager(getExecutionSession());
 }
 
 Expected<std::unique_ptr<MemoryAccess>>
 SimpleRemoteEPC::createDefaultMemoryAccess() {
-  return EPCGenericMemoryAccess::Create(getExecutionSession());
+  return sps::createEPCGenericMemoryAccess(getExecutionSession());
 }
 
 Error SimpleRemoteEPC::disconnect() {
diff --git a/llvm/tools/lli/ForwardingMemoryManager.h b/llvm/tools/lli/ForwardingMemoryManager.h
index 8e4dc024f04cb..d131ca466df07 100644
--- a/llvm/tools/lli/ForwardingMemoryManager.h
+++ b/llvm/tools/lli/ForwardingMemoryManager.h
@@ -14,7 +14,7 @@
 #define LLVM_TOOLS_LLI_FORWARDINGMEMORYMANAGER_H
 
 #include "llvm/ExecutionEngine/Orc/Core.h"
-#include "llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h"
+#include "llvm/ExecutionEngine/Orc/EPCGenericDylibManagerSPS.h"
 #include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
 #include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
 
@@ -93,10 +93,10 @@ class RemoteResolver : public LegacyJITSymbolResolver {
 public:
   static Expected<std::unique_ptr<RemoteResolver>>
   Create(orc::ExecutionSession &ES) {
-    auto DylibMgr = orc::EPCGenericDylibManager::Create(ES);
+    auto DylibMgr = orc::sps::createEPCGenericDylibManager(ES);
     if (!DylibMgr)
       return DylibMgr.takeError();
-    auto H = DylibMgr->open("", 0);
+    auto H = (*DylibMgr)->open("", 0);
     if (!H)
       return H.takeError();
     return std::make_unique<RemoteResolver>(ES, std::move(*DylibMgr),
@@ -106,7 +106,7 @@ class RemoteResolver : public LegacyJITSymbolResolver {
   JITSymbol findSymbol(const std::string &Name) override {
     orc::SymbolLookupSet LS(ES.intern(Name),
                             orc::SymbolLookupFlags::WeaklyReferencedSymbol);
-    if (auto Syms = DylibMgr.lookup(H, LS)) {
+    if (auto Syms = DylibMgr->lookup(H, LS)) {
       if (Syms->size() != 1)
         return make_error<StringError>("Unexpected remote lookup result",
                                        inconvertibleErrorCode());
@@ -124,12 +124,12 @@ class RemoteResolver : public LegacyJITSymbolResolver {
 
 public:
   RemoteResolver(orc::ExecutionSession &ES,
-                 orc::EPCGenericDylibManager DylibMgr,
+                 std::unique_ptr<orc::EPCGenericDylibManager> DylibMgr,
                  orc::tpctypes::DylibHandle H)
       : ES(ES), DylibMgr(std::move(DylibMgr)), H(std::move(H)) {}
 
   orc::ExecutionSession &ES;
-  orc::EPCGenericDylibManager DylibMgr;
+  std::unique_ptr<orc::EPCGenericDylibManager> DylibMgr;
   orc::tpctypes::DylibHandle H;
 };
 } // namespace llvm
diff --git a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt b/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
index 5dc798c64eea9..8af05a8b32e8f 100644
--- a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
+++ b/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
@@ -48,7 +48,7 @@ add_llvm_unittest(OrcJITTests
   SharedMemoryMapperTest.cpp
   SimpleExecutorMemoryManagerTest.cpp
   SimplePackedSerializationTest.cpp
-  SPSProxiesTest.cpp
+  SPSProxySpecTest.cpp
   SymbolStringPoolTest.cpp
   TaskDispatchTest.cpp
   ThreadSafeModuleTest.cpp
diff --git a/llvm/unittests/ExecutionEngine/Orc/EPCGenericDylibManagerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/EPCGenericDylibManagerTest.cpp
index f97d055201abb..1f69990f39b88 100644
--- a/llvm/unittests/ExecutionEngine/Orc/EPCGenericDylibManagerTest.cpp
+++ b/llvm/unittests/ExecutionEngine/Orc/EPCGenericDylibManagerTest.cpp
@@ -8,7 +8,7 @@
 
 #include "OrcTestCommon.h"
 
-#include "llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h"
+#include "llvm/ExecutionEngine/Orc/EPCGenericDylibManagerSPS.h"
 
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ExecutionEngine/Orc/Core.h"
@@ -44,7 +44,7 @@ TEST(EPCGenericDylibManagerTest, CreateFromExecutionSession) {
       std::make_unique<EPCWithBootstrapSymbols>(SSP, std::move(BootstrapSyms));
   ExecutionSession ES(std::move(EPC));
 
-  auto Result = EPCGenericDylibManager::Create(ES);
+  auto Result = sps::createEPCGenericDylibManager(ES);
   EXPECT_THAT_EXPECTED(Result, Succeeded());
 
   cantFail(ES.endSession());
diff --git a/llvm/unittests/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerTest.cpp
index 71d2106d18a97..fd39f9fbc7227 100644
--- a/llvm/unittests/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerTest.cpp
+++ b/llvm/unittests/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerTest.cpp
@@ -8,7 +8,7 @@
 
 #include "OrcTestCommon.h"
 
-#include "llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h"
+#include "llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerSPS.h"
 
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"
@@ -129,7 +129,7 @@ TEST(EPCGenericJITLinkMemoryManagerTest, AllocFinalizeFree) {
        {ExecutorAddr::fromPtr(&testRelease), Exported}},
   })));
 
-  auto MemMgr = cantFail(EPCGenericJITLinkMemoryManager::Create(ES));
+  auto MemMgr = cantFail(sps::createEPCGenericJITLinkMemoryManager(ES));
   StringRef Hello = "hello";
   auto SSA = jitlink::SimpleSegmentAlloc::Create(
       *MemMgr, std::make_shared<SymbolStringPool>(),
@@ -181,7 +181,7 @@ TEST(EPCGenericJITLinkMemoryManagerTest, CreateFromJITDylib) {
        {ReleaseAddr, JITSymbolFlags::Exported}},
   })));
 
-  auto Result = EPCGenericJITLinkMemoryManager::Create(JD);
+  auto Result = sps::createEPCGenericJITLinkMemoryManager(JD);
   EXPECT_THAT_EXPECTED(Result, Succeeded());
 
   cantFail(ES.endSession());
@@ -202,7 +202,7 @@ TEST(EPCGenericJITLinkMemoryManagerTest, CreateFailsOnMissingSymbol) {
        {ExecutorAddr(1), JITSymbolFlags::Exported}},
   })));
 
-  auto Result = EPCGenericJITLinkMemoryManager::Create(JD);
+  auto Result = sps::createEPCGenericJITLinkMemoryManager(JD);
   EXPECT_THAT_EXPECTED(Result, Failed());
 
   cantFail(ES.endSession());
@@ -236,7 +236,7 @@ TEST(EPCGenericJITLinkMemoryManagerTest, CreateFromExecutionSession) {
       std::make_unique<EPCWithBootstrapSymbols>(SSP, std::move(BootstrapSyms));
   ExecutionSession ES(std::move(EPC));
 
-  auto Result = EPCGenericJITLinkMemoryManager::Create(ES);
+  auto Result = sps::createEPCGenericJITLinkMemoryManager(ES);
   EXPECT_THAT_EXPECTED(Result, Succeeded());
 
   cantFail(ES.endSession());
diff --git a/llvm/unittests/ExecutionEngine/Orc/EPCGenericMemoryAccessTest.cpp b/llvm/unittests/ExecutionEngine/Orc/EPCGenericMemoryAccessTest.cpp
index f5438ed650833..6c25cfb48d6c2 100644
--- a/llvm/unittests/ExecutionEngine/Orc/EPCGenericMemoryAccessTest.cpp
+++ b/llvm/unittests/ExecutionEngine/Orc/EPCGenericMemoryAccessTest.cpp
@@ -9,7 +9,7 @@
 #include "OrcTestCommon.h"
 
 #include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"
-#include "llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h"
+#include "llvm/ExecutionEngine/Orc/EPCGenericMemoryAccessSPS.h"
 #include "llvm/ExecutionEngine/Orc/SelfExecutorProcessControl.h"
 #include "llvm/ExecutionEngine/Orc/Shared/SPSCI/MemoryAccessSPSCI.h"
 #include "llvm/Testing/Support/Error.h"
@@ -122,7 +122,7 @@ class EPCGenericMemoryAccessTest : public testing::Test {
         cantFail(SelfExecutorProcessControl::Create()));
 
     // Register the test wrappers in the bootstrap JITDylib under the SPS
-    // controller-interface names, so that EPCGenericMemoryAccess::Create
+    // controller-interface names, so that sps::createEPCGenericMemoryAccess
     // resolves its proxies to them.
     namespace sps_ci = rt::sps_ci;
     auto Exported = JITSymbolFlags::Exported;
@@ -162,7 +162,7 @@ class EPCGenericMemoryAccessTest : public testing::Test {
          {ES->intern(sps_ci::MemReadStrings::Name),
           {ExecutorAddr::fromPtr(&testReadStrings), Exported}}})));
 
-    MemAccess = cantFail(EPCGenericMemoryAccess::Create(*ES));
+    MemAccess = cantFail(sps::createEPCGenericMemoryAccess(*ES));
   }
 
   ~EPCGenericMemoryAccessTest() override { cantFail(ES->endSession()); }
diff --git a/llvm/unittests/ExecutionEngine/Orc/ProxyTest.cpp b/llvm/unittests/ExecutionEngine/Orc/ProxyTest.cpp
index 0bd07edcf6d78..21c2e10c12c22 100644
--- a/llvm/unittests/ExecutionEngine/Orc/ProxyTest.cpp
+++ b/llvm/unittests/ExecutionEngine/Orc/ProxyTest.cpp
@@ -1,4 +1,4 @@
-//===- ProxyTest.cpp - Test rt::Proxy -------------------------------------===//
+//===- ProxyTest.cpp - Test Proxy -----------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,15 +6,15 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// Tests for rt::Proxy that are independent of any serialization protocol.
+// Tests for Proxy that are independent of any serialization protocol.
 // A trivial in-process dispatch (interpreting the callee address as a local
 // function pointer, no serialization) is used throughout -- this exercises the
 // Proxy plumbing directly and demonstrates that Proxy is protocol-agnostic.
-// The SPS protocol itself is tested in SPSProxiesTest.cpp.
+// The SPS protocol itself is tested in SPSProxySpecTest.cpp.
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/ExecutionEngine/Orc/RTBridge/Proxy.h"
+#include "llvm/ExecutionEngine/Orc/Proxy.h"
 #include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"
 #include "llvm/ExecutionEngine/Orc/SelfExecutorProcessControl.h"
 #include "llvm/Support/MSVCErrorWorkarounds.h"
@@ -33,13 +33,12 @@ namespace {
 int32_t addOne(int32_t X) { return X + 1; }
 
 // A protocol-free dispatch: interpret the callee address as a local function
-// pointer and call it directly. This drives rt::Proxy without any
+// pointer and call it directly. This drives Proxy without any
 // serialization, so the tests exercise Proxy's own logic (result plumbing,
 // operator bool, lookup) rather than a particular protocol.
 template <typename RetT, typename... ArgTs>
 void inProcessDispatch(
-    unique_function<void(typename rt::Proxy<RetT(ArgTs...)>::ErrorRetT)>
-        OnComplete,
+    unique_function<void(typename Proxy<RetT(ArgTs...)>::ErrorRetT)> OnComplete,
     ExecutionSession &ES, ExecutorAddr Callee, const ArgTs &...Args) {
   auto *Fn = Callee.toPtr<RetT(ArgTs...)>();
   if constexpr (std::is_void_v<RetT>) {
@@ -49,7 +48,7 @@ void inProcessDispatch(
     OnComplete(Fn(Args...));
 }
 
-using AddOneProxy = rt::Proxy<int32_t(int32_t)>;
+using AddOneProxy = Proxy<int32_t(int32_t)>;
 constexpr AddOneProxy::DispatchFn AddOneDispatch =
     &inProcessDispatch<int32_t, int32_t>;
 
@@ -61,7 +60,7 @@ Error maybeFail(bool ShouldFail) {
                                    inconvertibleErrorCode());
   return Error::success();
 }
-using MaybeFailProxy = rt::Proxy<Error(bool)>;
+using MaybeFailProxy = Proxy<Error(bool)>;
 constexpr MaybeFailProxy::DispatchFn MaybeFailDispatch =
     &inProcessDispatch<Error, bool>;
 
@@ -73,7 +72,7 @@ Expected<int32_t> addOneOrFail(int32_t Arg) {
                                    inconvertibleErrorCode());
   return Arg + 1;
 }
-using AddOneOrFailProxy = rt::Proxy<Expected<int32_t>(int32_t)>;
+using AddOneOrFailProxy = Proxy<Expected<int32_t>(int32_t)>;
 constexpr AddOneOrFailProxy::DispatchFn AddOneOrFailDispatch =
     &inProcessDispatch<Expected<int32_t>, int32_t>;
 
@@ -82,11 +81,11 @@ constexpr AddOneOrFailProxy::DispatchFn AddOneOrFailDispatch =
 //         Error -> Error
 //             T -> Expected<T>
 //   Expected<T> -> Expected<T>
-static_assert(std::is_same_v<rt::Proxy<void(int)>::ErrorRetT, Error>);
-static_assert(std::is_same_v<rt::Proxy<Error(int)>::ErrorRetT, Error>);
-static_assert(std::is_same_v<rt::Proxy<int(int)>::ErrorRetT, Expected<int>>);
+static_assert(std::is_same_v<Proxy<void(int)>::ErrorRetT, Error>);
+static_assert(std::is_same_v<Proxy<Error(int)>::ErrorRetT, Error>);
+static_assert(std::is_same_v<Proxy<int(int)>::ErrorRetT, Expected<int>>);
 static_assert(
-    std::is_same_v<rt::Proxy<Expected<int>(int)>::ErrorRetT, Expected<int>>);
+    std::is_same_v<Proxy<Expected<int>(int)>::ErrorRetT, Expected<int>>);
 
 // A minimal ProxySpec-shaped type (static dispatch + Name) for exercising the
 // proxyInit / buildProxies client path without depending on a protocol.
@@ -220,7 +219,7 @@ TEST(ProxyTest, BuildProxies) {
         {ExecutorAddr::fromPtr(addOne), JITSymbolFlags::Exported}}})));
 
   AddOneProxy Call;
-  cantFail(rt::buildProxies(ES, rt::proxyInit<AddOneSpec>(&Call)));
+  cantFail(buildProxies(ES, proxyInit<AddOneSpec>(&Call)));
   ASSERT_TRUE(static_cast<bool>(Call));
 
   Expected<int32_t> R = Call(ES, 41);
@@ -241,8 +240,8 @@ TEST(ProxyTest, BuildProxiesExplicitDispatch) {
         {ExecutorAddr::fromPtr(addOne), JITSymbolFlags::Exported}}})));
 
   AddOneProxy Call;
-  cantFail(rt::buildProxies(
-      ES, rt::proxyInit(&Call, AddOneDispatch, AddOneSpec::Name)));
+  cantFail(
+      buildProxies(ES, proxyInit(&Call, AddOneDispatch, AddOneSpec::Name)));
   ASSERT_TRUE(static_cast<bool>(Call));
 
   Expected<int32_t> R = Call(ES, 41);
@@ -265,8 +264,7 @@ TEST(ProxyTest, BuildProxiesSpecNameOverride) {
         {ExecutorAddr::fromPtr(addOne), JITSymbolFlags::Exported}}})));
 
   AddOneProxy Call;
-  cantFail(
-      rt::buildProxies(ES, rt::proxyInit<AddOneSpec>(&Call, "add_one_alias")));
+  cantFail(buildProxies(ES, proxyInit<AddOneSpec>(&Call, "add_one_alias")));
   ASSERT_TRUE(static_cast<bool>(Call));
 
   Expected<int32_t> R = Call(ES, 41);
@@ -282,9 +280,9 @@ TEST(ProxyTest, BuildProxiesWeaklyReferencedAbsent) {
   ExecutionSession ES(cantFail(SelfExecutorProcessControl::Create()));
 
   AddOneProxy Call;
-  cantFail(rt::buildProxies(
-      ES, rt::proxyInit<AddOneSpec>(
-              &Call, SymbolLookupFlags::WeaklyReferencedSymbol)));
+  cantFail(buildProxies(
+      ES,
+      proxyInit<AddOneSpec>(&Call, SymbolLookupFlags::WeaklyReferencedSymbol)));
   EXPECT_FALSE(static_cast<bool>(Call));
 
   cantFail(ES.endSession());
diff --git a/llvm/unittests/ExecutionEngine/Orc/SPSProxiesTest.cpp b/llvm/unittests/ExecutionEngine/Orc/SPSProxySpecTest.cpp
similarity index 92%
rename from llvm/unittests/ExecutionEngine/Orc/SPSProxiesTest.cpp
rename to llvm/unittests/ExecutionEngine/Orc/SPSProxySpecTest.cpp
index 23858f41f542b..0e2aa0a8222d5 100644
--- a/llvm/unittests/ExecutionEngine/Orc/SPSProxiesTest.cpp
+++ b/llvm/unittests/ExecutionEngine/Orc/SPSProxySpecTest.cpp
@@ -1,4 +1,4 @@
-//===- SPSProxiesTest.cpp - Test SPS proxy round-trips --------------------===//
+//===- SPSProxySpecTest.cpp - Test SPS proxy round-trips ------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -8,13 +8,13 @@
 //
 // End-to-end tests for the SPS proxies: that each Call*ProxySpec's dispatch
 // serializes its arguments, invokes the executor-side wrapper, and
-// deserializes the result. Generic rt::Proxy behavior (independent of the
+// deserializes the result. Generic Proxy behavior (independent of the
 // serialization protocol) is covered by ProxyTest.cpp.
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/ExecutionEngine/Orc/RTBridge/SPS/CallProxySpecs.h"
-#include "llvm/ExecutionEngine/Orc/RTBridge/SPS/ProxySpec.h"
+#include "llvm/ExecutionEngine/Orc/SPSProxySpec.h"
+#include "llvm/ExecutionEngine/Orc/CallProxiesSPS.h"
 #include "llvm/ExecutionEngine/Orc/SelfExecutorProcessControl.h"
 #include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h"
 #include "llvm/Support/MSVCErrorWorkarounds.h"
@@ -31,11 +31,11 @@ using namespace llvm;
 using namespace llvm::orc;
 using namespace llvm::orc::shared;
 
-namespace sps = llvm::orc::rt::sps;
-using llvm::orc::rt::CallInt32Int32Proxy;
-using llvm::orc::rt::CallInt32VoidProxy;
-using llvm::orc::rt::CallMainProxy;
-using llvm::orc::rt::CallVoidVoidProxy;
+namespace sps = llvm::orc::sps;
+using llvm::orc::CallInt32Int32Proxy;
+using llvm::orc::CallInt32VoidProxy;
+using llvm::orc::CallMainProxy;
+using llvm::orc::CallVoidVoidProxy;
 
 // Test "main" function. Returns argc plus the length of the first element of
 // argv (if argv is non-empty). Does not inspect argv entries beyond the first.
@@ -67,7 +67,7 @@ static CWrapperFunctionBuffer callMainWrapper(const char *ArgData,
 
 // Exercises argv marshaling: an argument vector is serialized, decoded by the
 // wrapper, and the int64_t result is deserialized.
-TEST(SPSProxiesTest, CallMainSyncViaDirectConstruction) {
+TEST(SPSProxySpecTest, CallMainSyncViaDirectConstruction) {
   ExecutionSession ES(cantFail(SelfExecutorProcessControl::Create()));
 
   CallMainProxy CallMain(sps::CallMainProxySpec::dispatch,
@@ -92,7 +92,7 @@ TEST(SPSProxiesTest, CallMainSyncViaDirectConstruction) {
   cantFail(ES.endSession());
 }
 
-TEST(SPSProxiesTest, CallMainAsyncViaCallOperator) {
+TEST(SPSProxySpecTest, CallMainAsyncViaCallOperator) {
   ExecutionSession ES(cantFail(SelfExecutorProcessControl::Create()));
 
   CallMainProxy CallMain(sps::CallMainProxySpec::dispatch,
@@ -128,7 +128,7 @@ static CWrapperFunctionBuffer callVoidVoidWrapper(const char *ArgData,
 
 // Exercises the void-return path (ErrorRetT == Error) and the empty argument
 // pack, through both the synchronous and asynchronous call operators.
-TEST(SPSProxiesTest, VoidVoidSyncAndAsync) {
+TEST(SPSProxySpecTest, VoidVoidSyncAndAsync) {
   ExecutionSession ES(cantFail(SelfExecutorProcessControl::Create()));
 
   CallVoidVoidProxy Call(sps::CallVoidVoidProxySpec::dispatch,
@@ -169,7 +169,7 @@ static CWrapperFunctionBuffer callInt32Int32Wrapper(const char *ArgData,
 
 // Exercises a non-void proxy with an argument (so argument forwarding through
 // the pack is covered).
-TEST(SPSProxiesTest, Int32Int32Sync) {
+TEST(SPSProxySpecTest, Int32Int32Sync) {
   ExecutionSession ES(cantFail(SelfExecutorProcessControl::Create()));
 
   CallInt32Int32Proxy Call(sps::CallInt32Int32ProxySpec::dispatch,
@@ -197,7 +197,7 @@ static CWrapperFunctionBuffer callInt32VoidWrapper(const char *ArgData,
 }
 
 // Exercises a non-void, zero-argument proxy.
-TEST(SPSProxiesTest, Int32VoidSync) {
+TEST(SPSProxySpecTest, Int32VoidSync) {
   ExecutionSession ES(cantFail(SelfExecutorProcessControl::Create()));
 
   CallInt32VoidProxy Call(sps::CallInt32VoidProxySpec::dispatch,
@@ -227,12 +227,12 @@ struct ErrorFnCI {
   static constexpr char Name[] = "test_sps_error_fn";
   using SPSSig = SPSError(bool);
 };
-using ErrorFnProxy = rt::Proxy<Error(bool)>;
+using ErrorFnProxy = Proxy<Error(bool)>;
 using ErrorFnProxySpec = sps::ProxySpec<ErrorFnProxy, ErrorFnCI>;
 
 // Exercises the Error -> Error mapping across the SPS boundary, including a
 // failure reported by the executor-side function itself.
-TEST(SPSProxiesTest, ErrorReturn) {
+TEST(SPSProxySpecTest, ErrorReturn) {
   ExecutionSession ES(cantFail(SelfExecutorProcessControl::Create()));
 
   ErrorFnProxy Call(ErrorFnProxySpec::dispatch,
@@ -263,12 +263,12 @@ struct ExpectedFnCI {
   static constexpr char Name[] = "test_sps_expected_fn";
   using SPSSig = SPSExpected<int32_t>(int32_t);
 };
-using ExpectedFnProxy = rt::Proxy<Expected<int32_t>(int32_t)>;
+using ExpectedFnProxy = Proxy<Expected<int32_t>(int32_t)>;
 using ExpectedFnProxySpec = sps::ProxySpec<ExpectedFnProxy, ExpectedFnCI>;
 
 // Exercises the Expected<T> -> Expected<T> (flattening) mapping across the SPS
 // boundary, for both the value and the executor-reported-error cases.
-TEST(SPSProxiesTest, ExpectedReturn) {
+TEST(SPSProxySpecTest, ExpectedReturn) {
   ExecutionSession ES(cantFail(SelfExecutorProcessControl::Create()));
 
   ExpectedFnProxy Call(ExpectedFnProxySpec::dispatch,
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 c7dd6be414af9..723b65337ba61 100644
--- a/llvm/utils/gn/secondary/llvm/lib/ExecutionEngine/Orc/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/lib/ExecutionEngine/Orc/BUILD.gn
@@ -29,7 +29,10 @@ static_library("Orc") {
     "ELFNixPlatform.cpp",
     "EPCDynamicLibrarySearchGenerator.cpp",
     "EPCGenericDylibManager.cpp",
+    "EPCGenericDylibManagerSPS.cpp",
     "EPCGenericJITLinkMemoryManager.cpp",
+    "EPCGenericJITLinkMemoryManagerSPS.cpp",
+    "EPCGenericMemoryAccessSPS.cpp",
     "EPCGenericRTDyldMemoryManager.cpp",
     "EPCIndirectionUtils.cpp",
     "ExecutionUtils.cpp",
diff --git a/llvm/utils/gn/secondary/llvm/unittests/ExecutionEngine/Orc/BUILD.gn b/llvm/utils/gn/secondary/llvm/unittests/ExecutionEngine/Orc/BUILD.gn
index b6a67328e00f9..dfbf74b3cd1a9 100644
--- a/llvm/utils/gn/secondary/llvm/unittests/ExecutionEngine/Orc/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/unittests/ExecutionEngine/Orc/BUILD.gn
@@ -44,7 +44,7 @@ unittest("OrcJITTests") {
     "RTDyldObjectLinkingLayerTest.cpp",
     "ReOptimizeLayerTest.cpp",
     "ResourceTrackerTest.cpp",
-    "SPSProxiesTest.cpp",
+    "SPSProxySpecTest.cpp",
     "SharedMemoryMapperTest.cpp",
     "SimpleExecutorMemoryManagerTest.cpp",
     "SimplePackedSerializationTest.cpp",



More information about the llvm-commits mailing list