Skip to content

Commit 1faa1e6

Browse files
committed
Fix Sema unreachable when shfting by vector containing undef elems
Added some missing checks for undef values before using `compareHetero` and `getUnsignedInt` to avoid hitting an unreachable prong. Also added a small AIR optimization that is basically free because of the new checks.
1 parent 43fba5e commit 1faa1e6

File tree

1 file changed

+29
-5
lines changed

1 file changed

+29
-5
lines changed

src/Sema.zig

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14030,7 +14030,7 @@ fn zirShl(
1403014030

1403114031
if (maybe_rhs_val) |rhs_val| {
1403214032
if (rhs_val.isUndef(zcu)) {
14033-
return pt.undefRef(sema.typeOf(lhs));
14033+
return pt.undefRef(lhs_ty);
1403414034
}
1403514035
// If rhs is 0, return lhs without doing any calculations.
1403614036
if (try rhs_val.compareAllWithZeroSema(.eq, pt)) {
@@ -14042,6 +14042,7 @@ fn zirShl(
1404214042
var i: usize = 0;
1404314043
while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {
1404414044
const rhs_elem = try rhs_val.elemValue(pt, i);
14045+
if (rhs_elem.isUndef(zcu)) continue;
1404514046
if (rhs_elem.compareHetero(.gte, bit_value, zcu)) {
1404614047
return sema.fail(block, rhs_src, "shift amount '{f}' at index '{d}' is too large for operand type '{f}'", .{
1404714048
rhs_elem.fmtValueSema(pt, sema),
@@ -14059,15 +14060,23 @@ fn zirShl(
1405914060
}
1406014061
if (rhs_ty.zigTypeTag(zcu) == .vector) {
1406114062
var i: usize = 0;
14063+
var undef_count: usize = 0;
1406214064
while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {
1406314065
const rhs_elem = try rhs_val.elemValue(pt, i);
14066+
if (rhs_elem.isUndef(zcu)) {
14067+
undef_count += 1;
14068+
continue;
14069+
}
1406414070
if (rhs_elem.compareHetero(.lt, try pt.intValue(scalar_rhs_ty, 0), zcu)) {
1406514071
return sema.fail(block, rhs_src, "shift by negative amount '{f}' at index '{d}'", .{
1406614072
rhs_elem.fmtValueSema(pt, sema),
1406714073
i,
1406814074
});
1406914075
}
1407014076
}
14077+
if (undef_count == rhs_ty.vectorLen(zcu)) {
14078+
return pt.undefRef(lhs_ty);
14079+
}
1407114080
} else if (rhs_val.compareHetero(.lt, try pt.intValue(rhs_ty, 0), zcu)) {
1407214081
return sema.fail(block, rhs_src, "shift by negative amount '{f}'", .{
1407314082
rhs_val.fmtValueSema(pt, sema),
@@ -14117,10 +14126,16 @@ fn zirShl(
1411714126
)).toIntern();
1411814127
const rhs_len = rhs_ty.vectorLen(zcu);
1411914128
const rhs_elems = try sema.arena.alloc(InternPool.Index, rhs_len);
14120-
for (rhs_elems, 0..) |*rhs_elem, i| rhs_elem.* = (try pt.intValue(
14121-
rt_rhs_scalar_ty,
14122-
@min(try (try rhs_val.elemValue(pt, i)).getUnsignedIntSema(pt) orelse bit_count, bit_count),
14123-
)).toIntern();
14129+
for (rhs_elems, 0..) |*rhs_elem, i| {
14130+
const elem_val = try rhs_val.elemValue(pt, i);
14131+
const min_val = if (elem_val.isUndef(zcu))
14132+
bit_count
14133+
else if (try elem_val.getUnsignedIntSema(pt)) |uint|
14134+
@min(uint, bit_count)
14135+
else
14136+
bit_count;
14137+
rhs_elem.* = (try pt.intValue(rt_rhs_scalar_ty, min_val)).toIntern();
14138+
}
1412414139
break :rt_rhs try pt.intern(.{ .aggregate = .{
1412514140
.ty = (try pt.vectorType(.{
1412614141
.len = rhs_len,
@@ -14223,6 +14238,7 @@ fn zirShr(
1422314238
var i: usize = 0;
1422414239
while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {
1422514240
const rhs_elem = try rhs_val.elemValue(pt, i);
14241+
if (rhs_elem.isUndef(zcu)) continue;
1422614242
if (rhs_elem.compareHetero(.gte, bit_value, zcu)) {
1422714243
return sema.fail(block, rhs_src, "shift amount '{f}' at index '{d}' is too large for operand type '{f}'", .{
1422814244
rhs_elem.fmtValueSema(pt, sema),
@@ -14240,15 +14256,23 @@ fn zirShr(
1424014256
}
1424114257
if (rhs_ty.zigTypeTag(zcu) == .vector) {
1424214258
var i: usize = 0;
14259+
var undef_count: usize = 0;
1424314260
while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {
1424414261
const rhs_elem = try rhs_val.elemValue(pt, i);
14262+
if (rhs_elem.isUndef(zcu)) {
14263+
undef_count += 1;
14264+
continue;
14265+
}
1424514266
if (rhs_elem.compareHetero(.lt, try pt.intValue(rhs_ty.childType(zcu), 0), zcu)) {
1424614267
return sema.fail(block, rhs_src, "shift by negative amount '{f}' at index '{d}'", .{
1424714268
rhs_elem.fmtValueSema(pt, sema),
1424814269
i,
1424914270
});
1425014271
}
1425114272
}
14273+
if (undef_count == rhs_ty.vectorLen(zcu)) {
14274+
return pt.undefRef(lhs_ty);
14275+
}
1425214276
} else if (rhs_val.compareHetero(.lt, try pt.intValue(rhs_ty, 0), zcu)) {
1425314277
return sema.fail(block, rhs_src, "shift by negative amount '{f}'", .{
1425414278
rhs_val.fmtValueSema(pt, sema),

0 commit comments

Comments
 (0)