Skip to content

Commit 1d67ca0

Browse files
committed
add helper method for ptr ops on Scalar; reduce unnecessary large operand of overflowing_signed_offset
1 parent afcb634 commit 1d67ca0

File tree

2 files changed

+35
-49
lines changed

2 files changed

+35
-49
lines changed

src/librustc/mir/interpret/pointer.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -73,17 +73,16 @@ pub trait PointerArithmetic: layout::HasDataLayout {
7373
self.truncate_to_ptr(res)
7474
}
7575

76-
// Overflow checking only works properly on the range from -u64 to +u64.
7776
#[inline]
78-
fn overflowing_signed_offset(&self, val: u64, i: i128) -> (u64, bool) {
79-
// FIXME: is it possible to over/underflow here?
77+
fn overflowing_signed_offset(&self, val: u64, i: i64) -> (u64, bool) {
8078
if i < 0 {
8179
// Trickery to ensure that `i64::MIN` works fine: compute `n = -i`.
8280
// This formula only works for true negative values; it overflows for zero!
8381
let n = u64::MAX - (i as u64) + 1;
8482
let res = val.overflowing_sub(n);
8583
self.truncate_to_ptr(res)
8684
} else {
85+
// `i >= 0`, so the cast is safe.
8786
self.overflowing_offset(val, i as u64)
8887
}
8988
}
@@ -96,7 +95,7 @@ pub trait PointerArithmetic: layout::HasDataLayout {
9695

9796
#[inline]
9897
fn signed_offset<'tcx>(&self, val: u64, i: i64) -> InterpResult<'tcx, u64> {
99-
let (res, over) = self.overflowing_signed_offset(val, i128::from(i));
98+
let (res, over) = self.overflowing_signed_offset(val, i);
10099
if over { throw_ub!(PointerArithOverflow) } else { Ok(res) }
101100
}
102101
}
@@ -189,14 +188,14 @@ impl<'tcx, Tag> Pointer<Tag> {
189188
}
190189

191190
#[inline]
192-
pub fn overflowing_signed_offset(self, i: i128, cx: &impl HasDataLayout) -> (Self, bool) {
191+
pub fn overflowing_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> (Self, bool) {
193192
let (res, over) = cx.data_layout().overflowing_signed_offset(self.offset.bytes(), i);
194193
(Pointer::new_with_tag(self.alloc_id, Size::from_bytes(res), self.tag), over)
195194
}
196195

197196
#[inline(always)]
198197
pub fn wrapping_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> Self {
199-
self.overflowing_signed_offset(i128::from(i), cx).0
198+
self.overflowing_signed_offset(i, cx).0
200199
}
201200

202201
#[inline(always)]

src/librustc/mir/interpret/value.rs

+30-43
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
use std::convert::TryFrom;
2+
use std::fmt;
23

34
use rustc_apfloat::{
45
ieee::{Double, Single},
56
Float,
67
};
78
use rustc_macros::HashStable;
8-
use std::fmt;
9+
use rustc_target::abi::TargetDataLayout;
910

1011
use crate::ty::{
1112
layout::{HasDataLayout, Size},
@@ -200,68 +201,54 @@ impl<'tcx, Tag> Scalar<Tag> {
200201
Scalar::Raw { data: 0, size: 0 }
201202
}
202203

203-
#[inline]
204-
pub fn ptr_offset(self, i: Size, cx: &impl HasDataLayout) -> InterpResult<'tcx, Self> {
205-
let dl = cx.data_layout();
204+
#[inline(always)]
205+
fn ptr_op(
206+
self,
207+
dl: &TargetDataLayout,
208+
f_int: impl FnOnce(u64) -> InterpResult<'tcx, u64>,
209+
f_ptr: impl FnOnce(Pointer<Tag>) -> InterpResult<'tcx, Pointer<Tag>>,
210+
) -> InterpResult<'tcx, Self> {
206211
match self {
207212
Scalar::Raw { data, size } => {
208213
assert_eq!(u64::from(size), dl.pointer_size.bytes());
209-
Ok(Scalar::Raw {
210-
data: u128::from(dl.offset(u64::try_from(data).unwrap(), i.bytes())?),
211-
size,
212-
})
214+
Ok(Scalar::Raw { data: u128::from(f_int(u64::try_from(data).unwrap())?), size })
213215
}
214-
Scalar::Ptr(ptr) => ptr.offset(i, dl).map(Scalar::Ptr),
216+
Scalar::Ptr(ptr) => Ok(Scalar::Ptr(f_ptr(ptr)?)),
215217
}
216218
}
217219

220+
#[inline]
221+
pub fn ptr_offset(self, i: Size, cx: &impl HasDataLayout) -> InterpResult<'tcx, Self> {
222+
let dl = cx.data_layout();
223+
self.ptr_op(dl, |int| dl.offset(int, i.bytes()), |ptr| ptr.offset(i, dl))
224+
}
225+
218226
#[inline]
219227
pub fn ptr_wrapping_offset(self, i: Size, cx: &impl HasDataLayout) -> Self {
220228
let dl = cx.data_layout();
221-
match self {
222-
Scalar::Raw { data, size } => {
223-
assert_eq!(u64::from(size), dl.pointer_size.bytes());
224-
Scalar::Raw {
225-
data: u128::from(
226-
dl.overflowing_offset(u64::try_from(data).unwrap(), i.bytes()).0,
227-
),
228-
size,
229-
}
230-
}
231-
Scalar::Ptr(ptr) => Scalar::Ptr(ptr.wrapping_offset(i, dl)),
232-
}
229+
self.ptr_op(
230+
dl,
231+
|int| Ok(dl.overflowing_offset(int, i.bytes()).0),
232+
|ptr| Ok(ptr.wrapping_offset(i, dl)),
233+
)
234+
.unwrap()
233235
}
234236

235237
#[inline]
236238
pub fn ptr_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> InterpResult<'tcx, Self> {
237239
let dl = cx.data_layout();
238-
match self {
239-
Scalar::Raw { data, size } => {
240-
assert_eq!(u64::from(size), dl.pointer_size.bytes());
241-
Ok(Scalar::Raw {
242-
data: u128::from(dl.signed_offset(u64::try_from(data).unwrap(), i)?),
243-
size,
244-
})
245-
}
246-
Scalar::Ptr(ptr) => ptr.signed_offset(i, dl).map(Scalar::Ptr),
247-
}
240+
self.ptr_op(dl, |int| dl.signed_offset(int, i), |ptr| ptr.signed_offset(i, dl))
248241
}
249242

250243
#[inline]
251244
pub fn ptr_wrapping_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> Self {
252245
let dl = cx.data_layout();
253-
match self {
254-
Scalar::Raw { data, size } => {
255-
assert_eq!(u64::from(size), dl.pointer_size.bytes());
256-
Scalar::Raw {
257-
data: u128::from(
258-
dl.overflowing_signed_offset(u64::try_from(data).unwrap(), i128::from(i)).0,
259-
),
260-
size,
261-
}
262-
}
263-
Scalar::Ptr(ptr) => Scalar::Ptr(ptr.wrapping_signed_offset(i, dl)),
264-
}
246+
self.ptr_op(
247+
dl,
248+
|int| Ok(dl.overflowing_signed_offset(int, i).0),
249+
|ptr| Ok(ptr.wrapping_signed_offset(i, dl)),
250+
)
251+
.unwrap()
265252
}
266253

267254
#[inline]

0 commit comments

Comments
 (0)