Skip to content

Commit 02a721b

Browse files
committed
Auto merge of #1459 - RalfJung:ptr_guaranteed_eq, r=RalfJung
supply our own implementation of the CTFE pointer comparison intrinsics
2 parents 76d99cf + b46f946 commit 02a721b

File tree

2 files changed

+33
-11
lines changed

2 files changed

+33
-11
lines changed

src/shims/intrinsics.rs

+27-10
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use rustc_middle::{mir, ty};
66
use rustc_middle::ty::layout::IntegerExt;
77
use rustc_apfloat::{Float, Round};
88
use rustc_target::abi::{Align, Integer, LayoutOf};
9+
use rustc_span::symbol::sym;
910

1011
use crate::*;
1112
use helpers::check_arg_count;
@@ -20,17 +21,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
2021
unwind: Option<mir::BasicBlock>,
2122
) -> InterpResult<'tcx> {
2223
let this = self.eval_context_mut();
23-
if this.emulate_intrinsic(instance, args, ret)? {
24+
let intrinsic_name = this.tcx.item_name(instance.def_id());
25+
// We want to overwrite some of the intrinsic implementations that CTFE uses.
26+
let prefer_miri_intrinsic = match intrinsic_name {
27+
sym::ptr_guaranteed_eq | sym::ptr_guaranteed_ne => true,
28+
_ => false,
29+
};
30+
31+
if !prefer_miri_intrinsic && this.emulate_intrinsic(instance, args, ret)? {
2432
return Ok(());
2533
}
26-
let substs = instance.substs;
27-
28-
// All these intrinsics take raw pointers, so if we access memory directly
29-
// (as opposed to through a place), we have to remember to erase any tag
30-
// that might still hang around!
31-
let intrinsic_name = &*this.tcx.item_name(instance.def_id()).as_str();
3234

3335
// First handle intrinsics without return place.
36+
let intrinsic_name = &*intrinsic_name.as_str();
3437
let (dest, ret) = match ret {
3538
None => match intrinsic_name {
3639
"miri_start_panic" => return this.handle_miri_start_panic(args, unwind),
@@ -42,13 +45,27 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
4245

4346
// Then handle terminating intrinsics.
4447
match intrinsic_name {
48+
// Miri overwriting CTFE intrinsics.
49+
"ptr_guaranteed_eq" => {
50+
let &[left, right] = check_arg_count(args)?;
51+
let left = this.read_immediate(left)?;
52+
let right = this.read_immediate(right)?;
53+
this.binop_ignore_overflow(mir::BinOp::Eq, left, right, dest)?;
54+
}
55+
"ptr_guaranteed_ne" => {
56+
let &[left, right] = check_arg_count(args)?;
57+
let left = this.read_immediate(left)?;
58+
let right = this.read_immediate(right)?;
59+
this.binop_ignore_overflow(mir::BinOp::Ne, left, right, dest)?;
60+
}
61+
4562
// Raw memory accesses
4663
#[rustfmt::skip]
4764
| "copy"
4865
| "copy_nonoverlapping"
4966
=> {
5067
let &[src, dest, count] = check_arg_count(args)?;
51-
let elem_ty = substs.type_at(0);
68+
let elem_ty = instance.substs.type_at(0);
5269
let elem_layout = this.layout_of(elem_ty)?;
5370
let count = this.read_scalar(count)?.to_machine_usize(this)?;
5471
let elem_align = elem_layout.align.abi;
@@ -89,7 +106,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
89106

90107
"write_bytes" => {
91108
let &[ptr, val_byte, count] = check_arg_count(args)?;
92-
let ty = substs.type_at(0);
109+
let ty = instance.substs.type_at(0);
93110
let ty_layout = this.layout_of(ty)?;
94111
let val_byte = this.read_scalar(val_byte)?.to_u8()?;
95112
let ptr = this.read_scalar(ptr)?.not_undef()?;
@@ -455,7 +472,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
455472
"assert_zero_valid" |
456473
"assert_uninit_valid" => {
457474
let &[] = check_arg_count(args)?;
458-
let ty = substs.type_at(0);
475+
let ty = instance.substs.type_at(0);
459476
let layout = this.layout_of(ty)?;
460477
// Abort here because the caller might not be panic safe.
461478
if layout.abi.is_uninhabited() {

tests/run-pass/intrinsics.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![feature(core_intrinsics)]
1+
#![feature(core_intrinsics, const_raw_ptr_comparison)]
22

33
use std::intrinsics;
44
use std::mem::{size_of, size_of_val};
@@ -30,4 +30,9 @@ fn main() {
3030
let _v = intrinsics::discriminant_value(&0);
3131
let _v = intrinsics::discriminant_value(&true);
3232
let _v = intrinsics::discriminant_value(&vec![1,2,3]);
33+
34+
let addr = &13 as *const i32;
35+
let addr2 = (addr as usize).wrapping_add(usize::MAX).wrapping_add(1);
36+
assert!(addr.guaranteed_eq(addr2 as *const _));
37+
assert!(addr.guaranteed_ne(0x100 as *const _));
3338
}

0 commit comments

Comments
 (0)