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!
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)
}
}
#[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) }
}
}
}
#[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)]
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},
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]