diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index bcc4d11e64b..dea5aa82545 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -234,7 +234,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &r, )?; let val = if overflowed { - let num_bits = l.layout.size.bits(); + let size = l.layout.size; + let num_bits = size.bits(); if l.layout.abi.is_signed() { // For signed ints the saturated value depends on the sign of the first // term since the sign of the second term can be inferred from this and @@ -259,10 +260,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // unsigned if is_add { // max unsigned - Scalar::from_uint( - u128::MAX >> (128 - num_bits), - Size::from_bits(num_bits), - ) + Scalar::from_uint(size.unsigned_max(), Size::from_bits(num_bits)) } else { // underflow to 0 Scalar::from_uint(0u128, Size::from_bits(num_bits)) diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index bad56220a0b..5bac561f24e 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -627,7 +627,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' // At least one value is excluded. let valid_range = scalar_layout.valid_range; let WrappingRange { start, end } = valid_range; - let max_value = u128::MAX >> (128 - op.layout.size.bits()); + let max_value = op.layout.size.unsigned_max(); assert!(end <= max_value); // Determine the allowed range let value = self.read_scalar(op)?; diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 67d33a0321f..6abad26e46e 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -512,9 +512,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let param_env = self.param_env; let dl = self.data_layout(); let scalar_unit = |value: Primitive| { - let bits = value.size(dl).bits(); - assert!(bits <= 128); - Scalar { value, valid_range: WrappingRange { start: 0, end: (!0 >> (128 - bits)) } } + let size = value.size(dl); + assert!(size.bits() <= 128); + Scalar { value, valid_range: WrappingRange { start: 0, end: size.unsigned_max() } } }; let scalar = |value: Primitive| tcx.intern_layout(Layout::scalar(self, scalar_unit(value))); @@ -1266,7 +1266,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } } - let tag_mask = !0u128 >> (128 - ity.size().bits()); + let tag_mask = ity.size().unsigned_max(); let tag = Scalar { value: Int(ity, signed), valid_range: WrappingRange { diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 1b8e94260b9..55f89f11c61 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -45,18 +45,6 @@ impl<'tcx> fmt::Display for Discr<'tcx> { } } -fn signed_min(size: Size) -> i128 { - size.sign_extend(1_u128 << (size.bits() - 1)) as i128 -} - -fn signed_max(size: Size) -> i128 { - i128::MAX >> (128 - size.bits()) -} - -fn unsigned_max(size: Size) -> u128 { - u128::MAX >> (128 - size.bits()) -} - fn int_size_and_signed<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> (Size, bool) { let (int, signed) = match *ty.kind() { Int(ity) => (Integer::from_int_ty(&tcx, ity), true), @@ -74,8 +62,8 @@ impl<'tcx> Discr<'tcx> { pub fn checked_add(self, tcx: TyCtxt<'tcx>, n: u128) -> (Self, bool) { let (size, signed) = int_size_and_signed(tcx, self.ty); let (val, oflo) = if signed { - let min = signed_min(size); - let max = signed_max(size); + let min = size.signed_min(); + let max = size.signed_max(); let val = size.sign_extend(self.val) as i128; assert!(n < (i128::MAX as u128)); let n = n as i128; @@ -86,7 +74,7 @@ impl<'tcx> Discr<'tcx> { let val = size.truncate(val); (val, oflo) } else { - let max = unsigned_max(size); + let max = size.unsigned_max(); let val = self.val; let oflo = val > max - n; let val = if oflo { n - (max - val) - 1 } else { val + n }; @@ -621,7 +609,7 @@ impl<'tcx> ty::TyS<'tcx> { let val = match self.kind() { ty::Int(_) | ty::Uint(_) => { let (size, signed) = int_size_and_signed(tcx, self); - let val = if signed { signed_max(size) as u128 } else { unsigned_max(size) }; + let val = if signed { size.signed_max() as u128 } else { size.unsigned_max() }; Some(val) } ty::Char => Some(std::char::MAX as u128), @@ -640,7 +628,7 @@ impl<'tcx> ty::TyS<'tcx> { let val = match self.kind() { ty::Int(_) | ty::Uint(_) => { let (size, signed) = int_size_and_signed(tcx, self); - let val = if signed { size.truncate(signed_min(size) as u128) } else { 0 }; + let val = if signed { size.truncate(size.signed_min() as u128) } else { 0 }; Some(val) } ty::Char => Some(0), diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 68de1af613d..3706543d07d 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -494,9 +494,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Helper to get a `-1` value of the appropriate type fn neg_1_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> { let param_ty = ty::ParamEnv::empty().and(ty); - let bits = self.tcx.layout_of(param_ty).unwrap().size.bits(); - let n = (!0u128) >> (128 - bits); - let literal = ty::Const::from_bits(self.tcx, n, param_ty); + let size = self.tcx.layout_of(param_ty).unwrap().size; + let literal = ty::Const::from_bits(self.tcx, size.unsigned_max(), param_ty); self.literal_operand(span, literal) } diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index 8764b851aff..eb0c51efb66 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -392,6 +392,21 @@ impl Size { // Truncate (shift left to drop out leftover values, shift right to fill with zeroes). (value << shift) >> shift } + + #[inline] + pub fn signed_min(&self) -> i128 { + self.sign_extend(1_u128 << (self.bits() - 1)) as i128 + } + + #[inline] + pub fn signed_max(&self) -> i128 { + i128::MAX >> (128 - self.bits()) + } + + #[inline] + pub fn unsigned_max(&self) -> u128 { + u128::MAX >> (128 - self.bits()) + } } // Panicking addition, subtraction and multiplication for convenience. @@ -775,7 +790,7 @@ impl WrappingRange { /// Returns `true` if `size` completely fills the range. #[inline] pub fn is_full_for(&self, size: Size) -> bool { - let max_value = u128::MAX >> (128 - size.bits()); + let max_value = size.unsigned_max(); debug_assert!(self.start <= max_value && self.end <= max_value); (self.start == 0 && self.end == max_value) || (self.end + 1 == self.start) } @@ -1067,9 +1082,9 @@ impl Niche { pub fn available(&self, cx: &C) -> u128 { let Scalar { value, valid_range: v } = self.scalar; - let bits = value.size(cx).bits(); - assert!(bits <= 128); - let max_value = !0u128 >> (128 - bits); + let size = value.size(cx); + assert!(size.bits() <= 128); + let max_value = size.unsigned_max(); // Find out how many values are outside the valid range. let niche = v.end.wrapping_add(1)..v.start; @@ -1080,9 +1095,9 @@ impl Niche { assert!(count > 0); let Scalar { value, valid_range: v } = self.scalar; - let bits = value.size(cx).bits(); - assert!(bits <= 128); - let max_value = !0u128 >> (128 - bits); + let size = value.size(cx); + assert!(size.bits() <= 128); + let max_value = size.unsigned_max(); if count > max_value { return None;