Implement a Windows Baldrdash calling convention;

This commit is contained in:
Benjamin Bouvier
2019-08-14 10:39:18 +02:00
parent d8d3602257
commit 2ee35b7ea1
21 changed files with 92 additions and 55 deletions

View File

@@ -373,7 +373,8 @@ mod tests {
CallConv::Cold,
CallConv::SystemV,
CallConv::WindowsFastcall,
CallConv::Baldrdash,
CallConv::BaldrdashSystemV,
CallConv::BaldrdashWindows,
] {
assert_eq!(Ok(cc), cc.to_string().parse())
}
@@ -381,16 +382,19 @@ mod tests {
#[test]
fn signatures() {
let mut sig = Signature::new(CallConv::Baldrdash);
assert_eq!(sig.to_string(), "() baldrdash");
let mut sig = Signature::new(CallConv::BaldrdashSystemV);
assert_eq!(sig.to_string(), "() baldrdash_system_v");
sig.params.push(AbiParam::new(I32));
assert_eq!(sig.to_string(), "(i32) baldrdash");
assert_eq!(sig.to_string(), "(i32) baldrdash_system_v");
sig.returns.push(AbiParam::new(F32));
assert_eq!(sig.to_string(), "(i32) -> f32 baldrdash");
assert_eq!(sig.to_string(), "(i32) -> f32 baldrdash_system_v");
sig.params.push(AbiParam::new(I32.by(4).unwrap()));
assert_eq!(sig.to_string(), "(i32, i32x4) -> f32 baldrdash");
assert_eq!(sig.to_string(), "(i32, i32x4) -> f32 baldrdash_system_v");
sig.returns.push(AbiParam::new(B8));
assert_eq!(sig.to_string(), "(i32, i32x4) -> f32, b8 baldrdash");
assert_eq!(
sig.to_string(),
"(i32, i32x4) -> f32, b8 baldrdash_system_v"
);
// Order does not matter.
sig.params[0].location = ArgumentLoc::Stack(24);
@@ -399,7 +403,7 @@ mod tests {
// Writing ABI-annotated signatures.
assert_eq!(
sig.to_string(),
"(i32 [24], i32x4 [8]) -> f32, b8 baldrdash"
"(i32 [24], i32x4 [8]) -> f32, b8 baldrdash_system_v"
);
}
}

View File

@@ -179,7 +179,7 @@ fn make_funcref_for_inst(
sig.returns.push(AbiParam::new(func.dfg.value_type(v)));
}
if call_conv == CallConv::Baldrdash {
if call_conv.extends_baldrdash() {
// Adds the special VMContext parameter to the signature.
sig.params.push(AbiParam::special(
isa.pointer_type(),

View File

@@ -15,8 +15,10 @@ pub enum CallConv {
SystemV,
/// Windows "fastcall" convention, also used for x64 and ARM
WindowsFastcall,
/// SpiderMonkey WebAssembly convention
Baldrdash,
/// SpiderMonkey WebAssembly convention on systems using natively SystemV
BaldrdashSystemV,
/// SpiderMonkey WebAssembly convention on Windows
BaldrdashWindows,
/// Specialized convention for the probestack function
Probestack,
}
@@ -40,10 +42,27 @@ impl CallConv {
LibcallCallConv::Cold => CallConv::Cold,
LibcallCallConv::SystemV => CallConv::SystemV,
LibcallCallConv::WindowsFastcall => CallConv::WindowsFastcall,
LibcallCallConv::Baldrdash => CallConv::Baldrdash,
LibcallCallConv::BaldrdashSystemV => CallConv::BaldrdashSystemV,
LibcallCallConv::BaldrdashWindows => CallConv::BaldrdashWindows,
LibcallCallConv::Probestack => CallConv::Probestack,
}
}
/// Is the calling convention extending the Windows Fastcall ABI?
pub fn extends_windows_fastcall(&self) -> bool {
match self {
CallConv::WindowsFastcall | CallConv::BaldrdashWindows => true,
_ => false,
}
}
/// Is the calling convention extending the Baldrdash ABI?
pub fn extends_baldrdash(&self) -> bool {
match self {
CallConv::BaldrdashSystemV | CallConv::BaldrdashWindows => true,
_ => false,
}
}
}
impl fmt::Display for CallConv {
@@ -53,7 +72,8 @@ impl fmt::Display for CallConv {
CallConv::Cold => "cold",
CallConv::SystemV => "system_v",
CallConv::WindowsFastcall => "windows_fastcall",
CallConv::Baldrdash => "baldrdash",
CallConv::BaldrdashSystemV => "baldrdash_system_v",
CallConv::BaldrdashWindows => "baldrdash_windows",
CallConv::Probestack => "probestack",
})
}
@@ -67,7 +87,8 @@ impl str::FromStr for CallConv {
"cold" => Ok(CallConv::Cold),
"system_v" => Ok(CallConv::SystemV),
"windows_fastcall" => Ok(CallConv::WindowsFastcall),
"baldrdash" => Ok(CallConv::Baldrdash),
"baldrdash_system_v" => Ok(CallConv::BaldrdashSystemV),
"baldrdash_windows" => Ok(CallConv::BaldrdashWindows),
"probestack" => Ok(CallConv::Probestack),
_ => Err(()),
}

View File

@@ -343,7 +343,7 @@ pub trait TargetIsa: fmt::Display + Sync {
let word_size = StackSize::from(self.pointer_bytes());
// Account for the SpiderMonkey standard prologue pushes.
if func.signature.call_conv == CallConv::Baldrdash {
if func.signature.call_conv.extends_baldrdash() {
let bytes = StackSize::from(self.flags().baldrdash_prologue_words()) * word_size;
let mut ss = ir::StackSlotData::new(ir::StackSlotKind::IncomingArg, bytes);
ss.offset = Some(-(bytes as StackOffset));

View File

@@ -55,7 +55,7 @@ impl Args {
shared_flags: &shared_settings::Flags,
isa_flags: &isa_settings::Flags,
) -> Self {
let offset = if let CallConv::WindowsFastcall = call_conv {
let offset = if call_conv.extends_windows_fastcall() {
// [1] "The caller is responsible for allocating space for parameters to the callee,
// and must always allocate sufficient space to store four register parameters"
32
@@ -109,7 +109,7 @@ impl ArgAssigner for Args {
}
// Handle special-purpose arguments.
if ty.is_int() && self.call_conv == CallConv::Baldrdash {
if ty.is_int() && self.call_conv.extends_baldrdash() {
match arg.purpose {
// This is SpiderMonkey's `WasmTlsReg`.
ArgumentPurpose::VMContext => {
@@ -134,7 +134,7 @@ impl ArgAssigner for Args {
}
// Try to use an FPR.
let fpr_offset = if self.call_conv == CallConv::WindowsFastcall {
let fpr_offset = if self.call_conv.extends_windows_fastcall() {
// Float and general registers on windows share the same parameter index.
// The used register depends entirely on the parameter index: Even if XMM0
// is not used for the first parameter, it cannot be used for the second parameter.
@@ -143,6 +143,7 @@ impl ArgAssigner for Args {
} else {
&mut self.fpr_used
};
if ty.is_float() && *fpr_offset < self.fpr_limit {
let reg = FPR.unit(*fpr_offset);
*fpr_offset += 1;
@@ -176,7 +177,7 @@ pub fn legalize_signature(
}
PointerWidth::U64 => {
bits = 64;
args = if sig.call_conv == CallConv::WindowsFastcall {
args = if sig.call_conv.extends_windows_fastcall() {
Args::new(
bits,
&ARG_GPRS_WIN_FASTCALL_X64[..],
@@ -200,7 +201,7 @@ pub fn legalize_signature(
legalize_args(&mut sig.params, &mut args);
let (regs, fpr_limit) = if sig.call_conv == CallConv::WindowsFastcall {
let (regs, fpr_limit) = if sig.call_conv.extends_windows_fastcall() {
// windows-x64 calling convention only uses XMM0 or RAX for return values
(&RET_GPRS_WIN_FASTCALL_X64[..], 1)
} else {
@@ -250,7 +251,7 @@ fn callee_saved_gprs(isa: &dyn TargetIsa, call_conv: CallConv) -> &'static [RU]
PointerWidth::U16 => panic!(),
PointerWidth::U32 => &[RU::rbx, RU::rsi, RU::rdi],
PointerWidth::U64 => {
if call_conv == CallConv::WindowsFastcall {
if call_conv.extends_windows_fastcall() {
// "registers RBX, RBP, RDI, RSI, RSP, R12, R13, R14, R15 are considered nonvolatile
// and must be saved and restored by a function that uses them."
// as per https://msdn.microsoft.com/en-us/library/6t169e9c.aspx
@@ -322,7 +323,9 @@ pub fn prologue_epilogue(func: &mut ir::Function, isa: &dyn TargetIsa) -> Codege
system_v_prologue_epilogue(func, isa)
}
CallConv::WindowsFastcall => fastcall_prologue_epilogue(func, isa),
CallConv::Baldrdash => baldrdash_prologue_epilogue(func, isa),
CallConv::BaldrdashSystemV | CallConv::BaldrdashWindows => {
baldrdash_prologue_epilogue(func, isa)
}
CallConv::Probestack => unimplemented!("probestack calling convention"),
}
}
@@ -336,7 +339,14 @@ fn baldrdash_prologue_epilogue(func: &mut ir::Function, isa: &dyn TargetIsa) ->
// Baldrdash on 32-bit x86 always aligns its stack pointer to 16 bytes.
let stack_align = 16;
let word_size = StackSize::from(isa.pointer_bytes());
let bytes = StackSize::from(isa.flags().baldrdash_prologue_words()) * word_size;
let shadow_store_size = if func.signature.call_conv.extends_windows_fastcall() {
32
} else {
0
};
let bytes =
StackSize::from(isa.flags().baldrdash_prologue_words()) * word_size + shadow_store_size;
let mut ss = ir::StackSlotData::new(ir::StackSlotKind::IncomingArg, bytes);
ss.offset = Some(-(bytes as StackOffset));

View File

@@ -20,7 +20,7 @@ pub fn expand_as_libcall(inst: ir::Inst, func: &mut ir::Function, isa: &dyn Targ
args.extend_from_slice(func.dfg.inst_args(inst));
let call_conv = CallConv::for_libcall(isa);
if call_conv == CallConv::Baldrdash {
if call_conv.extends_baldrdash() {
let vmctx = func
.special_param(ir::ArgumentPurpose::VMContext)
.expect("Missing vmctx parameter for baldrdash libcall");