| author | |
| committer | |
| log | 3ad81c40c01649551b4ad3d2c450d8b5f7934362 |
| tree | 56775cdd64157a6756c6544f36ed58b00e9f627a |
| parent | ca752c61c08eaa06458bdc6fa3cc724c09a62f77 |
Same validation rules as the backing integer would have.5 files changed, 64 insertions(+), 42 deletions(-)
src/Sema.zig+2-2| ... | ... | @@ -23950,7 +23950,7 @@ fn checkAtomicPtrOperand( |
| 23950 | 23950 | error.BadType => return sema.fail( |
| 23951 | 23951 | block, |
| 23952 | 23952 | elem_ty_src, |
| 23953 | "expected bool, integer, float, enum, or pointer type; found '{}'", | |
| 23953 | "expected bool, integer, float, enum, packed struct, or pointer type; found '{}'", | |
| 23954 | 23954 | .{elem_ty.fmt(pt)}, |
| 23955 | 23955 | ), |
| 23956 | 23956 | }; |
| ... | ... | @@ -24279,7 +24279,7 @@ fn zirCmpxchg( |
| 24279 | 24279 | return sema.fail( |
| 24280 | 24280 | block, |
| 24281 | 24281 | elem_ty_src, |
| 24282 | "expected bool, integer, enum, or pointer type; found '{}'", | |
| 24282 | "expected bool, integer, enum, packed struct, or pointer type; found '{}'", | |
| 24283 | 24283 | .{elem_ty.fmt(pt)}, |
| 24284 | 24284 | ); |
| 24285 | 24285 | } |
src/Zcu.zig+24-30| ... | ... | @@ -3305,37 +3305,31 @@ pub fn atomicPtrAlignment( |
| 3305 | 3305 | .spirv => @panic("TODO what should this value be?"), |
| 3306 | 3306 | }; |
| 3307 | 3307 | |
| 3308 | const int_ty = switch (ty.zigTypeTag(mod)) { | |
| 3309 | .Int => ty, | |
| 3310 | .Enum => ty.intTagType(mod), | |
| 3311 | .Float => { | |
| 3312 | const bit_count = ty.floatBits(target); | |
| 3313 | if (bit_count > max_atomic_bits) { | |
| 3314 | diags.* = .{ | |
| 3315 | .bits = bit_count, | |
| 3316 | .max_bits = max_atomic_bits, | |
| 3317 | }; | |
| 3318 | return error.FloatTooBig; | |
| 3319 | } | |
| 3320 | return .none; | |
| 3321 | }, | |
| 3322 | .Bool => return .none, | |
| 3323 | else => { | |
| 3324 | if (ty.isPtrAtRuntime(mod)) return .none; | |
| 3325 | return error.BadType; | |
| 3326 | }, | |
| 3327 | }; | |
| 3328 | ||
| 3329 | const bit_count = int_ty.intInfo(mod).bits; | |
| 3330 | if (bit_count > max_atomic_bits) { | |
| 3331 | diags.* = .{ | |
| 3332 | .bits = bit_count, | |
| 3333 | .max_bits = max_atomic_bits, | |
| 3334 | }; | |
| 3335 | return error.IntTooBig; | |
| 3308 | if (ty.toIntern() == .bool_type) return .none; | |
| 3309 | if (ty.isRuntimeFloat()) { | |
| 3310 | const bit_count = ty.floatBits(target); | |
| 3311 | if (bit_count > max_atomic_bits) { | |
| 3312 | diags.* = .{ | |
| 3313 | .bits = bit_count, | |
| 3314 | .max_bits = max_atomic_bits, | |
| 3315 | }; | |
| 3316 | return error.FloatTooBig; | |
| 3317 | } | |
| 3318 | return .none; | |
| 3319 | } | |
| 3320 | if (ty.isAbiInt(mod)) { | |
| 3321 | const bit_count = ty.intInfo(mod).bits; | |
| 3322 | if (bit_count > max_atomic_bits) { | |
| 3323 | diags.* = .{ | |
| 3324 | .bits = bit_count, | |
| 3325 | .max_bits = max_atomic_bits, | |
| 3326 | }; | |
| 3327 | return error.IntTooBig; | |
| 3328 | } | |
| 3329 | return .none; | |
| 3336 | 3330 | } |
| 3337 | ||
| 3338 | return .none; | |
| 3331 | if (ty.isPtrAtRuntime(mod)) return .none; | |
| 3332 | return error.BadType; | |
| 3339 | 3333 | } |
| 3340 | 3334 | |
| 3341 | 3335 | pub fn declFileScope(mod: *Module, decl_index: Decl.Index) *File { |
test/behavior/atomics.zig+20| ... | ... | @@ -413,6 +413,14 @@ test "atomics with different types" { |
| 413 | 413 | |
| 414 | 414 | try testAtomicsWithType(u0, 0, 0); |
| 415 | 415 | try testAtomicsWithType(i0, 0, 0); |
| 416 | ||
| 417 | try testAtomicsWithType(enum(u32) { x = 1234, y = 5678 }, .x, .y); | |
| 418 | ||
| 419 | try testAtomicsWithPackedStruct( | |
| 420 | packed struct { x: u7, y: u24, z: bool }, | |
| 421 | .{ .x = 1, .y = 2, .z = true }, | |
| 422 | .{ .x = 3, .y = 4, .z = false }, | |
| 423 | ); | |
| 416 | 424 | } |
| 417 | 425 | |
| 418 | 426 | fn testAtomicsWithType(comptime T: type, a: T, b: T) !void { |
| ... | ... | @@ -426,6 +434,18 @@ fn testAtomicsWithType(comptime T: type, a: T, b: T) !void { |
| 426 | 434 | try expect(@cmpxchgStrong(T, &x, b, a, .seq_cst, .seq_cst).? == a); |
| 427 | 435 | } |
| 428 | 436 | |
| 437 | fn testAtomicsWithPackedStruct(comptime T: type, a: T, b: T) !void { | |
| 438 | const BackingInt = @typeInfo(T).Struct.backing_integer.?; | |
| 439 | var x: T = b; | |
| 440 | @atomicStore(T, &x, a, .seq_cst); | |
| 441 | try expect(@as(BackingInt, @bitCast(x)) == @as(BackingInt, @bitCast(a))); | |
| 442 | try expect(@as(BackingInt, @bitCast(@atomicLoad(T, &x, .seq_cst))) == @as(BackingInt, @bitCast(a))); | |
| 443 | try expect(@as(BackingInt, @bitCast(@atomicRmw(T, &x, .Xchg, b, .seq_cst))) == @as(BackingInt, @bitCast(a))); | |
| 444 | try expect(@cmpxchgStrong(T, &x, b, a, .seq_cst, .seq_cst) == null); | |
| 445 | if (@sizeOf(T) != 0) | |
| 446 | try expect(@as(BackingInt, @bitCast(@cmpxchgStrong(T, &x, b, a, .seq_cst, .seq_cst).?)) == @as(BackingInt, @bitCast(a))); | |
| 447 | } | |
| 448 | ||
| 429 | 449 | test "return @atomicStore, using it as a void value" { |
| 430 | 450 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 431 | 451 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
test/cases/compile_errors/atomics_with_invalid_type.zig created+18| ... | ... | @@ -0,0 +1,18 @@ |
| 1 | export fn float() void { | |
| 2 | var x: f32 = 0; | |
| 3 | _ = @cmpxchgWeak(f32, &x, 1, 2, .seq_cst, .seq_cst); | |
| 4 | } | |
| 5 | ||
| 6 | const NormalStruct = struct { x: u32 }; | |
| 7 | export fn normalStruct() void { | |
| 8 | var x: NormalStruct = 0; | |
| 9 | _ = @cmpxchgWeak(NormalStruct, &x, .{ .x = 1 }, .{ .x = 2 }, .seq_cst, .seq_cst); | |
| 10 | } | |
| 11 | ||
| 12 | // error | |
| 13 | // backend=stage2 | |
| 14 | // target=native | |
| 15 | // | |
| 16 | // :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' | |
| 18 | // :6:22: note: struct declared here |
test/cases/compile_errors/cmpxchg_with_float.zig deleted-10| ... | ... | @@ -1,10 +0,0 @@ |
| 1 | export fn entry() void { | |
| 2 | var x: f32 = 0; | |
| 3 | _ = @cmpxchgWeak(f32, &x, 1, 2, .seq_cst, .seq_cst); | |
| 4 | } | |
| 5 | ||
| 6 | // error | |
| 7 | // backend=stage2 | |
| 8 | // target=native | |
| 9 | // | |
| 10 | // :3:22: error: expected bool, integer, enum, or pointer type; found 'f32' |