about summary refs log tree commit diff
path: root/src/librustc_mir
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-11-05 12:46:29 +0000
committerbors <bors@rust-lang.org>2019-11-05 12:46:29 +0000
commit3a1b3b30c6cdd674049b144a3ced7b711de962b2 (patch)
treeb28aa0b22f11b2adc83b52c6eea06fc63236ed18 /src/librustc_mir
parentd1fff4a4b213b3341c1ff994061b7965a5932c70 (diff)
parenta593b5419901774c134e18433452c4dd5f7ff648 (diff)
downloadrust-3a1b3b30c6cdd674049b144a3ced7b711de962b2.tar.gz
rust-3a1b3b30c6cdd674049b144a3ced7b711de962b2.zip
Auto merge of #66083 - RalfJung:miri-offset-from, r=oli-obk
fix Miri offset_from

This is needed to make https://github.com/rust-lang/miri/pull/1032 pass.
Diffstat (limited to 'src/librustc_mir')
-rw-r--r--src/librustc_mir/interpret/intrinsics.rs25
1 files changed, 22 insertions, 3 deletions
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index c08e4c89609..04032847385 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -251,8 +251,28 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             }
 
             "ptr_offset_from" => {
-                let a = self.read_immediate(args[0])?.to_scalar()?.to_ptr()?;
-                let b = self.read_immediate(args[1])?.to_scalar()?.to_ptr()?;
+                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, we pretend there is an allocation of size 0 right there,
+                // and their offset is 0. (There's never a valid object at NULL, making it an
+                // exception from the exception.)
+                // This is the dual to the special exception for offset-by-0
+                // in the inbounds pointer offset operation (see the Miri code, `src/operator.rs`).
+                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 +286,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)?;