Skip to content

Commit 6eb76c7

Browse files
committed
Work around bad ptr::with_addr codegen in core::ptr
1 parent baaa3b6 commit 6eb76c7

File tree

2 files changed

+28
-12
lines changed

2 files changed

+28
-12
lines changed

library/core/src/ptr/const_ptr.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -242,12 +242,20 @@ impl<T: ?Sized> *const T {
242242
// In the mean-time, this operation is defined to be "as if" it was
243243
// a wrapping_offset, so we can emulate it as such. This should properly
244244
// restore pointer provenance even under today's compiler.
245-
let self_addr = self.addr() as isize;
246-
let dest_addr = addr as isize;
247-
let offset = dest_addr.wrapping_sub(self_addr);
248-
249-
// This is the canonical desugarring of this operation
250-
self.cast::<u8>().wrapping_offset(offset).cast::<T>()
245+
let self_addr = self.addr();
246+
// Unfortunately, the CHERI-compatible way of defining this operation
247+
// optimizes worse, so we special case it... in a somewhat ad-hoc way
248+
// (checking for 128 bit pointers) because at the time of this writing,
249+
// we don't actually support CHERI yet. Ideally this would be
250+
// `cfg!(target_supports_large_wrapping_offsets)` or something, see
251+
// #96152 for details.
252+
if cfg!(target_pointer_width = "128") {
253+
let offset = (addr as isize).wrapping_sub(self_addr as isize);
254+
// This is the canonical desugarring of this operation
255+
self.cast::<u8>().wrapping_offset(offset).cast::<T>()
256+
} else {
257+
self.cast::<u8>().wrapping_sub(self_addr).wrapping_add(addr).cast::<T>()
258+
}
251259
}
252260

253261
/// Creates a new pointer by mapping `self`'s address to a new one.

library/core/src/ptr/mut_ptr.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -246,12 +246,20 @@ impl<T: ?Sized> *mut T {
246246
// In the mean-time, this operation is defined to be "as if" it was
247247
// a wrapping_offset, so we can emulate it as such. This should properly
248248
// restore pointer provenance even under today's compiler.
249-
let self_addr = self.addr() as isize;
250-
let dest_addr = addr as isize;
251-
let offset = dest_addr.wrapping_sub(self_addr);
252-
253-
// This is the canonical desugarring of this operation
254-
self.cast::<u8>().wrapping_offset(offset).cast::<T>()
249+
let self_addr = self.addr();
250+
// Unfortunately, the CHERI-compatible way of defining this operation
251+
// optimizes worse, so we special case it... in a somewhat ad-hoc way
252+
// (checking for 128 bit pointers) because at the time of this writing,
253+
// we don't actually support CHERI yet. Ideally this would be
254+
// `cfg!(target_supports_large_wrapping_offsets)` or something, see
255+
// #96152 for details.
256+
if cfg!(target_pointer_width = "128") {
257+
let offset = (addr as isize).wrapping_sub(self_addr as isize);
258+
// This is the canonical desugarring of this operation
259+
self.cast::<u8>().wrapping_offset(offset).cast::<T>()
260+
} else {
261+
self.cast::<u8>().wrapping_sub(self_addr).wrapping_add(addr).cast::<T>()
262+
}
255263
}
256264

257265
/// Creates a new pointer by mapping `self`'s address to a new one.

0 commit comments

Comments
 (0)