Skip to content

Commit 1799896

Browse files
committed
Refactor const saturating intrinsics emulation and add unstable feature attribute #58030
1 parent d7efc76 commit 1799896

File tree

3 files changed

+29
-39
lines changed

3 files changed

+29
-39
lines changed

src/libcore/num/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -909,6 +909,7 @@ $EndFeature, "
909909
```"),
910910

911911
#[stable(feature = "rust1", since = "1.0.0")]
912+
#[rustc_const_unstable(feature = "const_saturating_int_methods")]
912913
#[inline]
913914
#[cfg(not(stage0))]
914915
pub const fn saturating_add(self, rhs: Self) -> Self {
@@ -957,6 +958,7 @@ assert_eq!(", stringify!($SelfT), "::min_value().saturating_sub(100), ", stringi
957958
$EndFeature, "
958959
```"),
959960
#[stable(feature = "rust1", since = "1.0.0")]
961+
#[rustc_const_unstable(feature = "const_saturating_int_methods")]
960962
#[inline]
961963
#[cfg(not(stage0))]
962964
pub const fn saturating_sub(self, rhs: Self) -> Self {

src/librustc_mir/interpret/intrinsics.rs

Lines changed: 25 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -122,55 +122,41 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
122122
self.binop_with_overflow(bin_op, lhs, rhs, dest)?;
123123
}
124124
}
125-
"saturating_add" => {
125+
"saturating_add" | "saturating_sub" => {
126126
let l = self.read_immediate(args[0])?;
127127
let r = self.read_immediate(args[1])?;
128-
let (val, overflowed) = self.binary_op_imm(BinOp::Add, l, r)?;
129-
if overflowed {
130-
let first_term: u128 = l.to_scalar()?.to_bits(l.layout.size)?;
131-
let num_bits = l.layout.size.bits();
132-
let val = if l.layout.abi.is_signed() {
133-
// For signed addition the saturated value depends on the
134-
// sign of either term
135-
if first_term & (1 << (num_bits-1)) == 0 { // signed term is positive
136-
Scalar::from_uint((1u128 << (num_bits - 1)) - 1,
137-
Size::from_bits(num_bits))
138-
} else { // signed term is negative
139-
Scalar::from_uint(1u128 << (num_bits - 1), Size::from_bits(num_bits))
140-
}
141-
} else {
142-
Scalar::from_uint(u128::max_value() >> (128 - num_bits),
143-
Size::from_bits(num_bits))
144-
};
145-
self.write_scalar(val, dest)?;
128+
let is_add = intrinsic_name == "saturating_add";
129+
let (val, overflowed) = self.binary_op_imm(if is_add {
130+
BinOp::Add
146131
} else {
147-
self.write_scalar(val, dest)?;
148-
}
149-
}
150-
"saturating_sub" => {
151-
let l = self.read_immediate(args[0])?;
152-
let r = self.read_immediate(args[1])?;
153-
let (val, overflowed) = self.binary_op_imm(BinOp::Sub, l, r)?;
154-
if overflowed {
132+
BinOp::Sub
133+
}, l, r)?;
134+
let val = if overflowed {
135+
// For signed ints the saturated value depends on the
136+
// sign of the first term
155137
let first_term: u128 = l.to_scalar()?.to_bits(l.layout.size)?;
156138
let num_bits = l.layout.size.bits();
157-
let val = if l.layout.abi.is_signed() {
139+
if l.layout.abi.is_signed() {
158140
if first_term & (1 << (num_bits-1)) == 0 { // first term is positive
159-
// so overflow is positive
160-
Scalar::from_uint((1u128 << (num_bits - 1)) - 1,
141+
Scalar::from_uint((1u128 << (num_bits - 1)) - 1, // max positive
161142
Size::from_bits(num_bits))
162-
} else {
163-
// if first term negative, overflow must be negative
143+
} else { // first term is negative
144+
// max negative
164145
Scalar::from_uint(1u128 << (num_bits - 1), Size::from_bits(num_bits))
165146
}
166-
} else {
167-
// unsigned underflow saturates to 0
168-
Scalar::from_uint(0u128, Size::from_bits(num_bits))
169-
};
170-
self.write_scalar(val, dest)?;
147+
} else { // unsigned
148+
if is_add {
149+
// max unsigned
150+
Scalar::from_uint(u128::max_value() >> (128 - num_bits),
151+
Size::from_bits(num_bits))
152+
} else { // underflow to 0
153+
Scalar::from_uint(0u128, Size::from_bits(num_bits))
154+
}
155+
}
171156
} else {
172-
self.write_scalar(val, dest)?;
173-
}
157+
val
158+
};
159+
self.write_scalar(val, dest)?;
174160
}
175161
"unchecked_shl" | "unchecked_shr" => {
176162
let l = self.read_immediate(args[0])?;

src/test/run-pass/const-int-saturating-arith.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#![feature(const_saturating_int_methods)]
2+
13
const INT_U32_NO: u32 = (42 as u32).saturating_add(2);
24
const INT_U32: u32 = u32::max_value().saturating_add(1);
35
const INT_U128: u128 = u128::max_value().saturating_add(1);

0 commit comments

Comments
 (0)