From b335f9712ce23fc4d3ed71bf28aa556d1d940b9c Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Tue, 16 Dec 2025 15:30:53 -0600 Subject: [PATCH v13 1/1] Add support for building with MSVC for AArch64. This commit does the following to get tests passing for MSVC/AArch64: * Implements spin_delay() with an ISB instruction (like we do for gcc/clang on AArch64). * Sets USE_ARMV8_CRC32C unconditionally. Vendor-supported versions of Windows for AArch64 require at least ARMv8.1, which is where CRC extension support became mandatory. * Implements S_UNLOCK() with _InterlockedExchange(). The existing implementation for MSVC uses _ReadWriteBarrier() (a compiler barrier), which is insufficient for this purpose on non-TSO architectures. There are likely other changes required to take full advantage of the hardware (e.g., atomics/arch-arm.h, simd.h, pg_popcount_aarch64.c), but those can be dealt with later. Author: Niyas Sait Co-authored-by: Greg Burd Co-authored-by: Dave Cramer Reviewed-by: Michael Paquier Reviewed-by: John Naylor Reviewed-by: Peter Eisentraut Reviewed-by: Andres Freund Reviewed-by: Thomas Munro Tested-by: Andrew Dunstan Discussion: https://postgr.es/m/A6152C7C-F5E3-4958-8F8E-7692D259FF2F%40greg.burd.me Discussion: https://postgr.es/m/CAFPTBD-74%2BAEuN9n7caJ0YUnW5A0r-KBX8rYoEJWqFPgLKpzdg%40mail.gmail.com --- doc/src/sgml/installation.sgml | 3 ++- meson.build | 6 +++++- src/include/storage/s_lock.h | 30 +++++++++++++++++++++++++----- src/port/pg_crc32c_armv8.c | 4 ++++ src/tools/msvc_gendef.pl | 8 ++++---- 5 files changed, 40 insertions(+), 11 deletions(-) diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml index fe8d73e1f8c..c903ccff988 100644 --- a/doc/src/sgml/installation.sgml +++ b/doc/src/sgml/installation.sgml @@ -3967,7 +3967,8 @@ configure ... LDFLAGS="-R /usr/sfw/lib:/opt/sfw/lib:/usr/local/lib" Special Considerations for 64-Bit Windows - PostgreSQL will only build for the x64 architecture on 64-bit Windows. + PostgreSQL will only build for the x64 and AArch64 architectures on 64-bit + Windows. Mixing 32- and 64-bit versions in the same build tree is not supported. diff --git a/meson.build b/meson.build index d7c5193d4ce..d521e13690c 100644 --- a/meson.build +++ b/meson.build @@ -2523,7 +2523,11 @@ int main(void) } ''' - if cc.links(prog, name: '__crc32cb, __crc32ch, __crc32cw, and __crc32cd without -march=armv8-a+crc', + # Vendor-supported versions of Windows for AArch64 require at least ARMv8.1, + # which is where CRC extension support became mandatory. Thus, use it + # unconditionally on MSVC/AArch64. + if (host_cpu == 'aarch64' and cc.get_id() == 'msvc') or \ + cc.links(prog, name: '__crc32cb, __crc32ch, __crc32cw, and __crc32cd without -march=armv8-a+crc', args: test_c_args) # Use ARM CRC Extension unconditionally cdata.set('USE_ARMV8_CRC32C', 1) diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h index 7f8f566bd40..20badae8e41 100644 --- a/src/include/storage/s_lock.h +++ b/src/include/storage/s_lock.h @@ -602,13 +602,24 @@ typedef LONG slock_t; #define SPIN_DELAY() spin_delay() -/* If using Visual C++ on Win64, inline assembly is unavailable. - * Use a _mm_pause intrinsic instead of rep nop. - */ -#if defined(_WIN64) +#ifdef _M_ARM64 +static __forceinline void +spin_delay(void) +{ + /* + * Research indicates ISB is better than __yield() on AArch64. See + * https://postgr.es/m/1c2a29b8-5b1e-44f7-a871-71ec5fefc120%40app.fastmail.com. + */ + __isb(_ARM64_BARRIER_SY); +} +#elif defined(_WIN64) static __forceinline void spin_delay(void) { + /* + * If using Visual C++ on Win64, inline assembly is unavailable. + * Use a _mm_pause intrinsic instead of rep nop. + */ _mm_pause(); } #else @@ -621,12 +632,21 @@ spin_delay(void) #endif #include -#pragma intrinsic(_ReadWriteBarrier) +#ifdef _M_ARM64 + +/* _ReadWriteBarrier() is insufficient on non-TSO architectures. */ +#pragma intrinsic(_InterlockedExchange) +#define S_UNLOCK(lock) _InterlockedExchange(lock, 0) + +#else + +#pragma intrinsic(_ReadWriteBarrier) #define S_UNLOCK(lock) \ do { _ReadWriteBarrier(); (*(lock)) = 0; } while (0) #endif +#endif #endif /* !defined(HAS_TEST_AND_SET) */ diff --git a/src/port/pg_crc32c_armv8.c b/src/port/pg_crc32c_armv8.c index 5ba070bb99d..e49b383b26a 100644 --- a/src/port/pg_crc32c_armv8.c +++ b/src/port/pg_crc32c_armv8.c @@ -14,7 +14,11 @@ */ #include "c.h" +#ifdef _MSC_VER +#include +#else #include +#endif #include "port/pg_crc32c.h" diff --git a/src/tools/msvc_gendef.pl b/src/tools/msvc_gendef.pl index 868aad51b09..c92c94c4775 100644 --- a/src/tools/msvc_gendef.pl +++ b/src/tools/msvc_gendef.pl @@ -118,9 +118,9 @@ sub writedef { my $isdata = $def->{$f} eq 'data'; - # Strip the leading underscore for win32, but not x64 + # Strip the leading underscore for win32, but not x64 and aarch64 $f =~ s/^_// - unless ($arch eq "x86_64"); + unless ($arch eq "x86_64" || $arch eq "aarch64"); # Emit just the name if it's a function symbol, or emit the name # decorated with the DATA option for variables. @@ -141,7 +141,7 @@ sub writedef sub usage { die("Usage: msvc_gendef.pl --arch --deffile --tempdir files-or-directories\n" - . " arch: x86 | x86_64\n" + . " arch: x86 | x86_64 | aarch64\n" . " deffile: path of the generated file\n" . " tempdir: directory for temporary files\n" . " files or directories: object files or directory containing object files\n" @@ -158,7 +158,7 @@ GetOptions( 'tempdir:s' => \$tempdir,) or usage(); usage("arch: $arch") - unless ($arch eq 'x86' || $arch eq 'x86_64'); + unless ($arch eq 'x86' || $arch eq 'x86_64' || $arch eq 'aarch64'); my @files; -- 2.39.5 (Apple Git-154)