[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());
|
assert_eq!(into_regs.len(), slots.len());
|
||||||
for (slot, into_reg) in slots.iter().zip(into_regs.regs().iter()) {
|
for (slot, into_reg) in slots.iter().zip(into_regs.regs().iter()) {
|
||||||
match slot {
|
match slot {
|
||||||
|
&ABIArgSlot::Reg { reg, ty, .. } => {
|
||||||
// Extension mode doesn't matter (we're copying out, not in; we
|
// Extension mode doesn't matter (we're copying out, not in; we
|
||||||
// ignore high bits by convention).
|
// ignore high bits by convention).
|
||||||
&ABIArgSlot::Reg { reg, ty, .. } => {
|
|
||||||
insts.push(M::gen_move(*into_reg, reg.into(), ty));
|
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(
|
insts.push(M::gen_load_stack(
|
||||||
StackAMode::FPOffset(
|
StackAMode::FPOffset(
|
||||||
M::fp_to_arg_offset(self.call_conv, &self.flags) + offset,
|
M::fp_to_arg_offset(self.call_conv, &self.flags) + offset,
|
||||||
|
|||||||
@@ -125,3 +125,61 @@ block0(v0: i64, v1: i64):
|
|||||||
; lmg %r14, %r15, 272(%r15)
|
; lmg %r14, %r15, 272(%r15)
|
||||||
; br %r14
|
; 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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user