Add convenience byte offset/check align functions to pointers#95643
Add convenience byte offset/check align functions to pointers#95643bors merged 5 commits intorust-lang:masterfrom
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 |
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)`
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
This PR adds the following APIs:
Note that all functions except
is_aligneddo not requireT: Sizedas their pointee-sized-offset counterparts.cc @oli-obk (you may want to check that I've correctly placed
consts)cc @RalfJung