|
1 | 1 | use std::iter; |
2 | 2 |
|
3 | | -use rustc_abi::Float::*; |
4 | 3 | use rustc_abi::Primitive::{Float, Pointer}; |
5 | 4 | use rustc_abi::{Abi, AddressSpace, PointerKind, Scalar, Size}; |
6 | 5 | use rustc_hir as hir; |
@@ -695,37 +694,31 @@ fn fn_abi_adjust_for_abi<'tcx>( |
695 | 694 | } |
696 | 695 |
|
697 | 696 | // Avoid returning floats in x87 registers on x86 as loading and storing from x87 |
698 | | - // registers will quiet signalling NaNs. |
| 697 | + // registers will quiet signalling NaNs. Also avoid using SSE registers since they |
| 698 | + // are not always available (depending on target features). |
699 | 699 | if tcx.sess.target.arch == "x86" |
700 | 700 | && arg_idx.is_none() |
701 | 701 | // Intrinsics themselves are not actual "real" functions, so theres no need to |
702 | 702 | // change their ABIs. |
703 | 703 | && abi != SpecAbi::RustIntrinsic |
704 | 704 | { |
705 | | - match arg.layout.abi { |
706 | | - // Handle similar to the way arguments with an `Abi::Aggregate` abi are handled |
707 | | - // below, by returning arguments up to the size of a pointer (32 bits on x86) |
708 | | - // cast to an appropriately sized integer. |
709 | | - Abi::Scalar(s) if s.primitive() == Float(F32) => { |
710 | | - // Same size as a pointer, return in a register. |
711 | | - arg.cast_to(Reg::i32()); |
712 | | - return; |
| 705 | + let has_float = match arg.layout.abi { |
| 706 | + Abi::Scalar(s) => matches!(s.primitive(), Float(_)), |
| 707 | + Abi::ScalarPair(s1, s2) => { |
| 708 | + matches!(s1.primitive(), Float(_)) || matches!(s2.primitive(), Float(_)) |
713 | 709 | } |
714 | | - Abi::Scalar(s) if s.primitive() == Float(F64) => { |
715 | | - // Larger than a pointer, return indirectly. |
716 | | - arg.make_indirect(); |
717 | | - return; |
718 | | - } |
719 | | - Abi::ScalarPair(s1, s2) |
720 | | - if matches!(s1.primitive(), Float(F32 | F64)) |
721 | | - || matches!(s2.primitive(), Float(F32 | F64)) => |
722 | | - { |
| 710 | + _ => false, // anyway not passed via registers on x86 |
| 711 | + }; |
| 712 | + if has_float { |
| 713 | + if arg.layout.size <= Pointer(AddressSpace::DATA).size(cx) { |
| 714 | + // Same size or smaller than pointer, return in a register. |
| 715 | + arg.cast_to(Reg { kind: RegKind::Integer, size: arg.layout.size }); |
| 716 | + } else { |
723 | 717 | // Larger than a pointer, return indirectly. |
724 | 718 | arg.make_indirect(); |
725 | | - return; |
726 | 719 | } |
727 | | - _ => {} |
728 | | - }; |
| 720 | + return; |
| 721 | + } |
729 | 722 | } |
730 | 723 |
|
731 | 724 | match arg.layout.abi { |
|
0 commit comments