| ... | ... | @@ -8826,8 +8826,6 @@ fn zirShl( |
| 8826 | 8826 | return sema.addConstant(lhs_ty, val); |
| 8827 | 8827 | } else lhs_src; |
| 8828 | 8828 | |
| 8829 | | // TODO: insert runtime safety check for shl_exact |
| 8830 | | |
| 8831 | 8829 | const new_rhs = if (air_tag == .shl_sat) rhs: { |
| 8832 | 8830 | // Limit the RHS type for saturating shl to be an integer as small as the LHS. |
| 8833 | 8831 | if (rhs_is_comptime_int or |
| ... | ... | @@ -8845,6 +8843,41 @@ fn zirShl( |
| 8845 | 8843 | } else rhs; |
| 8846 | 8844 | |
| 8847 | 8845 | try sema.requireRuntimeBlock(block, runtime_src); |
| 8846 | if (block.wantSafety()) { |
| 8847 | const maybe_op_ov: ?Air.Inst.Tag = switch (air_tag) { |
| 8848 | .shl_exact => .shl_with_overflow, |
| 8849 | else => null, |
| 8850 | }; |
| 8851 | if (maybe_op_ov) |op_ov_tag| { |
| 8852 | const op_ov_tuple_ty = try sema.overflowArithmeticTupleType(lhs_ty); |
| 8853 | const op_ov = try block.addInst(.{ |
| 8854 | .tag = op_ov_tag, |
| 8855 | .data = .{ .ty_pl = .{ |
| 8856 | .ty = try sema.addType(op_ov_tuple_ty), |
| 8857 | .payload = try sema.addExtra(Air.Bin{ |
| 8858 | .lhs = lhs, |
| 8859 | .rhs = rhs, |
| 8860 | }), |
| 8861 | } }, |
| 8862 | }); |
| 8863 | const ov_bit = try sema.tupleFieldValByIndex(block, src, op_ov, 1, op_ov_tuple_ty); |
| 8864 | const any_ov_bit = if (lhs_ty.zigTypeTag() == .Vector) |
| 8865 | try block.addInst(.{ |
| 8866 | .tag = .reduce, |
| 8867 | .data = .{ .reduce = .{ |
| 8868 | .operand = ov_bit, |
| 8869 | .operation = .Or, |
| 8870 | } }, |
| 8871 | }) |
| 8872 | else |
| 8873 | ov_bit; |
| 8874 | const zero_ov = try sema.addConstant(Type.@"u1", Value.zero); |
| 8875 | const no_ov = try block.addBinOp(.cmp_eq, any_ov_bit, zero_ov); |
| 8876 | |
| 8877 | try sema.addSafetyCheck(block, no_ov, .shl_overflow); |
| 8878 | return sema.tupleFieldValByIndex(block, src, op_ov, 0, op_ov_tuple_ty); |
| 8879 | } |
| 8880 | } |
| 8848 | 8881 | return block.addBinOp(air_tag, lhs, new_rhs); |
| 8849 | 8882 | } |
| 8850 | 8883 | |
| ... | ... | @@ -16751,6 +16784,7 @@ pub const PanicId = enum { |
| 16751 | 16784 | index_out_of_bounds, |
| 16752 | 16785 | cast_truncated_data, |
| 16753 | 16786 | integer_overflow, |
| 16787 | shl_overflow, |
| 16754 | 16788 | }; |
| 16755 | 16789 | |
| 16756 | 16790 | fn addSafetyCheck( |
| ... | ... | @@ -16875,6 +16909,7 @@ fn safetyPanic( |
| 16875 | 16909 | .index_out_of_bounds => "attempt to index out of bounds", |
| 16876 | 16910 | .cast_truncated_data => "integer cast truncated bits", |
| 16877 | 16911 | .integer_overflow => "integer overflow", |
| 16912 | .shl_overflow => "left shift overflowed bits", |
| 16878 | 16913 | }; |
| 16879 | 16914 | |
| 16880 | 16915 | const msg_inst = msg_inst: { |