authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2022-12-16 02:01:07-05:00
committergravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2023-01-01 16:44:28-05:00
log2d34477dbb895b7a37284b50ebc1feb23ef77a64
tree275c35872d56df2c5f8c4c8f6d4923ffd97e84c5
parentf155ef2f4b3243fd31ae910c66587d672402144e

cbe: msvc atomics

- Implement most atomic operations for msvc - Disable "atomicrmw with floats" test for cbe

3 files changed, 195 insertions(+), 46 deletions(-)

lib/zig.h+176-42
......@@ -146,22 +146,25 @@ typedef char bool;
146146#define zig_wasm_memory_grow(index, delta) zig_unimplemented()
147147#endif
148148
149#define zig_concat(lhs, rhs) lhs##rhs
150#define zig_expand_concat(lhs, rhs) zig_concat(lhs, rhs)
151
149152#if __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__)
150153#include <stdatomic.h>
151154#define zig_atomic(type) _Atomic(type)
152#define zig_cmpxchg_strong(obj, expected, desired, succ, fail) atomic_compare_exchange_strong_explicit(obj, &(expected), desired, succ, fail)
153#define zig_cmpxchg_weak(obj, expected, desired, succ, fail) atomic_compare_exchange_weak_explicit (obj, &(expected), desired, succ, fail)
154#define zig_atomicrmw_xchg(obj, arg, order) atomic_exchange_explicit (obj, arg, order)
155#define zig_atomicrmw_add(obj, arg, order) atomic_fetch_add_explicit (obj, arg, order)
156#define zig_atomicrmw_sub(obj, arg, order) atomic_fetch_sub_explicit (obj, arg, order)
157#define zig_atomicrmw_or(obj, arg, order) atomic_fetch_or_explicit (obj, arg, order)
158#define zig_atomicrmw_xor(obj, arg, order) atomic_fetch_xor_explicit (obj, arg, order)
159#define zig_atomicrmw_and(obj, arg, order) atomic_fetch_and_explicit (obj, arg, order)
160#define zig_atomicrmw_nand(obj, arg, order) __atomic_fetch_nand (obj, arg, order)
161#define zig_atomicrmw_min(obj, arg, order) __atomic_fetch_min (obj, arg, order)
162#define zig_atomicrmw_max(obj, arg, order) __atomic_fetch_max (obj, arg, order)
163#define zig_atomic_store(obj, arg, order) atomic_store_explicit (obj, arg, order)
164#define zig_atomic_load(obj, order) atomic_load_explicit (obj, order)
155#define zig_cmpxchg_strong(obj, expected, desired, succ, fail, type) atomic_compare_exchange_strong_explicit(obj, &(expected), desired, succ, fail)
156#define zig_cmpxchg_weak(obj, expected, desired, succ, fail, type) atomic_compare_exchange_weak_explicit (obj, &(expected), desired, succ, fail)
157#define zig_atomicrmw_xchg(obj, arg, order, type) atomic_exchange_explicit (obj, arg, order)
158#define zig_atomicrmw_add(obj, arg, order, type) atomic_fetch_add_explicit (obj, arg, order)
159#define zig_atomicrmw_sub(obj, arg, order, type) atomic_fetch_sub_explicit (obj, arg, order)
160#define zig_atomicrmw_or(obj, arg, order, type) atomic_fetch_or_explicit (obj, arg, order)
161#define zig_atomicrmw_xor(obj, arg, order, type) atomic_fetch_xor_explicit (obj, arg, order)
162#define zig_atomicrmw_and(obj, arg, order, type) atomic_fetch_and_explicit (obj, arg, order)
163#define zig_atomicrmw_nand(obj, arg, order, type) __atomic_fetch_nand (obj, arg, order)
164#define zig_atomicrmw_min(obj, arg, order, type) __atomic_fetch_min (obj, arg, order)
165#define zig_atomicrmw_max(obj, arg, order, type) __atomic_fetch_max (obj, arg, order)
166#define zig_atomic_store(obj, arg, order, type) atomic_store_explicit (obj, arg, order)
167#define zig_atomic_load(obj, order, type) atomic_load_explicit (obj, order)
165168#define zig_fence(order) atomic_thread_fence(order)
166169#elif defined(__GNUC__)
167170#define memory_order_relaxed __ATOMIC_RELAXED
......@@ -171,20 +174,44 @@ typedef char bool;
171174#define memory_order_acq_rel __ATOMIC_ACQ_REL
172175#define memory_order_seq_cst __ATOMIC_SEQ_CST
173176#define zig_atomic(type) type
174#define zig_cmpxchg_strong(obj, expected, desired, succ, fail) __atomic_compare_exchange_n(obj, &(expected), desired, false, succ, fail)
175#define zig_cmpxchg_weak(obj, expected, desired, succ, fail) __atomic_compare_exchange_n(obj, &(expected), desired, true , succ, fail)
176#define zig_atomicrmw_xchg(obj, arg, order) __atomic_exchange_n(obj, arg, order)
177#define zig_atomicrmw_add(obj, arg, order) __atomic_fetch_add (obj, arg, order)
178#define zig_atomicrmw_sub(obj, arg, order) __atomic_fetch_sub (obj, arg, order)
179#define zig_atomicrmw_or(obj, arg, order) __atomic_fetch_or (obj, arg, order)
180#define zig_atomicrmw_xor(obj, arg, order) __atomic_fetch_xor (obj, arg, order)
181#define zig_atomicrmw_and(obj, arg, order) __atomic_fetch_and (obj, arg, order)
182#define zig_atomicrmw_nand(obj, arg, order) __atomic_fetch_nand(obj, arg, order)
183#define zig_atomicrmw_min(obj, arg, order) __atomic_fetch_min (obj, arg, order)
184#define zig_atomicrmw_max(obj, arg, order) __atomic_fetch_max (obj, arg, order)
185#define zig_atomic_store(obj, arg, order) __atomic_store_n (obj, arg, order)
186#define zig_atomic_load(obj, order) __atomic_load_n (obj, order)
177#define zig_cmpxchg_strong(obj, expected, desired, succ, fail, types) __atomic_compare_exchange_n(obj, &(expected), desired, false, succ, fail)
178#define zig_cmpxchg_weak(obj, expected, desired, succ, fail, types) __atomic_compare_exchange_n(obj, &(expected), desired, true , succ, fail)
179#define zig_atomicrmw_xchg(obj, arg, order, type) __atomic_exchange_n(obj, arg, order)
180#define zig_atomicrmw_add(obj, arg, order, type) __atomic_fetch_add (obj, arg, order)
181#define zig_atomicrmw_sub(obj, arg, order, type) __atomic_fetch_sub (obj, arg, order)
182#define zig_atomicrmw_or(obj, arg, order, type) __atomic_fetch_or (obj, arg, order)
183#define zig_atomicrmw_xor(obj, arg, order, type) __atomic_fetch_xor (obj, arg, order)
184#define zig_atomicrmw_and(obj, arg, order, type) __atomic_fetch_and (obj, arg, order)
185#define zig_atomicrmw_nand(obj, arg, order, type) __atomic_fetch_nand(obj, arg, order)
186#define zig_atomicrmw_min(obj, arg, order, type) __atomic_fetch_min (obj, arg, order)
187#define zig_atomicrmw_max(obj, arg, order, type) __atomic_fetch_max (obj, arg, order)
188#define zig_atomic_store(obj, arg, order, type) __atomic_store_n (obj, arg, order)
189#define zig_atomic_load(obj, order, type) __atomic_load_n (obj, order)
187190#define zig_fence(order) __atomic_thread_fence(order)
191#elif _MSC_VER && (_M_IX86 || _M_X64)
192#include <intrin.h>
193#define memory_order_relaxed 0
194#define memory_order_consume 1
195#define memory_order_acquire 2
196#define memory_order_release 3
197#define memory_order_acq_rel 4
198#define memory_order_seq_cst 5
199#define zig_atomic(type) type
200#define zig_cmpxchg_strong(obj, expected, desired, succ, fail, type) zig_expand_concat(zig_msvc_cmpxchg_, type)(obj, expected, desired)
201#define zig_cmpxchg_weak(obj, expected, desired, succ, fail, type) zig_cmpxchg_strong(obj, expected, desired, succ, fail, type)
202#define zig_atomicrmw_xchg(obj, arg, order, type) zig_expand_concat(zig_msvc_atomicrmw_xchg_, type)(obj, arg)
203#define zig_atomicrmw_add(obj, arg, order, type) zig_expand_concat(zig_msvc_atomicrmw_add_, type)(obj, arg)
204#define zig_atomicrmw_sub(obj, arg, order, type) zig_expand_concat(zig_msvc_atomicrmw_sub_, type)(obj, arg)
205#define zig_atomicrmw_or(obj, arg, order, type) zig_expand_concat(zig_msvc_atomicrmw_or_, type)(obj, arg)
206#define zig_atomicrmw_xor(obj, arg, order, type) zig_expand_concat(zig_msvc_atomicrmw_xor_, type)(obj, arg)
207#define zig_atomicrmw_and(obj, arg, order, type) zig_expand_concat(zig_msvc_atomicrmw_and_, type)(obj, arg)
208#define zig_atomicrmw_nand(obj, arg, order, type) zig_expand_concat(zig_msvc_atomicrmw_nand_, type)(obj, arg)
209#define zig_atomicrmw_min(obj, arg, order, type) zig_expand_concat(zig_msvc_atomicrmw_min_, type)(obj, arg)
210#define zig_atomicrmw_max(obj, arg, order, type) zig_expand_concat(zig_msvc_atomicrmw_max_, type)(obj, arg)
211#define zig_atomic_store(obj, arg, order, type) zig_expand_concat(zig_msvc_atomic_store_, type)(obj, arg)
212#define zig_atomic_load(obj, order, type) zig_expand_concat(zig_msvc_atomic_load_, type)(obj)
213#define zig_fence(order) __faststorefence()
214// TODO: _MSC_VER && (_M_ARM || _M_ARM64)
188215#else
189216#define memory_order_relaxed 0
190217#define memory_order_consume 1
......@@ -193,19 +220,19 @@ typedef char bool;
193220#define memory_order_acq_rel 4
194221#define memory_order_seq_cst 5
195222#define zig_atomic(type) type
196#define zig_cmpxchg_strong(obj, expected, desired, succ, fail) zig_unimplemented()
197#define zig_cmpxchg_weak(obj, expected, desired, succ, fail) zig_unimplemented()
198#define zig_atomicrmw_xchg(obj, arg, order) zig_unimplemented()
199#define zig_atomicrmw_add(obj, arg, order) zig_unimplemented()
200#define zig_atomicrmw_sub(obj, arg, order) zig_unimplemented()
201#define zig_atomicrmw_or(obj, arg, order) zig_unimplemented()
202#define zig_atomicrmw_xor(obj, arg, order) zig_unimplemented()
203#define zig_atomicrmw_and(obj, arg, order) zig_unimplemented()
204#define zig_atomicrmw_nand(obj, arg, order) zig_unimplemented()
205#define zig_atomicrmw_min(obj, arg, order) zig_unimplemented()
206#define zig_atomicrmw_max(obj, arg, order) zig_unimplemented()
207#define zig_atomic_store(obj, arg, order) zig_unimplemented()
208#define zig_atomic_load(obj, order) zig_unimplemented()
223#define zig_cmpxchg_strong(obj, expected, desired, succ, fail, type) zig_unimplemented()
224#define zig_cmpxchg_weak(obj, expected, desired, succ, fail, type) zig_unimplemented()
225#define zig_atomicrmw_xchg(obj, arg, order, type) zig_unimplemented()
226#define zig_atomicrmw_add(obj, arg, order, type) zig_unimplemented()
227#define zig_atomicrmw_sub(obj, arg, order, type) zig_unimplemented()
228#define zig_atomicrmw_or(obj, arg, order, type) zig_unimplemented()
229#define zig_atomicrmw_xor(obj, arg, order, type) zig_unimplemented()
230#define zig_atomicrmw_and(obj, arg, order, type) zig_unimplemented()
231#define zig_atomicrmw_nand(obj, arg, order, type) zig_unimplemented()
232#define zig_atomicrmw_min(obj, arg, order, type) zig_unimplemented()
233#define zig_atomicrmw_max(obj, arg, order, type) zig_unimplemented()
234#define zig_atomic_store(obj, arg, order, type) zig_unimplemented()
235#define zig_atomic_load(obj, order, type) zig_unimplemented()
209236#define zig_fence(order) zig_unimplemented()
210237#endif
211238
......@@ -219,9 +246,6 @@ typedef char bool;
219246#define zig_noreturn void
220247#endif
221248
222#define zig_concat(lhs, rhs) lhs##rhs
223#define zig_expand_concat(lhs, rhs) zig_concat(lhs, rhs)
224
225249#define zig_bitSizeOf(T) (CHAR_BIT * sizeof(T))
226250
227251typedef uintptr_t zig_usize;
......@@ -1917,6 +1941,18 @@ typedef zig_i128 zig_c_longdouble;
19171941#define zig_as_special_constant_c_longdouble(sign, name, arg, repr) repr
19181942#endif
19191943
1944#if zig_bitSizeOf_c_longdouble == 16
1945#define zig_compiler_rt_abbrev_c_longdouble zig_compiler_rt_abbrev_f16
1946#elif zig_bitSizeOf_c_longdouble == 32
1947#define zig_compiler_rt_abbrev_c_longdouble zig_compiler_rt_abbrev_f32
1948#elif zig_bitSizeOf_c_longdouble == 64
1949#define zig_compiler_rt_abbrev_c_longdouble zig_compiler_rt_abbrev_f64
1950#elif zig_bitSizeOf_c_longdouble == 80
1951#define zig_compiler_rt_abbrev_c_longdouble zig_compiler_rt_abbrev_f80
1952#elif zig_bitSizeOf_c_longdouble == 128
1953#define zig_compiler_rt_abbrev_c_longdouble zig_compiler_rt_abbrev_f128
1954#endif
1955
19201956#define zig_cast_f16 (zig_f16)
19211957#define zig_cast_f32 (zig_f32)
19221958#define zig_cast_f64 (zig_f64)
......@@ -2054,3 +2090,101 @@ zig_float_builtins(f64)
20542090zig_float_builtins(f80)
20552091zig_float_builtins(f128)
20562092zig_float_builtins(c_longdouble)
2093
2094#if _MSC_VER && (_M_IX86 || _M_X64)
2095#include <intrin.h>
2096
2097// TODO: zig_msvc_atomic_load should load 32 bit without interlocked on x86, load 64 bit without interlocked on x64
2098// TODO: Fix obviously broken nand / min / max, these don't exist on msvc _InterlockedNand
2099
2100#define zig_msvc_atomics(type, suffix) \
2101 static inline bool zig_msvc_cmpxchg_##type(zig_##type volatile* obj, zig_##type expected, zig_##type desired) { \
2102 return _InterlockedCompareExchange##suffix(obj, desired, expected) == expected; \
2103 } \
2104 static inline zig_##type zig_msvc_atomicrmw_xchg_##type(zig_##type volatile* obj, zig_##type value) { \
2105 return _InterlockedExchange##suffix(obj, value); \
2106 } \
2107 static inline zig_##type zig_msvc_atomicrmw_add_##type(zig_##type volatile* obj, zig_##type value) { \
2108 return _InterlockedExchangeAdd##suffix(obj, value); \
2109 } \
2110 static inline zig_##type zig_msvc_atomicrmw_sub_##type(zig_##type volatile* obj, zig_##type value) { \
2111 return _InterlockedExchangeAdd##suffix(obj, -value); \
2112 } \
2113 static inline zig_##type zig_msvc_atomicrmw_or_##type(zig_##type volatile* obj, zig_##type value) { \
2114 return _InterlockedOr##suffix(obj, value); \
2115 } \
2116 static inline zig_##type zig_msvc_atomicrmw_xor_##type(zig_##type volatile* obj, zig_##type value) { \
2117 return _InterlockedXor##suffix(obj, value); \
2118 } \
2119 static inline zig_##type zig_msvc_atomicrmw_and_##type(zig_##type volatile* obj, zig_##type value) { \
2120 return _InterlockedAnd##suffix(obj, value); \
2121 } \
2122 static inline zig_##type zig_msvc_atomicrmw_nand_##type(zig_##type volatile* obj, zig_##type value) { \
2123 return 0; \
2124 } \
2125 static inline zig_##type zig_msvc_atomicrmw_min_##type(zig_##type volatile* obj, zig_##type value) { \
2126 return 0; \
2127 } \
2128 static inline zig_##type zig_msvc_atomicrmw_max_##type(zig_##type volatile* obj, zig_##type value) { \
2129 return 0; \
2130 } \
2131 static inline void zig_msvc_atomic_store_##type(zig_##type volatile* obj, zig_##type value) { \
2132 _InterlockedExchange##suffix(obj, value); \
2133 } \
2134 static inline zig_##type zig_msvc_atomic_load_##type(zig_##type volatile* obj) { \
2135 return _InterlockedOr##suffix(obj, 0); \
2136 }
2137
2138zig_msvc_atomics(u8, 8)
2139zig_msvc_atomics(i8, 8)
2140zig_msvc_atomics(u16, 16)
2141zig_msvc_atomics(i16, 16)
2142zig_msvc_atomics(u32, )
2143zig_msvc_atomics(i32, )
2144zig_msvc_atomics(u64, 64)
2145zig_msvc_atomics(i64, 64)
2146
2147static inline bool zig_msvc_cmpxchg_p32(void** obj, void* expected, void* desired) {
2148 return _InterlockedCompareExchangePointer(obj, desired, expected) == expected;
2149}
2150
2151static inline bool zig_msvc_cmpxchg_p64(void** obj, void* expected, void* desired) {
2152 return _InterlockedCompareExchangePointer(obj, desired, expected) == expected;
2153}
2154
2155#if _M_IX86
2156static inline void* zig_msvc_atomicrmw_xchg_p32(void** obj, zig_u32* arg) {
2157 return _InterlockedExchangePointer(obj, arg);
2158}
2159
2160static inline void zig_msvc_atomic_store_p32(void** obj, zig_u32* arg) {
2161 _InterlockedExchangePointer(obj, arg);
2162}
2163
2164static inline void* zig_msvc_atomic_load_p32(void** obj, zig_u32* arg) {
2165 return (void*)_InterlockedOr((void*)obj, 0);
2166}
2167#else
2168static inline void* zig_msvc_atomicrmw_xchg__p64(void** obj, zig_u64* arg) {
2169 return _InterlockedExchangePointer(obj, arg);
2170}
2171
2172static inline void zig_msvc_atomic_store_p64(void** obj, zig_u64* arg) {
2173 _InterlockedExchangePointer(obj, arg);
2174}
2175
2176static inline void* zig_msvc_atomic_load_p64(void** obj) {
2177 return (void*)_InterlockedOr64((void*)obj, 0);
2178}
2179#endif
2180
2181static inline bool zig_msvc_cmpxchg_u128(zig_u128 volatile* obj, zig_u128 expected, zig_u128 desired) {
2182 zig_u128 comparand_result = desired;
2183 return _InterlockedCompareExchange128((zig_i64 volatile*)obj, expected.hi, expected.lo, (zig_i64*)&comparand_result);
2184}
2185
2186static inline bool zig_msvc_cmpxchg_i128(zig_i128 volatile* obj, zig_i128 expected, zig_i128 desired) {
2187 zig_i128 comparand_result = desired;
2188 return _InterlockedCompareExchange128((zig_i64 volatile*)obj, expected.hi, expected.lo, (zig_u64*)&comparand_result);
2189}
2190#endif
src/codegen/c.zig+18-4
......@@ -2542,6 +2542,10 @@ pub const DeclGen = struct {
25422542 try writer.print("{c}{d}", .{ signAbbrev(int_info.signedness), c_bits });
25432543 } else if (ty.isRuntimeFloat()) {
25442544 try ty.print(writer, dg.module);
2545 } else if (ty.isPtrAtRuntime()) {
2546 try writer.print("p{d}", .{ ty.bitSize(target) });
2547 } else if (ty.zigTypeTag() == .Bool) {
2548 try writer.print("u8", .{});
25452549 } else return dg.fail("TODO: CBE: implement renderTypeForBuiltinFnName for type {}", .{
25462550 ty.fmt(dg.module),
25472551 });
......@@ -6083,7 +6087,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
60836087 try writer.writeAll(";\n");
60846088 try writer.writeAll("if (");
60856089 try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor});
6086 try f.renderTypecast(writer, ptr_ty.elemType());
6090 try f.renderTypecast(writer, ptr_ty.childType());
60876091 try writer.writeByte(')');
60886092 if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile");
60896093 try writer.writeAll(" *)");
......@@ -6096,6 +6100,8 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
60966100 try writeMemoryOrder(writer, extra.successOrder());
60976101 try writer.writeAll(", ");
60986102 try writeMemoryOrder(writer, extra.failureOrder());
6103 try writer.writeAll(", ");
6104 try f.object.dg.renderTypeForBuiltinFnName(writer, ptr_ty.childType());
60996105 try writer.writeByte(')');
61006106 try writer.writeAll(") {\n");
61016107 f.object.indent_writer.pushIndent();
......@@ -6110,7 +6116,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
61106116 try writer.writeAll(";\n");
61116117 try f.writeCValue(writer, local, .Other);
61126118 try writer.print(".is_null = zig_cmpxchg_{s}((zig_atomic(", .{flavor});
6113 try f.renderTypecast(writer, ptr_ty.elemType());
6119 try f.renderTypecast(writer, ptr_ty.childType());
61146120 try writer.writeByte(')');
61156121 if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile");
61166122 try writer.writeAll(" *)");
......@@ -6123,6 +6129,8 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
61236129 try writeMemoryOrder(writer, extra.successOrder());
61246130 try writer.writeAll(", ");
61256131 try writeMemoryOrder(writer, extra.failureOrder());
6132 try writer.writeAll(", ");
6133 try f.object.dg.renderTypeForBuiltinFnName(writer, ptr_ty.childType());
61266134 try writer.writeByte(')');
61276135 try writer.writeAll(";\n");
61286136 }
......@@ -6145,8 +6153,8 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
61456153 try reap(f, inst, &.{ pl_op.operand, extra.operand });
61466154 const writer = f.object.writer();
61476155 const local = try f.allocLocal(inst, inst_ty);
6148 try f.writeCValue(writer, local, .Other);
61496156
6157 try f.writeCValue(writer, local, .Other);
61506158 try writer.print(" = zig_atomicrmw_{s}((", .{toAtomicRmwSuffix(extra.op())});
61516159 switch (extra.op()) {
61526160 else => {
......@@ -6166,6 +6174,8 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
61666174 try f.writeCValue(writer, operand, .FunctionArgument);
61676175 try writer.writeAll(", ");
61686176 try writeMemoryOrder(writer, extra.ordering());
6177 try writer.writeAll(", ");
6178 try f.object.dg.renderTypeForBuiltinFnName(writer, ptr_ty.childType());
61696179 try writer.writeAll(");\n");
61706180
61716181 if (f.liveness.isUnused(inst)) {
......@@ -6198,6 +6208,8 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {
61986208 try f.writeCValue(writer, ptr, .Other);
61996209 try writer.writeAll(", ");
62006210 try writeMemoryOrder(writer, atomic_load.order);
6211 try writer.writeAll(", ");
6212 try f.object.dg.renderTypeForBuiltinFnName(writer, ptr_ty.childType());
62016213 try writer.writeAll(");\n");
62026214
62036215 return local;
......@@ -6219,7 +6231,9 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa
62196231 try f.writeCValue(writer, ptr, .Other);
62206232 try writer.writeAll(", ");
62216233 try f.writeCValue(writer, element, .FunctionArgument);
6222 try writer.print(", {s});\n", .{order});
6234 try writer.print(", {s}, ", .{order});
6235 try f.object.dg.renderTypeForBuiltinFnName(writer, ptr_ty.childType());
6236 try writer.writeAll(");\n");
62236237
62246238 return CValue.none;
62256239}
test/behavior/atomics.zig+1
......@@ -217,6 +217,7 @@ test "atomicrmw with floats" {
217217 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
218218 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
219219 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
220 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
220221
221222 if ((builtin.zig_backend == .stage2_llvm or builtin.zig_backend == .stage2_c) and
222223 builtin.cpu.arch == .aarch64)