Skip to content

Commit e4be0ad

Browse files
committed
Auto merge of #161456 - RalfJung:scalar-size-check, r=<try>
reduce perf impact of scalar size checks try-job: aarch64-gnu
2 parents e457a7b + d802d17 commit e4be0ad

2 files changed

Lines changed: 30 additions & 22 deletions

File tree

compiler/rustc_middle/src/mir/interpret/value.rs

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::fmt;
2+
use std::num::NonZero;
23

34
use either::{Either, Left, Right};
45
use rustc_abi::{HasDataLayout, Size};
@@ -29,7 +30,7 @@ pub enum Scalar<Prov = CtfeProvenance> {
2930
/// We also store the size of the pointer, such that a `Scalar` always knows how big it is.
3031
/// The size is always the pointer size of the current target, but this is not information
3132
/// that we always have readily available.
32-
Ptr(Pointer<Prov>, u8),
33+
Ptr(Pointer<Prov>, NonZero<u8>),
3334
}
3435

3536
#[cfg(target_pointer_width = "64")]
@@ -102,7 +103,8 @@ impl<Prov> From<ScalarInt> for Scalar<Prov> {
102103
impl<Prov> Scalar<Prov> {
103104
#[inline(always)]
104105
pub fn from_pointer(ptr: Pointer<Prov>, cx: &impl HasDataLayout) -> Self {
105-
Scalar::Ptr(ptr, u8::try_from(cx.pointer_size().bytes()).unwrap())
106+
let ptr_size = u8::try_from(cx.pointer_size().bytes()).ok().and_then(NonZero::new).unwrap();
107+
Scalar::Ptr(ptr, ptr_size)
106108
}
107109

108110
/// Create a Scalar from a pointer with an `Option<_>` provenance (where `None` represents a
@@ -236,17 +238,20 @@ impl<Prov> Scalar<Prov> {
236238
/// This throws UB (instead of ICEing) on a size mismatch since size mismatches can arise in
237239
/// Miri when someone declares a function that we shim (such as `malloc`) with a wrong type.
238240
#[inline]
239-
pub fn to_bits_or_ptr_internal(self, target_size: Size) -> Either<u128, Pointer<Prov>> {
240-
assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST");
241+
pub fn to_bits_or_ptr_internal(self, expected_size: Size) -> Either<u128, Pointer<Prov>> {
241242
match self {
242-
Scalar::Int(int) => Left(int.to_bits(target_size)),
243+
Scalar::Int(int) => Left(int.to_bits(expected_size)),
243244
Scalar::Ptr(ptr, sz) => {
244-
assert_eq!(
245-
target_size.bytes(),
246-
u64::from(sz),
247-
"Scalar is a pointer but expected size {}",
248-
target_size.bytes()
249-
);
245+
let self_size = u64::from(sz.get());
246+
if expected_size.bytes() != self_size {
247+
#[cold]
248+
fn invalid(expected_size: u64, self_size: u64) -> ! {
249+
panic!("Scalar pointer has size {self_size} but expected {expected_size}")
250+
}
251+
252+
invalid(expected_size.bytes(), self_size)
253+
}
254+
250255
Right(ptr)
251256
}
252257
}
@@ -256,7 +261,7 @@ impl<Prov> Scalar<Prov> {
256261
pub fn size(self) -> Size {
257262
match self {
258263
Scalar::Int(int) => int.size(),
259-
Scalar::Ptr(_ptr, sz) => Size::from_bytes(sz),
264+
Scalar::Ptr(_ptr, sz) => Size::from_bytes(sz.get()),
260265
}
261266
}
262267
}
@@ -287,7 +292,8 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
287292
Scalar::Int(int) => Ok(int),
288293
Scalar::Ptr(ptr, sz) => {
289294
if Prov::OFFSET_IS_ADDR {
290-
Ok(ScalarInt::try_from_uint(ptr.offset.bytes(), Size::from_bytes(sz)).unwrap())
295+
Ok(ScalarInt::try_from_uint(ptr.offset.bytes(), Size::from_bytes(sz.get()))
296+
.unwrap())
291297
} else {
292298
// We know `offset` is relative, since `OFFSET_IS_ADDR == false`.
293299
let (prov, offset) = ptr.into_raw_parts();

compiler/rustc_middle/src/ty/consts/int.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -262,15 +262,17 @@ impl ScalarInt {
262262

263263
/// Convert this ScalarInt to the underlying bits.
264264
#[inline]
265-
pub fn to_bits(self, target_size: Size) -> u128 {
266-
assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST");
267-
assert_eq!(
268-
target_size.bytes(),
269-
u64::from(self.size.get()),
270-
"ScalarInt has size {} but expected {}",
271-
self.size,
272-
target_size.bytes(),
273-
);
265+
pub fn to_bits(self, expected_size: Size) -> u128 {
266+
let self_size = u64::from(self.size.get());
267+
if expected_size.bytes() != self_size {
268+
#[cold]
269+
fn invalid(expected_size: u64, self_size: u64) -> ! {
270+
panic!("ScalarInt has size {self_size} but expected {expected_size}")
271+
}
272+
273+
invalid(expected_size.bytes(), self_size);
274+
}
275+
274276
self.check_data();
275277
self.data
276278
}

0 commit comments

Comments
 (0)