-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add convenience byte offset/check align functions to pointers #95643
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