Skip to content

Commit 4cdcf87

Browse files
authored
Rollup merge of rust-lang#40521 - TimNN:panic-free-shift, r=nagisa
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 63fb201 + cc23d17 commit 4cdcf87

File tree

5 files changed

+123
-28
lines changed

5 files changed

+123
-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

+95-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,16 @@ 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+
#[cfg(stage0)]
853863
pub fn wrapping_shl(self, rhs: u32) -> Self {
854864
self.overflowing_shl(rhs).0
855865
}
@@ -875,6 +885,16 @@ macro_rules! int_impl {
875885
/// ```
876886
#[stable(feature = "num_wrapping", since = "1.2.0")]
877887
#[inline(always)]
888+
#[cfg(not(stage0))]
889+
pub fn wrapping_shr(self, rhs: u32) -> Self {
890+
unsafe {
891+
intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT)
892+
}
893+
}
894+
895+
/// Stage 0
896+
#[stable(feature = "num_wrapping", since = "1.2.0")]
897+
#[cfg(stage0)]
878898
pub fn wrapping_shr(self, rhs: u32) -> Self {
879899
self.overflowing_shr(rhs).0
880900
}
@@ -1089,6 +1109,15 @@ macro_rules! int_impl {
10891109
/// ```
10901110
#[inline]
10911111
#[stable(feature = "wrapping", since = "1.7.0")]
1112+
#[cfg(not(stage0))]
1113+
pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
1114+
(self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
1115+
}
1116+
1117+
/// Stage 0
1118+
#[inline]
1119+
#[stable(feature = "wrapping", since = "1.7.0")]
1120+
#[cfg(stage0)]
10921121
pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
10931122
(self << (rhs & ($BITS - 1)), (rhs > ($BITS - 1)))
10941123
}
@@ -1111,6 +1140,15 @@ macro_rules! int_impl {
11111140
/// ```
11121141
#[inline]
11131142
#[stable(feature = "wrapping", since = "1.7.0")]
1143+
#[cfg(not(stage0))]
1144+
pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
1145+
(self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
1146+
}
1147+
1148+
/// Stage 0
1149+
#[inline]
1150+
#[stable(feature = "wrapping", since = "1.7.0")]
1151+
#[cfg(stage0)]
11141152
pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
11151153
(self >> (rhs & ($BITS - 1)), (rhs > ($BITS - 1)))
11161154
}
@@ -1268,39 +1306,39 @@ macro_rules! int_impl {
12681306

12691307
#[lang = "i8"]
12701308
impl i8 {
1271-
int_impl! { i8, u8, 8,
1309+
int_impl! { i8, i8, u8, 8,
12721310
intrinsics::add_with_overflow,
12731311
intrinsics::sub_with_overflow,
12741312
intrinsics::mul_with_overflow }
12751313
}
12761314

12771315
#[lang = "i16"]
12781316
impl i16 {
1279-
int_impl! { i16, u16, 16,
1317+
int_impl! { i16, i16, u16, 16,
12801318
intrinsics::add_with_overflow,
12811319
intrinsics::sub_with_overflow,
12821320
intrinsics::mul_with_overflow }
12831321
}
12841322

12851323
#[lang = "i32"]
12861324
impl i32 {
1287-
int_impl! { i32, u32, 32,
1325+
int_impl! { i32, i32, u32, 32,
12881326
intrinsics::add_with_overflow,
12891327
intrinsics::sub_with_overflow,
12901328
intrinsics::mul_with_overflow }
12911329
}
12921330

12931331
#[lang = "i64"]
12941332
impl i64 {
1295-
int_impl! { i64, u64, 64,
1333+
int_impl! { i64, i64, u64, 64,
12961334
intrinsics::add_with_overflow,
12971335
intrinsics::sub_with_overflow,
12981336
intrinsics::mul_with_overflow }
12991337
}
13001338

13011339
#[lang = "i128"]
13021340
impl i128 {
1303-
int_impl! { i128, u128, 128,
1341+
int_impl! { i128, i128, u128, 128,
13041342
intrinsics::add_with_overflow,
13051343
intrinsics::sub_with_overflow,
13061344
intrinsics::mul_with_overflow }
@@ -1309,7 +1347,7 @@ impl i128 {
13091347
#[cfg(target_pointer_width = "16")]
13101348
#[lang = "isize"]
13111349
impl isize {
1312-
int_impl! { i16, u16, 16,
1350+
int_impl! { isize, i16, u16, 16,
13131351
intrinsics::add_with_overflow,
13141352
intrinsics::sub_with_overflow,
13151353
intrinsics::mul_with_overflow }
@@ -1318,7 +1356,7 @@ impl isize {
13181356
#[cfg(target_pointer_width = "32")]
13191357
#[lang = "isize"]
13201358
impl isize {
1321-
int_impl! { i32, u32, 32,
1359+
int_impl! { isize, i32, u32, 32,
13221360
intrinsics::add_with_overflow,
13231361
intrinsics::sub_with_overflow,
13241362
intrinsics::mul_with_overflow }
@@ -1327,15 +1365,15 @@ impl isize {
13271365
#[cfg(target_pointer_width = "64")]
13281366
#[lang = "isize"]
13291367
impl isize {
1330-
int_impl! { i64, u64, 64,
1368+
int_impl! { isize, i64, u64, 64,
13311369
intrinsics::add_with_overflow,
13321370
intrinsics::sub_with_overflow,
13331371
intrinsics::mul_with_overflow }
13341372
}
13351373

13361374
// `Int` + `UnsignedInt` implemented for unsigned integers
13371375
macro_rules! uint_impl {
1338-
($ActualT:ty, $BITS:expr,
1376+
($SelfT:ty, $ActualT:ty, $BITS:expr,
13391377
$ctpop:path,
13401378
$ctlz:path,
13411379
$cttz:path,
@@ -1978,6 +2016,16 @@ macro_rules! uint_impl {
19782016
/// ```
19792017
#[stable(feature = "num_wrapping", since = "1.2.0")]
19802018
#[inline(always)]
2019+
#[cfg(not(stage0))]
2020+
pub fn wrapping_shl(self, rhs: u32) -> Self {
2021+
unsafe {
2022+
intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT)
2023+
}
2024+
}
2025+
2026+
/// Stage 0
2027+
#[stable(feature = "num_wrapping", since = "1.2.0")]
2028+
#[cfg(stage0)]
19812029
pub fn wrapping_shl(self, rhs: u32) -> Self {
19822030
self.overflowing_shl(rhs).0
19832031
}
@@ -2003,6 +2051,16 @@ macro_rules! uint_impl {
20032051
/// ```
20042052
#[stable(feature = "num_wrapping", since = "1.2.0")]
20052053
#[inline(always)]
2054+
#[cfg(not(stage0))]
2055+
pub fn wrapping_shr(self, rhs: u32) -> Self {
2056+
unsafe {
2057+
intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT)
2058+
}
2059+
}
2060+
2061+
/// Stage 0
2062+
#[stable(feature = "num_wrapping", since = "1.2.0")]
2063+
#[cfg(stage0)]
20062064
pub fn wrapping_shr(self, rhs: u32) -> Self {
20072065
self.overflowing_shr(rhs).0
20082066
}
@@ -2170,6 +2228,15 @@ macro_rules! uint_impl {
21702228
/// ```
21712229
#[inline]
21722230
#[stable(feature = "wrapping", since = "1.7.0")]
2231+
#[cfg(not(stage0))]
2232+
pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
2233+
(self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
2234+
}
2235+
2236+
/// Stage 0
2237+
#[inline]
2238+
#[stable(feature = "wrapping", since = "1.7.0")]
2239+
#[cfg(stage0)]
21732240
pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
21742241
(self << (rhs & ($BITS - 1)), (rhs > ($BITS - 1)))
21752242
}
@@ -2192,6 +2259,16 @@ macro_rules! uint_impl {
21922259
/// ```
21932260
#[inline]
21942261
#[stable(feature = "wrapping", since = "1.7.0")]
2262+
#[cfg(not(stage0))]
2263+
pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
2264+
(self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
2265+
2266+
}
2267+
2268+
/// Stage 0
2269+
#[inline]
2270+
#[stable(feature = "wrapping", since = "1.7.0")]
2271+
#[cfg(stage0)]
21952272
pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
21962273
(self >> (rhs & ($BITS - 1)), (rhs > ($BITS - 1)))
21972274
}
@@ -2292,7 +2369,7 @@ macro_rules! uint_impl {
22922369

22932370
#[lang = "u8"]
22942371
impl u8 {
2295-
uint_impl! { u8, 8,
2372+
uint_impl! { u8, u8, 8,
22962373
intrinsics::ctpop,
22972374
intrinsics::ctlz,
22982375
intrinsics::cttz,
@@ -2304,7 +2381,7 @@ impl u8 {
23042381

23052382
#[lang = "u16"]
23062383
impl u16 {
2307-
uint_impl! { u16, 16,
2384+
uint_impl! { u16, u16, 16,
23082385
intrinsics::ctpop,
23092386
intrinsics::ctlz,
23102387
intrinsics::cttz,
@@ -2316,7 +2393,7 @@ impl u16 {
23162393

23172394
#[lang = "u32"]
23182395
impl u32 {
2319-
uint_impl! { u32, 32,
2396+
uint_impl! { u32, u32, 32,
23202397
intrinsics::ctpop,
23212398
intrinsics::ctlz,
23222399
intrinsics::cttz,
@@ -2328,7 +2405,7 @@ impl u32 {
23282405

23292406
#[lang = "u64"]
23302407
impl u64 {
2331-
uint_impl! { u64, 64,
2408+
uint_impl! { u64, u64, 64,
23322409
intrinsics::ctpop,
23332410
intrinsics::ctlz,
23342411
intrinsics::cttz,
@@ -2340,7 +2417,7 @@ impl u64 {
23402417

23412418
#[lang = "u128"]
23422419
impl u128 {
2343-
uint_impl! { u128, 128,
2420+
uint_impl! { u128, u128, 128,
23442421
intrinsics::ctpop,
23452422
intrinsics::ctlz,
23462423
intrinsics::cttz,
@@ -2353,7 +2430,7 @@ impl u128 {
23532430
#[cfg(target_pointer_width = "16")]
23542431
#[lang = "usize"]
23552432
impl usize {
2356-
uint_impl! { u16, 16,
2433+
uint_impl! { usize, u16, 16,
23572434
intrinsics::ctpop,
23582435
intrinsics::ctlz,
23592436
intrinsics::cttz,
@@ -2365,7 +2442,7 @@ impl usize {
23652442
#[cfg(target_pointer_width = "32")]
23662443
#[lang = "usize"]
23672444
impl usize {
2368-
uint_impl! { u32, 32,
2445+
uint_impl! { usize, u32, 32,
23692446
intrinsics::ctpop,
23702447
intrinsics::ctlz,
23712448
intrinsics::cttz,
@@ -2378,7 +2455,7 @@ impl usize {
23782455
#[cfg(target_pointer_width = "64")]
23792456
#[lang = "usize"]
23802457
impl usize {
2381-
uint_impl! { u64, 64,
2458+
uint_impl! { usize, u64, 64,
23822459
intrinsics::ctpop,
23832460
intrinsics::ctlz,
23842461
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)