Skip to content

Commit 7474930

Browse files
author
Ariel Ben-Yehuda
authored
Rollup merge of rust-lang#40521 - TimNN:panic-free-shift, r=alexcrichton
Implemente overflowing_sh* with new unchecked_sh* intrinsics Also update some 128 bit builtins to not rely on the constant evaluator to avoid checked operations. Fixes rust-lang#40508. cc @nagisa, @alexcrichton Note: I still have a build running to see if the 128 bit changes worked (unoptimized builds take *forever* to compile), however at least the overflowing builtins no longer reference `core::panicking::panic`.
2 parents bed891d + e16d286 commit 7474930

File tree

5 files changed

+127
-28
lines changed

5 files changed

+127
-28
lines changed

src/libcompiler_builtins/lib.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ pub mod reimpls {
3434
macro_rules! ashl {
3535
($a:expr, $b:expr, $ty:ty) => {{
3636
let (a, b) = ($a, $b);
37-
let bits = (::core::mem::size_of::<$ty>() * 8) as $ty;
38-
let half_bits = bits >> 1;
37+
let bits = ::core::mem::size_of::<$ty>().wrapping_mul(8) as $ty;
38+
let half_bits = bits.wrapping_shr(1);
3939
if b & half_bits != 0 {
4040
<$ty>::from_parts(0, a.low().wrapping_shl(
4141
b.wrapping_sub(half_bits) as u32))
@@ -58,8 +58,8 @@ pub mod reimpls {
5858
macro_rules! ashr {
5959
($a: expr, $b: expr, $ty:ty) => {{
6060
let (a, b) = ($a, $b);
61-
let bits = (::core::mem::size_of::<$ty>() * 8) as $ty;
62-
let half_bits = bits >> 1;
61+
let bits = ::core::mem::size_of::<$ty>().wrapping_mul(8) as $ty;
62+
let half_bits = bits.wrapping_shr(1);
6363
if b & half_bits != 0 {
6464
<$ty>::from_parts(a.high().wrapping_shr(b.wrapping_sub(half_bits) as u32)
6565
as <$ty as LargeInt>::LowHalf,
@@ -83,8 +83,8 @@ pub mod reimpls {
8383
macro_rules! lshr {
8484
($a: expr, $b: expr, $ty:ty) => {{
8585
let (a, b) = ($a, $b);
86-
let bits = (::core::mem::size_of::<$ty>() * 8) as $ty;
87-
let half_bits = bits >> 1;
86+
let bits = ::core::mem::size_of::<$ty>().wrapping_mul(8) as $ty;
87+
let half_bits = bits.wrapping_shr(1);
8888
if b & half_bits != 0 {
8989
<$ty>::from_parts(a.high().wrapping_shr(b.wrapping_sub(half_bits) as u32), 0)
9090
} else if b == 0 {
@@ -370,7 +370,7 @@ pub mod reimpls {
370370
macro_rules! mul {
371371
($a:expr, $b:expr, $ty: ty, $tyh: ty) => {{
372372
let (a, b) = ($a, $b);
373-
let half_bits = ((::core::mem::size_of::<$tyh>() * 8) / 2) as u32;
373+
let half_bits = ::core::mem::size_of::<$tyh>().wrapping_mul(4) as u32;
374374
let lower_mask = (!0u64).wrapping_shr(half_bits);
375375
let mut low = (a.low() & lower_mask).wrapping_mul(b.low() & lower_mask);
376376
let mut t = low.wrapping_shr(half_bits);
@@ -478,7 +478,7 @@ pub mod reimpls {
478478
let mantissa_fraction = repr & <$fromty as FloatStuff>::MANTISSA_MASK;
479479
let mantissa = mantissa_fraction | <$fromty as FloatStuff>::MANTISSA_LEAD_BIT;
480480
if sign == -1.0 || exponent < 0 { return 0 as u128; }
481-
if exponent > ::core::mem::size_of::<$outty>() as i32 * 8 {
481+
if exponent > ::core::mem::size_of::<$outty>().wrapping_mul(8) as i32 {
482482
return !(0 as u128);
483483
}
484484
(if exponent < (<$fromty as FloatStuff>::MANTISSA_BITS) as i32 {
@@ -503,7 +503,7 @@ pub mod reimpls {
503503
let mantissa = mantissa_fraction | <$fromty as FloatStuff>::MANTISSA_LEAD_BIT;
504504

505505
if exponent < 0 { return 0 as i128; }
506-
if exponent > ::core::mem::size_of::<$outty>() as i32 * 8 {
506+
if exponent > ::core::mem::size_of::<$outty>().wrapping_mul(8) as i32 {
507507
let ret = if sign > 0.0 { <$outty>::max_value() } else { <$outty>::min_value() };
508508
return ret
509509
}

src/libcore/intrinsics.rs

+9
Original file line numberDiff line numberDiff line change
@@ -1238,6 +1238,15 @@ extern "rust-intrinsic" {
12381238
/// undefined behavior where y = 0 or x = `T::min_value()` and y = -1
12391239
pub fn unchecked_rem<T>(x: T, y: T) -> T;
12401240

1241+
/// Performs an unchecked left shift, resulting in undefined behavior when
1242+
/// y < 0 or y >= N, where N is the width of T in bits.
1243+
#[cfg(not(stage0))]
1244+
pub fn unchecked_shl<T>(x: T, y: T) -> T;
1245+
/// Performs an unchecked right shift, resulting in undefined behavior when
1246+
/// y < 0 or y >= N, where N is the width of T in bits.
1247+
#[cfg(not(stage0))]
1248+
pub fn unchecked_shr<T>(x: T, y: T) -> T;
1249+
12411250
/// Returns (a + b) mod 2^N, where N is the width of T in bits.
12421251
/// The stabilized versions of this intrinsic are available on the integer
12431252
/// primitives via the `wrapping_add` method. For example,

src/libcore/num/mod.rs

+99-18
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ macro_rules! checked_op {
177177

178178
// `Int` + `SignedInt` implemented for signed integers
179179
macro_rules! int_impl {
180-
($ActualT:ident, $UnsignedT:ty, $BITS:expr,
180+
($SelfT:ty, $ActualT:ident, $UnsignedT:ty, $BITS:expr,
181181
$add_with_overflow:path,
182182
$sub_with_overflow:path,
183183
$mul_with_overflow:path) => {
@@ -850,6 +850,17 @@ macro_rules! int_impl {
850850
/// ```
851851
#[stable(feature = "num_wrapping", since = "1.2.0")]
852852
#[inline(always)]
853+
#[cfg(not(stage0))]
854+
pub fn wrapping_shl(self, rhs: u32) -> Self {
855+
unsafe {
856+
intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT)
857+
}
858+
}
859+
860+
/// Stage 0
861+
#[stable(feature = "num_wrapping", since = "1.2.0")]
862+
#[inline(always)]
863+
#[cfg(stage0)]
853864
pub fn wrapping_shl(self, rhs: u32) -> Self {
854865
self.overflowing_shl(rhs).0
855866
}
@@ -875,6 +886,17 @@ macro_rules! int_impl {
875886
/// ```
876887
#[stable(feature = "num_wrapping", since = "1.2.0")]
877888
#[inline(always)]
889+
#[cfg(not(stage0))]
890+
pub fn wrapping_shr(self, rhs: u32) -> Self {
891+
unsafe {
892+
intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT)
893+
}
894+
}
895+
896+
/// Stage 0
897+
#[stable(feature = "num_wrapping", since = "1.2.0")]
898+
#[inline(always)]
899+
#[cfg(stage0)]
878900
pub fn wrapping_shr(self, rhs: u32) -> Self {
879901
self.overflowing_shr(rhs).0
880902
}
@@ -1089,6 +1111,15 @@ macro_rules! int_impl {
10891111
/// ```
10901112
#[inline]
10911113
#[stable(feature = "wrapping", since = "1.7.0")]
1114+
#[cfg(not(stage0))]
1115+
pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
1116+
(self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
1117+
}
1118+
1119+
/// Stage 0
1120+
#[inline]
1121+
#[stable(feature = "wrapping", since = "1.7.0")]
1122+
#[cfg(stage0)]
10921123
pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
10931124
(self << (rhs & ($BITS - 1)), (rhs > ($BITS - 1)))
10941125
}
@@ -1111,6 +1142,15 @@ macro_rules! int_impl {
11111142
/// ```
11121143
#[inline]
11131144
#[stable(feature = "wrapping", since = "1.7.0")]
1145+
#[cfg(not(stage0))]
1146+
pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
1147+
(self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
1148+
}
1149+
1150+
/// Stage 0
1151+
#[inline]
1152+
#[stable(feature = "wrapping", since = "1.7.0")]
1153+
#[cfg(stage0)]
11141154
pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
11151155
(self >> (rhs & ($BITS - 1)), (rhs > ($BITS - 1)))
11161156
}
@@ -1268,39 +1308,39 @@ macro_rules! int_impl {
12681308

12691309
#[lang = "i8"]
12701310
impl i8 {
1271-
int_impl! { i8, u8, 8,
1311+
int_impl! { i8, i8, u8, 8,
12721312
intrinsics::add_with_overflow,
12731313
intrinsics::sub_with_overflow,
12741314
intrinsics::mul_with_overflow }
12751315
}
12761316

12771317
#[lang = "i16"]
12781318
impl i16 {
1279-
int_impl! { i16, u16, 16,
1319+
int_impl! { i16, i16, u16, 16,
12801320
intrinsics::add_with_overflow,
12811321
intrinsics::sub_with_overflow,
12821322
intrinsics::mul_with_overflow }
12831323
}
12841324

12851325
#[lang = "i32"]
12861326
impl i32 {
1287-
int_impl! { i32, u32, 32,
1327+
int_impl! { i32, i32, u32, 32,
12881328
intrinsics::add_with_overflow,
12891329
intrinsics::sub_with_overflow,
12901330
intrinsics::mul_with_overflow }
12911331
}
12921332

12931333
#[lang = "i64"]
12941334
impl i64 {
1295-
int_impl! { i64, u64, 64,
1335+
int_impl! { i64, i64, u64, 64,
12961336
intrinsics::add_with_overflow,
12971337
intrinsics::sub_with_overflow,
12981338
intrinsics::mul_with_overflow }
12991339
}
13001340

13011341
#[lang = "i128"]
13021342
impl i128 {
1303-
int_impl! { i128, u128, 128,
1343+
int_impl! { i128, i128, u128, 128,
13041344
intrinsics::add_with_overflow,
13051345
intrinsics::sub_with_overflow,
13061346
intrinsics::mul_with_overflow }
@@ -1309,7 +1349,7 @@ impl i128 {
13091349
#[cfg(target_pointer_width = "16")]
13101350
#[lang = "isize"]
13111351
impl isize {
1312-
int_impl! { i16, u16, 16,
1352+
int_impl! { isize, i16, u16, 16,
13131353
intrinsics::add_with_overflow,
13141354
intrinsics::sub_with_overflow,
13151355
intrinsics::mul_with_overflow }
@@ -1318,7 +1358,7 @@ impl isize {
13181358
#[cfg(target_pointer_width = "32")]
13191359
#[lang = "isize"]
13201360
impl isize {
1321-
int_impl! { i32, u32, 32,
1361+
int_impl! { isize, i32, u32, 32,
13221362
intrinsics::add_with_overflow,
13231363
intrinsics::sub_with_overflow,
13241364
intrinsics::mul_with_overflow }
@@ -1327,15 +1367,15 @@ impl isize {
13271367
#[cfg(target_pointer_width = "64")]
13281368
#[lang = "isize"]
13291369
impl isize {
1330-
int_impl! { i64, u64, 64,
1370+
int_impl! { isize, i64, u64, 64,
13311371
intrinsics::add_with_overflow,
13321372
intrinsics::sub_with_overflow,
13331373
intrinsics::mul_with_overflow }
13341374
}
13351375

13361376
// `Int` + `UnsignedInt` implemented for unsigned integers
13371377
macro_rules! uint_impl {
1338-
($ActualT:ty, $BITS:expr,
1378+
($SelfT:ty, $ActualT:ty, $BITS:expr,
13391379
$ctpop:path,
13401380
$ctlz:path,
13411381
$cttz:path,
@@ -1978,6 +2018,17 @@ macro_rules! uint_impl {
19782018
/// ```
19792019
#[stable(feature = "num_wrapping", since = "1.2.0")]
19802020
#[inline(always)]
2021+
#[cfg(not(stage0))]
2022+
pub fn wrapping_shl(self, rhs: u32) -> Self {
2023+
unsafe {
2024+
intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT)
2025+
}
2026+
}
2027+
2028+
/// Stage 0
2029+
#[stable(feature = "num_wrapping", since = "1.2.0")]
2030+
#[inline(always)]
2031+
#[cfg(stage0)]
19812032
pub fn wrapping_shl(self, rhs: u32) -> Self {
19822033
self.overflowing_shl(rhs).0
19832034
}
@@ -2003,6 +2054,17 @@ macro_rules! uint_impl {
20032054
/// ```
20042055
#[stable(feature = "num_wrapping", since = "1.2.0")]
20052056
#[inline(always)]
2057+
#[cfg(not(stage0))]
2058+
pub fn wrapping_shr(self, rhs: u32) -> Self {
2059+
unsafe {
2060+
intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT)
2061+
}
2062+
}
2063+
2064+
/// Stage 0
2065+
#[stable(feature = "num_wrapping", since = "1.2.0")]
2066+
#[inline(always)]
2067+
#[cfg(stage0)]
20062068
pub fn wrapping_shr(self, rhs: u32) -> Self {
20072069
self.overflowing_shr(rhs).0
20082070
}
@@ -2170,6 +2232,15 @@ macro_rules! uint_impl {
21702232
/// ```
21712233
#[inline]
21722234
#[stable(feature = "wrapping", since = "1.7.0")]
2235+
#[cfg(not(stage0))]
2236+
pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
2237+
(self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
2238+
}
2239+
2240+
/// Stage 0
2241+
#[inline]
2242+
#[stable(feature = "wrapping", since = "1.7.0")]
2243+
#[cfg(stage0)]
21732244
pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
21742245
(self << (rhs & ($BITS - 1)), (rhs > ($BITS - 1)))
21752246
}
@@ -2192,6 +2263,16 @@ macro_rules! uint_impl {
21922263
/// ```
21932264
#[inline]
21942265
#[stable(feature = "wrapping", since = "1.7.0")]
2266+
#[cfg(not(stage0))]
2267+
pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
2268+
(self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
2269+
2270+
}
2271+
2272+
/// Stage 0
2273+
#[inline]
2274+
#[stable(feature = "wrapping", since = "1.7.0")]
2275+
#[cfg(stage0)]
21952276
pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
21962277
(self >> (rhs & ($BITS - 1)), (rhs > ($BITS - 1)))
21972278
}
@@ -2292,7 +2373,7 @@ macro_rules! uint_impl {
22922373

22932374
#[lang = "u8"]
22942375
impl u8 {
2295-
uint_impl! { u8, 8,
2376+
uint_impl! { u8, u8, 8,
22962377
intrinsics::ctpop,
22972378
intrinsics::ctlz,
22982379
intrinsics::cttz,
@@ -2304,7 +2385,7 @@ impl u8 {
23042385

23052386
#[lang = "u16"]
23062387
impl u16 {
2307-
uint_impl! { u16, 16,
2388+
uint_impl! { u16, u16, 16,
23082389
intrinsics::ctpop,
23092390
intrinsics::ctlz,
23102391
intrinsics::cttz,
@@ -2316,7 +2397,7 @@ impl u16 {
23162397

23172398
#[lang = "u32"]
23182399
impl u32 {
2319-
uint_impl! { u32, 32,
2400+
uint_impl! { u32, u32, 32,
23202401
intrinsics::ctpop,
23212402
intrinsics::ctlz,
23222403
intrinsics::cttz,
@@ -2328,7 +2409,7 @@ impl u32 {
23282409

23292410
#[lang = "u64"]
23302411
impl u64 {
2331-
uint_impl! { u64, 64,
2412+
uint_impl! { u64, u64, 64,
23322413
intrinsics::ctpop,
23332414
intrinsics::ctlz,
23342415
intrinsics::cttz,
@@ -2340,7 +2421,7 @@ impl u64 {
23402421

23412422
#[lang = "u128"]
23422423
impl u128 {
2343-
uint_impl! { u128, 128,
2424+
uint_impl! { u128, u128, 128,
23442425
intrinsics::ctpop,
23452426
intrinsics::ctlz,
23462427
intrinsics::cttz,
@@ -2353,7 +2434,7 @@ impl u128 {
23532434
#[cfg(target_pointer_width = "16")]
23542435
#[lang = "usize"]
23552436
impl usize {
2356-
uint_impl! { u16, 16,
2437+
uint_impl! { usize, u16, 16,
23572438
intrinsics::ctpop,
23582439
intrinsics::ctlz,
23592440
intrinsics::cttz,
@@ -2365,7 +2446,7 @@ impl usize {
23652446
#[cfg(target_pointer_width = "32")]
23662447
#[lang = "usize"]
23672448
impl usize {
2368-
uint_impl! { u32, 32,
2449+
uint_impl! { usize, u32, 32,
23692450
intrinsics::ctpop,
23702451
intrinsics::ctlz,
23712452
intrinsics::cttz,
@@ -2378,7 +2459,7 @@ impl usize {
23782459
#[cfg(target_pointer_width = "64")]
23792460
#[lang = "usize"]
23802461
impl usize {
2381-
uint_impl! { u64, 64,
2462+
uint_impl! { usize, u64, 64,
23822463
intrinsics::ctpop,
23832464
intrinsics::ctlz,
23842465
intrinsics::cttz,

src/librustc_trans/intrinsic.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
261261
"ctlz" | "cttz" | "ctpop" | "bswap" |
262262
"add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" |
263263
"overflowing_add" | "overflowing_sub" | "overflowing_mul" |
264-
"unchecked_div" | "unchecked_rem" => {
264+
"unchecked_div" | "unchecked_rem" | "unchecked_shl" | "unchecked_shr" => {
265265
let sty = &arg_tys[0].sty;
266266
match int_type_width_signed(sty, ccx) {
267267
Some((width, signed)) =>
@@ -311,6 +311,13 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
311311
} else {
312312
bcx.urem(llargs[0], llargs[1])
313313
},
314+
"unchecked_shl" => bcx.shl(llargs[0], llargs[1]),
315+
"unchecked_shr" =>
316+
if signed {
317+
bcx.ashr(llargs[0], llargs[1])
318+
} else {
319+
bcx.lshr(llargs[0], llargs[1])
320+
},
314321
_ => bug!(),
315322
},
316323
None => {

0 commit comments

Comments
 (0)