diff options
| author | beetrees <b@beetr.ee> | 2024-04-02 05:08:56 +0100 |
|---|---|---|
| committer | beetrees <b@beetr.ee> | 2024-06-01 07:39:13 +0100 |
| commit | 952becc0bdf814f194a42d34ea78fed792a1f760 (patch) | |
| tree | 818a7713b38d6d4c0642f246e172957d2eed02b6 /compiler/rustc_ty_utils/src | |
| parent | dcc9a8f2831a9afd2896e3fe2cc020bb2bf949bd (diff) | |
Ensure floats are returned losslessly by the Rust ABI on 32-bit x86
Diffstat (limited to 'compiler/rustc_ty_utils/src')
| -rw-r--r-- | compiler/rustc_ty_utils/src/abi.rs | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index c5ea85c90dc..ca503dd16b9 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -744,6 +744,40 @@ fn fn_abi_adjust_for_abi<'tcx>( return; } + // Avoid returning floats in x87 registers on x86 as loading and storing from x87 + // registers will quiet signalling NaNs. + if cx.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; + } + 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)) => + { + // Larger than a pointer, return indirectly. + arg.make_indirect(); + return; + } + _ => {} + }; + } + match arg.layout.abi { Abi::Aggregate { .. } => {} |
