-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Add convenience byte offset/check align functions to pointers #95643
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Conversation
r? @m-ou-se (rust-highfive has picked a reviewer for you, use r? to override) |
I proposed and drafted the initial code for this PR, so I 100% endorse the concept. For motivation we need look no farther than #95241, where I poked at most of the ptr<->int casts in the codebase. Patterns that showed up that I left in their "manual" state:
|
Are you sure we need the check & panic in |
I was just mirroring the semantics of the more evil existing alignment-handling function, on the assumption that it was needed for... Reasons. |
Are you talking about |
Yeah, I figured it align_offset insisted it was important I should be consistent with it, and we can always relax the panic to "it's all fine"... right? I guess we would have to say "might panic" or "it's UB" or something? So that people aren't allowed to treat it as an assert they can depend on? |
I don't think "it's UB" is a good idea (especially not when the method is safe and I don't think it should be unsafe just because of that), but "might panic" sounds good. |
@WaffleLapkin is this ready to land? are there still things to do? |
@Gankra I believe this is ready to land, yes. |
Filed please add these to the unstable decls. insofar as my opinion carries weight anymore, I would be happy to r+ this |
r? rust-lang/libs-api @rustbot label +T-libs-api -T-libs |
I'm reassigning this PR because I'm taking a break from the review rotation for a little while. Thank you for your patience. r? rust-lang/libs-api |
Since they work on byte pointers (by `.cast::<u8>()`ing them), there is no need to know the size of `T` and so there is no need for `T: Sized`. The `is_aligned_to` is similar, though it doesn't need the _alignment_ of `T`.
Apparently LLVM is unable to understand that if count_ones() == 1 then self != 0. Adding `assume(align != 0)` helps generating better asm: https://rust.godbolt.org/z/ja18YKq91
…ter_byte_offsets and pointer_is_aligned
ad372d3
to
03d4569
Compare
I wander if we also need |
Looks reasonable to me! We can always bikeshed names later, but I personally think these names look good. @bors r+ |
📌 Commit 03d4569 has been approved by |
☀️ Test successful - checks-actions |
Finished benchmarking commit (d8a3fc4): comparison url. Summary: This benchmark run did not return any relevant results. If you disagree with this performance assessment, please file an issue in rust-lang/rustc-perf. @rustbot label: -perf-regression |
1. change `PtrMut::as_ptr(self)` and `OwnedPtr::as_ptr(self)` to take `&self`, otherwise printing the pointer will prevent doing anything else afterwards 2. make all `as_ptr` methods safe. There's nothing unsafe about obtaining a pointer, these kinds of methods are safe in std as well [str::as_ptr](https://doc.rust-lang.org/stable/std/primitive.str.html#method.as_ptr), [Rc::as_ptr](https://doc.rust-lang.org/stable/std/rc/struct.Rc.html#method.as_ptr) 3. rename `offset`/`add` to `byte_offset`/`byte_add`. The unprefixed methods in std add in increments of `std::mem::size_of::<T>`, not in bytes. There's a PR for rust to add these byte_ methods rust-lang/rust#95643 and at the call site it makes it much more clear that you need to do `.byte_add(i * layout_size)` instead of `.add(i)`
…o, r=workingjubilee Optimize `pointer::as_aligned_to` This PR replaces `addr % align` with `addr & align - 1`, which is correct due to `align` being a power of two. Here is a proof that this makes things better: [[godbolt]](https://godbolt.org/z/Wbq3hx6YG). This PR also removes `assume(align != 0)`, with the new impl it does not improve anything anymore ([[godbolt]](https://rust.godbolt.org/z/zcnrG4777), [[original concern]](rust-lang#95643 (comment))).
Add pointer masking convenience functions This PR adds the following public API: ```rust impl<T: ?Sized> *const T { fn mask(self, mask: usize) -> *const T; } impl<T: ?Sized> *mut T { fn mask(self, mask: usize) -> *const T; } // mod intrinsics fn mask<T>(ptr: *const T, mask: usize) -> *const T ``` This is equivalent to `ptr.map_addr(|a| a & mask)` but also uses a cool llvm intrinsic. Proposed in rust-lang#95643 (comment) cc `@Gankra` `@scottmcm` `@RalfJung` r? rust-lang/libs-api
Add pointer masking convenience functions This PR adds the following public API: ```rust impl<T: ?Sized> *const T { fn mask(self, mask: usize) -> *const T; } impl<T: ?Sized> *mut T { fn mask(self, mask: usize) -> *const T; } // mod intrinsics fn mask<T>(ptr: *const T, mask: usize) -> *const T ``` This is equivalent to `ptr.map_addr(|a| a & mask)` but also uses a cool llvm intrinsic. Proposed in rust-lang#95643 (comment) cc ``@Gankra`` ``@scottmcm`` ``@RalfJung`` r? rust-lang/libs-api
Add pointer masking convenience functions This PR adds the following public API: ```rust impl<T: ?Sized> *const T { fn mask(self, mask: usize) -> *const T; } impl<T: ?Sized> *mut T { fn mask(self, mask: usize) -> *const T; } // mod intrinsics fn mask<T>(ptr: *const T, mask: usize) -> *const T ``` This is equivalent to `ptr.map_addr(|a| a & mask)` but also uses a cool llvm intrinsic. Proposed in rust-lang#95643 (comment) cc `@Gankra` `@scottmcm` `@RalfJung` r? rust-lang/libs-api
Add pointer masking convenience functions This PR adds the following public API: ```rust impl<T: ?Sized> *const T { fn mask(self, mask: usize) -> *const T; } impl<T: ?Sized> *mut T { fn mask(self, mask: usize) -> *const T; } // mod intrinsics fn mask<T>(ptr: *const T, mask: usize) -> *const T ``` This is equivalent to `ptr.map_addr(|a| a & mask)` but also uses a cool llvm intrinsic. Proposed in rust-lang/rust#95643 (comment) cc `@Gankra` `@scottmcm` `@RalfJung` r? rust-lang/libs-api
Add pointer masking convenience functions This PR adds the following public API: ```rust impl<T: ?Sized> *const T { fn mask(self, mask: usize) -> *const T; } impl<T: ?Sized> *mut T { fn mask(self, mask: usize) -> *const T; } // mod intrinsics fn mask<T>(ptr: *const T, mask: usize) -> *const T ``` This is equivalent to `ptr.map_addr(|a| a & mask)` but also uses a cool llvm intrinsic. Proposed in rust-lang/rust#95643 (comment) cc `@Gankra` `@scottmcm` `@RalfJung` r? rust-lang/libs-api
…ingjubilee Optimize `pointer::as_aligned_to` This PR replaces `addr % align` with `addr & align - 1`, which is correct due to `align` being a power of two. Here is a proof that this makes things better: [[godbolt]](https://godbolt.org/z/Wbq3hx6YG). This PR also removes `assume(align != 0)`, with the new impl it does not improve anything anymore ([[godbolt]](https://rust.godbolt.org/z/zcnrG4777), [[original concern]](rust-lang/rust#95643 (comment))).
Add pointer masking convenience functions This PR adds the following public API: ```rust impl<T: ?Sized> *const T { fn mask(self, mask: usize) -> *const T; } impl<T: ?Sized> *mut T { fn mask(self, mask: usize) -> *const T; } // mod intrinsics fn mask<T>(ptr: *const T, mask: usize) -> *const T ``` This is equivalent to `ptr.map_addr(|a| a & mask)` but also uses a cool llvm intrinsic. Proposed in rust-lang/rust#95643 (comment) cc `@Gankra` `@scottmcm` `@RalfJung` r? rust-lang/libs-api
1. change `PtrMut::as_ptr(self)` and `OwnedPtr::as_ptr(self)` to take `&self`, otherwise printing the pointer will prevent doing anything else afterwards 2. make all `as_ptr` methods safe. There's nothing unsafe about obtaining a pointer, these kinds of methods are safe in std as well [str::as_ptr](https://doc.rust-lang.org/stable/std/primitive.str.html#method.as_ptr), [Rc::as_ptr](https://doc.rust-lang.org/stable/std/rc/struct.Rc.html#method.as_ptr) 3. rename `offset`/`add` to `byte_offset`/`byte_add`. The unprefixed methods in std add in increments of `std::mem::size_of::<T>`, not in bytes. There's a PR for rust to add these byte_ methods rust-lang/rust#95643 and at the call site it makes it much more clear that you need to do `.byte_add(i * layout_size)` instead of `.add(i)`
This PR adds the following APIs:
Note that all functions except
is_aligned
do not requireT: Sized
as their pointee-sized-offset counterparts.cc @oli-obk (you may want to check that I've correctly placed
const
s)cc @RalfJung