Handle i128 arguments in the aarch64 ABI
When dealing with params that need to be split, we follow the arch64 ABI and split the value in two, and make sure that start that argument in an even numbered xN register. The apple ABI does not require this, so on those platforms, we start params anywhere.
This commit is contained in:
@@ -1572,10 +1572,21 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
||||
// N.B.: according to the AArch64 ABI, the top bits of a register
|
||||
// (above the bits for the value's type) are undefined, so we
|
||||
// need not extend the return values.
|
||||
let reg = put_input_in_reg(ctx, *input, NarrowValueMode::None);
|
||||
let retval_reg = ctx.retval(i).only_reg().unwrap();
|
||||
let src_regs = put_input_in_regs(ctx, *input);
|
||||
let retval_regs = ctx.retval(i);
|
||||
|
||||
assert_eq!(src_regs.len(), retval_regs.len());
|
||||
let ty = ctx.input_ty(insn, i);
|
||||
ctx.emit(Inst::gen_move(retval_reg, reg, ty));
|
||||
let (_, tys) = Inst::rc_for_type(ty)?;
|
||||
|
||||
src_regs
|
||||
.regs()
|
||||
.iter()
|
||||
.zip(retval_regs.regs().iter())
|
||||
.zip(tys.iter())
|
||||
.for_each(|((&src, &dst), &ty)| {
|
||||
ctx.emit(Inst::gen_move(dst, src, ty));
|
||||
});
|
||||
}
|
||||
// N.B.: the Ret itself is generated by the ABI.
|
||||
}
|
||||
@@ -1753,13 +1764,13 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
||||
assert!(inputs.len() == abi.num_args());
|
||||
for i in abi.get_copy_to_arg_order() {
|
||||
let input = inputs[i];
|
||||
let arg_reg = put_input_in_reg(ctx, input, NarrowValueMode::None);
|
||||
abi.emit_copy_regs_to_arg(ctx, i, ValueRegs::one(arg_reg));
|
||||
let arg_regs = put_input_in_regs(ctx, input);
|
||||
abi.emit_copy_regs_to_arg(ctx, i, arg_regs);
|
||||
}
|
||||
abi.emit_call(ctx);
|
||||
for (i, output) in outputs.iter().enumerate() {
|
||||
let retval_reg = get_output_reg(ctx, *output).only_reg().unwrap();
|
||||
abi.emit_copy_retval_to_regs(ctx, i, ValueRegs::one(retval_reg));
|
||||
let retval_regs = get_output_reg(ctx, *output);
|
||||
abi.emit_copy_retval_to_regs(ctx, i, retval_regs);
|
||||
}
|
||||
abi.emit_stack_post_adjust(ctx);
|
||||
}
|
||||
@@ -2306,7 +2317,39 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
||||
panic!("Vector ops not implemented.");
|
||||
}
|
||||
|
||||
Opcode::Isplit | Opcode::Iconcat => panic!("Vector ops not supported."),
|
||||
Opcode::Isplit => {
|
||||
assert_eq!(
|
||||
ctx.input_ty(insn, 0),
|
||||
I128,
|
||||
"Isplit only implemented for i128's"
|
||||
);
|
||||
assert_eq!(ctx.output_ty(insn, 0), I64);
|
||||
assert_eq!(ctx.output_ty(insn, 1), I64);
|
||||
|
||||
let src_regs = put_input_in_regs(ctx, inputs[0]);
|
||||
let dst_lo = get_output_reg(ctx, outputs[0]).only_reg().unwrap();
|
||||
let dst_hi = get_output_reg(ctx, outputs[1]).only_reg().unwrap();
|
||||
|
||||
ctx.emit(Inst::gen_move(dst_lo, src_regs.regs()[0], I64));
|
||||
ctx.emit(Inst::gen_move(dst_hi, src_regs.regs()[1], I64));
|
||||
}
|
||||
|
||||
Opcode::Iconcat => {
|
||||
assert_eq!(
|
||||
ctx.output_ty(insn, 0),
|
||||
I128,
|
||||
"Iconcat only implemented for i128's"
|
||||
);
|
||||
assert_eq!(ctx.input_ty(insn, 0), I64);
|
||||
assert_eq!(ctx.input_ty(insn, 1), I64);
|
||||
|
||||
let src_lo = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
|
||||
let src_hi = put_input_in_reg(ctx, inputs[1], NarrowValueMode::None);
|
||||
let dst = get_output_reg(ctx, outputs[0]);
|
||||
|
||||
ctx.emit(Inst::gen_move(dst.regs()[0], src_lo, I64));
|
||||
ctx.emit(Inst::gen_move(dst.regs()[1], src_hi, I64));
|
||||
}
|
||||
|
||||
Opcode::Imax | Opcode::Umax | Opcode::Umin | Opcode::Imin => {
|
||||
let alu_op = match op {
|
||||
|
||||
Reference in New Issue
Block a user