diff --git a/cranelift/codegen/src/isa/x86/abi.rs b/cranelift/codegen/src/isa/x86/abi.rs index 0321e36e85..b25c17e1f6 100644 --- a/cranelift/codegen/src/isa/x86/abi.rs +++ b/cranelift/codegen/src/isa/x86/abi.rs @@ -115,9 +115,18 @@ impl ArgAssigner for Args { } // Try to use an FPR. - if ty.is_float() && self.fpr_used < self.fpr_limit { - let reg = FPR.unit(self.fpr_used); - self.fpr_used += 1; + let fpr_offset = if self.call_conv == CallConv::WindowsFastcall { + // 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. + debug_assert_eq!(self.fpr_limit, self.gpr.len()); + &mut self.gpr_used + } else { + &mut self.fpr_used + }; + if ty.is_float() && *fpr_offset < self.fpr_limit { + let reg = FPR.unit(*fpr_offset); + *fpr_offset += 1; return ArgumentLoc::Reg(reg).into(); } diff --git a/cranelift/filetests/filetests/isa/x86/windows_fastcall_x64.clif b/cranelift/filetests/filetests/isa/x86/windows_fastcall_x64.clif index 7af721ed8e..a84c17fb9e 100644 --- a/cranelift/filetests/filetests/isa/x86/windows_fastcall_x64.clif +++ b/cranelift/filetests/filetests/isa/x86/windows_fastcall_x64.clif @@ -31,3 +31,9 @@ ebb0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64): return } ; check: function %five_args(i64 [%rcx], i64 [%rdx], i64 [%r8], i64 [%r9], i64 [32], i64 fp [%rbp]) -> i64 fp [%rbp] windows_fastcall { + +function %mixed_int_float(i64, f64, i64, f32) windows_fastcall { +ebb0(v0: i64, v1: f64, v2: i64, v3: f32): + return +} +; check: function %mixed_int_float(i64 [%rcx], f64 [%xmm1], i64 [%r8], f32 [%xmm3], i64 fp [%rbp]) -> i64 fp [%rbp] windows_fastcall { \ No newline at end of file