diff --git a/cranelift/codegen/src/isa/x86/abi.rs b/cranelift/codegen/src/isa/x86/abi.rs index 549ec644c7..85e9c18ffd 100644 --- a/cranelift/codegen/src/isa/x86/abi.rs +++ b/cranelift/codegen/src/isa/x86/abi.rs @@ -1,6 +1,8 @@ //! x86 ABI implementation. +use super::super::settings as shared_settings; use super::registers::{FPR, GPR, RU}; +use super::settings as isa_settings; use crate::abi::{legalize_args, ArgAction, ArgAssigner, ValueConversion}; use crate::cursor::{Cursor, CursorPosition, EncCursor}; use crate::ir; @@ -39,10 +41,20 @@ struct Args { fpr_used: usize, offset: u32, call_conv: CallConv, + shared_flags: shared_settings::Flags, + #[allow(dead_code)] + isa_flags: isa_settings::Flags, } 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 { // [1] "The caller is responsible for allocating space for parameters to the callee, // and must always allocate sufficient space to store four register parameters" @@ -61,6 +73,8 @@ impl Args { fpr_used: 0, offset, 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 { let ty = arg.value_type; - // Check for a legal type. - // We don't support SIMD yet, so break all vectors down. + // Vectors should stay in vector registers unless SIMD is not enabled--then they are split 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. @@ -139,7 +158,13 @@ impl ArgAssigner for Args { } /// 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 mut args; @@ -147,14 +172,28 @@ pub fn legalize_signature(sig: &mut ir::Signature, triple: &Triple, _current: bo PointerWidth::U16 => panic!(), PointerWidth::U32 => { bits = 32; - args = Args::new(bits, &[], 0, sig.call_conv); + args = Args::new(bits, &[], 0, sig.call_conv, shared_flags, isa_flags); } PointerWidth::U64 => { bits = 64; 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 { - 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) }; - 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); } diff --git a/cranelift/codegen/src/isa/x86/mod.rs b/cranelift/codegen/src/isa/x86/mod.rs index c71e97410a..dfac5cacc3 100644 --- a/cranelift/codegen/src/isa/x86/mod.rs +++ b/cranelift/codegen/src/isa/x86/mod.rs @@ -106,7 +106,13 @@ impl TargetIsa for Isa { } 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 {