| ... | ... | @@ -2097,49 +2097,80 @@ zig_float_builtins(c_longdouble) |
| 2097 | 2097 | #include <intrin.h> |
| 2098 | 2098 | |
| 2099 | 2099 | // TODO: zig_msvc_atomic_load should just load 32 bit without interlocked on x86, and just load 64 bit without interlocked on x64 |
| 2100 | | // TODO: Fix obviously broken nand / min / max, these don't exist on msvc |
| 2101 | 2100 | |
| 2102 | | #define zig_msvc_atomics(type, suffix) \ |
| 2103 | | static inline bool zig_msvc_cmpxchg_##type(zig_##type volatile* obj, zig_##type* expected, zig_##type desired) { \ |
| 2104 | | zig_##type comparand = *expected; \ |
| 2105 | | zig_##type initial = _InterlockedCompareExchange##suffix(obj, desired, comparand); \ |
| 2101 | #define zig_msvc_atomics(Type, suffix) \ |
| 2102 | static inline bool zig_msvc_cmpxchg_##Type(zig_##Type volatile* obj, zig_##Type* expected, zig_##Type desired) { \ |
| 2103 | zig_##Type comparand = *expected; \ |
| 2104 | zig_##Type initial = _InterlockedCompareExchange##suffix(obj, desired, comparand); \ |
| 2106 | 2105 | bool exchanged = initial == comparand; \ |
| 2107 | 2106 | if (!exchanged) { \ |
| 2108 | 2107 | *expected = initial; \ |
| 2109 | 2108 | } \ |
| 2110 | 2109 | return exchanged; \ |
| 2111 | 2110 | } \ |
| 2112 | | static inline zig_##type zig_msvc_atomicrmw_xchg_##type(zig_##type volatile* obj, zig_##type value) { \ |
| 2111 | static inline zig_##Type zig_msvc_atomicrmw_xchg_##Type(zig_##Type volatile* obj, zig_##Type value) { \ |
| 2113 | 2112 | return _InterlockedExchange##suffix(obj, value); \ |
| 2114 | 2113 | } \ |
| 2115 | | static inline zig_##type zig_msvc_atomicrmw_add_##type(zig_##type volatile* obj, zig_##type value) { \ |
| 2114 | static inline zig_##Type zig_msvc_atomicrmw_add_##Type(zig_##Type volatile* obj, zig_##Type value) { \ |
| 2116 | 2115 | return _InterlockedExchangeAdd##suffix(obj, value); \ |
| 2117 | 2116 | } \ |
| 2118 | | static inline zig_##type zig_msvc_atomicrmw_sub_##type(zig_##type volatile* obj, zig_##type value) { \ |
| 2119 | | return _InterlockedExchangeAdd##suffix(obj, -value); \ |
| 2117 | static inline zig_##Type zig_msvc_atomicrmw_sub_##Type(zig_##Type volatile* obj, zig_##Type value) { \ |
| 2118 | bool success = false; \ |
| 2119 | zig_##Type new; \ |
| 2120 | zig_##Type prev; \ |
| 2121 | while (!success) { \ |
| 2122 | prev = *obj; \ |
| 2123 | new = prev - value; \ |
| 2124 | success = zig_msvc_cmpxchg_##Type(obj, &prev, new); \ |
| 2125 | } \ |
| 2126 | return prev; \ |
| 2120 | 2127 | } \ |
| 2121 | | static inline zig_##type zig_msvc_atomicrmw_or_##type(zig_##type volatile* obj, zig_##type value) { \ |
| 2128 | static inline zig_##Type zig_msvc_atomicrmw_or_##Type(zig_##Type volatile* obj, zig_##Type value) { \ |
| 2122 | 2129 | return _InterlockedOr##suffix(obj, value); \ |
| 2123 | 2130 | } \ |
| 2124 | | static inline zig_##type zig_msvc_atomicrmw_xor_##type(zig_##type volatile* obj, zig_##type value) { \ |
| 2131 | static inline zig_##Type zig_msvc_atomicrmw_xor_##Type(zig_##Type volatile* obj, zig_##Type value) { \ |
| 2125 | 2132 | return _InterlockedXor##suffix(obj, value); \ |
| 2126 | 2133 | } \ |
| 2127 | | static inline zig_##type zig_msvc_atomicrmw_and_##type(zig_##type volatile* obj, zig_##type value) { \ |
| 2134 | static inline zig_##Type zig_msvc_atomicrmw_and_##Type(zig_##Type volatile* obj, zig_##Type value) { \ |
| 2128 | 2135 | return _InterlockedAnd##suffix(obj, value); \ |
| 2129 | 2136 | } \ |
| 2130 | | static inline zig_##type zig_msvc_atomicrmw_nand_##type(zig_##type volatile* obj, zig_##type value) { \ |
| 2131 | | return 0; \ |
| 2137 | static inline zig_##Type zig_msvc_atomicrmw_nand_##Type(zig_##Type volatile* obj, zig_##Type value) { \ |
| 2138 | bool success = false; \ |
| 2139 | zig_##Type new; \ |
| 2140 | zig_##Type prev; \ |
| 2141 | while (!success) { \ |
| 2142 | prev = *obj; \ |
| 2143 | new = ~(prev & value); \ |
| 2144 | success = zig_msvc_cmpxchg_##Type(obj, &prev, new); \ |
| 2145 | } \ |
| 2146 | return prev; \ |
| 2132 | 2147 | } \ |
| 2133 | | static inline zig_##type zig_msvc_atomicrmw_min_##type(zig_##type volatile* obj, zig_##type value) { \ |
| 2134 | | return 0; \ |
| 2148 | static inline zig_##Type zig_msvc_atomicrmw_min_##Type(zig_##Type volatile* obj, zig_##Type value) { \ |
| 2149 | bool success = false; \ |
| 2150 | zig_##Type new; \ |
| 2151 | zig_##Type prev; \ |
| 2152 | while (!success) { \ |
| 2153 | prev = *obj; \ |
| 2154 | new = value < prev ? value : prev; \ |
| 2155 | success = zig_msvc_cmpxchg_##Type(obj, &prev, new); \ |
| 2156 | } \ |
| 2157 | return prev; \ |
| 2135 | 2158 | } \ |
| 2136 | | static inline zig_##type zig_msvc_atomicrmw_max_##type(zig_##type volatile* obj, zig_##type value) { \ |
| 2137 | | return 0; \ |
| 2159 | static inline zig_##Type zig_msvc_atomicrmw_max_##Type(zig_##Type volatile* obj, zig_##Type value) { \ |
| 2160 | bool success = false; \ |
| 2161 | zig_##Type new; \ |
| 2162 | zig_##Type prev; \ |
| 2163 | while (!success) { \ |
| 2164 | prev = *obj; \ |
| 2165 | new = value > prev ? value : prev; \ |
| 2166 | success = zig_msvc_cmpxchg_##Type(obj, &prev, new); \ |
| 2167 | } \ |
| 2168 | return prev; \ |
| 2138 | 2169 | } \ |
| 2139 | | static inline void zig_msvc_atomic_store_##type(zig_##type volatile* obj, zig_##type value) { \ |
| 2170 | static inline void zig_msvc_atomic_store_##Type(zig_##Type volatile* obj, zig_##Type value) { \ |
| 2140 | 2171 | _InterlockedExchange##suffix(obj, value); \ |
| 2141 | 2172 | } \ |
| 2142 | | static inline zig_##type zig_msvc_atomic_load_##type(zig_##type volatile* obj) { \ |
| 2173 | static inline zig_##Type zig_msvc_atomic_load_##Type(zig_##Type volatile* obj) { \ |
| 2143 | 2174 | return _InterlockedOr##suffix(obj, 0); \ |
| 2144 | 2175 | } |
| 2145 | 2176 | |
| ... | ... | @@ -2152,26 +2183,6 @@ zig_msvc_atomics(i32, ) |
| 2152 | 2183 | zig_msvc_atomics(u64, 64) |
| 2153 | 2184 | zig_msvc_atomics(i64, 64) |
| 2154 | 2185 | |
| 2155 | | static inline bool zig_msvc_cmpxchg_p32(void** obj, void** expected, void* desired) { |
| 2156 | | void* comparand = *expected; |
| 2157 | | void* initial = _InterlockedCompareExchangePointer(obj, desired, comparand); |
| 2158 | | bool exchanged = initial == comparand; |
| 2159 | | if (!exchanged) { |
| 2160 | | *expected = initial; |
| 2161 | | } |
| 2162 | | return exchanged; |
| 2163 | | } |
| 2164 | | |
| 2165 | | static inline bool zig_msvc_cmpxchg_p64(void** obj, void** expected, void* desired) { |
| 2166 | | void* comparand = *expected; |
| 2167 | | void* initial = _InterlockedCompareExchangePointer(obj, desired, comparand); |
| 2168 | | bool exchanged = initial == comparand; |
| 2169 | | if (!exchanged) { |
| 2170 | | *expected = initial; |
| 2171 | | } |
| 2172 | | return exchanged; |
| 2173 | | } |
| 2174 | | |
| 2175 | 2186 | #if _M_IX86 |
| 2176 | 2187 | static inline void* zig_msvc_atomicrmw_xchg_p32(void** obj, zig_u32* arg) { |
| 2177 | 2188 | return _InterlockedExchangePointer(obj, arg); |
| ... | ... | @@ -2184,8 +2195,18 @@ static inline void zig_msvc_atomic_store_p32(void** obj, zig_u32* arg) { |
| 2184 | 2195 | static inline void* zig_msvc_atomic_load_p32(void** obj, zig_u32* arg) { |
| 2185 | 2196 | return (void*)_InterlockedOr((void*)obj, 0); |
| 2186 | 2197 | } |
| 2198 | |
| 2199 | static inline bool zig_msvc_cmpxchg_p32(void** obj, void** expected, void* desired) { |
| 2200 | void* comparand = *expected; |
| 2201 | void* initial = _InterlockedCompareExchangePointer(obj, desired, comparand); |
| 2202 | bool exchanged = initial == comparand; |
| 2203 | if (!exchanged) { |
| 2204 | *expected = initial; |
| 2205 | } |
| 2206 | return exchanged; |
| 2207 | } |
| 2187 | 2208 | #else |
| 2188 | | static inline void* zig_msvc_atomicrmw_xchg__p64(void** obj, zig_u64* arg) { |
| 2209 | static inline void* zig_msvc_atomicrmw_xchg_p64(void** obj, zig_u64* arg) { |
| 2189 | 2210 | return _InterlockedExchangePointer(obj, arg); |
| 2190 | 2211 | } |
| 2191 | 2212 | |
| ... | ... | @@ -2196,6 +2217,16 @@ static inline void zig_msvc_atomic_store_p64(void** obj, zig_u64* arg) { |
| 2196 | 2217 | static inline void* zig_msvc_atomic_load_p64(void** obj) { |
| 2197 | 2218 | return (void*)_InterlockedOr64((void*)obj, 0); |
| 2198 | 2219 | } |
| 2220 | |
| 2221 | static inline bool zig_msvc_cmpxchg_p64(void** obj, void** expected, void* desired) { |
| 2222 | void* comparand = *expected; |
| 2223 | void* initial = _InterlockedCompareExchangePointer(obj, desired, comparand); |
| 2224 | bool exchanged = initial == comparand; |
| 2225 | if (!exchanged) { |
| 2226 | *expected = initial; |
| 2227 | } |
| 2228 | return exchanged; |
| 2229 | } |
| 2199 | 2230 | #endif |
| 2200 | 2231 | |
| 2201 | 2232 | static inline bool zig_msvc_cmpxchg_u128(zig_u128 volatile* obj, zig_u128* expected, zig_u128 desired) { |
| ... | ... | @@ -2205,4 +2236,5 @@ static inline bool zig_msvc_cmpxchg_u128(zig_u128 volatile* obj, zig_u128* expec |
| 2205 | 2236 | static inline bool zig_msvc_cmpxchg_i128(zig_i128 volatile* obj, zig_i128* expected, zig_i128 desired) { |
| 2206 | 2237 | return _InterlockedCompareExchange128((zig_i64 volatile*)obj, desired.hi, desired.lo, (zig_u64*)expected); |
| 2207 | 2238 | } |
| 2239 | |
| 2208 | 2240 | #endif |