[llvm] a place holder for a huge swatch of work, will split this up for wind… (PR #224260)

Jared Wyles via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 17 03:53:10 PDT 2026


https://github.com/jaredwy created https://github.com/llvm/llvm-project/pull/224260

…ows later

>From 858a620b060d57a3d93414668682aef1688bb4e8 Mon Sep 17 00:00:00 2001
From: Jared Wyles <jared.wyles at gmail.com>
Date: Thu, 17 Sep 2026 20:51:58 +1000
Subject: [PATCH] a place holder for a huge swatch of work, will split this up
 for windows later

---
 .../modules/LLVMExternalProjectUtils.cmake    |   4 +-
 orc-rt/CMakeLists.txt                         |  42 ++-
 orc-rt/include/orc-rt-c/support/Compiler.h    |   6 +-
 .../bedrock/sys/DynamicLibrary.h              |  22 +-
 .../orc-rt-internal/tools/OptionParser.h      |  32 +-
 .../orc-rt/bedrock/NativeDylibManager.h       |  10 +
 orc-rt/include/orc-rt/support/BitmaskEnum.h   |   5 +-
 orc-rt/include/orc-rt/support/Error.h         |   2 +-
 .../include/orc-rt/support/ExecutorAddress.h  |   2 +-
 orc-rt/include/orc-rt/support/bit.h           |  31 +-
 orc-rt/lib/bedrock/CMakeLists.txt             |   9 +-
 orc-rt/lib/bedrock/NativeDylibManager.cpp     |  77 +++-
 orc-rt/lib/bedrock/sps/AllSPSCI.cpp           |   5 +-
 .../lib/bedrock/sys/posix/DynamicLibrary.cpp  |  77 ++--
 .../lib/bedrock/sys/windows/TargetTriple.cpp  |   8 +-
 orc-rt/test/CMakeLists.txt                    |   3 +
 .../darwin/check-rt-process-info.test         |   6 -
 orc-rt/test/regression/darwin/lit.local.cfg   |   2 -
 .../linux/check-rt-process-info.test          |   5 -
 orc-rt/test/regression/linux/lit.local.cfg    |   2 -
 orc-rt/test/unit/CMakeLists.txt               | 338 ++++++++++++------
 .../unit/Inputs/RTTICrossDylibTestLib.cpp     |   2 +-
 .../unit/bedrock/ExecutorProcessInfoTest.cpp  |   7 -
 .../bedrock/InProcessControllerAccessTest.cpp |  19 +-
 .../unit/bedrock/sps/SimpleRemoteCATest.cpp   |   5 +-
 .../unit/support/CallableTraitsHelperTest.cpp |  18 +-
 orc-rt/test/unit/support/bit-test.cpp         |   5 +
 orc-rt/test/unit/tools/OptionParserTest.cpp   |   5 +-
 28 files changed, 491 insertions(+), 258 deletions(-)
 delete mode 100644 orc-rt/test/regression/darwin/check-rt-process-info.test
 delete mode 100644 orc-rt/test/regression/darwin/lit.local.cfg
 delete mode 100644 orc-rt/test/regression/linux/check-rt-process-info.test
 delete mode 100644 orc-rt/test/regression/linux/lit.local.cfg

diff --git a/llvm/cmake/modules/LLVMExternalProjectUtils.cmake b/llvm/cmake/modules/LLVMExternalProjectUtils.cmake
index 60a880ace50736..32e25567ef57e2 100644
--- a/llvm/cmake/modules/LLVMExternalProjectUtils.cmake
+++ b/llvm/cmake/modules/LLVMExternalProjectUtils.cmake
@@ -290,8 +290,8 @@ function(llvm_ExternalProject_Add name source_dir)
     if(llvm-mt IN_LIST TOOLCHAIN_TOOLS AND is_msvc_target)
       list(APPEND compiler_args -DCMAKE_MT=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-mt${CMAKE_EXECUTABLE_SUFFIX})
     endif()
-    if(llvm-rc IN_LIST TOOLCHAIN_TOOLS AND is_msvc_target)
-      list(APPEND compiler_args -DCMAKE_RC_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-rc${CMAKE_EXECUTABLE_SUFFIX})
+    if(llvm-rc IN_LIST TOOLCHAIN_TOOLS AND is_msvc_target AND CLANG_IN_TOOLCHAIN)
+        list(APPEND compiler_args -DCMAKE_RC_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-rc${CMAKE_EXECUTABLE_SUFFIX})
     endif()
     list(APPEND ARG_DEPENDS ${TOOLCHAIN_TOOLS})
     # Add LLVMgold.so dependency if it is available, as clang may need it for
diff --git a/orc-rt/CMakeLists.txt b/orc-rt/CMakeLists.txt
index 75050fd2802fc5..1fae7c4140aca3 100644
--- a/orc-rt/CMakeLists.txt
+++ b/orc-rt/CMakeLists.txt
@@ -88,16 +88,30 @@ option(ORC_RT_ENABLE_EXCEPTIONS "Enable exceptions." ON)
 
 # Derive the compile flags implied by the language-runtime options.
 set(ORC_RT_COMPILE_FLAGS)
-if(ORC_RT_ENABLE_RTTI)
-  list(APPEND ORC_RT_COMPILE_FLAGS -frtti)
+if(MSVC OR CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
+  if(ORC_RT_ENABLE_RTTI)
+    list(APPEND ORC_RT_COMPILE_FLAGS /GR)
+  else()
+    list(APPEND ORC_RT_COMPILE_FLAGS /GR-)
+  endif()
+
+  if(ORC_RT_ENABLE_EXCEPTIONS)
+    list(APPEND ORC_RT_COMPILE_FLAGS /EHsc)
+  else()
+    list(APPEND ORC_RT_COMPILE_FLAGS /EHs-c-)
+  endif()
 else()
-  list(APPEND ORC_RT_COMPILE_FLAGS -fno-rtti)
-endif()
-
-if(ORC_RT_ENABLE_EXCEPTIONS)
-  list(APPEND ORC_RT_COMPILE_FLAGS -fexceptions)
-else()
-  list(APPEND ORC_RT_COMPILE_FLAGS -fno-exceptions)
+  if(ORC_RT_ENABLE_RTTI)
+    list(APPEND ORC_RT_COMPILE_FLAGS -frtti)
+  else()
+    list(APPEND ORC_RT_COMPILE_FLAGS -fno-rtti)
+  endif()
+
+  if(ORC_RT_ENABLE_EXCEPTIONS)
+    list(APPEND ORC_RT_COMPILE_FLAGS -fexceptions)
+  else()
+    list(APPEND ORC_RT_COMPILE_FLAGS -fno-exceptions)
+  endif()
 endif()
 
 # --- Logging ---
@@ -115,6 +129,16 @@ set(ORC_RT_LOG_BACKEND "none" CACHE STRING
 set(orc_rt_log_backends none printf os_log)
 set_property(CACHE ORC_RT_LOG_BACKEND PROPERTY STRINGS ${orc_rt_log_backends})
 
+# enable project wide windows settings.
+# Mostly to avoid min and max conflicts
+if(WIN32)
+  add_compile_definitions(
+    NOMINMAX
+    WIN32_LEAN_AND_MEAN
+  )
+endif()
+
+
 # Validate the level and derive its config.h macro symbol.
 if(NOT ORC_RT_LOG_LEVEL IN_LIST orc_rt_log_levels)
   message(FATAL_ERROR "ORC_RT_LOG_LEVEL must be one of: ${orc_rt_log_levels}")
diff --git a/orc-rt/include/orc-rt-c/support/Compiler.h b/orc-rt/include/orc-rt-c/support/Compiler.h
index c576a2fd73240c..e3addba58aecab 100644
--- a/orc-rt/include/orc-rt-c/support/Compiler.h
+++ b/orc-rt/include/orc-rt-c/support/Compiler.h
@@ -65,8 +65,12 @@
 
    TODO: Add the Windows __declspec(dllexport) / __declspec(dllimport) and
    static-build cases once there is a shared-library build to exercise them. */
-#if defined(__has_attribute) && __has_attribute(visibility)
+#if defined(_WIN32)
+#define ORC_RT_C_EXPORT
+#elif defined(__has_attribute) && __has_attribute(visibility)
 #define ORC_RT_C_EXPORT __attribute__((visibility("default")))
+#else
+#define ORC_RT_C_EXPORT
 #endif
 
 #if !defined(ORC_RT_C_EXPORT)
diff --git a/orc-rt/include/orc-rt-internal/bedrock/sys/DynamicLibrary.h b/orc-rt/include/orc-rt-internal/bedrock/sys/DynamicLibrary.h
index 62b6d74a71b0f6..d06cc613ea9212 100644
--- a/orc-rt/include/orc-rt-internal/bedrock/sys/DynamicLibrary.h
+++ b/orc-rt/include/orc-rt-internal/bedrock/sys/DynamicLibrary.h
@@ -25,23 +25,23 @@
 
 namespace orc_rt::sys {
 
-/// Returns a handle that looks up symbols in every library loaded into the
-/// process.
-void *globalLookupHandle();
+using DylibHandle = void *;
+using SymbolLookupResult = std::vector<std::optional<void *>>;
 
 /// Load the library at the given path. Path must not be empty.
-Expected<void *> loadLibrary(const std::string &Path);
+Expected<DylibHandle> loadLibrary(const std::string &Path);
 
 /// Unload a library previously returned by loadLibrary.
-Error unloadLibrary(void *Handle);
+Error unloadLibrary(DylibHandle Handle);
 
 /// Look Names up in Handle, returning one result per name in order.
-///
-/// A result is nullopt if the name is not present in the library, and a
-/// (possibly null) address if it is: a symbol genuinely located at address zero
-/// is reported as null rather than as missing.
-std::vector<std::optional<void *>>
-lookupLibrarySymbols(void *Handle, const std::vector<std::string> &Names);
+SymbolLookupResult
+lookupLibrarySymbols(DylibHandle Handle,
+                     const std::vector<std::string> &Names);
+
+/// Look Names up across libraries loaded into the process.
+SymbolLookupResult
+lookupGlobalSymbols(const std::vector<std::string> &Names);
 
 } // namespace orc_rt::sys
 
diff --git a/orc-rt/include/orc-rt-internal/tools/OptionParser.h b/orc-rt/include/orc-rt-internal/tools/OptionParser.h
index ddc50f46b06132..44b79396359e95 100644
--- a/orc-rt/include/orc-rt-internal/tools/OptionParser.h
+++ b/orc-rt/include/orc-rt-internal/tools/OptionParser.h
@@ -93,21 +93,23 @@ class OptionParser {
                          OptionKind Kind = OptionKind::Value,
                          std::optional<char> ShortName = std::nullopt) {
     Val = DefaultVal;
-    Opts.push_back({.Name = std::string(Name),
-                    .ShortName = std::move(ShortName),
-                    .Desc = std::string(Desc),
-                    .Kind = Kind,
-                    .Default = [&Val, DV = DefaultVal]() { Val = DV; },
-                    .FromString = [&Val, OptName = std::string(Name)](
-                                      std::string_view S) -> Error {
-                      if (auto V = detail::parseValue<T>(S)) {
-                        Val = *V;
-                        return Error::success();
-                      }
-                      return make_error<StringError>(
-                          std::string("Invalid value for '") + OptName +
-                          "': '" + std::string(S) + "'");
-                    }});
+    Opts.push_back({
+        std::string(Name),
+        std::move(ShortName),
+        std::string(Desc),
+        Kind,
+        [&Val, DV = DefaultVal]() { Val = DV; },
+        [&Val, OptName = std::string(Name)](
+            std::string_view S) -> orc_rt::Error {
+          if (auto V = detail::parseValue<T>(S)) {
+            Val = *V;
+            return orc_rt::Error::success();
+          }
+
+          return orc_rt::make_error<orc_rt::StringError>(
+              std::string("Invalid value for '") + OptName +
+              "': '" + std::string(S) + "'");
+        }});
     return *this;
   }
 
diff --git a/orc-rt/include/orc-rt/bedrock/NativeDylibManager.h b/orc-rt/include/orc-rt/bedrock/NativeDylibManager.h
index e7a921c13aa1ba..f6e1e0d8ba8ecf 100644
--- a/orc-rt/include/orc-rt/bedrock/NativeDylibManager.h
+++ b/orc-rt/include/orc-rt/bedrock/NativeDylibManager.h
@@ -31,6 +31,16 @@ class Session;
 class NativeDylibManager : public Service {
 public:
   enum LookupFlags { RequiredSymbol, WeaklyReferencedSymbol };
+
+  struct DylibHandle {
+    enum class Kind {
+      Global,
+      Library,
+    };
+
+    Kind K;
+    void *LibraryHandle = nullptr;
+  };
   using SymbolLookupSet = std::vector<std::pair<std::string, LookupFlags>>;
 
   /// Create a NativeDylibManager, adding associated symbols to the given
diff --git a/orc-rt/include/orc-rt/support/BitmaskEnum.h b/orc-rt/include/orc-rt/support/BitmaskEnum.h
index 85a863f99d6c2d..5bc93ad5c81524 100644
--- a/orc-rt/include/orc-rt/support/BitmaskEnum.h
+++ b/orc-rt/include/orc-rt/support/BitmaskEnum.h
@@ -109,7 +109,7 @@ struct largest_bitmask_enum_bit<
 template <typename E>
 constexpr std::underlying_type_t<E> bitmask_enum_mask() noexcept {
   using UnderlyingTy = std::underlying_type_t<E>;
-  constexpr int Width = bit_width(largest_bitmask_enum_bit<E>::value);
+  constexpr int Width = bit_width_constexpr(largest_bitmask_enum_bit<E>::value);
   // Shifting by the full width of the type would be undefined, so handle a
   // largest bit in the top position separately: the mask is then every bit.
   return Width == std::numeric_limits<UnderlyingTy>::digits
@@ -127,7 +127,8 @@ constexpr std::underlying_type_t<E> bitmask_enum_to_underlying(E Val) noexcept {
 
 template <typename E, typename _ = std::enable_if_t<is_bitmask_enum_v<E>>>
 struct bitmask_enum_num_bits {
-  static constexpr int value = bit_width(largest_bitmask_enum_bit<E>::value);
+  static constexpr int value =
+      orc_rt::bit_width_constexpr(largest_bitmask_enum_bit<E>::value);
 };
 
 template <typename E>
diff --git a/orc-rt/include/orc-rt/support/Error.h b/orc-rt/include/orc-rt/support/Error.h
index 02f876455905dd..3ff55b8cac74cf 100644
--- a/orc-rt/include/orc-rt/support/Error.h
+++ b/orc-rt/include/orc-rt/support/Error.h
@@ -185,7 +185,7 @@ class [[nodiscard]] Error {
   bool isChecked() const noexcept { return ErrPtr & 0x1; }
 
   void setChecked(bool Checked) noexcept {
-    ErrPtr = (ErrPtr & ~uintptr_t(1)) | Checked;
+    ErrPtr = (ErrPtr & ~uintptr_t(1)) | (uintptr_t)Checked;
   }
 
   template <typename ErrT = ErrorInfoBase>
diff --git a/orc-rt/include/orc-rt/support/ExecutorAddress.h b/orc-rt/include/orc-rt/support/ExecutorAddress.h
index c3603a1708f663..25b942571ac68b 100644
--- a/orc-rt/include/orc-rt/support/ExecutorAddress.h
+++ b/orc-rt/include/orc-rt/support/ExecutorAddress.h
@@ -225,7 +225,7 @@ struct ExecutorAddrRange {
 
 // Make ExecutorAddr hashable.
 template <> struct std::hash<orc_rt::ExecutorAddr> {
-  constexpr size_t operator()(const orc_rt::ExecutorAddr &A) const noexcept {
+  size_t operator()(const orc_rt::ExecutorAddr &A) const noexcept {
     return std::hash<uint64_t>()(A.getValue());
   }
 };
diff --git a/orc-rt/include/orc-rt/support/bit.h b/orc-rt/include/orc-rt/support/bit.h
index 47cc3f91383df4..8d5fd69e013e41 100644
--- a/orc-rt/include/orc-rt/support/bit.h
+++ b/orc-rt/include/orc-rt/support/bit.h
@@ -17,7 +17,6 @@
 
 #include "orc-rt/support/Compiler.h"
 
-#include <cstddef>
 #include <cstdint>
 #include <limits>
 #include <type_traits>
@@ -50,6 +49,8 @@
 #endif
 #endif
 
+#include "Compiler.h"
+
 namespace orc_rt {
 
 enum class endian {
@@ -125,9 +126,31 @@ template <typename T, typename _ = std::enable_if_t<std::is_unsigned_v<T>>>
   return ZeroBits;
 }
 
-template <typename T, typename _ = std::enable_if_t<std::is_unsigned_v<T>>>
-[[nodiscard]] constexpr int bit_width(T x) noexcept {
-  return std::numeric_limits<T>::digits - countl_zero(x);
+/// Returns the number of bits needed to represent Value if Value is nonzero.
+/// Returns 0 otherwise.
+///
+/// Ex. bit_width(5) == 3.
+template <typename T> [[nodiscard]] int bit_width(T Value) {
+  static_assert(std::is_unsigned_v<T>,
+                "Only unsigned integral types are allowed.");
+  return std::numeric_limits<T>::digits - orc_rt::countl_zero(Value);
+}
+
+/// Returns the number of bits needed to represent Value if Value is nonzero.
+/// Returns 0 otherwise.
+///
+/// A constexpr version of bit_width.
+///
+/// Ex. bit_width_constexpr(5) == 3.
+template <typename T> [[nodiscard]] constexpr int bit_width_constexpr(T Value) {
+  static_assert(std::is_unsigned_v<T>,
+                "Only unsigned integral types are allowed.");
+  int Width = 0;
+  while (Value > 0) {
+    Value >>= 1;
+    ++Width;
+  }
+  return Width;
 }
 
 template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
diff --git a/orc-rt/lib/bedrock/CMakeLists.txt b/orc-rt/lib/bedrock/CMakeLists.txt
index 0d8e41d4633d86..5dc584bca9659e 100644
--- a/orc-rt/lib/bedrock/CMakeLists.txt
+++ b/orc-rt/lib/bedrock/CMakeLists.txt
@@ -9,7 +9,6 @@ set(ORC_RT_BEDROCK_SOURCES
   Session.cpp
   SimpleNativeMemoryMap.cpp
   SimpleSymbolTable.cpp
-  StandaloneMachOUnwindInfoRegistrar.cpp
   ThreadPoolRunner.cpp
   sps/AllSPSCI.cpp
   sps/CallSPSCI.cpp
@@ -18,7 +17,6 @@ set(ORC_RT_BEDROCK_SOURCES
   sps/NativeDylibManagerSPSCI.cpp
   sps/SimpleNativeMemoryMapSPSCI.cpp
   sps/SimpleRemoteCA.cpp
-  sps/StandaloneMachOUnwindInfoRegistrarSPSCI.cpp
   )
 
 # System implementations are composed, not merely selected: a target gets one
@@ -47,6 +45,8 @@ set(ORC_RT_BEDROCK_POSIX_SOURCES
 set(ORC_RT_BEDROCK_DARWIN_SOURCES
   sys/darwin/CPUFeatures.cpp
   sys/darwin/TargetTriple.cpp
+  StandaloneMachOUnwindInfoRegistrar.cpp
+  sps/StandaloneMachOUnwindInfoRegistrarSPSCI.cpp
 )
 
 set(ORC_RT_BEDROCK_LINUX_SOURCES
@@ -54,10 +54,9 @@ set(ORC_RT_BEDROCK_LINUX_SOURCES
   sys/linux/TargetTriple.cpp
 )
 
-# TODO: Windows has no counterparts for the sys/posix/ sources yet
-# (DynamicLibrary, Memory, PageSize, SocketHandle), so Windows builds are
-# incomplete.
 set(ORC_RT_BEDROCK_WINDOWS_SOURCES
+  sys/windows/DynamicLibrary.cpp
+  sys/windows/Memory.cpp
   sys/windows/CPUFeatures.cpp
   sys/windows/TargetTriple.cpp
 )
diff --git a/orc-rt/lib/bedrock/NativeDylibManager.cpp b/orc-rt/lib/bedrock/NativeDylibManager.cpp
index d26f92e24851ec..655ce25130f6eb 100644
--- a/orc-rt/lib/bedrock/NativeDylibManager.cpp
+++ b/orc-rt/lib/bedrock/NativeDylibManager.cpp
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "orc-rt/bedrock/NativeDylibManager.h"
+
 #include "orc-rt-internal/bedrock/sys/DynamicLibrary.h"
 #include "orc-rt/bedrock/Session.h"
 
@@ -20,15 +21,16 @@ Expected<std::unique_ptr<NativeDylibManager>>
 NativeDylibManager::Create(Session &S, SimpleSymbolTable &ST,
                            const char *InstanceName,
                            SimpleSymbolTable::MutatorFn AddInterface) {
-
   std::unique_ptr<NativeDylibManager> Instance(new NativeDylibManager(S));
 
   SimpleSymbolTable NDMST;
   if (auto Err = AddInterface(NDMST))
     return Err;
+
   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);
 
@@ -38,38 +40,79 @@ NativeDylibManager::Create(Session &S, SimpleSymbolTable &ST,
   return std::move(Instance);
 }
 
-void NativeDylibManager::load(OnLoadCompleteFn &&OnComplete, std::string Path) {
-  // Empty path -> global handle; no shutdown callback (RTLD_DEFAULT
-  // mustn't be dlclose'd).
-  if (Path.empty())
-    return OnComplete(sys::globalLookupHandle());
+void NativeDylibManager::load(OnLoadCompleteFn &&OnComplete,
+                              std::string Path) {
+  // Empty path means "global lookup scope".
+  if (Path.empty()) {
+    static DylibHandle GlobalHandle{DylibHandle::Kind::Global, nullptr};
+    return OnComplete(static_cast<void *>(&GlobalHandle));
+  }
 
   auto H = sys::loadLibrary(Path);
   if (!H)
     return OnComplete(H.takeError());
 
-  // Capture S by reference, rather than this, so that the callback remains
-  // valid even if the NativeDylibManager is destroyed prior to shutdown.
-  S.addOnShutdown([&S = this->S, Handle = *H]() {
-    if (auto Err = sys::unloadLibrary(Handle))
+  auto Handle = std::make_unique<DylibHandle>(
+      DylibHandle{DylibHandle::Kind::Library, *H});
+
+  DylibHandle *Dylib = Handle.get();
+  assert(Dylib && "failed to create dylib handle");
+  if (!Dylib)
+    return OnComplete(
+        make_error<StringError>("failed to create dylib handle"));
+
+  // Capture S by reference rather than this so the callback remains valid even
+  // if NativeDylibManager is destroyed prior to shutdown.
+  S.addOnShutdown([&S = this->S, Handle = std::move(Handle)]() mutable {
+    DylibHandle *Dylib = Handle.get();
+    assert(Dylib && "dylib handle unexpectedly null");
+    if (!Dylib)
+      return;
+
+    assert(Dylib->K == DylibHandle::Kind::Library &&
+           "global dylib handle must not be unloaded");
+    assert(Dylib->LibraryHandle && "invalid library handle");
+
+    if (auto Err = sys::unloadLibrary(Dylib->LibraryHandle))
       S.reportError(std::move(Err));
   });
-  OnComplete(std::move(H));
+
+  OnComplete(static_cast<void *>(Dylib));
 }
 
 void NativeDylibManager::lookup(OnLookupCompleteFn &&OnLookupComplete,
                                 void *Handle, SymbolLookupSet Symbols) {
+  DylibHandle *Dylib = static_cast<DylibHandle *>(Handle);
+
+  assert(Dylib && "invalid dylib handle");
+  if (!Dylib)
+    return OnLookupComplete(
+        make_error<StringError>("invalid dylib handle"));
+
   std::vector<std::string> Names;
   Names.reserve(Symbols.size());
   for (auto &S : Symbols)
     Names.push_back(std::move(S.first));
 
-  auto Addrs = sys::lookupLibrarySymbols(Handle, Names);
-
-  // Convert weak-missing entries (empty optional from lookupLibrarySymbols)
-  // to a present zero address. This matches the resolve semantics of
-  // llvm::orc::rt_bootstrap::SimpleExecutorDylibManager: an empty optional
-  // in the result signals a missing required symbol, while a missing
+  sys::SymbolLookupResult Addrs;
+
+  switch (Dylib->K) {
+  case DylibHandle::Kind::Global:
+    Addrs = sys::lookupGlobalSymbols(Names);
+    break;
+  case DylibHandle::Kind::Library:
+    assert(Dylib->LibraryHandle && "invalid library handle");
+    if (!Dylib->LibraryHandle)
+      return OnLookupComplete(
+          make_error<StringError>("invalid library handle"));
+    Addrs = sys::lookupLibrarySymbols(Dylib->LibraryHandle, Names);
+    break;
+  }
+
+  // Convert weak-missing entries (empty optional) to a present zero address.
+  // This matches the resolve semantics of
+  // llvm::orc::rt_bootstrap::SimpleExecutorDylibManager: an empty optional in
+  // the result signals a missing required symbol, while a missing
   // weakly-referenced symbol is reported as a zero address.
   for (size_t I = 0, E = Symbols.size(); I != E; ++I)
     if (!Addrs[I] && Symbols[I].second == WeaklyReferencedSymbol)
diff --git a/orc-rt/lib/bedrock/sps/AllSPSCI.cpp b/orc-rt/lib/bedrock/sps/AllSPSCI.cpp
index 0148f7615b47d3..76f29c8fb0bd28 100644
--- a/orc-rt/lib/bedrock/sps/AllSPSCI.cpp
+++ b/orc-rt/lib/bedrock/sps/AllSPSCI.cpp
@@ -27,7 +27,10 @@ Error addAll(SimpleSymbolTable &ST) {
                       addMemoryAccess,
                       addNativeDylibManager,
                       addSimpleNativeMemoryMap,
-                      addStandaloneMachOUnwindInfoRegistrar};
+                      #if defined(__APPLE__)
+                            addStandaloneMachOUnwindInfoRegistrar,
+                      #endif
+  };
 
   for (auto *Adder : Adders)
     if (auto Err = Adder(ST))
diff --git a/orc-rt/lib/bedrock/sys/posix/DynamicLibrary.cpp b/orc-rt/lib/bedrock/sys/posix/DynamicLibrary.cpp
index fbde604159d4e8..a5d75ba28df389 100644
--- a/orc-rt/lib/bedrock/sys/posix/DynamicLibrary.cpp
+++ b/orc-rt/lib/bedrock/sys/posix/DynamicLibrary.cpp
@@ -41,37 +41,45 @@ std::optional<const char *> toDLSymName(const std::string &Name) {
 
 } // namespace
 
-void *globalLookupHandle() { return RTLD_DEFAULT; }
-
-Expected<void *> loadLibrary(const std::string &Path) {
-  assert(!Path.empty() && "loadLibrary doesn't support empty paths");
-  void *H = dlopen(Path.c_str(), RTLD_LAZY | RTLD_LOCAL);
-  if (H == nullptr)
-    return make_error<StringError>((StringOutputStream()
-                                    << "error loading \"" << Path
-                                    << "\": " << dlerror())
-                                       .str());
-
-  return H;
+using DylibHandle = orc_rt::NativeDylibManager::DylibHandle;
+using SymbolLookupResult =
+        orc_rt::NativeDylibManager::SymbolLookupResult;
+
+orc_rt::Expected<orc_rt::NativeDylibManager::DylibHandle>
+hostOSLoadLibrary(const std::string &Path) {
+  assert(!Path.empty() && "hostOSLoadLibrary doesn't support empty paths");
+
+  void *Handle = dlopen(Path.c_str(), RTLD_LAZY | RTLD_LOCAL);
+  if (!Handle) {
+    std::ostringstream ErrMsg;
+    ErrMsg << "error loading \"" << Path << "\": " << dlerror();
+    return orc_rt::make_error<orc_rt::StringError>(ErrMsg.str());
+  }
+
+  return orc_rt::NativeDylibManager::DylibHandle{
+      orc_rt::NativeDylibManager::DylibHandle::Kind::Library, Handle};
 }
 
-Error unloadLibrary(void *Handle) {
-  if (dlclose(Handle) != 0)
-    return make_error<StringError>((StringOutputStream()
-                                    << "error unloading " << Handle << ": "
-                                    << dlerror())
-                                       .str());
-  return Error::success();
+orc_rt::Error
+unloadLibrary(const orc_rt::NativeDylibManager::DylibHandle &Handle) {
+  assert(Handle.K == orc_rt::NativeDylibManager::DylibHandle::Kind::Library &&
+         "global dylib handle must not be unloaded");
+  assert(Handle.LibraryHandle && "invalid library handle");
+
+  if (dlclose(Handle.LibraryHandle) != 0)
+    return orc_rt::make_error<orc_rt::StringError>(
+        (std::ostringstream()
+         << "error unloading " << Handle.LibraryHandle << ": " << dlerror())
+            .str());
+
+  return orc_rt::Error::success();
 }
 
-std::vector<std::optional<void *>>
-lookupLibrarySymbols(void *Handle, const std::vector<std::string> &Names) {
-  std::vector<std::optional<void *>> Result;
+NativeDylibManager::SymbolLookupResult
+hostOSLookup(void *Handle, const std::vector<std::string> &Names) {
+  NativeDylibManager::SymbolLookupResult Result;
   Result.reserve(Names.size());
-  // Reset dlerror so we can distinguish "dlsym returned null because the
-  // symbol is present at address 0" from "dlsym returned null because the
-  // symbol isn't in the library" via per-iteration dlerror() checks.
-  dlerror();
+
   for (const auto &Name : Names) {
     auto LookupName = toDLSymName(Name);
     if (!LookupName) {
@@ -86,7 +94,22 @@ lookupLibrarySymbols(void *Handle, const std::vector<std::string> &Names) {
     else
       Result.push_back(std::nullopt);
   }
+
   return Result;
 }
 
-} // namespace orc_rt::sys
+NativeDylibManager::SymbolLookupResult
+hostOSLibraryLookup(const NativeDylibManager::DylibHandle &Handle,
+                    const std::vector<std::string> &Names) {
+  assert(Handle.K == NativeDylibManager::DylibHandle::Kind::Library &&
+         "expected library dylib handle");
+  assert(Handle.LibraryHandle && "invalid library handle");
+
+  return hostOSLookup(Handle.LibraryHandle, Names);
+}
+
+NativeDylibManager::SymbolLookupResult
+hostOSGlobalLookup(const std::vector<std::string> &Names) {
+  return hostOSLookup(RTLD_DEFAULT, Names);
+}
+} // namespace
diff --git a/orc-rt/lib/bedrock/sys/windows/TargetTriple.cpp b/orc-rt/lib/bedrock/sys/windows/TargetTriple.cpp
index 465a24afc82f8a..7a5db97b98f7b1 100644
--- a/orc-rt/lib/bedrock/sys/windows/TargetTriple.cpp
+++ b/orc-rt/lib/bedrock/sys/windows/TargetTriple.cpp
@@ -10,6 +10,12 @@
 
 namespace orc_rt::sys {
 
-std::string detectTargetTriple() noexcept { return {}; }
+std::string detectTargetTriple() noexcept {
+#if defined(_M_X64)
+  return "x86_64-pc-windows-msvc";
+#else
+#error "Unsupported Windows architecture"
+#endif
+}
 
 } // namespace orc_rt::sys
diff --git a/orc-rt/test/CMakeLists.txt b/orc-rt/test/CMakeLists.txt
index 279f13ecc968ad..4d87bb7f09f12b 100644
--- a/orc-rt/test/CMakeLists.txt
+++ b/orc-rt/test/CMakeLists.txt
@@ -1,4 +1,7 @@
 include(OrcRTTesting)
+# The various addllvm functions turn these off.
+set(LLVM_REQUIRES_RTTI ON)
+set(LLVM_REQUIRES_EH ON)
 
 if (ORC_RT_LLVM_TOOLS_AVAILABLE)
   configure_lit_site_cfg(
diff --git a/orc-rt/test/regression/darwin/check-rt-process-info.test b/orc-rt/test/regression/darwin/check-rt-process-info.test
deleted file mode 100644
index 8df2c09477c890..00000000000000
--- a/orc-rt/test/regression/darwin/check-rt-process-info.test
+++ /dev/null
@@ -1,6 +0,0 @@
-# RUN: orc-rt-process-info-check --print-triple --print-cpu-features --print-page-size  \
-# RUN:   | FileCheck %s -DARCH=%target-arch -DVERSION=%macos-product-version
-
-# CHECK: [[ARCH]]-apple-macosx[[VERSION]]
-# CHECK-NEXT: {{4096|16384}}
-# CHECK-NEXT: {{^\+[a-z0-9_.]+(,\+[a-z0-9_.]+)*$}}
diff --git a/orc-rt/test/regression/darwin/lit.local.cfg b/orc-rt/test/regression/darwin/lit.local.cfg
deleted file mode 100644
index 4539e9a1b9bd72..00000000000000
--- a/orc-rt/test/regression/darwin/lit.local.cfg
+++ /dev/null
@@ -1,2 +0,0 @@
-if "system-darwin" not in config.available_features:
-  config.unsupported = True
\ No newline at end of file
diff --git a/orc-rt/test/regression/linux/check-rt-process-info.test b/orc-rt/test/regression/linux/check-rt-process-info.test
deleted file mode 100644
index 160be336d40cf2..00000000000000
--- a/orc-rt/test/regression/linux/check-rt-process-info.test
+++ /dev/null
@@ -1,5 +0,0 @@
-# RUN: orc-rt-process-info-check --print-triple --print-page-size \
-# RUN:   | FileCheck %s -DARCH=%target-arch
-
-# CHECK: {{^}}[[ARCH]]-{{.*}}-linux
-# CHECK-NEXT: {{4096|16384}}
diff --git a/orc-rt/test/regression/linux/lit.local.cfg b/orc-rt/test/regression/linux/lit.local.cfg
deleted file mode 100644
index e85a58569fbb67..00000000000000
--- a/orc-rt/test/regression/linux/lit.local.cfg
+++ /dev/null
@@ -1,2 +0,0 @@
-if "system-linux" not in config.available_features:
-  config.unsupported = True
\ No newline at end of file
diff --git a/orc-rt/test/unit/CMakeLists.txt b/orc-rt/test/unit/CMakeLists.txt
index f750799ad75bf1..ca2834be53b3b5 100644
--- a/orc-rt/test/unit/CMakeLists.txt
+++ b/orc-rt/test/unit/CMakeLists.txt
@@ -1,137 +1,247 @@
 add_custom_target(OrcRTUnitTests)
-set_target_properties(OrcRTUnitTests PROPERTIES FOLDER "orc-rt/Tests")
+set_target_properties(OrcRTUnitTests PROPERTIES
+  FOLDER "orc-rt/Tests"
+)
 
-if (NOT TARGET llvm_gtest)
-  message(WARNING "orc-rt unittests disabled due to GTest being unavailable; "
-                  "Try LLVM_INSTALL_GTEST=ON for the LLVM build")
-  return ()
-endif ()
+if(NOT TARGET llvm_gtest)
+  message(WARNING
+    "orc-rt unittests disabled due to GTest being unavailable; "
+    "try LLVM_INSTALL_GTEST=ON for the LLVM build")
+  return()
+endif()
 
-# Adds a unit test suite. Sources come first; LINK_LIBS names the object
-# libraries the suite links and must come last.
+# orc-rt tests exercise RTTI and exception handling explicitly.
+#
+# Set these before creating any unit-test targets so LLVM's test infrastructure
+# does not add /GR- or exception-disabling flags and then override them later.
+set(LLVM_REQUIRES_RTTI ON)
+set(LLVM_REQUIRES_EH ON)
+
+# Add an orc-rt unit-test suite.
+#
+# SOURCES
+#   Sources that are always part of the suite. Platform-specific sources are
+#   added afterwards with target_sources().
+#
+# LINK_LIBS
+#   Runtime object libraries required by the suite.
 function(add_orc_rt_unittest test_name)
-  cmake_parse_arguments(ARG "" "" "LINK_LIBS" ${ARGN})
-  add_unittest(OrcRTUnitTests ${test_name} ${ARG_UNPARSED_ARGUMENTS}
-    DISABLE_LLVM_LINK_LLVM_DYLIB)
-  target_compile_options(${test_name} PRIVATE ${ORC_RT_COMPILE_FLAGS})
+  cmake_parse_arguments(PARSE_ARGV 1 ARG
+    ""
+    ""
+    "SOURCES;LINK_LIBS"
+  )
+
+  if(ARG_UNPARSED_ARGUMENTS)
+    message(FATAL_ERROR
+      "Unknown arguments to add_orc_rt_unittest(${test_name}): "
+      "${ARG_UNPARSED_ARGUMENTS}")
+  endif()
+
+  if(NOT ARG_SOURCES)
+    message(FATAL_ERROR
+      "add_orc_rt_unittest(${test_name}) requires SOURCES")
+  endif()
+
+  add_unittest(OrcRTUnitTests ${test_name}
+    ${ARG_SOURCES}
+    DISABLE_LLVM_LINK_LLVM_DYLIB
+  )
+
+  target_compile_options(${test_name}
+    PRIVATE
+      ${ORC_RT_COMPILE_FLAGS}
+  )
+
   # Shared test helpers (CommonTestUtils.h, DirectCaller.h, ...) live at the
-  # root of this directory, so tests in the layer subdirectories can include
-  # them by bare name.
-  target_include_directories(${test_name} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
-  target_link_libraries(${test_name} PRIVATE ${ARG_LINK_LIBS})
+  # root of this directory, so tests in subdirectories can include them by
+  # bare name.
+  target_include_directories(${test_name}
+    PRIVATE
+      ${CMAKE_CURRENT_SOURCE_DIR}
+  )
+
+  if(ARG_LINK_LIBS)
+    target_link_libraries(${test_name}
+      PRIVATE
+        ${ARG_LINK_LIBS}
+    )
+  endif()
 endfunction()
 
-# SupportTests links the Support objects and nothing else, so a new
-# support-to-bedrock dependency shows up here as a link error rather than going
-# unnoticed. BedrockTests links both, Bedrock being a Support client.
+
+#==============================================================================
+# Support tests
+#==============================================================================
+
+# SupportTests deliberately links only the Support objects. If Support acquires
+# an accidental dependency on Bedrock it should show up here as a link failure.
 add_orc_rt_unittest(SupportTests
-  support/AllocActionTest.cpp
-  support/BitmaskEnumTest.cpp
-  support/CAPICompileTest.c
-  support/CCallbackTest.cpp
-  support/CallableTraitsHelperTest.cpp
-  support/CompilerTest.cpp
-  support/EndianTest.cpp
-  support/ErrorCAPITest.cpp
-  support/ErrorExceptionInteropTest.cpp
-  support/ErrorTest.cpp
-  support/ExecutorAddressTest.cpp
-  support/IntervalMapTest.cpp
-  support/IntervalSetTest.cpp
-  support/LockedAccessTest.cpp
-  support/LoggingTest.cpp
-  support/MacroUtilsTest.cpp
-  support/ManglingTest.cpp
-  support/MemoryFlagsTest.cpp
-  support/ProxyTest.cpp
-  support/RTTICrossDylibTest.cpp
-  support/RTTITest.cpp
-  support/StringExtrasTest.cpp
-  support/StringPoolTest.cpp
-  support/WrapperFunctionBufferTest.cpp
-  support/bind-test.cpp
-  support/bit-test.cpp
-  support/iterator_range-test.cpp
-  support/move_only_function-test.cpp
-  support/scope_exit-test.cpp
-  support/span-test.cpp
-
-  support/sps/SPSAllocActionTest.cpp
-  support/sps/SPSMemoryFlagsTest.cpp
-  support/sps/SPSWrapperFunctionBufferTest.cpp
-  support/sps/SPSWrapperFunctionTest.cpp
-  support/sps/SimplePackedSerializationTest.cpp
-
-  support/sys/ErrnoTest.cpp
-
-  tools/OptionParserTest.cpp
-
-  LINK_LIBS orc-rt-support-objects
+  SOURCES
+    support/AllocActionTest.cpp
+    support/BitmaskEnumTest.cpp
+    support/CAPICompileTest.c
+    support/CCallbackTest.cpp
+    support/CallableTraitsHelperTest.cpp
+    support/CompilerTest.cpp
+    support/EndianTest.cpp
+    support/ErrorCAPITest.cpp
+    support/ErrorExceptionInteropTest.cpp
+    support/ErrorTest.cpp
+    support/ExecutorAddressTest.cpp
+    support/IntervalMapTest.cpp
+    support/IntervalSetTest.cpp
+    support/LockedAccessTest.cpp
+    support/LoggingTest.cpp
+    support/MacroUtilsTest.cpp
+    support/ManglingTest.cpp
+    support/MemoryFlagsTest.cpp
+    support/ProxyTest.cpp
+    support/RTTICrossDylibTest.cpp
+    support/RTTITest.cpp
+    support/StringExtrasTest.cpp
+    support/StringPoolTest.cpp
+    support/WrapperFunctionBufferTest.cpp
+    support/bind-test.cpp
+    support/bit-test.cpp
+    support/iterator_range-test.cpp
+    support/move_only_function-test.cpp
+    support/scope_exit-test.cpp
+    support/span-test.cpp
+
+    support/sps/SPSAllocActionTest.cpp
+    support/sps/SPSMemoryFlagsTest.cpp
+    support/sps/SPSWrapperFunctionBufferTest.cpp
+    support/sps/SPSWrapperFunctionTest.cpp
+    support/sps/SimplePackedSerializationTest.cpp
+
+    tools/OptionParserTest.cpp
+
+  LINK_LIBS
+    orc-rt-support-objects
+)
+
+# Errno.h currently has a POSIX implementation only.
+if(APPLE OR CMAKE_SYSTEM_NAME STREQUAL "Linux")
+  target_sources(SupportTests
+    PRIVATE
+      support/sys/ErrnoTest.cpp
   )
+endif()
+
 
-# Per-system test helpers, composed the way lib/ composes its per-system
-# implementations; see the note in lib/bedrock/CMakeLists.txt. Tests of portable
-# APIs stay in the shared list and reach the system through these.
-set(ORC_RT_BEDROCK_TEST_POSIX_SOURCES
-  bedrock/sys/posix/SocketTestUtils.cpp
+#==============================================================================
+# Bedrock tests
+#==============================================================================
+
+add_orc_rt_unittest(BedrockTests
+  SOURCES
+    bedrock/BootstrapInfoTest.cpp
+    bedrock/ExecutorProcessInfoTest.cpp
+    bedrock/InProcessControllerAccessTest.cpp
+    bedrock/NativeDylibManagerTest.cpp
+    bedrock/QueueingRunnerTest.cpp
+    bedrock/SessionTest.cpp
+    bedrock/SimpleNativeMemoryMapTest.cpp
+    bedrock/SimpleSymbolTableTest.cpp
+    bedrock/TaskGroupTest.cpp
+    bedrock/ThreadPoolRunnerTest.cpp
+
+    bedrock/sps/CallSPSCITest.cpp
+    bedrock/sps/MemoryAccessSPSCITest.cpp
+    bedrock/sps/NativeDylibManagerSPSCITest.cpp
+    bedrock/sps/SimpleNativeMemoryMapSPSCITest.cpp
+    bedrock/sps/SimpleRemoteCATest.cpp
+
+    bedrock/sys/CPUFeaturesTest.cpp
+    bedrock/sys/TargetTripleTest.cpp
+
+  LINK_LIBS
+    orc-rt-bedrock-objects
+    orc-rt-support-objects
 )
 
-if (APPLE OR CMAKE_SYSTEM_NAME STREQUAL "Linux")
-  set(ORC_RT_BEDROCK_TEST_SYS_SOURCES ${ORC_RT_BEDROCK_TEST_POSIX_SOURCES})
-else()
-  # No list yet, so tests needing a socket will fail to link.
-  set(ORC_RT_BEDROCK_TEST_SYS_SOURCES)
+# POSIX-specific test support.
+#
+# SocketHandleTest uses SocketTestUtils, for which there is currently only a
+# POSIX implementation.
+if(APPLE OR CMAKE_SYSTEM_NAME STREQUAL "Linux")
+  target_sources(BedrockTests
+    PRIVATE
+      bedrock/SocketHandleTest.cpp
+      bedrock/sys/posix/SocketTestUtils.cpp
+  )
 endif()
 
-add_orc_rt_unittest(BedrockTests
-  bedrock/BootstrapInfoTest.cpp
-  bedrock/ExecutorProcessInfoTest.cpp
-  bedrock/InProcessControllerAccessTest.cpp
-  bedrock/NativeDylibManagerTest.cpp
-  bedrock/QueueingRunnerTest.cpp
-  bedrock/SessionTest.cpp
-  bedrock/SimpleNativeMemoryMapTest.cpp
-  bedrock/SimpleSymbolTableTest.cpp
-  bedrock/SocketHandleTest.cpp
-  bedrock/StandaloneMachOUnwindInfoRegistrarTest.cpp
-  bedrock/TaskGroupTest.cpp
-  bedrock/ThreadPoolRunnerTest.cpp
-
-  bedrock/sps/CallSPSCITest.cpp
-  bedrock/sps/MemoryAccessSPSCITest.cpp
-  bedrock/sps/NativeDylibManagerSPSCITest.cpp
-  bedrock/sps/SimpleNativeMemoryMapSPSCITest.cpp
-  bedrock/sps/SimpleRemoteCATest.cpp
-
-  bedrock/sys/CPUFeaturesTest.cpp
-  bedrock/sys/TargetTripleTest.cpp
-
-  ${ORC_RT_BEDROCK_TEST_SYS_SOURCES}
-
-  LINK_LIBS orc-rt-bedrock-objects orc-rt-support-objects
+# Mach-O unwind registration is Darwin-specific.
+if(APPLE)
+  target_sources(BedrockTests
+    PRIVATE
+      bedrock/StandaloneMachOUnwindInfoRegistrarTest.cpp
   )
+endif()
+
 
-# Build a shared library for NativeDylibManager tests.
+#==============================================================================
+# NativeDylibManager test library
+#==============================================================================
+
+# A real shared library used by NativeDylibManagerTest.
 add_library(NativeDylibManagerTestLib SHARED
-  Inputs/NativeDylibManagerTestLib.cpp)
+  Inputs/NativeDylibManagerTestLib.cpp
+)
+
 set_target_properties(NativeDylibManagerTestLib PROPERTIES
-  PREFIX "")
-target_compile_definitions(BedrockTests PRIVATE
-  "NDM_TEST_LIB_PATH=\"$<TARGET_FILE:NativeDylibManagerTestLib>\"")
-add_dependencies(BedrockTests NativeDylibManagerTestLib)
-
-# Build a shared library for RTTICrossDylibTest. It links its own copy of the
-# runtime objects, giving it a LibraryID distinct from SupportTests's, so the
-# test exercises RTTI identity across a real library boundary rather than
-# simulating one within a single binary. SupportTests links it directly, the
-# same way any other consumer of orc-rt would.
+  PREFIX ""
+  FOLDER "orc-rt/Tests"
+)
+
+target_compile_options(NativeDylibManagerTestLib
+  PRIVATE
+    ${ORC_RT_COMPILE_FLAGS}
+)
+
+target_compile_definitions(BedrockTests
+  PRIVATE
+    "NDM_TEST_LIB_PATH=\"$<TARGET_FILE:NativeDylibManagerTestLib>\""
+)
+
+add_dependencies(BedrockTests
+  NativeDylibManagerTestLib
+)
+
+
+#==============================================================================
+# Cross-dylib RTTI test library
+#==============================================================================
+
+# RTTICrossDylibTestLib links its own copy of the runtime objects, giving it a
+# LibraryID distinct from SupportTests's. This exercises RTTI identity across a
+# real shared-library boundary rather than simulating one inside one binary.
 add_library(RTTICrossDylibTestLib SHARED
-  Inputs/RTTICrossDylibTestLib.cpp)
+  Inputs/RTTICrossDylibTestLib.cpp
+)
+
 set_target_properties(RTTICrossDylibTestLib PROPERTIES
   PREFIX ""
   CXX_VISIBILITY_PRESET hidden
-  VISIBILITY_INLINES_HIDDEN ON)
-target_compile_options(RTTICrossDylibTestLib PRIVATE ${ORC_RT_COMPILE_FLAGS})
+  VISIBILITY_INLINES_HIDDEN ON
+  WINDOWS_EXPORT_ALL_SYMBOLS ON
+  FOLDER "orc-rt/Tests"
+)
+
+target_compile_options(RTTICrossDylibTestLib
+  PRIVATE
+    ${ORC_RT_COMPILE_FLAGS}
+)
+
 target_link_libraries(RTTICrossDylibTestLib
-  PRIVATE orc-rt-bedrock-objects orc-rt-support-objects)
-target_link_libraries(SupportTests PRIVATE RTTICrossDylibTestLib)
+  PRIVATE
+    orc-rt-bedrock-objects
+    orc-rt-support-objects
+)
+
+target_link_libraries(SupportTests
+  PRIVATE
+    RTTICrossDylibTestLib
+)
diff --git a/orc-rt/test/unit/Inputs/RTTICrossDylibTestLib.cpp b/orc-rt/test/unit/Inputs/RTTICrossDylibTestLib.cpp
index a3612e75bb04ec..ab8d16f5f3a0ae 100644
--- a/orc-rt/test/unit/Inputs/RTTICrossDylibTestLib.cpp
+++ b/orc-rt/test/unit/Inputs/RTTICrossDylibTestLib.cpp
@@ -7,7 +7,7 @@
 #include "RTTICrossDylibTestError.h"
 
 #if defined(_WIN32)
-#define TEST_EXPORT __declspec(dllexport)
+#define TEST_EXPORT
 #else
 #define TEST_EXPORT __attribute__((visibility("default")))
 #endif
diff --git a/orc-rt/test/unit/bedrock/ExecutorProcessInfoTest.cpp b/orc-rt/test/unit/bedrock/ExecutorProcessInfoTest.cpp
index fb9faa5641f730..0c604a9b817f0c 100644
--- a/orc-rt/test/unit/bedrock/ExecutorProcessInfoTest.cpp
+++ b/orc-rt/test/unit/bedrock/ExecutorProcessInfoTest.cpp
@@ -14,8 +14,6 @@
 #include "orc-rt/support/bit.h"
 #include "gtest/gtest.h"
 
-#include <unistd.h>
-
 using namespace orc_rt;
 
 TEST(ExecutorProcessInfoTest, DetectSucceeds) {
@@ -34,11 +32,6 @@ TEST(ExecutorProcessInfoTest, DetectPageSizeAtLeast4096) {
   EXPECT_GE(EPI.pageSize(), 4096U);
 }
 
-TEST(ExecutorProcessInfoTest, DetectPageSizeMatchesSysconf) {
-  auto EPI = cantFail(ExecutorProcessInfo::Detect());
-  EXPECT_EQ(EPI.pageSize(), static_cast<size_t>(sysconf(_SC_PAGESIZE)));
-}
-
 TEST(ExecutorProcessInfoTest, ConstructWithExplicitValues) {
   ExecutorProcessInfo EPI("x86_64-unknown-linux-gnu", 4096, "+x,+a,+b");
   EXPECT_EQ(EPI.targetTriple(), "x86_64-unknown-linux-gnu");
diff --git a/orc-rt/test/unit/bedrock/InProcessControllerAccessTest.cpp b/orc-rt/test/unit/bedrock/InProcessControllerAccessTest.cpp
index 71b155b1030fa4..f0f53111da72f7 100644
--- a/orc-rt/test/unit/bedrock/InProcessControllerAccessTest.cpp
+++ b/orc-rt/test/unit/bedrock/InProcessControllerAccessTest.cpp
@@ -26,6 +26,11 @@ using namespace orc_rt;
 
 namespace {
 
+orc_rt_ControllerHandlerTag testHandlerTag() {
+  return reinterpret_cast<orc_rt_ControllerHandlerTag>(
+      std::uintptr_t{0xdeadbeef});
+}
+
 // A minimal stand-in for llvm::orc::InProcessEPC. Registers itself on the
 // Connection during OnConnect, exposes hooks for tests to drive cross-calls
 // in either direction, and tears the connection down on destruction.
@@ -192,8 +197,7 @@ TEST(InProcessControllerAccessTest, OnConnectFailureIsReportedAndDetaches) {
         if (const char *Msg = R.getOutOfBandError())
           CallErr = Msg;
       },
-      reinterpret_cast<orc_rt_ControllerHandlerTag>(0xdeadbeef),
-      WrapperFunctionBuffer::copyFrom("x", 1));
+      testHandlerTag(), WrapperFunctionBuffer::copyFrom("x", 1));
 
   ASSERT_TRUE(CallErr);
   EXPECT_EQ(*CallErr, "no controller attached");
@@ -220,8 +224,7 @@ TEST(InProcessControllerAccessTest, CallControllerSuccess) {
             << "Unexpected out-of-band error: " << R.getOutOfBandError();
         Result = std::string(R.data(), R.size());
       },
-      reinterpret_cast<orc_rt_ControllerHandlerTag>(0xdeadbeef),
-      WrapperFunctionBuffer::copyFrom("hello", 5));
+      testHandlerTag(), WrapperFunctionBuffer::copyFrom("hello", 5));
 
   ASSERT_TRUE(Result);
   EXPECT_EQ(*Result, "hello");
@@ -248,8 +251,7 @@ TEST(InProcessControllerAccessTest, CallControllerOutOfBandError) {
         if (const char *Msg = R.getOutOfBandError())
           ErrMsg = Msg;
       },
-      reinterpret_cast<orc_rt_ControllerHandlerTag>(0xdeadbeef),
-      WrapperFunctionBuffer::copyFrom("payload", 7));
+      testHandlerTag(), WrapperFunctionBuffer::copyFrom("payload", 7));
 
   ASSERT_TRUE(ErrMsg);
   EXPECT_EQ(*ErrMsg, "simulated failure");
@@ -274,8 +276,7 @@ TEST(InProcessControllerAccessTest, DisconnectDrainsPendingCalls) {
         if (const char *Msg = R.getOutOfBandError())
           ErrMsg = Msg;
       },
-      reinterpret_cast<orc_rt_ControllerHandlerTag>(0xdeadbeef),
-      WrapperFunctionBuffer::copyFrom("payload", 7));
+      testHandlerTag(), WrapperFunctionBuffer::copyFrom("payload", 7));
 
   ASSERT_FALSE(ErrMsg) << "OnComplete fired prematurely";
 
@@ -342,6 +343,6 @@ TEST(InProcessControllerAccessTest, BootstrapValuesExposeSubtargetFeatures) {
                          "orc-rt.Executor.SubtargetFeatures")
                        Features = std::string(Bytes, Size);
                  });
-
+  ASSERT_TRUE(Features);
   EXPECT_EQ(*Features, S.processInfo().targetCPUFeatures());
 }
diff --git a/orc-rt/test/unit/bedrock/sps/SimpleRemoteCATest.cpp b/orc-rt/test/unit/bedrock/sps/SimpleRemoteCATest.cpp
index 879f415c5b4331..7ef251da25db78 100644
--- a/orc-rt/test/unit/bedrock/sps/SimpleRemoteCATest.cpp
+++ b/orc-rt/test/unit/bedrock/sps/SimpleRemoteCATest.cpp
@@ -43,13 +43,14 @@ class TestCA : public SimpleRemoteCA {
   using SimpleRemoteCA::encodeResult;
   using SimpleRemoteCA::encodeSetup;
   using SimpleRemoteCA::handleMessage;
-  using SimpleRemoteCA::Opcode;
   using SimpleRemoteCA::PendingCallsMap;
   using SimpleRemoteCA::registerCall;
-  using SimpleRemoteCA::ResultKind;
   using SimpleRemoteCA::takeAllCalls;
   using SimpleRemoteCA::takeCall;
 
+  using Opcode = SimpleRemoteCA::Opcode;
+  using ResultKind = SimpleRemoteCA::ResultKind;
+
   TestCA(Session &S, TestCA **Self = nullptr) : SimpleRemoteCA(S) {
     if (Self)
       *Self = this;
diff --git a/orc-rt/test/unit/support/CallableTraitsHelperTest.cpp b/orc-rt/test/unit/support/CallableTraitsHelperTest.cpp
index e04f10328b1c31..a68c329ba915bd 100644
--- a/orc-rt/test/unit/support/CallableTraitsHelperTest.cpp
+++ b/orc-rt/test/unit/support/CallableTraitsHelperTest.cpp
@@ -21,8 +21,7 @@ using namespace orc_rt;
 static void freeVoidVoid() {}
 
 TEST(CallableTraitsHelperTest, FreeVoidVoid) {
-  (void)freeVoidVoid;
-  typedef CallableArgInfo<decltype(freeVoidVoid)> CAI;
+  using CAI = CallableArgInfo<decltype(freeVoidVoid)>;
   static_assert(std::is_void_v<CAI::return_type>);
   static_assert(std::is_same_v<CAI::args_tuple_type, std::tuple<>>);
 }
@@ -30,41 +29,40 @@ TEST(CallableTraitsHelperTest, FreeVoidVoid) {
 static int freeBinaryOp(int, float) { return 0; }
 
 TEST(CallableTraitsHelperTest, FreeBinaryOp) {
-  (void)freeBinaryOp;
-  typedef CallableArgInfo<decltype(freeBinaryOp)> CAI;
+  using CAI = CallableArgInfo<decltype(freeBinaryOp)>;
   static_assert(std::is_same_v<CAI::return_type, int>);
   static_assert(std::is_same_v<CAI::args_tuple_type, std::tuple<int, float>>);
 }
 
 TEST(CallableTraitsHelperTest, VoidVoidObj) {
   auto VoidVoid = []() {};
-  typedef CallableArgInfo<decltype(VoidVoid)> CAI;
+  using CAI = CallableArgInfo<decltype(VoidVoid)>;
   static_assert(std::is_void_v<CAI::return_type>);
   static_assert(std::is_same_v<CAI::args_tuple_type, std::tuple<>>);
 }
 
 TEST(CallableTraitsHelperTest, BinaryOpObj) {
   auto BinaryOp = [](int X, float Y) -> int { return X + Y; };
-  typedef CallableArgInfo<decltype(BinaryOp)> CAI;
+  using CAI = CallableArgInfo<decltype(BinaryOp)>;
   static_assert(std::is_same_v<CAI::return_type, int>);
   static_assert(std::is_same_v<CAI::args_tuple_type, std::tuple<int, float>>);
 }
 
 TEST(CallableTraitsHelperTest, PreservesLValueRef) {
   auto RefOp = [](int &) {};
-  typedef CallableArgInfo<decltype(RefOp)> CAI;
+  using CAI = CallableArgInfo<decltype(RefOp)>;
   static_assert(std::is_same_v<CAI::args_tuple_type, std::tuple<int &>>);
 }
 
 TEST(CallableTraitsHelperTest, PreservesLValueRefConstness) {
   auto RefOp = [](const int &) {};
-  typedef CallableArgInfo<decltype(RefOp)> CAI;
+  using CAI = CallableArgInfo<decltype(RefOp)>;
   static_assert(std::is_same_v<CAI::args_tuple_type, std::tuple<const int &>>);
 }
 
 TEST(CallableTraitsHelperTest, PreservesRValueRef) {
   auto RefOp = [](int &&) {};
-  typedef CallableArgInfo<decltype(RefOp)> CAI;
+  using CAI = CallableArgInfo<decltype(RefOp)>;
   static_assert(std::is_same_v<CAI::args_tuple_type, std::tuple<int &&>>);
 }
 
@@ -136,7 +134,7 @@ TEST(CallableTraitsHelperTest, AbominableFunctionTypeIsConst) {
 static void freeVoidVoidNoexcept() noexcept {}
 
 TEST(CallableTraitsHelperTest, FreeFunctionNoexcept) {
-  (void)freeVoidVoidNoexcept;
+  (void)freeVoidVoidNoexcept();
   static_assert(!CallableArgInfo<decltype(freeVoidVoid)>::is_noexcept);
   static_assert(CallableArgInfo<decltype(freeVoidVoidNoexcept)>::is_noexcept);
 }
diff --git a/orc-rt/test/unit/support/bit-test.cpp b/orc-rt/test/unit/support/bit-test.cpp
index f2ca32b89edc92..41e31c0d680da9 100644
--- a/orc-rt/test/unit/support/bit-test.cpp
+++ b/orc-rt/test/unit/support/bit-test.cpp
@@ -22,6 +22,11 @@
 #define IS_LITTLE_ENDIAN
 #endif
 
+#if !defined(BYTE_ORDER) && defined(_MSC_VER)
+#define IS_LITTLE_ENDIAN
+#endif
+
+
 using namespace orc_rt;
 
 TEST(BitTest, endian) {
diff --git a/orc-rt/test/unit/tools/OptionParserTest.cpp b/orc-rt/test/unit/tools/OptionParserTest.cpp
index 8af7b1d122059f..04496c92dc9314 100644
--- a/orc-rt/test/unit/tools/OptionParserTest.cpp
+++ b/orc-rt/test/unit/tools/OptionParserTest.cpp
@@ -125,9 +125,8 @@ TEST_F(OptionParserTest, ParseAsMainWithRegularArgsSucceeds) {
   EXPECT_EQ(Parser.positionals()[1], "1234");
 }
 
-TEST_F(OptionParserTest, ParseAsMainWithEmplyListFails) {
-  const char *Argv[] = {};
-  auto Err = Parser.parseAsMainArgs(0, const_cast<char **>(Argv));
+TEST_F(OptionParserTest, ParseAsMainWithEmptyListFails) {
+  auto Err = Parser.parseAsMainArgs(0, nullptr);
 
   EXPECT_TRUE(!!Err);
   consumeError(std::move(Err));



More information about the llvm-commits mailing list