Skip to content
This repository was archived by the owner on Jun 26, 2020. It is now read-only.
64 changes: 55 additions & 9 deletions cranelift-codegen/src/isa/x86/abi.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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"
Expand All @@ -61,6 +73,8 @@ impl Args {
fpr_used: 0,
offset,
call_conv,
shared_flags: shared_flags.clone(),
isa_flags: isa_flags.clone(),
}
}
}
Expand All @@ -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.
Expand Down Expand Up @@ -139,22 +158,42 @@ 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;

match triple.pointer_width().unwrap() {
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,
)
};
}
}
Expand All @@ -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);
}

Expand Down
8 changes: 7 additions & 1 deletion cranelift-codegen/src/isa/x86/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down