| 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,11 +4218,10 @@ pub fn print(self: *Writer, arg0: []const u8, arg1: i32) !void { |
| 4218 | {#header_close#} | 4218 | {#header_close#} |
| 4219 | 4219 | ||
| 4220 | {#header_open|Atomics#} | 4220 | {#header_open|Atomics#} |
| 4221 | <p>TODO: @fence()</p> | ||
| 4222 | <p>TODO: @atomic rmw</p> | 4221 | <p>TODO: @atomic rmw</p> |
| 4223 | <p>TODO: builtin atomic memory ordering enum</p> | 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 | {#header_close#} | 4226 | {#header_close#} |
| 4228 | 4227 | ||
| ... | @@ -4307,7 +4306,7 @@ comptime { | ... | @@ -4307,7 +4306,7 @@ comptime { |
| 4307 | an integer or an enum. | 4306 | an integer or an enum. |
| 4308 | </p> | 4307 | </p> |
| 4309 | <p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p> | 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 | {#header_close#} | 4310 | {#header_close#} |
| 4312 | 4311 | ||
| 4313 | {#header_open|@atomicRmw#} | 4312 | {#header_open|@atomicRmw#} |
| ... | @@ -4322,7 +4321,7 @@ comptime { | ... | @@ -4322,7 +4321,7 @@ comptime { |
| 4322 | </p> | 4321 | </p> |
| 4323 | <p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p> | 4322 | <p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p> |
| 4324 | <p>{#syntax#}AtomicRmwOp{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicRmwOp{#endsyntax#}.</p> | 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 | {#header_close#} | 4325 | {#header_close#} |
| 4327 | 4326 | ||
| 4328 | {#header_open|@atomicStore#} | 4327 | {#header_open|@atomicStore#} |
| ... | @@ -4335,7 +4334,7 @@ comptime { | ... | @@ -4335,7 +4334,7 @@ comptime { |
| 4335 | an integer or an enum. | 4334 | an integer or an enum. |
| 4336 | </p> | 4335 | </p> |
| 4337 | <p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p> | 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 | {#header_close#} | 4338 | {#header_close#} |
| 4340 | 4339 | ||
| 4341 | {#header_open|@bitCast#} | 4340 | {#header_open|@bitCast#} |
| ... | @@ -4568,7 +4567,7 @@ comptime { | ... | @@ -4568,7 +4567,7 @@ comptime { |
| 4568 | </p> | 4567 | </p> |
| 4569 | <p>{#syntax#}@typeInfo(@TypeOf(ptr)).pointer.alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p> | 4568 | <p>{#syntax#}@typeInfo(@TypeOf(ptr)).pointer.alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p> |
| 4570 | <p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p> | 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 | {#header_close#} | 4571 | {#header_close#} |
| 4573 | 4572 | ||
| 4574 | {#header_open|@cmpxchgWeak#} | 4573 | {#header_open|@cmpxchgWeak#} |
| ... | @@ -4600,7 +4599,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val | ... | @@ -4600,7 +4599,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 4600 | </p> | 4599 | </p> |
| 4601 | <p>{#syntax#}@typeInfo(@TypeOf(ptr)).pointer.alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p> | 4600 | <p>{#syntax#}@typeInfo(@TypeOf(ptr)).pointer.alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p> |
| 4602 | <p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p> | 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 | {#header_close#} | 4603 | {#header_close#} |
| 4605 | 4604 | ||
| 4606 | {#header_open|@compileError#} | 4605 | {#header_open|@compileError#} |
| ... | @@ -4857,15 +4856,6 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val | ... | @@ -4857,15 +4856,6 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 4857 | {#see_also|@export#} | 4856 | {#see_also|@export#} |
| 4858 | {#header_close#} | 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 | {#header_open|@field#} | 4859 | {#header_open|@field#} |
| 4870 | <pre>{#syntax#}@field(lhs: anytype, comptime field_name: []const u8) (field){#endsyntax#}</pre> | 4860 | <pre>{#syntax#}@field(lhs: anytype, comptime field_name: []const u8) (field){#endsyntax#}</pre> |
| 4871 | <p>Performs field access by a compile-time string. Works on both fields and declarations. | 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,9 +794,8 @@ const PosixImpl = struct { |
| 794 | // - T1: bumps pending waiters (was reordered after the ptr == expect check) | 794 | // - T1: bumps pending waiters (was reordered after the ptr == expect check) |
| 795 | // - T1: goes to sleep and misses both the ptr change and T2's wake up | 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. | 797 | // 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(). | 798 | var pending = bucket.pending.fetchAdd(1, .acquire); |
| 799 | var pending = bucket.pending.fetchAdd(1, .seq_cst); | ||
| 800 | assert(pending < std.math.maxInt(usize)); | 799 | assert(pending < std.math.maxInt(usize)); |
| 801 | 800 | ||
| 802 | // If the wait gets cancelled, remove the pending count we previously added. | 801 | // If the wait gets cancelled, remove the pending count we previously added. |
| ... | @@ -858,15 +857,8 @@ const PosixImpl = struct { | ... | @@ -858,15 +857,8 @@ const PosixImpl = struct { |
| 858 | // | 857 | // |
| 859 | // What we really want here is a Release load, but that doesn't exist under the C11 memory model. | 858 | // What we really want here is a Release load, but that doesn't exist under the C11 memory model. |
| 860 | // We could instead do `bucket.pending.fetchAdd(0, Release) == 0` which achieves effectively the same thing, | 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. | 860 | // LLVM lowers the fetchAdd(0, .release) into an mfence+load which avoids gaining ownership of the cache-line. |
| 862 | // | 861 | if (bucket.pending.fetchAdd(0, .release) == 0) { |
| 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) { | ||
| 870 | return; | 862 | return; |
| 871 | } | 863 | } |
| 872 | 864 | ||
| ... | @@ -979,15 +971,14 @@ test "broadcasting" { | ... | @@ -979,15 +971,14 @@ test "broadcasting" { |
| 979 | fn wait(self: *@This()) !void { | 971 | fn wait(self: *@This()) !void { |
| 980 | // Decrement the counter. | 972 | // Decrement the counter. |
| 981 | // Release ensures stuff before this barrier.wait() happens before the last one. | 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 | try testing.expect(count <= num_threads); | 976 | try testing.expect(count <= num_threads); |
| 984 | try testing.expect(count > 0); | 977 | try testing.expect(count > 0); |
| 985 | 978 | ||
| 986 | // First counter to reach zero wakes all other threads. | 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 | // Release on futex update ensures stuff before all barrier.wait()'s happens before they all return. | 980 | // Release on futex update ensures stuff before all barrier.wait()'s happens before they all return. |
| 989 | if (count - 1 == 0) { | 981 | if (count - 1 == 0) { |
| 990 | _ = self.count.load(.acquire); // TODO: could be fence(acquire) if not for TSAN | ||
| 991 | self.futex.store(1, .release); | 982 | self.futex.store(1, .release); |
| 992 | Futex.wake(&self.futex, num_threads - 1); | 983 | Futex.wake(&self.futex, num_threads - 1); |
| 993 | return; | 984 | return; |
lib/std/Thread/ResetEvent.zig+3-5| ... | @@ -112,9 +112,9 @@ const FutexImpl = struct { | ... | @@ -112,9 +112,9 @@ const FutexImpl = struct { |
| 112 | // Try to set the state from `unset` to `waiting` to indicate | 112 | // Try to set the state from `unset` to `waiting` to indicate |
| 113 | // to the set() thread that others are blocked on the ResetEvent. | 113 | // to the set() thread that others are blocked on the ResetEvent. |
| 114 | // We avoid using any strict barriers until the end when we know the ResetEvent is set. | 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 | if (state == unset) { | 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 | // Wait until the ResetEvent is set since the state is waiting. | 120 | // Wait until the ResetEvent is set since the state is waiting. |
| ... | @@ -124,7 +124,7 @@ const FutexImpl = struct { | ... | @@ -124,7 +124,7 @@ const FutexImpl = struct { |
| 124 | const wait_result = futex_deadline.wait(&self.state, waiting); | 124 | const wait_result = futex_deadline.wait(&self.state, waiting); |
| 125 | 125 | ||
| 126 | // Check if the ResetEvent was set before possibly reporting error.Timeout below. | 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 | if (state != waiting) { | 128 | if (state != waiting) { |
| 129 | break; | 129 | break; |
| 130 | } | 130 | } |
| ... | @@ -133,9 +133,7 @@ const FutexImpl = struct { | ... | @@ -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 | assert(state == is_set); | 136 | assert(state == is_set); |
| 138 | self.state.fence(.acquire); | ||
| 139 | } | 137 | } |
| 140 | 138 | ||
| 141 | fn set(self: *Impl) void { | 139 | fn set(self: *Impl) void { |
lib/std/Thread/WaitGroup.zig+1-2| ... | @@ -15,11 +15,10 @@ pub fn start(self: *WaitGroup) void { | ... | @@ -15,11 +15,10 @@ pub fn start(self: *WaitGroup) void { |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | pub fn finish(self: *WaitGroup) void { | 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 | assert((state / one_pending) > 0); | 19 | assert((state / one_pending) > 0); |
| 20 | 20 | ||
| 21 | if (state == (one_pending | is_waiting)) { | 21 | if (state == (one_pending | is_waiting)) { |
| 22 | self.state.fence(.acquire); | ||
| 23 | self.event.set(); | 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,31 +10,7 @@ pub fn Value(comptime T: type) type { |
| 10 | return .{ .raw = value }; | 10 | return .{ .raw = value }; |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | /// Perform an atomic fence which uses the atomic value as a hint for | 13 | pub const fence = @compileError("@fence is deprecated, use other atomics to establish ordering"); |
| 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 | } | ||
| 38 | 14 | ||
| 39 | pub inline fn load(self: *const Self, comptime order: AtomicOrder) T { | 15 | pub inline fn load(self: *const Self, comptime order: AtomicOrder) T { |
| 40 | return @atomicLoad(T, &self.raw, order); | 16 | return @atomicLoad(T, &self.raw, order); |
| ... | @@ -148,21 +124,19 @@ test Value { | ... | @@ -148,21 +124,19 @@ test Value { |
| 148 | const RefCount = @This(); | 124 | const RefCount = @This(); |
| 149 | 125 | ||
| 150 | fn ref(rc: *RefCount) void { | 126 | fn ref(rc: *RefCount) void { |
| 151 | // No ordering necessary; just updating a counter. | 127 | // no synchronization necessary; just updating a counter. |
| 152 | _ = rc.count.fetchAdd(1, .monotonic); | 128 | _ = rc.count.fetchAdd(1, .monotonic); |
| 153 | } | 129 | } |
| 154 | 130 | ||
| 155 | fn unref(rc: *RefCount) void { | 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 | // count is decremented as dropFn could be called by then. | 133 | // count is decremented as dropFn could be called by then. |
| 158 | if (rc.count.fetchSub(1, .release) == 1) { | 134 | if (rc.count.fetchSub(1, .release) == 1) { |
| 159 | // acquire ensures count decrement and code before | 135 | // seeing 1 in the counter means that other unref()s have happened, |
| 160 | // previous unrefs()s happens-before we call dropFn | 136 | // but it doesn't mean that uses before each unref() are visible. |
| 161 | // below. | 137 | // The load acquires the release-sequence created by previous unref()s |
| 162 | // Another alternative is to use .acq_rel on the | 138 | // in order to ensure visibility of uses before dropping. |
| 163 | // fetchSub count decrement but it's extra barrier in | 139 | _ = rc.count.load(.acquire); |
| 164 | // possibly hot path. | ||
| 165 | rc.count.fence(.acquire); | ||
| 166 | (rc.dropFn)(rc); | 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,7 +2901,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As |
| 2901 | .extended => switch (gz.astgen.instructions.items(.data)[@intFromEnum(inst)].extended.opcode) { | 2901 | .extended => switch (gz.astgen.instructions.items(.data)[@intFromEnum(inst)].extended.opcode) { |
| 2902 | .breakpoint, | 2902 | .breakpoint, |
| 2903 | .disable_instrumentation, | 2903 | .disable_instrumentation, |
| 2904 | .fence, | ||
| 2905 | .set_float_mode, | 2904 | .set_float_mode, |
| 2906 | .set_align_stack, | 2905 | .set_align_stack, |
| 2907 | .branch_hint, | 2906 | .branch_hint, |
| ... | @@ -9307,15 +9306,6 @@ fn builtinCall( | ... | @@ -9307,15 +9306,6 @@ fn builtinCall( |
| 9307 | }); | 9306 | }); |
| 9308 | return rvalue(gz, ri, result, node); | 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 | .set_float_mode => { | 9309 | .set_float_mode => { |
| 9320 | const float_mode_ty = try gz.addBuiltinValue(node, .float_mode); | 9310 | const float_mode_ty = try gz.addBuiltinValue(node, .float_mode); |
| 9321 | const order = try expr(gz, scope, .{ .rl = .{ .coerced_ty = float_mode_ty } }, params[0]); | 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,7 +908,6 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast. |
| 908 | .c_include, | 908 | .c_include, |
| 909 | .wasm_memory_size, | 909 | .wasm_memory_size, |
| 910 | .splat, | 910 | .splat, |
| 911 | .fence, | ||
| 912 | .set_float_mode, | 911 | .set_float_mode, |
| 913 | .set_align_stack, | 912 | .set_align_stack, |
| 914 | .type_info, | 913 | .type_info, |
lib/std/zig/BuiltinFn.zig-8| ... | @@ -48,7 +48,6 @@ pub const Tag = enum { | ... | @@ -48,7 +48,6 @@ pub const Tag = enum { |
| 48 | error_cast, | 48 | error_cast, |
| 49 | @"export", | 49 | @"export", |
| 50 | @"extern", | 50 | @"extern", |
| 51 | fence, | ||
| 52 | field, | 51 | field, |
| 53 | field_parent_ptr, | 52 | field_parent_ptr, |
| 54 | float_cast, | 53 | float_cast, |
| ... | @@ -500,13 +499,6 @@ pub const list = list: { | ... | @@ -500,13 +499,6 @@ pub const list = list: { |
| 500 | .param_count = 2, | 499 | .param_count = 2, |
| 501 | }, | 500 | }, |
| 502 | }, | 501 | }, |
| 503 | .{ | ||
| 504 | "@fence", | ||
| 505 | .{ | ||
| 506 | .tag = .fence, | ||
| 507 | .param_count = 1, | ||
| 508 | }, | ||
| 509 | }, | ||
| 510 | .{ | 502 | .{ |
| 511 | "@field", | 503 | "@field", |
| 512 | .{ | 504 | .{ |
lib/std/zig/Zir.zig+1-5| ... | @@ -1575,7 +1575,7 @@ pub const Inst = struct { | ... | @@ -1575,7 +1575,7 @@ pub const Inst = struct { |
| 1575 | => false, | 1575 | => false, |
| 1576 | 1576 | ||
| 1577 | .extended => switch (data.extended.opcode) { | 1577 | .extended => switch (data.extended.opcode) { |
| 1578 | .fence, .branch_hint, .breakpoint, .disable_instrumentation => true, | 1578 | .branch_hint, .breakpoint, .disable_instrumentation => true, |
| 1579 | else => false, | 1579 | else => false, |
| 1580 | }, | 1580 | }, |
| 1581 | }; | 1581 | }; |
| ... | @@ -1979,9 +1979,6 @@ pub const Inst = struct { | ... | @@ -1979,9 +1979,6 @@ pub const Inst = struct { |
| 1979 | /// The `@prefetch` builtin. | 1979 | /// The `@prefetch` builtin. |
| 1980 | /// `operand` is payload index to `BinNode`. | 1980 | /// `operand` is payload index to `BinNode`. |
| 1981 | prefetch, | 1981 | prefetch, |
| 1982 | /// Implements the `@fence` builtin. | ||
| 1983 | /// `operand` is payload index to `UnNode`. | ||
| 1984 | fence, | ||
| 1985 | /// Implement builtin `@setFloatMode`. | 1982 | /// Implement builtin `@setFloatMode`. |
| 1986 | /// `operand` is payload index to `UnNode`. | 1983 | /// `operand` is payload index to `UnNode`. |
| 1987 | set_float_mode, | 1984 | set_float_mode, |
| ... | @@ -4014,7 +4011,6 @@ fn findDeclsInner( | ... | @@ -4014,7 +4011,6 @@ fn findDeclsInner( |
| 4014 | .wasm_memory_size, | 4011 | .wasm_memory_size, |
| 4015 | .wasm_memory_grow, | 4012 | .wasm_memory_grow, |
| 4016 | .prefetch, | 4013 | .prefetch, |
| 4017 | .fence, | ||
| 4018 | .set_float_mode, | 4014 | .set_float_mode, |
| 4019 | .set_align_stack, | 4015 | .set_align_stack, |
| 4020 | .error_cast, | 4016 | .error_cast, |
lib/zig.h-8| ... | @@ -3610,7 +3610,6 @@ typedef enum memory_order zig_memory_order; | ... | @@ -3610,7 +3610,6 @@ typedef enum memory_order zig_memory_order; |
| 3610 | #define zig_atomicrmw_add_float zig_atomicrmw_add | 3610 | #define zig_atomicrmw_add_float zig_atomicrmw_add |
| 3611 | #undef zig_atomicrmw_sub_float | 3611 | #undef zig_atomicrmw_sub_float |
| 3612 | #define zig_atomicrmw_sub_float zig_atomicrmw_sub | 3612 | #define zig_atomicrmw_sub_float zig_atomicrmw_sub |
| 3613 | #define zig_fence(order) atomic_thread_fence(order) | ||
| 3614 | #elif defined(__GNUC__) | 3613 | #elif defined(__GNUC__) |
| 3615 | typedef int zig_memory_order; | 3614 | typedef int zig_memory_order; |
| 3616 | #define zig_memory_order_relaxed __ATOMIC_RELAXED | 3615 | #define zig_memory_order_relaxed __ATOMIC_RELAXED |
| ... | @@ -3634,7 +3633,6 @@ typedef int zig_memory_order; | ... | @@ -3634,7 +3633,6 @@ typedef int zig_memory_order; |
| 3634 | #define zig_atomic_load(res, obj, order, Type, ReprType) __atomic_load (obj, &(res), order) | 3633 | #define zig_atomic_load(res, obj, order, Type, ReprType) __atomic_load (obj, &(res), order) |
| 3635 | #undef zig_atomicrmw_xchg_float | 3634 | #undef zig_atomicrmw_xchg_float |
| 3636 | #define zig_atomicrmw_xchg_float zig_atomicrmw_xchg | 3635 | #define zig_atomicrmw_xchg_float zig_atomicrmw_xchg |
| 3637 | #define zig_fence(order) __atomic_thread_fence(order) | ||
| 3638 | #elif _MSC_VER && (_M_IX86 || _M_X64) | 3636 | #elif _MSC_VER && (_M_IX86 || _M_X64) |
| 3639 | #define zig_memory_order_relaxed 0 | 3637 | #define zig_memory_order_relaxed 0 |
| 3640 | #define zig_memory_order_acquire 2 | 3638 | #define zig_memory_order_acquire 2 |
| ... | @@ -3655,11 +3653,6 @@ typedef int zig_memory_order; | ... | @@ -3655,11 +3653,6 @@ typedef int zig_memory_order; |
| 3655 | #define zig_atomicrmw_max(res, obj, arg, order, Type, ReprType) res = zig_msvc_atomicrmw_max_ ##Type(obj, arg) | 3653 | #define zig_atomicrmw_max(res, obj, arg, order, Type, ReprType) res = zig_msvc_atomicrmw_max_ ##Type(obj, arg) |
| 3656 | #define zig_atomic_store( obj, arg, order, Type, ReprType) zig_msvc_atomic_store_ ##Type(obj, arg) | 3654 | #define zig_atomic_store( obj, arg, order, Type, ReprType) zig_msvc_atomic_store_ ##Type(obj, arg) |
| 3657 | #define zig_atomic_load(res, obj, order, Type, ReprType) res = zig_msvc_atomic_load_ ##order##_##Type(obj) | 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 | /* TODO: _MSC_VER && (_M_ARM || _M_ARM64) */ | 3656 | /* TODO: _MSC_VER && (_M_ARM || _M_ARM64) */ |
| 3664 | #else | 3657 | #else |
| 3665 | #define zig_memory_order_relaxed 0 | 3658 | #define zig_memory_order_relaxed 0 |
| ... | @@ -3681,7 +3674,6 @@ typedef int zig_memory_order; | ... | @@ -3681,7 +3674,6 @@ typedef int zig_memory_order; |
| 3681 | #define zig_atomicrmw_max(res, obj, arg, order, Type, ReprType) zig_atomics_unavailable | 3674 | #define zig_atomicrmw_max(res, obj, arg, order, Type, ReprType) zig_atomics_unavailable |
| 3682 | #define zig_atomic_store( obj, arg, order, Type, ReprType) zig_atomics_unavailable | 3675 | #define zig_atomic_store( obj, arg, order, Type, ReprType) zig_atomics_unavailable |
| 3683 | #define zig_atomic_load(res, obj, order, Type, ReprType) zig_atomics_unavailable | 3676 | #define zig_atomic_load(res, obj, order, Type, ReprType) zig_atomics_unavailable |
| 3684 | #define zig_fence(order) zig_fence_unavailable | ||
| 3685 | #endif | 3677 | #endif |
| 3686 | 3678 | ||
| 3687 | #if _MSC_VER && (_M_IX86 || _M_X64) | 3679 | #if _MSC_VER && (_M_IX86 || _M_X64) |
src/Air.zig-7| ... | @@ -734,10 +734,6 @@ pub const Inst = struct { | ... | @@ -734,10 +734,6 @@ pub const Inst = struct { |
| 734 | cmpxchg_weak, | 734 | cmpxchg_weak, |
| 735 | /// Uses the `ty_pl` field with payload `Cmpxchg`. | 735 | /// Uses the `ty_pl` field with payload `Cmpxchg`. |
| 736 | cmpxchg_strong, | 736 | cmpxchg_strong, |
| 737 | /// Lowers to a memory fence instruction. | ||
| 738 | /// Result type is always void. | ||
| 739 | /// Uses the `fence` field. | ||
| 740 | fence, | ||
| 741 | /// Atomically load from a pointer. | 737 | /// Atomically load from a pointer. |
| 742 | /// Result type is the element type of the pointer. | 738 | /// Result type is the element type of the pointer. |
| 743 | /// Uses the `atomic_load` field. | 739 | /// Uses the `atomic_load` field. |
| ... | @@ -1066,7 +1062,6 @@ pub const Inst = struct { | ... | @@ -1066,7 +1062,6 @@ pub const Inst = struct { |
| 1066 | line: u32, | 1062 | line: u32, |
| 1067 | column: u32, | 1063 | column: u32, |
| 1068 | }, | 1064 | }, |
| 1069 | fence: std.builtin.AtomicOrder, | ||
| 1070 | atomic_load: struct { | 1065 | atomic_load: struct { |
| 1071 | ptr: Ref, | 1066 | ptr: Ref, |
| 1072 | order: std.builtin.AtomicOrder, | 1067 | order: std.builtin.AtomicOrder, |
| ... | @@ -1478,7 +1473,6 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool) | ... | @@ -1478,7 +1473,6 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool) |
| 1478 | .dbg_arg_inline, | 1473 | .dbg_arg_inline, |
| 1479 | .store, | 1474 | .store, |
| 1480 | .store_safe, | 1475 | .store_safe, |
| 1481 | .fence, | ||
| 1482 | .atomic_store_unordered, | 1476 | .atomic_store_unordered, |
| 1483 | .atomic_store_monotonic, | 1477 | .atomic_store_monotonic, |
| 1484 | .atomic_store_release, | 1478 | .atomic_store_release, |
| ... | @@ -1653,7 +1647,6 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool { | ... | @@ -1653,7 +1647,6 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool { |
| 1653 | .memcpy, | 1647 | .memcpy, |
| 1654 | .cmpxchg_weak, | 1648 | .cmpxchg_weak, |
| 1655 | .cmpxchg_strong, | 1649 | .cmpxchg_strong, |
| 1656 | .fence, | ||
| 1657 | .atomic_store_unordered, | 1650 | .atomic_store_unordered, |
| 1658 | .atomic_store_monotonic, | 1651 | .atomic_store_monotonic, |
| 1659 | .atomic_store_release, | 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,7 +416,6 @@ fn checkBody(air: Air, body: []const Air.Inst.Index, zcu: *Zcu) bool { |
| 416 | .work_item_id, | 416 | .work_item_id, |
| 417 | .work_group_size, | 417 | .work_group_size, |
| 418 | .work_group_id, | 418 | .work_group_id, |
| 419 | .fence, | ||
| 420 | .dbg_stmt, | 419 | .dbg_stmt, |
| 421 | .err_return_trace, | 420 | .err_return_trace, |
| 422 | .save_err_return_trace_index, | 421 | .save_err_return_trace_index, |
src/Liveness.zig-3| ... | @@ -346,8 +346,6 @@ pub fn categorizeOperand( | ... | @@ -346,8 +346,6 @@ pub fn categorizeOperand( |
| 346 | .work_group_id, | 346 | .work_group_id, |
| 347 | => return .none, | 347 | => return .none, |
| 348 | 348 | ||
| 349 | .fence => return .write, | ||
| 350 | |||
| 351 | .not, | 349 | .not, |
| 352 | .bitcast, | 350 | .bitcast, |
| 353 | .load, | 351 | .load, |
| ... | @@ -975,7 +973,6 @@ fn analyzeInst( | ... | @@ -975,7 +973,6 @@ fn analyzeInst( |
| 975 | .ret_ptr, | 973 | .ret_ptr, |
| 976 | .breakpoint, | 974 | .breakpoint, |
| 977 | .dbg_stmt, | 975 | .dbg_stmt, |
| 978 | .fence, | ||
| 979 | .ret_addr, | 976 | .ret_addr, |
| 980 | .frame_addr, | 977 | .frame_addr, |
| 981 | .wasm_memory_size, | 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,7 +56,6 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { |
| 56 | .ret_ptr, | 56 | .ret_ptr, |
| 57 | .breakpoint, | 57 | .breakpoint, |
| 58 | .dbg_stmt, | 58 | .dbg_stmt, |
| 59 | .fence, | ||
| 60 | .ret_addr, | 59 | .ret_addr, |
| 61 | .frame_addr, | 60 | .frame_addr, |
| 62 | .wasm_memory_size, | 61 | .wasm_memory_size, |
src/Sema.zig-24| ... | @@ -1321,11 +1321,6 @@ fn analyzeBodyInner( | ... | @@ -1321,11 +1321,6 @@ fn analyzeBodyInner( |
| 1321 | .closure_get => try sema.zirClosureGet( block, extended), | 1321 | .closure_get => try sema.zirClosureGet( block, extended), |
| 1322 | // zig fmt: on | 1322 | // zig fmt: on |
| 1323 | 1323 | ||
| 1324 | .fence => { | ||
| 1325 | try sema.zirFence(block, extended); | ||
| 1326 | i += 1; | ||
| 1327 | continue; | ||
| 1328 | }, | ||
| 1329 | .set_float_mode => { | 1324 | .set_float_mode => { |
| 1330 | try sema.zirSetFloatMode(block, extended); | 1325 | try sema.zirSetFloatMode(block, extended); |
| 1331 | i += 1; | 1326 | i += 1; |
| ... | @@ -6556,25 +6551,6 @@ fn zirSetRuntimeSafety(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compile | ... | @@ -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 | fn zirBreak(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError!void { | 6554 | fn zirBreak(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError!void { |
| 6579 | const tracy = trace(@src()); | 6555 | const tracy = trace(@src()); |
| 6580 | defer tracy.end(); | 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,7 +739,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 739 | .breakpoint => try self.airBreakpoint(), | 739 | .breakpoint => try self.airBreakpoint(), |
| 740 | .ret_addr => try self.airRetAddr(inst), | 740 | .ret_addr => try self.airRetAddr(inst), |
| 741 | .frame_addr => try self.airFrameAddress(inst), | 741 | .frame_addr => try self.airFrameAddress(inst), |
| 742 | .fence => try self.airFence(), | ||
| 743 | .cond_br => try self.airCondBr(inst), | 742 | .cond_br => try self.airCondBr(inst), |
| 744 | .fptrunc => try self.airFptrunc(inst), | 743 | .fptrunc => try self.airFptrunc(inst), |
| 745 | .fpext => try self.airFpext(inst), | 744 | .fpext => try self.airFpext(inst), |
| ... | @@ -4264,11 +4263,6 @@ fn airFrameAddress(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4264,11 +4263,6 @@ fn airFrameAddress(self: *Self, inst: Air.Inst.Index) !void { |
| 4264 | return self.finishAir(inst, result, .{ .none, .none, .none }); | 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 | fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void { | 4266 | fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void { |
| 4273 | if (modifier == .always_tail) return self.fail("TODO implement tail calls for aarch64", .{}); | 4267 | if (modifier == .always_tail) return self.fail("TODO implement tail calls for aarch64", .{}); |
| 4274 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | 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,7 +726,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 726 | .breakpoint => try self.airBreakpoint(), | 726 | .breakpoint => try self.airBreakpoint(), |
| 727 | .ret_addr => try self.airRetAddr(inst), | 727 | .ret_addr => try self.airRetAddr(inst), |
| 728 | .frame_addr => try self.airFrameAddress(inst), | 728 | .frame_addr => try self.airFrameAddress(inst), |
| 729 | .fence => try self.airFence(), | ||
| 730 | .cond_br => try self.airCondBr(inst), | 729 | .cond_br => try self.airCondBr(inst), |
| 731 | .fptrunc => try self.airFptrunc(inst), | 730 | .fptrunc => try self.airFptrunc(inst), |
| 732 | .fpext => try self.airFpext(inst), | 731 | .fpext => try self.airFpext(inst), |
| ... | @@ -4244,11 +4243,6 @@ fn airFrameAddress(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4244,11 +4243,6 @@ fn airFrameAddress(self: *Self, inst: Air.Inst.Index) !void { |
| 4244 | return self.finishAir(inst, result, .{ .none, .none, .none }); | 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 | fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void { | 4246 | fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void { |
| 4253 | if (modifier == .always_tail) return self.fail("TODO implement tail calls for arm", .{}); | 4247 | if (modifier == .always_tail) return self.fail("TODO implement tail calls for arm", .{}); |
| 4254 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | 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,7 +1593,6 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void { |
| 1593 | .breakpoint => try func.airBreakpoint(), | 1593 | .breakpoint => try func.airBreakpoint(), |
| 1594 | .ret_addr => try func.airRetAddr(inst), | 1594 | .ret_addr => try func.airRetAddr(inst), |
| 1595 | .frame_addr => try func.airFrameAddress(inst), | 1595 | .frame_addr => try func.airFrameAddress(inst), |
| 1596 | .fence => try func.airFence(inst), | ||
| 1597 | .cond_br => try func.airCondBr(inst), | 1596 | .cond_br => try func.airCondBr(inst), |
| 1598 | .dbg_stmt => try func.airDbgStmt(inst), | 1597 | .dbg_stmt => try func.airDbgStmt(inst), |
| 1599 | .fptrunc => try func.airFptrunc(inst), | 1598 | .fptrunc => try func.airFptrunc(inst), |
| ... | @@ -4833,26 +4832,6 @@ fn airFrameAddress(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -4833,26 +4832,6 @@ fn airFrameAddress(func: *Func, inst: Air.Inst.Index) !void { |
| 4833 | return func.finishAir(inst, dst_mcv, .{ .none, .none, .none }); | 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 | fn airCall(func: *Func, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void { | 4835 | fn airCall(func: *Func, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void { |
| 4857 | if (modifier == .always_tail) return func.fail("TODO implement tail calls for riscv64", .{}); | 4836 | if (modifier == .always_tail) return func.fail("TODO implement tail calls for riscv64", .{}); |
| 4858 | const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | 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,7 +581,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 581 | .breakpoint => try self.airBreakpoint(), | 581 | .breakpoint => try self.airBreakpoint(), |
| 582 | .ret_addr => @panic("TODO try self.airRetAddr(inst)"), | 582 | .ret_addr => @panic("TODO try self.airRetAddr(inst)"), |
| 583 | .frame_addr => @panic("TODO try self.airFrameAddress(inst)"), | 583 | .frame_addr => @panic("TODO try self.airFrameAddress(inst)"), |
| 584 | .fence => try self.airFence(inst), | ||
| 585 | .cond_br => try self.airCondBr(inst), | 584 | .cond_br => try self.airCondBr(inst), |
| 586 | .fptrunc => @panic("TODO try self.airFptrunc(inst)"), | 585 | .fptrunc => @panic("TODO try self.airFptrunc(inst)"), |
| 587 | .fpext => @panic("TODO try self.airFpext(inst)"), | 586 | .fpext => @panic("TODO try self.airFpext(inst)"), |
| ... | @@ -1693,29 +1692,6 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1693,29 +1692,6 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { |
| 1693 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 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 | fn airIntFromFloat(self: *Self, inst: Air.Inst.Index) !void { | 1695 | fn airIntFromFloat(self: *Self, inst: Air.Inst.Index) !void { |
| 1720 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 1696 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 1721 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airIntFromFloat for {}", .{ | 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,7 +2040,6 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2040 | .atomic_rmw => func.airAtomicRmw(inst), | 2040 | .atomic_rmw => func.airAtomicRmw(inst), |
| 2041 | .cmpxchg_weak => func.airCmpxchg(inst), | 2041 | .cmpxchg_weak => func.airCmpxchg(inst), |
| 2042 | .cmpxchg_strong => func.airCmpxchg(inst), | 2042 | .cmpxchg_strong => func.airCmpxchg(inst), |
| 2043 | .fence => func.airFence(inst), | ||
| 2044 | 2043 | ||
| 2045 | .add_optimized, | 2044 | .add_optimized, |
| 2046 | .sub_optimized, | 2045 | .sub_optimized, |
| ... | @@ -7742,20 +7741,6 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -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 | fn airAtomicStore(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 7744 | fn airAtomicStore(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7760 | const pt = func.pt; | 7745 | const pt = func.pt; |
| 7761 | const zcu = pt.zcu; | 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,7 +2294,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 2294 | .breakpoint => try self.airBreakpoint(), | 2294 | .breakpoint => try self.airBreakpoint(), |
| 2295 | .ret_addr => try self.airRetAddr(inst), | 2295 | .ret_addr => try self.airRetAddr(inst), |
| 2296 | .frame_addr => try self.airFrameAddress(inst), | 2296 | .frame_addr => try self.airFrameAddress(inst), |
| 2297 | .fence => try self.airFence(inst), | ||
| 2298 | .cond_br => try self.airCondBr(inst), | 2297 | .cond_br => try self.airCondBr(inst), |
| 2299 | .fptrunc => try self.airFptrunc(inst), | 2298 | .fptrunc => try self.airFptrunc(inst), |
| 2300 | .fpext => try self.airFpext(inst), | 2299 | .fpext => try self.airFpext(inst), |
| ... | @@ -12251,16 +12250,6 @@ fn airFrameAddress(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -12251,16 +12250,6 @@ fn airFrameAddress(self: *Self, inst: Air.Inst.Index) !void { |
| 12251 | return self.finishAir(inst, dst_mcv, .{ .none, .none, .none }); | 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 | fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void { | 12253 | fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void { |
| 12265 | if (modifier == .always_tail) return self.fail("TODO implement tail calls for x86_64", .{}); | 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,7 +3144,6 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, |
| 3144 | .breakpoint => try airBreakpoint(f.object.writer()), | 3144 | .breakpoint => try airBreakpoint(f.object.writer()), |
| 3145 | .ret_addr => try airRetAddr(f, inst), | 3145 | .ret_addr => try airRetAddr(f, inst), |
| 3146 | .frame_addr => try airFrameAddress(f, inst), | 3146 | .frame_addr => try airFrameAddress(f, inst), |
| 3147 | .fence => try airFence(f, inst), | ||
| 3148 | 3147 | ||
| 3149 | .ptr_add => try airPtrAddSub(f, inst, '+'), | 3148 | .ptr_add => try airPtrAddSub(f, inst, '+'), |
| 3150 | .ptr_sub => try airPtrAddSub(f, inst, '-'), | 3149 | .ptr_sub => try airPtrAddSub(f, inst, '-'), |
| ... | @@ -4988,17 +4987,6 @@ fn airFrameAddress(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4988,17 +4987,6 @@ fn airFrameAddress(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4988 | return local; | 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 | fn airUnreach(f: *Function) !void { | 4990 | fn airUnreach(f: *Function) !void { |
| 5003 | // Not even allowed to call unreachable in a naked function. | 4991 | // Not even allowed to call unreachable in a naked function. |
| 5004 | if (f.object.dg.is_naked_fn) return; | 4992 | if (f.object.dg.is_naked_fn) return; |
src/codegen/llvm.zig-8| ... | @@ -5139,7 +5139,6 @@ pub const FuncGen = struct { | ... | @@ -5139,7 +5139,6 @@ pub const FuncGen = struct { |
| 5139 | .float_from_int => try self.airFloatFromInt(inst), | 5139 | .float_from_int => try self.airFloatFromInt(inst), |
| 5140 | .cmpxchg_weak => try self.airCmpxchg(inst, .weak), | 5140 | .cmpxchg_weak => try self.airCmpxchg(inst, .weak), |
| 5141 | .cmpxchg_strong => try self.airCmpxchg(inst, .strong), | 5141 | .cmpxchg_strong => try self.airCmpxchg(inst, .strong), |
| 5142 | .fence => try self.airFence(inst), | ||
| 5143 | .atomic_rmw => try self.airAtomicRmw(inst), | 5142 | .atomic_rmw => try self.airAtomicRmw(inst), |
| 5144 | .atomic_load => try self.airAtomicLoad(inst), | 5143 | .atomic_load => try self.airAtomicLoad(inst), |
| 5145 | .memset => try self.airMemset(inst, false), | 5144 | .memset => try self.airMemset(inst, false), |
| ... | @@ -9666,13 +9665,6 @@ pub const FuncGen = struct { | ... | @@ -9666,13 +9665,6 @@ pub const FuncGen = struct { |
| 9666 | return self.wip.cast(.ptrtoint, result, try o.lowerType(Type.usize), ""); | 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 | fn airCmpxchg( | 9668 | fn airCmpxchg( |
| 9677 | self: *FuncGen, | 9669 | self: *FuncGen, |
| 9678 | inst: Air.Inst.Index, | 9670 | inst: Air.Inst.Index, |
src/print_air.zig-7| ... | @@ -303,7 +303,6 @@ const Writer = struct { | ... | @@ -303,7 +303,6 @@ const Writer = struct { |
| 303 | .try_ptr, .try_ptr_cold => try w.writeTryPtr(s, inst), | 303 | .try_ptr, .try_ptr_cold => try w.writeTryPtr(s, inst), |
| 304 | .loop_switch_br, .switch_br => try w.writeSwitchBr(s, inst), | 304 | .loop_switch_br, .switch_br => try w.writeSwitchBr(s, inst), |
| 305 | .cmpxchg_weak, .cmpxchg_strong => try w.writeCmpxchg(s, inst), | 305 | .cmpxchg_weak, .cmpxchg_strong => try w.writeCmpxchg(s, inst), |
| 306 | .fence => try w.writeFence(s, inst), | ||
| 307 | .atomic_load => try w.writeAtomicLoad(s, inst), | 306 | .atomic_load => try w.writeAtomicLoad(s, inst), |
| 308 | .prefetch => try w.writePrefetch(s, inst), | 307 | .prefetch => try w.writePrefetch(s, inst), |
| 309 | .atomic_store_unordered => try w.writeAtomicStore(s, inst, .unordered), | 308 | .atomic_store_unordered => try w.writeAtomicStore(s, inst, .unordered), |
| ... | @@ -552,12 +551,6 @@ const Writer = struct { | ... | @@ -552,12 +551,6 @@ const Writer = struct { |
| 552 | try w.writeOperand(s, inst, 2, extra.rhs); | 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 | fn writeAtomicLoad(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | 554 | fn writeAtomicLoad(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| 562 | const atomic_load = w.air.instructions.items(.data)[@intFromEnum(inst)].atomic_load; | 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,7 +566,6 @@ const Writer = struct { |
| 566 | .await_nosuspend, | 566 | .await_nosuspend, |
| 567 | .c_undef, | 567 | .c_undef, |
| 568 | .c_include, | 568 | .c_include, |
| 569 | .fence, | ||
| 570 | .set_float_mode, | 569 | .set_float_mode, |
| 571 | .set_align_stack, | 570 | .set_align_stack, |
| 572 | .wasm_memory_size, | 571 | .wasm_memory_size, |
test/behavior/atomics.zig-10| ... | @@ -37,16 +37,6 @@ fn testCmpxchg() !void { | ... | @@ -37,16 +37,6 @@ fn testCmpxchg() !void { |
| 37 | try expect(x == 42); | 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 | test "atomicrmw and atomicload" { | 40 | test "atomicrmw and atomicload" { |
| 51 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 41 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 52 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 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,7 +16,6 @@ test { |
| 16 | try testing.expectEqual({}, @atomicStore(u8, &val, 0, .unordered)); | 16 | try testing.expectEqual({}, @atomicStore(u8, &val, 0, .unordered)); |
| 17 | try testing.expectEqual(void, @TypeOf(@breakpoint())); | 17 | try testing.expectEqual(void, @TypeOf(@breakpoint())); |
| 18 | try testing.expectEqual({}, @export(&x, .{ .name = "x" })); | 18 | try testing.expectEqual({}, @export(&x, .{ .name = "x" })); |
| 19 | try testing.expectEqual({}, @fence(.acquire)); | ||
| 20 | try testing.expectEqual({}, @memcpy(@as([*]u8, @ptrFromInt(1))[0..0], @as([*]u8, @ptrFromInt(1))[0..0])); | 19 | try testing.expectEqual({}, @memcpy(@as([*]u8, @ptrFromInt(1))[0..0], @as([*]u8, @ptrFromInt(1))[0..0])); |
| 21 | try testing.expectEqual({}, @memset(@as([*]u8, @ptrFromInt(1))[0..0], undefined)); | 20 | try testing.expectEqual({}, @memset(@as([*]u8, @ptrFromInt(1))[0..0], undefined)); |
| 22 | try testing.expectEqual(noreturn, @TypeOf(if (true) @panic("") else {})); | 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 | ||