mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-22 03:44:24 +00:00
Remove Rvalue::CheckedBinaryOp
This commit is contained in:
parent
8e78d16804
commit
95c0e5c6a8
@ -1312,8 +1312,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
);
|
||||
}
|
||||
|
||||
Rvalue::BinaryOp(_bin_op, box (operand1, operand2))
|
||||
| Rvalue::CheckedBinaryOp(_bin_op, box (operand1, operand2)) => {
|
||||
Rvalue::BinaryOp(_bin_op, box (operand1, operand2)) => {
|
||||
self.consume_operand(location, (operand1, span), flow_state);
|
||||
self.consume_operand(location, (operand2, span), flow_state);
|
||||
}
|
||||
|
@ -302,8 +302,7 @@ impl<'cx, 'tcx> LoanInvalidationsGenerator<'cx, 'tcx> {
|
||||
);
|
||||
}
|
||||
|
||||
Rvalue::BinaryOp(_bin_op, box (operand1, operand2))
|
||||
| Rvalue::CheckedBinaryOp(_bin_op, box (operand1, operand2)) => {
|
||||
Rvalue::BinaryOp(_bin_op, box (operand1, operand2)) => {
|
||||
self.consume_operand(location, operand1);
|
||||
self.consume_operand(location, operand2);
|
||||
}
|
||||
|
@ -2417,8 +2417,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
self.check_operand(op, location);
|
||||
}
|
||||
|
||||
Rvalue::BinaryOp(_, box (left, right))
|
||||
| Rvalue::CheckedBinaryOp(_, box (left, right)) => {
|
||||
Rvalue::BinaryOp(_, box (left, right)) => {
|
||||
self.check_operand(left, location);
|
||||
self.check_operand(right, location);
|
||||
}
|
||||
@ -2445,7 +2444,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
| Rvalue::Cast(..)
|
||||
| Rvalue::ShallowInitBox(..)
|
||||
| Rvalue::BinaryOp(..)
|
||||
| Rvalue::CheckedBinaryOp(..)
|
||||
| Rvalue::NullaryOp(..)
|
||||
| Rvalue::CopyForDeref(..)
|
||||
| Rvalue::UnaryOp(..)
|
||||
|
@ -609,14 +609,11 @@ fn codegen_stmt<'tcx>(
|
||||
let lhs = codegen_operand(fx, &lhs_rhs.0);
|
||||
let rhs = codegen_operand(fx, &lhs_rhs.1);
|
||||
|
||||
let res = crate::num::codegen_binop(fx, bin_op, lhs, rhs);
|
||||
lval.write_cvalue(fx, res);
|
||||
}
|
||||
Rvalue::CheckedBinaryOp(bin_op, ref lhs_rhs) => {
|
||||
let lhs = codegen_operand(fx, &lhs_rhs.0);
|
||||
let rhs = codegen_operand(fx, &lhs_rhs.1);
|
||||
|
||||
let res = crate::num::codegen_checked_int_binop(fx, bin_op, lhs, rhs);
|
||||
let res = if let Some(bin_op) = bin_op.overflowing_to_wrapping() {
|
||||
crate::num::codegen_checked_int_binop(fx, bin_op, lhs, rhs)
|
||||
} else {
|
||||
crate::num::codegen_binop(fx, bin_op, lhs, rhs)
|
||||
};
|
||||
lval.write_cvalue(fx, res);
|
||||
}
|
||||
Rvalue::UnaryOp(un_op, ref operand) => {
|
||||
|
@ -70,6 +70,7 @@ pub(crate) fn maybe_codegen<'tcx>(
|
||||
}
|
||||
BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne | BinOp::Cmp => None,
|
||||
BinOp::Shl | BinOp::ShlUnchecked | BinOp::Shr | BinOp::ShrUnchecked => None,
|
||||
BinOp::AddWithOverflow | BinOp::SubWithOverflow | BinOp::MulWithOverflow => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,6 +133,7 @@ pub(crate) fn maybe_codegen_checked<'tcx>(
|
||||
Some(out_place.to_cvalue(fx))
|
||||
}
|
||||
BinOp::AddUnchecked | BinOp::SubUnchecked | BinOp::MulUnchecked => unreachable!(),
|
||||
BinOp::AddWithOverflow | BinOp::SubWithOverflow | BinOp::MulWithOverflow => unreachable!(),
|
||||
BinOp::Offset => unreachable!("offset should only be used on pointers, not 128bit ints"),
|
||||
BinOp::Div | BinOp::Rem => unreachable!(),
|
||||
BinOp::Cmp => unreachable!(),
|
||||
|
@ -179,6 +179,9 @@ pub(crate) fn codegen_int_binop<'tcx>(
|
||||
}
|
||||
}
|
||||
BinOp::Offset => unreachable!("Offset is not an integer operation"),
|
||||
BinOp::AddWithOverflow | BinOp::SubWithOverflow | BinOp::MulWithOverflow => {
|
||||
unreachable!("Overflow binops handled by `codegen_checked_int_binop`")
|
||||
}
|
||||
// Compare binops handles by `codegen_binop`.
|
||||
BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge | BinOp::Cmp => {
|
||||
unreachable!("{:?}({:?}, {:?})", bin_op, in_lhs.layout().ty, in_rhs.layout().ty);
|
||||
|
@ -572,6 +572,22 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
}
|
||||
}
|
||||
|
||||
mir::Rvalue::BinaryOp(op_with_overflow, box (ref lhs, ref rhs))
|
||||
if let Some(op) = op_with_overflow.overflowing_to_wrapping() =>
|
||||
{
|
||||
let lhs = self.codegen_operand(bx, lhs);
|
||||
let rhs = self.codegen_operand(bx, rhs);
|
||||
let result = self.codegen_scalar_checked_binop(
|
||||
bx,
|
||||
op,
|
||||
lhs.immediate(),
|
||||
rhs.immediate(),
|
||||
lhs.layout.ty,
|
||||
);
|
||||
let val_ty = op.ty(bx.tcx(), lhs.layout.ty, rhs.layout.ty);
|
||||
let operand_ty = Ty::new_tup(bx.tcx(), &[val_ty, bx.tcx().types.bool]);
|
||||
OperandRef { val: result, layout: bx.cx().layout_of(operand_ty) }
|
||||
}
|
||||
mir::Rvalue::BinaryOp(op, box (ref lhs, ref rhs)) => {
|
||||
let lhs = self.codegen_operand(bx, lhs);
|
||||
let rhs = self.codegen_operand(bx, rhs);
|
||||
@ -600,20 +616,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
layout: bx.cx().layout_of(op.ty(bx.tcx(), lhs.layout.ty, rhs.layout.ty)),
|
||||
}
|
||||
}
|
||||
mir::Rvalue::CheckedBinaryOp(op, box (ref lhs, ref rhs)) => {
|
||||
let lhs = self.codegen_operand(bx, lhs);
|
||||
let rhs = self.codegen_operand(bx, rhs);
|
||||
let result = self.codegen_scalar_checked_binop(
|
||||
bx,
|
||||
op,
|
||||
lhs.immediate(),
|
||||
rhs.immediate(),
|
||||
lhs.layout.ty,
|
||||
);
|
||||
let val_ty = op.ty(bx.tcx(), lhs.layout.ty, rhs.layout.ty);
|
||||
let operand_ty = Ty::new_tup(bx.tcx(), &[val_ty, bx.tcx().types.bool]);
|
||||
OperandRef { val: result, layout: bx.cx().layout_of(operand_ty) }
|
||||
}
|
||||
|
||||
mir::Rvalue::UnaryOp(op, ref operand) => {
|
||||
let operand = self.codegen_operand(bx, operand);
|
||||
@ -924,6 +926,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
bx.select(is_lt, bx.cx().const_i8(Ordering::Less as i8), ge)
|
||||
}
|
||||
}
|
||||
mir::BinOp::AddWithOverflow
|
||||
| mir::BinOp::SubWithOverflow
|
||||
| mir::BinOp::MulWithOverflow => {
|
||||
bug!("{op:?} needs to return a pair, so call codegen_scalar_checked_binop instead")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1036,7 +1043,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
mir::Rvalue::Cast(..) | // (*)
|
||||
mir::Rvalue::ShallowInitBox(..) | // (*)
|
||||
mir::Rvalue::BinaryOp(..) |
|
||||
mir::Rvalue::CheckedBinaryOp(..) |
|
||||
mir::Rvalue::UnaryOp(..) |
|
||||
mir::Rvalue::Discriminant(..) |
|
||||
mir::Rvalue::NullaryOp(..) |
|
||||
|
@ -167,15 +167,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
let left = self.read_immediate(&self.eval_operand(left, layout)?)?;
|
||||
let layout = util::binop_right_homogeneous(bin_op).then_some(left.layout);
|
||||
let right = self.read_immediate(&self.eval_operand(right, layout)?)?;
|
||||
self.binop_ignore_overflow(bin_op, &left, &right, &dest)?;
|
||||
}
|
||||
|
||||
CheckedBinaryOp(bin_op, box (ref left, ref right)) => {
|
||||
// Due to the extra boolean in the result, we can never reuse the `dest.layout`.
|
||||
let left = self.read_immediate(&self.eval_operand(left, None)?)?;
|
||||
let layout = util::binop_right_homogeneous(bin_op).then_some(left.layout);
|
||||
let right = self.read_immediate(&self.eval_operand(right, layout)?)?;
|
||||
self.binop_with_overflow(bin_op, &left, &right, &dest)?;
|
||||
if let Some(bin_op) = bin_op.overflowing_to_wrapping() {
|
||||
self.binop_with_overflow(bin_op, &left, &right, &dest)?;
|
||||
} else {
|
||||
self.binop_ignore_overflow(bin_op, &left, &right, &dest)?;
|
||||
}
|
||||
}
|
||||
|
||||
UnaryOp(un_op, ref operand) => {
|
||||
|
@ -580,7 +580,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
Rvalue::BinaryOp(op, box (lhs, rhs)) | Rvalue::CheckedBinaryOp(op, box (lhs, rhs)) => {
|
||||
Rvalue::BinaryOp(op, box (lhs, rhs)) => {
|
||||
let lhs_ty = lhs.ty(self.body, self.tcx);
|
||||
let rhs_ty = rhs.ty(self.body, self.tcx);
|
||||
|
||||
|
@ -261,7 +261,7 @@ where
|
||||
| Rvalue::Cast(_, operand, _)
|
||||
| Rvalue::ShallowInitBox(operand, _) => in_operand::<Q, _>(cx, in_local, operand),
|
||||
|
||||
Rvalue::BinaryOp(_, box (lhs, rhs)) | Rvalue::CheckedBinaryOp(_, box (lhs, rhs)) => {
|
||||
Rvalue::BinaryOp(_, box (lhs, rhs)) => {
|
||||
in_operand::<Q, _>(cx, in_local, lhs) || in_operand::<Q, _>(cx, in_local, rhs)
|
||||
}
|
||||
|
||||
|
@ -200,7 +200,6 @@ where
|
||||
| mir::Rvalue::Repeat(..)
|
||||
| mir::Rvalue::Len(..)
|
||||
| mir::Rvalue::BinaryOp(..)
|
||||
| mir::Rvalue::CheckedBinaryOp(..)
|
||||
| mir::Rvalue::NullaryOp(..)
|
||||
| mir::Rvalue::UnaryOp(..)
|
||||
| mir::Rvalue::Discriminant(..)
|
||||
|
@ -1037,8 +1037,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||
)
|
||||
}
|
||||
}
|
||||
AddUnchecked | SubUnchecked | MulUnchecked | Shl | ShlUnchecked | Shr
|
||||
| ShrUnchecked => {
|
||||
AddUnchecked | AddWithOverflow | SubUnchecked | SubWithOverflow
|
||||
| MulUnchecked | MulWithOverflow | Shl | ShlUnchecked | Shr | ShrUnchecked => {
|
||||
for x in [a, b] {
|
||||
check_kinds!(
|
||||
x,
|
||||
@ -1067,31 +1067,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
Rvalue::CheckedBinaryOp(op, vals) => {
|
||||
use BinOp::*;
|
||||
let a = vals.0.ty(&self.body.local_decls, self.tcx);
|
||||
let b = vals.1.ty(&self.body.local_decls, self.tcx);
|
||||
match op {
|
||||
Add | Sub | Mul => {
|
||||
for x in [a, b] {
|
||||
check_kinds!(
|
||||
x,
|
||||
"Cannot perform checked arithmetic on type {:?}",
|
||||
ty::Uint(..) | ty::Int(..)
|
||||
)
|
||||
}
|
||||
if a != b {
|
||||
self.fail(
|
||||
location,
|
||||
format!(
|
||||
"Cannot perform checked arithmetic on unequal types {a:?} and {b:?}"
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => self.fail(location, format!("There is no checked version of {op:?}")),
|
||||
}
|
||||
}
|
||||
Rvalue::UnaryOp(op, operand) => {
|
||||
let a = operand.ty(&self.body.local_decls, self.tcx);
|
||||
match op {
|
||||
|
@ -19,7 +19,9 @@ pub fn binop_left_homogeneous(op: mir::BinOp) -> bool {
|
||||
match op {
|
||||
Add | AddUnchecked | Sub | SubUnchecked | Mul | MulUnchecked | Div | Rem | BitXor
|
||||
| BitAnd | BitOr | Offset | Shl | ShlUnchecked | Shr | ShrUnchecked => true,
|
||||
Eq | Ne | Lt | Le | Gt | Ge | Cmp => false,
|
||||
AddWithOverflow | SubWithOverflow | MulWithOverflow | Eq | Ne | Lt | Le | Gt | Ge | Cmp => {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,8 +31,9 @@ pub fn binop_left_homogeneous(op: mir::BinOp) -> bool {
|
||||
pub fn binop_right_homogeneous(op: mir::BinOp) -> bool {
|
||||
use rustc_middle::mir::BinOp::*;
|
||||
match op {
|
||||
Add | AddUnchecked | Sub | SubUnchecked | Mul | MulUnchecked | Div | Rem | BitXor
|
||||
| BitAnd | BitOr | Eq | Ne | Lt | Le | Gt | Ge | Cmp => true,
|
||||
Add | AddUnchecked | AddWithOverflow | Sub | SubUnchecked | SubWithOverflow | Mul
|
||||
| MulUnchecked | MulWithOverflow | Div | Rem | BitXor | BitAnd | BitOr | Eq | Ne | Lt
|
||||
| Le | Gt | Ge | Cmp => true,
|
||||
Offset | Shl | ShlUnchecked | Shr | ShrUnchecked => false,
|
||||
}
|
||||
}
|
||||
|
@ -971,9 +971,6 @@ impl<'tcx> Debug for Rvalue<'tcx> {
|
||||
with_no_trimmed_paths!(write!(fmt, "{place:?} as {ty} ({kind:?})"))
|
||||
}
|
||||
BinaryOp(ref op, box (ref a, ref b)) => write!(fmt, "{op:?}({a:?}, {b:?})"),
|
||||
CheckedBinaryOp(ref op, box (ref a, ref b)) => {
|
||||
write!(fmt, "Checked{op:?}({a:?}, {b:?})")
|
||||
}
|
||||
UnaryOp(ref op, ref a) => write!(fmt, "{op:?}({a:?})"),
|
||||
Discriminant(ref place) => write!(fmt, "discriminant({place:?})"),
|
||||
NullaryOp(ref op, ref t) => {
|
||||
|
@ -438,7 +438,6 @@ impl<'tcx> Rvalue<'tcx> {
|
||||
_,
|
||||
)
|
||||
| Rvalue::BinaryOp(_, _)
|
||||
| Rvalue::CheckedBinaryOp(_, _)
|
||||
| Rvalue::NullaryOp(_, _)
|
||||
| Rvalue::UnaryOp(_, _)
|
||||
| Rvalue::Discriminant(_)
|
||||
|
@ -1295,18 +1295,12 @@ pub enum Rvalue<'tcx> {
|
||||
/// truncated as needed.
|
||||
/// * The `Bit*` operations accept signed integers, unsigned integers, or bools with matching
|
||||
/// types and return a value of that type.
|
||||
/// * The `FooWithOverflow` are like the `Foo`, but returning `(T, bool)` instead of just `T`,
|
||||
/// where the `bool` is true if the result is not equal to the infinite-precision result.
|
||||
/// * The remaining operations accept signed integers, unsigned integers, or floats with
|
||||
/// matching types and return a value of that type.
|
||||
BinaryOp(BinOp, Box<(Operand<'tcx>, Operand<'tcx>)>),
|
||||
|
||||
/// Same as `BinaryOp`, but yields `(T, bool)` with a `bool` indicating an error condition.
|
||||
///
|
||||
/// For addition, subtraction, and multiplication on integers the error condition is set when
|
||||
/// the infinite precision result would not be equal to the actual result.
|
||||
///
|
||||
/// Other combinations of types and operators are unsupported.
|
||||
CheckedBinaryOp(BinOp, Box<(Operand<'tcx>, Operand<'tcx>)>),
|
||||
|
||||
/// Computes a value as described by the operation.
|
||||
NullaryOp(NullOp<'tcx>, Ty<'tcx>),
|
||||
|
||||
@ -1449,14 +1443,23 @@ pub enum BinOp {
|
||||
Add,
|
||||
/// Like `Add`, but with UB on overflow. (Integers only.)
|
||||
AddUnchecked,
|
||||
/// Like `Add`, but returns `(T, bool)` of both the wrapped result
|
||||
/// and a bool indicating whether it overflowed.
|
||||
AddWithOverflow,
|
||||
/// The `-` operator (subtraction)
|
||||
Sub,
|
||||
/// Like `Sub`, but with UB on overflow. (Integers only.)
|
||||
SubUnchecked,
|
||||
/// Like `Sub`, but returns `(T, bool)` of both the wrapped result
|
||||
/// and a bool indicating whether it overflowed.
|
||||
SubWithOverflow,
|
||||
/// The `*` operator (multiplication)
|
||||
Mul,
|
||||
/// Like `Mul`, but with UB on overflow. (Integers only.)
|
||||
MulUnchecked,
|
||||
/// Like `Mul`, but returns `(T, bool)` of both the wrapped result
|
||||
/// and a bool indicating whether it overflowed.
|
||||
MulWithOverflow,
|
||||
/// The `/` operator (division)
|
||||
///
|
||||
/// For integer types, division by zero is UB, as is `MIN / -1` for signed.
|
||||
|
@ -179,12 +179,6 @@ impl<'tcx> Rvalue<'tcx> {
|
||||
let rhs_ty = rhs.ty(local_decls, tcx);
|
||||
op.ty(tcx, lhs_ty, rhs_ty)
|
||||
}
|
||||
Rvalue::CheckedBinaryOp(op, box (ref lhs, ref rhs)) => {
|
||||
let lhs_ty = lhs.ty(local_decls, tcx);
|
||||
let rhs_ty = rhs.ty(local_decls, tcx);
|
||||
let ty = op.ty(tcx, lhs_ty, rhs_ty);
|
||||
Ty::new_tup(tcx, &[ty, tcx.types.bool])
|
||||
}
|
||||
Rvalue::UnaryOp(UnOp::Not | UnOp::Neg, ref operand) => operand.ty(local_decls, tcx),
|
||||
Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx),
|
||||
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {
|
||||
@ -263,6 +257,11 @@ impl<'tcx> BinOp {
|
||||
assert_eq!(lhs_ty, rhs_ty);
|
||||
lhs_ty
|
||||
}
|
||||
&BinOp::AddWithOverflow | &BinOp::SubWithOverflow | &BinOp::MulWithOverflow => {
|
||||
// these should be integers of the same size.
|
||||
assert_eq!(lhs_ty, rhs_ty);
|
||||
Ty::new_tup(tcx, &[lhs_ty, tcx.types.bool])
|
||||
}
|
||||
&BinOp::Shl
|
||||
| &BinOp::ShlUnchecked
|
||||
| &BinOp::Shr
|
||||
@ -315,6 +314,9 @@ impl BinOp {
|
||||
BinOp::Le => hir::BinOpKind::Le,
|
||||
BinOp::Ge => hir::BinOpKind::Ge,
|
||||
BinOp::Cmp
|
||||
| BinOp::AddWithOverflow
|
||||
| BinOp::SubWithOverflow
|
||||
| BinOp::MulWithOverflow
|
||||
| BinOp::AddUnchecked
|
||||
| BinOp::SubUnchecked
|
||||
| BinOp::MulUnchecked
|
||||
@ -325,4 +327,24 @@ impl BinOp {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// If this is a `FooWithOverflow`, return `Some(Foo)`.
|
||||
pub fn overflowing_to_wrapping(self) -> Option<BinOp> {
|
||||
Some(match self {
|
||||
BinOp::AddWithOverflow => BinOp::Add,
|
||||
BinOp::SubWithOverflow => BinOp::Sub,
|
||||
BinOp::MulWithOverflow => BinOp::Mul,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
/// If this is a `Foo`, return `Some(FooWithOverflow)`.
|
||||
pub fn wrapping_to_overflowing(self) -> Option<BinOp> {
|
||||
Some(match self {
|
||||
BinOp::Add => BinOp::AddWithOverflow,
|
||||
BinOp::Sub => BinOp::SubWithOverflow,
|
||||
BinOp::Mul => BinOp::MulWithOverflow,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -696,8 +696,7 @@ macro_rules! make_mir_visitor {
|
||||
self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
|
||||
}
|
||||
|
||||
Rvalue::BinaryOp(_bin_op, box(lhs, rhs))
|
||||
| Rvalue::CheckedBinaryOp(_bin_op, box(lhs, rhs)) => {
|
||||
Rvalue::BinaryOp(_bin_op, box(lhs, rhs)) => {
|
||||
self.visit_operand(lhs, location);
|
||||
self.visit_operand(rhs, location);
|
||||
}
|
||||
|
@ -195,9 +195,15 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
|
||||
},
|
||||
@call(mir_checked, args) => {
|
||||
parse_by_kind!(self, args[0], _, "binary op",
|
||||
ExprKind::Binary { op, lhs, rhs } => Ok(Rvalue::CheckedBinaryOp(
|
||||
*op, Box::new((self.parse_operand(*lhs)?, self.parse_operand(*rhs)?))
|
||||
)),
|
||||
ExprKind::Binary { op, lhs, rhs } => {
|
||||
if let Some(op_with_overflow) = op.wrapping_to_overflowing() {
|
||||
Ok(Rvalue::BinaryOp(
|
||||
op_with_overflow, Box::new((self.parse_operand(*lhs)?, self.parse_operand(*rhs)?))
|
||||
))
|
||||
} else {
|
||||
Err(self.expr_error(expr_id, "No WithOverflow form of this operator"))
|
||||
}
|
||||
},
|
||||
)
|
||||
},
|
||||
@call(mir_offset, args) => {
|
||||
|
@ -568,11 +568,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
let result_tup = Ty::new_tup(self.tcx, &[ty, bool_ty]);
|
||||
let result_value = self.temp(result_tup, span);
|
||||
|
||||
let op_with_overflow = op.wrapping_to_overflowing().unwrap();
|
||||
|
||||
self.cfg.push_assign(
|
||||
block,
|
||||
source_info,
|
||||
result_value,
|
||||
Rvalue::CheckedBinaryOp(op, Box::new((lhs.to_copy(), rhs.to_copy()))),
|
||||
Rvalue::BinaryOp(op_with_overflow, Box::new((lhs.to_copy(), rhs.to_copy()))),
|
||||
);
|
||||
let val_fld = FieldIdx::ZERO;
|
||||
let of_fld = FieldIdx::new(1);
|
||||
|
@ -109,7 +109,6 @@ where
|
||||
| Rvalue::Repeat(..)
|
||||
| Rvalue::Len(..)
|
||||
| Rvalue::BinaryOp(..)
|
||||
| Rvalue::CheckedBinaryOp(..)
|
||||
| Rvalue::NullaryOp(..)
|
||||
| Rvalue::UnaryOp(..)
|
||||
| Rvalue::Discriminant(..)
|
||||
|
@ -420,8 +420,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> {
|
||||
| Rvalue::Cast(_, ref operand, _)
|
||||
| Rvalue::ShallowInitBox(ref operand, _)
|
||||
| Rvalue::UnaryOp(_, ref operand) => self.gather_operand(operand),
|
||||
Rvalue::BinaryOp(ref _binop, box (ref lhs, ref rhs))
|
||||
| Rvalue::CheckedBinaryOp(ref _binop, box (ref lhs, ref rhs)) => {
|
||||
Rvalue::BinaryOp(ref _binop, box (ref lhs, ref rhs)) => {
|
||||
self.gather_operand(lhs);
|
||||
self.gather_operand(rhs);
|
||||
}
|
||||
|
@ -184,7 +184,6 @@ pub trait ValueAnalysis<'tcx> {
|
||||
| Rvalue::Len(..)
|
||||
| Rvalue::Cast(..)
|
||||
| Rvalue::BinaryOp(..)
|
||||
| Rvalue::CheckedBinaryOp(..)
|
||||
| Rvalue::NullaryOp(..)
|
||||
| Rvalue::UnaryOp(..)
|
||||
| Rvalue::Discriminant(..)
|
||||
|
@ -165,7 +165,9 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
Rvalue::CheckedBinaryOp(op, box (left, right)) => {
|
||||
Rvalue::BinaryOp(overflowing_op, box (left, right))
|
||||
if let Some(op) = overflowing_op.overflowing_to_wrapping() =>
|
||||
{
|
||||
// Flood everything now, so we can use `insert_value_idx` directly later.
|
||||
state.flood(target.as_ref(), self.map());
|
||||
|
||||
@ -175,7 +177,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
|
||||
let overflow_target = self.map().apply(target, TrackElem::Field(1_u32.into()));
|
||||
|
||||
if value_target.is_some() || overflow_target.is_some() {
|
||||
let (val, overflow) = self.binary_op(state, *op, left, right);
|
||||
let (val, overflow) = self.binary_op(state, op, left, right);
|
||||
|
||||
if let Some(value_target) = value_target {
|
||||
// We have flooded `target` earlier.
|
||||
|
@ -564,7 +564,7 @@ impl WriteInfo {
|
||||
| Rvalue::ShallowInitBox(op, _) => {
|
||||
self.add_operand(op);
|
||||
}
|
||||
Rvalue::BinaryOp(_, ops) | Rvalue::CheckedBinaryOp(_, ops) => {
|
||||
Rvalue::BinaryOp(_, ops) => {
|
||||
for op in [&ops.0, &ops.1] {
|
||||
self.add_operand(op);
|
||||
}
|
||||
|
@ -831,23 +831,18 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||
// on both operands for side effect.
|
||||
let lhs = lhs?;
|
||||
let rhs = rhs?;
|
||||
if let Some(value) = self.simplify_binary(op, false, ty, lhs, rhs) {
|
||||
return Some(value);
|
||||
|
||||
if let Some(op) = op.overflowing_to_wrapping() {
|
||||
if let Some(value) = self.simplify_binary(op, true, ty, lhs, rhs) {
|
||||
return Some(value);
|
||||
}
|
||||
Value::CheckedBinaryOp(op, lhs, rhs)
|
||||
} else {
|
||||
if let Some(value) = self.simplify_binary(op, false, ty, lhs, rhs) {
|
||||
return Some(value);
|
||||
}
|
||||
Value::BinaryOp(op, lhs, rhs)
|
||||
}
|
||||
Value::BinaryOp(op, lhs, rhs)
|
||||
}
|
||||
Rvalue::CheckedBinaryOp(op, box (ref mut lhs, ref mut rhs)) => {
|
||||
let ty = lhs.ty(self.local_decls, self.tcx);
|
||||
let lhs = self.simplify_operand(lhs, location);
|
||||
let rhs = self.simplify_operand(rhs, location);
|
||||
// Only short-circuit options after we called `simplify_operand`
|
||||
// on both operands for side effect.
|
||||
let lhs = lhs?;
|
||||
let rhs = rhs?;
|
||||
if let Some(value) = self.simplify_binary(op, true, ty, lhs, rhs) {
|
||||
return Some(value);
|
||||
}
|
||||
Value::CheckedBinaryOp(op, lhs, rhs)
|
||||
}
|
||||
Rvalue::UnaryOp(op, ref mut arg) => {
|
||||
let arg = self.simplify_operand(arg, location)?;
|
||||
|
@ -399,16 +399,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||
}
|
||||
Rvalue::BinaryOp(op, box (left, right)) => {
|
||||
trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right);
|
||||
self.check_binary_op(*op, left, right, location)?;
|
||||
}
|
||||
Rvalue::CheckedBinaryOp(op, box (left, right)) => {
|
||||
trace!(
|
||||
"checking CheckedBinaryOp(op = {:?}, left = {:?}, right = {:?})",
|
||||
op,
|
||||
left,
|
||||
right
|
||||
);
|
||||
self.check_binary_op(*op, left, right, location)?;
|
||||
let op = op.overflowing_to_wrapping().unwrap_or(*op);
|
||||
self.check_binary_op(op, left, right, location)?;
|
||||
}
|
||||
|
||||
// Do not try creating references (#67862)
|
||||
@ -555,24 +547,18 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||
let right = self.eval_operand(right)?;
|
||||
let right = self.use_ecx(|this| this.ecx.read_immediate(&right))?;
|
||||
|
||||
let val =
|
||||
self.use_ecx(|this| this.ecx.wrapping_binary_op(bin_op, &left, &right))?;
|
||||
val.into()
|
||||
}
|
||||
|
||||
CheckedBinaryOp(bin_op, box (ref left, ref right)) => {
|
||||
let left = self.eval_operand(left)?;
|
||||
let left = self.use_ecx(|this| this.ecx.read_immediate(&left))?;
|
||||
|
||||
let right = self.eval_operand(right)?;
|
||||
let right = self.use_ecx(|this| this.ecx.read_immediate(&right))?;
|
||||
|
||||
let (val, overflowed) =
|
||||
self.use_ecx(|this| this.ecx.overflowing_binary_op(bin_op, &left, &right))?;
|
||||
let overflowed = ImmTy::from_bool(overflowed, self.tcx);
|
||||
Value::Aggregate {
|
||||
variant: VariantIdx::ZERO,
|
||||
fields: [Value::from(val), overflowed.into()].into_iter().collect(),
|
||||
if let Some(bin_op) = bin_op.overflowing_to_wrapping() {
|
||||
let (val, overflowed) =
|
||||
self.use_ecx(|this| this.ecx.overflowing_binary_op(bin_op, &left, &right))?;
|
||||
let overflowed = ImmTy::from_bool(overflowed, self.tcx);
|
||||
Value::Aggregate {
|
||||
variant: VariantIdx::ZERO,
|
||||
fields: [Value::from(val), overflowed.into()].into_iter().collect(),
|
||||
}
|
||||
} else {
|
||||
let val =
|
||||
self.use_ecx(|this| this.ecx.wrapping_binary_op(bin_op, &left, &right))?;
|
||||
val.into()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,16 +140,16 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
|
||||
rhs = args.next().unwrap();
|
||||
}
|
||||
let bin_op = match intrinsic.name {
|
||||
sym::add_with_overflow => BinOp::Add,
|
||||
sym::sub_with_overflow => BinOp::Sub,
|
||||
sym::mul_with_overflow => BinOp::Mul,
|
||||
sym::add_with_overflow => BinOp::AddWithOverflow,
|
||||
sym::sub_with_overflow => BinOp::SubWithOverflow,
|
||||
sym::mul_with_overflow => BinOp::MulWithOverflow,
|
||||
_ => bug!("unexpected intrinsic"),
|
||||
};
|
||||
block.statements.push(Statement {
|
||||
source_info: terminator.source_info,
|
||||
kind: StatementKind::Assign(Box::new((
|
||||
*destination,
|
||||
Rvalue::CheckedBinaryOp(bin_op, Box::new((lhs.node, rhs.node))),
|
||||
Rvalue::BinaryOp(bin_op, Box::new((lhs.node, rhs.node))),
|
||||
))),
|
||||
});
|
||||
terminator.kind = TerminatorKind::Goto { target };
|
||||
|
@ -470,7 +470,7 @@ impl<'tcx> Validator<'_, 'tcx> {
|
||||
self.validate_operand(operand)?;
|
||||
}
|
||||
|
||||
Rvalue::BinaryOp(op, box (lhs, rhs)) | Rvalue::CheckedBinaryOp(op, box (lhs, rhs)) => {
|
||||
Rvalue::BinaryOp(op, box (lhs, rhs)) => {
|
||||
let op = *op;
|
||||
let lhs_ty = lhs.ty(self.body, self.tcx);
|
||||
|
||||
@ -539,10 +539,13 @@ impl<'tcx> Validator<'_, 'tcx> {
|
||||
| BinOp::Offset
|
||||
| BinOp::Add
|
||||
| BinOp::AddUnchecked
|
||||
| BinOp::AddWithOverflow
|
||||
| BinOp::Sub
|
||||
| BinOp::SubUnchecked
|
||||
| BinOp::SubWithOverflow
|
||||
| BinOp::Mul
|
||||
| BinOp::MulUnchecked
|
||||
| BinOp::MulWithOverflow
|
||||
| BinOp::BitXor
|
||||
| BinOp::BitAnd
|
||||
| BinOp::BitOr
|
||||
|
@ -1,5 +1,6 @@
|
||||
//! Conversion of internal Rust compiler `mir` items to stable ones.
|
||||
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::mir::interpret::alloc_range;
|
||||
use rustc_middle::mir::mono::MonoItem;
|
||||
@ -183,16 +184,21 @@ impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> {
|
||||
op.stable(tables),
|
||||
ty.stable(tables),
|
||||
),
|
||||
BinaryOp(bin_op, ops) => stable_mir::mir::Rvalue::BinaryOp(
|
||||
bin_op.stable(tables),
|
||||
ops.0.stable(tables),
|
||||
ops.1.stable(tables),
|
||||
),
|
||||
CheckedBinaryOp(bin_op, ops) => stable_mir::mir::Rvalue::CheckedBinaryOp(
|
||||
bin_op.stable(tables),
|
||||
ops.0.stable(tables),
|
||||
ops.1.stable(tables),
|
||||
),
|
||||
BinaryOp(bin_op, ops) => {
|
||||
if let Some(bin_op) = bin_op.overflowing_to_wrapping() {
|
||||
stable_mir::mir::Rvalue::CheckedBinaryOp(
|
||||
bin_op.stable(tables),
|
||||
ops.0.stable(tables),
|
||||
ops.1.stable(tables),
|
||||
)
|
||||
} else {
|
||||
stable_mir::mir::Rvalue::BinaryOp(
|
||||
bin_op.stable(tables),
|
||||
ops.0.stable(tables),
|
||||
ops.1.stable(tables),
|
||||
)
|
||||
}
|
||||
}
|
||||
NullaryOp(null_op, ty) => {
|
||||
stable_mir::mir::Rvalue::NullaryOp(null_op.stable(tables), ty.stable(tables))
|
||||
}
|
||||
@ -485,10 +491,13 @@ impl<'tcx> Stable<'tcx> for mir::BinOp {
|
||||
match self {
|
||||
BinOp::Add => stable_mir::mir::BinOp::Add,
|
||||
BinOp::AddUnchecked => stable_mir::mir::BinOp::AddUnchecked,
|
||||
BinOp::AddWithOverflow => bug!("AddWithOverflow should have been translated already"),
|
||||
BinOp::Sub => stable_mir::mir::BinOp::Sub,
|
||||
BinOp::SubUnchecked => stable_mir::mir::BinOp::SubUnchecked,
|
||||
BinOp::SubWithOverflow => bug!("AddWithOverflow should have been translated already"),
|
||||
BinOp::Mul => stable_mir::mir::BinOp::Mul,
|
||||
BinOp::MulUnchecked => stable_mir::mir::BinOp::MulUnchecked,
|
||||
BinOp::MulWithOverflow => bug!("AddWithOverflow should have been translated already"),
|
||||
BinOp::Div => stable_mir::mir::BinOp::Div,
|
||||
BinOp::Rem => stable_mir::mir::BinOp::Rem,
|
||||
BinOp::BitXor => stable_mir::mir::BinOp::BitXor,
|
||||
|
@ -81,9 +81,9 @@ fn destructure_const<'tcx>(
|
||||
fn check_binop(op: mir::BinOp) -> bool {
|
||||
use mir::BinOp::*;
|
||||
match op {
|
||||
Add | AddUnchecked | Sub | SubUnchecked | Mul | MulUnchecked | Div | Rem | BitXor
|
||||
| BitAnd | BitOr | Shl | ShlUnchecked | Shr | ShrUnchecked | Eq | Lt | Le | Ne | Ge
|
||||
| Gt | Cmp => true,
|
||||
Add | AddUnchecked | AddWithOverflow | Sub | SubUnchecked | SubWithOverflow | Mul
|
||||
| MulUnchecked | MulWithOverflow | Div | Rem | BitXor | BitAnd | BitOr | Shl
|
||||
| ShlUnchecked | Shr | ShrUnchecked | Eq | Lt | Le | Ne | Ge | Gt | Cmp => true,
|
||||
Offset => false,
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ fn f(_1: i32, _2: bool) -> i32 {
|
||||
_2 = Le(_1, _1);
|
||||
_2 = Ge(_1, _1);
|
||||
_2 = Gt(_1, _1);
|
||||
_3 = CheckedAdd(_1, _1);
|
||||
_3 = AddWithOverflow(_1, _1);
|
||||
_2 = (_3.1: bool);
|
||||
_1 = (_3.0: i32);
|
||||
_0 = _1;
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
- _2 = CheckedAdd(const 1_u32, const 1_u32);
|
||||
- _2 = AddWithOverflow(const 1_u32, const 1_u32);
|
||||
- assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 1_u32, const 1_u32) -> [success: bb1, unwind unreachable];
|
||||
+ _2 = const (2_u32, false);
|
||||
+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 1_u32, const 1_u32) -> [success: bb1, unwind unreachable];
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
- _2 = CheckedAdd(const 1_u32, const 1_u32);
|
||||
- _2 = AddWithOverflow(const 1_u32, const 1_u32);
|
||||
- assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 1_u32, const 1_u32) -> [success: bb1, unwind continue];
|
||||
+ _2 = const (2_u32, false);
|
||||
+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 1_u32, const 1_u32) -> [success: bb1, unwind continue];
|
||||
|
@ -14,7 +14,7 @@
|
||||
StorageLive(_1);
|
||||
StorageLive(_2);
|
||||
- _2 = const 2_u32 as u8 (IntToInt);
|
||||
- _3 = CheckedAdd(_2, const 1_u8);
|
||||
- _3 = AddWithOverflow(_2, const 1_u8);
|
||||
- assert(!move (_3.1: bool), "attempt to compute `{} + {}`, which would overflow", move _2, const 1_u8) -> [success: bb1, unwind unreachable];
|
||||
+ _2 = const 2_u8;
|
||||
+ _3 = const (3_u8, false);
|
||||
|
@ -14,7 +14,7 @@
|
||||
StorageLive(_1);
|
||||
StorageLive(_2);
|
||||
- _2 = const 2_u32 as u8 (IntToInt);
|
||||
- _3 = CheckedAdd(_2, const 1_u8);
|
||||
- _3 = AddWithOverflow(_2, const 1_u8);
|
||||
- assert(!move (_3.1: bool), "attempt to compute `{} + {}`, which would overflow", move _2, const 1_u8) -> [success: bb1, unwind continue];
|
||||
+ _2 = const 2_u8;
|
||||
+ _3 = const (3_u8, false);
|
||||
|
@ -19,7 +19,7 @@
|
||||
StorageLive(_3);
|
||||
_3 = const 1_u8;
|
||||
StorageLive(_4);
|
||||
- _4 = CheckedAdd(_2, _3);
|
||||
- _4 = AddWithOverflow(_2, _3);
|
||||
- assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind unreachable];
|
||||
+ _4 = const (0_u8, true);
|
||||
+ assert(!const true, "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> [success: bb1, unwind unreachable];
|
||||
|
@ -19,7 +19,7 @@
|
||||
StorageLive(_3);
|
||||
_3 = const 1_u8;
|
||||
StorageLive(_4);
|
||||
- _4 = CheckedAdd(_2, _3);
|
||||
- _4 = AddWithOverflow(_2, _3);
|
||||
- assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind continue];
|
||||
+ _4 = const (0_u8, true);
|
||||
+ assert(!const true, "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> [success: bb1, unwind continue];
|
||||
|
@ -6,7 +6,7 @@
|
||||
let mut _1: (u32, bool);
|
||||
|
||||
bb0: {
|
||||
- _1 = CheckedAdd(const 2_u32, const 2_u32);
|
||||
- _1 = AddWithOverflow(const 2_u32, const 2_u32);
|
||||
- assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> [success: bb1, unwind unreachable];
|
||||
+ _1 = const (4_u32, false);
|
||||
+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> [success: bb1, unwind unreachable];
|
||||
|
@ -6,7 +6,7 @@
|
||||
let mut _1: (u32, bool);
|
||||
|
||||
bb0: {
|
||||
- _1 = CheckedAdd(const 2_u32, const 2_u32);
|
||||
- _1 = AddWithOverflow(const 2_u32, const 2_u32);
|
||||
- assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> [success: bb1, unwind continue];
|
||||
+ _1 = const (4_u32, false);
|
||||
+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> [success: bb1, unwind continue];
|
||||
|
@ -40,7 +40,7 @@
|
||||
+ _4 = const 1_i32;
|
||||
StorageLive(_5);
|
||||
- _5 = _2;
|
||||
- _6 = CheckedAdd(_4, _5);
|
||||
- _6 = AddWithOverflow(_4, _5);
|
||||
- assert(!move (_6.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, move _5) -> [success: bb1, unwind unreachable];
|
||||
+ _5 = const 2_i32;
|
||||
+ _6 = const (3_i32, false);
|
||||
@ -57,7 +57,7 @@
|
||||
StorageLive(_8);
|
||||
StorageLive(_9);
|
||||
- _9 = _7;
|
||||
- _10 = CheckedAdd(_9, const 1_i32);
|
||||
- _10 = AddWithOverflow(_9, const 1_i32);
|
||||
- assert(!move (_10.1: bool), "attempt to compute `{} + {}`, which would overflow", move _9, const 1_i32) -> [success: bb2, unwind unreachable];
|
||||
+ _9 = const i32::MAX;
|
||||
+ _10 = const (i32::MIN, true);
|
||||
|
@ -40,7 +40,7 @@
|
||||
+ _4 = const 1_i32;
|
||||
StorageLive(_5);
|
||||
- _5 = _2;
|
||||
- _6 = CheckedAdd(_4, _5);
|
||||
- _6 = AddWithOverflow(_4, _5);
|
||||
- assert(!move (_6.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, move _5) -> [success: bb1, unwind continue];
|
||||
+ _5 = const 2_i32;
|
||||
+ _6 = const (3_i32, false);
|
||||
@ -57,7 +57,7 @@
|
||||
StorageLive(_8);
|
||||
StorageLive(_9);
|
||||
- _9 = _7;
|
||||
- _10 = CheckedAdd(_9, const 1_i32);
|
||||
- _10 = AddWithOverflow(_9, const 1_i32);
|
||||
- assert(!move (_10.1: bool), "attempt to compute `{} + {}`, which would overflow", move _9, const 1_i32) -> [success: bb2, unwind continue];
|
||||
+ _9 = const i32::MAX;
|
||||
+ _10 = const (i32::MIN, true);
|
||||
|
@ -19,7 +19,7 @@
|
||||
StorageLive(_3);
|
||||
_3 = const 1_u8;
|
||||
StorageLive(_4);
|
||||
- _4 = CheckedAdd(_2, _3);
|
||||
- _4 = AddWithOverflow(_2, _3);
|
||||
- assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind unreachable];
|
||||
+ _4 = const (0_u8, true);
|
||||
+ assert(!const true, "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> [success: bb1, unwind unreachable];
|
||||
|
@ -19,7 +19,7 @@
|
||||
StorageLive(_3);
|
||||
_3 = const 1_u8;
|
||||
StorageLive(_4);
|
||||
- _4 = CheckedAdd(_2, _3);
|
||||
- _4 = AddWithOverflow(_2, _3);
|
||||
- assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind continue];
|
||||
+ _4 = const (0_u8, true);
|
||||
+ assert(!const true, "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> [success: bb1, unwind continue];
|
||||
|
@ -31,9 +31,9 @@
|
||||
StorageLive(_3);
|
||||
StorageLive(_4);
|
||||
_4 = _1;
|
||||
- _5 = CheckedAdd(_4, const 0_u64);
|
||||
- _5 = AddWithOverflow(_4, const 0_u64);
|
||||
- assert(!move (_5.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, const 0_u64) -> [success: bb1, unwind unreachable];
|
||||
+ _5 = CheckedAdd(_1, const 0_u64);
|
||||
+ _5 = AddWithOverflow(_1, const 0_u64);
|
||||
+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", _1, const 0_u64) -> [success: bb1, unwind unreachable];
|
||||
}
|
||||
|
||||
@ -52,7 +52,7 @@
|
||||
StorageLive(_7);
|
||||
StorageLive(_8);
|
||||
_8 = _1;
|
||||
- _9 = CheckedSub(_8, const 0_u64);
|
||||
- _9 = SubWithOverflow(_8, const 0_u64);
|
||||
- assert(!move (_9.1: bool), "attempt to compute `{} - {}`, which would overflow", move _8, const 0_u64) -> [success: bb3, unwind unreachable];
|
||||
+ _9 = _5;
|
||||
+ assert(!const false, "attempt to compute `{} - {}`, which would overflow", _1, const 0_u64) -> [success: bb3, unwind unreachable];
|
||||
@ -76,7 +76,7 @@
|
||||
_12 = _1;
|
||||
StorageLive(_13);
|
||||
_13 = _1;
|
||||
- _14 = CheckedSub(_12, _13);
|
||||
- _14 = SubWithOverflow(_12, _13);
|
||||
- assert(!move (_14.1: bool), "attempt to compute `{} - {}`, which would overflow", move _12, move _13) -> [success: bb5, unwind unreachable];
|
||||
+ _14 = const (0_u64, false);
|
||||
+ assert(!const false, "attempt to compute `{} - {}`, which would overflow", _1, _1) -> [success: bb5, unwind unreachable];
|
||||
@ -99,7 +99,7 @@
|
||||
StorageLive(_16);
|
||||
StorageLive(_17);
|
||||
_17 = _1;
|
||||
- _18 = CheckedMul(_17, const 0_u64);
|
||||
- _18 = MulWithOverflow(_17, const 0_u64);
|
||||
- assert(!move (_18.1: bool), "attempt to compute `{} * {}`, which would overflow", move _17, const 0_u64) -> [success: bb7, unwind unreachable];
|
||||
+ _18 = const (0_u64, false);
|
||||
+ assert(!const false, "attempt to compute `{} * {}`, which would overflow", _1, const 0_u64) -> [success: bb7, unwind unreachable];
|
||||
@ -120,7 +120,7 @@
|
||||
StorageLive(_20);
|
||||
StorageLive(_21);
|
||||
_21 = _1;
|
||||
- _22 = CheckedMul(_21, const 1_u64);
|
||||
- _22 = MulWithOverflow(_21, const 1_u64);
|
||||
- assert(!move (_22.1: bool), "attempt to compute `{} * {}`, which would overflow", move _21, const 1_u64) -> [success: bb9, unwind unreachable];
|
||||
+ _22 = _5;
|
||||
+ assert(!const false, "attempt to compute `{} * {}`, which would overflow", _1, const 1_u64) -> [success: bb9, unwind unreachable];
|
||||
|
@ -31,9 +31,9 @@
|
||||
StorageLive(_3);
|
||||
StorageLive(_4);
|
||||
_4 = _1;
|
||||
- _5 = CheckedAdd(_4, const 0_u64);
|
||||
- _5 = AddWithOverflow(_4, const 0_u64);
|
||||
- assert(!move (_5.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, const 0_u64) -> [success: bb1, unwind continue];
|
||||
+ _5 = CheckedAdd(_1, const 0_u64);
|
||||
+ _5 = AddWithOverflow(_1, const 0_u64);
|
||||
+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", _1, const 0_u64) -> [success: bb1, unwind continue];
|
||||
}
|
||||
|
||||
@ -52,7 +52,7 @@
|
||||
StorageLive(_7);
|
||||
StorageLive(_8);
|
||||
_8 = _1;
|
||||
- _9 = CheckedSub(_8, const 0_u64);
|
||||
- _9 = SubWithOverflow(_8, const 0_u64);
|
||||
- assert(!move (_9.1: bool), "attempt to compute `{} - {}`, which would overflow", move _8, const 0_u64) -> [success: bb3, unwind continue];
|
||||
+ _9 = _5;
|
||||
+ assert(!const false, "attempt to compute `{} - {}`, which would overflow", _1, const 0_u64) -> [success: bb3, unwind continue];
|
||||
@ -76,7 +76,7 @@
|
||||
_12 = _1;
|
||||
StorageLive(_13);
|
||||
_13 = _1;
|
||||
- _14 = CheckedSub(_12, _13);
|
||||
- _14 = SubWithOverflow(_12, _13);
|
||||
- assert(!move (_14.1: bool), "attempt to compute `{} - {}`, which would overflow", move _12, move _13) -> [success: bb5, unwind continue];
|
||||
+ _14 = const (0_u64, false);
|
||||
+ assert(!const false, "attempt to compute `{} - {}`, which would overflow", _1, _1) -> [success: bb5, unwind continue];
|
||||
@ -99,7 +99,7 @@
|
||||
StorageLive(_16);
|
||||
StorageLive(_17);
|
||||
_17 = _1;
|
||||
- _18 = CheckedMul(_17, const 0_u64);
|
||||
- _18 = MulWithOverflow(_17, const 0_u64);
|
||||
- assert(!move (_18.1: bool), "attempt to compute `{} * {}`, which would overflow", move _17, const 0_u64) -> [success: bb7, unwind continue];
|
||||
+ _18 = const (0_u64, false);
|
||||
+ assert(!const false, "attempt to compute `{} * {}`, which would overflow", _1, const 0_u64) -> [success: bb7, unwind continue];
|
||||
@ -120,7 +120,7 @@
|
||||
StorageLive(_20);
|
||||
StorageLive(_21);
|
||||
_21 = _1;
|
||||
- _22 = CheckedMul(_21, const 1_u64);
|
||||
- _22 = MulWithOverflow(_21, const 1_u64);
|
||||
- assert(!move (_22.1: bool), "attempt to compute `{} * {}`, which would overflow", move _21, const 1_u64) -> [success: bb9, unwind continue];
|
||||
+ _22 = _5;
|
||||
+ assert(!const false, "attempt to compute `{} * {}`, which would overflow", _1, const 1_u64) -> [success: bb9, unwind continue];
|
||||
|
@ -5,7 +5,7 @@
|
||||
let mut _1: (usize, bool);
|
||||
|
||||
bb0: {
|
||||
_1 = CheckedAdd(const 1_usize, const 1_usize);
|
||||
_1 = AddWithOverflow(const 1_usize, const 1_usize);
|
||||
assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 1_usize, const 1_usize) -> [success: bb1, unwind: bb2];
|
||||
}
|
||||
|
||||
|
@ -184,9 +184,9 @@ pub fn assume() {
|
||||
// EMIT_MIR lower_intrinsics.with_overflow.LowerIntrinsics.diff
|
||||
pub fn with_overflow(a: i32, b: i32) {
|
||||
// CHECK-LABEL: fn with_overflow(
|
||||
// CHECK: CheckedAdd(
|
||||
// CHECK: CheckedSub(
|
||||
// CHECK: CheckedMul(
|
||||
// CHECK: AddWithOverflow(
|
||||
// CHECK: SubWithOverflow(
|
||||
// CHECK: MulWithOverflow(
|
||||
|
||||
let _x = core::intrinsics::add_with_overflow(a, b);
|
||||
let _y = core::intrinsics::sub_with_overflow(a, b);
|
||||
|
@ -31,7 +31,7 @@
|
||||
StorageLive(_5);
|
||||
_5 = _2;
|
||||
- _3 = add_with_overflow::<i32>(move _4, move _5) -> [return: bb1, unwind unreachable];
|
||||
+ _3 = CheckedAdd(move _4, move _5);
|
||||
+ _3 = AddWithOverflow(move _4, move _5);
|
||||
+ goto -> bb1;
|
||||
}
|
||||
|
||||
@ -44,7 +44,7 @@
|
||||
StorageLive(_8);
|
||||
_8 = _2;
|
||||
- _6 = sub_with_overflow::<i32>(move _7, move _8) -> [return: bb2, unwind unreachable];
|
||||
+ _6 = CheckedSub(move _7, move _8);
|
||||
+ _6 = SubWithOverflow(move _7, move _8);
|
||||
+ goto -> bb2;
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@
|
||||
StorageLive(_11);
|
||||
_11 = _2;
|
||||
- _9 = mul_with_overflow::<i32>(move _10, move _11) -> [return: bb3, unwind unreachable];
|
||||
+ _9 = CheckedMul(move _10, move _11);
|
||||
+ _9 = MulWithOverflow(move _10, move _11);
|
||||
+ goto -> bb3;
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@
|
||||
StorageLive(_5);
|
||||
_5 = _2;
|
||||
- _3 = add_with_overflow::<i32>(move _4, move _5) -> [return: bb1, unwind unreachable];
|
||||
+ _3 = CheckedAdd(move _4, move _5);
|
||||
+ _3 = AddWithOverflow(move _4, move _5);
|
||||
+ goto -> bb1;
|
||||
}
|
||||
|
||||
@ -44,7 +44,7 @@
|
||||
StorageLive(_8);
|
||||
_8 = _2;
|
||||
- _6 = sub_with_overflow::<i32>(move _7, move _8) -> [return: bb2, unwind unreachable];
|
||||
+ _6 = CheckedSub(move _7, move _8);
|
||||
+ _6 = SubWithOverflow(move _7, move _8);
|
||||
+ goto -> bb2;
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@
|
||||
StorageLive(_11);
|
||||
_11 = _2;
|
||||
- _9 = mul_with_overflow::<i32>(move _10, move _11) -> [return: bb3, unwind unreachable];
|
||||
+ _9 = CheckedMul(move _10, move _11);
|
||||
+ _9 = MulWithOverflow(move _10, move _11);
|
||||
+ goto -> bb3;
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
- _2 = CheckedAdd(const 2_i32, const 2_i32);
|
||||
- _2 = AddWithOverflow(const 2_i32, const 2_i32);
|
||||
- assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind unreachable];
|
||||
+ _2 = const (4_i32, false);
|
||||
+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind unreachable];
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
- _2 = CheckedAdd(const 2_i32, const 2_i32);
|
||||
- _2 = AddWithOverflow(const 2_i32, const 2_i32);
|
||||
- assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind continue];
|
||||
+ _2 = const (4_i32, false);
|
||||
+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind continue];
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
- _2 = CheckedAdd(const 2_i32, const 2_i32);
|
||||
- _2 = AddWithOverflow(const 2_i32, const 2_i32);
|
||||
- assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind unreachable];
|
||||
+ _2 = const (4_i32, false);
|
||||
+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind unreachable];
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
- _2 = CheckedAdd(const 2_i32, const 2_i32);
|
||||
- _2 = AddWithOverflow(const 2_i32, const 2_i32);
|
||||
- assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind continue];
|
||||
+ _2 = const (4_i32, false);
|
||||
+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind continue];
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
_2 = CheckedAdd(const 2_i32, const 2_i32);
|
||||
_2 = AddWithOverflow(const 2_i32, const 2_i32);
|
||||
assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind unreachable];
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
_2 = CheckedAdd(const 2_i32, const 2_i32);
|
||||
_2 = AddWithOverflow(const 2_i32, const 2_i32);
|
||||
assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind continue];
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
_2 = CheckedAdd(const 2_i32, const 2_i32);
|
||||
_2 = AddWithOverflow(const 2_i32, const 2_i32);
|
||||
assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind unreachable];
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
_2 = CheckedAdd(const 2_i32, const 2_i32);
|
||||
_2 = AddWithOverflow(const 2_i32, const 2_i32);
|
||||
assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind continue];
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ fn foo() -> i32 {
|
||||
let mut _1: (i32, bool);
|
||||
|
||||
bb0: {
|
||||
_1 = CheckedAdd(const 5_i32, const 6_i32);
|
||||
_1 = AddWithOverflow(const 5_i32, const 6_i32);
|
||||
assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 5_i32, const 6_i32) -> [success: bb1, unwind continue];
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ fn foo() -> i32 {
|
||||
let mut _1: (i32, bool);
|
||||
|
||||
bb0: {
|
||||
_1 = CheckedAdd(const 5_i32, const 6_i32);
|
||||
_1 = AddWithOverflow(const 5_i32, const 6_i32);
|
||||
assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 5_i32, const 6_i32) -> [success: bb1, unwind continue];
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user