[llvm] [orc-rt] Implement Windows target triple detection (PR #224514)

Jared Wyles via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 21 01:11:03 PDT 2026


https://github.com/jaredwy updated https://github.com/llvm/llvm-project/pull/224514

>From 159d1a3f1262542e0814867028a756d5100fb149 Mon Sep 17 00:00:00 2001
From: Jared Wyles <jared.wyles at gmail.com>
Date: Fri, 18 Sep 2026 20:42:56 +1000
Subject: [PATCH 1/2] [orc-rt] Changes to enable Windows compilation

---
 orc-rt/CMakeLists.txt                         | 36 ++++++++++++---
 orc-rt/include/orc-rt-c/support/Compiler.h    | 22 ++++++----
 .../orc-rt-internal/tools/OptionParser.h      | 28 ++++++------
 orc-rt/include/orc-rt/support/BitmaskEnum.h   |  7 +--
 orc-rt/include/orc-rt/support/Error.h         |  2 +-
 .../include/orc-rt/support/ExecutorAddress.h  |  2 +-
 orc-rt/include/orc-rt/support/bit.h           | 15 ++++++-
 orc-rt/lib/bedrock/CMakeLists.txt             |  9 ++--
 orc-rt/lib/bedrock/sps/AllSPSCI.cpp           | 16 ++++---
 .../bedrock/sys/windows/DynamicLibrary.cpp    | 28 ++++++++++++
 orc-rt/lib/bedrock/sys/windows/Memory.cpp     | 29 ++++++++++++
 orc-rt/test/unit/CMakeLists.txt               | 44 ++++++++++++++++---
 .../unit/Inputs/RTTICrossDylibTestLib.cpp     | 14 +++---
 .../test/unit/Inputs/RTTICrossDylibTestLib.h  | 20 +++++++--
 .../unit/bedrock/ExecutorProcessInfoTest.cpp  | 13 ++++--
 .../bedrock/InProcessControllerAccessTest.cpp | 16 +++----
 .../unit/bedrock/NativeDylibManagerTest.cpp   |  3 +-
 .../bedrock/SimpleNativeMemoryMapTest.cpp     |  2 +
 .../sps/NativeDylibManagerSPSCITest.cpp       |  3 +-
 .../sps/SimpleNativeMemoryMapSPSCITest.cpp    |  3 +-
 .../unit/bedrock/sps/SimpleRemoteCATest.cpp   |  5 ++-
 .../unit/bedrock/sys/TargetTripleTest.cpp     |  4 +-
 .../unit/support/CallableTraitsHelperTest.cpp | 10 ++---
 .../support/ErrorExceptionInteropTest.cpp     |  4 +-
 orc-rt/test/unit/support/bit-test.cpp         |  4 ++
 orc-rt/test/unit/tools/OptionParserTest.cpp   |  6 +--
 26 files changed, 249 insertions(+), 96 deletions(-)
 create mode 100644 orc-rt/lib/bedrock/sys/windows/DynamicLibrary.cpp
 create mode 100644 orc-rt/lib/bedrock/sys/windows/Memory.cpp

diff --git a/orc-rt/CMakeLists.txt b/orc-rt/CMakeLists.txt
index 75050fd2802fc..da07db5ba9441 100644
--- a/orc-rt/CMakeLists.txt
+++ b/orc-rt/CMakeLists.txt
@@ -88,16 +88,38 @@ 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)
+  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()
 
-if(ORC_RT_ENABLE_EXCEPTIONS)
-  list(APPEND ORC_RT_COMPILE_FLAGS -fexceptions)
-else()
-  list(APPEND ORC_RT_COMPILE_FLAGS -fno-exceptions)
+# --- Windows compatibility ---
+if(WIN32)
+  add_compile_definitions(
+    NOMINMAX
+    WIN32_LEAN_AND_MEAN
+  )
 endif()
 
 # --- Logging ---
diff --git a/orc-rt/include/orc-rt-c/support/Compiler.h b/orc-rt/include/orc-rt-c/support/Compiler.h
index c576a2fd73240..05bd27d216828 100644
--- a/orc-rt/include/orc-rt-c/support/Compiler.h
+++ b/orc-rt/include/orc-rt-c/support/Compiler.h
@@ -28,13 +28,21 @@
    This wraps __has_builtin rather than supplying a fallback definition for it.
    __has_builtin is a reserved identifier, and defining one from a public header
    can collide with the compiler's own definition or with other libraries that
