| author | |
| committer | |
| log | 043b1adb8dff184deaf9e145e6045b36b9bf733b |
| tree | 30c1e0e35c1e9b289ca1590431a59d9d44565520 |
| parent | 163d505e27bfbdb0aed30339fcc98c0f5f364e7a |
| signature |
closes #1165028 files changed, 25 insertions(+), 271 deletions(-)
doc/langref.html.in+6-16| ... | ... | @@ -4218,11 +4218,10 @@ pub fn print(self: *Writer, arg0: []const u8, arg1: i32) !void { |
| 4218 | 4218 | {#header_close#} |
| 4219 | 4219 | |
| 4220 | 4220 | {#header_open|Atomics#} |
| 4221 | <p>TODO: @fence()</p> | |
| 4222 | 4221 | <p>TODO: @atomic rmw</p> |
| 4223 | 4222 | <p>TODO: builtin atomic memory ordering enum</p> |
| 4224 | 4223 | |
| 4225 | {#see_also|@atomicLoad|@atomicStore|@atomicRmw|@fence|@cmpxchgWeak|@cmpxchgStrong#} | |
| 4224 | {#see_also|@atomicLoad|@atomicStore|@atomicRmw|@cmpxchgWeak|@cmpxchgStrong#} | |
| 4226 | 4225 | |
| 4227 | 4226 | {#header_close#} |
| 4228 | 4227 | |
| ... | ... | @@ -4307,7 +4306,7 @@ comptime { |
| 4307 | 4306 | an integer or an enum. |
| 4308 | 4307 | </p> |
| 4309 | 4308 | <p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p> |
| 4310 | {#see_also|@atomicStore|@atomicRmw|@fence|@cmpxchgWeak|@cmpxchgStrong#} | |
| 4309 | {#see_also|@atomicStore|@atomicRmw||@cmpxchgWeak|@cmpxchgStrong#} | |
| 4311 | 4310 | {#header_close#} |
| 4312 | 4311 | |
| 4313 | 4312 | {#header_open|@atomicRmw#} |
| ... | ... | @@ -4322,7 +4321,7 @@ comptime { |
| 4322 | 4321 | </p> |
| 4323 | 4322 | <p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p> |
| 4324 | 4323 | <p>{#syntax#}AtomicRmwOp{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicRmwOp{#endsyntax#}.</p> |
| 4325 | {#see_also|@atomicStore|@atomicLoad|@fence|@cmpxchgWeak|@cmpxchgStrong#} | |
| 4324 | {#see_also|@atomicStore|@atomicLoad|@cmpxchgWeak|@cmpxchgStrong#} | |
| 4326 | 4325 | {#header_close#} |
| 4327 | 4326 | |
| 4328 | 4327 | {#header_open|@atomicStore#} |
| ... | ... | @@ -4335,7 +4334,7 @@ comptime { |
| 4335 | 4334 | an integer or an enum. |
| 4336 | 4335 | </p> |
| 4337 | 4336 | <p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p> |
| 4338 | {#see_also|@atomicLoad|@atomicRmw|@fence|@cmpxchgWeak|@cmpxchgStrong#} | |
| 4337 | {#see_also|@atomicLoad|@atomicRmw|@cmpxchgWeak|@cmpxchgStrong#} | |
| 4339 | 4338 | {#header_close#} |
| 4340 | 4339 | |
| 4341 | 4340 | {#header_open|@bitCast#} |
| ... | ... | @@ -4568,7 +4567,7 @@ comptime { |
| 4568 | 4567 | </p> |
| 4569 | 4568 | <p>{#syntax#}@typeInfo(@TypeOf(ptr)).pointer.alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p> |
| 4570 | 4569 | <p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p> |
| 4571 | {#see_also|@atomicStore|@atomicLoad|@atomicRmw|@fence|@cmpxchgWeak#} | |
| 4570 | {#see_also|@atomicStore|@atomicLoad|@atomicRmw|@cmpxchgWeak#} | |
| 4572 | 4571 | {#header_close#} |
| 4573 | 4572 | |
| 4574 | 4573 | {#header_open|@cmpxchgWeak#} |
| ... | ... | @@ -4600,7 +4599,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 4600 | 4599 | </p> |
| 4601 | 4600 | <p>{#syntax#}@typeInfo(@TypeOf(ptr)).pointer.alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p> |
| 4602 | 4601 | <p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p> |
| 4603 | {#see_also|@atomicStore|@atomicLoad|@atomicRmw|@fence|@cmpxchgStrong#} | |
| 4602 | {#see_also|@atomicStore|@atomicLoad|@atomicRmw|@cmpxchgStrong#} | |
| 4604 | 4603 | {#header_close#} |
| 4605 | 4604 | |
| 4606 | 4605 | {#header_open|@compileError#} |
| ... | ... | @@ -4857,15 +4856,6 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 4857 | 4856 | {#see_also|@export#} |
| 4858 | 4857 | {#header_close#} |
| 4859 | 4858 | |
| 4860 | {#header_open|@fence#} | |
| 4861 | <pre>{#syntax#}@fence(order: AtomicOrder) void{#endsyntax#}</pre> | |
| 4862 | <p> | |
| 4863 | The {#syntax#}fence{#endsyntax#} function is used to introduce happens-before edges between operations. | |
| 4864 | </p> | |
| 4865 | <p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p> | |
| 4866 | {#see_also|@atomicStore|@atomicLoad|@atomicRmw|@cmpxchgWeak|@cmpxchgStrong#} | |
| 4867 | {#header_close#} | |
| 4868 | ||
| 4869 | 4859 | {#header_open|@field#} |
| 4870 | 4860 | <pre>{#syntax#}@field(lhs: anytype, comptime field_name: []const u8) (field){#endsyntax#}</pre> |
| 4871 | 4861 | <p>Performs field access by a compile-time string. Works on both fields and declarations. |
lib/std/Thread/Futex.zig+6-15| ... | ... | @@ -794,9 +794,8 @@ const PosixImpl = struct { |
| 794 | 794 | // - T1: bumps pending waiters (was reordered after the ptr == expect check) |
| 795 | 795 | // - T1: goes to sleep and misses both the ptr change and T2's wake up |
| 796 | 796 | // |
| 797 | // seq_cst as Acquire barrier to ensure the announcement happens before the ptr check below. | |
| 798 | // seq_cst as shared modification order to form a happens-before edge with the fence(.seq_cst)+load() in wake(). | |
| 799 | var pending = bucket.pending.fetchAdd(1, .seq_cst); | |
| 797 | // acquire barrier to ensure the announcement happens before the ptr check below. | |
| 798 | var pending = bucket.pending.fetchAdd(1, .acquire); | |
| 800 | 799 | assert(pending < std.math.maxInt(usize)); |
| 801 | 800 | |
| 802 | 801 | // If the wait gets cancelled, remove the pending count we previously added. |
| ... | ... | @@ -858,15 +857,8 @@ const PosixImpl = struct { |
| 858 | 857 | // |
| 859 | 858 | // What we really want here is a Release load, but that doesn't exist under the C11 memory model. |
| 860 | 859 | // We could instead do `bucket.pending.fetchAdd(0, Release) == 0` which achieves effectively the same thing, |
| 861 | // but the RMW operation unconditionally marks the cache-line as modified for others causing unnecessary fetching/contention. | |
| 862 | // | |
| 863 | // Instead we opt to do a full-fence + load instead which avoids taking ownership of the cache-line. | |
| 864 | // fence(seq_cst) effectively converts the ptr update to seq_cst and the pending load to seq_cst: creating a Store-Load barrier. | |
| 865 | // | |
| 866 | // The pending count increment in wait() must also now use seq_cst for the update + this pending load | |
| 867 | // to be in the same modification order as our load isn't using release/acquire to guarantee it. | |
| 868 | bucket.pending.fence(.seq_cst); | |
| 869 | if (bucket.pending.load(.monotonic) == 0) { | |
| 860 | // LLVM lowers the fetchAdd(0, .release) into an mfence+load which avoids gaining ownership of the cache-line. | |
| 861 | if (bucket.pending.fetchAdd(0, .release) == 0) { | |
| 870 | 862 | return; |
| 871 | 863 | } |
| 872 | 864 | |
| ... | ... | @@ -979,15 +971,14 @@ test "broadcasting" { |
| 979 | 971 | fn wait(self: *@This()) !void { |
| 980 | 972 | // Decrement the counter. |
| 981 | 973 | // Release ensures stuff before this barrier.wait() happens before the last one. |
| 982 | const count = self.count.fetchSub(1, .release); | |
| 974 | // Acquire for the last counter ensures stuff before previous barrier.wait()s happened before it. | |
| 975 | const count = self.count.fetchSub(1, .acq_rel); | |
| 983 | 976 | try testing.expect(count <= num_threads); |
| 984 | 977 | try testing.expect(count > 0); |
| 985 | 978 | |
| 986 | 979 | // First counter to reach zero wakes all other threads. |
| 987 | // Acquire for the last counter ensures stuff before previous barrier.wait()s happened before it. | |
| 988 | 980 | // Release on futex update ensures stuff before all barrier.wait()'s happens before they all return. |
| 989 | 981 | if (count - 1 == 0) { |
| 990 | _ = self.count.load(.acquire); // TODO: could be fence(acquire) if not for TSAN | |
| 991 | 982 | self.futex.store(1, .release); |
| 992 | 983 | Futex.wake(&self.futex, num_threads - 1); |
| 993 | 984 | return; |
lib/std/Thread/ResetEvent.zig+3-5| ... | ... | @@ -112,9 +112,9 @@ const FutexImpl = struct { |
| 112 | 112 | // Try to set the state from `unset` to `waiting` to indicate |
| 113 | 113 | // to the set() thread that others are blocked on the ResetEvent. |
| 114 | 114 | // We avoid using any strict barriers until the end when we know the ResetEvent is set. |
| 115 | var state = self.state.load(.monotonic); | |
| 115 | var state = self.state.load(.acquire); | |
| 116 | 116 | if (state == unset) { |
| 117 | state = self.state.cmpxchgStrong(state, waiting, .monotonic, .monotonic) orelse waiting; | |
| 117 | state = self.state.cmpxchgStrong(state, waiting, .acquire, .acquire) orelse waiting; | |
| 118 | 118 | } |
| 119 | 119 | |
| 120 | 120 | // Wait until the ResetEvent is set since the state is waiting. |
| ... | ... | @@ -124,7 +124,7 @@ const FutexImpl = struct { |
| 124 | 124 | const wait_result = futex_deadline.wait(&self.state, waiting); |
| 125 | 125 | |
| 126 | 126 | // Check if the ResetEvent was set before possibly reporting error.Timeout below. |
| 127 | state = self.state.load(.monotonic); | |
| 127 | state = self.state.load(.acquire); | |
| 128 | 128 | if (state != waiting) { |
| 129 | 129 | break; |
| 130 | 130 | } |
| ... | ... | @@ -133,9 +133,7 @@ const FutexImpl = struct { |
| 133 | 133 | } |
| 134 | 134 | } |
| 135 | 135 | |
| 136 | // Acquire barrier ensures memory accesses before set() happen before we return. | |
| 137 | 136 | assert(state == is_set); |
| 138 | self.state.fence(.acquire); | |
| 139 | 137 | } |
| 140 | 138 | |
| 141 | 139 | fn set(self: *Impl) void { |
lib/std/Thread/WaitGroup.zig+1-2| ... | ... | @@ -15,11 +15,10 @@ pub fn start(self: *WaitGroup) void { |
| 15 | 15 | } |
| 16 | 16 | |
| 17 | 17 | pub fn finish(self: *WaitGroup) void { |
| 18 | const state = self.state.fetchSub(one_pending, .release); | |
| 18 | const state = self.state.fetchSub(one_pending, .acq_rel); | |
| 19 | 19 | assert((state / one_pending) > 0); |
| 20 | 20 | |
| 21 | 21 | if (state == (one_pending | is_waiting)) { |
| 22 | self.state.fence(.acquire); | |
| 23 | 22 | self.event.set(); |
| 24 | 23 | } |
| 25 | 24 | } |
lib/std/atomic.zig+8-34| ... | ... | @@ -10,31 +10,7 @@ pub fn Value(comptime T: type) type { |
| 10 | 10 | return .{ .raw = value }; |
| 11 | 11 | } |
| 12 | 12 | |
| 13 | /// Perform an atomic fence which uses the atomic value as a hint for | |
| 14 | /// the modification order. Use this when you want to imply a fence on | |
| 15 | /// an atomic variable without necessarily performing a memory access. | |
| 16 | pub inline fn fence(self: *Self, comptime order: AtomicOrder) void { | |
| 17 | // LLVM's ThreadSanitizer doesn't support the normal fences so we specialize for it. | |
| 18 | if (builtin.sanitize_thread) { | |
| 19 | const tsan = struct { | |
| 20 | extern "c" fn __tsan_acquire(addr: *anyopaque) void; | |
| 21 | extern "c" fn __tsan_release(addr: *anyopaque) void; | |
| 22 | }; | |
| 23 | ||
| 24 | const addr: *anyopaque = self; | |
| 25 | return switch (order) { | |
| 26 | .unordered, .monotonic => @compileError(@tagName(order) ++ " only applies to atomic loads and stores"), | |
| 27 | .acquire => tsan.__tsan_acquire(addr), | |
| 28 | .release => tsan.__tsan_release(addr), | |
| 29 | .acq_rel, .seq_cst => { | |
| 30 | tsan.__tsan_acquire(addr); | |
| 31 | tsan.__tsan_release(addr); | |
| 32 | }, | |
| 33 | }; | |
| 34 | } | |
| 35 | ||
| 36 | return @fence(order); | |
| 37 | } | |
| 13 | pub const fence = @compileError("@fence is deprecated, use other atomics to establish ordering"); | |
| 38 | 14 | |
| 39 | 15 | pub inline fn load(self: *const Self, comptime order: AtomicOrder) T { |
| 40 | 16 | return @atomicLoad(T, &self.raw, order); |
| ... | ... | @@ -148,21 +124,19 @@ test Value { |
| 148 | 124 | const RefCount = @This(); |
| 149 | 125 | |
| 150 | 126 | fn ref(rc: *RefCount) void { |
| 151 | // No ordering necessary; just updating a counter. | |
| 127 | // no synchronization necessary; just updating a counter. | |
| 152 | 128 | _ = rc.count.fetchAdd(1, .monotonic); |
| 153 | 129 | } |
| 154 | 130 | |
| 155 | 131 | fn unref(rc: *RefCount) void { |
| 156 | // Release ensures code before unref() happens-before the | |
| 132 | // release ensures code before unref() happens-before the | |
| 157 | 133 | // count is decremented as dropFn could be called by then. |
| 158 | 134 | if (rc.count.fetchSub(1, .release) == 1) { |
| 159 | // acquire ensures count decrement and code before | |
| 160 | // previous unrefs()s happens-before we call dropFn | |
| 161 | // below. | |
| 162 | // Another alternative is to use .acq_rel on the | |
| 163 | // fetchSub count decrement but it's extra barrier in | |
| 164 | // possibly hot path. | |
| 165 | rc.count.fence(.acquire); | |
| 135 | // seeing 1 in the counter means that other unref()s have happened, | |
| 136 | // but it doesn't mean that uses before each unref() are visible. | |
| 137 | // The load acquires the release-sequence created by previous unref()s | |
| 138 | // in order to ensure visibility of uses before dropping. | |
| 139 | _ = rc.count.load(.acquire); | |
| 166 | 140 | (rc.dropFn)(rc); |
| 167 | 141 | } |
| 168 | 142 | } |
lib/std/zig/AstGen.zig-10| ... | ... | @@ -2901,7 +2901,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As |
| 2901 | 2901 | .extended => switch (gz.astgen.instructions.items(.data)[@intFromEnum(inst)].extended.opcode) { |
| 2902 | 2902 | .breakpoint, |
| 2903 | 2903 | .disable_instrumentation, |
| 2904 | .fence, | |
| 2905 | 2904 | .set_float_mode, |
| 2906 | 2905 | .set_align_stack, |
| 2907 | 2906 | .branch_hint, |
| ... | ... | @@ -9307,15 +9306,6 @@ fn builtinCall( |
| 9307 | 9306 | }); |
| 9308 | 9307 | return rvalue(gz, ri, result, node); |
| 9309 | 9308 | }, |
| 9310 | .fence => { | |
| 9311 | const atomic_order_ty = try gz.addBuiltinValue(node, .atomic_order); | |
| 9312 | const order = try expr(gz, scope, .{ .rl = .{ .coerced_ty = atomic_order_ty } }, params[0]); | |
| 9313 | _ = try gz.addExtendedPayload(.fence, Zir.Inst.UnNode{ | |
| 9314 | .node = gz.nodeIndexToRelative(node), | |
| 9315 | .operand = order, | |
| 9316 | }); | |
| 9317 | return rvalue(gz, ri, .void_value, node); | |
| 9318 | }, | |
| 9319 | 9309 | .set_float_mode => { |
| 9320 | 9310 | const float_mode_ty = try gz.addBuiltinValue(node, .float_mode); |
| 9321 | 9311 | const order = try expr(gz, scope, .{ .rl = .{ .coerced_ty = float_mode_ty } }, params[0]); |
lib/std/zig/AstRlAnnotate.zig-1| ... | ... | @@ -908,7 +908,6 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast. |
| 908 | 908 | .c_include, |
| 909 | 909 | .wasm_memory_size, |
| 910 | 910 | .splat, |
| 911 | .fence, | |
| 912 | 911 | .set_float_mode, |
| 913 | 912 | .set_align_stack, |
| 914 | 913 | .type_info, |
lib/std/zig/BuiltinFn.zig-8| ... | ... | @@ -48,7 +48,6 @@ pub const Tag = enum { |
| 48 | 48 | error_cast, |
| 49 | 49 | @"export", |
| 50 | 50 | @"extern", |
| 51 | fence, | |
| 52 | 51 | field, |
| 53 | 52 | field_parent_ptr, |
| 54 | 53 | float_cast, |
| ... | ... | @@ -500,13 +499,6 @@ pub const list = list: { |
| 500 | 499 | .param_count = 2, |
| 501 | 500 | }, |
| 502 | 501 | }, |
| 503 | .{ | |
| 504 | "@fence", | |
| 505 | .{ | |
| 506 | .tag = .fence, | |
| 507 | .param_count = 1, | |
| 508 | }, | |
| 509 | }, | |
| 510 | 502 | .{ |
| 511 | 503 | "@field", |
| 512 | 504 | .{ |
lib/std/zig/Zir.zig+1-5| ... | ... | @@ -1575,7 +1575,7 @@ pub const Inst = struct { |
| 1575 | 1575 | => false, |
| 1576 | 1576 | |
| 1577 | 1577 | .extended => switch (data.extended.opcode) { |
| 1578 | .fence, .branch_hint, .breakpoint, .disable_instrumentation => true, | |
| 1578 | .branch_hint, .breakpoint, .disable_instrumentation => true, | |
| 1579 | 1579 | else => false, |
| 1580 | 1580 | }, |
| 1581 | 1581 | }; |
| ... | ... | @@ -1979,9 +1979,6 @@ pub const Inst = struct { |
| 1979 | 1979 | /// The `@prefetch` builtin. |
| 1980 | 1980 | /// `operand` is payload index to `BinNode`. |
| 1981 | 1981 | prefetch, |
| 1982 | /// Implements the `@fence` builtin. | |
| 1983 | /// `operand` is payload index to `UnNode`. | |
| 1984 | fence, | |
| 1985 | 1982 | /// Implement builtin `@setFloatMode`. |
| 1986 | 1983 | /// `operand` is payload index to `UnNode`. |
| 1987 | 1984 | set_float_mode, |
| ... | ... | @@ -4014,7 +4011,6 @@ fn findDeclsInner( |
| 4014 | 4011 | .wasm_memory_size, |
| 4015 | 4012 | .wasm_memory_grow, |
| 4016 | 4013 | .prefetch, |
| 4017 | .fence, | |
| 4018 | 4014 | .set_float_mode, |
| 4019 | 4015 | .set_align_stack, |
| 4020 | 4016 | .error_cast, |
lib/zig.h-8| ... | ... | @@ -3610,7 +3610,6 @@ typedef enum memory_order zig_memory_order; |
| 3610 | 3610 | #define zig_atomicrmw_add_float zig_atomicrmw_add |
| 3611 | 3611 | #undef zig_atomicrmw_sub_float |
| 3612 | 3612 | #define zig_atomicrmw_sub_float zig_atomicrmw_sub |
| 3613 | #define zig_fence(order) atomic_thread_fence(order) | |
| 3614 | 3613 | #elif defined(__GNUC__) |
| 3615 | 3614 | typedef int zig_memory_order; |
| 3616 | 3615 | #define zig_memory_order_relaxed __ATOMIC_RELAXED |
| ... | ... | @@ -3634,7 +3633,6 @@ typedef int zig_memory_order; |
| 3634 | 3633 | #define zig_atomic_load(res, obj, order, Type, ReprType) __atomic_load (obj, &(res), order) |
| 3635 | 3634 | #undef zig_atomicrmw_xchg_float |
| 3636 | 3635 | #define zig_atomicrmw_xchg_float zig_atomicrmw_xchg |
| 3637 | #define zig_fence(order) __atomic_thread_fence(order) | |
| 3638 | 3636 | #elif _MSC_VER && (_M_IX86 || _M_X64) |
| 3639 | 3637 | #define zig_memory_order_relaxed 0 |
| 3640 | 3638 | #define zig_memory_order_acquire 2 |
| ... | ... | @@ -3655,11 +3653,6 @@ typedef int zig_memory_order; |
| 3655 | 3653 | #define zig_atomicrmw_max(res, obj, arg, order, Type, ReprType) res = zig_msvc_atomicrmw_max_ ##Type(obj, arg) |
| 3656 | 3654 | #define zig_atomic_store( obj, arg, order, Type, ReprType) zig_msvc_atomic_store_ ##Type(obj, arg) |
| 3657 | 3655 | #define zig_atomic_load(res, obj, order, Type, ReprType) res = zig_msvc_atomic_load_ ##order##_##Type(obj) |
| 3658 | #if _M_X64 | |
| 3659 | #define zig_fence(order) __faststorefence() | |
| 3660 | #else | |
| 3661 | #define zig_fence(order) zig_msvc_atomic_barrier() | |
| 3662 | #endif | |
| 3663 | 3656 | /* TODO: _MSC_VER && (_M_ARM || _M_ARM64) */ |
| 3664 | 3657 | #else |
| 3665 | 3658 | #define zig_memory_order_relaxed 0 |
| ... | ... | @@ -3681,7 +3674,6 @@ typedef int zig_memory_order; |
| 3681 | 3674 | #define zig_atomicrmw_max(res, obj, arg, order, Type, ReprType) zig_atomics_unavailable |
| 3682 | 3675 | #define zig_atomic_store( obj, arg, order, Type, ReprType) zig_atomics_unavailable |
| 3683 | 3676 | #define zig_atomic_load(res, obj, order, Type, ReprType) zig_atomics_unavailable |
| 3684 | #define zig_fence(order) zig_fence_unavailable | |
| 3685 | 3677 | #endif |
| 3686 | 3678 | |
| 3687 | 3679 | #if _MSC_VER && (_M_IX86 || _M_X64) |
src/Air.zig-7| ... | ... | @@ -734,10 +734,6 @@ pub const Inst = struct { |
| 734 | 734 | cmpxchg_weak, |
| 735 | 735 | /// Uses the `ty_pl` field with payload `Cmpxchg`. |
| 736 | 736 | cmpxchg_strong, |
| 737 | /// Lowers to a memory fence instruction. | |
| 738 | /// Result type is always void. | |
| 739 | /// Uses the `fence` field. | |
| 740 | fence, | |
| 741 | 737 | /// Atomically load from a pointer. |
| 742 | 738 | /// Result type is the element type of the pointer. |
| 743 | 739 | /// Uses the `atomic_load` field. |
| ... | ... | @@ -1066,7 +1062,6 @@ pub const Inst = struct { |
| 1066 | 1062 | line: u32, |
| 1067 | 1063 | column: u32, |
| 1068 | 1064 | }, |
| 1069 | fence: std.builtin.AtomicOrder, | |
| 1070 | 1065 | atomic_load: struct { |
| 1071 | 1066 | ptr: Ref, |
| 1072 | 1067 | order: std.builtin.AtomicOrder, |
| ... | ... | @@ -1478,7 +1473,6 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool) |
| 1478 | 1473 | .dbg_arg_inline, |
| 1479 | 1474 | .store, |
| 1480 | 1475 | .store_safe, |
| 1481 | .fence, | |
| 1482 | 1476 | .atomic_store_unordered, |
| 1483 | 1477 | .atomic_store_monotonic, |
| 1484 | 1478 | .atomic_store_release, |
| ... | ... | @@ -1653,7 +1647,6 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool { |
| 1653 | 1647 | .memcpy, |
| 1654 | 1648 | .cmpxchg_weak, |
| 1655 | 1649 | .cmpxchg_strong, |
| 1656 | .fence, | |
| 1657 | 1650 | .atomic_store_unordered, |
| 1658 | 1651 | .atomic_store_monotonic, |
| 1659 | 1652 | .atomic_store_release, |
src/Air/types_resolved.zig-1| ... | ... | @@ -416,7 +416,6 @@ fn checkBody(air: Air, body: []const Air.Inst.Index, zcu: *Zcu) bool { |
| 416 | 416 | .work_item_id, |
| 417 | 417 | .work_group_size, |
| 418 | 418 | .work_group_id, |
| 419 | .fence, | |
| 420 | 419 | .dbg_stmt, |
| 421 | 420 | .err_return_trace, |
| 422 | 421 | .save_err_return_trace_index, |
src/Liveness.zig-3| ... | ... | @@ -346,8 +346,6 @@ pub fn categorizeOperand( |
| 346 | 346 | .work_group_id, |
| 347 | 347 | => return .none, |
| 348 | 348 | |
| 349 | .fence => return .write, | |
| 350 | ||
| 351 | 349 | .not, |
| 352 | 350 | .bitcast, |
| 353 | 351 | .load, |
| ... | ... | @@ -975,7 +973,6 @@ fn analyzeInst( |
| 975 | 973 | .ret_ptr, |
| 976 | 974 | .breakpoint, |
| 977 | 975 | .dbg_stmt, |
| 978 | .fence, | |
| 979 | 976 | .ret_addr, |
| 980 | 977 | .frame_addr, |
| 981 | 978 | .wasm_memory_size, |
src/Liveness/Verify.zig-1| ... | ... | @@ -56,7 +56,6 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { |
| 56 | 56 | .ret_ptr, |
| 57 | 57 | .breakpoint, |
| 58 | 58 | .dbg_stmt, |
| 59 | .fence, | |
| 60 | 59 | .ret_addr, |
| 61 | 60 | .frame_addr, |
| 62 | 61 | .wasm_memory_size, |
src/Sema.zig-24| ... | ... | @@ -1321,11 +1321,6 @@ fn analyzeBodyInner( |
| 1321 | 1321 | .closure_get => try sema.zirClosureGet( block, extended), |
| 1322 | 1322 | // zig fmt: on |
| 1323 | 1323 | |
| 1324 | .fence => { | |
| 1325 | try sema.zirFence(block, extended); | |
| 1326 | i += 1; | |
| 1327 | continue; | |
| 1328 | }, | |
| 1329 | 1324 | .set_float_mode => { |
| 1330 | 1325 | try sema.zirSetFloatMode(block, extended); |
| 1331 | 1326 | i += 1; |
| ... | ... | @@ -6556,25 +6551,6 @@ fn zirSetRuntimeSafety(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compile |
| 6556 | 6551 | }); |
| 6557 | 6552 | } |
| 6558 | 6553 | |
| 6559 | fn zirFence(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void { | |
| 6560 | if (block.is_comptime) return; | |
| 6561 | ||
| 6562 | const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; | |
| 6563 | const order_src = block.builtinCallArgSrc(extra.node, 0); | |
| 6564 | const order = try sema.resolveAtomicOrder(block, order_src, extra.operand, .{ | |
| 6565 | .needed_comptime_reason = "atomic order of @fence must be comptime-known", | |
| 6566 | }); | |
| 6567 | ||
| 6568 | if (@intFromEnum(order) < @intFromEnum(std.builtin.AtomicOrder.acquire)) { | |
| 6569 | return sema.fail(block, order_src, "atomic ordering must be acquire or stricter", .{}); | |
| 6570 | } | |
| 6571 | ||
| 6572 | _ = try block.addInst(.{ | |
| 6573 | .tag = .fence, | |
| 6574 | .data = .{ .fence = order }, | |
| 6575 | }); | |
| 6576 | } | |
| 6577 | ||
| 6578 | 6554 | fn zirBreak(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError!void { |
| 6579 | 6555 | const tracy = trace(@src()); |
| 6580 | 6556 | defer tracy.end(); |
src/arch/aarch64/CodeGen.zig-6| ... | ... | @@ -739,7 +739,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 739 | 739 | .breakpoint => try self.airBreakpoint(), |
| 740 | 740 | .ret_addr => try self.airRetAddr(inst), |
| 741 | 741 | .frame_addr => try self.airFrameAddress(inst), |
| 742 | .fence => try self.airFence(), | |
| 743 | 742 | .cond_br => try self.airCondBr(inst), |
| 744 | 743 | .fptrunc => try self.airFptrunc(inst), |
| 745 | 744 | .fpext => try self.airFpext(inst), |
| ... | ... | @@ -4264,11 +4263,6 @@ fn airFrameAddress(self: *Self, inst: Air.Inst.Index) !void { |
| 4264 | 4263 | return self.finishAir(inst, result, .{ .none, .none, .none }); |
| 4265 | 4264 | } |
| 4266 | 4265 | |
| 4267 | fn airFence(self: *Self) !void { | |
| 4268 | return self.fail("TODO implement fence() for {}", .{self.target.cpu.arch}); | |
| 4269 | //return self.finishAirBookkeeping(); | |
| 4270 | } | |
| 4271 | ||
| 4272 | 4266 | fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void { |
| 4273 | 4267 | if (modifier == .always_tail) return self.fail("TODO implement tail calls for aarch64", .{}); |
| 4274 | 4268 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
src/arch/arm/CodeGen.zig-6| ... | ... | @@ -726,7 +726,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 726 | 726 | .breakpoint => try self.airBreakpoint(), |
| 727 | 727 | .ret_addr => try self.airRetAddr(inst), |
| 728 | 728 | .frame_addr => try self.airFrameAddress(inst), |
| 729 | .fence => try self.airFence(), | |
| 730 | 729 | .cond_br => try self.airCondBr(inst), |
| 731 | 730 | .fptrunc => try self.airFptrunc(inst), |
| 732 | 731 | .fpext => try self.airFpext(inst), |
| ... | ... | @@ -4244,11 +4243,6 @@ fn airFrameAddress(self: *Self, inst: Air.Inst.Index) !void { |
| 4244 | 4243 | return self.finishAir(inst, result, .{ .none, .none, .none }); |
| 4245 | 4244 | } |
| 4246 | 4245 | |
| 4247 | fn airFence(self: *Self) !void { | |
| 4248 | return self.fail("TODO implement fence() for {}", .{self.target.cpu.arch}); | |
| 4249 | //return self.finishAirBookkeeping(); | |
| 4250 | } | |
| 4251 | ||
| 4252 | 4246 | fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void { |
| 4253 | 4247 | if (modifier == .always_tail) return self.fail("TODO implement tail calls for arm", .{}); |
| 4254 | 4248 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
src/arch/riscv64/CodeGen.zig-21| ... | ... | @@ -1593,7 +1593,6 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void { |
| 1593 | 1593 | .breakpoint => try func.airBreakpoint(), |
| 1594 | 1594 | .ret_addr => try func.airRetAddr(inst), |
| 1595 | 1595 | .frame_addr => try func.airFrameAddress(inst), |
| 1596 | .fence => try func.airFence(inst), | |
| 1597 | 1596 | .cond_br => try func.airCondBr(inst), |
| 1598 | 1597 | .dbg_stmt => try func.airDbgStmt(inst), |
| 1599 | 1598 | .fptrunc => try func.airFptrunc(inst), |
| ... | ... | @@ -4833,26 +4832,6 @@ fn airFrameAddress(func: *Func, inst: Air.Inst.Index) !void { |
| 4833 | 4832 | return func.finishAir(inst, dst_mcv, .{ .none, .none, .none }); |
| 4834 | 4833 | } |
| 4835 | 4834 | |
| 4836 | fn airFence(func: *Func, inst: Air.Inst.Index) !void { | |
| 4837 | const order = func.air.instructions.items(.data)[@intFromEnum(inst)].fence; | |
| 4838 | const pred: Mir.Barrier, const succ: Mir.Barrier = switch (order) { | |
| 4839 | .unordered, .monotonic => unreachable, | |
| 4840 | .acquire => .{ .r, .rw }, | |
| 4841 | .release => .{ .rw, .r }, | |
| 4842 | .acq_rel => .{ .rw, .rw }, | |
| 4843 | .seq_cst => .{ .rw, .rw }, | |
| 4844 | }; | |
| 4845 | ||
| 4846 | _ = try func.addInst(.{ | |
| 4847 | .tag = if (order == .acq_rel) .fencetso else .fence, | |
| 4848 | .data = .{ .fence = .{ | |
| 4849 | .pred = pred, | |
| 4850 | .succ = succ, | |
| 4851 | } }, | |
| 4852 | }); | |
| 4853 | return func.finishAirBookkeeping(); | |
| 4854 | } | |
| 4855 | ||
| 4856 | 4835 | fn airCall(func: *Func, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void { |
| 4857 | 4836 | if (modifier == .always_tail) return func.fail("TODO implement tail calls for riscv64", .{}); |
| 4858 | 4837 | const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
src/arch/sparc64/CodeGen.zig-24| ... | ... | @@ -581,7 +581,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 581 | 581 | .breakpoint => try self.airBreakpoint(), |
| 582 | 582 | .ret_addr => @panic("TODO try self.airRetAddr(inst)"), |
| 583 | 583 | .frame_addr => @panic("TODO try self.airFrameAddress(inst)"), |
| 584 | .fence => try self.airFence(inst), | |
| 585 | 584 | .cond_br => try self.airCondBr(inst), |
| 586 | 585 | .fptrunc => @panic("TODO try self.airFptrunc(inst)"), |
| 587 | 586 | .fpext => @panic("TODO try self.airFpext(inst)"), |
| ... | ... | @@ -1693,29 +1692,6 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { |
| 1693 | 1692 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1694 | 1693 | } |
| 1695 | 1694 | |
| 1696 | fn airFence(self: *Self, inst: Air.Inst.Index) !void { | |
| 1697 | // TODO weaken this as needed, currently this implements the strongest membar form | |
| 1698 | const fence = self.air.instructions.items(.data)[@intFromEnum(inst)].fence; | |
| 1699 | _ = fence; | |
| 1700 | ||
| 1701 | // membar #StoreStore | #LoadStore | #StoreLoad | #LoadLoad | |
| 1702 | _ = try self.addInst(.{ | |
| 1703 | .tag = .membar, | |
| 1704 | .data = .{ | |
| 1705 | .membar_mask = .{ | |
| 1706 | .mmask = .{ | |
| 1707 | .store_store = true, | |
| 1708 | .store_load = true, | |
| 1709 | .load_store = true, | |
| 1710 | .load_load = true, | |
| 1711 | }, | |
| 1712 | }, | |
| 1713 | }, | |
| 1714 | }); | |
| 1715 | ||
| 1716 | return self.finishAir(inst, .dead, .{ .none, .none, .none }); | |
| 1717 | } | |
| 1718 | ||
| 1719 | 1695 | fn airIntFromFloat(self: *Self, inst: Air.Inst.Index) !void { |
| 1720 | 1696 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 1721 | 1697 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airIntFromFloat for {}", .{ |
src/arch/wasm/CodeGen.zig-15| ... | ... | @@ -2040,7 +2040,6 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2040 | 2040 | .atomic_rmw => func.airAtomicRmw(inst), |
| 2041 | 2041 | .cmpxchg_weak => func.airCmpxchg(inst), |
| 2042 | 2042 | .cmpxchg_strong => func.airCmpxchg(inst), |
| 2043 | .fence => func.airFence(inst), | |
| 2044 | 2043 | |
| 2045 | 2044 | .add_optimized, |
| 2046 | 2045 | .sub_optimized, |
| ... | ... | @@ -7742,20 +7741,6 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7742 | 7741 | } |
| 7743 | 7742 | } |
| 7744 | 7743 | |
| 7745 | fn airFence(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | |
| 7746 | const pt = func.pt; | |
| 7747 | const zcu = pt.zcu; | |
| 7748 | // Only when the atomic feature is enabled, and we're not building | |
| 7749 | // for a single-threaded build, can we emit the `fence` instruction. | |
| 7750 | // In all other cases, we emit no instructions for a fence. | |
| 7751 | const single_threaded = zcu.navFileScope(func.owner_nav).mod.single_threaded; | |
| 7752 | if (func.useAtomicFeature() and !single_threaded) { | |
| 7753 | try func.addAtomicTag(.atomic_fence); | |
| 7754 | } | |
| 7755 | ||
| 7756 | return func.finishAir(inst, .none, &.{}); | |
| 7757 | } | |
| 7758 | ||
| 7759 | 7744 | fn airAtomicStore(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7760 | 7745 | const pt = func.pt; |
| 7761 | 7746 | const zcu = pt.zcu; |
src/arch/x86_64/CodeGen.zig-11| ... | ... | @@ -2294,7 +2294,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 2294 | 2294 | .breakpoint => try self.airBreakpoint(), |
| 2295 | 2295 | .ret_addr => try self.airRetAddr(inst), |
| 2296 | 2296 | .frame_addr => try self.airFrameAddress(inst), |
| 2297 | .fence => try self.airFence(inst), | |
| 2298 | 2297 | .cond_br => try self.airCondBr(inst), |
| 2299 | 2298 | .fptrunc => try self.airFptrunc(inst), |
| 2300 | 2299 | .fpext => try self.airFpext(inst), |
| ... | ... | @@ -12251,16 +12250,6 @@ fn airFrameAddress(self: *Self, inst: Air.Inst.Index) !void { |
| 12251 | 12250 | return self.finishAir(inst, dst_mcv, .{ .none, .none, .none }); |
| 12252 | 12251 | } |
| 12253 | 12252 | |
| 12254 | fn airFence(self: *Self, inst: Air.Inst.Index) !void { | |
| 12255 | const order = self.air.instructions.items(.data)[@intFromEnum(inst)].fence; | |
| 12256 | switch (order) { | |
| 12257 | .unordered, .monotonic => unreachable, | |
| 12258 | .acquire, .release, .acq_rel => {}, | |
| 12259 | .seq_cst => try self.asmOpOnly(.{ ._, .mfence }), | |
| 12260 | } | |
| 12261 | self.finishAirBookkeeping(); | |
| 12262 | } | |
| 12263 | ||
| 12264 | 12253 | fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void { |
| 12265 | 12254 | if (modifier == .always_tail) return self.fail("TODO implement tail calls for x86_64", .{}); |
| 12266 | 12255 |
src/codegen/c.zig-12| ... | ... | @@ -3144,7 +3144,6 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, |
| 3144 | 3144 | .breakpoint => try airBreakpoint(f.object.writer()), |
| 3145 | 3145 | .ret_addr => try airRetAddr(f, inst), |
| 3146 | 3146 | .frame_addr => try airFrameAddress(f, inst), |
| 3147 | .fence => try airFence(f, inst), | |
| 3148 | 3147 | |
| 3149 | 3148 | .ptr_add => try airPtrAddSub(f, inst, '+'), |
| 3150 | 3149 | .ptr_sub => try airPtrAddSub(f, inst, '-'), |
| ... | ... | @@ -4988,17 +4987,6 @@ fn airFrameAddress(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4988 | 4987 | return local; |
| 4989 | 4988 | } |
| 4990 | 4989 | |
| 4991 | fn airFence(f: *Function, inst: Air.Inst.Index) !CValue { | |
| 4992 | const atomic_order = f.air.instructions.items(.data)[@intFromEnum(inst)].fence; | |
| 4993 | const writer = f.object.writer(); | |
| 4994 | ||
| 4995 | try writer.writeAll("zig_fence("); | |
| 4996 | try writeMemoryOrder(writer, atomic_order); | |
| 4997 | try writer.writeAll(");\n"); | |
| 4998 | ||
| 4999 | return .none; | |
| 5000 | } | |
| 5001 | ||
| 5002 | 4990 | fn airUnreach(f: *Function) !void { |
| 5003 | 4991 | // Not even allowed to call unreachable in a naked function. |
| 5004 | 4992 | if (f.object.dg.is_naked_fn) return; |
src/codegen/llvm.zig-8| ... | ... | @@ -5139,7 +5139,6 @@ pub const FuncGen = struct { |
| 5139 | 5139 | .float_from_int => try self.airFloatFromInt(inst), |
| 5140 | 5140 | .cmpxchg_weak => try self.airCmpxchg(inst, .weak), |
| 5141 | 5141 | .cmpxchg_strong => try self.airCmpxchg(inst, .strong), |
| 5142 | .fence => try self.airFence(inst), | |
| 5143 | 5142 | .atomic_rmw => try self.airAtomicRmw(inst), |
| 5144 | 5143 | .atomic_load => try self.airAtomicLoad(inst), |
| 5145 | 5144 | .memset => try self.airMemset(inst, false), |
| ... | ... | @@ -9666,13 +9665,6 @@ pub const FuncGen = struct { |
| 9666 | 9665 | return self.wip.cast(.ptrtoint, result, try o.lowerType(Type.usize), ""); |
| 9667 | 9666 | } |
| 9668 | 9667 | |
| 9669 | fn airFence(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { | |
| 9670 | const atomic_order = self.air.instructions.items(.data)[@intFromEnum(inst)].fence; | |
| 9671 | const ordering = toLlvmAtomicOrdering(atomic_order); | |
| 9672 | _ = try self.wip.fence(self.sync_scope, ordering); | |
| 9673 | return .none; | |
| 9674 | } | |
| 9675 | ||
| 9676 | 9668 | fn airCmpxchg( |
| 9677 | 9669 | self: *FuncGen, |
| 9678 | 9670 | inst: Air.Inst.Index, |
src/print_air.zig-7| ... | ... | @@ -303,7 +303,6 @@ const Writer = struct { |
| 303 | 303 | .try_ptr, .try_ptr_cold => try w.writeTryPtr(s, inst), |
| 304 | 304 | .loop_switch_br, .switch_br => try w.writeSwitchBr(s, inst), |
| 305 | 305 | .cmpxchg_weak, .cmpxchg_strong => try w.writeCmpxchg(s, inst), |
| 306 | .fence => try w.writeFence(s, inst), | |
| 307 | 306 | .atomic_load => try w.writeAtomicLoad(s, inst), |
| 308 | 307 | .prefetch => try w.writePrefetch(s, inst), |
| 309 | 308 | .atomic_store_unordered => try w.writeAtomicStore(s, inst, .unordered), |
| ... | ... | @@ -552,12 +551,6 @@ const Writer = struct { |
| 552 | 551 | try w.writeOperand(s, inst, 2, extra.rhs); |
| 553 | 552 | } |
| 554 | 553 | |
| 555 | fn writeFence(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | |
| 556 | const atomic_order = w.air.instructions.items(.data)[@intFromEnum(inst)].fence; | |
| 557 | ||
| 558 | try s.print("{s}", .{@tagName(atomic_order)}); | |
| 559 | } | |
| 560 | ||
| 561 | 554 | fn writeAtomicLoad(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| 562 | 555 | const atomic_load = w.air.instructions.items(.data)[@intFromEnum(inst)].atomic_load; |
| 563 | 556 |
src/print_zir.zig-1| ... | ... | @@ -566,7 +566,6 @@ const Writer = struct { |
| 566 | 566 | .await_nosuspend, |
| 567 | 567 | .c_undef, |
| 568 | 568 | .c_include, |
| 569 | .fence, | |
| 570 | 569 | .set_float_mode, |
| 571 | 570 | .set_align_stack, |
| 572 | 571 | .wasm_memory_size, |
test/behavior/atomics.zig-10| ... | ... | @@ -37,16 +37,6 @@ fn testCmpxchg() !void { |
| 37 | 37 | try expect(x == 42); |
| 38 | 38 | } |
| 39 | 39 | |
| 40 | test "fence" { | |
| 41 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 42 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 43 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 44 | ||
| 45 | var x: i32 = 1234; | |
| 46 | @fence(.seq_cst); | |
| 47 | x = 5678; | |
| 48 | } | |
| 49 | ||
| 50 | 40 | test "atomicrmw and atomicload" { |
| 51 | 41 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 52 | 42 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
test/behavior/builtin_functions_returning_void_or_noreturn.zig-1| ... | ... | @@ -16,7 +16,6 @@ test { |
| 16 | 16 | try testing.expectEqual({}, @atomicStore(u8, &val, 0, .unordered)); |
| 17 | 17 | try testing.expectEqual(void, @TypeOf(@breakpoint())); |
| 18 | 18 | try testing.expectEqual({}, @export(&x, .{ .name = "x" })); |
| 19 | try testing.expectEqual({}, @fence(.acquire)); | |
| 20 | 19 | try testing.expectEqual({}, @memcpy(@as([*]u8, @ptrFromInt(1))[0..0], @as([*]u8, @ptrFromInt(1))[0..0])); |
| 21 | 20 | try testing.expectEqual({}, @memset(@as([*]u8, @ptrFromInt(1))[0..0], undefined)); |
| 22 | 21 | try testing.expectEqual(noreturn, @TypeOf(if (true) @panic("") else {})); |
test/cases/compile_errors/atomic_orderings_of_fence_Acquire_or_stricter.zig deleted-9| ... | ... | @@ -1,9 +0,0 @@ |
| 1 | export fn entry() void { | |
| 2 | @fence(.monotonic); | |
| 3 | } | |
| 4 | ||
| 5 | // error | |
| 6 | // backend=stage2 | |
| 7 | // target=native | |
| 8 | // | |
| 9 | // :2:13: error: atomic ordering must be acquire or stricter |