Skip to content

Commit 389ccf6

Browse files
authored
Merge pull request #24278 from gooncreeper/atomic-fixes
atomic fixes and clarification
2 parents 3d63948 + cbe6e5b commit 389ccf6

File tree

5 files changed

+42
-16
lines changed

5 files changed

+42
-16
lines changed

doc/langref.html.in

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4319,7 +4319,7 @@ comptime {
43194319
</p>
43204320
<p>
43214321
{#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float,
4322-
an integer or an enum.
4322+
an integer, an enum, or a packed struct.
43234323
</p>
43244324
<p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p>
43254325
{#see_also|@atomicStore|@atomicRmw||@cmpxchgWeak|@cmpxchgStrong#}
@@ -4333,7 +4333,7 @@ comptime {
43334333
</p>
43344334
<p>
43354335
{#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float,
4336-
an integer or an enum.
4336+
an integer, an enum, or a packed struct.
43374337
</p>
43384338
<p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p>
43394339
<p>{#syntax#}AtomicRmwOp{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicRmwOp{#endsyntax#}.</p>
@@ -4347,7 +4347,7 @@ comptime {
43474347
</p>
43484348
<p>
43494349
{#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float,
4350-
an integer or an enum.
4350+
an integer, an enum, or a packed struct.
43514351
</p>
43524352
<p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p>
43534353
{#see_also|@atomicLoad|@atomicRmw|@cmpxchgWeak|@cmpxchgStrong#}
@@ -4576,8 +4576,8 @@ comptime {
45764576
more efficiently in machine instructions.
45774577
</p>
45784578
<p>
4579-
{#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float,
4580-
an integer or an enum.
4579+
{#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#},
4580+
an integer, an enum, or a packed struct.
45814581
</p>
45824582
<p>{#syntax#}@typeInfo(@TypeOf(ptr)).pointer.alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p>
45834583
<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
46084608
However if you need a stronger guarantee, use {#link|@cmpxchgStrong#}.
46094609
</p>
46104610
<p>
4611-
{#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float,
4612-
an integer or an enum.
4611+
{#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#},
4612+
an integer, an enum, or a packed struct.
46134613
</p>
46144614
<p>{#syntax#}@typeInfo(@TypeOf(ptr)).pointer.alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p>
46154615
<p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p>

src/Zcu.zig

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3859,7 +3859,12 @@ pub fn atomicPtrAlignment(
38593859
}
38603860
return .none;
38613861
}
3862-
if (ty.isAbiInt(zcu)) {
3862+
if (switch (ty.zigTypeTag(zcu)) {
3863+
.int, .@"enum" => true,
3864+
.@"struct" => ty.containerLayout(zcu) == .@"packed",
3865+
else => false,
3866+
}) {
3867+
assert(ty.isAbiInt(zcu));
38633868
const bit_count = ty.intInfo(zcu).bits;
38643869
if (bit_count > max_atomic_bits) {
38653870
diags.* = .{

src/codegen/llvm.zig

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4339,9 +4339,11 @@ pub const Object = struct {
43394339
/// types to work around a LLVM deficiency when targeting ARM/AArch64.
43404340
fn getAtomicAbiType(o: *Object, pt: Zcu.PerThread, ty: Type, is_rmw_xchg: bool) Allocator.Error!Builder.Type {
43414341
const zcu = pt.zcu;
4342+
const ip = &zcu.intern_pool;
43424343
const int_ty = switch (ty.zigTypeTag(zcu)) {
43434344
.int => ty,
43444345
.@"enum" => ty.intTagType(zcu),
4346+
.@"struct" => Type.fromInterned(ip.loadStructType(ty.toIntern()).backingIntTypeUnordered(ip)),
43454347
.float => {
43464348
if (!is_rmw_xchg) return .none;
43474349
return o.builder.intType(@intCast(ty.abiSize(zcu) * 8));
@@ -11424,7 +11426,7 @@ pub const FuncGen = struct {
1142411426

1142511427
if (workaround_disable_truncate) {
1142611428
// see https://github.com/llvm/llvm-project/issues/64222
11427-
// disable the truncation codepath for larger that 32bits value - with this heuristic, the backend passes the test suite.
11429+
// disable the truncation codepath for larger than 32bits value - with this heuristic, the backend passes the test suite.
1142811430
return try fg.wip.load(access_kind, payload_llvm_ty, payload_ptr, payload_alignment, "");
1142911431
}
1143011432

test/behavior/atomics.zig

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
const std = @import("std");
22
const builtin = @import("builtin");
33
const expect = std.testing.expect;
4-
const expectEqual = std.testing.expectEqual;
54

65
const supports_128_bit_atomics = switch (builtin.cpu.arch) {
76
// TODO: Ideally this could be sync'd with the logic in Sema.
@@ -364,25 +363,32 @@ test "atomics with different types" {
364363
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
365364
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
366365
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
366+
if (builtin.target.cpu.arch.endian() == .big) return error.SkipZigTest; // #24282
367367

368368
try testAtomicsWithType(bool, true, false);
369369

370370
try testAtomicsWithType(u1, 0, 1);
371-
try testAtomicsWithType(i4, 0, 1);
372-
try testAtomicsWithType(u5, 0, 1);
373-
try testAtomicsWithType(i15, 0, 1);
374-
try testAtomicsWithType(u24, 0, 1);
371+
try testAtomicsWithType(i4, 2, 1);
372+
try testAtomicsWithType(u5, 2, 1);
373+
try testAtomicsWithType(i15, 2, 1);
374+
try testAtomicsWithType(u24, 2, 1);
375375

376376
try testAtomicsWithType(u0, 0, 0);
377377
try testAtomicsWithType(i0, 0, 0);
378378

379379
try testAtomicsWithType(enum(u32) { x = 1234, y = 5678 }, .x, .y);
380+
try testAtomicsWithType(enum(u19) { x = 1234, y = 5678 }, .x, .y);
380381

381382
try testAtomicsWithPackedStruct(
382383
packed struct { x: u7, y: u24, z: bool },
383384
.{ .x = 1, .y = 2, .z = true },
384385
.{ .x = 3, .y = 4, .z = false },
385386
);
387+
try testAtomicsWithPackedStruct(
388+
packed struct { x: u19, y: bool },
389+
.{ .x = 1, .y = true },
390+
.{ .x = 3, .y = false },
391+
);
386392
}
387393

388394
fn testAtomicsWithType(comptime T: type, a: T, b: T) !void {

test/cases/compile_errors/atomics_with_invalid_type.zig

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,27 @@ export fn float() void {
55

66
const NormalStruct = struct { x: u32 };
77
export fn normalStruct() void {
8-
var x: NormalStruct = 0;
8+
var x: NormalStruct = .{ .x = 0 };
99
_ = @cmpxchgWeak(NormalStruct, &x, .{ .x = 1 }, .{ .x = 2 }, .seq_cst, .seq_cst);
1010
}
1111

12+
export fn anyError() void {
13+
var x: anyerror = error.A;
14+
_ = @cmpxchgWeak(anyerror, &x, error.A, error.B, .seq_cst, .seq_cst);
15+
}
16+
17+
const ErrorSet = error{ A, B };
18+
export fn errorSet() void {
19+
var x: ErrorSet = error.A;
20+
_ = @cmpxchgWeak(ErrorSet, &x, error.A, error.B, .seq_cst, .seq_cst);
21+
}
22+
1223
// error
1324
// backend=stage2
1425
// target=native
1526
//
1627
// :3:22: error: expected bool, integer, enum, packed struct, or pointer type; found 'f32'
17-
// :8:27: error: expected type 'tmp.NormalStruct', found 'comptime_int'
28+
// :9:22: error: expected bool, integer, float, enum, packed struct, or pointer type; found 'tmp.NormalStruct'
1829
// :6:22: note: struct declared here
30+
// :14:22: error: expected bool, integer, float, enum, packed struct, or pointer type; found 'anyerror'
31+
// :20:22: error: expected bool, integer, float, enum, packed struct, or pointer type; found 'error{A,B}'

0 commit comments

Comments
 (0)