about summary refs log tree commit diff
path: root/compiler/rustc_ty_utils/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-10-22 22:36:59 +0000
committerbors <bors@rust-lang.org>2024-10-22 22:36:59 +0000
commit8bf64f106ac0cd1f2b9c6fd27965dd2dc4b862dd (patch)
treea12bfad99e5c05d0313ac32ae62cefb6b095f779 /compiler/rustc_ty_utils/src
parent86d69c705a552236a622eee3fdea94bf13c5f102 (diff)
parent09068192f86e84bb0dddc105c9f7cc1971684fb7 (diff)
downloadrust-8bf64f106ac0cd1f2b9c6fd27965dd2dc4b862dd.tar.gz
rust-8bf64f106ac0cd1f2b9c6fd27965dd2dc4b862dd.zip
Auto merge of #131871 - RalfJung:x86-32-float, r=workingjubilee
x86-32 float return for 'Rust' ABI: treat all float types consistently

This helps with https://github.com/rust-lang/rust/issues/131819: for our own ABI on x86-32, we want to *never* use the float registers. The previous logic only considered F32 and F64, but skipped F16 and F128. So I made the logic just apply to all float types.

try-job: i686-gnu
try-job: i686-gnu-nopt
Diffstat (limited to 'compiler/rustc_ty_utils/src')
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs37
1 files changed, 15 insertions, 22 deletions
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 13691204c96..09b9ecb3486 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -1,6 +1,5 @@
 use std::iter;
 
-use rustc_abi::Float::*;
 use rustc_abi::Primitive::{Float, Pointer};
 use rustc_abi::{Abi, AddressSpace, PointerKind, Scalar, Size};
 use rustc_hir as hir;
@@ -695,37 +694,31 @@ fn fn_abi_adjust_for_abi<'tcx>(
             }
 
             // Avoid returning floats in x87 registers on x86 as loading and storing from x87
-            // registers will quiet signalling NaNs.
+            // registers will quiet signalling NaNs. Also avoid using SSE registers since they
+            // are not always available (depending on target features).
             if tcx.sess.target.arch == "x86"
                 && arg_idx.is_none()
                 // Intrinsics themselves are not actual "real" functions, so theres no need to
                 // change their ABIs.
                 && abi != SpecAbi::RustIntrinsic
             {
-                match arg.layout.abi {
-                    // Handle similar to the way arguments with an `Abi::Aggregate` abi are handled
-                    // below, by returning arguments up to the size of a pointer (32 bits on x86)
-                    // cast to an appropriately sized integer.
-                    Abi::Scalar(s) if s.primitive() == Float(F32) => {
-                        // Same size as a pointer, return in a register.
-                        arg.cast_to(Reg::i32());
-                        return;
+                let has_float = match arg.layout.abi {
+                    Abi::Scalar(s) => matches!(s.primitive(), Float(_)),
+                    Abi::ScalarPair(s1, s2) => {
+                        matches!(s1.primitive(), Float(_)) || matches!(s2.primitive(), Float(_))
                     }
-                    Abi::Scalar(s) if s.primitive() == Float(F64) => {
-                        // Larger than a pointer, return indirectly.
-                        arg.make_indirect();
-                        return;
-                    }
-                    Abi::ScalarPair(s1, s2)
-                        if matches!(s1.primitive(), Float(F32 | F64))
-                            || matches!(s2.primitive(), Float(F32 | F64)) =>
-                    {
+                    _ => false, // anyway not passed via registers on x86
+                };
+                if has_float {
+                    if arg.layout.size <= Pointer(AddressSpace::DATA).size(cx) {
+                        // Same size or smaller than pointer, return in a register.
+                        arg.cast_to(Reg { kind: RegKind::Integer, size: arg.layout.size });
+                    } else {
                         // Larger than a pointer, return indirectly.
                         arg.make_indirect();
-                        return;
                     }
-                    _ => {}
-                };
+                    return;
+                }
             }
 
             if arg_idx.is_none() && arg.layout.size > Pointer(AddressSpace::DATA).size(cx) * 2 {