| author | |
| committer | |
| log | 389ccf692a56411186e32b25e1a19442542c9f30 |
| tree | 81e0b838d7acbc1f684ff0abbcc3c932b78d415d |
| parent | 3d639481d9001df391744720b756b7f97dce2c01 |
| parent | cbe6e5b7fece38623d5eab43b71a83d1b6c7f323 |
| signature |
atomic fixes and clarification5 files changed, 42 insertions(+), 16 deletions(-)
doc/langref.html.in+7-7| ... | @@ -4319,7 +4319,7 @@ comptime { | ... | @@ -4319,7 +4319,7 @@ comptime { |
| 4319 | </p> | 4319 | </p> |
| 4320 | <p> | 4320 | <p> |
| 4321 | {#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float, | 4321 | {#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. |
| 4323 | </p> | 4323 | </p> |
| 4324 | <p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p> | 4324 | <p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p> |
| 4325 | {#see_also|@atomicStore|@atomicRmw||@cmpxchgWeak|@cmpxchgStrong#} | 4325 | {#see_also|@atomicStore|@atomicRmw||@cmpxchgWeak|@cmpxchgStrong#} |
| ... | @@ -4333,7 +4333,7 @@ comptime { | ... | @@ -4333,7 +4333,7 @@ comptime { |
| 4333 | </p> | 4333 | </p> |
| 4334 | <p> | 4334 | <p> |
| 4335 | {#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float, | 4335 | {#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. |
| 4337 | </p> | 4337 | </p> |
| 4338 | <p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p> | 4338 | <p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p> |
| 4339 | <p>{#syntax#}AtomicRmwOp{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicRmwOp{#endsyntax#}.</p> | 4339 | <p>{#syntax#}AtomicRmwOp{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicRmwOp{#endsyntax#}.</p> |
| ... | @@ -4347,7 +4347,7 @@ comptime { | ... | @@ -4347,7 +4347,7 @@ comptime { |
| 4347 | </p> | 4347 | </p> |
| 4348 | <p> | 4348 | <p> |
| 4349 | {#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float, | 4349 | {#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. |
| 4351 | </p> | 4351 | </p> |
| 4352 | <p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p> | 4352 | <p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p> |
| 4353 | {#see_also|@atomicLoad|@atomicRmw|@cmpxchgWeak|@cmpxchgStrong#} | 4353 | {#see_also|@atomicLoad|@atomicRmw|@cmpxchgWeak|@cmpxchgStrong#} |
| ... | @@ -4576,8 +4576,8 @@ comptime { | ... | @@ -4576,8 +4576,8 @@ comptime { |
| 4576 | more efficiently in machine instructions. | 4576 | more efficiently in machine instructions. |
| 4577 | </p> | 4577 | </p> |
| 4578 | <p> | 4578 | <p> |
| 4579 | {#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float, | 4579 | {#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, |
| 4580 | an integer or an enum. | 4580 | an integer, an enum, or a packed struct. |
| 4581 | </p> | 4581 | </p> |
| 4582 | <p>{#syntax#}@typeInfo(@TypeOf(ptr)).pointer.alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p> | 4582 | <p>{#syntax#}@typeInfo(@TypeOf(ptr)).pointer.alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p> |
| 4583 | <p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p> | 4583 | <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 | ... | @@ -4608,8 +4608,8 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 4608 | However if you need a stronger guarantee, use {#link|@cmpxchgStrong#}. | 4608 | However if you need a stronger guarantee, use {#link|@cmpxchgStrong#}. |
| 4609 | </p> | 4609 | </p> |
| 4610 | <p> | 4610 | <p> |
| 4611 | {#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float, | 4611 | {#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, |
| 4612 | an integer or an enum. | 4612 | an integer, an enum, or a packed struct. |
| 4613 | </p> | 4613 | </p> |
| 4614 | <p>{#syntax#}@typeInfo(@TypeOf(ptr)).pointer.alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p> | 4614 | <p>{#syntax#}@typeInfo(@TypeOf(ptr)).pointer.alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p> |
| 4615 | <p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p> | 4615 | <p>{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.</p> |
src/Zcu.zig+6-1| ... | @@ -3859,7 +3859,12 @@ pub fn atomicPtrAlignment( | ... | @@ -3859,7 +3859,12 @@ pub fn atomicPtrAlignment( |
| 3859 | } | 3859 | } |
| 3860 | return .none; | 3860 | return .none; |
| 3861 | } | 3861 | } |
| 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)); | ||
| 3863 | const bit_count = ty.intInfo(zcu).bits; | 3868 | const bit_count = ty.intInfo(zcu).bits; |
| 3864 | if (bit_count > max_atomic_bits) { | 3869 | if (bit_count > max_atomic_bits) { |
| 3865 | diags.* = .{ | 3870 | diags.* = .{ |
src/codegen/llvm.zig+3-1| ... | @@ -4339,9 +4339,11 @@ pub const Object = struct { | ... | @@ -4339,9 +4339,11 @@ pub const Object = struct { |
| 4339 | /// types to work around a LLVM deficiency when targeting ARM/AArch64. | 4339 | /// types to work around a LLVM deficiency when targeting ARM/AArch64. |
| 4340 | fn getAtomicAbiType(o: *Object, pt: Zcu.PerThread, ty: Type, is_rmw_xchg: bool) Allocator.Error!Builder.Type { | 4340 | fn getAtomicAbiType(o: *Object, pt: Zcu.PerThread, ty: Type, is_rmw_xchg: bool) Allocator.Error!Builder.Type { |
| 4341 | const zcu = pt.zcu; | 4341 | const zcu = pt.zcu; |
| 4342 | const ip = &zcu.intern_pool; | ||
| 4342 | const int_ty = switch (ty.zigTypeTag(zcu)) { | 4343 | const int_ty = switch (ty.zigTypeTag(zcu)) { |
| 4343 | .int => ty, | 4344 | .int => ty, |
| 4344 | .@"enum" => ty.intTagType(zcu), | 4345 | .@"enum" => ty.intTagType(zcu), |
| 4346 | .@"struct" => Type.fromInterned(ip.loadStructType(ty.toIntern()).backingIntTypeUnordered(ip)), | ||
| 4345 | .float => { | 4347 | .float => { |
| 4346 | if (!is_rmw_xchg) return .none; | 4348 | if (!is_rmw_xchg) return .none; |
| 4347 | return o.builder.intType(@intCast(ty.abiSize(zcu) * 8)); | 4349 | return o.builder.intType(@intCast(ty.abiSize(zcu) * 8)); |
| ... | @@ -11424,7 +11426,7 @@ pub const FuncGen = struct { | ... | @@ -11424,7 +11426,7 @@ pub const FuncGen = struct { |
| 11424 | 11426 | ||
| 11425 | if (workaround_disable_truncate) { | 11427 | if (workaround_disable_truncate) { |
| 11426 | // see https://github.com/llvm/llvm-project/issues/64222 | 11428 | // 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. |
| 11428 | return try fg.wip.load(access_kind, payload_llvm_ty, payload_ptr, payload_alignment, ""); | 11430 | return try fg.wip.load(access_kind, payload_llvm_ty, payload_ptr, payload_alignment, ""); |
| 11429 | } | 11431 | } |
| 11430 | 11432 |
test/behavior/atomics.zig+11-5| ... | @@ -1,7 +1,6 @@ | ... | @@ -1,7 +1,6 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const expect = std.testing.expect; | 3 | const expect = std.testing.expect; |
| 4 | const expectEqual = std.testing.expectEqual; | ||
| 5 | 4 | ||
| 6 | const supports_128_bit_atomics = switch (builtin.cpu.arch) { | 5 | const supports_128_bit_atomics = switch (builtin.cpu.arch) { |
| 7 | // TODO: Ideally this could be sync'd with the logic in Sema. | 6 | // TODO: Ideally this could be sync'd with the logic in Sema. |
| ... | @@ -364,25 +363,32 @@ test "atomics with different types" { | ... | @@ -364,25 +363,32 @@ test "atomics with different types" { |
| 364 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 363 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 365 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | 364 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 366 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | 365 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 366 | if (builtin.target.cpu.arch.endian() == .big) return error.SkipZigTest; // #24282 | ||
| 367 | 367 | ||
| 368 | try testAtomicsWithType(bool, true, false); | 368 | try testAtomicsWithType(bool, true, false); |
| 369 | 369 | ||
| 370 | try testAtomicsWithType(u1, 0, 1); | 370 | try testAtomicsWithType(u1, 0, 1); |
| 371 | try testAtomicsWithType(i4, 0, 1); | 371 | try testAtomicsWithType(i4, 2, 1); |
| 372 | try testAtomicsWithType(u5, 0, 1); | 372 | try testAtomicsWithType(u5, 2, 1); |
| 373 | try testAtomicsWithType(i15, 0, 1); | 373 | try testAtomicsWithType(i15, 2, 1); |
| 374 | try testAtomicsWithType(u24, 0, 1); | 374 | try testAtomicsWithType(u24, 2, 1); |
| 375 | 375 | ||
| 376 | try testAtomicsWithType(u0, 0, 0); | 376 | try testAtomicsWithType(u0, 0, 0); |
| 377 | try testAtomicsWithType(i0, 0, 0); | 377 | try testAtomicsWithType(i0, 0, 0); |
| 378 | 378 | ||
| 379 | try testAtomicsWithType(enum(u32) { x = 1234, y = 5678 }, .x, .y); | 379 | try testAtomicsWithType(enum(u32) { x = 1234, y = 5678 }, .x, .y); |
| 380 | try testAtomicsWithType(enum(u19) { x = 1234, y = 5678 }, .x, .y); | ||
| 380 | 381 | ||
| 381 | try testAtomicsWithPackedStruct( | 382 | try testAtomicsWithPackedStruct( |
| 382 | packed struct { x: u7, y: u24, z: bool }, | 383 | packed struct { x: u7, y: u24, z: bool }, |
| 383 | .{ .x = 1, .y = 2, .z = true }, | 384 | .{ .x = 1, .y = 2, .z = true }, |
| 384 | .{ .x = 3, .y = 4, .z = false }, | 385 | .{ .x = 3, .y = 4, .z = false }, |
| 385 | ); | 386 | ); |
| 387 | try testAtomicsWithPackedStruct( | ||
| 388 | packed struct { x: u19, y: bool }, | ||
| 389 | .{ .x = 1, .y = true }, | ||
| 390 | .{ .x = 3, .y = false }, | ||
| 391 | ); | ||
| 386 | } | 392 | } |
| 387 | 393 | ||
| 388 | fn testAtomicsWithType(comptime T: type, a: T, b: T) !void { | 394 | fn testAtomicsWithType(comptime T: type, a: T, b: T) !void { |
test/cases/compile_errors/atomics_with_invalid_type.zig+15-2| ... | @@ -5,14 +5,27 @@ export fn float() void { | ... | @@ -5,14 +5,27 @@ export fn float() void { |
| 5 | 5 | ||
| 6 | const NormalStruct = struct { x: u32 }; | 6 | const NormalStruct = struct { x: u32 }; |
| 7 | export fn normalStruct() void { | 7 | export fn normalStruct() void { |
| 8 | var x: NormalStruct = 0; | 8 | var x: NormalStruct = .{ .x = 0 }; |
| 9 | _ = @cmpxchgWeak(NormalStruct, &x, .{ .x = 1 }, .{ .x = 2 }, .seq_cst, .seq_cst); | 9 | _ = @cmpxchgWeak(NormalStruct, &x, .{ .x = 1 }, .{ .x = 2 }, .seq_cst, .seq_cst); |
| 10 | } | 10 | } |
| 11 | 11 | ||
| 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 | |||
| 12 | // error | 23 | // error |
| 13 | // backend=stage2 | 24 | // backend=stage2 |
| 14 | // target=native | 25 | // target=native |
| 15 | // | 26 | // |
| 16 | // :3:22: error: expected bool, integer, enum, packed struct, or pointer type; found 'f32' | 27 | // :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' |
| 18 | // :6:22: note: struct declared here | 29 | // :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}' |