Skip to content

Commit

Permalink
Windows FPRs preservation (#1216)
Browse files Browse the repository at this point in the history
Preserve FPRs as required by the Windows fastcall calling convention.

This exposes an implementation limit due to Cranelift's approach to stack layout, which conflicts with expectations Windows makes in SEH layout - functions where the Cranelift user desires fastcall unwind information, that require preservation of an ABI-reserved FPR, that have a stack frame 240 bytes or larger, now produce an error when compiled. Several wasm spectests were disabled because they would trip this limit. This is a temporary constraint that should be fixed promptly.

Co-authored-by: bjorn3 <bjorn3@users.noreply.github.com>
  • Loading branch information
iximeow and bjorn3 authored Apr 10, 2020
1 parent 7eea5d8 commit 4cca510
Show file tree
Hide file tree
Showing 15 changed files with 610 additions and 76 deletions.
11 changes: 11 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,17 @@ fn ignore(testsuite: &str, testname: &str, strategy: &str) -> bool {
("reference_types", "table_copy_on_imported_tables") => return false,
("reference_types", _) => return true,

("misc_testsuite", "export_large_signature")
| ("spec_testsuite", "call")
| ("multi_value", "call")
| ("multi_value", "func") => {
// FIXME These involves functions with very large stack frames that Cranelift currently
// cannot compile using the fastcall (Windows) calling convention.
// See https://github.com/bytecodealliance/wasmtime/pull/1216.
#[cfg(windows)]
return true;
}

_ => {}
},
_ => panic!("unrecognized strategy"),
Expand Down
4 changes: 2 additions & 2 deletions cranelift/codegen/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,8 @@ impl Context {
isa: &dyn TargetIsa,
kind: FrameUnwindKind,
sink: &mut dyn FrameUnwindSink,
) {
isa.emit_unwind_info(&self.func, kind, sink);
) -> CodegenResult<()> {
isa.emit_unwind_info(&self.func, kind, sink)
}

/// Run the verifier on the function.
Expand Down
3 changes: 2 additions & 1 deletion cranelift/codegen/src/isa/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,8 +398,9 @@ pub trait TargetIsa: fmt::Display + Send + Sync {
_func: &ir::Function,
_kind: binemit::FrameUnwindKind,
_sink: &mut dyn binemit::FrameUnwindSink,
) {
) -> CodegenResult<()> {
// No-op by default
Ok(())
}
}

Expand Down
241 changes: 220 additions & 21 deletions cranelift/codegen/src/isa/x86/abi.rs

Large diffs are not rendered by default.

13 changes: 10 additions & 3 deletions cranelift/codegen/src/isa/x86/fde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::binemit::{FrameUnwindOffset, FrameUnwindSink, Reloc};
use crate::ir::{FrameLayoutChange, Function};
use crate::isa::fde::RegisterMappingError;
use crate::isa::{CallConv, RegUnit, TargetIsa};
use crate::result::CodegenResult;
use alloc::vec::Vec;
use core::convert::TryInto;
use gimli::write::{
Expand Down Expand Up @@ -178,7 +179,11 @@ fn to_cfi(
}

/// Creates FDE structure from FrameLayout.
pub fn emit_fde(func: &Function, isa: &dyn TargetIsa, sink: &mut dyn FrameUnwindSink) {
pub fn emit_fde(
func: &Function,
isa: &dyn TargetIsa,
sink: &mut dyn FrameUnwindSink,
) -> CodegenResult<()> {
assert!(isa.name() == "x86");

// Expecting function with System V prologue
Expand Down Expand Up @@ -266,6 +271,8 @@ pub fn emit_fde(func: &Function, isa: &dyn TargetIsa, sink: &mut dyn FrameUnwind

// Need 0 marker for GCC unwind to end FDE "list".
sink.bytes(&[0, 0, 0, 0]);

Ok(())
}

#[cfg(test)]
Expand Down Expand Up @@ -314,7 +321,7 @@ mod tests {
context.compile(&*isa).expect("expected compilation");

let mut sink = SimpleUnwindSink(Vec::new(), 0, Vec::new());
emit_fde(&context.func, &*isa, &mut sink);
emit_fde(&context.func, &*isa, &mut sink).expect("can emit fde");

assert_eq!(
sink.0,
Expand Down Expand Up @@ -376,7 +383,7 @@ mod tests {
context.compile(&*isa).expect("expected compilation");

let mut sink = SimpleUnwindSink(Vec::new(), 0, Vec::new());
emit_fde(&context.func, &*isa, &mut sink);
emit_fde(&context.func, &*isa, &mut sink).expect("can emit fde");

assert_eq!(
sink.0,
Expand Down
4 changes: 2 additions & 2 deletions cranelift/codegen/src/isa/x86/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,8 @@ impl TargetIsa for Isa {
func: &ir::Function,
kind: FrameUnwindKind,
sink: &mut dyn FrameUnwindSink,
) {
abi::emit_unwind_info(func, self, kind, sink);
) -> CodegenResult<()> {
abi::emit_unwind_info(func, self, kind, sink)
}
}

Expand Down
Loading

0 comments on commit 4cca510

Please sign in to comment.