[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,

View File

@@ -125,3 +125,61 @@ block0(v0: i64, v1: i64):
; lmg %r14, %r15, 272(%r15)
; br %r14
function %incoming_args(i64, i32, i32 uext, i32 sext, i16, i16 uext, i16 sext, i8, i8 uext, i8 sext) -> i64 {
block0(v0: i64, v1: i32, v2: i32, v3: i32, v4: i16, v5: i16, v6: i16, v7: i8, v8: i8, v9: i8):
v10 = uextend.i64 v1
v11 = uextend.i64 v2
v12 = uextend.i64 v3
v13 = uextend.i64 v4
v14 = uextend.i64 v5
v15 = uextend.i64 v6
v16 = uextend.i64 v7
v17 = uextend.i64 v8
v18 = uextend.i64 v9
v19 = iadd v0, v10
v20 = iadd v11, v12
v21 = iadd v13, v14
v22 = iadd v15, v16
v23 = iadd v17, v18
v24 = iadd v19, v20
v25 = iadd v21, v22
v26 = iadd v23, v24
v27 = iadd v25, v26
return v27
}
; stmg %r7, %r15, 56(%r15)
; aghi %r15, -16
; block0:
; stg %r4, 8(%r15)
; lgr %r10, %r5
; lg %r11, 176(%r15)
; lg %r12, 184(%r15)
; llgc %r13, 199(%r15)
; lg %r8, 200(%r15)
; lg %r7, 208(%r15)
; llgfr %r4, %r3
; lg %r5, 8(%r15)
; llgfr %r5, %r5
; lgr %r3, %r10
; llgfr %r3, %r3
; llghr %r9, %r6
; llghr %r10, %r11
; llghr %r11, %r12
; llgcr %r12, %r13
; llgcr %r8, %r8
; llgcr %r13, %r7
; agrk %r4, %r2, %r4
; agr %r5, %r3
; agrk %r2, %r9, %r10
; agrk %r3, %r11, %r12
; agr %r8, %r13
; agr %r4, %r5
; agrk %r5, %r2, %r3
; agrk %r4, %r8, %r4
; agrk %r2, %r5, %r4
; lmg %r7, %r15, 72(%r15)
; br %r14