about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2019-11-04 13:24:27 +0100
committerRalf Jung <post@ralfj.de>2019-11-04 13:32:38 +0100
commit047e702c66ec04d44366210251ae7189ac4bf20a (patch)
treeec71ba620c05ed41f9a80c7ddf42e470d8d9514b
parentda0c7c664ba19339c606b3384ef6eebb6c0e4105 (diff)
downloadrust-047e702c66ec04d44366210251ae7189ac4bf20a.tar.gz
rust-047e702c66ec04d44366210251ae7189ac4bf20a.zip
Miri: ptr_offset_from: support offset_from with twice the same non-null integer
-rw-r--r--src/librustc_mir/interpret/intrinsics.rs23
1 files changed, 20 insertions, 3 deletions
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index 0b8e3ff6736..990e3007755 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -251,8 +251,26 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             }
 
             "ptr_offset_from" => {
-                let a = self.force_ptr(self.read_immediate(args[0])?.to_scalar()?)?;
-                let b = self.force_ptr(self.read_immediate(args[1])?.to_scalar()?)?;
+                let isize_layout = self.layout_of(self.tcx.types.isize)?;
+                let a = self.read_immediate(args[0])?.to_scalar()?;
+                let b = self.read_immediate(args[1])?.to_scalar()?;
+
+                // Special case: if both scalars are *equal integers*
+                // and not NULL, their offset is 0.
+                // This is the dual to the special exception for offset-by-0
+                // in the inbounds pointer offset operation.
+                if a.is_bits() && b.is_bits() {
+                    let a = a.to_usize(self)?;
+                    let b = b.to_usize(self)?;
+                    if a == b && a != 0 {
+                        self.write_scalar(Scalar::from_int(0, isize_layout.size), dest)?;
+                        return Ok(true);
+                    }
+                }
+
+                // General case: we need two pointers.
+                let a = self.force_ptr(a)?;
+                let b = self.force_ptr(b)?;
                 if a.alloc_id != b.alloc_id {
                     throw_ub_format!(
                         "ptr_offset_from cannot compute offset of pointers into different \
@@ -266,7 +284,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     BinOp::Sub, a_offset, b_offset,
                 )?;
                 let pointee_layout = self.layout_of(substs.type_at(0))?;
-                let isize_layout = self.layout_of(self.tcx.types.isize)?;
                 let val = ImmTy::from_scalar(val, isize_layout);
                 let size = ImmTy::from_int(pointee_layout.size.bytes(), isize_layout);
                 self.exact_div(val, size, dest)?;