[abi_impl] Respect extension for incoming stack arguments (#4576)

The gen_copy_arg_to_regs routine currently ignores argument extension
flags when loading incoming arguments.  This causes a problem with
stack arguments on big-endian systems, since the argument address
points to the word on the stack as extended by the caller, but the
generated code only loads the inner type from the address, causing
it to receive an incorrect value.  (This happens to work on little-
endian systems.)

Fixed by loading extended arguments as full words.
This commit is contained in:
Ulrich Weigand
2022-08-02 22:54:13 +02:00
committed by GitHub
parent ee5b192d35
commit 6b4e6523f7
2 changed files with 77 additions and 3 deletions

View File

@@ -1095,12 +1095,28 @@ impl<M: ABIMachineSpec> ABICallee for ABICalleeImpl<M> {
assert_eq!(into_regs.len(), slots.len());
for (slot, into_reg) in slots.iter().zip(into_regs.regs().iter()) {
match slot {
// Extension mode doesn't matter (we're copying out, not in; we
// ignore high bits by convention).
&ABIArgSlot::Reg { reg, ty, .. } => {
// Extension mode doesn't matter (we're copying out, not in; we
// ignore high bits by convention).
insts.push(M::gen_move(*into_reg, reg.into(), ty));
}
&ABIArgSlot::Stack { offset, ty, .. } => {
&ABIArgSlot::Stack {
offset,
ty,
extension,
..
} => {
// However, we have to respect the extention mode for stack
// slots, or else we grab the wrong bytes on big-endian.
let ext = M::get_ext_mode(self.sig.call_conv, extension);
let ty = match (ext, ty_bits(ty) as u32) {
(ArgumentExtension::Uext, n) | (ArgumentExtension::Sext, n)
if n < M::word_bits() =>
{
M::word_type()
}
_ => ty,
};
insts.push(M::gen_load_stack(
StackAMode::FPOffset(
M::fp_to_arg_offset(self.call_conv, &self.flags) + offset,