-   the client also includes. */
+   the client also includes */
 #if defined(__has_builtin)
 #define ORC_RT_HAS_BUILTIN(X) __has_builtin(X)
 #else
 #define ORC_RT_HAS_BUILTIN(X) 0
 #endif
 
+/* MSVC diagnoses uses of unavailable __has_attribute expressions, so wrap it
+   in the same way as __has_builtin. */
+#if defined(__has_attribute)
+#define ORC_RT_HAS_ATTRIBUTE(X) __has_attribute(X)
+#else
+#define ORC_RT_HAS_ATTRIBUTE(X) 0
+#endif
+
 /* Helper to promote strict prototype warnings to errors */
 #ifdef __clang__
 #define ORC_RT_C_STRICT_PROTOTYPES_BEGIN                                       \
@@ -63,13 +71,11 @@
    runtime's binary interface: exported from the runtime when it is built as a
    shared library, and imported by consumers of that library.
 
-   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)
+TODO: Add the Windows __declspec(dllexport) / __declspec(dllimport) and
+static-build cases once there is a shared-library build to exercise them. */
+#if ORC_RT_HAS_ATTRIBUTE(visibility)
 #define ORC_RT_C_EXPORT __attribute__((visibility("default")))
-#endif
-
-#if !defined(ORC_RT_C_EXPORT)
+#else
 #define ORC_RT_C_EXPORT
 #endif
 
@@ -77,7 +83,7 @@
    compiler should not issue unused-symbol warnings for it. */
 #if defined(__cplusplus)
 #define ORC_RT_MAYBE_UNUSED [[maybe_unused]]
-#elif defined(__has_attribute) && __has_attribute(unused)
+#elif ORC_RT_HAS_ATTRIBUTE(unused)
 #define ORC_RT_MAYBE_UNUSED __attribute__((unused))
 #else
 #define ORC_RT_MAYBE_UNUSED
diff --git a/orc-rt/include/orc-rt-internal/tools/OptionParser.h b/orc-rt/include/orc-rt-internal/tools/OptionParser.h
index ddc50f46b0613..cd30b313ab841 100644
--- a/orc-rt/include/orc-rt-internal/tools/OptionParser.h
+++ b/orc-rt/include/orc-rt-internal/tools/OptionParser.h
@@ -93,21 +93,19 @@ 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) -> 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) +
+                                          "'");
+         }});
     return *this;
   }
 
diff --git a/orc-rt/include/orc-rt/support/BitmaskEnum.h b/orc-rt/include/orc-rt/support/BitmaskEnum.h
index 85a863f99d6c2..4344802077408 100644
--- a/orc-rt/include/orc-rt/support/BitmaskEnum.h
+++ b/orc-rt/include/orc-rt/support/BitmaskEnum.h
@@ -112,9 +112,10 @@ constexpr std::underlying_type_t<E> bitmask_enum_mask() noexcept {
   constexpr int Width = bit_width(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
-             ? static_cast<UnderlyingTy>(~UnderlyingTy(0))
-             : static_cast<UnderlyingTy>((UnderlyingTy(1) << Width) - 1);
+  if constexpr (Width == std::numeric_limits<UnderlyingTy>::digits)
+    return static_cast<UnderlyingTy>(~UnderlyingTy(0));
+  else
+    return static_cast<UnderlyingTy>((UnderlyingTy(1) << Width) - 1);
 }
 
 template <typename E>
diff --git a/orc-rt/include/orc-rt/support/Error.h b/orc-rt/include/orc-rt/support/Error.h
index 02f876455905d..3ff55b8cac74c 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 c3603a1708f66..25b942571ac68 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 47cc3f91383df..ee3218e7684bc 100644
--- a/orc-rt/include/orc-rt/support/bit.h
+++ b/orc-rt/include/orc-rt/support/bit.h
@@ -125,9 +125,20 @@ template <typename T, typename _ = std::enable_if_t<std::is_unsigned_v<T>>>
   return ZeroBits;
 }
 
+/// Returns the number of bits needed to represent Value if Value is nonzero.
+/// Returns 0 otherwise.
+///
+/// Ex. bit_width(5) == 3.
 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);
