add helper method for ptr ops on Scalar; reduce unnecessary large operand of overflowing_signed_offset
This commit is contained in:
parent
afcb6342fa
commit
1d67ca00a1
2 changed files with 35 additions and 49 deletions
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue