headers: i386: Fall back to kernel32 Interlocked
On i386, GCC cannot inline the __sync_* builtins because the ISA has no
CMPXCHG or XADD instructions (which were introduced with i486). GCC
emits calls to library helpers such as __sync_val_compare_and_swap_4
that do not exist, causing undefined-reference link errors in any
program that uses the CRT (crt2.o references InterlockedCompareExchange
via the _InterlockedCompareExchangePointer intrinsic in crtexe.c):
ld: crt2.o:crtexe.c:(.text+0x...): undefined reference to `__sync_add_and_fetch_4'
ld: crt2.o:crtexe.c:(.text+0x...): undefined reference to `__sync_sub_and_fetch_4'
ld: crt2.o:crtexe.c:(.text+0x...): undefined reference to `__sync_fetch_and_add_4'
ld: crt2.o:crtexe.c:(.text+0x...): undefined reference to `__sync_val_compare_and_swap_4'
When __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 is not defined (as on i386, but
not on i486 and up), fall back to the real Interlocked functions
exported by kernel32.dll for the five functions it provides:
InterlockedCompareExchange, InterlockedIncrement, InterlockedDecrement,
InterlockedExchange, and InterlockedExchangeAdd. The functions remain
inline intrinsics as before: only the implementation body changes when
targeting i386.
_InterlockedAdd, _InterlockedAdd64, and _InterlockedCompareExchange64
also use __sync_* builtins but are intentionally left alone since
kernel32.dll does not export InterlockedAdd or 64-bit variants of these
functions (there is no kernel32 function to fall back to).
The kernel32 imports are declared with __asm__ labels to avoid
collisions with the macros (from winnt.h) that map unprefixed names to
underscore-prefixed intrinsics. GCC prepends underscores to __asm__
label strings but Clang does not, so a __MINGW_K32_ASM helper handles
this portably for both toolchains.
This fixes https://sourceforge.net/p/mingw-w64/bugs/961/
Signed-off-by: Jaeden Amero <jaeden@patater.com>
Signed-off-by: LIU Hao <lh_mouse@126.com>
1 file changed