Skip to content

Commit 5906e8e

Browse files
authored
Rollup merge of rust-lang#121242 - joboet:ptr_invalid_codegen, r=scottmcm,Nilstrieb
Generate `getelementptr` instead of `inttoptr` for `ptr::invalid` Currently, `ptr::invalid` [generates an `inttoptr`](https://godbolt.org/z/3cj15dEG1), which means LLVM doesn't know that the pointer shouldn't have provenance. This PR changes the implementation so that a `getelementptr` relative to the null pointer is generated, which LLVM knows not to have provenance.
2 parents 736f958 + bb399b1 commit 5906e8e

File tree

2 files changed

+31
-12
lines changed

2 files changed

+31
-12
lines changed

library/core/src/ptr/mod.rs

+16-12
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,10 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
537537
#[rustc_allow_const_fn_unstable(ptr_metadata)]
538538
#[rustc_diagnostic_item = "ptr_null"]
539539
pub const fn null<T: ?Sized + Thin>() -> *const T {
540-
from_raw_parts(invalid(0), ())
540+
// Use transmute instead of casting so that Miri knows that the pointer is invalid.
541+
// SAFETY: on all current platforms, usize and pointers have the same layout,
542+
// and the validity invariant of pointers is the same as that of integers
543+
unsafe { mem::transmute(0usize) }
541544
}
542545

543546
/// Creates a null mutable raw pointer.
@@ -563,7 +566,10 @@ pub const fn null<T: ?Sized + Thin>() -> *const T {
563566
#[rustc_allow_const_fn_unstable(ptr_metadata)]
564567
#[rustc_diagnostic_item = "ptr_null_mut"]
565568
pub const fn null_mut<T: ?Sized + Thin>() -> *mut T {
566-
from_raw_parts_mut(invalid_mut(0), ())
569+
// Use transmute instead of casting so that Miri knows that the pointer is invalid.
570+
// SAFETY: on all current platforms, usize and pointers have the same layout,
571+
// and the validity invariant of pointers is the same as that of integers
572+
unsafe { mem::transmute(0usize) }
567573
}
568574

569575
/// Creates an invalid pointer with the given address.
@@ -590,11 +596,10 @@ pub const fn null_mut<T: ?Sized + Thin>() -> *mut T {
590596
#[unstable(feature = "strict_provenance", issue = "95228")]
591597
pub const fn invalid<T>(addr: usize) -> *const T {
592598
// FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic.
593-
// We use transmute rather than a cast so tools like Miri can tell that this
594-
// is *not* the same as from_exposed_addr.
595-
// SAFETY: every valid integer is also a valid pointer (as long as you don't dereference that
596-
// pointer).
597-
unsafe { mem::transmute(addr) }
599+
// We offset the null pointer instead of using a cast so that LLVM doesn't
600+
// use inttoptr and so tools like Miri can tell that it is *not* the same
601+
// as from_exposed_addr.
602+
null::<T>().wrapping_byte_add(addr)
598603
}
599604

600605
/// Creates an invalid mutable pointer with the given address.
@@ -621,11 +626,10 @@ pub const fn invalid<T>(addr: usize) -> *const T {
621626
#[unstable(feature = "strict_provenance", issue = "95228")]
622627
pub const fn invalid_mut<T>(addr: usize) -> *mut T {
623628
// FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic.
624-
// We use transmute rather than a cast so tools like Miri can tell that this
625-
// is *not* the same as from_exposed_addr.
626-
// SAFETY: every valid integer is also a valid pointer (as long as you don't dereference that
627-
// pointer).
628-
unsafe { mem::transmute(addr) }
629+
// We offset the null pointer instead of using a cast so that LLVM doesn't
630+
// use inttoptr and so tools like Miri can tell that it is *not* the same
631+
// as from_exposed_addr.
632+
null_mut::<T>().wrapping_byte_add(addr)
629633
}
630634

631635
/// Convert an address back to a pointer, picking up a previously 'exposed' provenance.

tests/codegen/strict-provenance.rs

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// compile-flags: -O
2+
3+
#![crate_type = "lib"]
4+
#![feature(strict_provenance)]
5+
6+
use std::ptr;
7+
8+
// CHECK-LABEL: @invalid
9+
#[no_mangle]
10+
fn invalid(addr: usize) -> *const () {
11+
// CHECK: start
12+
// CHECK-NEXT: %0 = getelementptr i8, ptr null, i64 %addr
13+
// CHECK-NEXT: ret ptr %0
14+
ptr::invalid(addr)
15+
}

0 commit comments

Comments
 (0)