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 | buf[l] = 0; | 85 | buf[l] = 0; |
| 86 | return buf; | 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 | #if CONFIG_TCC_SEMLOCK | 1930 | #if CONFIG_TCC_SEMLOCK |
| 1931 | #if defined _WIN32 | 1931 | #if defined _WIN32 |
| 1932 | typedef struct { volatile LONG init; CRITICAL_SECTION cs; } TCCSem; | 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 | static inline void wait_sem(TCCSem *p) { | 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 | InitializeCriticalSection(&p->cs); | 1935 | InitializeCriticalSection(&p->cs); |
| 1969 | tcc_sem_store(&p->init, 2); | 1936 | InterlockedExchange(&p->init, 2); |
| 1970 | } else { | 1937 | } else { |
| 1971 | /* On tcc/arm64, __atomic_load maps to the acquire helper path. */ | 1938 | while (InterlockedCompareExchange(&p->init, 2, 2) != 2) |
| 1972 | while (tcc_sem_load(&p->init) != 2) | ||
| 1973 | Sleep(0); | 1939 | Sleep(0); |
| 1974 | } | 1940 | } |
| 1975 | EnterCriticalSection(&p->cs); | 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 | SKIP += 139_arm64_errors.test | 65 | SKIP += 139_arm64_errors.test |
| 66 | SKIP += 140_arm64_extasm.test | 66 | SKIP += 140_arm64_extasm.test |
| 67 | endif | 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 | ifeq (,$(filter riscv64,$(ARCH))) | 73 | ifeq (,$(filter riscv64,$(ARCH))) |
| 69 | SKIP += 141_riscv_asm.test # riscv64 asm | 74 | SKIP += 141_riscv_asm.test # riscv64 asm |
| 70 | endif | 75 | endif |
| @@ -972,7 +972,9 @@ extern "C" { · 971 unmodified lines | |||
| 972 | LONG WINAPI InterlockedDecrement(LONG volatile *lpAddend); | 972 | LONG WINAPI InterlockedDecrement(LONG volatile *lpAddend); |
| 973 | LONG WINAPI InterlockedExchange(LONG volatile *Target,LONG Value); | 973 | LONG WINAPI InterlockedExchange(LONG volatile *Target,LONG Value); |
| 974 | 974 | ||
| 975 | #ifndef InterlockedExchangePointer | ||
| 975 | #define InterlockedExchangePointer(Target,Value) (PVOID)InterlockedExchange((PLONG)(Target),(LONG)(Value)) | 976 | #define InterlockedExchangePointer(Target,Value) (PVOID)InterlockedExchange((PLONG)(Target),(LONG)(Value)) |
| 977 | #endif | ||
| 976 | 978 | ||
| 977 | LONG WINAPI InterlockedExchangeAdd(LONG volatile *Addend,LONG Value); | 979 | LONG WINAPI InterlockedExchangeAdd(LONG volatile *Addend,LONG Value); |
| 978 | LONG WINAPI InterlockedCompareExchange(LONG volatile *Destination,LONG Exchange,LONG Comperand); | 980 | LONG WINAPI InterlockedCompareExchange(LONG volatile *Destination,LONG Exchange,LONG Comperand); |
| @@ -1035,6 +1037,7 @@ extern "C" { · 56 unmodified lines | |||
| 1035 | return Old; | 1037 | return Old; |
| 1036 | } | 1038 | } |
| 1037 | 1039 | ||
| 1040 | #ifndef InterlockedCompareExchangePointer | ||
| 1038 | #ifdef __cplusplus | 1041 | #ifdef __cplusplus |
| 1039 | __CRT_INLINE PVOID __cdecl __InlineInterlockedCompareExchangePointer(PVOID volatile *Destination,PVOID ExChange,PVOID Comperand) { | 1042 | __CRT_INLINE PVOID __cdecl __InlineInterlockedCompareExchangePointer(PVOID volatile *Destination,PVOID ExChange,PVOID Comperand) { |
| 1040 | return((PVOID)(LONG_PTR)InterlockedCompareExchange((LONG volatile *)Destination,(LONG)(LONG_PTR)ExChange,(LONG)(LONG_PTR)Comperand)); | 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 | #else | 1046 | #else |
| 1044 | #define InterlockedCompareExchangePointer(Destination,ExChange,Comperand)(PVOID)(LONG_PTR)InterlockedCompareExchange((LONG volatile *)(Destination),(LONG)(LONG_PTR)(ExChange),(LONG)(LONG_PTR)(Comperand)) | 1047 | #define InterlockedCompareExchangePointer(Destination,ExChange,Comperand)(PVOID)(LONG_PTR)InterlockedCompareExchange((LONG volatile *)(Destination),(LONG)(LONG_PTR)(ExChange),(LONG)(LONG_PTR)(Comperand)) |
| 1045 | #endif | 1048 | #endif |
| 1049 | #endif | ||
| 1046 | 1050 | ||
| 1047 | #define InterlockedIncrementAcquire InterlockedIncrement | 1051 | #define InterlockedIncrementAcquire InterlockedIncrement |
| 1048 | #define InterlockedIncrementRelease InterlockedIncrement | 1052 | #define InterlockedIncrementRelease InterlockedIncrement |
| @@ -1054,9 +1058,13 @@ extern "C" { · 5 unmodified lines | |||
| 1054 | #define InterlockedCompareExchangeRelease InterlockedCompareExchange | 1058 | #define InterlockedCompareExchangeRelease InterlockedCompareExchange |
| 1055 | #define InterlockedCompareExchangeAcquire64 InterlockedCompareExchange64 | 1059 | #define InterlockedCompareExchangeAcquire64 InterlockedCompareExchange64 |
| 1056 | #define InterlockedCompareExchangeRelease64 InterlockedCompareExchange64 | 1060 | #define InterlockedCompareExchangeRelease64 InterlockedCompareExchange64 |
| 1061 | #ifndef InterlockedCompareExchangePointerAcquire | ||
| 1057 | #define InterlockedCompareExchangePointerAcquire InterlockedCompareExchangePointer | 1062 | #define InterlockedCompareExchangePointerAcquire InterlockedCompareExchangePointer |
| 1063 | #endif | ||
| 1064 | #ifndef InterlockedCompareExchangePointerRelease | ||
| 1058 | #define InterlockedCompareExchangePointerRelease InterlockedCompareExchangePointer | 1065 | #define InterlockedCompareExchangePointerRelease InterlockedCompareExchangePointer |
| 1059 | #endif | 1066 | #endif |
| 1067 | #endif | ||
| 1060 | 1068 | ||
| 1061 | #if defined(_SLIST_HEADER_) && !defined(_NTOSP_) | 1069 | #if defined(_SLIST_HEADER_) && !defined(_NTOSP_) |
| 1062 | WINBASEAPI VOID WINAPI InitializeSListHead(PSLIST_HEADER ListHead); | 1070 | WINBASEAPI VOID WINAPI InitializeSListHead(PSLIST_HEADER ListHead); |
| @@ -1419,6 +1419,69 @@ typedef DWORD LCID; · 1418 unmodified lines | |||
| 1419 | #define OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK_EXPORT_NAME "OutOfProcessFunctionTableCallback" | 1419 | #define OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK_EXPORT_NAME "OutOfProcessFunctionTableCallback" |
| 1420 | #endif /* defined(__x86_64) && !defined(RC_INVOKED) */ | 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 | #if defined(_ARM64_) | 1485 | #if defined(_ARM64_) |
| 1423 | 1486 | ||
| 1424 | /* ARM64 Context Definition */ | 1487 | /* ARM64 Context Definition */ |