diff --git a/cranelift/codegen/src/machinst/abi_impl.rs b/cranelift/codegen/src/machinst/abi_impl.rs index 3ab06f397e..203efe78cd 100644 --- a/cranelift/codegen/src/machinst/abi_impl.rs +++ b/cranelift/codegen/src/machinst/abi_impl.rs @@ -1095,12 +1095,28 @@ impl ABICallee for ABICalleeImpl { 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, diff --git a/cranelift/filetests/filetests/isa/s390x/call.clif b/cranelift/filetests/filetests/isa/s390x/call.clif index bd3648316b..3df63e9f65 100644 --- a/cranelift/filetests/filetests/isa/s390x/call.clif +++ b/cranelift/filetests/filetests/isa/s390x/call.clif @@ -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 +