diff options
| author | bors <bors@rust-lang.org> | 2024-10-22 22:36:59 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-10-22 22:36:59 +0000 |
| commit | 8bf64f106ac0cd1f2b9c6fd27965dd2dc4b862dd (patch) | |
| tree | a12bfad99e5c05d0313ac32ae62cefb6b095f779 /compiler/rustc_ty_utils/src | |
| parent | 86d69c705a552236a622eee3fdea94bf13c5f102 (diff) | |
| parent | 09068192f86e84bb0dddc105c9f7cc1971684fb7 (diff) | |
| download | rust-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.rs | 37 |
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 { |
