From 13a926adc6e68443df3d1447d6c2c270d709b721 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Mon, 24 Jan 2022 15:39:19 +0200 Subject: [PATCH 1/2] regression test for GPR exhaustion during calls --- tests/compilers/issues.rs | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/tests/compilers/issues.rs b/tests/compilers/issues.rs index a07d9a82bd9..8a23405baff 100644 --- a/tests/compilers/issues.rs +++ b/tests/compilers/issues.rs @@ -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(()) +} From a358e847412401a6dd89bfe1c86a8e9a4ccc639c Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Mon, 24 Jan 2022 15:54:17 +0200 Subject: [PATCH 2/2] x64: fix assert when calling a function --- lib/compiler-singlepass/src/machine_x64.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/compiler-singlepass/src/machine_x64.rs b/lib/compiler-singlepass/src/machine_x64.rs index 3f428fe19fe..e2e13a4c7d3 100644 --- a/lib/compiler-singlepass/src/machine_x64.rs +++ b/lib/compiler-singlepass/src/machine_x64.rs @@ -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`.