| ... | @@ -9996,40 +9996,34 @@ fn zirShl( | ... | @@ -9996,40 +9996,34 @@ fn zirShl( |
| 9996 | } else rhs; | 9996 | } else rhs; |
| 9997 | | 9997 | |
| 9998 | try sema.requireRuntimeBlock(block, src, runtime_src); | 9998 | try sema.requireRuntimeBlock(block, src, runtime_src); |
| 9999 | if (block.wantSafety()) { | 9999 | if (block.wantSafety() and air_tag == .shl_exact) { |
| 10000 | const maybe_op_ov: ?Air.Inst.Tag = switch (air_tag) { | 10000 | const op_ov_tuple_ty = try sema.overflowArithmeticTupleType(lhs_ty); |
| 10001 | .shl_exact => .shl_with_overflow, | 10001 | const op_ov = try block.addInst(.{ |
| 10002 | else => null, | 10002 | .tag = .shl_with_overflow, |
| 10003 | }; | 10003 | .data = .{ .ty_pl = .{ |
| 10004 | if (maybe_op_ov) |op_ov_tag| { | 10004 | .ty = try sema.addType(op_ov_tuple_ty), |
| 10005 | const op_ov_tuple_ty = try sema.overflowArithmeticTupleType(lhs_ty); | 10005 | .payload = try sema.addExtra(Air.Bin{ |
| 10006 | const op_ov = try block.addInst(.{ | 10006 | .lhs = lhs, |
| 10007 | .tag = op_ov_tag, | 10007 | .rhs = rhs, |
| 10008 | .data = .{ .ty_pl = .{ | 10008 | }), |
| 10009 | .ty = try sema.addType(op_ov_tuple_ty), | 10009 | } }, |
| 10010 | .payload = try sema.addExtra(Air.Bin{ | 10010 | }); |
| 10011 | .lhs = lhs, | 10011 | const ov_bit = try sema.tupleFieldValByIndex(block, src, op_ov, 1, op_ov_tuple_ty); |
| 10012 | .rhs = rhs, | 10012 | const any_ov_bit = if (lhs_ty.zigTypeTag() == .Vector) |
| 10013 | }), | 10013 | try block.addInst(.{ |
| | 10014 | .tag = .reduce, |
| | 10015 | .data = .{ .reduce = .{ |
| | 10016 | .operand = ov_bit, |
| | 10017 | .operation = .Or, |
| 10014 | } }, | 10018 | } }, |
| 10015 | }); | 10019 | }) |
| 10016 | const ov_bit = try sema.tupleFieldValByIndex(block, src, op_ov, 1, op_ov_tuple_ty); | 10020 | else |
| 10017 | const any_ov_bit = if (lhs_ty.zigTypeTag() == .Vector) | 10021 | ov_bit; |
| 10018 | try block.addInst(.{ | 10022 | const zero_ov = try sema.addConstant(Type.@"u1", Value.zero); |
| 10019 | .tag = .reduce, | 10023 | const no_ov = try block.addBinOp(.cmp_eq, any_ov_bit, zero_ov); |
| 10020 | .data = .{ .reduce = .{ | | |
| 10021 | .operand = ov_bit, | | |
| 10022 | .operation = .Or, | | |
| 10023 | } }, | | |
| 10024 | }) | | |
| 10025 | else | | |
| 10026 | ov_bit; | | |
| 10027 | const zero_ov = try sema.addConstant(Type.@"u1", Value.zero); | | |
| 10028 | const no_ov = try block.addBinOp(.cmp_eq, any_ov_bit, zero_ov); | | |
| 10029 | | 10024 | |
| 10030 | try sema.addSafetyCheck(block, no_ov, .shl_overflow); | 10025 | try sema.addSafetyCheck(block, no_ov, .shl_overflow); |
| 10031 | return sema.tupleFieldValByIndex(block, src, op_ov, 0, op_ov_tuple_ty); | 10026 | return sema.tupleFieldValByIndex(block, src, op_ov, 0, op_ov_tuple_ty); |
| 10032 | } | | |
| 10033 | } | 10027 | } |
| 10034 | return block.addBinOp(air_tag, lhs, new_rhs); | 10028 | return block.addBinOp(air_tag, lhs, new_rhs); |
| 10035 | } | 10029 | } |
| ... | @@ -10107,7 +10101,23 @@ fn zirShr( | ... | @@ -10107,7 +10101,23 @@ fn zirShr( |
| 10107 | } else rhs_src; | 10101 | } else rhs_src; |
| 10108 | | 10102 | |
| 10109 | try sema.requireRuntimeBlock(block, src, runtime_src); | 10103 | try sema.requireRuntimeBlock(block, src, runtime_src); |
| 10110 | return block.addBinOp(air_tag, lhs, rhs); | 10104 | const result = try block.addBinOp(air_tag, lhs, rhs); |
| | 10105 | if (block.wantSafety() and air_tag == .shr_exact) { |
| | 10106 | const back = try block.addBinOp(.shl, result, rhs); |
| | 10107 | |
| | 10108 | const ok = if (rhs_ty.zigTypeTag() == .Vector) ok: { |
| | 10109 | const eql = try block.addCmpVector(lhs, back, .eq, try sema.addType(rhs_ty)); |
| | 10110 | break :ok try block.addInst(.{ |
| | 10111 | .tag = .reduce, |
| | 10112 | .data = .{ .reduce = .{ |
| | 10113 | .operand = eql, |
| | 10114 | .operation = .And, |
| | 10115 | } }, |
| | 10116 | }); |
| | 10117 | } else try block.addBinOp(.cmp_eq, lhs, back); |
| | 10118 | try sema.addSafetyCheck(block, ok, .shr_overflow); |
| | 10119 | } |
| | 10120 | return result; |
| 10111 | } | 10121 | } |
| 10112 | | 10122 | |
| 10113 | fn zirBitwise( | 10123 | fn zirBitwise( |
| ... | @@ -18802,6 +18812,7 @@ pub const PanicId = enum { | ... | @@ -18802,6 +18812,7 @@ pub const PanicId = enum { |
| 18802 | cast_truncated_data, | 18812 | cast_truncated_data, |
| 18803 | integer_overflow, | 18813 | integer_overflow, |
| 18804 | shl_overflow, | 18814 | shl_overflow, |
| | 18815 | shr_overflow, |
| 18805 | }; | 18816 | }; |
| 18806 | | 18817 | |
| 18807 | fn addSafetyCheck( | 18818 | fn addSafetyCheck( |
| ... | @@ -19019,6 +19030,7 @@ fn safetyPanic( | ... | @@ -19019,6 +19030,7 @@ fn safetyPanic( |
| 19019 | .cast_truncated_data => "integer cast truncated bits", | 19030 | .cast_truncated_data => "integer cast truncated bits", |
| 19020 | .integer_overflow => "integer overflow", | 19031 | .integer_overflow => "integer overflow", |
| 19021 | .shl_overflow => "left shift overflowed bits", | 19032 | .shl_overflow => "left shift overflowed bits", |
| | 19033 | .shr_overflow => "right shift overflowed bits", |
| 19022 | }; | 19034 | }; |
| 19023 | | 19035 | |
| 19024 | const msg_inst = msg_inst: { | 19036 | const msg_inst = msg_inst: { |