-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Tracking issue for RFC 2043: Add align_offset
intrinsic (formerly: and [T]::align_to
function)
#44488
Comments
More `align_offset` things cc rust-lang#44488
More `align_offset` things cc rust-lang#44488
More `align_offset` things cc rust-lang#44488
…trochenkov Fix the wrong subtraction in align_offset intrinsic. Given how the stage0 implementation in rust-lang#43903 is written, as well as that in the RFC, I suppose the current implementation has a typo. cc rust-lang#44488, cc @oli-obk.
@oli-obk Is it useful to stabilize |
Generally yes, because that's the key feature. Align_to is just convenience |
Alright, then. Let’s stabilize @rfcbot fcp merge |
Team member @SimonSapin has proposed to merge this. The next step is review by the rest of the tagged team members: Concerns:
Once a majority of reviewers approve (and none object), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
@rfcbot concern motivation-and-ergonomics The original motivation for these functions (unless it's changed, which it may have!) I believe was for miri and const evaluating various functions. Is that still the main motivation for these functions? If so do we expect that more things to be available on stable once these are stabilized? I'm a little unclear about how and when such an intrinsic would be used so I'm mostly looking to straighten up my own thinking! In particular the clause "If it is not possible to align the pointer, the implementation returns usize::max_value()." I'm having trouble wrapping my head around in how it'd be expected to get used. Is the long term plan to make this a In terms of ergonomics I'd also naively expect a signature like: pub fn align_to(self, align: usize) -> Option<*mut Self>; but would that create the same problems it's trying to avoid? |
yes
This will allow making it const fn, which is a separate topic in the future
No matter which computation you use to figure out the number of bytes that you need to offset your pointer in order to make it aligned, you will need to check whether it still points into your buffer. If you have a
No, these operations are fine. The issue is that no matter how many bytes you offset a
You could do that, but then you'd also need an argument for the allocation size. Now that I think about it, that doesn't seem too bad and since you need to check anyway... As long as the intrinsic doesn't have to return an |
Ok, thanks for the info! It sounds like this function doesn't necessarily unlock anything in the near term as const-things are still pretty unstable? If that's the case I'm personally tempted to leave these as unstable until we've got the const story more fleshed out to see how they fit into the grand scheme of things |
Oh dear, it has been almost a year since the RFC and it went totally outside my radar, until I really, really needed Thinking about possible implementation approaches, I realised that to implement loop {
x = intrinsics::align_offset(ptr, align);
if (x is aligned to object start) { return }
ptr = x.offset(1);
} So with @oli-obk we decided that it would probably be most prudent to simply change the intrinsic to do such calculation by itself, changing its signature from the current one to |
I’m almost done with the improved implementation of the
I propose that we change |
I'm assuming we are talking about elements of the source slice and not the aligned slice. Sgtm |
I guess I should’ve said in “number of |
IIRC this was in bytes in the intrinsic because the pointer to align could have a ZST pointee, and always using bytes sidesteps the questions of what to do there. (Not that I'm sure why you'd want to align a |
FYI implementation for |
Implement [T]::align_to Note that this PR deviates from what is accepted by RFC slightly by making `align_offset` to return an offset in elements, rather than bytes. This is necessary to sanely support `[T]::align_to` and also simply makes more sense™. The caveat is that trying to align a pointer of ZST is now an equivalent to `is_aligned` check, rather than anything else (as no number of ZST elements will align a misaligned ZST pointer). It also implements the `align_to` slightly differently than proposed in the RFC to properly handle cases where size of T and U aren’t co-prime. Furthermore, a promise is made that the slice containing `U`s will be as large as possible (contrary to the RFC) – otherwise the function is quite useless. The implementation uses quite a few underhanded tricks and takes advantage of the fact that alignment is a power-of-two quite heavily to optimise the machine code down to something that results in as few known-expensive instructions as possible. Currently calling `ptr.align_offset` with an unknown-at-compile-time `align` results in code that has just a single "expensive" modulo operation; the rest is "cheap" arithmetic and bitwise ops. cc #44488 @oli-obk As mentioned in the commit message for align_offset, many thanks go to Chris McDonald.
align_offset
intrinsic and [T]::align_to
function align_offset
intrinsic (formerly: and [T]::align_to
function)
@rfcbot resolve motivation-and-ergonomics I don't want to personally be on the hook for blocking this any more |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
The final comment period, with a disposition to merge, as per the review above, is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. The RFC will be merged soon. |
What's the status of this? |
In terms of process, this FCP includes |
Cool, I'll look into creating that then. |
Stabilize pointer::align_offset Closes #44488
What is the point of this function? I'm dealing with hardware where if the pointer is not aligned, the instruction will fault. So I need to implement this function myself because this function is not guaranteed to be useful? |
The point of this function that if it returns an offset that is out of bounds of your allocation, you should run your backup logic that does not depend on alignment. Imagine having a Platforms like |
What backup logic? As stated, in my use case it is not possible to use an unaligned value. |
In that case, what happens if you get an aligned value but it's outside of your allocation? You can't make a memory location aligned, you can only offset a pointer until it is aligned. But offsetting a pointer may go beyond the allocation your pointer points to EDIT: maybe you need to make this decision at a higher level? e.g. by using the corresponding slice method (https://doc.rust-lang.org/std/primitive.slice.html#method.align_to) ? |
This function is for cases where e.g. you have a But as @oli-obk said, you need backup logic anyway because the pointer you are getting might not be sufficiently aligned, and the buffer might not be large enough to find something aligned "in the middle". What do you want to do in that case? I think we need a bit more context here. |
No this is pretty much exactly the case for me. But I know that my input buffer is guaranteed to be large enough to hold the "aligned center". |
Well, that is a subtly different use-case -- not what this function was designed for, and also one that Miri currently does not support. (There are trade-offs here: supporting that means being less good at detecting misaligned memory accesses.) In particular, what do you do with the unaligned prefix and suffix? Usually they also need processing, and that's why you need fall-back code. You could always use |
I'm talking about
I'm using |
Yeah that's not at all the use-case for which this was designed. If you want to implement an aligned allocator based on an unaligned one, this function currently won't help you. libstd in fact also contains such code because Windows.
Oh but it is doing way more than that. Quoting from the docs:
That's what makes this function complicated. It actually solves an integer modulo congruence. |
@RalfJung It seems weird to me that |
I guessed as much. So? All I said is, the function is more general than your use-case, making it way more complicated than "rounding up", and its reason to exist is not what you seem to think it is (to remove some simple rounding-up code from allocators -- an extremely rare thing to write). You are looking at a very complicated tool with subtle trade-offs, wanting to use it in its simplest possible form (ignoring 99% of its functionality) and then complain that it doesn't exactly do what you want it to do. Well, I am afraid the tradeoffs that informed its design are different than yours. Probably this is not the tool you are looking for. Assuming allocation is expensive, it also shouldn't be too much of a problem to call
You (like, the general public) should use it. You (@jethrogb) are just misinterpreting what it should be used for. |
In fact the docs say quite clearly:
So, if that's not a constraint you can live with, that's okay -- just don't use this function. |
Except that won't work, because:
So when I do the assertion (which I'd be fine with), the implementation is free to unconditionally insert an assertion failure. Unless you think that that's not the case, in which case this is a documentation issue.
I definitely can't live with this, because now I still need to implement a "round up" function in case this function failed. Then I might as well just not use this function.
I don't think pointer alignment manipulation is at all rare when dealing with low-level code, something Rust is supposed to be good at. Definitely not limited to allocators. I will not be the first person to come across this function when looking at the |
Correct. The current situation is that the libstd/rustc implementation will always succeed to align if
So far, allocators are the only use-case I am aware of that would need proper alignment for correctness, not just performance. Most of the time you are fed in data you have to work with; allocation is the only time when you are asked to produce memory with a certain alignment. But I am mostly unfamiliar with embedded programming and many other ways of using Rust, so if anyone reading along also has a use-case that is affected by this, please chime in. :) For your use-case, a "please round up this pointer/integer to alignment X" function seems to be much more useful though than something that just computes the offset? |
This is a tracking issue for the RFC "Add
align_offset
intrinsic and[T]::align_to
function " (rust-lang/rfcs#2043).align_to
is stable, so this tracks justalign_offset
now.Steps:
align_to
: stabilize slice_align_to #53754Unresolved questions:
sizeof<T>() % sizeof<U>() != 0
and in case the expansion is not part of a monomorphisation, since in that casealign_to
is statically known to never be effectiveThe text was updated successfully, but these errors were encountered: