diff options
| author | Ralf Jung <post@ralfj.de> | 2020-03-24 10:16:39 +0100 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2020-03-25 15:53:53 +0100 |
| commit | 1d67ca00a1b2f667068e24d4f98676f3ec62de42 (patch) | |
| tree | 8833b49479007b323f5875c022b18dff28016a12 /src | |
| parent | afcb6342fa8cf206a80e8555454bff74d9144973 (diff) | |
| download | rust-1d67ca00a1b2f667068e24d4f98676f3ec62de42.tar.gz rust-1d67ca00a1b2f667068e24d4f98676f3ec62de42.zip | |
add helper method for ptr ops on Scalar; reduce unnecessary large operand of overflowing_signed_offset
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/mir/interpret/pointer.rs | 11 | ||||
| -rw-r--r-- | src/librustc/mir/interpret/value.rs | 73 |
2 files changed, 35 insertions, 49 deletions
diff --git a/src/librustc/mir/interpret/pointer.rs b/src/librustc/mir/interpret/pointer.rs index ff479aee4e0..3f841cfb330 100644 --- a/src/librustc/mir/interpret/pointer.rs +++ b/src/librustc/mir/interpret/pointer.rs @@ -73,10 +73,8 @@ pub trait PointerArithmetic: layout::HasDataLayout { self.truncate_to_ptr(res) } - // Overflow checking only works properly on the range from -u64 to +u64. #[inline] - fn overflowing_signed_offset(&self, val: u64, i: i128) -> (u64, bool) { - // FIXME: is it possible to over/underflow here? + fn overflowing_signed_offset(&self, val: u64, i: i64) -> (u64, bool) { if i < 0 { // Trickery to ensure that `i64::MIN` works fine: compute `n = -i`. // This formula only works for true negative values; it overflows for zero! @@ -84,6 +82,7 @@ pub trait PointerArithmetic: layout::HasDataLayout { let res = val.overflowing_sub(n); self.truncate_to_ptr(res) } else { + // `i >= 0`, so the cast is safe. self.overflowing_offset(val, i as u64) } } @@ -96,7 +95,7 @@ pub trait PointerArithmetic: layout::HasDataLayout { #[inline] fn signed_offset<'tcx>(&self, val: u64, i: i64) -> InterpResult<'tcx, u64> { - let (res, over) = self.overflowing_signed_offset(val, i128::from(i)); + let (res, over) = self.overflowing_signed_offset(val, i); if over { throw_ub!(PointerArithOverflow) } else { Ok(res) } } } @@ -189,14 +188,14 @@ impl<'tcx, Tag> Pointer<Tag> { } #[inline] - pub fn overflowing_signed_offset(self, i: i128, cx: &impl HasDataLayout) -> (Self, bool) { + pub fn overflowing_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> (Self, bool) { let (res, over) = cx.data_layout().overflowing_signed_offset(self.offset.bytes(), i); (Pointer::new_with_tag(self.alloc_id, Size::from_bytes(res), self.tag), over) } #[inline(always)] pub fn wrapping_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> Self { - self.overflowing_signed_offset(i128::from(i), cx).0 + self.overflowing_signed_offset(i, cx).0 } #[inline(always)] diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index f00952e3725..706cf1cd09a 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -1,11 +1,12 @@ use std::convert::TryFrom; +use std::fmt; use rustc_apfloat::{ ieee::{Double, Single}, Float, }; use rustc_macros::HashStable; -use std::fmt; +use rustc_target::abi::TargetDataLayout; use crate::ty::{ layout::{HasDataLayout, Size}, @@ -200,68 +201,54 @@ impl<'tcx, Tag> Scalar<Tag> { Scalar::Raw { data: 0, size: 0 } } - #[inline] - pub fn ptr_offset(self, i: Size, cx: &impl HasDataLayout) -> InterpResult<'tcx, Self> { - let dl = cx.data_layout(); + #[inline(always)] + fn ptr_op( + self, + dl: &TargetDataLayout, + f_int: impl FnOnce(u64) -> InterpResult<'tcx, u64>, + f_ptr: impl FnOnce(Pointer<Tag>) -> InterpResult<'tcx, Pointer<Tag>>, + ) -> InterpResult<'tcx, Self> { match self { Scalar::Raw { data, size } => { assert_eq!(u64::from(size), dl.pointer_size.bytes()); - Ok(Scalar::Raw { - data: u128::from(dl.offset(u64::try_from(data).unwrap(), i.bytes())?), - size, - }) + Ok(Scalar::Raw { data: u128::from(f_int(u64::try_from(data).unwrap())?), size }) } - Scalar::Ptr(ptr) => ptr.offset(i, dl).map(Scalar::Ptr), + Scalar::Ptr(ptr) => Ok(Scalar::Ptr(f_ptr(ptr)?)), } } #[inline] + pub fn ptr_offset(self, i: Size, cx: &impl HasDataLayout) -> InterpResult<'tcx, Self> { + let dl = cx.data_layout(); + self.ptr_op(dl, |int| dl.offset(int, i.bytes()), |ptr| ptr.offset(i, dl)) + } + + #[inline] pub fn ptr_wrapping_offset(self, i: Size, cx: &impl HasDataLayout) -> Self { let dl = cx.data_layout(); - match self { - Scalar::Raw { data, size } => { - assert_eq!(u64::from(size), dl.pointer_size.bytes()); - Scalar::Raw { - data: u128::from( - dl.overflowing_offset(u64::try_from(data).unwrap(), i.bytes()).0, - ), - size, - } - } - Scalar::Ptr(ptr) => Scalar::Ptr(ptr.wrapping_offset(i, dl)), - } + self.ptr_op( + dl, + |int| Ok(dl.overflowing_offset(int, i.bytes()).0), + |ptr| Ok(ptr.wrapping_offset(i, dl)), + ) + .unwrap() } #[inline] pub fn ptr_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> InterpResult<'tcx, Self> { let dl = cx.data_layout(); - match self { - Scalar::Raw { data, size } => { - assert_eq!(u64::from(size), dl.pointer_size.bytes()); - Ok(Scalar::Raw { - data: u128::from(dl.signed_offset(u64::try_from(data).unwrap(), i)?), - size, - }) - } - Scalar::Ptr(ptr) => ptr.signed_offset(i, dl).map(Scalar::Ptr), - } + self.ptr_op(dl, |int| dl.signed_offset(int, i), |ptr| ptr.signed_offset(i, dl)) } #[inline] pub fn ptr_wrapping_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> Self { let dl = cx.data_layout(); - match self { - Scalar::Raw { data, size } => { - assert_eq!(u64::from(size), dl.pointer_size.bytes()); - Scalar::Raw { - data: u128::from( - dl.overflowing_signed_offset(u64::try_from(data).unwrap(), i128::from(i)).0, - ), - size, - } - } - Scalar::Ptr(ptr) => Scalar::Ptr(ptr.wrapping_signed_offset(i, dl)), - } + self.ptr_op( + dl, + |int| Ok(dl.overflowing_signed_offset(int, i).0), + |ptr| Ok(ptr.wrapping_signed_offset(i, dl)), + ) + .unwrap() } #[inline] |
