]> git.lizzy.rs Git - rust.git/commitdiff
add helper method for ptr ops on Scalar; reduce unnecessary large operand of overflow...
authorRalf Jung <post@ralfj.de>
Tue, 24 Mar 2020 09:16:39 +0000 (10:16 +0100)
committerRalf Jung <post@ralfj.de>
Wed, 25 Mar 2020 14:53:53 +0000 (15:53 +0100)
src/librustc/mir/interpret/pointer.rs
src/librustc/mir/interpret/value.rs

index ff479aee4e0a93d5bdb49f0af378aebae431676c..3f841cfb3300326addce2ef4de00ed112433a5db 100644 (file)
@@ -73,10 +73,8 @@ fn overflowing_offset(&self, val: u64, i: u64) -> (u64, bool) {
         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 @@ fn overflowing_signed_offset(&self, val: u64, i: i128) -> (u64, bool) {
             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 @@ fn offset<'tcx>(&self, val: u64, i: u64) -> InterpResult<'tcx, 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) }
     }
 }
@@ -189,14 +188,14 @@ pub fn signed_offset(self, i: i64, cx: &impl HasDataLayout) -> InterpResult<'tcx
     }
 
     #[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)]
index f00952e3725eb862b22dca16bf96e97945e039d4..706cf1cd09a79048898f42c97586f78f9630a55d 100644 (file)
@@ -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 @@ pub fn zst() -> Self {
         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]