Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial support for x64 windows calling convention on the single pass compiler #1998

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 16 additions & 17 deletions lib/compiler-singlepass/src/codegen_x64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -956,13 +956,13 @@ impl<'a> FuncGen<'a> {
Ok(())
}

/// Emits a System V call sequence.
/// Emits a System V or Windows x64 call sequence.
///
/// This function will not use RAX before `cb` is called.
///
/// The caller MUST NOT hold any temporary registers allocated by `acquire_temp_gpr` when calling
/// this function.
fn emit_call_sysv<I: Iterator<Item = Location>, F: FnOnce(&mut Self)>(
fn emit_call<I: Iterator<Item = Location>, F: FnOnce(&mut Self)>(
&mut self,
cb: F,
params: I,
Expand All @@ -983,7 +983,7 @@ impl<'a> FuncGen<'a> {
self.machine.state.register_values[X64Register::GPR(*r).to_index().0].clone();
if content == MachineValue::Undefined {
return Err(CodegenError {
message: "emit_call_sysv: Undefined used_gprs content".to_string(),
message: "emit_call: Undefined used_gprs content".to_string(),
});
}
self.machine.state.stack_values.push(content);
Expand All @@ -1010,7 +1010,7 @@ impl<'a> FuncGen<'a> {
self.machine.state.register_values[X64Register::XMM(*r).to_index().0].clone();
if content == MachineValue::Undefined {
return Err(CodegenError {
message: "emit_call_sysv: Undefined used_xmms content".to_string(),
message: "emit_call: Undefined used_xmms content".to_string(),
});
}
self.machine.state.stack_values.push(content);
Expand Down Expand Up @@ -1058,7 +1058,7 @@ impl<'a> FuncGen<'a> {
let content = self.machine.state.register_values
[X64Register::GPR(x).to_index().0]
.clone();
// FIXME: There might be some corner cases (release -> emit_call_sysv -> acquire?) that cause this assertion to fail.
// FIXME: There might be some corner cases (release -> emit_call -> acquire?) that cause this assertion to fail.
// Hopefully nothing would be incorrect at runtime.

//assert!(content != MachineValue::Undefined);
Expand All @@ -1074,8 +1074,7 @@ impl<'a> FuncGen<'a> {
Location::Memory(reg, offset) => {
if reg != GPR::RBP {
return Err(CodegenError {
message: "emit_call_sysv loc param: unreachable code"
.to_string(),
message: "emit_call loc param: unreachable code".to_string(),
});
}
self.machine
Expand Down Expand Up @@ -1125,7 +1124,7 @@ impl<'a> FuncGen<'a> {
}
_ => {
return Err(CodegenError {
message: "emit_call_sysv loc: unreachable code".to_string(),
message: "emit_call loc: unreachable code".to_string(),
})
}
}
Expand All @@ -1150,7 +1149,7 @@ impl<'a> FuncGen<'a> {

if (self.machine.state.stack_values.len() % 2) != 1 {
return Err(CodegenError {
message: "emit_call_sysv: explicit shadow takes one slot".to_string(),
message: "emit_call: explicit shadow takes one slot".to_string(),
});
}

Expand Down Expand Up @@ -1184,7 +1183,7 @@ impl<'a> FuncGen<'a> {
);
if (stack_offset % 8) != 0 {
return Err(CodegenError {
message: "emit_call_sysv: Bad restoring stack alignement".to_string(),
message: "emit_call: Bad restoring stack alignement".to_string(),
});
}
for _ in 0..stack_offset / 8 {
Expand Down Expand Up @@ -1219,7 +1218,7 @@ impl<'a> FuncGen<'a> {

if self.machine.state.stack_values.pop().unwrap() != MachineValue::ExplicitShadow {
return Err(CodegenError {
message: "emit_call_sysv: Popped value is not ExplicitShadow".to_string(),
message: "emit_call: Popped value is not ExplicitShadow".to_string(),
});
}
Ok(())
Expand All @@ -1231,7 +1230,7 @@ impl<'a> FuncGen<'a> {
label: DynamicLabel,
params: I,
) -> Result<(), CodegenError> {
self.emit_call_sysv(|this| this.assembler.emit_call_label(label), params)?;
self.emit_call(|this| this.assembler.emit_call_label(label), params)?;
Ok(())
}

Expand Down Expand Up @@ -5202,15 +5201,15 @@ impl<'a> FuncGen<'a> {
addend: 0,
});

// RAX is preserved on entry to `emit_call_sysv` callback.
// RAX is preserved on entry to `emit_call` callback.
// The Imm64 value is relocated by the JIT linker.
self.assembler.emit_mov(
Size::S64,
Location::Imm64(std::u64::MAX),
Location::GPR(GPR::RAX),
);

self.emit_call_sysv(
self.emit_call(
|this| {
let offset = this.assembler.get_offset().0;
this.trap_table
Expand Down Expand Up @@ -5400,7 +5399,7 @@ impl<'a> FuncGen<'a> {
let vmcaller_checked_anyfunc_func_ptr =
self.vmoffsets.vmcaller_checked_anyfunc_func_ptr() as usize;

self.emit_call_sysv(
self.emit_call(
|this| {
if this.assembler.arch_requires_indirect_call_trampoline() {
this.assembler.arch_emit_indirect_call_with_trampoline(
Expand Down Expand Up @@ -5672,7 +5671,7 @@ impl<'a> FuncGen<'a> {
),
Location::GPR(GPR::RAX),
);
self.emit_call_sysv(
self.emit_call(
|this| {
let label = this.assembler.get_label();
let after = this.assembler.get_label();
Expand Down Expand Up @@ -5717,7 +5716,7 @@ impl<'a> FuncGen<'a> {

self.machine.release_locations_only_osr_state(1);

self.emit_call_sysv(
self.emit_call(
|this| {
let label = this.assembler.get_label();
let after = this.assembler.get_label();
Expand Down
5 changes: 0 additions & 5 deletions lib/compiler-singlepass/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,6 @@ impl Compiler for SinglepassCompiler {
_module_translation: &ModuleTranslationState,
function_body_inputs: PrimaryMap<LocalFunctionIndex, FunctionBodyData<'_>>,
) -> Result<Compilation, CompileError> {
if target.triple().operating_system == OperatingSystem::Windows {
return Err(CompileError::UnsupportedTarget(
OperatingSystem::Windows.to_string(),
));
}
if let Architecture::X86_32(arch) = target.triple().architecture {
return Err(CompileError::UnsupportedTarget(arch.to_string()));
}
Expand Down
27 changes: 26 additions & 1 deletion lib/compiler-singlepass/src/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,12 @@ impl Machine {
/// This method does not mark the register as used.
pub fn pick_gpr(&self) -> Option<GPR> {
use GPR::*;

#[cfg(not(target_os = "windows"))]
static REGS: &[GPR] = &[RSI, RDI, R8, R9, R10, R11];
#[cfg(target_os = "windows")]
static REGS: &[GPR] = &[RCX, RDX, R8, R9];

for r in REGS {
if !self.used_gprs.contains(r) {
return Some(*r);
Expand All @@ -64,7 +69,10 @@ impl Machine {
/// This method does not mark the register as used.
pub fn pick_temp_gpr(&self) -> Option<GPR> {
use GPR::*;
static REGS: &[GPR] = &[RAX, RCX, RDX];
#[cfg(not(target_os = "windows"))]
static REGS: &[GPR] = &[RDI, RSI, RBX, R10, R11, R12, R13, R14, R15];
#[cfg(target_os = "windows")]
static REGS: &[GPR] = &[RAX, RCX, RDX, R8, R9, R10, R11];
for r in REGS {
if !self.used_gprs.contains(r) {
return Some(*r);
Expand Down Expand Up @@ -99,7 +107,12 @@ impl Machine {
/// This method does not mark the register as used.
pub fn pick_xmm(&self) -> Option<XMM> {
use XMM::*;

#[cfg(not(target_os = "windows"))]
static REGS: &[XMM] = &[XMM3, XMM4, XMM5, XMM6, XMM7];
#[cfg(target_os = "windows")]
static REGS: &[XMM] = &[XMM3, XMM4, XMM5];

for r in REGS {
if !self.used_xmms.contains(r) {
return Some(*r);
Expand Down Expand Up @@ -487,6 +500,7 @@ impl Machine {
}
}

#[cfg(not(target_os = "windows"))]
pub fn get_param_location(idx: usize) -> Location {
match idx {
0 => Location::GPR(GPR::RDI),
Expand All @@ -498,6 +512,17 @@ impl Machine {
_ => Location::Memory(GPR::RBP, (16 + (idx - 6) * 8) as i32),
}
}

#[cfg(target_os = "windows")]
pub fn get_param_location(idx: usize) -> Location {
match idx {
0 => Location::GPR(GPR::RCX),
1 => Location::GPR(GPR::RDX),
2 => Location::GPR(GPR::R8),
3 => Location::GPR(GPR::R9),
_ => Location::Memory(GPR::RBP, (16 + (idx - 4) * 8) as i32),
}
}
}

#[cfg(test)]
Expand Down