Move the TinyCC/Windows ARM64 Interlocked workaround from the semlock call site into the bundled WinAPI header. This keeps tcc.h using the normal Interlocked API while avoiding unresolved Interlocked imports when tcc -run self-compiles on Windows ARM64. Update lib/bt-exe.c as well so its ARM64 runtime object does not define a second InterlockedExchange fallback now provided by winnt.h.
Unified · Split
| @@ -85,13 +85,3 @@ ST_FUNC char *pstrcpy(char *buf, size_t buf_size, const char *s) · 84 unmodified lines | ||
| 85 | 85 | buf[l] = 0; |
| 86 | 86 | return buf; |
| 87 | 87 | } |
| 88 | − | |
| 89 | −#if defined(_WIN64) && defined(__aarch64__) | |
| 90 | −/* The bt-only Windows ARM64 build should not rely on importing this helper. */ | |
| 91 | −LONG InterlockedExchange(LONG volatile *Target, LONG Value) | |
| 92 | −{ | |
| 93 | − LONG Old = *Target; | |
| 94 | − *Target = Value; | |
| 95 | − return Old; | |
| 96 | −} | |
| 97 | −#endif | |
| @@ -1930,46 +1930,12 @@ dwarf_read_sleb128(unsigned char **ln, unsigned char *end) · 1929 unmodified lines | ||
| 1930 | 1930 | #if CONFIG_TCC_SEMLOCK |
| 1931 | 1931 | #if defined _WIN32 |
| 1932 | 1932 | typedef struct { volatile LONG init; CRITICAL_SECTION cs; } TCCSem; |
| 1933 | −#if defined __TINYC__ && (defined __aarch64__ || defined __arm64__) | |
| 1934 | −/* Windows/arm64 Interlocked* names are compiler intrinsics, not | |
| 1935 | − kernel32 exports, so tcc -run must not emit calls to them. */ | |
| 1936 | −# define TCC_SEM_USE_ATOMICS 1 | |
| 1937 | −enum { TCC_SEM_ATOMIC_SEQ_CST = 5 }; | |
| 1938 | −#endif | |
| 1939 | −static inline LONG tcc_sem_cmpxchg(volatile LONG *ptr, LONG val, LONG cmp) { | |
| 1940 | −#ifdef TCC_SEM_USE_ATOMICS | |
| 1941 | − LONG old = cmp; | |
| 1942 | − __atomic_compare_exchange((LONG *)ptr, &old, &val, 0, | |
| 1943 | − TCC_SEM_ATOMIC_SEQ_CST, | |
| 1944 | − TCC_SEM_ATOMIC_SEQ_CST); | |
| 1945 | − return old; | |
| 1946 | −#else | |
| 1947 | − return InterlockedCompareExchange(ptr, val, cmp); | |
| 1948 | −#endif | |
| 1949 | −} | |
| 1950 | −static inline void tcc_sem_store(volatile LONG *ptr, LONG val) { | |
| 1951 | −#ifdef TCC_SEM_USE_ATOMICS | |
| 1952 | − __atomic_store((LONG *)ptr, &val, TCC_SEM_ATOMIC_SEQ_CST); | |
| 1953 | −#else | |
| 1954 | − InterlockedExchange(ptr, val); | |
| 1955 | −#endif | |
| 1956 | −} | |
| 1957 | −static inline LONG tcc_sem_load(volatile LONG *ptr) { | |
| 1958 | −#ifdef TCC_SEM_USE_ATOMICS | |
| 1959 | − LONG val; | |
| 1960 | − __atomic_load((LONG *)ptr, &val, TCC_SEM_ATOMIC_SEQ_CST); | |
| 1961 | − return val; | |
| 1962 | −#else | |
| 1963 | − return InterlockedCompareExchange(ptr, 0, 0); | |
| 1964 | −#endif | |
| 1965 | −} | |
| 1966 | 1933 | static inline void wait_sem(TCCSem *p) { |
| 1967 | − if (tcc_sem_cmpxchg(&p->init, 1, 0) == 0) { | |
| 1934 | + if (InterlockedCompareExchange(&p->init, 1, 0) == 0) { | |
| 1968 | 1935 | InitializeCriticalSection(&p->cs); |
| 1969 | − tcc_sem_store(&p->init, 2); | |
| 1936 | + InterlockedExchange(&p->init, 2); | |
| 1970 | 1937 | } else { |
| 1971 | − /* On tcc/arm64, __atomic_load maps to the acquire helper path. */ | |
| 1972 | − while (tcc_sem_load(&p->init) != 2) | |
| 1938 | + while (InterlockedCompareExchange(&p->init, 2, 2) != 2) | |
| 1973 | 1939 | Sleep(0); |
| 1974 | 1940 | } |
| 1975 | 1941 | EnterCriticalSection(&p->cs); |
| @@ -0,0 +1,35 @@ | ||
| 1 | +#include <stdio.h> | |
| 2 | +#include <windows.h> | |
| 3 | + | |
| 4 | +#define PTR(x) ((PVOID)(ULONG_PTR)(x)) | |
| 5 | +#define CHECK(name, expr) printf("%s: %s\n", name, (expr) ? "yes" : "no") | |
| 6 | + | |
| 7 | +int main(void) | |
| 8 | +{ | |
| 9 | + PVOID volatile slot = PTR(0x1111222233334444ULL); | |
| 10 | + PVOID old; | |
| 11 | + | |
| 12 | + old = InterlockedExchangePointer(&slot, PTR(0x5555666677778888ULL)); | |
| 13 | + CHECK("exchange old", old == PTR(0x1111222233334444ULL)); | |
| 14 | + CHECK("exchange stored", slot == PTR(0x5555666677778888ULL)); | |
| 15 | + | |
| 16 | + old = InterlockedCompareExchangePointer(&slot, | |
| 17 | + PTR(0x9999aaaabbbbccccULL), | |
| 18 | + PTR(0x5555666677778888ULL)); | |
| 19 | + CHECK("compare old", old == PTR(0x5555666677778888ULL)); | |
| 20 | + CHECK("compare stored", slot == PTR(0x9999aaaabbbbccccULL)); | |
| 21 | + | |
| 22 | + old = InterlockedCompareExchangePointerAcquire(&slot, | |
| 23 | + PTR(0xdddd111122223333ULL), | |
| 24 | + PTR(0x0123456789abcdefULL)); | |
| 25 | + CHECK("acquire old", old == PTR(0x9999aaaabbbbccccULL)); | |
| 26 | + CHECK("acquire stored", slot == PTR(0x9999aaaabbbbccccULL)); | |
| 27 | + | |
| 28 | + old = InterlockedCompareExchangePointerRelease(&slot, | |
| 29 | + PTR(0xdddd111122223333ULL), | |
| 30 | + PTR(0x9999aaaabbbbccccULL)); | |
| 31 | + CHECK("release old", old == PTR(0x9999aaaabbbbccccULL)); | |
| 32 | + CHECK("release stored", slot == PTR(0xdddd111122223333ULL)); | |
| 33 | + | |
| 34 | + return 0; | |
| 35 | +} | |
| @@ -0,0 +1,8 @@ | ||
| 1 | +exchange old: yes | |
| 2 | +exchange stored: yes | |
| 3 | +compare old: yes | |
| 4 | +compare stored: yes | |
| 5 | +acquire old: yes | |
| 6 | +acquire stored: yes | |
| 7 | +release old: yes | |
| 8 | +release stored: yes | |
| @@ -65,6 +65,11 @@ ifeq (,$(filter arm64 aarch64,$(ARCH))) · 64 unmodified lines | ||
| 65 | 65 | SKIP += 139_arm64_errors.test |
| 66 | 66 | SKIP += 140_arm64_extasm.test |
| 67 | 67 | endif |
| 68 | +ifneq ($(CONFIG_WIN32),yes) | |
| 69 | + SKIP += 145_winarm64_interlocked.test | |
| 70 | +else ifeq (,$(filter arm64 aarch64,$(ARCH))) | |
| 71 | + SKIP += 145_winarm64_interlocked.test | |
| 72 | +endif | |
| 68 | 73 | ifeq (,$(filter riscv64,$(ARCH))) |
| 69 | 74 | SKIP += 141_riscv_asm.test # riscv64 asm |
| 70 | 75 | endif |
| @@ -972,7 +972,9 @@ extern "C" { · 971 unmodified lines | ||
| 972 | 972 | LONG WINAPI InterlockedDecrement(LONG volatile *lpAddend); |
| 973 | 973 | LONG WINAPI InterlockedExchange(LONG volatile *Target,LONG Value); |
| 974 | 974 | |
| 975 | +#ifndef InterlockedExchangePointer | |
| 975 | 976 | #define InterlockedExchangePointer(Target,Value) (PVOID)InterlockedExchange((PLONG)(Target),(LONG)(Value)) |
| 977 | +#endif | |
| 976 | 978 | |
| 977 | 979 | LONG WINAPI InterlockedExchangeAdd(LONG volatile *Addend,LONG Value); |
| 978 | 980 | LONG WINAPI InterlockedCompareExchange(LONG volatile *Destination,LONG Exchange,LONG Comperand); |
| @@ -1035,6 +1037,7 @@ extern "C" { · 56 unmodified lines | ||
| 1035 | 1037 | return Old; |
| 1036 | 1038 | } |
| 1037 | 1039 | |
| 1040 | +#ifndef InterlockedCompareExchangePointer | |
| 1038 | 1041 | #ifdef __cplusplus |
| 1039 | 1042 | __CRT_INLINE PVOID __cdecl __InlineInterlockedCompareExchangePointer(PVOID volatile *Destination,PVOID ExChange,PVOID Comperand) { |
| 1040 | 1043 | return((PVOID)(LONG_PTR)InterlockedCompareExchange((LONG volatile *)Destination,(LONG)(LONG_PTR)ExChange,(LONG)(LONG_PTR)Comperand)); |
| @@ -1043,6 +1046,7 @@ extern "C" { · 2 unmodified lines | ||
| 1043 | 1046 | #else |
| 1044 | 1047 | #define InterlockedCompareExchangePointer(Destination,ExChange,Comperand)(PVOID)(LONG_PTR)InterlockedCompareExchange((LONG volatile *)(Destination),(LONG)(LONG_PTR)(ExChange),(LONG)(LONG_PTR)(Comperand)) |
| 1045 | 1048 | #endif |
| 1049 | +#endif | |
| 1046 | 1050 | |
| 1047 | 1051 | #define InterlockedIncrementAcquire InterlockedIncrement |
| 1048 | 1052 | #define InterlockedIncrementRelease InterlockedIncrement |
| @@ -1054,9 +1058,13 @@ extern "C" { · 5 unmodified lines | ||
| 1054 | 1058 | #define InterlockedCompareExchangeRelease InterlockedCompareExchange |
| 1055 | 1059 | #define InterlockedCompareExchangeAcquire64 InterlockedCompareExchange64 |
| 1056 | 1060 | #define InterlockedCompareExchangeRelease64 InterlockedCompareExchange64 |
| 1061 | +#ifndef InterlockedCompareExchangePointerAcquire | |
| 1057 | 1062 | #define InterlockedCompareExchangePointerAcquire InterlockedCompareExchangePointer |
| 1063 | +#endif | |
| 1064 | +#ifndef InterlockedCompareExchangePointerRelease | |
| 1058 | 1065 | #define InterlockedCompareExchangePointerRelease InterlockedCompareExchangePointer |
| 1059 | 1066 | #endif |
| 1067 | +#endif | |
| 1060 | 1068 | |
| 1061 | 1069 | #if defined(_SLIST_HEADER_) && !defined(_NTOSP_) |
| 1062 | 1070 | WINBASEAPI VOID WINAPI InitializeSListHead(PSLIST_HEADER ListHead); |
| @@ -1419,6 +1419,69 @@ typedef DWORD LCID; · 1418 unmodified lines | ||
| 1419 | 1419 | #define OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK_EXPORT_NAME "OutOfProcessFunctionTableCallback" |
| 1420 | 1420 | #endif /* defined(__x86_64) && !defined(RC_INVOKED) */ |
| 1421 | 1421 | |
| 1422 | +#if defined(__TINYC__) && (defined(__aarch64__) || defined(__arm64__)) && !defined(RC_INVOKED) | |
| 1423 | + | |
| 1424 | +#define __TCC_WINNT_ATOMIC_SEQ_CST 5 | |
| 1425 | +/* TCC lowers __atomic_compare_exchange's fourth argument as weak, but the | |
| 1426 | + ARM64 helper reads it as success_memorder. Strong CAS passes weak == 0, | |
| 1427 | + so keep Interlocked's barriers explicit here. */ | |
| 1428 | +#define __TCC_WINNT_MEMORY_BARRIER() __asm__ __volatile__("dmb ish" : : : "memory") | |
| 1429 | + | |
| 1430 | +/* This covers the LONG operations needed by TCC's semaphore code and the | |
| 1431 | + pointer helpers that winbase.h exposes through Interlocked pointer macros. | |
| 1432 | + Add local helpers before relying on increment/decrement, add/exchange-add, | |
| 1433 | + bitwise, or 64-bit Interlocked forms on Windows ARM64 with TCC. */ | |
| 1434 | + | |
| 1435 | + __CRT_INLINE LONG InterlockedExchange(LONG volatile *Target,LONG Value) { | |
| 1436 | + LONG Old; | |
| 1437 | + __atomic_load(Target,&Old,__TCC_WINNT_ATOMIC_SEQ_CST); | |
| 1438 | + __TCC_WINNT_MEMORY_BARRIER(); | |
| 1439 | + while (!__atomic_compare_exchange(Target,&Old,&Value,0, | |
| 1440 | + __TCC_WINNT_ATOMIC_SEQ_CST,__TCC_WINNT_ATOMIC_SEQ_CST)) | |
| 1441 | + ; | |
| 1442 | + __TCC_WINNT_MEMORY_BARRIER(); | |
| 1443 | + return Old; | |
| 1444 | + } | |
| 1445 | + __CRT_INLINE LONG InterlockedCompareExchange(LONG volatile *Destination,LONG ExChange,LONG Comperand) { | |
| 1446 | + LONG Old = Comperand; | |
| 1447 | + __TCC_WINNT_MEMORY_BARRIER(); | |
| 1448 | + __atomic_compare_exchange(Destination,&Old,&ExChange,0, | |
| 1449 | + __TCC_WINNT_ATOMIC_SEQ_CST,__TCC_WINNT_ATOMIC_SEQ_CST); | |
| 1450 | + __TCC_WINNT_MEMORY_BARRIER(); | |
| 1451 | + return Old; | |
| 1452 | + } | |
| 1453 | + __CRT_INLINE PVOID __TCC_WINNT_InterlockedExchangePointer(PVOID volatile *Target,PVOID Value) { | |
| 1454 | + PVOID Old; | |
| 1455 | + __atomic_load(Target,&Old,__TCC_WINNT_ATOMIC_SEQ_CST); | |
| 1456 | + __TCC_WINNT_MEMORY_BARRIER(); | |
| 1457 | + while (!__atomic_compare_exchange(Target,&Old,&Value,0, | |
| 1458 | + __TCC_WINNT_ATOMIC_SEQ_CST,__TCC_WINNT_ATOMIC_SEQ_CST)) | |
| 1459 | + ; | |
| 1460 | + __TCC_WINNT_MEMORY_BARRIER(); | |
| 1461 | + return Old; | |
| 1462 | + } | |
| 1463 | + __CRT_INLINE PVOID __TCC_WINNT_InterlockedCompareExchangePointer(PVOID volatile *Destination,PVOID ExChange,PVOID Comperand) { | |
| 1464 | + PVOID Old = Comperand; | |
| 1465 | + __TCC_WINNT_MEMORY_BARRIER(); | |
| 1466 | + __atomic_compare_exchange(Destination,&Old,&ExChange,0, | |
| 1467 | + __TCC_WINNT_ATOMIC_SEQ_CST,__TCC_WINNT_ATOMIC_SEQ_CST); | |
| 1468 | + __TCC_WINNT_MEMORY_BARRIER(); | |
| 1469 | + return Old; | |
| 1470 | + } | |
| 1471 | + | |
| 1472 | +#define InterlockedExchangePointer __TCC_WINNT_InterlockedExchangePointer | |
| 1473 | +#define InterlockedCompareExchangePointer __TCC_WINNT_InterlockedCompareExchangePointer | |
| 1474 | +#define InterlockedCompareExchangePointerAcquire InterlockedCompareExchangePointer | |
| 1475 | +#define InterlockedCompareExchangePointerRelease InterlockedCompareExchangePointer | |
| 1476 | + | |
| 1477 | +#define InterlockedCompareExchangeAcquire InterlockedCompareExchange | |
| 1478 | +#define InterlockedCompareExchangeRelease InterlockedCompareExchange | |
| 1479 | + | |
| 1480 | +#undef __TCC_WINNT_MEMORY_BARRIER | |
| 1481 | +#undef __TCC_WINNT_ATOMIC_SEQ_CST | |
| 1482 | + | |
| 1483 | +#endif /* defined(__TINYC__) && (defined(__aarch64__) || defined(__arm64__)) && !defined(RC_INVOKED) */ | |
| 1484 | + | |
| 1422 | 1485 | #if defined(_ARM64_) |
| 1423 | 1486 | |
| 1424 | 1487 | /* ARM64 Context Definition */ |