[llvm] [orc-rt] Express CI symbols as C-level names (PR #222564)

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 10 02:33:39 PDT 2026


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

Controller-interface wrapper functions are now declared extern "C", exported, and registered under their C-level names, so that they resolve identically whether looked up through the bootstrap symbol map or via dlsym.

In addition to removing the inconsistency between the symbol-table and dlsym names, making CI functions public declarations allows unit tests to call CI wrappers directly (rather than having to resigster them and then look them up in a symbol table).

ORC_RT_SPS_WRAPPER and ORC_RT_SPS_ALLOC_ACTION each split into _DECL and _IMPL forms sharing a _SIG macro, giving the wrappers extern "C" linkage and an ORC_RT_C_EXPORT annotation.

SimpleSymbolTable::addUnique now takes SymbolNameSpec names and mangles them, with a second overload for merging one table into another.

>From 2240fee0a4d9bdd1982b131d2fffd94e411c8f69 Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at apple.com>
Date: Wed, 9 Sep 2026 14:12:45 +1000
Subject: [PATCH] [orc-rt] Express CI symbols as C-level names

Controller-interface wrapper functions are now declared extern "C",
exported, and registered under their C-level names, so that they resolve
identically whether looked up through the bootstrap symbol map or via
dlsym.

In addition to removing the inconsistency between the symbol-table and
dlsym names, making CI functions public declarations allows unit tests
to call CI wrappers directly (rather than having to resigster them and
then look them up in a symbol table).

ORC_RT_SPS_WRAPPER and ORC_RT_SPS_ALLOC_ACTION each split into _DECL and
_IMPL forms sharing a _SIG macro, giving the wrappers extern "C" linkage
and an ORC_RT_C_EXPORT annotation.

SimpleSymbolTable::addUnique now takes SymbolNameSpec names and mangles
them, with a second overload for merging one table into another.
---
 .../orc-rt/bedrock/SimpleSymbolTable.h        |  94 +++++++++++-----
 orc-rt/include/orc-rt/bedrock/sps/CallSPSCI.h |   4 +
 .../orc-rt/bedrock/sps/GDBJITRegistrarSPSCI.h |   4 +
 .../orc-rt/bedrock/sps/MemoryAccessSPSCI.h    |  15 +++
 .../bedrock/sps/NativeDylibManagerSPSCI.h     |   4 +
 .../bedrock/sps/SimpleNativeMemoryMapSPSCI.h  |   7 ++
 .../StandaloneMachOUnwindInfoRegistrarSPSCI.h |   7 ++
 .../orc-rt/support/sps/SPSAllocAction.h       |  25 +++--
 .../orc-rt/support/sps/SPSWrapperFunction.h   |  31 +++++-
 orc-rt/lib/bedrock/BootstrapInfo.cpp          |   5 +-
 orc-rt/lib/bedrock/NativeDylibManager.cpp     |   7 +-
 orc-rt/lib/bedrock/SimpleNativeMemoryMap.cpp  |   7 +-
 orc-rt/lib/bedrock/sps/CallSPSCI.cpp          |  16 +--
 .../lib/bedrock/sps/GDBJITRegistrarSPSCI.cpp  |  15 ++-
 orc-rt/lib/bedrock/sps/MemoryAccessSPSCI.cpp  | 102 +++++++++---------
 .../bedrock/sps/NativeDylibManagerSPSCI.cpp   |  11 +-
 .../sps/SimpleNativeMemoryMapSPSCI.cpp        |  33 +++---
 ...tandaloneMachOUnwindInfoRegistrarSPSCI.cpp |  11 +-
 .../test/unit/bedrock/BootstrapInfoTest.cpp   |  26 ++---
 orc-rt/test/unit/bedrock/SessionTest.cpp      |   7 +-
 .../unit/bedrock/SimpleSymbolTableTest.cpp    |  76 +++++++------
 .../test/unit/bedrock/sps/CallSPSCITest.cpp   |  29 ++---
 .../bedrock/sps/MemoryAccessSPSCITest.cpp     |  93 ++++++++--------
 .../sps/NativeDylibManagerSPSCITest.cpp       |  17 ++-
 .../sps/SimpleNativeMemoryMapSPSCITest.cpp    |  29 ++---
 .../unit/bedrock/sps/SimpleRemoteCATest.cpp   |   4 +-
 .../unit/support/sps/SPSAllocActionTest.cpp   |   4 +-
 .../support/sps/SPSWrapperFunctionTest.cpp    |   4 +-
 28 files changed, 403 insertions(+), 284 deletions(-)

diff --git a/orc-rt/include/orc-rt/bedrock/SimpleSymbolTable.h b/orc-rt/include/orc-rt/bedrock/SimpleSymbolTable.h
index c18cdb66abf8ff..55bfd0745f9432 100644
--- a/orc-rt/include/orc-rt/bedrock/SimpleSymbolTable.h
+++ b/orc-rt/include/orc-rt/bedrock/SimpleSymbolTable.h
@@ -14,18 +14,27 @@
 #define ORC_RT_BEDROCK_SIMPLESYMBOLTABLE_H
 
 #include "orc-rt/support/Error.h"
+#include "orc-rt/support/Mangling.h"
 #include "orc-rt/support/move_only_function.h"
+
+#include <algorithm>
 #include <string>
 #include <string_view>
 #include <unordered_map>
 #include <vector>
 
-#define ORC_RT_SYMTAB_PAIR(sym) {{#sym}, reinterpret_cast<const void *>(&sym)}
+/// Builds a (name, address) pair for a symbol, taking its C-level name from the
+/// identifier itself. For use in the interface arrays passed to addUnique.
+#define ORC_RT_SYMTAB_C_PAIR(sym)                                              \
+  {SymbolNameSpec::c(#sym), reinterpret_cast<const void *>(&sym)}
 
 namespace orc_rt {
 
-/// A simple string-to-pointer symbol table. Symbols are added via
-/// addSymbolsUnique, which rejects duplicates with an error.
+/// A simple symbol table mapping linker-level names to addresses.
+///
+/// Entries are added via addUnique. Keys are always linker-level names: names
+/// given as SymbolNameSpecs are mangled on the way in, and count() and at()
+/// mangle their argument the same way.
 class SimpleSymbolTable {
 public:
   using SymbolTable = std::unordered_map<std::string, const void *>;
@@ -38,43 +47,72 @@ class SimpleSymbolTable {
   iterator begin() const noexcept { return Symbols.begin(); }
   iterator end() const noexcept { return Symbols.end(); }
 
-  template <typename KeyT> decltype(auto) count(KeyT &&K) const {
-    return Symbols.count(std::forward<KeyT>(K));
+  /// Returns 1 if NameSpec's mangled name is in the table, 0 otherwise.
+  size_t count(const SymbolNameSpec &NameSpec) const {
+    return Symbols.count(mangledCopy(NameSpec));
   }
 
-  template <typename KeyT> decltype(auto) at(KeyT &&K) const {
-    return Symbols.at(std::forward<KeyT>(K));
+  /// Returns the address registered for NameSpec's mangled name, which must be
+  /// present in the table.
+  const void *at(const SymbolNameSpec &NameSpec) const {
+    auto MangledName = mangledCopy(NameSpec);
+    assert(Symbols.count(MangledName) && "Name not present");
+    return Symbols.at(MangledName);
   }
 
-  /// Adds symbol/address pairs from NewSymbols, first checking that all
-  /// symbols in NewSymbols are unique (i.e. not previously defined).
+  /// Adds (name, address) pairs from NewSymbols, mangling each name according
+  /// to its SymbolNameKind. Redundant definitions where the (name, address)
+  /// pair matches an existing table entry are allowed. Duplicate symbol names
+  /// with different addresses will return an error, and addUnique will leave
+  /// the table unchanged.
   ///
   /// NewSymbols must not contain any internal duplicates.
   template <typename SymbolRangeT> Error addUnique(SymbolRangeT &&NewSymbols) {
+    // Generate the mangled version of the NewSymbols map.
+    std::vector<std::pair<std::string, const void *>> NewMangledSymbols;
+    NewMangledSymbols.reserve(std::size(NewSymbols));
+    for (auto &[NameSpec, Addr] : NewSymbols)
+      NewMangledSymbols.emplace_back(mangledCopy(NameSpec), Addr);
+
+    // Check for duplicate definitions whose addresses disagree.
+    std::vector<std::string_view> IncompatibleDefs;
+    for (auto &[MangledName, Addr] : NewMangledSymbols) {
+      auto I = Symbols.find(MangledName);
+      if (I != Symbols.end() && I->second != Addr)
+        IncompatibleDefs.push_back(MangledName);
+    }
 
-    // First check for incompatible duplicate definitions (duplicates are
-    // only permitted if they resolve to the same address). Error out if any
-    // incompatible defs are found.
-    {
-      std::vector<std::string_view> IncompatibleDefs;
-      for (auto &[Name, Addr] : NewSymbols) {
-        auto I = Symbols.find(Name);
-        if (I == Symbols.end() || I->second == Addr)
-          continue;
-        if (Symbols.count(Name))
-          IncompatibleDefs.push_back(Name);
-      }
-      if (!IncompatibleDefs.empty())
-        return makeIncompatibleDefsError(std::move(IncompatibleDefs));
+    // If any incompatible definitions exist then return with an error.
+    if (!IncompatibleDefs.empty())
+      return makeIncompatibleDefsError(std::move(IncompatibleDefs));
+
+    // Otherwise update the table.
+    for (auto &[MangledName, Addr] : NewMangledSymbols) {
+      [[maybe_unused]] auto [I, Added] =
+          Symbols.insert({std::move(MangledName), Addr});
+      assert((Added || I->second == Addr) &&
+             "NewSymbols contains internal duplicates");
     }
 
-    // No duplicates. Add entries.
-    for (auto &P : NewSymbols) {
-      [[maybe_unused]] auto [I, Added] = Symbols.insert(P);
-      assert((Added || I->second == P.second) &&
-             "NewSymbols contains incompatible definitions");
+    return Error::success();
+  }
+
+  /// Adds all entries from Other. Duplicate handling matches addUnique above:
+  /// on error this table is left unchanged. Consumes Other.
+  Error addUnique(SimpleSymbolTable &&Other) {
+    std::vector<std::string_view> IncompatibleDefs;
+    for (auto &[Name, Addr] : Other.Symbols) {
+      auto I = Symbols.find(Name);
+      if (I != Symbols.end() && I->second != Addr)
+        IncompatibleDefs.push_back(Name);
     }
 
+    if (!IncompatibleDefs.empty())
+      return makeIncompatibleDefsError(std::move(IncompatibleDefs));
+
+    // Splices nodes across, so no keys are copied.
+    Symbols.merge(Other.Symbols);
+
     return Error::success();
   }
 
diff --git a/orc-rt/include/orc-rt/bedrock/sps/CallSPSCI.h b/orc-rt/include/orc-rt/bedrock/sps/CallSPSCI.h
index eee9535aa21a65..6987cb51cca39d 100644
--- a/orc-rt/include/orc-rt/bedrock/sps/CallSPSCI.h
+++ b/orc-rt/include/orc-rt/bedrock/sps/CallSPSCI.h
@@ -14,6 +14,10 @@
 #define ORC_RT_BEDROCK_SPS_CALLSPSCI_H
 
 #include "orc-rt/bedrock/SimpleSymbolTable.h"
+#include "orc-rt/support/sps/SPSWrapperFunction.h"
+
+ORC_RT_SPS_WRAPPER_DECL(orc_rt_ci_sps_call_void_void)
+ORC_RT_SPS_WRAPPER_DECL(orc_rt_ci_sps_call_main)
 
 namespace orc_rt::sps_ci {
 
diff --git a/orc-rt/include/orc-rt/bedrock/sps/GDBJITRegistrarSPSCI.h b/orc-rt/include/orc-rt/bedrock/sps/GDBJITRegistrarSPSCI.h
index 6653cc65473a94..1cc3f18a9f6dda 100644
--- a/orc-rt/include/orc-rt/bedrock/sps/GDBJITRegistrarSPSCI.h
+++ b/orc-rt/include/orc-rt/bedrock/sps/GDBJITRegistrarSPSCI.h
@@ -14,6 +14,10 @@
 #define ORC_RT_BEDROCK_SPS_GDBJITREGISTRARSPSCI_H
 
 #include "orc-rt/bedrock/SimpleSymbolTable.h"
+#include "orc-rt/support/sps/SPSAllocAction.h"
+
+ORC_RT_SPS_ALLOC_ACTION_DECL(orc_rt_ci_aa_sps_GDBJITRegistrar_register)
+ORC_RT_SPS_ALLOC_ACTION_DECL(orc_rt_ci_aa_sps_GDBJITRegistrar_deregister)
 
 namespace orc_rt::sps_ci {
 
diff --git a/orc-rt/include/orc-rt/bedrock/sps/MemoryAccessSPSCI.h b/orc-rt/include/orc-rt/bedrock/sps/MemoryAccessSPSCI.h
index 36db6745242567..32690e461c1c14 100644
--- a/orc-rt/include/orc-rt/bedrock/sps/MemoryAccessSPSCI.h
+++ b/orc-rt/include/orc-rt/bedrock/sps/MemoryAccessSPSCI.h
@@ -14,6 +14,21 @@
 #define ORC_RT_BEDROCK_SPS_MEMORYACCESSSPSCI_H
 
 #include "orc-rt/bedrock/SimpleSymbolTable.h"
+#include "orc-rt/support/sps/SPSWrapperFunction.h"
+
+ORC_RT_SPS_WRAPPER_DECL(orc_rt_ci_sps_mem_write_uint8s)
+ORC_RT_SPS_WRAPPER_DECL(orc_rt_ci_sps_mem_write_uint16s)
+ORC_RT_SPS_WRAPPER_DECL(orc_rt_ci_sps_mem_write_uint32s)
+ORC_RT_SPS_WRAPPER_DECL(orc_rt_ci_sps_mem_write_uint64s)
+ORC_RT_SPS_WRAPPER_DECL(orc_rt_ci_sps_mem_write_pointers)
+ORC_RT_SPS_WRAPPER_DECL(orc_rt_ci_sps_mem_write_buffers)
+ORC_RT_SPS_WRAPPER_DECL(orc_rt_ci_sps_mem_read_uint8s)
+ORC_RT_SPS_WRAPPER_DECL(orc_rt_ci_sps_mem_read_uint16s)
+ORC_RT_SPS_WRAPPER_DECL(orc_rt_ci_sps_mem_read_uint32s)
+ORC_RT_SPS_WRAPPER_DECL(orc_rt_ci_sps_mem_read_uint64s)
+ORC_RT_SPS_WRAPPER_DECL(orc_rt_ci_sps_mem_read_pointers)
+ORC_RT_SPS_WRAPPER_DECL(orc_rt_ci_sps_mem_read_buffers)
+ORC_RT_SPS_WRAPPER_DECL(orc_rt_ci_sps_mem_read_strings)
 
 namespace orc_rt::sps_ci {
 
diff --git a/orc-rt/include/orc-rt/bedrock/sps/NativeDylibManagerSPSCI.h b/orc-rt/include/orc-rt/bedrock/sps/NativeDylibManagerSPSCI.h
index a454f7e14d1e99..fde54a43a38e7c 100644
--- a/orc-rt/include/orc-rt/bedrock/sps/NativeDylibManagerSPSCI.h
+++ b/orc-rt/include/orc-rt/bedrock/sps/NativeDylibManagerSPSCI.h
@@ -14,6 +14,10 @@
 #define ORC_RT_BEDROCK_SPS_NATIVEDYLIBMANAGERSPSCI_H
 
 #include "orc-rt/bedrock/SimpleSymbolTable.h"
+#include "orc-rt/support/sps/SPSWrapperFunction.h"
+
+ORC_RT_SPS_WRAPPER_DECL(orc_rt_ci_sps_NativeDylibManager_load)
+ORC_RT_SPS_WRAPPER_DECL(orc_rt_ci_sps_NativeDylibManager_lookup)
 
 namespace orc_rt::sps_ci {
 
diff --git a/orc-rt/include/orc-rt/bedrock/sps/SimpleNativeMemoryMapSPSCI.h b/orc-rt/include/orc-rt/bedrock/sps/SimpleNativeMemoryMapSPSCI.h
index 01c224d144bec5..cbdec5ae6c6ea0 100644
--- a/orc-rt/include/orc-rt/bedrock/sps/SimpleNativeMemoryMapSPSCI.h
+++ b/orc-rt/include/orc-rt/bedrock/sps/SimpleNativeMemoryMapSPSCI.h
@@ -14,6 +14,13 @@
 #define ORC_RT_BEDROCK_SPS_SIMPLENATIVEMEMORYMAPSPSCI_H
 
 #include "orc-rt/bedrock/SimpleSymbolTable.h"
+#include "orc-rt/support/sps/SPSWrapperFunction.h"
+
+ORC_RT_SPS_WRAPPER_DECL(orc_rt_ci_sps_SimpleNativeMemoryMap_reserve)
+ORC_RT_SPS_WRAPPER_DECL(orc_rt_ci_sps_SimpleNativeMemoryMap_releaseMultiple)
+ORC_RT_SPS_WRAPPER_DECL(orc_rt_ci_sps_SimpleNativeMemoryMap_initialize)
+ORC_RT_SPS_WRAPPER_DECL(
+    orc_rt_ci_sps_SimpleNativeMemoryMap_deinitializeMultiple)
 
 namespace orc_rt::sps_ci {
 
diff --git a/orc-rt/include/orc-rt/bedrock/sps/StandaloneMachOUnwindInfoRegistrarSPSCI.h b/orc-rt/include/orc-rt/bedrock/sps/StandaloneMachOUnwindInfoRegistrarSPSCI.h
index 9cf88b2df49757..1552b0ccfb06fc 100644
--- a/orc-rt/include/orc-rt/bedrock/sps/StandaloneMachOUnwindInfoRegistrarSPSCI.h
+++ b/orc-rt/include/orc-rt/bedrock/sps/StandaloneMachOUnwindInfoRegistrarSPSCI.h
@@ -15,6 +15,13 @@
 #define ORC_RT_BEDROCK_SPS_STANDALONEMACHOUNWINDINFOREGISTRARSPSCI_H
 
 #include "orc-rt/bedrock/SimpleSymbolTable.h"
+#include "orc-rt/support/sps/SPSAllocAction.h"
+
+ORC_RT_SPS_ALLOC_ACTION_DECL(
+    orc_rt_ci_aa_sps_MachOUnwindInfoRegistrar_registerSections)
+
+ORC_RT_SPS_ALLOC_ACTION_DECL(
+    orc_rt_ci_aa_sps_MachOUnwindInfoRegistrar_deregisterSections)
 
 namespace orc_rt::sps_ci {
 
diff --git a/orc-rt/include/orc-rt/support/sps/SPSAllocAction.h b/orc-rt/include/orc-rt/support/sps/SPSAllocAction.h
index a8d973fb695e24..c4f8955340dffb 100644
--- a/orc-rt/include/orc-rt/support/sps/SPSAllocAction.h
+++ b/orc-rt/include/orc-rt/support/sps/SPSAllocAction.h
@@ -19,19 +19,30 @@
 #include "orc-rt/support/sps/SPSWrapperFunctionBuffer.h"
 #include "orc-rt/support/sps/SimplePackedSerialization.h"
 
+// The signature shared by ORC_RT_SPS_ALLOC_ACTION_DECL and _IMPL. Writing it
+// once keeps the declaration and definition from drifting apart.
+#define ORC_RT_SPS_ALLOC_ACTION_SIG(Name)                                      \
+  orc_rt_WrapperFunctionBuffer Name(const char *ArgData, size_t ArgSize)
+
+/// Declare an allocation-action wrapper function. The name has C linkage, so it
+/// is the same function regardless of which namespace the declaration appears
+/// in.
+#define ORC_RT_SPS_ALLOC_ACTION_DECL(Name)                                     \
+  extern "C" ORC_RT_C_EXPORT ORC_RT_SPS_ALLOC_ACTION_SIG(Name);
+
 /// Define an allocation-action wrapper function with the given Name that
 /// uses SPS to deserialize its arguments and dispatches to Handle.
 ///
-/// SPSArgs is a parenthesized comma-separated list of SPS argument types
-/// (the parens are stripped by ORC_RT_DEPAREN before being expanded into
-/// the SPSAllocActionFunction template instantiation):
+/// SPSArgs is a parenthesized comma-separated list of SPS argument types:
 ///
 ///     static Error checkEq(int32_t X, int32_t Y);
-///     ORC_RT_SPS_ALLOC_ACTION(check_eq_action, (int32_t, int32_t), checkEq)
+///     ORC_RT_SPS_ALLOC_ACTION_IMPL(check_eq_action,
+///                                  (int32_t, int32_t),
+///                                  checkEq)
 ///
-#define ORC_RT_SPS_ALLOC_ACTION(Name, SPSArgs, Handle)                         \
-  static orc_rt_WrapperFunctionBuffer Name(const char *ArgData,                \
-                                           size_t ArgSize) {                   \
+#define ORC_RT_SPS_ALLOC_ACTION_IMPL(Name, SPSArgs, Handle)                    \
+  ORC_RT_SPS_ALLOC_ACTION_DECL(Name)                                           \
+  extern "C" ORC_RT_SPS_ALLOC_ACTION_SIG(Name) {                               \
     return orc_rt::SPSAllocActionFunction<ORC_RT_DEPAREN(SPSArgs)>::handle(    \
                ArgData, ArgSize, Handle)                                       \
         .release();                                                            \
diff --git a/orc-rt/include/orc-rt/support/sps/SPSWrapperFunction.h b/orc-rt/include/orc-rt/support/sps/SPSWrapperFunction.h
index c2f92341090349..03ec8235dd8881 100644
--- a/orc-rt/include/orc-rt/support/sps/SPSWrapperFunction.h
+++ b/orc-rt/include/orc-rt/support/sps/SPSWrapperFunction.h
@@ -18,9 +18,34 @@
 #include "orc-rt/support/WrapperFunction.h"
 #include "orc-rt/support/sps/SimplePackedSerialization.h"
 
-#define ORC_RT_SPS_WRAPPER(Name, SPSSig, Handle)                               \
-  static void Name(orc_rt_SessionRef S, orc_rt_WrapperFunctionBuffer ArgBytes, \
-                   orc_rt_WrapperFunctionReturn Return, uint64_t CallId) {     \
+// The signature shared by ORC_RT_SPS_WRAPPER_DECL and _IMPL. Writing it once
+// keeps the declaration and definition from drifting apart.
+#define ORC_RT_SPS_WRAPPER_SIG(Name)                                           \
+  void Name(orc_rt_SessionRef S, orc_rt_WrapperFunctionBuffer ArgBytes,        \
+            orc_rt_WrapperFunctionReturn Return, uint64_t CallId)
+
+/// Declare an SPS wrapper function. The name has C linkage, so it is the same
+/// function regardless of which namespace the declaration appears in.
+#define ORC_RT_SPS_WRAPPER_DECL(Name)                                          \
+  extern "C" ORC_RT_C_EXPORT ORC_RT_SPS_WRAPPER_SIG(Name);
+
+/// Define an SPS wrapper function with the given Name that uses SPS to
+/// deserialize its arguments, dispatches to Handle, and serializes the result
+/// that Handle passes to its Return continuation.
+///
+/// SPSSig is the SPS function signature to serialize against:
+///
+///     void call_main(move_only_function<void(int64_t)> Return, MainFn Main,
+///                    std::vector<std::string> Args);
+///     ORC_RT_SPS_WRAPPER_IMPL(
+///         orc_rt_ci_sps_call_main,
+///         int64_t(SPSExecutorAddr, SPSSequence<SPSString>),
+///         call_main)
+///
+/// Also emits the declaration, so the definition is checked against it.
+#define ORC_RT_SPS_WRAPPER_IMPL(Name, SPSSig, Handle)                          \
+  ORC_RT_SPS_WRAPPER_DECL(Name)                                                \
+  extern "C" ORC_RT_SPS_WRAPPER_SIG(Name) {                                    \
     orc_rt::SPSWrapperFunction<SPSSig>::handle(S, ArgBytes, Return, CallId,    \
                                                Handle);                        \
   }
diff --git a/orc-rt/lib/bedrock/BootstrapInfo.cpp b/orc-rt/lib/bedrock/BootstrapInfo.cpp
index 0a32c1bd59d1f8..c65ca3cf075415 100644
--- a/orc-rt/lib/bedrock/BootstrapInfo.cpp
+++ b/orc-rt/lib/bedrock/BootstrapInfo.cpp
@@ -29,8 +29,9 @@ BootstrapInfo::CreateDefault(Session &S,
 
   SimpleSymbolTable InitialSymbols;
   // Add session symbol.
-  std::pair<const char *, const void *> SessionSymbol[] = {
-      {"orc_rt_Session_Instance", static_cast<const void *>(&S)}};
+  std::pair<SymbolNameSpec, const void *> SessionSymbol[] = {
+      {SymbolNameSpec::c("orc_rt_Session_Instance"),
+       static_cast<const void *>(&S)}};
   if (auto Err = InitialSymbols.addUnique(SessionSymbol))
     return std::move(Err);
 
diff --git a/orc-rt/lib/bedrock/NativeDylibManager.cpp b/orc-rt/lib/bedrock/NativeDylibManager.cpp
index 441942a77f70b6..d26f92e24851ec 100644
--- a/orc-rt/lib/bedrock/NativeDylibManager.cpp
+++ b/orc-rt/lib/bedrock/NativeDylibManager.cpp
@@ -26,12 +26,13 @@ NativeDylibManager::Create(Session &S, SimpleSymbolTable &ST,
   SimpleSymbolTable NDMST;
   if (auto Err = AddInterface(NDMST))
     return Err;
-  std::pair<const char *, const void *> InstanceSym[] = {
-      {InstanceName, static_cast<const void *>(Instance.get())}};
+  std::pair<SymbolNameSpec, const void *> InstanceSym[] = {
+      {SymbolNameSpec::c(InstanceName),
+       static_cast<const void *>(Instance.get())}};
   if (auto Err = NDMST.addUnique(InstanceSym))
     return std::move(Err);
 
-  if (auto Err = ST.addUnique(NDMST))
+  if (auto Err = ST.addUnique(std::move(NDMST)))
     return std::move(Err);
 
   return std::move(Instance);
diff --git a/orc-rt/lib/bedrock/SimpleNativeMemoryMap.cpp b/orc-rt/lib/bedrock/SimpleNativeMemoryMap.cpp
index a547e2d80c47e2..afefdc674f2b0a 100644
--- a/orc-rt/lib/bedrock/SimpleNativeMemoryMap.cpp
+++ b/orc-rt/lib/bedrock/SimpleNativeMemoryMap.cpp
@@ -32,12 +32,13 @@ SimpleNativeMemoryMap::Create(Session &S, SimpleSymbolTable &ST,
   SimpleSymbolTable SNMMST;
   if (auto Err = AddInterface(SNMMST))
     return Err;
-  std::pair<const char *, const void *> InstanceSym[] = {
-      {InstanceName, static_cast<const void *>(Instance.get())}};
+  std::pair<SymbolNameSpec, const void *> InstanceSym[] = {
+      {SymbolNameSpec::c(InstanceName),
+       static_cast<const void *>(Instance.get())}};
   if (auto Err = SNMMST.addUnique(InstanceSym))
     return std::move(Err);
 
-  if (auto Err = ST.addUnique(SNMMST))
+  if (auto Err = ST.addUnique(std::move(SNMMST)))
     return std::move(Err);
 
   return std::move(Instance);
diff --git a/orc-rt/lib/bedrock/sps/CallSPSCI.cpp b/orc-rt/lib/bedrock/sps/CallSPSCI.cpp
index 53b1e27337a21a..e049b32d33f734 100644
--- a/orc-rt/lib/bedrock/sps/CallSPSCI.cpp
+++ b/orc-rt/lib/bedrock/sps/CallSPSCI.cpp
@@ -12,7 +12,6 @@
 
 #include "orc-rt/bedrock/sps/CallSPSCI.h"
 #include "orc-rt/support/move_only_function.h"
-#include "orc-rt/support/sps/SPSWrapperFunction.h"
 
 #include <string>
 #include <vector>
@@ -26,8 +25,8 @@ void call_void_void(move_only_function<void()> Return, VoidVoidFn Fn) {
   Return();
 }
 
-ORC_RT_SPS_WRAPPER(orc_rt_ci_sps_call_void_void, void(SPSExecutorAddr),
-                   call_void_void);
+ORC_RT_SPS_WRAPPER_IMPL(orc_rt_ci_sps_call_void_void, void(SPSExecutorAddr),
+                        call_void_void)
 
 using MainFn = int(int argc, char *argv[]);
 
@@ -49,12 +48,13 @@ void call_main(move_only_function<void(int64_t)> Return, MainFn Main,
   Return(Main(Args.size(), ArgV.data()));
 }
 
-ORC_RT_SPS_WRAPPER(orc_rt_ci_sps_call_main,
-                   int64_t(SPSExecutorAddr, SPSSequence<SPSString>), call_main);
+ORC_RT_SPS_WRAPPER_IMPL(orc_rt_ci_sps_call_main,
+                        int64_t(SPSExecutorAddr, SPSSequence<SPSString>),
+                        call_main)
 
-static std::pair<const char *, const void *> orc_rt_ci_sps_call_interface[] = {
-    ORC_RT_SYMTAB_PAIR(orc_rt_ci_sps_call_void_void),
-    ORC_RT_SYMTAB_PAIR(orc_rt_ci_sps_call_main)};
+static std::pair<SymbolNameSpec, const void *> orc_rt_ci_sps_call_interface[] =
+    {ORC_RT_SYMTAB_C_PAIR(orc_rt_ci_sps_call_void_void),
+     ORC_RT_SYMTAB_C_PAIR(orc_rt_ci_sps_call_main)};
 
 Error addCall(SimpleSymbolTable &ST) {
   return ST.addUnique(orc_rt_ci_sps_call_interface);
diff --git a/orc-rt/lib/bedrock/sps/GDBJITRegistrarSPSCI.cpp b/orc-rt/lib/bedrock/sps/GDBJITRegistrarSPSCI.cpp
index cbfc30330bdaa7..7cb676138c495f 100644
--- a/orc-rt/lib/bedrock/sps/GDBJITRegistrarSPSCI.cpp
+++ b/orc-rt/lib/bedrock/sps/GDBJITRegistrarSPSCI.cpp
@@ -11,7 +11,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "orc-rt/bedrock/sps/GDBJITRegistrarSPSCI.h"
-#include "orc-rt/support/sps/SPSAllocAction.h"
 
 #include "orc-rt-internal/bedrock/GDBJITRegistrar.h"
 
@@ -19,16 +18,16 @@ using namespace orc_rt;
 
 namespace orc_rt::sps_ci {
 
-ORC_RT_SPS_ALLOC_ACTION(orc_rt_ci_aa_sps_GDBJITRegistrar_register,
-                        (SPSExecutorAddrRange), &gdb_jit::registerObject)
+ORC_RT_SPS_ALLOC_ACTION_IMPL(orc_rt_ci_aa_sps_GDBJITRegistrar_register,
+                             (SPSExecutorAddrRange), &gdb_jit::registerObject)
 
-ORC_RT_SPS_ALLOC_ACTION(orc_rt_ci_aa_sps_GDBJITRegistrar_deregister,
-                        (SPSExecutorAddrRange), &gdb_jit::deregisterObject)
+ORC_RT_SPS_ALLOC_ACTION_IMPL(orc_rt_ci_aa_sps_GDBJITRegistrar_deregister,
+                             (SPSExecutorAddrRange), &gdb_jit::deregisterObject)
 
-static std::pair<const char *, const void *>
+static std::pair<SymbolNameSpec, const void *>
     orc_rt_ci_GDBJITRegistrar_sps_interface[] = {
-        ORC_RT_SYMTAB_PAIR(orc_rt_ci_aa_sps_GDBJITRegistrar_register),
-        ORC_RT_SYMTAB_PAIR(orc_rt_ci_aa_sps_GDBJITRegistrar_deregister)};
+        ORC_RT_SYMTAB_C_PAIR(orc_rt_ci_aa_sps_GDBJITRegistrar_register),
+        ORC_RT_SYMTAB_C_PAIR(orc_rt_ci_aa_sps_GDBJITRegistrar_deregister)};
 
 Error addGDBJITRegistrar(SimpleSymbolTable &ST) {
   return ST.addUnique(orc_rt_ci_GDBJITRegistrar_sps_interface);
diff --git a/orc-rt/lib/bedrock/sps/MemoryAccessSPSCI.cpp b/orc-rt/lib/bedrock/sps/MemoryAccessSPSCI.cpp
index 4911f128a341c8..f62214f14f353f 100644
--- a/orc-rt/lib/bedrock/sps/MemoryAccessSPSCI.cpp
+++ b/orc-rt/lib/bedrock/sps/MemoryAccessSPSCI.cpp
@@ -12,7 +12,6 @@
 
 #include "orc-rt/bedrock/sps/MemoryAccessSPSCI.h"
 #include "orc-rt/support/move_only_function.h"
-#include "orc-rt/support/sps/SPSWrapperFunction.h"
 
 #include <cstring>
 #include <vector>
@@ -76,76 +75,77 @@ void readStrings(
 } // namespace
 namespace orc_rt::sps_ci {
 
-ORC_RT_SPS_WRAPPER(orc_rt_ci_sps_mem_write_uint8s,
-                   void(SPSSequence<SPSTuple<SPSExecutorAddr, uint8_t>>),
-                   writePrimitives<uint8_t>);
+ORC_RT_SPS_WRAPPER_IMPL(orc_rt_ci_sps_mem_write_uint8s,
+                        void(SPSSequence<SPSTuple<SPSExecutorAddr, uint8_t>>),
+                        writePrimitives<uint8_t>);
 
-ORC_RT_SPS_WRAPPER(orc_rt_ci_sps_mem_write_uint16s,
-                   void(SPSSequence<SPSTuple<SPSExecutorAddr, uint16_t>>),
-                   writePrimitives<uint16_t>);
+ORC_RT_SPS_WRAPPER_IMPL(orc_rt_ci_sps_mem_write_uint16s,
+                        void(SPSSequence<SPSTuple<SPSExecutorAddr, uint16_t>>),
+                        writePrimitives<uint16_t>);
 
-ORC_RT_SPS_WRAPPER(orc_rt_ci_sps_mem_write_uint32s,
-                   void(SPSSequence<SPSTuple<SPSExecutorAddr, uint32_t>>),
-                   writePrimitives<uint32_t>);
+ORC_RT_SPS_WRAPPER_IMPL(orc_rt_ci_sps_mem_write_uint32s,
+                        void(SPSSequence<SPSTuple<SPSExecutorAddr, uint32_t>>),
+                        writePrimitives<uint32_t>);
 
-ORC_RT_SPS_WRAPPER(orc_rt_ci_sps_mem_write_uint64s,
-                   void(SPSSequence<SPSTuple<SPSExecutorAddr, uint64_t>>),
-                   writePrimitives<uint64_t>);
+ORC_RT_SPS_WRAPPER_IMPL(orc_rt_ci_sps_mem_write_uint64s,
+                        void(SPSSequence<SPSTuple<SPSExecutorAddr, uint64_t>>),
+                        writePrimitives<uint64_t>);
 
-ORC_RT_SPS_WRAPPER(
+ORC_RT_SPS_WRAPPER_IMPL(
     orc_rt_ci_sps_mem_write_pointers,
     void(SPSSequence<SPSTuple<SPSExecutorAddr, SPSExecutorAddr>>),
     writePrimitives<void *>);
 
-ORC_RT_SPS_WRAPPER(
+ORC_RT_SPS_WRAPPER_IMPL(
     orc_rt_ci_sps_mem_write_buffers,
     void(SPSSequence<SPSTuple<SPSExecutorAddr, SPSSequence<char>>>),
     writeBuffers);
 
-ORC_RT_SPS_WRAPPER(orc_rt_ci_sps_mem_read_uint8s,
-                   SPSSequence<uint8_t>(SPSSequence<SPSExecutorAddr>),
-                   readPrimitives<uint8_t>);
+ORC_RT_SPS_WRAPPER_IMPL(orc_rt_ci_sps_mem_read_uint8s,
+                        SPSSequence<uint8_t>(SPSSequence<SPSExecutorAddr>),
+                        readPrimitives<uint8_t>);
 
-ORC_RT_SPS_WRAPPER(orc_rt_ci_sps_mem_read_uint16s,
-                   SPSSequence<uint16_t>(SPSSequence<SPSExecutorAddr>),
-                   readPrimitives<uint16_t>);
+ORC_RT_SPS_WRAPPER_IMPL(orc_rt_ci_sps_mem_read_uint16s,
+                        SPSSequence<uint16_t>(SPSSequence<SPSExecutorAddr>),
+                        readPrimitives<uint16_t>);
 
-ORC_RT_SPS_WRAPPER(orc_rt_ci_sps_mem_read_uint32s,
-                   SPSSequence<uint32_t>(SPSSequence<SPSExecutorAddr>),
-                   readPrimitives<uint32_t>);
+ORC_RT_SPS_WRAPPER_IMPL(orc_rt_ci_sps_mem_read_uint32s,
+                        SPSSequence<uint32_t>(SPSSequence<SPSExecutorAddr>),
+                        readPrimitives<uint32_t>);
 
-ORC_RT_SPS_WRAPPER(orc_rt_ci_sps_mem_read_uint64s,
-                   SPSSequence<uint64_t>(SPSSequence<SPSExecutorAddr>),
-                   readPrimitives<uint64_t>);
+ORC_RT_SPS_WRAPPER_IMPL(orc_rt_ci_sps_mem_read_uint64s,
+                        SPSSequence<uint64_t>(SPSSequence<SPSExecutorAddr>),
+                        readPrimitives<uint64_t>);
 
-ORC_RT_SPS_WRAPPER(orc_rt_ci_sps_mem_read_pointers,
-                   SPSSequence<SPSExecutorAddr>(SPSSequence<SPSExecutorAddr>),
-                   readPrimitives<void *>);
+ORC_RT_SPS_WRAPPER_IMPL(
+    orc_rt_ci_sps_mem_read_pointers,
+    SPSSequence<SPSExecutorAddr>(SPSSequence<SPSExecutorAddr>),
+    readPrimitives<void *>);
 
-ORC_RT_SPS_WRAPPER(orc_rt_ci_sps_mem_read_buffers,
-                   SPSSequence<SPSSequence<char>>(
-                       SPSSequence<SPSTuple<SPSExecutorAddr, uint64_t>>),
-                   readBuffers);
+ORC_RT_SPS_WRAPPER_IMPL(orc_rt_ci_sps_mem_read_buffers,
+                        SPSSequence<SPSSequence<char>>(
+                            SPSSequence<SPSTuple<SPSExecutorAddr, uint64_t>>),
+                        readBuffers);
 
-ORC_RT_SPS_WRAPPER(orc_rt_ci_sps_mem_read_strings,
-                   SPSSequence<SPSString>(SPSSequence<SPSExecutorAddr>),
-                   readStrings);
+ORC_RT_SPS_WRAPPER_IMPL(orc_rt_ci_sps_mem_read_strings,
+                        SPSSequence<SPSString>(SPSSequence<SPSExecutorAddr>),
+                        readStrings);
 
-static std::pair<const char *, const void *>
+static std::pair<SymbolNameSpec, const void *>
     orc_rt_ci_MemoryAccess_sps_interface[] = {
-        ORC_RT_SYMTAB_PAIR(orc_rt_ci_sps_mem_write_uint8s),
-        ORC_RT_SYMTAB_PAIR(orc_rt_ci_sps_mem_write_uint16s),
-        ORC_RT_SYMTAB_PAIR(orc_rt_ci_sps_mem_write_uint32s),
-        ORC_RT_SYMTAB_PAIR(orc_rt_ci_sps_mem_write_uint64s),
-        ORC_RT_SYMTAB_PAIR(orc_rt_ci_sps_mem_write_pointers),
-        ORC_RT_SYMTAB_PAIR(orc_rt_ci_sps_mem_write_buffers),
-        ORC_RT_SYMTAB_PAIR(orc_rt_ci_sps_mem_read_uint8s),
-        ORC_RT_SYMTAB_PAIR(orc_rt_ci_sps_mem_read_uint16s),
-        ORC_RT_SYMTAB_PAIR(orc_rt_ci_sps_mem_read_uint32s),
-        ORC_RT_SYMTAB_PAIR(orc_rt_ci_sps_mem_read_uint64s),
-        ORC_RT_SYMTAB_PAIR(orc_rt_ci_sps_mem_read_pointers),
-        ORC_RT_SYMTAB_PAIR(orc_rt_ci_sps_mem_read_buffers),
-        ORC_RT_SYMTAB_PAIR(orc_rt_ci_sps_mem_read_strings)};
+        ORC_RT_SYMTAB_C_PAIR(orc_rt_ci_sps_mem_write_uint8s),
+        ORC_RT_SYMTAB_C_PAIR(orc_rt_ci_sps_mem_write_uint16s),
+        ORC_RT_SYMTAB_C_PAIR(orc_rt_ci_sps_mem_write_uint32s),
+        ORC_RT_SYMTAB_C_PAIR(orc_rt_ci_sps_mem_write_uint64s),
+        ORC_RT_SYMTAB_C_PAIR(orc_rt_ci_sps_mem_write_pointers),
+        ORC_RT_SYMTAB_C_PAIR(orc_rt_ci_sps_mem_write_buffers),
+        ORC_RT_SYMTAB_C_PAIR(orc_rt_ci_sps_mem_read_uint8s),
+        ORC_RT_SYMTAB_C_PAIR(orc_rt_ci_sps_mem_read_uint16s),
+        ORC_RT_SYMTAB_C_PAIR(orc_rt_ci_sps_mem_read_uint32s),
+        ORC_RT_SYMTAB_C_PAIR(orc_rt_ci_sps_mem_read_uint64s),
+        ORC_RT_SYMTAB_C_PAIR(orc_rt_ci_sps_mem_read_pointers),
+        ORC_RT_SYMTAB_C_PAIR(orc_rt_ci_sps_mem_read_buffers),
+        ORC_RT_SYMTAB_C_PAIR(orc_rt_ci_sps_mem_read_strings)};
 
 Error addMemoryAccess(SimpleSymbolTable &ST) {
   return ST.addUnique(orc_rt_ci_MemoryAccess_sps_interface);
diff --git a/orc-rt/lib/bedrock/sps/NativeDylibManagerSPSCI.cpp b/orc-rt/lib/bedrock/sps/NativeDylibManagerSPSCI.cpp
index 1d319fd1f4cab5..1cf23f2c9f97bf 100644
--- a/orc-rt/lib/bedrock/sps/NativeDylibManagerSPSCI.cpp
+++ b/orc-rt/lib/bedrock/sps/NativeDylibManagerSPSCI.cpp
@@ -12,7 +12,6 @@
 
 #include "orc-rt/bedrock/sps/NativeDylibManagerSPSCI.h"
 #include "orc-rt/bedrock/NativeDylibManager.h"
-#include "orc-rt/support/sps/SPSWrapperFunction.h"
 
 namespace orc_rt {
 
@@ -47,22 +46,22 @@ class SPSSerializationTraits<bool, NativeDylibManager::LookupFlags> {
 
 namespace orc_rt::sps_ci {
 
-ORC_RT_SPS_WRAPPER(
+ORC_RT_SPS_WRAPPER_IMPL(
     orc_rt_ci_sps_NativeDylibManager_load,
     SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, SPSString),
     WrapperFunction::handleWithAsyncMethod(&NativeDylibManager::load))
 
-ORC_RT_SPS_WRAPPER(
+ORC_RT_SPS_WRAPPER_IMPL(
     orc_rt_ci_sps_NativeDylibManager_lookup,
     SPSExpected<SPSSequence<SPSOptional<SPSExecutorAddr>>>(
         SPSExecutorAddr, SPSExecutorAddr,
         SPSSequence<SPSTuple<SPSString, bool>>),
     WrapperFunction::handleWithAsyncMethod(&NativeDylibManager::lookup))
 
-static std::pair<const char *, const void *>
+static std::pair<SymbolNameSpec, const void *>
     orc_rt_ci_NativeDylibManager_sps_interface[] = {
-        ORC_RT_SYMTAB_PAIR(orc_rt_ci_sps_NativeDylibManager_load),
-        ORC_RT_SYMTAB_PAIR(orc_rt_ci_sps_NativeDylibManager_lookup)};
+        ORC_RT_SYMTAB_C_PAIR(orc_rt_ci_sps_NativeDylibManager_load),
+        ORC_RT_SYMTAB_C_PAIR(orc_rt_ci_sps_NativeDylibManager_lookup)};
 
 Error addNativeDylibManager(SimpleSymbolTable &ST) {
   return ST.addUnique(orc_rt_ci_NativeDylibManager_sps_interface);
diff --git a/orc-rt/lib/bedrock/sps/SimpleNativeMemoryMapSPSCI.cpp b/orc-rt/lib/bedrock/sps/SimpleNativeMemoryMapSPSCI.cpp
index 218900caaa0301..936d0c9b6f5877 100644
--- a/orc-rt/lib/bedrock/sps/SimpleNativeMemoryMapSPSCI.cpp
+++ b/orc-rt/lib/bedrock/sps/SimpleNativeMemoryMapSPSCI.cpp
@@ -15,7 +15,6 @@
 #include "orc-rt/bedrock/SimpleNativeMemoryMap.h"
 #include "orc-rt/support/sps/SPSAllocAction.h"
 #include "orc-rt/support/sps/SPSMemoryFlags.h"
-#include "orc-rt/support/sps/SPSWrapperFunction.h"
 
 namespace orc_rt {
 
@@ -62,33 +61,35 @@ class SPSSerializationTraits<SPSSimpleNativeMemoryMapInitializeRequest,
 
 namespace sps_ci {
 
-ORC_RT_SPS_WRAPPER(
+ORC_RT_SPS_WRAPPER_IMPL(
     orc_rt_ci_sps_SimpleNativeMemoryMap_reserve,
     SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, SPSSize),
     WrapperFunction::handleWithAsyncMethod(&SimpleNativeMemoryMap::reserve))
 
-ORC_RT_SPS_WRAPPER(orc_rt_ci_sps_SimpleNativeMemoryMap_releaseMultiple,
-                   SPSError(SPSExecutorAddr, SPSSequence<SPSExecutorAddr>),
-                   WrapperFunction::handleWithAsyncMethod(
-                       &SimpleNativeMemoryMap::releaseMultiple))
+ORC_RT_SPS_WRAPPER_IMPL(orc_rt_ci_sps_SimpleNativeMemoryMap_releaseMultiple,
+                        SPSError(SPSExecutorAddr, SPSSequence<SPSExecutorAddr>),
+                        WrapperFunction::handleWithAsyncMethod(
+                            &SimpleNativeMemoryMap::releaseMultiple))
 
-ORC_RT_SPS_WRAPPER(
+ORC_RT_SPS_WRAPPER_IMPL(
     orc_rt_ci_sps_SimpleNativeMemoryMap_initialize,
     SPSExpected<SPSExecutorAddr>(SPSExecutorAddr,
                                  SPSSimpleNativeMemoryMapInitializeRequest),
     WrapperFunction::handleWithAsyncMethod(&SimpleNativeMemoryMap::initialize))
 
-ORC_RT_SPS_WRAPPER(orc_rt_ci_sps_SimpleNativeMemoryMap_deinitializeMultiple,
-                   SPSError(SPSExecutorAddr, SPSSequence<SPSExecutorAddr>),
-                   WrapperFunction::handleWithAsyncMethod(
-                       &SimpleNativeMemoryMap::deinitializeMultiple))
+ORC_RT_SPS_WRAPPER_IMPL(
+    orc_rt_ci_sps_SimpleNativeMemoryMap_deinitializeMultiple,
+    SPSError(SPSExecutorAddr, SPSSequence<SPSExecutorAddr>),
+    WrapperFunction::handleWithAsyncMethod(
+        &SimpleNativeMemoryMap::deinitializeMultiple))
 
-static std::pair<const char *, const void *>
+static std::pair<SymbolNameSpec, const void *>
     orc_rt_ci_SimpleNativeMemoryMap_sps_interface[] = {
-        ORC_RT_SYMTAB_PAIR(orc_rt_ci_sps_SimpleNativeMemoryMap_reserve),
-        ORC_RT_SYMTAB_PAIR(orc_rt_ci_sps_SimpleNativeMemoryMap_releaseMultiple),
-        ORC_RT_SYMTAB_PAIR(orc_rt_ci_sps_SimpleNativeMemoryMap_initialize),
-        ORC_RT_SYMTAB_PAIR(
+        ORC_RT_SYMTAB_C_PAIR(orc_rt_ci_sps_SimpleNativeMemoryMap_reserve),
+        ORC_RT_SYMTAB_C_PAIR(
+            orc_rt_ci_sps_SimpleNativeMemoryMap_releaseMultiple),
+        ORC_RT_SYMTAB_C_PAIR(orc_rt_ci_sps_SimpleNativeMemoryMap_initialize),
+        ORC_RT_SYMTAB_C_PAIR(
             orc_rt_ci_sps_SimpleNativeMemoryMap_deinitializeMultiple)};
 
 Error addSimpleNativeMemoryMap(SimpleSymbolTable &ST) {
diff --git a/orc-rt/lib/bedrock/sps/StandaloneMachOUnwindInfoRegistrarSPSCI.cpp b/orc-rt/lib/bedrock/sps/StandaloneMachOUnwindInfoRegistrarSPSCI.cpp
index c279c5fcf199a5..0ee76e87e87cc7 100644
--- a/orc-rt/lib/bedrock/sps/StandaloneMachOUnwindInfoRegistrarSPSCI.cpp
+++ b/orc-rt/lib/bedrock/sps/StandaloneMachOUnwindInfoRegistrarSPSCI.cpp
@@ -13,26 +13,25 @@
 
 #include "orc-rt/bedrock/sps/StandaloneMachOUnwindInfoRegistrarSPSCI.h"
 #include "orc-rt/bedrock/StandaloneMachOUnwindInfoRegistrar.h"
-#include "orc-rt/support/sps/SPSAllocAction.h"
 
 namespace orc_rt::sps_ci {
 
-ORC_RT_SPS_ALLOC_ACTION(
+ORC_RT_SPS_ALLOC_ACTION_IMPL(
     orc_rt_ci_aa_sps_MachOUnwindInfoRegistrar_registerSections,
     (SPSSequence<SPSExecutorAddrRange>, SPSExecutorAddr, SPSExecutorAddrRange,
      SPSExecutorAddrRange),
     &StandaloneMachOUnwindInfoRegistrar::registerSections)
 
-ORC_RT_SPS_ALLOC_ACTION(
+ORC_RT_SPS_ALLOC_ACTION_IMPL(
     orc_rt_ci_aa_sps_MachOUnwindInfoRegistrar_deregisterSections,
     (SPSSequence<SPSExecutorAddrRange>),
     &StandaloneMachOUnwindInfoRegistrar::deregisterSections)
 
-static std::pair<const char *, const void *>
+static std::pair<SymbolNameSpec, const void *>
     orc_rt_ci_StandaloneMachOUnwindInfoRegistrar_sps_interface[] = {
-        ORC_RT_SYMTAB_PAIR(
+        ORC_RT_SYMTAB_C_PAIR(
             orc_rt_ci_aa_sps_MachOUnwindInfoRegistrar_registerSections),
-        ORC_RT_SYMTAB_PAIR(
+        ORC_RT_SYMTAB_C_PAIR(
             orc_rt_ci_aa_sps_MachOUnwindInfoRegistrar_deregisterSections)};
 
 Error addStandaloneMachOUnwindInfoRegistrar(SimpleSymbolTable &ST) {
diff --git a/orc-rt/test/unit/bedrock/BootstrapInfoTest.cpp b/orc-rt/test/unit/bedrock/BootstrapInfoTest.cpp
index 14671abcb16dab..10af33fdc17aed 100644
--- a/orc-rt/test/unit/bedrock/BootstrapInfoTest.cpp
+++ b/orc-rt/test/unit/bedrock/BootstrapInfoTest.cpp
@@ -32,7 +32,8 @@ TEST(BootstrapInfoTest, ExplicitConstructionWithSymbolsAndValues) {
   Session S(mockExecutorProcessInfo(), noDispatch, noErrors);
   int X = 0;
   SimpleSymbolTable Symbols;
-  std::pair<const char *, void *> Syms[] = {{"orc_rt_X", &X}};
+  std::pair<SymbolNameSpec, void *> Syms[] = {
+      {SymbolNameSpec::linker("orc_rt_X"), &X}};
   cantFail(Symbols.addUnique(Syms));
 
   BootstrapInfo::ValueMap Values;
@@ -40,8 +41,8 @@ TEST(BootstrapInfoTest, ExplicitConstructionWithSymbolsAndValues) {
 
   BootstrapInfo BI(S, std::move(Symbols), std::move(Values));
   EXPECT_EQ(BI.symbols().size(), 1U);
-  EXPECT_TRUE(BI.symbols().count("orc_rt_X"));
-  EXPECT_EQ(BI.symbols().at("orc_rt_X"), &X);
+  EXPECT_TRUE(BI.symbols().count(SymbolNameSpec::linker("orc_rt_X")));
+  EXPECT_EQ(BI.symbols().at(SymbolNameSpec::linker("orc_rt_X")), &X);
   EXPECT_EQ(BI.values().size(), 1U);
   EXPECT_EQ(BI.values().at("key"), "value");
 }
@@ -61,17 +62,17 @@ TEST(BootstrapInfoTest, CreateDefaultSucceeds) {
 TEST(BootstrapInfoTest, CreateDefaultContainsSessionSymbol) {
   Session S(mockExecutorProcessInfo(), noDispatch, noErrors);
   auto BI = cantFail(BootstrapInfo::CreateDefault(S));
-  ASSERT_TRUE(BI.symbols().count("orc_rt_Session_Instance"));
-  EXPECT_EQ(BI.symbols().at("orc_rt_Session_Instance"),
-            static_cast<const void *>(&S));
+  auto SessionName = SymbolNameSpec::c("orc_rt_Session_Instance");
+  ASSERT_TRUE(BI.symbols().count(SessionName));
+  EXPECT_EQ(BI.symbols().at(SessionName), static_cast<const void *>(&S));
 }
 
 TEST(BootstrapInfoTest, CreateDefaultContainsSPSCISymbols) {
   Session S(mockExecutorProcessInfo(), noDispatch, noErrors);
   auto BI = cantFail(BootstrapInfo::CreateDefault(S));
   // The default addAll should have registered SPS CI symbols.
-  EXPECT_TRUE(
-      BI.symbols().count("orc_rt_ci_sps_SimpleNativeMemoryMap_reserve"));
+  EXPECT_TRUE(BI.symbols().count(
+      SymbolNameSpec::c("orc_rt_ci_sps_SimpleNativeMemoryMap_reserve")));
 }
 
 TEST(BootstrapInfoTest, CreateDefaultWithNoSymbolsBuilder) {
@@ -79,10 +80,10 @@ TEST(BootstrapInfoTest, CreateDefaultWithNoSymbolsBuilder) {
   auto BI = cantFail(BootstrapInfo::CreateDefault(S, /*AddInitialSymbols=*/{},
                                                   /*AddInitialValues=*/{}));
   // Should still contain the session symbol (added unconditionally).
-  ASSERT_TRUE(BI.symbols().count("orc_rt_Session_Instance"));
+  ASSERT_TRUE(BI.symbols().count(SymbolNameSpec::c("orc_rt_Session_Instance")));
   // But no SPS CI symbols.
-  EXPECT_FALSE(
-      BI.symbols().count("orc_rt_ci_sps_SimpleNativeMemoryMap_reserve"));
+  EXPECT_FALSE(BI.symbols().count(
+      SymbolNameSpec::c("orc_rt_ci_sps_SimpleNativeMemoryMap_reserve")));
 }
 
 TEST(BootstrapInfoTest, CreateDefaultWithCustomValuesBuilder) {
@@ -121,7 +122,8 @@ TEST(BootstrapInfoTest, MutableSymbolsAndValues) {
   BootstrapInfo BI(S);
 
   int X = 0;
-  std::pair<const char *, void *> Syms[] = {{"orc_rt_X", &X}};
+  std::pair<SymbolNameSpec, void *> Syms[] = {
+      {SymbolNameSpec::linker("orc_rt_X"), &X}};
   cantFail(BI.symbols().addUnique(Syms));
   BI.values()["key"] = "value";
 
diff --git a/orc-rt/test/unit/bedrock/SessionTest.cpp b/orc-rt/test/unit/bedrock/SessionTest.cpp
index df51db33a63c4d..967075da542d42 100644
--- a/orc-rt/test/unit/bedrock/SessionTest.cpp
+++ b/orc-rt/test/unit/bedrock/SessionTest.cpp
@@ -880,15 +880,16 @@ TEST(ControllerAccessTest, BootstrapInfoPassedToConnect) {
 
   // Build a BootstrapInfo with custom symbols and values.
   BootstrapInfo BI(S);
-  std::pair<const char *, const void *> TestSyms[] = {
-      {SymName, static_cast<const void *>(&Sym)}};
+  std::pair<SymbolNameSpec, const void *> TestSyms[] = {
+      {SymbolNameSpec::linker(SymName), static_cast<const void *>(&Sym)}};
   cantFail(BI.symbols().addUnique(TestSyms));
   BI.values()[SecretKey] = SecretValue;
 
   bool OnConnectRan = false;
   S.attach<MockControllerAccess>(
       std::move(BI), MockControllerAccess::PostFn{}, [&](BootstrapInfo &BI) {
-        EXPECT_EQ(BI.symbols().at(SymName), static_cast<const void *>(&Sym));
+        EXPECT_EQ(BI.symbols().at(SymbolNameSpec::linker(SymName)),
+                  static_cast<const void *>(&Sym));
         EXPECT_EQ(BI.values().at(SecretKey), SecretValue);
         OnConnectRan = true;
         return Error::success();
diff --git a/orc-rt/test/unit/bedrock/SimpleSymbolTableTest.cpp b/orc-rt/test/unit/bedrock/SimpleSymbolTableTest.cpp
index d5e93bad9518a1..1276d1d7b83216 100644
--- a/orc-rt/test/unit/bedrock/SimpleSymbolTableTest.cpp
+++ b/orc-rt/test/unit/bedrock/SimpleSymbolTableTest.cpp
@@ -28,54 +28,61 @@ TEST(SimpleSymbolTableTest, EmptyByDefault) {
 TEST(SimpleSymbolTableTest, AddSymbolsUnique) {
   SimpleSymbolTable ST;
   int X = 0, Y = 0;
-  std::pair<const char *, void *> Syms[] = {{"orc_rt_A", &X}, {"orc_rt_B", &Y}};
+  std::pair<SymbolNameSpec, void *> Syms[] = {
+      {SymbolNameSpec::linker("orc_rt_A"), &X},
+      {SymbolNameSpec::linker("orc_rt_B"), &Y}};
 
   auto Err = ST.addUnique(Syms);
   EXPECT_FALSE(Err) << "Unexpected error adding unique symbols";
 
   EXPECT_EQ(ST.size(), 2U);
   EXPECT_FALSE(ST.empty());
-  EXPECT_TRUE(ST.count("orc_rt_A"));
-  EXPECT_TRUE(ST.count("orc_rt_B"));
-  EXPECT_EQ(ST.at("orc_rt_A"), &X);
-  EXPECT_EQ(ST.at("orc_rt_B"), &Y);
+  EXPECT_TRUE(ST.count(SymbolNameSpec::linker("orc_rt_A")));
+  EXPECT_TRUE(ST.count(SymbolNameSpec::linker("orc_rt_B")));
+  EXPECT_EQ(ST.at(SymbolNameSpec::linker("orc_rt_A")), &X);
+  EXPECT_EQ(ST.at(SymbolNameSpec::linker("orc_rt_B")), &Y);
 }
 
 TEST(SimpleSymbolTableTest, AddConstPointers) {
   SimpleSymbolTable ST;
   const int X = 42;
   const int Y = 7;
-  std::pair<const char *, const void *> Syms[] = {{"orc_rt_A", &X},
-                                                  {"orc_rt_B", &Y}};
+  std::pair<SymbolNameSpec, const void *> Syms[] = {
+      {SymbolNameSpec::linker("orc_rt_A"), &X},
+      {SymbolNameSpec::linker("orc_rt_B"), &Y}};
   cantFail(ST.addUnique(Syms));
 
-  EXPECT_EQ(ST.at("orc_rt_A"), &X);
-  EXPECT_EQ(ST.at("orc_rt_B"), &Y);
+  EXPECT_EQ(ST.at(SymbolNameSpec::linker("orc_rt_A")), &X);
+  EXPECT_EQ(ST.at(SymbolNameSpec::linker("orc_rt_B")), &Y);
 }
 
 TEST(SimpleSymbolTableTest, AddSymbolsUniqueMultipleCalls) {
   SimpleSymbolTable ST;
   int X = 0, Y = 0;
 
-  std::pair<const char *, void *> First[] = {{"orc_rt_A", &X}};
-  std::pair<const char *, void *> Second[] = {{"orc_rt_B", &Y}};
+  std::pair<SymbolNameSpec, void *> First[] = {
+      {SymbolNameSpec::linker("orc_rt_A"), &X}};
+  std::pair<SymbolNameSpec, void *> Second[] = {
+      {SymbolNameSpec::linker("orc_rt_B"), &Y}};
 
   cantFail(ST.addUnique(First));
   cantFail(ST.addUnique(Second));
 
   EXPECT_EQ(ST.size(), 2U);
-  EXPECT_EQ(ST.at("orc_rt_A"), &X);
-  EXPECT_EQ(ST.at("orc_rt_B"), &Y);
+  EXPECT_EQ(ST.at(SymbolNameSpec::linker("orc_rt_A")), &X);
+  EXPECT_EQ(ST.at(SymbolNameSpec::linker("orc_rt_B")), &Y);
 }
 
 TEST(SimpleSymbolTableTest, AddSymbolsUniqueDuplicateRejected) {
   SimpleSymbolTable ST;
   int X = 0, Y = 0;
 
-  std::pair<const char *, void *> First[] = {{"orc_rt_A", &X}};
+  std::pair<SymbolNameSpec, void *> First[] = {
+      {SymbolNameSpec::linker("orc_rt_A"), &X}};
   cantFail(ST.addUnique(First));
 
-  std::pair<const char *, void *> Second[] = {{"orc_rt_A", &Y}};
+  std::pair<SymbolNameSpec, void *> Second[] = {
+      {SymbolNameSpec::linker("orc_rt_A"), &Y}};
   auto Err = ST.addUnique(Second);
   EXPECT_TRUE(Err.isA<StringError>());
 
@@ -84,19 +91,21 @@ TEST(SimpleSymbolTableTest, AddSymbolsUniqueDuplicateRejected) {
       << "Error message should mention the duplicate symbol name";
 
   // Original not overwritten.
-  EXPECT_EQ(ST.at("orc_rt_A"), &X);
+  EXPECT_EQ(ST.at(SymbolNameSpec::linker("orc_rt_A")), &X);
 }
 
 TEST(SimpleSymbolTableTest, AddSymbolsUniqueMultipleDuplicates) {
   SimpleSymbolTable ST;
   int X = 0, Y = 0, Z = 0;
 
-  std::pair<const char *, void *> First[] = {{"orc_rt_A", &X},
-                                             {"orc_rt_B", &Y}};
+  std::pair<SymbolNameSpec, void *> First[] = {
+      {SymbolNameSpec::linker("orc_rt_A"), &X},
+      {SymbolNameSpec::linker("orc_rt_B"), &Y}};
   cantFail(ST.addUnique(First));
 
-  std::pair<const char *, void *> Second[] = {{"orc_rt_A", &Z},
-                                              {"orc_rt_B", &Z}};
+  std::pair<SymbolNameSpec, void *> Second[] = {
+      {SymbolNameSpec::linker("orc_rt_A"), &Z},
+      {SymbolNameSpec::linker("orc_rt_B"), &Z}};
   auto Err = ST.addUnique(Second);
   EXPECT_TRUE(Err.isA<StringError>());
 
@@ -105,44 +114,49 @@ TEST(SimpleSymbolTableTest, AddSymbolsUniqueMultipleDuplicates) {
   EXPECT_NE(ErrMsg.find("orc_rt_B"), std::string::npos);
 
   // Originals not overwritten.
-  EXPECT_EQ(ST.at("orc_rt_A"), &X);
-  EXPECT_EQ(ST.at("orc_rt_B"), &Y);
+  EXPECT_EQ(ST.at(SymbolNameSpec::linker("orc_rt_A")), &X);
+  EXPECT_EQ(ST.at(SymbolNameSpec::linker("orc_rt_B")), &Y);
 }
 
 TEST(SimpleSymbolTableTest, AddSymbolsUniqueAllOrNothing) {
   SimpleSymbolTable ST;
   int X = 0, Y = 0, Z = 0;
 
-  std::pair<const char *, void *> First[] = {{"orc_rt_existing", &X}};
+  std::pair<SymbolNameSpec, void *> First[] = {
+      {SymbolNameSpec::linker("orc_rt_existing"), &X}};
   cantFail(ST.addUnique(First));
 
   // One new, one incompatible — neither should be added.
-  std::pair<const char *, void *> Second[] = {{"orc_rt_new", &Y},
-                                              {"orc_rt_existing", &Z}};
+  std::pair<SymbolNameSpec, void *> Second[] = {
+      {SymbolNameSpec::linker("orc_rt_new"), &Y},
+      {SymbolNameSpec::linker("orc_rt_existing"), &Z}};
   auto Err = ST.addUnique(Second);
   EXPECT_TRUE(Err.isA<StringError>());
   consumeError(std::move(Err));
 
   EXPECT_EQ(ST.size(), 1U);
-  EXPECT_EQ(ST.at("orc_rt_existing"), &X);
-  EXPECT_FALSE(ST.count("orc_rt_new"));
+  EXPECT_EQ(ST.at(SymbolNameSpec::linker("orc_rt_existing")), &X);
+  EXPECT_FALSE(ST.count(SymbolNameSpec::linker("orc_rt_new")));
 }
 
 TEST(SimpleSymbolTableTest, AddUniqueSameAddressSucceeds) {
   SimpleSymbolTable ST;
   int X = 0;
-  std::pair<const char *, void *> Syms[] = {{"orc_rt_A", &X}};
+  std::pair<SymbolNameSpec, void *> Syms[] = {
+      {SymbolNameSpec::linker("orc_rt_A"), &X}};
   cantFail(ST.addUnique(Syms));
   cantFail(ST.addUnique(Syms)); // Same name, same address — should succeed.
   EXPECT_EQ(ST.size(), 1U);
-  EXPECT_EQ(ST.at("orc_rt_A"), &X);
+  EXPECT_EQ(ST.at(SymbolNameSpec::linker("orc_rt_A")), &X);
 }
 
 TEST(SimpleSymbolTableTest, Iteration) {
   SimpleSymbolTable ST;
   int X = 0, Y = 0, Z = 0;
-  std::pair<const char *, void *> Syms[] = {
-      {"orc_rt_A", &X}, {"orc_rt_B", &Y}, {"orc_rt_C", &Z}};
+  std::pair<SymbolNameSpec, void *> Syms[] = {
+      {SymbolNameSpec::linker("orc_rt_A"), &X},
+      {SymbolNameSpec::linker("orc_rt_B"), &Y},
+      {SymbolNameSpec::linker("orc_rt_C"), &Z}};
   cantFail(ST.addUnique(Syms));
 
   std::set<std::string> Names;
diff --git a/orc-rt/test/unit/bedrock/sps/CallSPSCITest.cpp b/orc-rt/test/unit/bedrock/sps/CallSPSCITest.cpp
index 26d803e0484d3f..f7c249e7c04481 100644
--- a/orc-rt/test/unit/bedrock/sps/CallSPSCITest.cpp
+++ b/orc-rt/test/unit/bedrock/sps/CallSPSCITest.cpp
@@ -24,30 +24,23 @@ using namespace orc_rt;
 
 namespace {
 
-class CallSPSCITest : public ::testing::Test {
-protected:
-  void SetUp() override { cantFail(sps_ci::addCall(CI)); }
-
-  DirectCaller caller(const char *Name) {
-    return DirectCaller(nullptr, reinterpret_cast<orc_rt_WrapperFunction>(
-                                     const_cast<void *>(CI.at(Name))));
-  }
+static DirectCaller caller(orc_rt_WrapperFunction Fn) { return {nullptr, Fn}; }
 
+TEST(CallSPSCITest, Registration) {
   SimpleSymbolTable CI;
-};
+  cantFail(sps_ci::addCall(CI));
 
-TEST_F(CallSPSCITest, Registration) {
-  EXPECT_TRUE(CI.count("orc_rt_ci_sps_call_void_void"));
-  EXPECT_TRUE(CI.count("orc_rt_ci_sps_call_main"));
+  EXPECT_TRUE(CI.count(SymbolNameSpec::c("orc_rt_ci_sps_call_void_void")));
+  EXPECT_TRUE(CI.count(SymbolNameSpec::c("orc_rt_ci_sps_call_main")));
 }
 
 static int CallVoidVoidCount = 0;
 static void callVoidVoidFn() { ++CallVoidVoidCount; }
 
-TEST_F(CallSPSCITest, CallVoidVoid) {
+TEST(CallSPSCITest, CallVoidVoid) {
   using SPSSig = void(SPSExecutorAddr);
   SPSWrapperFunction<SPSSig>::call(
-      caller("orc_rt_ci_sps_call_void_void"),
+      caller(orc_rt_ci_sps_call_void_void),
       [](Error Err) { cantFail(std::move(Err)); },
       reinterpret_cast<void *>(callVoidVoidFn));
   EXPECT_EQ(CallVoidVoidCount, 1);
@@ -64,12 +57,12 @@ static int callMainFn(int argc, char *argv[]) {
   return 42;
 }
 
-TEST_F(CallSPSCITest, CallMain) {
+TEST(CallSPSCITest, CallMain) {
   using SPSSig = int64_t(SPSExecutorAddr, SPSSequence<SPSString>);
   std::optional<Expected<int64_t>> Result;
   std::vector<std::string> Args = {"prog", "arg1", "arg2"};
   SPSWrapperFunction<SPSSig>::call(
-      caller("orc_rt_ci_sps_call_main"),
+      caller(orc_rt_ci_sps_call_main),
       [&](Expected<int64_t> R) { Result = std::move(R); },
       reinterpret_cast<void *>(callMainFn), Args);
 
@@ -96,12 +89,12 @@ static int callMainEmptyArgVFn(int argc, char *argv[]) {
   return 42;
 }
 
-TEST_F(CallSPSCITest, CallMainEmptyArgV) {
+TEST(CallSPSCITest, CallMainEmptyArgV) {
   using SPSSig = int64_t(SPSExecutorAddr, SPSSequence<SPSString>);
   std::optional<Expected<int64_t>> Result;
   std::vector<std::string> Args;
   SPSWrapperFunction<SPSSig>::call(
-      caller("orc_rt_ci_sps_call_main"),
+      caller(orc_rt_ci_sps_call_main),
       [&](Expected<int64_t> R) { Result = std::move(R); },
       reinterpret_cast<void *>(callMainEmptyArgVFn), Args);
 
diff --git a/orc-rt/test/unit/bedrock/sps/MemoryAccessSPSCITest.cpp b/orc-rt/test/unit/bedrock/sps/MemoryAccessSPSCITest.cpp
index cf98718cbbecc1..e1a68c36b6ca43 100644
--- a/orc-rt/test/unit/bedrock/sps/MemoryAccessSPSCITest.cpp
+++ b/orc-rt/test/unit/bedrock/sps/MemoryAccessSPSCITest.cpp
@@ -19,85 +19,78 @@
 
 using namespace orc_rt;
 
-class MemoryAccessSPSCITest : public ::testing::Test {
-protected:
-  void SetUp() override { cantFail(sps_ci::addMemoryAccess(CI)); }
-
-  DirectCaller caller(const char *Name) {
-    return DirectCaller(nullptr, reinterpret_cast<orc_rt_WrapperFunction>(
-                                     const_cast<void *>(CI.at(Name))));
-  }
+static DirectCaller caller(orc_rt_WrapperFunction Fn) { return {nullptr, Fn}; }
 
+TEST(MemoryAccessSPSCITest, Registration) {
   SimpleSymbolTable CI;
-};
-
-TEST_F(MemoryAccessSPSCITest, Registration) {
-  EXPECT_TRUE(CI.count("orc_rt_ci_sps_mem_write_uint8s"));
-  EXPECT_TRUE(CI.count("orc_rt_ci_sps_mem_write_uint16s"));
-  EXPECT_TRUE(CI.count("orc_rt_ci_sps_mem_write_uint32s"));
-  EXPECT_TRUE(CI.count("orc_rt_ci_sps_mem_write_uint64s"));
-  EXPECT_TRUE(CI.count("orc_rt_ci_sps_mem_write_pointers"));
-  EXPECT_TRUE(CI.count("orc_rt_ci_sps_mem_write_buffers"));
-  EXPECT_TRUE(CI.count("orc_rt_ci_sps_mem_read_uint8s"));
-  EXPECT_TRUE(CI.count("orc_rt_ci_sps_mem_read_uint16s"));
-  EXPECT_TRUE(CI.count("orc_rt_ci_sps_mem_read_uint32s"));
-  EXPECT_TRUE(CI.count("orc_rt_ci_sps_mem_read_uint64s"));
-  EXPECT_TRUE(CI.count("orc_rt_ci_sps_mem_read_pointers"));
-  EXPECT_TRUE(CI.count("orc_rt_ci_sps_mem_read_buffers"));
-  EXPECT_TRUE(CI.count("orc_rt_ci_sps_mem_read_strings"));
+  cantFail(sps_ci::addMemoryAccess(CI));
+
+  EXPECT_TRUE(CI.count(SymbolNameSpec::c("orc_rt_ci_sps_mem_write_uint8s")));
+  EXPECT_TRUE(CI.count(SymbolNameSpec::c("orc_rt_ci_sps_mem_write_uint16s")));
+  EXPECT_TRUE(CI.count(SymbolNameSpec::c("orc_rt_ci_sps_mem_write_uint32s")));
+  EXPECT_TRUE(CI.count(SymbolNameSpec::c("orc_rt_ci_sps_mem_write_uint64s")));
+  EXPECT_TRUE(CI.count(SymbolNameSpec::c("orc_rt_ci_sps_mem_write_pointers")));
+  EXPECT_TRUE(CI.count(SymbolNameSpec::c("orc_rt_ci_sps_mem_write_buffers")));
+  EXPECT_TRUE(CI.count(SymbolNameSpec::c("orc_rt_ci_sps_mem_read_uint8s")));
+  EXPECT_TRUE(CI.count(SymbolNameSpec::c("orc_rt_ci_sps_mem_read_uint16s")));
+  EXPECT_TRUE(CI.count(SymbolNameSpec::c("orc_rt_ci_sps_mem_read_uint32s")));
+  EXPECT_TRUE(CI.count(SymbolNameSpec::c("orc_rt_ci_sps_mem_read_uint64s")));
+  EXPECT_TRUE(CI.count(SymbolNameSpec::c("orc_rt_ci_sps_mem_read_pointers")));
+  EXPECT_TRUE(CI.count(SymbolNameSpec::c("orc_rt_ci_sps_mem_read_buffers")));
+  EXPECT_TRUE(CI.count(SymbolNameSpec::c("orc_rt_ci_sps_mem_read_strings")));
 }
 
-TEST_F(MemoryAccessSPSCITest, WriteUInt8s) {
+TEST(MemoryAccessSPSCITest, WriteUInt8s) {
   uint8_t X = 0, Y = 0;
   using SPSSig = void(SPSSequence<SPSTuple<SPSExecutorAddr, uint8_t>>);
   std::vector<std::pair<ExecutorAddr, uint8_t>> Writes = {
       {ExecutorAddr::fromPtr(&X), 42}, {ExecutorAddr::fromPtr(&Y), 255}};
   SPSWrapperFunction<SPSSig>::call(
-      caller("orc_rt_ci_sps_mem_write_uint8s"),
+      caller(orc_rt_ci_sps_mem_write_uint8s),
       [](Error Err) { cantFail(std::move(Err)); }, std::move(Writes));
   EXPECT_EQ(X, 42U);
   EXPECT_EQ(Y, 255U);
 }
 
-TEST_F(MemoryAccessSPSCITest, WriteUInt16s) {
+TEST(MemoryAccessSPSCITest, WriteUInt16s) {
   uint16_t X = 0, Y = 0;
   using SPSSig = void(SPSSequence<SPSTuple<SPSExecutorAddr, uint16_t>>);
   std::vector<std::pair<ExecutorAddr, uint16_t>> Writes = {
       {ExecutorAddr::fromPtr(&X), 1000}, {ExecutorAddr::fromPtr(&Y), 65535}};
   SPSWrapperFunction<SPSSig>::call(
-      caller("orc_rt_ci_sps_mem_write_uint16s"),
+      caller(orc_rt_ci_sps_mem_write_uint16s),
       [](Error Err) { cantFail(std::move(Err)); }, std::move(Writes));
   EXPECT_EQ(X, 1000U);
   EXPECT_EQ(Y, 65535U);
 }
 
-TEST_F(MemoryAccessSPSCITest, WriteUInt32s) {
+TEST(MemoryAccessSPSCITest, WriteUInt32s) {
   uint32_t X = 0, Y = 0;
   using SPSSig = void(SPSSequence<SPSTuple<SPSExecutorAddr, uint32_t>>);
   std::vector<std::pair<ExecutorAddr, uint32_t>> Writes = {
       {ExecutorAddr::fromPtr(&X), 100000},
       {ExecutorAddr::fromPtr(&Y), 0xdeadbeef}};
   SPSWrapperFunction<SPSSig>::call(
-      caller("orc_rt_ci_sps_mem_write_uint32s"),
+      caller(orc_rt_ci_sps_mem_write_uint32s),
       [](Error Err) { cantFail(std::move(Err)); }, std::move(Writes));
   EXPECT_EQ(X, 100000U);
   EXPECT_EQ(Y, 0xdeadbeefU);
 }
 
-TEST_F(MemoryAccessSPSCITest, WriteUInt64s) {
+TEST(MemoryAccessSPSCITest, WriteUInt64s) {
   uint64_t X = 0, Y = 0;
   using SPSSig = void(SPSSequence<SPSTuple<SPSExecutorAddr, uint64_t>>);
   std::vector<std::pair<ExecutorAddr, uint64_t>> Writes = {
       {ExecutorAddr::fromPtr(&X), 0x0102030405060708ULL},
       {ExecutorAddr::fromPtr(&Y), 0xdeadbeefcafef00dULL}};
   SPSWrapperFunction<SPSSig>::call(
-      caller("orc_rt_ci_sps_mem_write_uint64s"),
+      caller(orc_rt_ci_sps_mem_write_uint64s),
       [](Error Err) { cantFail(std::move(Err)); }, std::move(Writes));
   EXPECT_EQ(X, 0x0102030405060708ULL);
   EXPECT_EQ(Y, 0xdeadbeefcafef00dULL);
 }
 
-TEST_F(MemoryAccessSPSCITest, WritePointers) {
+TEST(MemoryAccessSPSCITest, WritePointers) {
   void *X = nullptr, *Y = nullptr;
   int A = 1, B = 2;
   using SPSSig = void(SPSSequence<SPSTuple<SPSExecutorAddr, SPSExecutorAddr>>);
@@ -105,13 +98,13 @@ TEST_F(MemoryAccessSPSCITest, WritePointers) {
       {ExecutorAddr::fromPtr(&X), ExecutorAddr::fromPtr(&A)},
       {ExecutorAddr::fromPtr(&Y), ExecutorAddr::fromPtr(&B)}};
   SPSWrapperFunction<SPSSig>::call(
-      caller("orc_rt_ci_sps_mem_write_pointers"),
+      caller(orc_rt_ci_sps_mem_write_pointers),
       [](Error Err) { cantFail(std::move(Err)); }, std::move(Writes));
   EXPECT_EQ(X, static_cast<void *>(&A));
   EXPECT_EQ(Y, static_cast<void *>(&B));
 }
 
-TEST_F(MemoryAccessSPSCITest, WriteBuffers) {
+TEST(MemoryAccessSPSCITest, WriteBuffers) {
   char Buf[8] = {};
   char Content[] = "hello";
   using SPSSig =
@@ -119,7 +112,7 @@ TEST_F(MemoryAccessSPSCITest, WriteBuffers) {
   std::vector<std::pair<ExecutorAddr, span<char>>> Writes = {
       {ExecutorAddr::fromPtr(Buf), span<char>(Content, sizeof(Content))}};
   SPSWrapperFunction<SPSSig>::call(
-      caller("orc_rt_ci_sps_mem_write_buffers"),
+      caller(orc_rt_ci_sps_mem_write_buffers),
       [](Error Err) { cantFail(std::move(Err)); }, std::move(Writes));
   EXPECT_EQ(Buf[0], 'h');
   EXPECT_EQ(Buf[1], 'e');
@@ -129,14 +122,14 @@ TEST_F(MemoryAccessSPSCITest, WriteBuffers) {
   EXPECT_EQ(Buf[5], '\0');
 }
 
-TEST_F(MemoryAccessSPSCITest, ReadUInt8s) {
+TEST(MemoryAccessSPSCITest, ReadUInt8s) {
   uint8_t X = 42, Y = 255;
   using SPSSig = SPSSequence<uint8_t>(SPSSequence<SPSExecutorAddr>);
   std::vector<ExecutorAddr> Addrs = {ExecutorAddr::fromPtr(&X),
                                      ExecutorAddr::fromPtr(&Y)};
   std::vector<uint8_t> Result;
   SPSWrapperFunction<SPSSig>::call(
-      caller("orc_rt_ci_sps_mem_read_uint8s"),
+      caller(orc_rt_ci_sps_mem_read_uint8s),
       [&](Expected<std::vector<uint8_t>> R) {
         Result = cantFail(std::move(R));
       },
@@ -146,14 +139,14 @@ TEST_F(MemoryAccessSPSCITest, ReadUInt8s) {
   EXPECT_EQ(Result[1], 255U);
 }
 
-TEST_F(MemoryAccessSPSCITest, ReadUInt16s) {
+TEST(MemoryAccessSPSCITest, ReadUInt16s) {
   uint16_t X = 1000, Y = 65535;
   using SPSSig = SPSSequence<uint16_t>(SPSSequence<SPSExecutorAddr>);
   std::vector<ExecutorAddr> Addrs = {ExecutorAddr::fromPtr(&X),
                                      ExecutorAddr::fromPtr(&Y)};
   std::vector<uint16_t> Result;
   SPSWrapperFunction<SPSSig>::call(
-      caller("orc_rt_ci_sps_mem_read_uint16s"),
+      caller(orc_rt_ci_sps_mem_read_uint16s),
       [&](Expected<std::vector<uint16_t>> R) {
         Result = cantFail(std::move(R));
       },
@@ -163,14 +156,14 @@ TEST_F(MemoryAccessSPSCITest, ReadUInt16s) {
   EXPECT_EQ(Result[1], 65535U);
 }
 
-TEST_F(MemoryAccessSPSCITest, ReadUInt32s) {
+TEST(MemoryAccessSPSCITest, ReadUInt32s) {
   uint32_t X = 100000, Y = 0xdeadbeef;
   using SPSSig = SPSSequence<uint32_t>(SPSSequence<SPSExecutorAddr>);
   std::vector<ExecutorAddr> Addrs = {ExecutorAddr::fromPtr(&X),
                                      ExecutorAddr::fromPtr(&Y)};
   std::vector<uint32_t> Result;
   SPSWrapperFunction<SPSSig>::call(
-      caller("orc_rt_ci_sps_mem_read_uint32s"),
+      caller(orc_rt_ci_sps_mem_read_uint32s),
       [&](Expected<std::vector<uint32_t>> R) {
         Result = cantFail(std::move(R));
       },
@@ -180,14 +173,14 @@ TEST_F(MemoryAccessSPSCITest, ReadUInt32s) {
   EXPECT_EQ(Result[1], 0xdeadbeefU);
 }
 
-TEST_F(MemoryAccessSPSCITest, ReadUInt64s) {
+TEST(MemoryAccessSPSCITest, ReadUInt64s) {
   uint64_t X = 0x0102030405060708ULL, Y = 0xdeadbeefcafebabeULL;
   using SPSSig = SPSSequence<uint64_t>(SPSSequence<SPSExecutorAddr>);
   std::vector<ExecutorAddr> Addrs = {ExecutorAddr::fromPtr(&X),
                                      ExecutorAddr::fromPtr(&Y)};
   std::vector<uint64_t> Result;
   SPSWrapperFunction<SPSSig>::call(
-      caller("orc_rt_ci_sps_mem_read_uint64s"),
+      caller(orc_rt_ci_sps_mem_read_uint64s),
       [&](Expected<std::vector<uint64_t>> R) {
         Result = cantFail(std::move(R));
       },
@@ -197,7 +190,7 @@ TEST_F(MemoryAccessSPSCITest, ReadUInt64s) {
   EXPECT_EQ(Result[1], 0xdeadbeefcafebabeULL);
 }
 
-TEST_F(MemoryAccessSPSCITest, ReadPointers) {
+TEST(MemoryAccessSPSCITest, ReadPointers) {
   int A = 1, B = 2;
   void *X = &A, *Y = &B;
   using SPSSig = SPSSequence<SPSExecutorAddr>(SPSSequence<SPSExecutorAddr>);
@@ -205,7 +198,7 @@ TEST_F(MemoryAccessSPSCITest, ReadPointers) {
                                      ExecutorAddr::fromPtr(&Y)};
   std::vector<void *> Result;
   SPSWrapperFunction<SPSSig>::call(
-      caller("orc_rt_ci_sps_mem_read_pointers"),
+      caller(orc_rt_ci_sps_mem_read_pointers),
       [&](Expected<std::vector<void *>> R) { Result = cantFail(std::move(R)); },
       std::move(Addrs));
   ASSERT_EQ(Result.size(), 2U);
@@ -213,7 +206,7 @@ TEST_F(MemoryAccessSPSCITest, ReadPointers) {
   EXPECT_EQ(Result[1], static_cast<void *>(&B));
 }
 
-TEST_F(MemoryAccessSPSCITest, ReadBuffers) {
+TEST(MemoryAccessSPSCITest, ReadBuffers) {
   const char Src[] = "hello world";
   using SPSSig = SPSSequence<SPSSequence<char>>(
       SPSSequence<SPSTuple<SPSExecutorAddr, uint64_t>>);
@@ -222,7 +215,7 @@ TEST_F(MemoryAccessSPSCITest, ReadBuffers) {
       {ExecutorAddr::fromPtr(Src + 6), 5}}; // "world"
   std::vector<std::vector<char>> Result;
   SPSWrapperFunction<SPSSig>::call(
-      caller("orc_rt_ci_sps_mem_read_buffers"),
+      caller(orc_rt_ci_sps_mem_read_buffers),
       [&](Expected<std::vector<std::vector<char>>> R) {
         Result = cantFail(std::move(R));
       },
@@ -232,7 +225,7 @@ TEST_F(MemoryAccessSPSCITest, ReadBuffers) {
   EXPECT_EQ(Result[1], (std::vector<char>{'w', 'o', 'r', 'l', 'd'}));
 }
 
-TEST_F(MemoryAccessSPSCITest, ReadStrings) {
+TEST(MemoryAccessSPSCITest, ReadStrings) {
   const char *Str1 = "hello";
   const char *Str2 = "world";
   using SPSSig = SPSSequence<SPSString>(SPSSequence<SPSExecutorAddr>);
@@ -240,7 +233,7 @@ TEST_F(MemoryAccessSPSCITest, ReadStrings) {
                                      ExecutorAddr::fromPtr(Str2)};
   std::vector<std::string> Result;
   SPSWrapperFunction<SPSSig>::call(
-      caller("orc_rt_ci_sps_mem_read_strings"),
+      caller(orc_rt_ci_sps_mem_read_strings),
       [&](Expected<std::vector<std::string>> R) {
         Result = cantFail(std::move(R));
       },
diff --git a/orc-rt/test/unit/bedrock/sps/NativeDylibManagerSPSCITest.cpp b/orc-rt/test/unit/bedrock/sps/NativeDylibManagerSPSCITest.cpp
index 8f258d612bb42f..b4252a14575dc3 100644
--- a/orc-rt/test/unit/bedrock/sps/NativeDylibManagerSPSCITest.cpp
+++ b/orc-rt/test/unit/bedrock/sps/NativeDylibManagerSPSCITest.cpp
@@ -73,6 +73,8 @@ constexpr auto Weak = NativeDylibManager::WeaklyReferencedSymbol;
     "NDM_TEST_LIB_PATH must be defined to the path of the test shared library"
 #endif
 
+static DirectCaller caller(orc_rt_WrapperFunction Fn) { return {nullptr, Fn}; }
+
 class NativeDylibManagerSPSCITest : public ::testing::Test {
 protected:
   void SetUp() override {
@@ -81,16 +83,11 @@ class NativeDylibManagerSPSCITest : public ::testing::Test {
     NDM = cantFail(NativeDylibManager::Create(*S, CI));
   }
 
-  DirectCaller caller(const char *Name) {
-    return DirectCaller(nullptr, reinterpret_cast<orc_rt_WrapperFunction>(
-                                     const_cast<void *>(CI.at(Name))));
-  }
-
   template <typename OnCompleteFn>
   void spsLoad(OnCompleteFn &&OnComplete, std::string Path) {
     using SPSSig = SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, SPSString);
     SPSWrapperFunction<SPSSig>::call(
-        caller("orc_rt_ci_sps_NativeDylibManager_load"),
+        caller(orc_rt_ci_sps_NativeDylibManager_load),
         std::forward<OnCompleteFn>(OnComplete), NDM.get(), std::move(Path));
   }
 
@@ -101,7 +98,7 @@ class NativeDylibManagerSPSCITest : public ::testing::Test {
         SPSExecutorAddr, SPSExecutorAddr,
         SPSSequence<SPSTuple<SPSString, bool>>);
     SPSWrapperFunction<SPSSig>::call(
-        caller("orc_rt_ci_sps_NativeDylibManager_lookup"),
+        caller(orc_rt_ci_sps_NativeDylibManager_lookup),
         std::forward<OnCompleteFn>(OnComplete), NDM.get(), Handle,
         std::move(Symbols));
   }
@@ -112,8 +109,10 @@ class NativeDylibManagerSPSCITest : public ::testing::Test {
 };
 
 TEST_F(NativeDylibManagerSPSCITest, Registration) {
-  EXPECT_TRUE(CI.count("orc_rt_ci_sps_NativeDylibManager_load"));
-  EXPECT_TRUE(CI.count("orc_rt_ci_sps_NativeDylibManager_lookup"));
+  EXPECT_TRUE(
+      CI.count(SymbolNameSpec::c("orc_rt_ci_sps_NativeDylibManager_load")));
+  EXPECT_TRUE(
+      CI.count(SymbolNameSpec::c("orc_rt_ci_sps_NativeDylibManager_lookup")));
 }
 
 TEST_F(NativeDylibManagerSPSCITest, Load) {
diff --git a/orc-rt/test/unit/bedrock/sps/SimpleNativeMemoryMapSPSCITest.cpp b/orc-rt/test/unit/bedrock/sps/SimpleNativeMemoryMapSPSCITest.cpp
index 522ddfa85f9154..e455afb209574f 100644
--- a/orc-rt/test/unit/bedrock/sps/SimpleNativeMemoryMapSPSCITest.cpp
+++ b/orc-rt/test/unit/bedrock/sps/SimpleNativeMemoryMapSPSCITest.cpp
@@ -111,6 +111,8 @@ read_value_sps_allocaction(const char *ArgData, size_t ArgSize) {
       .release();
 }
 
+DirectCaller caller(orc_rt_WrapperFunction Fn) { return {nullptr, Fn}; }
+
 class SimpleNativeMemoryMapSPSCITest : public ::testing::Test {
 protected:
   void SetUp() override {
@@ -127,16 +129,11 @@ class SimpleNativeMemoryMapSPSCITest : public ::testing::Test {
     }
   }
 
-  DirectCaller caller(const char *Name) {
-    return DirectCaller(nullptr, reinterpret_cast<orc_rt_WrapperFunction>(
-                                     const_cast<void *>(CI.at(Name))));
-  }
-
   template <typename OnCompleteFn>
   void spsReserve(OnCompleteFn &&OnComplete, size_t Size) {
     using SPSSig = SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, SPSSize);
     SPSWrapperFunction<SPSSig>::call(
-        caller("orc_rt_ci_sps_SimpleNativeMemoryMap_reserve"),
+        caller(orc_rt_ci_sps_SimpleNativeMemoryMap_reserve),
         std::forward<OnCompleteFn>(OnComplete), SNMM.get(), Size);
   }
 
@@ -144,7 +141,7 @@ class SimpleNativeMemoryMapSPSCITest : public ::testing::Test {
   void spsReleaseMultiple(OnCompleteFn &&OnComplete, span<void *> Addrs) {
     using SPSSig = SPSError(SPSExecutorAddr, SPSSequence<SPSExecutorAddr>);
     SPSWrapperFunction<SPSSig>::call(
-        caller("orc_rt_ci_sps_SimpleNativeMemoryMap_releaseMultiple"),
+        caller(orc_rt_ci_sps_SimpleNativeMemoryMap_releaseMultiple),
         std::forward<OnCompleteFn>(OnComplete), SNMM.get(), Addrs);
   }
 
@@ -153,7 +150,7 @@ class SimpleNativeMemoryMapSPSCITest : public ::testing::Test {
     using SPSSig = SPSExpected<SPSExecutorAddr>(
         SPSExecutorAddr, SPSSimpleNativeMemoryMapInitializeRequest);
     SPSWrapperFunction<SPSSig>::call(
-        caller("orc_rt_ci_sps_SimpleNativeMemoryMap_initialize"),
+        caller(orc_rt_ci_sps_SimpleNativeMemoryMap_initialize),
         std::forward<OnCompleteFn>(OnComplete), SNMM.get(), std::move(IR));
   }
 
@@ -161,7 +158,7 @@ class SimpleNativeMemoryMapSPSCITest : public ::testing::Test {
   void spsDeinitializeMultiple(OnCompleteFn &&OnComplete, span<void *> Bases) {
     using SPSSig = SPSError(SPSExecutorAddr, SPSSequence<SPSExecutorAddr>);
     SPSWrapperFunction<SPSSig>::call(
-        caller("orc_rt_ci_sps_SimpleNativeMemoryMap_deinitializeMultiple"),
+        caller(orc_rt_ci_sps_SimpleNativeMemoryMap_deinitializeMultiple),
         std::forward<OnCompleteFn>(OnComplete), SNMM.get(), Bases);
   }
 
@@ -171,11 +168,15 @@ class SimpleNativeMemoryMapSPSCITest : public ::testing::Test {
 };
 
 TEST_F(SimpleNativeMemoryMapSPSCITest, Registration) {
-  EXPECT_TRUE(CI.count("orc_rt_ci_sps_SimpleNativeMemoryMap_reserve"));
-  EXPECT_TRUE(CI.count("orc_rt_ci_sps_SimpleNativeMemoryMap_releaseMultiple"));
-  EXPECT_TRUE(CI.count("orc_rt_ci_sps_SimpleNativeMemoryMap_initialize"));
-  EXPECT_TRUE(
-      CI.count("orc_rt_ci_sps_SimpleNativeMemoryMap_deinitializeMultiple"));
+
+  EXPECT_TRUE(CI.count(
+      SymbolNameSpec::c("orc_rt_ci_sps_SimpleNativeMemoryMap_reserve")));
+  EXPECT_TRUE(CI.count(SymbolNameSpec::c(
+      "orc_rt_ci_sps_SimpleNativeMemoryMap_releaseMultiple")));
+  EXPECT_TRUE(CI.count(
+      SymbolNameSpec::c("orc_rt_ci_sps_SimpleNativeMemoryMap_initialize")));
+  EXPECT_TRUE(CI.count(SymbolNameSpec::c(
+      "orc_rt_ci_sps_SimpleNativeMemoryMap_deinitializeMultiple")));
 }
 
 TEST_F(SimpleNativeMemoryMapSPSCITest, ReserveAndRelease) {
diff --git a/orc-rt/test/unit/bedrock/sps/SimpleRemoteCATest.cpp b/orc-rt/test/unit/bedrock/sps/SimpleRemoteCATest.cpp
index 5dc1ef52a236ef..0e580edd1aeb19 100644
--- a/orc-rt/test/unit/bedrock/sps/SimpleRemoteCATest.cpp
+++ b/orc-rt/test/unit/bedrock/sps/SimpleRemoteCATest.cpp
@@ -146,8 +146,8 @@ TEST(SimpleRemoteCATest, SetupMessageRoundTrips) {
 
   int SomeSymbol = 0;
   SimpleSymbolTable Symbols;
-  std::vector<std::pair<std::string, const void *>> SymbolDefs = {
-      {"foo", &SomeSymbol}};
+  std::vector<std::pair<SymbolNameSpec, const void *>> SymbolDefs = {
+      {SymbolNameSpec::linker("foo"), &SomeSymbol}};
   cantFail(Symbols.addUnique(SymbolDefs));
 
   BootstrapInfo BI(S, std::move(Symbols),
diff --git a/orc-rt/test/unit/support/sps/SPSAllocActionTest.cpp b/orc-rt/test/unit/support/sps/SPSAllocActionTest.cpp
index c5d03c75dcbd44..08691fc2b6202c 100644
--- a/orc-rt/test/unit/support/sps/SPSAllocActionTest.cpp
+++ b/orc-rt/test/unit/support/sps/SPSAllocActionTest.cpp
@@ -133,8 +133,8 @@ static Error check_values_equal(int32_t X, int32_t Y) {
     return Error::success();
   return make_error<StringError>("X and Y differ");
 }
-ORC_RT_SPS_ALLOC_ACTION(macro_defined_allocaction, (int32_t, int32_t),
-                        check_values_equal)
+ORC_RT_SPS_ALLOC_ACTION_IMPL(macro_defined_allocaction, (int32_t, int32_t),
+                             check_values_equal)
 
 TEST(SPSAllocActionTest, RunMacroDefinedAllocActionWithErrorSuccessReturn) {
   AllocAction AA(macro_defined_allocaction,
diff --git a/orc-rt/test/unit/support/sps/SPSWrapperFunctionTest.cpp b/orc-rt/test/unit/support/sps/SPSWrapperFunctionTest.cpp
index 69488d6b547503..e68a459a95c90a 100644
--- a/orc-rt/test/unit/support/sps/SPSWrapperFunctionTest.cpp
+++ b/orc-rt/test/unit/support/sps/SPSWrapperFunctionTest.cpp
@@ -28,8 +28,8 @@ static void add_via_function(orc_rt::move_only_function<void(int32_t)> Return,
 // Note: This macro use has been deliberately moved above the
 // "using namespace orc_rt;" statement below to check that its expansion works
 // from other namespaces.
-ORC_RT_SPS_WRAPPER(add_via_function_sps_wrapper, int32_t(int32_t, int32_t),
-                   add_via_function);
+ORC_RT_SPS_WRAPPER_IMPL(add_via_function_sps_wrapper, int32_t(int32_t, int32_t),
+                        add_via_function);
 
 using namespace orc_rt;
 



More information about the llvm-commits mailing list