vtlb: make the preserve_most requirement a hard compile-time check

The arm64 recompiler emits calls to the vtlb dispatchers assuming the
preserve_most contract (x9-x15 spared) and skips pin spill/reload
around them. Compilers without the attribute break that contract
silently: GCC warns and ignores unknown attributes, producing a binary
that corrupts the EE pin registers at every MMIO slow path; MSVC
errors on the attribute syntax by accident (C2065, the Windows arm64
CI failure in run 29700912398).

Replace both outcomes with an explicit #error naming the requirement.
clang supports preserve_most on all arm64 targets we build for,
including aarch64-pc-windows-msvc (verified: caller keeps live values
in x9 across the call, no diagnostic), so the Windows leg can go green
by building with clang; until then it fails with a clear message
instead of a mystery identifier error.
This commit is contained in:
Brian Degenhardt
2026-07-19 13:10:28 -07:00
parent 7dd2b50df0
commit f7a039e870
+12
View File
@@ -100,8 +100,20 @@ extern bool vtlb_IsFaultingPC(u32 guest_pc);
// direct-RAM fast path. Return/argument registers are unaffected, so
// C++ callers (interpreter memory ops) behave identically.
#ifdef ARCH_ARM64
#if defined(__has_attribute) && __has_attribute(preserve_most)
#define VTLB_PRESERVE_MOST __attribute__((preserve_most))
#else
// Hard requirement, not an optimization: the arm64 recompiler emits calls to
// these dispatchers assuming the preserve_most contract (x9-x15 spared) and
// skips pin spill/reload around them (recVTLB-arm64.cpp, RecStubs.cpp). A
// compiler that drops the attribute (GCC warns and ignores unknown
// attributes; MSVC has no equivalent) would build a binary whose emitted
// code silently corrupts the EE pin registers at every MMIO slow path.
// Build arm64 targets with clang (works for linux, windows-msvc, android,
// and apple targets) until a no-preserve_most emitter fallback exists.
#error "ARCH_ARM64 requires a compiler with __attribute__((preserve_most)) - build with clang"
#endif
#else
#define VTLB_PRESERVE_MOST
#endif