Fix StructReturn handling: properly mark the clobber, and offset actual rets. (#5023)
* Fix StructReturn handling: properly mark the clobber, and offset actual rets. The legalization of `StructReturn` was causing issues in the new call-handling code: the `StructReturn` ret was included in the `SigData` as if it were an actual CLIF-level return value, but it is not. Prior to using regalloc constraints for return values, we unconditionally included rax (or the architecture's usual return register) as a def, so it would be properly handled as "clobbered" by the regalloc. With the new scheme, we include defs on the call only for CLIF-level outputs. Callees with `StructReturn` args were thus not known to clobber the return-value register, and values might be corrupted. This PR updates the code to include a `StructReturn` ret as a clobber rather than a returned value in the relevant spots. I observed it causing saves/restores of rax in some CLIF that @bjorn3 provided me, but I was having difficulty minimizing this into a test-case that I would be comfortable including as a precise-output case (including the whole thing verbatim would lock down a bunch of other irrelevant details and cause test-update noise later). If we can find a more minimized example I'm happy to include it as a filetest. Fixes #5018.
This commit is contained in:
@@ -1206,13 +1206,22 @@ macro_rules! isle_prelude_method_helpers {
|
||||
self.lower_ctx.emit(inst);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle retvals prior to emitting call, so the
|
||||
// constraints are on the call instruction; but buffer the
|
||||
// instructions till after the call.
|
||||
let mut outputs = InstOutput::new();
|
||||
let mut retval_insts: crate::machinst::abi::SmallInstVec<_> = smallvec::smallvec![];
|
||||
for i in 0..num_rets {
|
||||
let ret = self.lower_ctx.sigs()[abi].get_ret(i);
|
||||
// We take the *last* `num_rets` returns of the sig:
|
||||
// this skips a StructReturn, if any, that is present.
|
||||
let sigdata = &self.lower_ctx.sigs()[abi];
|
||||
debug_assert!(num_rets <= sigdata.num_rets());
|
||||
for i in (sigdata.num_rets() - num_rets)..sigdata.num_rets() {
|
||||
// Borrow `sigdata` again so we don't hold a `self`
|
||||
// borrow across the `&mut self` arg to
|
||||
// `abi_arg_slot_regs()` below.
|
||||
let sigdata = &self.lower_ctx.sigs()[abi];
|
||||
let ret = sigdata.get_ret(i);
|
||||
let retval_regs = self.abi_arg_slot_regs(&ret).unwrap();
|
||||
retval_insts.extend(
|
||||
caller
|
||||
|
||||
Reference in New Issue
Block a user