authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-11-06 14:30:34+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-11-07 06:42:15+00:00
logd78eda34c5de1ce869c55057b790081012e00bf5
tree67a02c8190529110b4c516ec528ec2632f43ddf9
parent9b394a200a55c8347e32607dcff568e8482ada48

Sema: emit @intCast safety check correctly for vectors

This code was previously tripping an assertion by not making this value used in the safety check a vector.

2 files changed, 28 insertions(+), 2 deletions(-)

src/Sema.zig+10-2
...@@ -10078,13 +10078,21 @@ fn intCast(...@@ -10078,13 +10078,21 @@ fn intCast(
10078 if (actual_info.signedness == .signed) {10078 if (actual_info.signedness == .signed) {
10079 // Reinterpret the sign-bit as part of the value. This will make10079 // Reinterpret the sign-bit as part of the value. This will make
10080 // negative differences (`operand` > `dest_max`) appear too big.10080 // negative differences (`operand` > `dest_max`) appear too big.
10081 const unsigned_operand_ty = try mod.intType(.unsigned, actual_bits);10081 const unsigned_scalar_operand_ty = try mod.intType(.unsigned, actual_bits);
10082 const unsigned_operand_ty = if (is_vector) try mod.vectorType(.{
10083 .len = dest_ty.vectorLen(mod),
10084 .child = unsigned_scalar_operand_ty.toIntern(),
10085 }) else unsigned_scalar_operand_ty;
10082 const diff_unsigned = try block.addBitCast(unsigned_operand_ty, diff);10086 const diff_unsigned = try block.addBitCast(unsigned_operand_ty, diff);
1008310087
10084 // If the destination type is signed, then we need to double its10088 // If the destination type is signed, then we need to double its
10085 // range to account for negative values.10089 // range to account for negative values.
10086 const dest_range_val = if (wanted_info.signedness == .signed) range_val: {10090 const dest_range_val = if (wanted_info.signedness == .signed) range_val: {
10087 const one = try mod.intValue(unsigned_operand_ty, 1);10091 const one_scalar = try mod.intValue(unsigned_scalar_operand_ty, 1);
10092 const one = if (is_vector) (try mod.intern(.{ .aggregate = .{
10093 .ty = unsigned_operand_ty.toIntern(),
10094 .storage = .{ .repeated_elem = one_scalar.toIntern() },
10095 } })).toValue() else one_scalar;
10088 const range_minus_one = try dest_max_val.shl(one, unsigned_operand_ty, sema.arena, mod);10096 const range_minus_one = try dest_max_val.shl(one, unsigned_operand_ty, sema.arena, mod);
10089 break :range_val try sema.intAdd(range_minus_one, one, unsigned_operand_ty, undefined);10097 break :range_val try sema.intAdd(range_minus_one, one, unsigned_operand_ty, undefined);
10090 } else try mod.getCoerced(dest_max_val, unsigned_operand_ty);10098 } else try mod.getCoerced(dest_max_val, unsigned_operand_ty);
test/behavior/cast.zig+18
...@@ -2428,3 +2428,21 @@ test "result information is preserved through many nested structures" {...@@ -2428,3 +2428,21 @@ test "result information is preserved through many nested structures" {
2428 try S.doTheTest();2428 try S.doTheTest();
2429 try comptime S.doTheTest();2429 try comptime S.doTheTest();
2430}2430}
2431
2432test "@intCast vector of signed integer" {
2433 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2434 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2435 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2436 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2437 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
2438 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
2439 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
2440
2441 var x: @Vector(4, i32) = .{ 1, 2, 3, 4 };
2442 const y: @Vector(4, i8) = @intCast(x);
2443
2444 try expect(y[0] == 1);
2445 try expect(y[1] == 2);
2446 try expect(y[2] == 3);
2447 try expect(y[3] == 4);
2448}