machinst x64: baldrdash: fix multi-value when both gpr and xmm are returned;

In baldrdash, only the first return value may live in a register, be it
an integer or a floating point value.
This commit is contained in:
Benjamin Bouvier
2020-07-22 11:59:59 +02:00
parent aa103698d4
commit 4b26f5b120

View File

@@ -129,15 +129,19 @@ fn get_fltreg_for_arg_systemv(call_conv: &CallConv, idx: usize) -> Option<Reg> {
} }
} }
fn get_intreg_for_retval_systemv(call_conv: &CallConv, idx: usize) -> Option<Reg> { fn get_intreg_for_retval_systemv(
call_conv: &CallConv,
intreg_idx: usize,
retval_idx: usize,
) -> Option<Reg> {
match call_conv { match call_conv {
CallConv::Fast | CallConv::Cold | CallConv::SystemV => match idx { CallConv::Fast | CallConv::Cold | CallConv::SystemV => match intreg_idx {
0 => Some(regs::rax()), 0 => Some(regs::rax()),
1 => Some(regs::rdx()), 1 => Some(regs::rdx()),
_ => None, _ => None,
}, },
CallConv::BaldrdashSystemV => { CallConv::BaldrdashSystemV => {
if idx == 0 { if intreg_idx == 0 && retval_idx == 0 {
Some(regs::rax()) Some(regs::rax())
} else { } else {
None None
@@ -147,15 +151,19 @@ fn get_intreg_for_retval_systemv(call_conv: &CallConv, idx: usize) -> Option<Reg
} }
} }
fn get_fltreg_for_retval_systemv(call_conv: &CallConv, idx: usize) -> Option<Reg> { fn get_fltreg_for_retval_systemv(
call_conv: &CallConv,
fltreg_idx: usize,
retval_idx: usize,
) -> Option<Reg> {
match call_conv { match call_conv {
CallConv::Fast | CallConv::Cold | CallConv::SystemV => match idx { CallConv::Fast | CallConv::Cold | CallConv::SystemV => match fltreg_idx {
0 => Some(regs::xmm0()), 0 => Some(regs::xmm0()),
1 => Some(regs::xmm1()), 1 => Some(regs::xmm1()),
_ => None, _ => None,
}, },
CallConv::BaldrdashSystemV => { CallConv::BaldrdashSystemV => {
if idx == 0 { if fltreg_idx == 0 && retval_idx == 0 {
Some(regs::xmm0()) Some(regs::xmm0())
} else { } else {
None None
@@ -823,7 +831,7 @@ fn compute_arg_locs(
let (next_reg, candidate) = if intreg { let (next_reg, candidate) = if intreg {
let candidate = match args_or_rets { let candidate = match args_or_rets {
ArgsOrRets::Args => get_intreg_for_arg_systemv(&call_conv, next_gpr), ArgsOrRets::Args => get_intreg_for_arg_systemv(&call_conv, next_gpr),
ArgsOrRets::Rets => get_intreg_for_retval_systemv(&call_conv, next_gpr), ArgsOrRets::Rets => get_intreg_for_retval_systemv(&call_conv, next_gpr, i),
}; };
debug_assert!(candidate debug_assert!(candidate
.map(|r| r.get_class() == RegClass::I64) .map(|r| r.get_class() == RegClass::I64)
@@ -832,7 +840,7 @@ fn compute_arg_locs(
} else { } else {
let candidate = match args_or_rets { let candidate = match args_or_rets {
ArgsOrRets::Args => get_fltreg_for_arg_systemv(&call_conv, next_vreg), ArgsOrRets::Args => get_fltreg_for_arg_systemv(&call_conv, next_vreg),
ArgsOrRets::Rets => get_fltreg_for_retval_systemv(&call_conv, next_vreg), ArgsOrRets::Rets => get_fltreg_for_retval_systemv(&call_conv, next_vreg, i),
}; };
debug_assert!(candidate debug_assert!(candidate
.map(|r| r.get_class() == RegClass::V128) .map(|r| r.get_class() == RegClass::V128)