Skip to content

Commit 956659e

Browse files
committed
move saturating_add/sub into (pub) helper method
1 parent 38a0b81 commit 956659e

File tree

1 file changed

+48
-39
lines changed

1 file changed

+48
-39
lines changed

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+48-39
Original file line numberDiff line numberDiff line change
@@ -219,48 +219,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
219219
sym::saturating_add | sym::saturating_sub => {
220220
let l = self.read_immediate(&args[0])?;
221221
let r = self.read_immediate(&args[1])?;
222-
let is_add = intrinsic_name == sym::saturating_add;
223-
let (val, overflowed, _ty) = self.overflowing_binary_op(
224-
if is_add { BinOp::Add } else { BinOp::Sub },
222+
let val = self.saturating_arith(
223+
if intrinsic_name == sym::saturating_add { BinOp::Add } else { BinOp::Sub },
225224
&l,
226225
&r,
227226
)?;
228-
let val = if overflowed {
229-
let size = l.layout.size;
230-
let num_bits = size.bits();
231-
if l.layout.abi.is_signed() {
232-
// For signed ints the saturated value depends on the sign of the first
233-
// term since the sign of the second term can be inferred from this and
234-
// the fact that the operation has overflowed (if either is 0 no
235-
// overflow can occur)
236-
let first_term: u128 = l.to_scalar()?.to_bits(l.layout.size)?;
237-
let first_term_positive = first_term & (1 << (num_bits - 1)) == 0;
238-
if first_term_positive {
239-
// Negative overflow not possible since the positive first term
240-
// can only increase an (in range) negative term for addition
241-
// or corresponding negated positive term for subtraction
242-
Scalar::from_uint(
243-
(1u128 << (num_bits - 1)) - 1, // max positive
244-
Size::from_bits(num_bits),
245-
)
246-
} else {
247-
// Positive overflow not possible for similar reason
248-
// max negative
249-
Scalar::from_uint(1u128 << (num_bits - 1), Size::from_bits(num_bits))
250-
}
251-
} else {
252-
// unsigned
253-
if is_add {
254-
// max unsigned
255-
Scalar::from_uint(size.unsigned_int_max(), Size::from_bits(num_bits))
256-
} else {
257-
// underflow to 0
258-
Scalar::from_uint(0u128, Size::from_bits(num_bits))
259-
}
260-
}
261-
} else {
262-
val
263-
};
264227
self.write_scalar(val, dest)?;
265228
}
266229
sym::discriminant_value => {
@@ -508,6 +471,52 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
508471
self.binop_ignore_overflow(BinOp::Div, &a, &b, dest)
509472
}
510473

474+
pub fn saturating_arith(
475+
&self,
476+
mir_op: BinOp,
477+
l: &ImmTy<'tcx, M::PointerTag>,
478+
r: &ImmTy<'tcx, M::PointerTag>,
479+
) -> InterpResult<'tcx, Scalar<M::PointerTag>> {
480+
assert!(matches!(mir_op, BinOp::Add | BinOp::Sub));
481+
let (val, overflowed, _ty) = self.overflowing_binary_op(mir_op, l, r)?;
482+
Ok(if overflowed {
483+
let size = l.layout.size;
484+
let num_bits = size.bits();
485+
if l.layout.abi.is_signed() {
486+
// For signed ints the saturated value depends on the sign of the first
487+
// term since the sign of the second term can be inferred from this and
488+
// the fact that the operation has overflowed (if either is 0 no
489+
// overflow can occur)
490+
let first_term: u128 = l.to_scalar()?.to_bits(l.layout.size)?;
491+
let first_term_positive = first_term & (1 << (num_bits - 1)) == 0;
492+
if first_term_positive {
493+
// Negative overflow not possible since the positive first term
494+
// can only increase an (in range) negative term for addition
495+
// or corresponding negated positive term for subtraction
496+
Scalar::from_uint(
497+
(1u128 << (num_bits - 1)) - 1, // max positive
498+
Size::from_bits(num_bits),
499+
)
500+
} else {
501+
// Positive overflow not possible for similar reason
502+
// max negative
503+
Scalar::from_uint(1u128 << (num_bits - 1), Size::from_bits(num_bits))
504+
}
505+
} else {
506+
// unsigned
507+
if matches!(mir_op, BinOp::Add) {
508+
// max unsigned
509+
Scalar::from_uint(size.unsigned_int_max(), Size::from_bits(num_bits))
510+
} else {
511+
// underflow to 0
512+
Scalar::from_uint(0u128, Size::from_bits(num_bits))
513+
}
514+
}
515+
} else {
516+
val
517+
})
518+
}
519+
511520
/// Offsets a pointer by some multiple of its type, returning an error if the pointer leaves its
512521
/// allocation. For integer pointers, we consider each of them their own tiny allocation of size
513522
/// 0, so offset-by-0 (and only 0) is okay -- except that null cannot be offset by _any_ value.

0 commit comments

Comments
 (0)