[clang] [llvm] Fixes to unblock building LLVM and Clang as Arm64EC (PR #150068)
Daniel Paoliello via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 24 12:05:53 PDT 2025
https://github.com/dpaoliello updated https://github.com/llvm/llvm-project/pull/150068
>From 8e6ec9a09cda6ffdbfd91250fae186ba8585dbf4 Mon Sep 17 00:00:00 2001
From: Daniel Paoliello <danpao at microsoft.com>
Date: Tue, 22 Jul 2025 10:17:02 -0700
Subject: [PATCH] Fixes to unblock building LLVM and Clang as Arm64EC
---
clang/tools/clang-repl/CMakeLists.txt | 15 +++++++++------
llvm/lib/Support/BLAKE3/CMakeLists.txt | 3 ++-
llvm/lib/TargetParser/Host.cpp | 13 ++++++++-----
llvm/tools/llvm-exegesis/lib/X86/Target.cpp | 16 +++++++++-------
third-party/benchmark/src/cycleclock.h | 4 ++--
5 files changed, 30 insertions(+), 21 deletions(-)
diff --git a/clang/tools/clang-repl/CMakeLists.txt b/clang/tools/clang-repl/CMakeLists.txt
index 68d86dd98cac3..c3d14ceb79792 100644
--- a/clang/tools/clang-repl/CMakeLists.txt
+++ b/clang/tools/clang-repl/CMakeLists.txt
@@ -19,14 +19,14 @@ if(MSVC)
set_target_properties(clang-repl PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS 1)
# RTTI/C++ symbols
- set(clang_repl_exports ${clang_repl_exports} ??_7type_info@@6B@
- ?__type_info_root_node@@3U__type_info_node@@A
- ?nothrow at std@@3Unothrow_t at 1@B
+ set(clang_repl_exports ${clang_repl_exports} ??_7type_info@@6B@,DATA
+ ?__type_info_root_node@@3U__type_info_node@@A,DATA
+ ?nothrow at std@@3Unothrow_t at 1@B,DATA
)
# Compiler added symbols for static variables. NOT for VStudio < 2015
- set(clang_repl_exports ${clang_repl_exports} _Init_thread_abort _Init_thread_epoch
- _Init_thread_footer _Init_thread_header _tls_index
+ set(clang_repl_exports ${clang_repl_exports} _Init_thread_abort _Init_thread_epoch,DATA
+ _Init_thread_footer _Init_thread_header _tls_index,DATA
)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
@@ -50,7 +50,10 @@ if(MSVC)
endif()
# List to '/EXPORT:sym0 /EXPORT:sym1 /EXPORT:sym2 ...'
- list(TRANSFORM clang_repl_exports PREPEND "LINKER:/EXPORT:")
+ # The 'SHELL' prefix tells CMake to use a space instead of comma as the
+ # separator between the driver and linker options, which we need since MSVC's
+ # linker uses `,DATA` as a suffix to indicate that data is being exported.
+ list(TRANSFORM clang_repl_exports PREPEND "LINKER:SHELL:/EXPORT:")
set_property(TARGET clang-repl APPEND PROPERTY LINK_OPTIONS ${clang_repl_exports})
diff --git a/llvm/lib/Support/BLAKE3/CMakeLists.txt b/llvm/lib/Support/BLAKE3/CMakeLists.txt
index eae2b0280e5d3..90311ae247219 100644
--- a/llvm/lib/Support/BLAKE3/CMakeLists.txt
+++ b/llvm/lib/Support/BLAKE3/CMakeLists.txt
@@ -26,7 +26,8 @@ endmacro()
if (CAN_USE_ASSEMBLER)
if (MSVC)
check_symbol_exists(_M_X64 "" IS_X64)
- if (IS_X64)
+ check_symbol_exists(_M_ARM64EC "" IS_ARM64EC)
+ if (IS_X64 AND NOT IS_ARM64EC)
enable_language(ASM_MASM)
set(LLVM_BLAKE3_ASM_FILES
blake3_sse2_x86-64_windows_msvc.asm
diff --git a/llvm/lib/TargetParser/Host.cpp b/llvm/lib/TargetParser/Host.cpp
index 78bd5b4b5bd25..7e09d30bf3d55 100644
--- a/llvm/lib/TargetParser/Host.cpp
+++ b/llvm/lib/TargetParser/Host.cpp
@@ -587,8 +587,9 @@ StringRef sys::detail::getHostCPUNameForBPF() {
#endif
}
-#if defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || \
- defined(_M_X64)
+#if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || \
+ defined(_M_X64)) && \
+ !defined(_M_ARM64EC)
/// getX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in
/// the specified arguments. If we can't run cpuid on the host, return true.
@@ -1853,8 +1854,9 @@ VendorSignatures getVendorSignature(unsigned *MaxLeaf) {
} // namespace llvm
#endif
-#if defined(__i386__) || defined(_M_IX86) || \
- defined(__x86_64__) || defined(_M_X64)
+#if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || \
+ defined(_M_X64)) && \
+ !defined(_M_ARM64EC)
StringMap<bool> sys::getHostCPUFeatures() {
unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
unsigned MaxLevel;
@@ -2147,7 +2149,8 @@ StringMap<bool> sys::getHostCPUFeatures() {
return Features;
}
-#elif defined(_WIN32) && (defined(__aarch64__) || defined(_M_ARM64))
+#elif defined(_WIN32) && (defined(__aarch64__) || defined(_M_ARM64) || \
+ defined(__arm64ec__) || defined(_M_ARM64EC))
StringMap<bool> sys::getHostCPUFeatures() {
StringMap<bool> Features;
diff --git a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
index 1659cfb31f117..5dae6c0a25fab 100644
--- a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
@@ -30,11 +30,12 @@
#include <memory>
#include <string>
#include <vector>
-#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
+#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) && \
+ !defined(_M_ARM64EC)
#include <immintrin.h>
#include <intrin.h>
#endif
-#if defined(_MSC_VER) && defined(_M_X64)
+#if defined(_MSC_VER) && defined(_M_X64) && !defined(_M_ARM64EC)
#include <float.h> // For _clearfp in ~X86SavedState().
#endif
@@ -654,7 +655,7 @@ namespace {
class X86SavedState : public ExegesisTarget::SavedState {
public:
X86SavedState() {
-#if defined(_MSC_VER) && defined(_M_X64)
+#if defined(_MSC_VER) && defined(_M_X64) && !defined(_M_ARM64EC)
_fxsave64(FPState);
Eflags = __readeflags();
#elif defined(__GNUC__) && defined(__x86_64__)
@@ -668,7 +669,7 @@ class X86SavedState : public ExegesisTarget::SavedState {
~X86SavedState() {
// Restoring the X87 state does not flush pending exceptions, make sure
// these exceptions are flushed now.
-#if defined(_MSC_VER) && defined(_M_X64)
+#if defined(_MSC_VER) && defined(_M_X64) && !defined(_M_ARM64EC)
_clearfp();
_fxrstor64(FPState);
__writeeflags(Eflags);
@@ -682,7 +683,7 @@ class X86SavedState : public ExegesisTarget::SavedState {
}
private:
-#if defined(__x86_64__) || defined(_M_X64)
+#if defined(__x86_64__) || defined(_M_X64) && !defined(_M_ARM64EC)
alignas(16) char FPState[512];
uint64_t Eflags;
#endif
@@ -824,8 +825,9 @@ class ExegesisX86Target : public ExegesisTarget {
// For now, only do the check if we see an Intel machine because
// the counter uses some intel-specific magic and it could
// be confuse and think an AMD machine actually has LBR support.
-#if defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || \
- defined(_M_X64)
+#if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || \
+ defined(_M_X64)) && \
+ !defined(_M_ARM64EC)
using namespace sys::detail::x86;
if (getVendorSignature() == VendorSignatures::GENUINE_INTEL)
diff --git a/third-party/benchmark/src/cycleclock.h b/third-party/benchmark/src/cycleclock.h
index d4f1330b671db..c0dffcf4b35f6 100644
--- a/third-party/benchmark/src/cycleclock.h
+++ b/third-party/benchmark/src/cycleclock.h
@@ -79,7 +79,7 @@ inline BENCHMARK_ALWAYS_INLINE int64_t Now() {
int64_t ret;
__asm__ volatile("rdtsc" : "=A"(ret));
return ret;
-#elif defined(__x86_64__) || defined(__amd64__)
+#elif (defined(__x86_64__) || defined(__amd64__)) && !defined(__arm64ec__)
uint64_t low, high;
__asm__ volatile("rdtsc" : "=a"(low), "=d"(high));
return (high << 32) | low;
@@ -139,7 +139,7 @@ inline BENCHMARK_ALWAYS_INLINE int64_t Now() {
struct timespec ts = {0, 0};
clock_gettime(CLOCK_MONOTONIC, &ts);
return static_cast<int64_t>(ts.tv_sec) * 1000000000 + ts.tv_nsec;
-#elif defined(__aarch64__)
+#elif defined(__aarch64__) || defined(__arm64ec__)
// System timer of ARMv8 runs at a different frequency than the CPU's.
// The frequency is fixed, typically in the range 1-50MHz. It can be
// read at CNTFRQ special register. We assume the OS has set up
More information about the llvm-commits
mailing list