| 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,7 +23950,7 @@ fn checkAtomicPtrOperand( |
| 23950 | error.BadType => return sema.fail( | 23950 | error.BadType => return sema.fail( |
| 23951 | block, | 23951 | block, |
| 23952 | elem_ty_src, | 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 | .{elem_ty.fmt(pt)}, | 23954 | .{elem_ty.fmt(pt)}, |
| 23955 | ), | 23955 | ), |
| 23956 | }; | 23956 | }; |
| ... | @@ -24279,7 +24279,7 @@ fn zirCmpxchg( | ... | @@ -24279,7 +24279,7 @@ fn zirCmpxchg( |
| 24279 | return sema.fail( | 24279 | return sema.fail( |
| 24280 | block, | 24280 | block, |
| 24281 | elem_ty_src, | 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 | .{elem_ty.fmt(pt)}, | 24283 | .{elem_ty.fmt(pt)}, |
| 24284 | ); | 24284 | ); |
| 24285 | } | 24285 | } |
src/Zcu.zig+24-30| ... | @@ -3305,37 +3305,31 @@ pub fn atomicPtrAlignment( | ... | @@ -3305,37 +3305,31 @@ pub fn atomicPtrAlignment( |
| 3305 | .spirv => @panic("TODO what should this value be?"), | 3305 | .spirv => @panic("TODO what should this value be?"), |
| 3306 | }; | 3306 | }; |
| 3307 | 3307 | ||
| 3308 | const int_ty = switch (ty.zigTypeTag(mod)) { | 3308 | if (ty.toIntern() == .bool_type) return .none; |
| 3309 | .Int => ty, | 3309 | if (ty.isRuntimeFloat()) { |
| 3310 | .Enum => ty.intTagType(mod), | 3310 | const bit_count = ty.floatBits(target); |
| 3311 | .Float => { | 3311 | if (bit_count > max_atomic_bits) { |
| 3312 | const bit_count = ty.floatBits(target); | 3312 | diags.* = .{ |
| 3313 | if (bit_count > max_atomic_bits) { | 3313 | .bits = bit_count, |
| 3314 | diags.* = .{ | 3314 | .max_bits = max_atomic_bits, |
| 3315 | .bits = bit_count, | 3315 | }; |
| 3316 | .max_bits = max_atomic_bits, | 3316 | return error.FloatTooBig; |
| 3317 | }; | 3317 | } |
| 3318 | return error.FloatTooBig; | 3318 | return .none; |
| 3319 | } | 3319 | } |
| 3320 | return .none; | 3320 | if (ty.isAbiInt(mod)) { |
| 3321 | }, | 3321 | const bit_count = ty.intInfo(mod).bits; |
| 3322 | .Bool => return .none, | 3322 | if (bit_count > max_atomic_bits) { |
| 3323 | else => { | 3323 | diags.* = .{ |
| 3324 | if (ty.isPtrAtRuntime(mod)) return .none; | 3324 | .bits = bit_count, |
| 3325 | return error.BadType; | 3325 | .max_bits = max_atomic_bits, |
| 3326 | }, | 3326 | }; |
| 3327 | }; | 3327 | return error.IntTooBig; |
| 3328 | 3328 | } | |
| 3329 | const bit_count = int_ty.intInfo(mod).bits; | 3329 | return .none; |
| 3330 | if (bit_count > max_atomic_bits) { | ||
| 3331 | diags.* = .{ | ||
| 3332 | .bits = bit_count, | ||
| 3333 | .max_bits = max_atomic_bits, | ||
| 3334 | }; | ||
| 3335 | return error.IntTooBig; | ||
| 3336 | } | 3330 | } |
| 3337 | 3331 | if (ty.isPtrAtRuntime(mod)) return .none; | |
| 3338 | return .none; | 3332 | return error.BadType; |
| 3339 | } | 3333 | } |
| 3340 | 3334 | ||
| 3341 | pub fn declFileScope(mod: *Module, decl_index: Decl.Index) *File { | 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,6 +413,14 @@ test "atomics with different types" { |
| 413 | 413 | ||
| 414 | try testAtomicsWithType(u0, 0, 0); | 414 | try testAtomicsWithType(u0, 0, 0); |
| 415 | try testAtomicsWithType(i0, 0, 0); | 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 | fn testAtomicsWithType(comptime T: type, a: T, b: T) !void { | 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,6 +434,18 @@ fn testAtomicsWithType(comptime T: type, a: T, b: T) !void { |
| 426 | try expect(@cmpxchgStrong(T, &x, b, a, .seq_cst, .seq_cst).? == a); | 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 | test "return @atomicStore, using it as a void value" { | 449 | test "return @atomicStore, using it as a void value" { |
| 430 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 450 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 431 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 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' | ||