Skip to content

Commit d3f0627

Browse files
committed
miri: support 'promising' alignment for symbolic alignment check
1 parent 341abd1 commit d3f0627

File tree

3 files changed

+85
-6
lines changed

3 files changed

+85
-6
lines changed

core/src/ptr/const_ptr.rs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1368,10 +1368,36 @@ impl<T: ?Sized> *const T {
13681368
panic!("align_offset: align is not a power-of-two");
13691369
}
13701370

1371-
{
1372-
// SAFETY: `align` has been checked to be a power of 2 above
1373-
unsafe { align_offset(self, align) }
1371+
// SAFETY: `align` has been checked to be a power of 2 above
1372+
let ret = unsafe { align_offset(self, align) };
1373+
1374+
// Inform Miri that we want to consider the resulting pointer to be suitably aligned.
1375+
#[cfg(miri)]
1376+
if ret != usize::MAX {
1377+
fn runtime(ptr: *const (), align: usize) {
1378+
extern "Rust" {
1379+
pub fn miri_promise_symbolic_alignment(ptr: *const (), align: usize);
1380+
}
1381+
1382+
// SAFETY: this call is always safe.
1383+
unsafe {
1384+
miri_promise_symbolic_alignment(ptr, align);
1385+
}
1386+
}
1387+
1388+
const fn compiletime(_ptr: *const (), _align: usize) {}
1389+
1390+
// SAFETY: the extra behavior at runtime is for UB checks only.
1391+
unsafe {
1392+
intrinsics::const_eval_select(
1393+
(self.wrapping_add(ret).cast(), align),
1394+
compiletime,
1395+
runtime,
1396+
);
1397+
}
13741398
}
1399+
1400+
ret
13751401
}
13761402

13771403
/// Returns whether the pointer is properly aligned for `T`.

core/src/ptr/mut_ptr.rs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1635,10 +1635,36 @@ impl<T: ?Sized> *mut T {
16351635
panic!("align_offset: align is not a power-of-two");
16361636
}
16371637

1638-
{
1639-
// SAFETY: `align` has been checked to be a power of 2 above
1640-
unsafe { align_offset(self, align) }
1638+
// SAFETY: `align` has been checked to be a power of 2 above
1639+
let ret = unsafe { align_offset(self, align) };
1640+
1641+
// Inform Miri that we want to consider the resulting pointer to be suitably aligned.
1642+
#[cfg(miri)]
1643+
if ret != usize::MAX {
1644+
fn runtime(ptr: *const (), align: usize) {
1645+
extern "Rust" {
1646+
pub fn miri_promise_symbolic_alignment(ptr: *const (), align: usize);
1647+
}
1648+
1649+
// SAFETY: this call is always safe.
1650+
unsafe {
1651+
miri_promise_symbolic_alignment(ptr, align);
1652+
}
1653+
}
1654+
1655+
const fn compiletime(_ptr: *const (), _align: usize) {}
1656+
1657+
// SAFETY: the extra behavior at runtime is for UB checks only.
1658+
unsafe {
1659+
intrinsics::const_eval_select(
1660+
(self.wrapping_add(ret).cast_const().cast(), align),
1661+
compiletime,
1662+
runtime,
1663+
);
1664+
}
16411665
}
1666+
1667+
ret
16421668
}
16431669

16441670
/// Returns whether the pointer is properly aligned for `T`.

core/src/slice/mod.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3868,6 +3868,18 @@ impl<T> [T] {
38683868
} else {
38693869
let (left, rest) = self.split_at(offset);
38703870
let (us_len, ts_len) = rest.align_to_offsets::<U>();
3871+
// Inform Miri that we want to consider the "middle" pointer to be suitably aligned.
3872+
#[cfg(miri)]
3873+
{
3874+
extern "Rust" {
3875+
pub fn miri_promise_symbolic_alignment(ptr: *const (), align: usize);
3876+
}
3877+
3878+
// SAFETY: this call is always safe.
3879+
unsafe {
3880+
miri_promise_symbolic_alignment(rest.as_ptr().cast(), mem::align_of::<U>());
3881+
}
3882+
}
38713883
// SAFETY: now `rest` is definitely aligned, so `from_raw_parts` below is okay,
38723884
// since the caller guarantees that we can transmute `T` to `U` safely.
38733885
unsafe {
@@ -3938,6 +3950,21 @@ impl<T> [T] {
39383950
let (us_len, ts_len) = rest.align_to_offsets::<U>();
39393951
let rest_len = rest.len();
39403952
let mut_ptr = rest.as_mut_ptr();
3953+
// Inform Miri that we want to consider the "middle" pointer to be suitably aligned.
3954+
#[cfg(miri)]
3955+
{
3956+
extern "Rust" {
3957+
pub fn miri_promise_symbolic_alignment(ptr: *const (), align: usize);
3958+
}
3959+
3960+
// SAFETY: this call is always safe.
3961+
unsafe {
3962+
miri_promise_symbolic_alignment(
3963+
mut_ptr.cast() as *const (),
3964+
mem::align_of::<U>(),
3965+
);
3966+
}
3967+
}
39413968
// We can't use `rest` again after this, that would invalidate its alias `mut_ptr`!
39423969
// SAFETY: see comments for `align_to`.
39433970
unsafe {

0 commit comments

Comments
 (0)