[llvm] [orc-rt] Add Windows virtual memory support (PR #224521)
Jared Wyles via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 21 05:14:03 PDT 2026
https://github.com/jaredwy updated https://github.com/llvm/llvm-project/pull/224521
>From 93b5c56d69517eb9e0226b5a584d11da005e6542 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 1/4] [orc-rt] Implement Windows target triple detection
---
orc-rt/lib/bedrock/sys/windows/TargetTriple.cpp | 8 +++++++-
orc-rt/test/unit/bedrock/sys/TargetTripleTest.cpp | 11 +++++++----
2 files changed, 14 insertions(+), 5 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..ad1a230dabe78 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,13 +46,16 @@ TEST(TargetTripleTest, ArchMatchesCompileTarget) {
TEST(TargetTripleTest, OSMatchesCompileTarget) {
auto Triple = sys::detectTargetTriple();
+
#if defined(__APPLE__)
- EXPECT_NE(Triple.find("-apple-"), std::string::npos);
+ EXPECT_NE(Triple.find("-apple-"), std::string::npos);
#elif defined(__linux__)
- EXPECT_NE(Triple.find("-linux-"), std::string::npos);
+ EXPECT_NE(Triple.find("-linux-"), std::string::npos);
+#elif defined(_WIN32)
+ EXPECT_NE(Triple.find("-windows-"), std::string::npos);
#endif
}
-#endif
+
TEST(TargetTripleTest, CachedResultIsIdempotent) {
EXPECT_EQ(sys::detectTargetTriple(), sys::detectTargetTriple());
}
>From 6e28b9b91bba48fdaf6c6c8273d0b9db8e182ef1 Mon Sep 17 00:00:00 2001
From: Jared Wyles <jared.wyles at gmail.com>
Date: Fri, 18 Sep 2026 15:10:04 +1000
Subject: [PATCH 2/4] [orc-rt] Implement Windows CPU feature detection
---
.../lib/bedrock/sys/windows/CPUFeatures.cpp | 55 ++++++++++++++++++-
.../test/unit/bedrock/sys/CPUFeaturesTest.cpp | 13 +++++
2 files changed, 67 insertions(+), 1 deletion(-)
diff --git a/orc-rt/lib/bedrock/sys/windows/CPUFeatures.cpp b/orc-rt/lib/bedrock/sys/windows/CPUFeatures.cpp
index 8cb9bfa7d7b14..9928a978c53a2 100644
--- a/orc-rt/lib/bedrock/sys/windows/CPUFeatures.cpp
+++ b/orc-rt/lib/bedrock/sys/windows/CPUFeatures.cpp
@@ -1,7 +1,60 @@
#include "orc-rt-internal/bedrock/sys/CPUFeatures.h"
+#include <intrin.h>
+#include <windows.h>
+
namespace orc_rt::sys {
-std::vector<std::string_view> detectTargetCPUFeatures() { return {}; }
+std::vector<std::string_view> detectTargetCPUFeatures() {
+ std::vector<std::string_view> Features;
+
+ auto A = [&](bool Present, std::string_view Feature) {
+ if (Present)
+ Features.push_back(Feature);
+ };
+
+ int Regs[4] = {};
+ __cpuid(Regs, 0);
+
+ const unsigned MaxLeaf = static_cast<unsigned>(Regs[0]);
+ if (MaxLeaf < 1)
+ return Features;
+
+ __cpuidex(Regs, 1, 0);
+
+ const unsigned ECX = static_cast<unsigned>(Regs[2]);
+ const unsigned EDX = static_cast<unsigned>(Regs[3]);
+
+ A(EDX & (1u << 25), "sse");
+ A(EDX & (1u << 26), "sse2");
+
+ A(ECX & (1u << 0), "sse3");
+ A(ECX & (1u << 9), "ssse3");
+ A(ECX & (1u << 19), "sse4.1");
+ A(ECX & (1u << 20), "sse4.2");
+
+ const bool HasXSAVE = ECX & (1u << 26);
+ const bool HasOSXSAVE = ECX & (1u << 27);
+ const bool HasAVXHardware = ECX & (1u << 28);
+
+ uint64_t XCR0 = 0;
+ if (HasXSAVE && HasOSXSAVE)
+ XCR0 = _xgetbv(0);
+
+ const bool HasAVXState = (XCR0 & 0x6) == 0x6;
+ const bool HasAVX = HasAVXHardware && HasAVXState;
+
+ A(HasAVX, "avx");
+
+ if (MaxLeaf >= 7) {
+ __cpuidex(Regs, 7, 0);
+
+ const unsigned EBX = static_cast<unsigned>(Regs[1]);
+
+ A(HasAVX && (EBX & (1u << 5)), "avx2");
+ }
+
+ return Features;
+}
} // namespace orc_rt::sys
diff --git a/orc-rt/test/unit/bedrock/sys/CPUFeaturesTest.cpp b/orc-rt/test/unit/bedrock/sys/CPUFeaturesTest.cpp
index a4cbffdf1da2a..54304b5f857f0 100644
--- a/orc-rt/test/unit/bedrock/sys/CPUFeaturesTest.cpp
+++ b/orc-rt/test/unit/bedrock/sys/CPUFeaturesTest.cpp
@@ -25,3 +25,16 @@ TEST(CPUFeaturesTest, DetectDoesNotCrash) {
TEST(CPUFeaturesTest, CachedResultIsIdempotent) {
EXPECT_EQ(sys::detectTargetCPUFeatures(), sys::detectTargetCPUFeatures());
}
+
+// A temporary test to tide us over until the next branch lands.
+// We we enable regression testing for EPI.
+#if defined(_WIN32) && defined(_M_X64)
+TEST(CPUFeaturesTest, DetectsBaselineX86Features) {
+ auto Features = sys::detectTargetCPUFeatures();
+
+ EXPECT_NE(std::find(Features.begin(), Features.end(), "sse"),
+ Features.end());
+ EXPECT_NE(std::find(Features.begin(), Features.end(), "sse2"),
+ Features.end());
+}
+#endif
>From 73107e2a4acdab6dcf04ba31ec669950739c7420 Mon Sep 17 00:00:00 2001
From: Jared Wyles <jared.wyles at gmail.com>
Date: Fri, 18 Sep 2026 15:29:23 +1000
Subject: [PATCH 3/4] [orc-rt] Add Windows page size detection
---
orc-rt/lib/bedrock/CMakeLists.txt | 1 +
orc-rt/lib/bedrock/sys/windows/Memory.cpp | 4 ----
orc-rt/lib/bedrock/sys/windows/PageSize.cpp | 21 +++++++++++++++++++
.../{linux => }/check-rt-process-info.test | 5 +++--
.../darwin/check-rt-process-info.test | 6 ------
.../unit/bedrock/ExecutorProcessInfoTest.cpp | 10 +--------
6 files changed, 26 insertions(+), 21 deletions(-)
create mode 100644 orc-rt/lib/bedrock/sys/windows/PageSize.cpp
rename orc-rt/test/regression/{linux => }/check-rt-process-info.test (56%)
delete mode 100644 orc-rt/test/regression/darwin/check-rt-process-info.test
diff --git a/orc-rt/lib/bedrock/CMakeLists.txt b/orc-rt/lib/bedrock/CMakeLists.txt
index 5dc584bca9659..105723ebda82d 100644
--- a/orc-rt/lib/bedrock/CMakeLists.txt
+++ b/orc-rt/lib/bedrock/CMakeLists.txt
@@ -58,6 +58,7 @@ set(ORC_RT_BEDROCK_WINDOWS_SOURCES
sys/windows/DynamicLibrary.cpp
sys/windows/Memory.cpp
sys/windows/CPUFeatures.cpp
+ sys/windows/PageSize.cpp
sys/windows/TargetTriple.cpp
)
diff --git a/orc-rt/lib/bedrock/sys/windows/Memory.cpp b/orc-rt/lib/bedrock/sys/windows/Memory.cpp
index 8ae525d13c5a5..276fa1e292c23 100644
--- a/orc-rt/lib/bedrock/sys/windows/Memory.cpp
+++ b/orc-rt/lib/bedrock/sys/windows/Memory.cpp
@@ -10,10 +10,6 @@
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");
}
diff --git a/orc-rt/lib/bedrock/sys/windows/PageSize.cpp b/orc-rt/lib/bedrock/sys/windows/PageSize.cpp
new file mode 100644
index 0000000000000..4a23b72a0195b
--- /dev/null
+++ b/orc-rt/lib/bedrock/sys/windows/PageSize.cpp
@@ -0,0 +1,21 @@
+//===- PageSize.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"
+
+#include <windows.h>
+
+namespace orc_rt::sys {
+
+Expected<uint64_t> detectPageSize() {
+ SYSTEM_INFO SI;
+ GetSystemInfo(&SI);
+ return static_cast<uint64_t>(SI.dwPageSize);
+}
+
+} // namespace orc_rt::sys
diff --git a/orc-rt/test/regression/linux/check-rt-process-info.test b/orc-rt/test/regression/check-rt-process-info.test
similarity index 56%
rename from orc-rt/test/regression/linux/check-rt-process-info.test
rename to orc-rt/test/regression/check-rt-process-info.test
index 160be336d40cf..a84d510ffcddb 100644
--- a/orc-rt/test/regression/linux/check-rt-process-info.test
+++ b/orc-rt/test/regression/check-rt-process-info.test
@@ -1,5 +1,6 @@
-# RUN: orc-rt-process-info-check --print-triple --print-page-size \
+# RUN: orc-rt-process-info-check --print-triple --print-page-size --print-cpu-features \
# RUN: | FileCheck %s -DARCH=%target-arch
-# CHECK: {{^}}[[ARCH]]-{{.*}}-linux
+# CHECK: {{^}}[[ARCH]]-
# CHECK-NEXT: {{4096|16384}}
+# CHECK-NEXT: {{^\+[a-z0-9_.]+(,\+[a-z0-9_.]+)*$}}
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 8df2c09477c89..0000000000000
--- 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/unit/bedrock/ExecutorProcessInfoTest.cpp b/orc-rt/test/unit/bedrock/ExecutorProcessInfoTest.cpp
index 78b16ac2beaef..a17fdedac7197 100644
--- a/orc-rt/test/unit/bedrock/ExecutorProcessInfoTest.cpp
+++ b/orc-rt/test/unit/bedrock/ExecutorProcessInfoTest.cpp
@@ -19,7 +19,7 @@
#endif
using namespace orc_rt;
-#ifndef _WIN32
+
TEST(ExecutorProcessInfoTest, DetectSucceeds) {
auto EPI = ExecutorProcessInfo::Detect();
EXPECT_TRUE(!!EPI);
@@ -36,14 +36,6 @@ TEST(ExecutorProcessInfoTest, DetectPageSizeAtLeast4096) {
EXPECT_GE(EPI.pageSize(), 4096U);
}
-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");
EXPECT_EQ(EPI.targetTriple(), "x86_64-unknown-linux-gnu");
>From 9a9076f16a25e76680d7dc62c53db702246fac59 Mon Sep 17 00:00:00 2001
From: Jared Wyles <jared.wyles at gmail.com>
Date: Mon, 21 Sep 2026 22:05:53 +1000
Subject: [PATCH 4/4] [orc-rt] Add Windows virtual memory support
---
.../support/sys/WinErrorToORCError.h | 43 ++++++++++++
orc-rt/lib/bedrock/sys/windows/Memory.cpp | 65 +++++++++++++++++--
.../bedrock/SimpleNativeMemoryMapTest.cpp | 2 -
.../sps/SimpleNativeMemoryMapSPSCITest.cpp | 3 +-
4 files changed, 102 insertions(+), 11 deletions(-)
create mode 100644 orc-rt/include/orc-rt-internal/support/sys/WinErrorToORCError.h
diff --git a/orc-rt/include/orc-rt-internal/support/sys/WinErrorToORCError.h b/orc-rt/include/orc-rt-internal/support/sys/WinErrorToORCError.h
new file mode 100644
index 0000000000000..3ebbf6d3dcb91
--- /dev/null
+++ b/orc-rt/include/orc-rt-internal/support/sys/WinErrorToORCError.h
@@ -0,0 +1,43 @@
+#ifndef ORC_RT_INTERNAL_SUPPORT_SYS_WINERRORTOORCERROR_H
+#define ORC_RT_INTERNAL_SUPPORT_SYS_WINERRORTOORCERROR_H
+
+#include "orc-rt/support/Error.h"
+
+#include <string>
+#include <string_view>
+
+#include <windows.h>
+
+namespace orc_rt::sys {
+
+inline std::string getWindowsErrorMessage(DWORD ErrorCode) {
+ LPSTR Message = nullptr;
+
+ const DWORD Length = FormatMessageA(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ nullptr, ErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ reinterpret_cast<LPSTR>(&Message), 0, nullptr);
+
+ if (!Length)
+ return "Windows error " + std::to_string(ErrorCode);
+
+ std::string Result(Message, Length);
+ LocalFree(Message);
+
+ while (!Result.empty() && (Result.back() == '\r' || Result.back() == '\n'))
+ Result.pop_back();
+
+ return Result;
+}
+
+inline Error generateErrorFromGetLastError(std::string_view Prefix) {
+ const DWORD ErrorCode = GetLastError();
+
+ return make_error<StringError>(std::string(Prefix) + ": " +
+ getWindowsErrorMessage(ErrorCode));
+}
+
+} // namespace orc_rt::sys
+
+#endif
diff --git a/orc-rt/lib/bedrock/sys/windows/Memory.cpp b/orc-rt/lib/bedrock/sys/windows/Memory.cpp
index 276fa1e292c23..d6e08fb89e32d 100644
--- a/orc-rt/lib/bedrock/sys/windows/Memory.cpp
+++ b/orc-rt/lib/bedrock/sys/windows/Memory.cpp
@@ -1,4 +1,4 @@
-//===- Memory.cpp ---------------------------------------------------------===//
+//===--- Memory.cpp - Windows memory operations ---------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -7,19 +7,70 @@
//===----------------------------------------------------------------------===//
#include "orc-rt-internal/bedrock/sys/Memory.h"
+#include "orc-rt-internal/support/sys/WinErrorToORCError.h"
+
+#include <windows.h>
namespace orc_rt::sys {
-Expected<void *> reserveMemory(uint64_t) {
- return make_error<StringError>("Windows reserveMemory not implemented");
+namespace {
+
+DWORD getWindowsProtection(MemProt Prot) {
+ const bool Read = (Prot & MemProt::Read) != MemProt::None;
+ const bool Write = (Prot & MemProt::Write) != MemProt::None;
+ const bool Exec = (Prot & MemProt::Exec) != MemProt::None;
+
+ if (Exec) {
+ if (Write)
+ return PAGE_EXECUTE_READWRITE;
+ if (Read)
+ return PAGE_EXECUTE_READ;
+ return PAGE_EXECUTE;
+ }
+
+ if (Write)
+ return PAGE_READWRITE;
+ if (Read)
+ return PAGE_READONLY;
+
+ return PAGE_NOACCESS;
+}
+
+} // namespace
+
+Expected<void *> reserveMemory(uint64_t Size) {
+ void *Addr =
+ VirtualAlloc(nullptr, static_cast<SIZE_T>(Size),
+ MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+
+ if (!Addr)
+ return generateErrorFromGetLastError("VirtualAlloc failed");
+
+ return Addr;
}
-Error releaseMemory(void *, uint64_t) {
- return make_error<StringError>("Windows releaseMemory not implemented");
+Error releaseMemory(void *Base, uint64_t) {
+ // When MEM_RELEASE is specified, dwSize must be zero and Base must be the
+ // address returned by VirtualAlloc.
+ if (!VirtualFree(Base, 0, MEM_RELEASE))
+ return generateErrorFromGetLastError("VirtualFree failed");
+
+ return Error::success();
}
-Error protectMemory(void *, uint64_t, MemProt) {
- return make_error<StringError>("Windows protectMemory not implemented");
+Error protectMemory(void *Base, uint64_t Size, MemProt Prot) {
+ DWORD OldProtect = 0;
+
+ if (!VirtualProtect(Base, static_cast<SIZE_T>(Size),
+ getWindowsProtection(Prot), &OldProtect))
+ return generateErrorFromGetLastError("VirtualProtect failed");
+
+ if ((Prot & MemProt::Exec) != MemProt::None &&
+ !FlushInstructionCache(GetCurrentProcess(), Base,
+ static_cast<SIZE_T>(Size)))
+ return generateErrorFromGetLastError("FlushInstructionCache failed");
+
+ return Error::success();
}
} // namespace orc_rt::sys
diff --git a/orc-rt/test/unit/bedrock/SimpleNativeMemoryMapTest.cpp b/orc-rt/test/unit/bedrock/SimpleNativeMemoryMapTest.cpp
index 5cdcb2fe1e681..23d3cd7393d2b 100644
--- a/orc-rt/test/unit/bedrock/SimpleNativeMemoryMapTest.cpp
+++ b/orc-rt/test/unit/bedrock/SimpleNativeMemoryMapTest.cpp
@@ -9,7 +9,6 @@
// Test SimpleNativeMemoryMap APIs.
//
//===----------------------------------------------------------------------===//
-#ifndef _WIN32
#include "orc-rt/bedrock/SimpleNativeMemoryMap.h"
#include "orc-rt/bedrock/Session.h"
@@ -323,4 +322,3 @@ TEST(SimpleNativeMemoryMapTest, ReserveInitializeDetachShutdown) {
EXPECT_EQ(SentinelValue, 42);
}
-#endif
diff --git a/orc-rt/test/unit/bedrock/sps/SimpleNativeMemoryMapSPSCITest.cpp b/orc-rt/test/unit/bedrock/sps/SimpleNativeMemoryMapSPSCITest.cpp
index d3ad5bef7edef..e455afb209574 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,4 +321,3 @@ TEST_F(SimpleNativeMemoryMapSPSCITest, ReserveInitializeDetachShutdown) {
EXPECT_EQ(SentinelValue, 42);
}
-#endif
More information about the llvm-commits
mailing list