Skip to content

Commit

Permalink
Merge pull request #2766 from nagisa/unassert
Browse files Browse the repository at this point in the history
Remove an attempt to reserve a GPR when no GPR clobbering is occurring
  • Loading branch information
syrusakbary committed Jan 26, 2022
2 parents 900df5e + cc1db81 commit 67be3ea
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 3 deletions.
12 changes: 9 additions & 3 deletions lib/compiler-singlepass/src/machine_x64.rs
Expand Up @@ -1807,16 +1807,22 @@ impl Machine for MachineX86_64 {
fn push_location_for_native(&mut self, loc: Location) {
match loc {
Location::Imm64(_) => {
// Push R9 value slot to be exchange with `mov`.
// x86_64 does not support `mov imm64, mem`. We must first place the immdiate value
// into a register and then write the register to the memory. Now the problem is
// that there might not be any registers available to clobber. In order to make
// this work out we spill a register thus retaining both the original value of the
// register and producing the required data at the top of the stack.
//
// FIXME(#2723): figure out how to not require spilling a register here. It should
// definitely be possible to `pick_gpr`/`pick_temp_gpr` to grab an otherwise unused
// register and just clobber its value here.
self.assembler.emit_push(Size::S64, Location::GPR(GPR::R9));
self.reserve_unused_temp_gpr(GPR::R9);
self.move_location(Size::S64, loc, Location::GPR(GPR::R9));
self.assembler.emit_xchg(
Size::S64,
Location::GPR(GPR::R9),
Location::Memory(GPR::RSP, 0),
);
self.release_gpr(GPR::R9);
}
Location::SIMD(_) => {
// Dummy value slot to be filled with `mov`.
Expand Down
39 changes: 39 additions & 0 deletions tests/compilers/issues.rs
Expand Up @@ -225,3 +225,42 @@ fn call_with_static_data_pointers(mut config: crate::Config) -> Result<()> {
instance.exports.get_function("repro")?.call(&[])?;
Ok(())
}

/// Exhaustion of GPRs when calling a function with many floating point arguments
///
/// Note: this one is specific to Singlepass, but we want to test in all
/// available compilers.
#[compiler_test(issues)]
fn regression_gpr_exhaustion_for_calls(mut config: crate::Config) -> Result<()> {
let store = config.store();
let wat = r#"
(module
(type (;0;) (func (param f64) (result i32)))
(type (;1;) (func (param f64 f64 f64 f64 f64 f64)))
(func (;0;) (type 0) (param f64) (result i32)
local.get 0
local.get 0
local.get 0
local.get 0
f64.const 0
f64.const 0
f64.const 0
f64.const 0
f64.const 0
f64.const 0
f64.const 0
i32.const 0
call_indirect (type 0)
call_indirect (type 1)
drop
drop
drop
drop
i32.const 0)
(table (;0;) 1 1 funcref))
"#;
let module = Module::new(&store, wat)?;
let imports: ImportObject = imports! {};
let instance = Instance::new(&module, &imports)?;
Ok(())
}

0 comments on commit 67be3ea

Please sign in to comment.