Skip to content

Commit 047e702

Browse files
committed
Miri: ptr_offset_from: support offset_from with twice the same non-null integer
1 parent da0c7c6 commit 047e702

File tree

1 file changed

+20
-3
lines changed

1 file changed

+20
-3
lines changed

src/librustc_mir/interpret/intrinsics.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,26 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
251251
}
252252

253253
"ptr_offset_from" => {
254-
let a = self.force_ptr(self.read_immediate(args[0])?.to_scalar()?)?;
255-
let b = self.force_ptr(self.read_immediate(args[1])?.to_scalar()?)?;
254+
let isize_layout = self.layout_of(self.tcx.types.isize)?;
255+
let a = self.read_immediate(args[0])?.to_scalar()?;
256+
let b = self.read_immediate(args[1])?.to_scalar()?;
257+
258+
// Special case: if both scalars are *equal integers*
259+
// and not NULL, their offset is 0.
260+
// This is the dual to the special exception for offset-by-0
261+
// in the inbounds pointer offset operation.
262+
if a.is_bits() && b.is_bits() {
263+
let a = a.to_usize(self)?;
264+
let b = b.to_usize(self)?;
265+
if a == b && a != 0 {
266+
self.write_scalar(Scalar::from_int(0, isize_layout.size), dest)?;
267+
return Ok(true);
268+
}
269+
}
270+
271+
// General case: we need two pointers.
272+
let a = self.force_ptr(a)?;
273+
let b = self.force_ptr(b)?;
256274
if a.alloc_id != b.alloc_id {
257275
throw_ub_format!(
258276
"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> {
266284
BinOp::Sub, a_offset, b_offset,
267285
)?;
268286
let pointee_layout = self.layout_of(substs.type_at(0))?;
269-
let isize_layout = self.layout_of(self.tcx.types.isize)?;
270287
let val = ImmTy::from_scalar(val, isize_layout);
271288
let size = ImmTy::from_int(pointee_layout.size.bytes(), isize_layout);
272289
self.exact_div(val, size, dest)?;

0 commit comments

Comments
 (0)