diff --git a/cranelift/codegen/src/machinst/abi_impl.rs b/cranelift/codegen/src/machinst/abi_impl.rs index fdf9409ae5..b90bc7916b 100644 --- a/cranelift/codegen/src/machinst/abi_impl.rs +++ b/cranelift/codegen/src/machinst/abi_impl.rs @@ -674,11 +674,12 @@ impl ABIBody for ABIBodyImpl { _ => ret.push(M::gen_move(dest_reg, from_reg.to_reg(), ty)), }; } - &ABIArg::Stack(off, ty, ext) => { + &ABIArg::Stack(off, mut ty, ext) => { let from_bits = ty_bits(ty) as u8; // Trash the from_reg; it should be its last use. match (ext, from_bits) { (ArgumentExtension::Uext, n) | (ArgumentExtension::Sext, n) if n < 64 => { + assert_eq!(RegClass::I64, from_reg.to_reg().get_class()); let signed = ext == ArgumentExtension::Sext; ret.push(M::gen_extend( from_reg, @@ -687,6 +688,8 @@ impl ABIBody for ABIBodyImpl { from_bits, /* to_bits = */ 64, )); + // Store the extended version. + ty = I64; } _ => {} }; @@ -1083,7 +1086,7 @@ impl ABICall for ABICallImpl { &ABIArg::Reg(reg, ty, _) => { ctx.emit(M::gen_move(Writable::from_reg(reg.to_reg()), from_reg, ty)); } - &ABIArg::Stack(off, ty, ext) => { + &ABIArg::Stack(off, mut ty, ext) => { if ext != ir::ArgumentExtension::None && ty_bits(ty) < 64 { assert_eq!(RegClass::I64, from_reg.get_class()); let signed = match ext { @@ -1101,6 +1104,8 @@ impl ABICall for ABICallImpl { ty_bits(ty) as u8, 64, )); + // Store the extended version. + ty = I64; } ctx.emit(M::gen_store_stack( StackAMode::SPOffset(off, ty), diff --git a/cranelift/filetests/filetests/vcode/aarch64/call.clif b/cranelift/filetests/filetests/vcode/aarch64/call.clif index 28d75cb36a..cded47dc5b 100644 --- a/cranelift/filetests/filetests/vcode/aarch64/call.clif +++ b/cranelift/filetests/filetests/vcode/aarch64/call.clif @@ -63,7 +63,7 @@ block0(v0: i32): ; nextln: ldp fp, lr, [sp], #16 ; nextln: ret -function %f3(i32) -> i32 sext { +function %f5(i32) -> i32 sext { block0(v0: i32): return v0 } @@ -74,3 +74,59 @@ block0(v0: i32): ; nextln: mov sp, fp ; nextln: ldp fp, lr, [sp], #16 ; nextln: ret + +function %f6(i8) -> i64 { + fn0 = %g(i32, i32, i32, i32, i32, i32, i32, i32, i8 sext) -> i64 + +block0(v0: i8): + v1 = iconst.i32 42 + v2 = call fn0(v1, v1, v1, v1, v1, v1, v1, v1, v0) + return v2 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: mov x8, x0 +; nextln: sub sp, sp, #16 +; nextln: virtual_sp_offset_adjust 16 +; nextln: movz x0, #42 +; nextln: movz x1, #42 +; nextln: movz x2, #42 +; nextln: movz x3, #42 +; nextln: movz x4, #42 +; nextln: movz x5, #42 +; nextln: movz x6, #42 +; nextln: movz x7, #42 +; nextln: sxtb x8, w8 +; nextln: stur x8, [sp] +; nextln: ldr x16, 8 ; b 12 ; data +; nextln: blr x16 +; nextln: add sp, sp, #16 +; nextln: virtual_sp_offset_adjust -16 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f7(i8) -> i32, i32, i32, i32, i32, i32, i32, i32, i8 sext { +block0(v0: i8): + v1 = iconst.i32 42 + return v1, v1, v1, v1, v1, v1, v1, v1, v0 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: mov x9, x0 +; nextln: mov x8, x1 +; nextln: movz x0, #42 +; nextln: movz x1, #42 +; nextln: movz x2, #42 +; nextln: movz x3, #42 +; nextln: movz x4, #42 +; nextln: movz x5, #42 +; nextln: movz x6, #42 +; nextln: movz x7, #42 +; nextln: sxtb x9, w9 +; nextln: stur x9, [x8] +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret