[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:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user