From e4b039b60415de861b6aecff8752bdbf0f14a651 Mon Sep 17 00:00:00 2001 From: LibretroAdmin Date: Sun, 14 Jun 2026 13:54:13 +0000 Subject: [PATCH] Fix MSVC C89 build: portable unaligned 64-bit store in pputile.h The per-tile fast path used a GCC-only typedef typedef uint64_t fceu_u64_unaligned __attribute__((may_alias, aligned(1))); which MSVC cannot parse, producing C2146/C2065/C2143 at every point pputile.h is textually included in ppu.c. Split the store by compiler: keep the may_alias typedef for GCC/Clang (preserving the direct movq) and use memcpy on MSVC, which is strict-aliasing-safe and lowers to the same unaligned 64-bit store. ppu.c already includes and is the only includer, so memcpy is always in scope. The packed value stays declared at the top of the block, keeping the C89 declaration-before-statement rule intact. --- src/pputile.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/pputile.h b/src/pputile.h index 74d59c7..52654a0 100644 --- a/src/pputile.h +++ b/src/pputile.h @@ -31,13 +31,21 @@ if (X1 >= 2) { * a stack scratch (which the obvious __builtin_memcpy / packed- * struct form would force, costing the optimisation entirely). */ { - typedef uint64_t fceu_u64_unaligned __attribute__((may_alias, aligned(1))); uint64_t packed = (uint64_t)fceu_bg_pair_lut[ pixdata & 0xFF] | ((uint64_t)fceu_bg_pair_lut[(pixdata >> 8) & 0xFF] << 16) | ((uint64_t)fceu_bg_pair_lut[(pixdata >> 16) & 0xFF] << 32) | ((uint64_t)fceu_bg_pair_lut[(pixdata >> 24) & 0xFF] << 48); +#if defined(__GNUC__) || defined(__clang__) + /* may_alias + aligned(1) lets gcc emit a direct movq without + * routing through a stack scratch. */ + typedef uint64_t fceu_u64_unaligned __attribute__((may_alias, aligned(1))); *(fceu_u64_unaligned *)P = packed; +#else + /* MSVC has no may_alias; memcpy is strict-aliasing-safe and is + * lowered to the same unaligned 64-bit store. */ + memcpy(P, &packed, sizeof(packed)); +#endif } P += 8; }