diff --git a/doc/langref.html.in b/doc/langref.html.in index e8189e5c42..e3aa8c584f 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -4319,7 +4319,7 @@ comptime {
{#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.
{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.
{#see_also|@atomicStore|@atomicRmw||@cmpxchgWeak|@cmpxchgStrong#} @@ -4333,7 +4333,7 @@ comptime {{#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.
{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.
{#syntax#}AtomicRmwOp{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicRmwOp{#endsyntax#}.
@@ -4347,7 +4347,7 @@ comptime {{#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.
{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.
{#see_also|@atomicLoad|@atomicRmw|@cmpxchgWeak|@cmpxchgStrong#} @@ -4576,8 +4576,8 @@ comptime { more efficiently in machine instructions.- {#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float, - an integer or an enum. + {#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, + an integer, an enum, or a packed struct.
{#syntax#}@typeInfo(@TypeOf(ptr)).pointer.alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}
{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.
@@ -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#}.- {#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float, - an integer or an enum. + {#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, + an integer, an enum, or a packed struct.
{#syntax#}@typeInfo(@TypeOf(ptr)).pointer.alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}
{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.
diff --git a/src/Zcu.zig b/src/Zcu.zig index df35777231..c13f7aaac9 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -3859,7 +3859,12 @@ pub fn atomicPtrAlignment( } 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; if (bit_count > max_atomic_bits) { diags.* = .{ diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 111fc6ec14..5e522c3d73 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -4339,9 +4339,11 @@ pub const Object = struct { /// 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 { const zcu = pt.zcu; + const ip = &zcu.intern_pool; const int_ty = switch (ty.zigTypeTag(zcu)) { .int => ty, .@"enum" => ty.intTagType(zcu), + .@"struct" => Type.fromInterned(ip.loadStructType(ty.toIntern()).backingIntTypeUnordered(ip)), .float => { if (!is_rmw_xchg) return .none; return o.builder.intType(@intCast(ty.abiSize(zcu) * 8)); @@ -11424,7 +11426,7 @@ pub const FuncGen = struct { if (workaround_disable_truncate) { // 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, ""); } diff --git a/test/behavior/atomics.zig b/test/behavior/atomics.zig index cda8b5f033..15d4b99ba4 100644 --- a/test/behavior/atomics.zig +++ b/test/behavior/atomics.zig @@ -1,7 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); const expect = std.testing.expect; -const expectEqual = std.testing.expectEqual; const supports_128_bit_atomics = switch (builtin.cpu.arch) { // 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_spirv) 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(u1, 0, 1); - try testAtomicsWithType(i4, 0, 1); - try testAtomicsWithType(u5, 0, 1); - try testAtomicsWithType(i15, 0, 1); - try testAtomicsWithType(u24, 0, 1); + try testAtomicsWithType(i4, 2, 1); + try testAtomicsWithType(u5, 2, 1); + try testAtomicsWithType(i15, 2, 1); + try testAtomicsWithType(u24, 2, 1); try testAtomicsWithType(u0, 0, 0); try testAtomicsWithType(i0, 0, 0); try testAtomicsWithType(enum(u32) { x = 1234, y = 5678 }, .x, .y); + try testAtomicsWithType(enum(u19) { x = 1234, y = 5678 }, .x, .y); try testAtomicsWithPackedStruct( packed struct { x: u7, y: u24, z: bool }, .{ .x = 1, .y = 2, .z = true }, .{ .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 { diff --git a/test/cases/compile_errors/atomics_with_invalid_type.zig b/test/cases/compile_errors/atomics_with_invalid_type.zig index 321cda3655..4643dc7543 100644 --- a/test/cases/compile_errors/atomics_with_invalid_type.zig +++ b/test/cases/compile_errors/atomics_with_invalid_type.zig @@ -5,14 +5,27 @@ export fn float() void { const NormalStruct = struct { x: u32 }; export fn normalStruct() void { - var x: NormalStruct = 0; + var x: NormalStruct = .{ .x = 0 }; _ = @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 // backend=stage2 // target=native // // :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 +// :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}'