From 047e702c66ec04d44366210251ae7189ac4bf20a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 4 Nov 2019 13:24:27 +0100 Subject: [PATCH] Miri: ptr_offset_from: support offset_from with twice the same non-null integer --- src/librustc_mir/interpret/intrinsics.rs | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 0b8e3ff6736f..990e3007755b 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)?;