+[[nodiscard]] constexpr int bit_width(T Value) noexcept {
+  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 0d8e41d4633d8..5dc584bca9659 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/sps/AllSPSCI.cpp b/orc-rt/lib/bedrock/sps/AllSPSCI.cpp
index 0148f7615b47d..5dc1fb32f5391 100644
--- a/orc-rt/lib/bedrock/sps/AllSPSCI.cpp
+++ b/orc-rt/lib/bedrock/sps/AllSPSCI.cpp
@@ -22,12 +22,16 @@ namespace orc_rt::sps_ci {
 
 Error addAll(SimpleSymbolTable &ST) {
   using AdderFn = Error (*)(SimpleSymbolTable &);
-  AdderFn Adders[] = {addCall,
-                      addGDBJITRegistrar,
-                      addMemoryAccess,
-                      addNativeDylibManager,
-                      addSimpleNativeMemoryMap,
-                      addStandaloneMachOUnwindInfoRegistrar};
+  AdderFn Adders[] = {
+      addCall,
+      addGDBJITRegistrar,
+      addMemoryAccess,
+      addNativeDylibManager,
+      addSimpleNativeMemoryMap,
+#if defined(__APPLE__)
+      addStandaloneMachOUnwindInfoRegistrar,
+#endif
+  };
 
   for (auto *Adder : Adders)
     if (auto Err = Adder(ST))
diff --git a/orc-rt/lib/bedrock/sys/windows/DynamicLibrary.cpp b/orc-rt/lib/bedrock/sys/windows/DynamicLibrary.cpp
new file mode 100644
index 0000000000000..c311fdc5006dc
--- /dev/null
+++ b/orc-rt/lib/bedrock/sys/windows/DynamicLibrary.cpp
@@ -0,0 +1,28 @@
+//===- DynamicLibrary.cpp -------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "orc-rt-internal/bedrock/sys/DynamicLibrary.h"
+
+namespace orc_rt::sys {
+
+void *globalLookupHandle() { return nullptr; }
+
+Expected<void *> loadLibrary(const std::string &) {
+  return make_error<StringError>("Windows loadLibrary not implemented");
+}
+
+Error unloadLibrary(void *) {
+  return make_error<StringError>("Windows unloadLibrary not implemented");
+}
+
+std::vector<std::optional<void *>>
+lookupLibrarySymbols(void *, const std::vector<std::string> &Names) {
+  return std::vector<std::optional<void *>>(Names.size(), std::nullopt);
+}
+
+} // namespace orc_rt::sys
diff --git a/orc-rt/lib/bedrock/sys/windows/Memory.cpp b/orc-rt/lib/bedrock/sys/windows/Memory.cpp
new file mode 100644
index 0000000000000..8ae525d13c5a5
--- /dev/null
+++ b/orc-rt/lib/bedrock/sys/windows/Memory.cpp
@@ -0,0 +1,29 @@
+//===- Memory.cpp ---------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "orc-rt-internal/bedrock/sys/Memory.h"
+
+namespace orc_rt::sys {
+
+Expected<uint64_t> detectPageSize() {
+  return make_error<StringError>("Windows detectPageSize not implemented");
+}
+
+Expected<void *> reserveMemory(uint64_t) {
+  return make_error<StringError>("Windows reserveMemory not implemented");
+}
+
+Error releaseMemory(void *, uint64_t) {
+  return make_error<StringError>("Windows releaseMemory not implemented");
+}
+
+Error protectMemory(void *, uint64_t, MemProt) {
+  return make_error<StringError>("Windows protectMemory not implemented");
+}
+
+} // namespace orc_rt::sys
diff --git a/orc-rt/test/unit/CMakeLists.txt b/orc-rt/test/unit/CMakeLists.txt
index f750799ad75bf..41132cc786d10 100644
--- a/orc-rt/test/unit/CMakeLists.txt
+++ b/orc-rt/test/unit/CMakeLists.txt
@@ -6,6 +6,10 @@ if (NOT TARGET llvm_gtest)
                   "Try LLVM_INSTALL_GTEST=ON for the LLVM build")
   return ()
 endif ()
+# add_unittest from llvm toggles exceptions/rtti on windows so match
+# the libs settings
+set(LLVM_REQUIRES_RTTI ${ORC_RT_ENABLE_RTTI})
+set(LLVM_REQUIRES_EH ${ORC_RT_ENABLE_EXCEPTIONS})
 
 # Adds a unit test suite. Sources come first; LINK_LIBS names the object
 # libraries the suite links and must come last.
@@ -14,6 +18,7 @@ function(add_orc_rt_unittest test_name)
   add_unittest(OrcRTUnitTests ${test_name} ${ARG_UNPARSED_ARGUMENTS}
     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.
@@ -21,6 +26,14 @@ function(add_orc_rt_unittest test_name)
   target_link_libraries(${test_name} PRIVATE ${ARG_LINK_LIBS})
 endfunction()
 
+if (APPLE OR CMAKE_SYSTEM_NAME STREQUAL "Linux")
+  set(ORC_RT_SUPPORT_TEST_SYS_SOURCES
+    support/sys/ErrnoTest.cpp
+  )
+else()
+  set(ORC_RT_SUPPORT_TEST_SYS_SOURCES)
+endif()
+
 # 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.
@@ -62,7 +75,7 @@ add_orc_rt_unittest(SupportTests
   support/sps/SPSWrapperFunctionTest.cpp
   support/sps/SimplePackedSerializationTest.cpp
 
-  support/sys/ErrnoTest.cpp
+  ${ORC_RT_SUPPORT_TEST_SYS_SOURCES}
 
   tools/OptionParserTest.cpp
 
@@ -73,8 +86,9 @@ add_orc_rt_unittest(SupportTests
 # 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/SocketHandleTest.cpp
   bedrock/sys/posix/SocketTestUtils.cpp
-)
+  )
 
 if (APPLE OR CMAKE_SYSTEM_NAME STREQUAL "Linux")
   set(ORC_RT_BEDROCK_TEST_SYS_SOURCES ${ORC_RT_BEDROCK_TEST_POSIX_SOURCES})
@@ -83,6 +97,14 @@ else()
   set(ORC_RT_BEDROCK_TEST_SYS_SOURCES)
 endif()
 
+if (APPLE)
+  set(ORC_RT_BEDROCK_TEST_APPLE_SOURCES
+    bedrock/StandaloneMachOUnwindInfoRegistrarTest.cpp
+    )
+else()
+  set(ORC_RT_BEDROCK_TEST_APPLE_SOURCES)
+endif()
+
 add_orc_rt_unittest(BedrockTests
   bedrock/BootstrapInfoTest.cpp
   bedrock/ExecutorProcessInfoTest.cpp
@@ -92,8 +114,6 @@ add_orc_rt_unittest(BedrockTests
   bedrock/SessionTest.cpp
   bedrock/SimpleNativeMemoryMapTest.cpp
   bedrock/SimpleSymbolTableTest.cpp
-  bedrock/SocketHandleTest.cpp
-  bedrock/StandaloneMachOUnwindInfoRegistrarTest.cpp
   bedrock/TaskGroupTest.cpp
   bedrock/ThreadPoolRunnerTest.cpp
 
@@ -107,6 +127,7 @@ add_orc_rt_unittest(BedrockTests
   bedrock/sys/TargetTripleTest.cpp
 
   ${ORC_RT_BEDROCK_TEST_SYS_SOURCES}
+  ${ORC_RT_BEDROCK_TEST_APPLE_SOURCES}
 
   LINK_LIBS orc-rt-bedrock-objects orc-rt-support-objects
   )
@@ -115,7 +136,10 @@ add_orc_rt_unittest(BedrockTests
 add_library(NativeDylibManagerTestLib SHARED
   Inputs/NativeDylibManagerTestLib.cpp)
 set_target_properties(NativeDylibManagerTestLib PROPERTIES
-  PREFIX "")
+  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)
@@ -127,11 +151,19 @@ add_dependencies(BedrockTests NativeDylibManagerTestLib)
 # same way any other consumer of orc-rt would.
 add_library(RTTICrossDylibTestLib SHARED
   Inputs/RTTICrossDylibTestLib.cpp)
+
 set_target_properties(RTTICrossDylibTestLib PROPERTIES
   PREFIX ""
   CXX_VISIBILITY_PRESET hidden
-  VISIBILITY_INLINES_HIDDEN ON)
+  VISIBILITY_INLINES_HIDDEN ON
+  FOLDER "orc-rt/Tests")
+
+target_compile_definitions(RTTICrossDylibTestLib PRIVATE
+  RTTI_CROSS_DYLIB_TEST_LIB_EXPORTS)
+
 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)
diff --git a/orc-rt/test/unit/Inputs/RTTICrossDylibTestLib.cpp b/orc-rt/test/unit/Inputs/RTTICrossDylibTestLib.cpp
index a3612e75bb04e..e6c3c2eb912fb 100644
--- a/orc-rt/test/unit/Inputs/RTTICrossDylibTestLib.cpp
+++ b/orc-rt/test/unit/Inputs/RTTICrossDylibTestLib.cpp
@@ -6,20 +6,16 @@
 #include "RTTICrossDylibTestLib.h"
 #include "RTTICrossDylibTestError.h"
 
-#if defined(_WIN32)
-#define TEST_EXPORT __declspec(dllexport)
-#else
-#define TEST_EXPORT __attribute__((visibility("default")))
-#endif
-
 using namespace orc_rt;
 using orc_rt_test::CrossDylibTestError;
 
-extern "C" TEST_EXPORT ErrorInfoBase *rttiCrossDylibTest_makeError(int Code) {
+extern "C" RTTI_TEST_EXPORT ErrorInfoBase *
+rttiCrossDylibTest_makeError(int Code) {
   return new CrossDylibTestError(Code);
 }
 
-extern "C" TEST_EXPORT void rttiCrossDylibTest_destroyError(ErrorInfoBase *E) {
+extern "C" RTTI_TEST_EXPORT void
+rttiCrossDylibTest_destroyError(ErrorInfoBase *E) {
   delete E;
 }
 
@@ -27,7 +23,7 @@ extern "C" TEST_EXPORT void rttiCrossDylibTest_destroyError(ErrorInfoBase *E) {
 // confirm the two libraries are genuinely using distinct identities (i.e.
 // that the test below exercises the cross-library strcmp path, not the
 // same-library pointer-equality fast path).
-extern "C" TEST_EXPORT const void *rttiCrossDylibTest_libraryID() {
+extern "C" RTTI_TEST_EXPORT const void *rttiCrossDylibTest_libraryID() {
   CrossDylibTestError E(0);
   return E.libraryID();
 }
diff --git a/orc-rt/test/unit/Inputs/RTTICrossDylibTestLib.h b/orc-rt/test/unit/Inputs/RTTICrossDylibTestLib.h
index 0ec2166bdfab3..5a3a990a632d7 100644
--- a/orc-rt/test/unit/Inputs/RTTICrossDylibTestLib.h
+++ b/orc-rt/test/unit/Inputs/RTTICrossDylibTestLib.h
@@ -17,8 +17,22 @@
 
 #include "orc-rt/support/Error.h"
 
-extern "C" orc_rt::ErrorInfoBase *rttiCrossDylibTest_makeError(int Code);
-extern "C" void rttiCrossDylibTest_destroyError(orc_rt::ErrorInfoBase *E);
-extern "C" const void *rttiCrossDylibTest_libraryID();
+#if defined(_WIN32)
+#if defined(RTTI_CROSS_DYLIB_TEST_LIB_EXPORTS)
+#define RTTI_TEST_EXPORT __declspec(dllexport)
+#else
+#define RTTI_TEST_EXPORT __declspec(dllimport)
+#endif
+#else
+#define RTTI_TEST_EXPORT __attribute__((visibility("default")))
+#endif
+
+extern "C" RTTI_TEST_EXPORT orc_rt::ErrorInfoBase *
+rttiCrossDylibTest_makeError(int Code);
+
+extern "C" RTTI_TEST_EXPORT void
+rttiCrossDylibTest_destroyError(orc_rt::ErrorInfoBase *E);
+
+extern "C" RTTI_TEST_EXPORT const void *rttiCrossDylibTest_libraryID();
 
 #endif // ORC_RT_TEST_RTTICROSSDYLIBTESTLIB_H
diff --git a/orc-rt/test/unit/bedrock/ExecutorProcessInfoTest.cpp b/orc-rt/test/unit/bedrock/ExecutorProcessInfoTest.cpp
index fb9faa5641f73..78b16ac2beaef 100644
--- a/orc-rt/test/unit/bedrock/ExecutorProcessInfoTest.cpp
+++ b/orc-rt/test/unit/bedrock/ExecutorProcessInfoTest.cpp
@@ -14,10 +14,12 @@
 #include "orc-rt/support/bit.h"
 #include "gtest/gtest.h"
 
+#ifndef _WIN32
 #include <unistd.h>
+#endif
 
 using namespace orc_rt;
-
+#ifndef _WIN32
 TEST(ExecutorProcessInfoTest, DetectSucceeds) {
   auto EPI = ExecutorProcessInfo::Detect();
   EXPECT_TRUE(!!EPI);
@@ -34,10 +36,13 @@ 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, DetectPageSizeMatchesSystem) {
+  auto EPI = ExecutorProcessInfo::Detect();
+  ASSERT_TRUE(EPI);
+
+  EXPECT_EQ(EPI->PageSize, static_cast<uint64_t>(sysconf(_SC_PAGESIZE)));
 }
+#endif
 
 TEST(ExecutorProcessInfoTest, ConstructWithExplicitValues) {
   ExecutorProcessInfo EPI("x86_64-unknown-linux-gnu", 4096, "+x,+a,+b");
diff --git a/orc-rt/test/unit/bedrock/InProcessControllerAccessTest.cpp b/orc-rt/test/unit/bedrock/InProcessControllerAccessTest.cpp
index 71b155b1030fa..29fd2c537fd7a 100644
--- a/orc-rt/test/unit/bedrock/InProcessControllerAccessTest.cpp
+++ b/orc-rt/test/unit/bedrock/InProcessControllerAccessTest.cpp
@@ -26,6 +26,10 @@ using namespace orc_rt;
 
 namespace {
 
+static orc_rt_ControllerHandlerTag testHandlerTag() {
+  return reinterpret_cast<orc_rt_ControllerHandlerTag>(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 +196,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 +223,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 +250,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 +275,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";
 
diff --git a/orc-rt/test/unit/bedrock/NativeDylibManagerTest.cpp b/orc-rt/test/unit/bedrock/NativeDylibManagerTest.cpp
index d8227f3f4987d..a6bf9c2050103 100644
--- a/orc-rt/test/unit/bedrock/NativeDylibManagerTest.cpp
+++ b/orc-rt/test/unit/bedrock/NativeDylibManagerTest.cpp
@@ -9,7 +9,7 @@
 // Test NativeDylibManager APIs.
 //
 //===----------------------------------------------------------------------===//
-
+#ifndef _WIN32
 #include "orc-rt/bedrock/NativeDylibManager.h"
 #include "orc-rt/bedrock/Session.h"
 
@@ -197,3 +197,4 @@ TEST(NativeDylibManagerTest, LookupMixedRequiredAndWeak) {
       << "weak-missing symbol should be reported as a present optional";
   EXPECT_EQ(*(*Result)[1], nullptr);
 }
+#endif
diff --git a/orc-rt/test/unit/bedrock/SimpleNativeMemoryMapTest.cpp b/orc-rt/test/unit/bedrock/SimpleNativeMemoryMapTest.cpp
index 23d3cd7393d2b..5cdcb2fe1e681 100644
--- a/orc-rt/test/unit/bedrock/SimpleNativeMemoryMapTest.cpp
+++ b/orc-rt/test/unit/bedrock/SimpleNativeMemoryMapTest.cpp
@@ -9,6 +9,7 @@
 // Test SimpleNativeMemoryMap APIs.
 //
 //===----------------------------------------------------------------------===//
+#ifndef _WIN32
 
 #include "orc-rt/bedrock/SimpleNativeMemoryMap.h"
 #include "orc-rt/bedrock/Session.h"
@@ -322,3 +323,4 @@ TEST(SimpleNativeMemoryMapTest, ReserveInitializeDetachShutdown) {
 
   EXPECT_EQ(SentinelValue, 42);
 }
+#endif
diff --git a/orc-rt/test/unit/bedrock/sps/NativeDylibManagerSPSCITest.cpp b/orc-rt/test/unit/bedrock/sps/NativeDylibManagerSPSCITest.cpp
index b4252a14575dc..46bff3794e411 100644
--- a/orc-rt/test/unit/bedrock/sps/NativeDylibManagerSPSCITest.cpp
+++ b/orc-rt/test/unit/bedrock/sps/NativeDylibManagerSPSCITest.cpp
@@ -9,7 +9,7 @@
 // Tests for NativeDylibManager's SPS Controller Interface.
 //
 //===----------------------------------------------------------------------===//
-
+#ifndef _WIN32
 #include "orc-rt/bedrock/sps/NativeDylibManagerSPSCI.h"
 #include "orc-rt/bedrock/NativeDylibManager.h"
 #include "orc-rt/bedrock/Session.h"
@@ -235,3 +235,4 @@ TEST_F(NativeDylibManagerSPSCITest, LookupMixedRequiredAndWeak) {
       << "weak-missing symbol should be reported as a present optional";
   EXPECT_EQ(*Addrs[1], nullptr);
 }
+#endif
diff --git a/orc-rt/test/unit/bedrock/sps/SimpleNativeMemoryMapSPSCITest.cpp b/orc-rt/test/unit/bedrock/sps/SimpleNativeMemoryMapSPSCITest.cpp
index e455afb209574..d3ad5bef7edef 100644
--- a/orc-rt/test/unit/bedrock/sps/SimpleNativeMemoryMapSPSCITest.cpp
+++ b/orc-rt/test/unit/bedrock/sps/SimpleNativeMemoryMapSPSCITest.cpp
@@ -9,7 +9,7 @@
 // Tests for SimpleNativeMemoryMap's SPS Controller Interface.
 //
 //===----------------------------------------------------------------------===//
-
+#ifndef _WIN32
 #include "orc-rt/bedrock/sps/SimpleNativeMemoryMapSPSCI.h"
 #include "orc-rt/bedrock/Session.h"
 #include "orc-rt/bedrock/SimpleNativeMemoryMap.h"
@@ -321,3 +321,4 @@ TEST_F(SimpleNativeMemoryMapSPSCITest, ReserveInitializeDetachShutdown) {
 
   EXPECT_EQ(SentinelValue, 42);
 }
+#endif
diff --git a/orc-rt/test/unit/bedrock/sps/SimpleRemoteCATest.cpp b/orc-rt/test/unit/bedrock/sps/SimpleRemoteCATest.cpp
index 879f415c5b433..7ef251da25db7 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/bedrock/sys/TargetTripleTest.cpp b/orc-rt/test/unit/bedrock/sys/TargetTripleTest.cpp
index 1a03de3870edf..65675d8db58d6 100644
--- a/orc-rt/test/unit/bedrock/sys/TargetTripleTest.cpp
+++ b/orc-rt/test/unit/bedrock/sys/TargetTripleTest.cpp
@@ -16,7 +16,7 @@
 #include <algorithm>
 
 using namespace orc_rt;
-
+#ifndef _WIN32
 TEST(TargetTripleTest, NotEmpty) {
   EXPECT_FALSE(sys::detectTargetTriple().empty());
 }
@@ -52,7 +52,7 @@ TEST(TargetTripleTest, OSMatchesCompileTarget) {
   EXPECT_NE(Triple.find("-linux-"), std::string::npos);
 #endif
 }
-
+#endif
 TEST(TargetTripleTest, CachedResultIsIdempotent) {
   EXPECT_EQ(sys::detectTargetTriple(), sys::detectTargetTriple());
 }
diff --git a/orc-rt/test/unit/support/CallableTraitsHelperTest.cpp b/orc-rt/test/unit/support/CallableTraitsHelperTest.cpp
index e04f10328b1c3..4c127e964542a 100644
--- a/orc-rt/test/unit/support/CallableTraitsHelperTest.cpp
+++ b/orc-rt/test/unit/support/CallableTraitsHelperTest.cpp
@@ -14,23 +14,22 @@
 //===----------------------------------------------------------------------===//
 
 #include "orc-rt/support/CallableTraitsHelper.h"
+#include "orc-rt/support/Compiler.h"
 #include "gtest/gtest.h"
 
 using namespace orc_rt;
 
-static void freeVoidVoid() {}
+ORC_RT_MAYBE_UNUSED static void freeVoidVoid() {}
 
 TEST(CallableTraitsHelperTest, FreeVoidVoid) {
-  (void)freeVoidVoid;
   typedef CallableArgInfo<decltype(freeVoidVoid)> CAI;
   static_assert(std::is_void_v<CAI::return_type>);
   static_assert(std::is_same_v<CAI::args_tuple_type, std::tuple<>>);
 }
 
-static int freeBinaryOp(int, float) { return 0; }
+ORC_RT_MAYBE_UNUSED static int freeBinaryOp(int, float) { return 0; }
 
 TEST(CallableTraitsHelperTest, FreeBinaryOp) {
-  (void)freeBinaryOp;
   typedef CallableArgInfo<decltype(freeBinaryOp)> CAI;
   static_assert(std::is_same_v<CAI::return_type, int>);
   static_assert(std::is_same_v<CAI::args_tuple_type, std::tuple<int, float>>);
@@ -133,10 +132,9 @@ TEST(CallableTraitsHelperTest, AbominableFunctionTypeIsConst) {
 
 // noexcept coverage — mirrors the const-qualifier tests above.
 
-static void freeVoidVoidNoexcept() noexcept {}
+ORC_RT_MAYBE_UNUSED static void freeVoidVoidNoexcept() noexcept {}
 
 TEST(CallableTraitsHelperTest, FreeFunctionNoexcept) {
-  (void)freeVoidVoidNoexcept;
   static_assert(!CallableArgInfo<decltype(freeVoidVoid)>::is_noexcept);
   static_assert(CallableArgInfo<decltype(freeVoidVoidNoexcept)>::is_noexcept);
 }
diff --git a/orc-rt/test/unit/support/ErrorExceptionInteropTest.cpp b/orc-rt/test/unit/support/ErrorExceptionInteropTest.cpp
index 8205f30bea083..bc885cceeadbb 100644
--- a/orc-rt/test/unit/support/ErrorExceptionInteropTest.cpp
+++ b/orc-rt/test/unit/support/ErrorExceptionInteropTest.cpp
@@ -166,9 +166,9 @@ TEST(ErrorExceptionInteropTest, ThrowErrorAndCatchAsException) {
     try {
       auto E = make_error<CustomError>();
       E.throwOnFailure();
-    } catch (CustomError &E) {
+    } catch (CustomError &) {
       HandlerRan = true;
-    } catch (ErrorInfoBase &E) {
+    } catch (ErrorInfoBase &) {
       ADD_FAILURE() << "Failed to downcase error to dynamic type";
     } catch (...) {
       ADD_FAILURE() << "Caught unexpected error type";
diff --git a/orc-rt/test/unit/support/bit-test.cpp b/orc-rt/test/unit/support/bit-test.cpp
index f2ca32b89edc9..83b03c5140fe1 100644
--- a/orc-rt/test/unit/support/bit-test.cpp
+++ b/orc-rt/test/unit/support/bit-test.cpp
@@ -22,6 +22,10 @@
 #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 8af7b1d122059..6a743b6e416af 100644
--- a/orc-rt/test/unit/tools/OptionParserTest.cpp
+++ b/orc-rt/test/unit/tools/OptionParserTest.cpp
@@ -125,9 +125,9 @@ 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) {
+  std::vector<char *> Argv;
+  auto Err = Parser.parseAsMainArgs(static_cast<int>(Argv.size()), Argv.data());
 
   EXPECT_TRUE(!!Err);
   consumeError(std::move(Err));

>From c69effa3d43cb1a6b433dd10b59e9e854e27505c Mon Sep 17 00:00:00 2001
From: Jared Wyles <jared.wyles at gmail.com>
Date: Fri, 18 Sep 2026 14:59:24 +1000
Subject: [PATCH 2/2] [orc-rt] Implement Windows target triple detection

---
 orc-rt/lib/bedrock/sys/windows/TargetTriple.cpp   |  8 +++++++-
 orc-rt/test/unit/bedrock/sys/TargetTripleTest.cpp | 15 ++++++++++++++-
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/orc-rt/lib/bedrock/sys/windows/TargetTriple.cpp b/orc-rt/lib/bedrock/sys/windows/TargetTriple.cpp
index 465a24afc82f8..7a5db97b98f7b 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/unit/bedrock/sys/TargetTripleTest.cpp b/orc-rt/test/unit/bedrock/sys/TargetTripleTest.cpp
index 65675d8db58d6..ea89b209564cd 100644
--- a/orc-rt/test/unit/bedrock/sys/TargetTripleTest.cpp
+++ b/orc-rt/test/unit/bedrock/sys/TargetTripleTest.cpp
@@ -16,7 +16,7 @@
 #include <algorithm>
 
 using namespace orc_rt;
-#ifndef _WIN32
+
 TEST(TargetTripleTest, NotEmpty) {
   EXPECT_FALSE(sys::detectTargetTriple().empty());
 }
@@ -46,6 +46,7 @@ TEST(TargetTripleTest, ArchMatchesCompileTarget) {
 
 TEST(TargetTripleTest, OSMatchesCompileTarget) {
   auto Triple = sys::detectTargetTriple();
+<<<<<<< HEAD
 #if defined(__APPLE__)
   EXPECT_NE(Triple.find("-apple-"), std::string::npos);
 #elif defined(__linux__)
@@ -53,6 +54,18 @@ TEST(TargetTripleTest, OSMatchesCompileTarget) {
 #endif
 }
 #endif
+=======
+
+#if defined(__APPLE__)
+    EXPECT_NE(Triple.find("-apple-"), std::string::npos);
+#elif defined(__linux__)
+      EXPECT_NE(Triple.find("-linux-"), std::string::npos);
+#elif defined(_WIN32)
+      EXPECT_NE(Triple.find("-windows-"), std::string::npos);
+#endif
+}
+
+>>>>>>> 4504f54e6dad ([orc-rt] Implement Windows target triple detection)
 TEST(TargetTripleTest, CachedResultIsIdempotent) {
   EXPECT_EQ(sys::detectTargetTriple(), sys::detectTargetTriple());
 }



More information about the llvm-commits mailing list