-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Allocate arguments from topmost frame into temporary storage before popping stack frame in init_fn_tail_call
#144933
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
base: master
Are you sure you want to change the base?
Conversation
|
be61cdf
to
20fc35f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both Ralf and Oli are on vacations so I guess I'll have to review it for now ^^'
This looks reasonable to me, r=me with/out nits.
match self.value { | ||
LocalValue::Dead => false, | ||
LocalValue::Live(val) => match val { | ||
Operand::Immediate(_) => false, | ||
Operand::Indirect(_) => true, | ||
}, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
match self.value { | |
LocalValue::Dead => false, | |
LocalValue::Live(val) => match val { | |
Operand::Immediate(_) => false, | |
Operand::Indirect(_) => true, | |
}, | |
} | |
match self.value { | |
LocalValue::Dead | LocalValue::Live(Operand::Immediate(_)) => false, | |
LocalValue::Live(Operand::Indirect(_)) => true, | |
} |
let local_allocs: FxHashSet<_> = frame_locals | ||
.iter() | ||
.filter_map(|local| local.as_mplace_or_imm()?.left()?.0.provenance?.get_alloc_id()) | ||
.collect(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you wrap this in std::cell::LazyCell
, so that we don't create a hash map if none of the arguments have mplaces?
I won't have time to review this during my vacation, but as a quick first note -- I rather strongly object to anything that involves special casing It would seem to me that passing a |
I'd appreciate if you could hold off on landing this until I'm back, since this is an unstable feature I hope it's not urgent. |
I'll wait until Ralf is back. I will note that I don't see what this has to do with Right now we pop a stack frame and deinit the locals in that stack frame before initializing a new stack frame for the tail call. If an arg is being passed indirectly from an allocation corresponding to local that has been deinited, then I don't see any way to make that a defined operation. |
This is a general tail call problem -- you need to move the indirect ABI arguments somewhere off of the current stack frame. I think this is (one of?) the reason(s?) why we have to have the same signature requirement -- that allows backends to move arguments to the caller (pseudocode): fn src_tail(arg: /* implicitly passed by ref in the ABI */ String) {
let local = arg.clone();
drop(arg);
become src_tail(local)
}
// ==>>
fn src_tail(arg: /* implicitly passed by ref in the ABI */ String) {
let local = arg.clone();
drop(arg);
write_through_implicit_ref(arg, local);
become src_tail(arg)
} I'm not sure we we want to emulate this in miri, but we do have to do something. I agree that we should indeed wait for Ralf to return though ^^' |
When doing a tail call, we pop the topmost frame and then push a new frame to replace it. If we have an argument that is being passed indirectly from an mplace of a local from that old stack frame, then it will be invalidated before we can copy them into the locals of the new stack frame.
THis PR detects arguments that are being indirectly via pointers which point into the allocations of the topmost stack frame's locals. If we find an argument, we copy it into new temporary memory for constructing the new stack frame, and then we deallocate that old memory.
Not totally sure who should review this, since I'm not totally sure if I'm using CTFE correctly 😎 Specifically I don't know if I am implementing the right logic for "does this argument come from an allocation that corresponds to a local in the top stack frame".
r? @WaffleLapkin @RalfJung @oli-obk
Fix #144820