mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
Merge pull request #24278 from gooncreeper/atomic-fixes
atomic fixes and clarification
This commit is contained in:
commit
389ccf692a
5 changed files with 42 additions and 16 deletions
|
|
@ -4319,7 +4319,7 @@ comptime {
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
{#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float,
|
{#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float,
|
||||||
an integer or an enum.
|
an integer, an enum, or a packed struct.
|
||||||
</p>
|
</p>
|
||||||
<p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p>
|
<p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p>
|
||||||
{#see_also|@atomicStore|@atomicRmw||@cmpxchgWeak|@cmpxchgStrong#}
|
{#see_also|@atomicStore|@atomicRmw||@cmpxchgWeak|@cmpxchgStrong#}
|
||||||
|
|
@ -4333,7 +4333,7 @@ comptime {
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
{#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float,
|
{#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float,
|
||||||
an integer or an enum.
|
an integer, an enum, or a packed struct.
|
||||||
</p>
|
</p>
|
||||||
<p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p>
|
<p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p>
|
||||||
<p>{#syntax#}AtomicRmwOp{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicRmwOp{#endsyntax#}.</p>
|
<p>{#syntax#}AtomicRmwOp{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicRmwOp{#endsyntax#}.</p>
|
||||||
|
|
@ -4347,7 +4347,7 @@ comptime {
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
{#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float,
|
{#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float,
|
||||||
an integer or an enum.
|
an integer, an enum, or a packed struct.
|
||||||
</p>
|
</p>
|
||||||
<p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p>
|
<p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p>
|
||||||
{#see_also|@atomicLoad|@atomicRmw|@cmpxchgWeak|@cmpxchgStrong#}
|
{#see_also|@atomicLoad|@atomicRmw|@cmpxchgWeak|@cmpxchgStrong#}
|
||||||
|
|
@ -4576,8 +4576,8 @@ comptime {
|
||||||
more efficiently in machine instructions.
|
more efficiently in machine instructions.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
{#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float,
|
{#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#},
|
||||||
an integer or an enum.
|
an integer, an enum, or a packed struct.
|
||||||
</p>
|
</p>
|
||||||
<p>{#syntax#}@typeInfo(@TypeOf(ptr)).pointer.alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p>
|
<p>{#syntax#}@typeInfo(@TypeOf(ptr)).pointer.alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p>
|
||||||
<p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p>
|
<p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p>
|
||||||
|
|
@ -4608,8 +4608,8 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
|
||||||
However if you need a stronger guarantee, use {#link|@cmpxchgStrong#}.
|
However if you need a stronger guarantee, use {#link|@cmpxchgStrong#}.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
{#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float,
|
{#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#},
|
||||||
an integer or an enum.
|
an integer, an enum, or a packed struct.
|
||||||
</p>
|
</p>
|
||||||
<p>{#syntax#}@typeInfo(@TypeOf(ptr)).pointer.alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p>
|
<p>{#syntax#}@typeInfo(@TypeOf(ptr)).pointer.alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p>
|
||||||
<p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p>
|
<p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p>
|
||||||
|
|
|
||||||
|
|
@ -3859,7 +3859,12 @@ pub fn atomicPtrAlignment(
|
||||||
}
|
}
|
||||||
return .none;
|
return .none;
|
||||||
}
|
}
|
||||||
if (ty.isAbiInt(zcu)) {
|
if (switch (ty.zigTypeTag(zcu)) {
|
||||||
|
.int, .@"enum" => true,
|
||||||
|
.@"struct" => ty.containerLayout(zcu) == .@"packed",
|
||||||
|
else => false,
|
||||||
|
}) {
|
||||||
|
assert(ty.isAbiInt(zcu));
|
||||||
const bit_count = ty.intInfo(zcu).bits;
|
const bit_count = ty.intInfo(zcu).bits;
|
||||||
if (bit_count > max_atomic_bits) {
|
if (bit_count > max_atomic_bits) {
|
||||||
diags.* = .{
|
diags.* = .{
|
||||||
|
|
|
||||||
|
|
@ -4339,9 +4339,11 @@ pub const Object = struct {
|
||||||
/// types to work around a LLVM deficiency when targeting ARM/AArch64.
|
/// types to work around a LLVM deficiency when targeting ARM/AArch64.
|
||||||
fn getAtomicAbiType(o: *Object, pt: Zcu.PerThread, ty: Type, is_rmw_xchg: bool) Allocator.Error!Builder.Type {
|
fn getAtomicAbiType(o: *Object, pt: Zcu.PerThread, ty: Type, is_rmw_xchg: bool) Allocator.Error!Builder.Type {
|
||||||
const zcu = pt.zcu;
|
const zcu = pt.zcu;
|
||||||
|
const ip = &zcu.intern_pool;
|
||||||
const int_ty = switch (ty.zigTypeTag(zcu)) {
|
const int_ty = switch (ty.zigTypeTag(zcu)) {
|
||||||
.int => ty,
|
.int => ty,
|
||||||
.@"enum" => ty.intTagType(zcu),
|
.@"enum" => ty.intTagType(zcu),
|
||||||
|
.@"struct" => Type.fromInterned(ip.loadStructType(ty.toIntern()).backingIntTypeUnordered(ip)),
|
||||||
.float => {
|
.float => {
|
||||||
if (!is_rmw_xchg) return .none;
|
if (!is_rmw_xchg) return .none;
|
||||||
return o.builder.intType(@intCast(ty.abiSize(zcu) * 8));
|
return o.builder.intType(@intCast(ty.abiSize(zcu) * 8));
|
||||||
|
|
@ -11424,7 +11426,7 @@ pub const FuncGen = struct {
|
||||||
|
|
||||||
if (workaround_disable_truncate) {
|
if (workaround_disable_truncate) {
|
||||||
// see https://github.com/llvm/llvm-project/issues/64222
|
// see https://github.com/llvm/llvm-project/issues/64222
|
||||||
// disable the truncation codepath for larger that 32bits value - with this heuristic, the backend passes the test suite.
|
// disable the truncation codepath for larger than 32bits value - with this heuristic, the backend passes the test suite.
|
||||||
return try fg.wip.load(access_kind, payload_llvm_ty, payload_ptr, payload_alignment, "");
|
return try fg.wip.load(access_kind, payload_llvm_ty, payload_ptr, payload_alignment, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const expect = std.testing.expect;
|
const expect = std.testing.expect;
|
||||||
const expectEqual = std.testing.expectEqual;
|
|
||||||
|
|
||||||
const supports_128_bit_atomics = switch (builtin.cpu.arch) {
|
const supports_128_bit_atomics = switch (builtin.cpu.arch) {
|
||||||
// TODO: Ideally this could be sync'd with the logic in Sema.
|
// TODO: Ideally this could be sync'd with the logic in Sema.
|
||||||
|
|
@ -364,25 +363,32 @@ test "atomics with different types" {
|
||||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||||
|
if (builtin.target.cpu.arch.endian() == .big) return error.SkipZigTest; // #24282
|
||||||
|
|
||||||
try testAtomicsWithType(bool, true, false);
|
try testAtomicsWithType(bool, true, false);
|
||||||
|
|
||||||
try testAtomicsWithType(u1, 0, 1);
|
try testAtomicsWithType(u1, 0, 1);
|
||||||
try testAtomicsWithType(i4, 0, 1);
|
try testAtomicsWithType(i4, 2, 1);
|
||||||
try testAtomicsWithType(u5, 0, 1);
|
try testAtomicsWithType(u5, 2, 1);
|
||||||
try testAtomicsWithType(i15, 0, 1);
|
try testAtomicsWithType(i15, 2, 1);
|
||||||
try testAtomicsWithType(u24, 0, 1);
|
try testAtomicsWithType(u24, 2, 1);
|
||||||
|
|
||||||
try testAtomicsWithType(u0, 0, 0);
|
try testAtomicsWithType(u0, 0, 0);
|
||||||
try testAtomicsWithType(i0, 0, 0);
|
try testAtomicsWithType(i0, 0, 0);
|
||||||
|
|
||||||
try testAtomicsWithType(enum(u32) { x = 1234, y = 5678 }, .x, .y);
|
try testAtomicsWithType(enum(u32) { x = 1234, y = 5678 }, .x, .y);
|
||||||
|
try testAtomicsWithType(enum(u19) { x = 1234, y = 5678 }, .x, .y);
|
||||||
|
|
||||||
try testAtomicsWithPackedStruct(
|
try testAtomicsWithPackedStruct(
|
||||||
packed struct { x: u7, y: u24, z: bool },
|
packed struct { x: u7, y: u24, z: bool },
|
||||||
.{ .x = 1, .y = 2, .z = true },
|
.{ .x = 1, .y = 2, .z = true },
|
||||||
.{ .x = 3, .y = 4, .z = false },
|
.{ .x = 3, .y = 4, .z = false },
|
||||||
);
|
);
|
||||||
|
try testAtomicsWithPackedStruct(
|
||||||
|
packed struct { x: u19, y: bool },
|
||||||
|
.{ .x = 1, .y = true },
|
||||||
|
.{ .x = 3, .y = false },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn testAtomicsWithType(comptime T: type, a: T, b: T) !void {
|
fn testAtomicsWithType(comptime T: type, a: T, b: T) !void {
|
||||||
|
|
|
||||||
|
|
@ -5,14 +5,27 @@ export fn float() void {
|
||||||
|
|
||||||
const NormalStruct = struct { x: u32 };
|
const NormalStruct = struct { x: u32 };
|
||||||
export fn normalStruct() void {
|
export fn normalStruct() void {
|
||||||
var x: NormalStruct = 0;
|
var x: NormalStruct = .{ .x = 0 };
|
||||||
_ = @cmpxchgWeak(NormalStruct, &x, .{ .x = 1 }, .{ .x = 2 }, .seq_cst, .seq_cst);
|
_ = @cmpxchgWeak(NormalStruct, &x, .{ .x = 1 }, .{ .x = 2 }, .seq_cst, .seq_cst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export fn anyError() void {
|
||||||
|
var x: anyerror = error.A;
|
||||||
|
_ = @cmpxchgWeak(anyerror, &x, error.A, error.B, .seq_cst, .seq_cst);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ErrorSet = error{ A, B };
|
||||||
|
export fn errorSet() void {
|
||||||
|
var x: ErrorSet = error.A;
|
||||||
|
_ = @cmpxchgWeak(ErrorSet, &x, error.A, error.B, .seq_cst, .seq_cst);
|
||||||
|
}
|
||||||
|
|
||||||
// error
|
// error
|
||||||
// backend=stage2
|
// backend=stage2
|
||||||
// target=native
|
// target=native
|
||||||
//
|
//
|
||||||
// :3:22: error: expected bool, integer, enum, packed struct, or pointer type; found 'f32'
|
// :3:22: error: expected bool, integer, enum, packed struct, or pointer type; found 'f32'
|
||||||
// :8:27: error: expected type 'tmp.NormalStruct', found 'comptime_int'
|
// :9:22: error: expected bool, integer, float, enum, packed struct, or pointer type; found 'tmp.NormalStruct'
|
||||||
// :6:22: note: struct declared here
|
// :6:22: note: struct declared here
|
||||||
|
// :14:22: error: expected bool, integer, float, enum, packed struct, or pointer type; found 'anyerror'
|
||||||
|
// :20:22: error: expected bool, integer, float, enum, packed struct, or pointer type; found 'error{A,B}'
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue