authorgravatar for rpkak@noreply.codeberg.orgrpkak <rpkak@noreply.codeberg.org> 2026-10-05 09:13:33+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-10-06 05:06:19+02:00
loga81a808db85bf8b4c19274e4b805455414486621
tree44f1b5841f875b8f585b59a73f0cf54067597971
parent44dce00408af3da922d35765393a6265ece44284
signature Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

Sema: emit shr instead of shr_exact when @shrExact is used and wantSafety is true

The safety check of @shrExact is to shift the result the same amount back to the left and compare if this matches the input of the @shrExact. But since the 'lshr exact' llvm instruction was used, llvm was allowed to assume, that the result of the left-shift matches the input.

1 files changed, 18 insertions(+), 21 deletions(-)

src/Sema.zig+18-21
......@@ -1231,8 +1231,8 @@ fn analyzeBodyInner(
12311231 .ref => try sema.zirRef(block, inst),
12321232 .deref => try sema.zirDeref(block, inst),
12331233 .ref_deref => try sema.zirRefDeref(block, inst),
1234 .shr => try sema.zirShr(block, inst, .shr),
1235 .shr_exact => try sema.zirShr(block, inst, .shr_exact),
1234 .shr => try sema.zirShr(block, inst, false),
1235 .shr_exact => try sema.zirShr(block, inst, true),
12361236 .slice_end => try sema.zirSliceEnd(block, inst),
12371237 .slice_sentinel => try sema.zirSliceSentinel(block, inst),
12381238 .slice_start => try sema.zirSliceStart(block, inst),
......@@ -13176,7 +13176,7 @@ fn zirShr(
1317613176 sema: *Sema,
1317713177 block: *Block,
1317813178 inst: Zir.Inst.Index,
13179 air_tag: Air.Inst.Tag,
13179 exact: bool,
1318013180) CompileError!Air.Inst.Ref {
1318113181 const pt = sema.pt;
1318213182 const zcu = pt.zcu;
......@@ -13188,16 +13188,15 @@ fn zirShr(
1318813188 const rhs_ty = sema.typeOf(rhs);
1318913189
1319013190 const src = block.nodeOffset(inst_data.src_node);
13191 const lhs_src = switch (air_tag) {
13192 .shr => block.src(.{ .node_offset_bin_lhs = inst_data.src_node }),
13193 .shr_exact => block.builtinCallArgSrc(inst_data.src_node, 0),
13194 else => unreachable,
13195 };
13196 const rhs_src = switch (air_tag) {
13197 .shr => block.src(.{ .node_offset_bin_rhs = inst_data.src_node }),
13198 .shr_exact => block.builtinCallArgSrc(inst_data.src_node, 1),
13199 else => unreachable,
13200 };
13191 const lhs_src = if (exact)
13192 block.builtinCallArgSrc(inst_data.src_node, 0)
13193 else
13194 block.src(.{ .node_offset_bin_lhs = inst_data.src_node });
13195
13196 const rhs_src = if (exact)
13197 block.builtinCallArgSrc(inst_data.src_node, 1)
13198 else
13199 block.src(.{ .node_offset_bin_rhs = inst_data.src_node });
1320113200
1320213201 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1320313202 const scalar_ty = lhs_ty.scalarType(zcu);
......@@ -13208,11 +13207,7 @@ fn zirShr(
1320813207 const runtime_src = rs: {
1320913208 if (maybe_rhs_val) |rhs_val| {
1321013209 if (maybe_lhs_val) |lhs_val| {
13211 return .fromValue(try arith.shr(sema, block, lhs_ty, rhs_ty, lhs_val, rhs_val, src, lhs_src, rhs_src, switch (air_tag) {
13212 .shr => .shr,
13213 .shr_exact => .shr_exact,
13214 else => unreachable,
13215 }));
13210 return .fromValue(try arith.shr(sema, block, lhs_ty, rhs_ty, lhs_val, rhs_val, src, lhs_src, rhs_src, if (exact) .shr_exact else .shr));
1321613211 }
1321713212 if (rhs_val.isUndef(zcu)) {
1321813213 return sema.failWithUseOfUndef(block, rhs_src, null);
......@@ -13269,8 +13264,10 @@ fn zirShr(
1326913264 break :rs rhs_src;
1327013265 };
1327113266 try sema.requireRuntimeBlock(block, src, runtime_src);
13272 const result = try block.addBinOp(air_tag, lhs, rhs);
13273 if (block.wantSafety()) {
13267
13268 const safety = block.wantSafety();
13269 const result = try block.addBinOp(if (!exact or safety) .shr else .shr_exact, lhs, rhs);
13270 if (safety) {
1327413271 const bit_count = scalar_ty.intInfo(zcu).bits;
1327513272 if (!std.math.isPowerOfTwo(bit_count)) {
1327613273 const bit_count_val = try pt.intValue(rhs_ty.scalarType(zcu), bit_count);
......@@ -13286,7 +13283,7 @@ fn zirShr(
1328613283 try sema.addSafetyCheck(block, src, ok, .shift_rhs_too_big);
1328713284 }
1328813285
13289 if (air_tag == .shr_exact) {
13286 if (exact) {
1329013287 const back = try block.addBinOp(.shl, result, rhs);
1329113288
1329213289 const ok = if (rhs_ty.zigTypeTag(zcu) == .vector) ok: {