Files
psxrecomp/runtime/include/psx_align.h
Alex Vanderveen a9a732aae8 runtime: build under MSVC (drop two GNU-only constructs)
The README and docs/BUILDING.md both advertise MSVC as a supported
Windows toolchain, and the build system means it: runtime.cmake carries
/GS- /guard:cf-, /STACK, /SUBSYSTEM:WINDOWS with /ENTRY:mainCRTStartup,
an /experimental:c11atomics scoped to audio_trace.c, an SDL2 MSVC
dev-package lookup, and psx-oracle / psx-beetle are skipped under MSVC
because they are MinGW-only. psx_cycles.c already picks _BitScanReverse
over __builtin_clz, and the recompiler already emits a .CRT$XCU static
initializer instead of __attribute__((constructor)).

Two translation units regressed past that work and stop cl.exe cold.
Both files are in the runtime source list (runtime.cmake:261,267), so
this hit the framework runtime and every generated game project alike.

  runtime/src/sio.c  -- five GNU [0 ... PSX_MAX_PLAYERS - 1] range
    designators, which MSVC has no equivalent for. Replaced with a
    PSX_PAD_INIT() element-repeat macro in sio.h, next to the
    PSX_MAX_PLAYERS 1..8 bound that makes the ladder finite. Each
    PSX_PAD_REP_n is flat rather than recursive so no nested macro call
    is involved and the expansion is the same under the conforming and
    the traditional MSVC preprocessor; variadic so a braced element
    survives argument splitting. Element count cannot drift from the
    array extent because both are spelled PSX_MAX_PLAYERS.

  runtime/src/mdec.c -- __attribute__((aligned(16))) on the two SSE2
    scratch locals. The alignment is load-bearing: idct_sse2_dot8 stores
    with _mm_store_si128, which faults on an under-aligned destination.
    The irony is that mdec.c:9-10 gates the SSE2 path on _M_X64 || _M_AMD64
    specifically so MSVC x64 takes it, and then that path used a
    GCC-only attribute. Replaced with PSX_ALIGN(n) from the new
    runtime/include/psx_align.h, which maps to __declspec(align(n)) on
    MSVC -- prefix position being the one placement both spellings share.
    Written in the style of the neighbouring psx_bss.h.

No behaviour change on the existing toolchains, and that is checked
rather than asserted: sio.o and mdec.o are byte-identical to their
pre-patch builds under both gcc and clang, and for sio.o at every
supported PSX_MAX_PLAYERS from 1 through 8. A -Wpedantic sweep over
runtime/src, which reported the five range designators before, now
reports none. psx-runtime and psx-oracle link, and the runtime ctest
suite is 43/43.

Unfixed and pre-existing, unrelated to this change: gte_register_access_test
fails to link (gte.cpp references gpu_ws_precise_nclip_enabled, defined in
gpu.c, which is not in that target's source list).

Not attempted here: nothing in CI compiles runtime/src with cl.exe, which
is why these two landed unnoticed. A windows-latest MSVC configure+build
job is the durable fix and should be its own change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014YD7rrVK63Kncki6prB65S
2026-08-27 14:39:54 -04:00

26 lines
900 B
C

/* psx_align.h — portable alignment attribute for SIMD scratch buffers.
*
* The SSE2/NEON kernels store to local scratch arrays with aligned stores
* (_mm_store_si128 and friends), so the alignment is load-bearing, not a
* hint: an under-aligned destination faults.
*
* GCC/Clang spell this __attribute__((aligned(n))); MSVC spells it
* __declspec(align(n)). Both are valid in prefix position on a declaration,
* which is the one placement the two spellings share -- hence the macro is
* written to be used as a prefix:
*
* PSX_ALIGN(16) int32_t tmp[4];
*/
#ifndef PSXRECOMP_PSX_ALIGN_H
#define PSXRECOMP_PSX_ALIGN_H
#if defined(_MSC_VER) && !defined(__clang__)
#define PSX_ALIGN(n) __declspec(align(n))
#elif defined(__GNUC__) || defined(__clang__)
#define PSX_ALIGN(n) __attribute__((aligned(n)))
#else
#define PSX_ALIGN(n) _Alignas(n)
#endif
#endif /* PSXRECOMP_PSX_ALIGN_H */