interpret: fix CheckedBinOp behavior when overflow checking is disabled
This commit is contained in:
parent
e1d1848cc6
commit
6f01ff61b3
3 changed files with 14 additions and 2 deletions
|
@ -217,7 +217,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
sym::mul_with_overflow => BinOp::Mul,
|
sym::mul_with_overflow => BinOp::Mul,
|
||||||
_ => bug!(),
|
_ => bug!(),
|
||||||
};
|
};
|
||||||
self.binop_with_overflow(bin_op, &lhs, &rhs, dest)?;
|
self.binop_with_overflow(
|
||||||
|
bin_op, /*force_overflow_checks*/ true, &lhs, &rhs, dest,
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
sym::saturating_add | sym::saturating_sub => {
|
sym::saturating_add | sym::saturating_sub => {
|
||||||
let l = self.read_immediate(&args[0])?;
|
let l = self.read_immediate(&args[0])?;
|
||||||
|
|
|
@ -12,9 +12,13 @@ use super::{ImmTy, Immediate, InterpCx, Machine, PlaceTy};
|
||||||
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
/// Applies the binary operation `op` to the two operands and writes a tuple of the result
|
/// Applies the binary operation `op` to the two operands and writes a tuple of the result
|
||||||
/// and a boolean signifying the potential overflow to the destination.
|
/// and a boolean signifying the potential overflow to the destination.
|
||||||
|
///
|
||||||
|
/// `force_overflow_checks` indicates whether overflow checks should be done even when
|
||||||
|
/// `tcx.sess.overflow_checks()` is `false`.
|
||||||
pub fn binop_with_overflow(
|
pub fn binop_with_overflow(
|
||||||
&mut self,
|
&mut self,
|
||||||
op: mir::BinOp,
|
op: mir::BinOp,
|
||||||
|
force_overflow_checks: bool,
|
||||||
left: &ImmTy<'tcx, M::PointerTag>,
|
left: &ImmTy<'tcx, M::PointerTag>,
|
||||||
right: &ImmTy<'tcx, M::PointerTag>,
|
right: &ImmTy<'tcx, M::PointerTag>,
|
||||||
dest: &PlaceTy<'tcx, M::PointerTag>,
|
dest: &PlaceTy<'tcx, M::PointerTag>,
|
||||||
|
@ -26,6 +30,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
"type mismatch for result of {:?}",
|
"type mismatch for result of {:?}",
|
||||||
op,
|
op,
|
||||||
);
|
);
|
||||||
|
// As per https://github.com/rust-lang/rust/pull/98738, we always return `false` in the 2nd
|
||||||
|
// component when overflow checking is disabled.
|
||||||
|
let overflowed = overflowed && (force_overflow_checks || self.tcx.sess.overflow_checks());
|
||||||
|
// Write the result to `dest`.
|
||||||
if let Abi::ScalarPair(..) = dest.layout.abi {
|
if let Abi::ScalarPair(..) = dest.layout.abi {
|
||||||
// We can use the optimized path and avoid `place_field` (which might do
|
// We can use the optimized path and avoid `place_field` (which might do
|
||||||
// `force_allocation`).
|
// `force_allocation`).
|
||||||
|
|
|
@ -185,7 +185,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
let left = self.read_immediate(&self.eval_operand(left, None)?)?;
|
let left = self.read_immediate(&self.eval_operand(left, None)?)?;
|
||||||
let layout = binop_right_homogeneous(bin_op).then_some(left.layout);
|
let layout = binop_right_homogeneous(bin_op).then_some(left.layout);
|
||||||
let right = self.read_immediate(&self.eval_operand(right, layout)?)?;
|
let right = self.read_immediate(&self.eval_operand(right, layout)?)?;
|
||||||
self.binop_with_overflow(bin_op, &left, &right, &dest)?;
|
self.binop_with_overflow(
|
||||||
|
bin_op, /*force_overflow_checks*/ false, &left, &right, &dest,
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
UnaryOp(un_op, ref operand) => {
|
UnaryOp(un_op, ref operand) => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue