-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Semantics of StorageLive in loops #42371
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
Comments
I suppose a somewhat weaker interpretation would be for |
FYI, I implemented the above suggestion in Miri, and the test suite passes. Now that's not a whole lot of code on the grand scheme of things, but this does invoke some interesting unsafe code in Vec and the |
Accidental triage (because I forgot about this and just rediscovered the issue^^): the situation is unchanged. |
…sakis Clean up MIR drop generation * Don't assign twice to the destination of a `while` loop containing a `break` expression * Use `as_temp` to evaluate statement expression * Avoid consecutive `StorageLive`s for the condition of a `while` loop * Unify `return`, `break` and `continue` handling, and move it to `scopes.rs` * Make some of the `scopes.rs` internals private * Don't use `Place`s that are always `Local`s in MIR drop generation Closes #42371 Closes #61579 Closes #61731 Closes #61834 Closes #61910 Closes #62115
@matthewjasper I don't think this is fixed. I am still seeing already-live locals marked as live if I make Miri check for that. You can see that in this example: the MIR with your patch is Expand MIR
You can see that there is a |
In fact, MIR generation in that example does not seem to change at all with your PR. |
Note-mostly-to-self: the branch to make Miri check if this issue is resolved is at https://github.com/RalfJung/rust/tree/miri-storage-live. |
…=pnkfelix Sometimes generate storage statements for temporaries with type `!` Closes rust-lang#62165 cc rust-lang#42371
Alive2 is a tool to check LLVM optimizations correct, and it has to give an operational semantics to LLVM IR. What they do for lifetime.start/end is interesting:
This is close to what Miri does, except Miri re-assigns a new block ID and address each time the lifetime of a local ends and starts again. (Compiling from Miri to Alive2 semantics is correct but not the other way around, so we are good.) Also:
and
|
Hi, maybe a silly question - is there a reason that Rust emits I'm wondering whether it makes sense for LLVM to typecheck whether a program has lifetime intrinsics arranged within well-known patterns only. If the usage pattern was too complex, LLVM would already have given up using the pairs for optimization. |
You mean the other way around? It seems to be in bb1. I'm afraid I do not know why we emit |
The The MIR now has a |
Would be good to have the LangRef updated then... where can I read more about StackColoring?
Oh, nice! I'll try to see if I can now adjust |
|
I love the introduction^^
Seems like everyone is very sure what these things do... doesn't make me worried about LLVM as the foundation of Rust at all...^^ |
Currently this fails to evaluate many constants; I suspect that is related to @oli-obk's #78679. I'll try again once that landed. For future reference, this is the branch. |
(I'm not sure whether here is a good place to ask this, but) can Rust generate lifetime.start/end with non-zero offset? |
Syntactically, the Rust/MIR equivalent of these intrinsics can only be applied to locals, not to a part of a place/local. However, fixing #71416 might require adding offsets to dynamically-sized alloca to make sure the alignment is right. Not sure if there is a way to make the lifetime intrinsics still refer to the original alloca as opposed to the properly aligned ptr. |
Okay, I understood the issue. |
This code
compiles to
On every run through the loop,
StorageLive(_4)
is executed, and there is no matchingStorageDead
.The intended semantics of multiple
StorageLive
on the same location are unclear. However, evidence suggests that LLVM considers a variable dead before anyllvm.lifetime.start
, in particular, inllvm.lifetime.start; load; llvm.lifetime.start
, LLVM feels free to treat that load as yieldingundef
. The reference manual says so (however, it doesn't say anything aboutllvm.lifetime.start; load; llvm.lifetime.end; llvm.lifetime.start
being fine, so it seems incomplete), and @eddyb managed to actually obtain UB from a redundantllvm.lifetime.start
inPlaypen
If you comment out the
MyStorageLive
, this prints some a's. If you leave it in, nothing is printed.This suggests we should rather not permit "redundant"
StorageLive
, and hence the program at the beginning of this report should be translated such that_4
is marked live before the loop, rather than inside the loop.The text was updated successfully, but these errors were encountered: