Assign vector arguments to FPR registers
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
//! x86 ABI implementation.
|
//! x86 ABI implementation.
|
||||||
|
|
||||||
|
use super::super::settings as shared_settings;
|
||||||
use super::registers::{FPR, GPR, RU};
|
use super::registers::{FPR, GPR, RU};
|
||||||
|
use super::settings as isa_settings;
|
||||||
use crate::abi::{legalize_args, ArgAction, ArgAssigner, ValueConversion};
|
use crate::abi::{legalize_args, ArgAction, ArgAssigner, ValueConversion};
|
||||||
use crate::cursor::{Cursor, CursorPosition, EncCursor};
|
use crate::cursor::{Cursor, CursorPosition, EncCursor};
|
||||||
use crate::ir;
|
use crate::ir;
|
||||||
@@ -39,10 +41,20 @@ struct Args {
|
|||||||
fpr_used: usize,
|
fpr_used: usize,
|
||||||
offset: u32,
|
offset: u32,
|
||||||
call_conv: CallConv,
|
call_conv: CallConv,
|
||||||
|
shared_flags: shared_settings::Flags,
|
||||||
|
#[allow(dead_code)]
|
||||||
|
isa_flags: isa_settings::Flags,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Args {
|
impl Args {
|
||||||
fn new(bits: u8, gpr: &'static [RU], fpr_limit: usize, call_conv: CallConv) -> Self {
|
fn new(
|
||||||
|
bits: u8,
|
||||||
|
gpr: &'static [RU],
|
||||||
|
fpr_limit: usize,
|
||||||
|
call_conv: CallConv,
|
||||||
|
shared_flags: &shared_settings::Flags,
|
||||||
|
isa_flags: &isa_settings::Flags,
|
||||||
|
) -> Self {
|
||||||
let offset = if let CallConv::WindowsFastcall = call_conv {
|
let offset = if let CallConv::WindowsFastcall = call_conv {
|
||||||
// [1] "The caller is responsible for allocating space for parameters to the callee,
|
// [1] "The caller is responsible for allocating space for parameters to the callee,
|
||||||
// and must always allocate sufficient space to store four register parameters"
|
// and must always allocate sufficient space to store four register parameters"
|
||||||
@@ -61,6 +73,8 @@ impl Args {
|
|||||||
fpr_used: 0,
|
fpr_used: 0,
|
||||||
offset,
|
offset,
|
||||||
call_conv,
|
call_conv,
|
||||||
|
shared_flags: shared_flags.clone(),
|
||||||
|
isa_flags: isa_flags.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -69,10 +83,15 @@ impl ArgAssigner for Args {
|
|||||||
fn assign(&mut self, arg: &AbiParam) -> ArgAction {
|
fn assign(&mut self, arg: &AbiParam) -> ArgAction {
|
||||||
let ty = arg.value_type;
|
let ty = arg.value_type;
|
||||||
|
|
||||||
// Check for a legal type.
|
// Vectors should stay in vector registers unless SIMD is not enabled--then they are split
|
||||||
// We don't support SIMD yet, so break all vectors down.
|
|
||||||
if ty.is_vector() {
|
if ty.is_vector() {
|
||||||
return ValueConversion::VectorSplit.into();
|
if self.shared_flags.enable_simd() {
|
||||||
|
let reg = FPR.unit(self.fpr_used);
|
||||||
|
self.fpr_used += 1;
|
||||||
|
return ArgumentLoc::Reg(reg).into();
|
||||||
|
} else {
|
||||||
|
return ValueConversion::VectorSplit.into();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Large integers and booleans are broken down to fit in a register.
|
// Large integers and booleans are broken down to fit in a register.
|
||||||
@@ -139,7 +158,13 @@ impl ArgAssigner for Args {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Legalize `sig`.
|
/// Legalize `sig`.
|
||||||
pub fn legalize_signature(sig: &mut ir::Signature, triple: &Triple, _current: bool) {
|
pub fn legalize_signature(
|
||||||
|
sig: &mut ir::Signature,
|
||||||
|
triple: &Triple,
|
||||||
|
_current: bool,
|
||||||
|
shared_flags: &shared_settings::Flags,
|
||||||
|
isa_flags: &isa_settings::Flags,
|
||||||
|
) {
|
||||||
let bits;
|
let bits;
|
||||||
let mut args;
|
let mut args;
|
||||||
|
|
||||||
@@ -147,14 +172,28 @@ pub fn legalize_signature(sig: &mut ir::Signature, triple: &Triple, _current: bo
|
|||||||
PointerWidth::U16 => panic!(),
|
PointerWidth::U16 => panic!(),
|
||||||
PointerWidth::U32 => {
|
PointerWidth::U32 => {
|
||||||
bits = 32;
|
bits = 32;
|
||||||
args = Args::new(bits, &[], 0, sig.call_conv);
|
args = Args::new(bits, &[], 0, sig.call_conv, shared_flags, isa_flags);
|
||||||
}
|
}
|
||||||
PointerWidth::U64 => {
|
PointerWidth::U64 => {
|
||||||
bits = 64;
|
bits = 64;
|
||||||
args = if sig.call_conv == CallConv::WindowsFastcall {
|
args = if sig.call_conv == CallConv::WindowsFastcall {
|
||||||
Args::new(bits, &ARG_GPRS_WIN_FASTCALL_X64[..], 4, sig.call_conv)
|
Args::new(
|
||||||
|
bits,
|
||||||
|
&ARG_GPRS_WIN_FASTCALL_X64[..],
|
||||||
|
4,
|
||||||
|
sig.call_conv,
|
||||||
|
shared_flags,
|
||||||
|
isa_flags,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
Args::new(bits, &ARG_GPRS[..], 8, sig.call_conv)
|
Args::new(
|
||||||
|
bits,
|
||||||
|
&ARG_GPRS[..],
|
||||||
|
8,
|
||||||
|
sig.call_conv,
|
||||||
|
shared_flags,
|
||||||
|
isa_flags,
|
||||||
|
)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -168,7 +207,14 @@ pub fn legalize_signature(sig: &mut ir::Signature, triple: &Triple, _current: bo
|
|||||||
(&RET_GPRS[..], 2)
|
(&RET_GPRS[..], 2)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut rets = Args::new(bits, regs, fpr_limit, sig.call_conv);
|
let mut rets = Args::new(
|
||||||
|
bits,
|
||||||
|
regs,
|
||||||
|
fpr_limit,
|
||||||
|
sig.call_conv,
|
||||||
|
shared_flags,
|
||||||
|
isa_flags,
|
||||||
|
);
|
||||||
legalize_args(&mut sig.returns, &mut rets);
|
legalize_args(&mut sig.returns, &mut rets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -106,7 +106,13 @@ impl TargetIsa for Isa {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn legalize_signature(&self, sig: &mut ir::Signature, current: bool) {
|
fn legalize_signature(&self, sig: &mut ir::Signature, current: bool) {
|
||||||
abi::legalize_signature(sig, &self.triple, current)
|
abi::legalize_signature(
|
||||||
|
sig,
|
||||||
|
&self.triple,
|
||||||
|
current,
|
||||||
|
&self.shared_flags,
|
||||||
|
&self.isa_flags,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn regclass_for_abi_type(&self, ty: ir::Type) -> RegClass {
|
fn regclass_for_abi_type(&self, ty: ir::Type) -> RegClass {
|
||||||
|
|||||||
Reference in New Issue
Block a user