1
1
use std:: iter;
2
2
3
- use rustc_abi:: Float :: * ;
4
- use rustc_abi:: Primitive :: { Float , Pointer } ;
5
- use rustc_abi:: { Abi , AddressSpace , PointerKind , Scalar , Size } ;
3
+ use rustc_abi:: Primitive :: Pointer ;
4
+ use rustc_abi:: { Abi , PointerKind , Scalar , Size } ;
6
5
use rustc_hir as hir;
7
6
use rustc_hir:: lang_items:: LangItem ;
8
7
use rustc_middle:: bug;
@@ -14,8 +13,7 @@ use rustc_middle::ty::{self, InstanceKind, Ty, TyCtxt};
14
13
use rustc_session:: config:: OptLevel ;
15
14
use rustc_span:: def_id:: DefId ;
16
15
use rustc_target:: abi:: call:: {
17
- ArgAbi , ArgAttribute , ArgAttributes , ArgExtension , Conv , FnAbi , PassMode , Reg , RegKind ,
18
- RiscvInterruptKind ,
16
+ ArgAbi , ArgAttribute , ArgAttributes , ArgExtension , Conv , FnAbi , PassMode , RiscvInterruptKind ,
19
17
} ;
20
18
use rustc_target:: spec:: abi:: Abi as SpecAbi ;
21
19
use tracing:: debug;
@@ -679,6 +677,8 @@ fn fn_abi_adjust_for_abi<'tcx>(
679
677
let tcx = cx. tcx ( ) ;
680
678
681
679
if abi == SpecAbi :: Rust || abi == SpecAbi :: RustCall || abi == SpecAbi :: RustIntrinsic {
680
+ fn_abi. adjust_for_rust_abi ( cx, abi) ;
681
+
682
682
// Look up the deduced parameter attributes for this function, if we have its def ID and
683
683
// we're optimizing in non-incremental mode. We'll tag its parameters with those attributes
684
684
// as appropriate.
@@ -689,141 +689,17 @@ fn fn_abi_adjust_for_abi<'tcx>(
689
689
& [ ]
690
690
} ;
691
691
692
- let fixup = | arg : & mut ArgAbi < ' tcx , Ty < ' tcx > > , arg_idx : Option < usize > | {
692
+ for ( arg_idx , arg) in fn_abi . args . iter_mut ( ) . enumerate ( ) {
693
693
if arg. is_ignore ( ) {
694
- return ;
695
- }
696
-
697
- // Avoid returning floats in x87 registers on x86 as loading and storing from x87
698
- // registers will quiet signalling NaNs.
699
- if tcx. sess . target . arch == "x86"
700
- && arg_idx. is_none ( )
701
- // Intrinsics themselves are not actual "real" functions, so theres no need to
702
- // change their ABIs.
703
- && abi != SpecAbi :: RustIntrinsic
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 ;
713
- }
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
- {
723
- // Larger than a pointer, return indirectly.
724
- arg. make_indirect ( ) ;
725
- return ;
726
- }
727
- _ => { }
728
- } ;
729
- }
730
-
731
- if arg_idx. is_none ( ) && arg. layout . size > Pointer ( AddressSpace :: DATA ) . size ( cx) * 2 {
732
- // Return values larger than 2 registers using a return area
733
- // pointer. LLVM and Cranelift disagree about how to return
734
- // values that don't fit in the registers designated for return
735
- // values. LLVM will force the entire return value to be passed
736
- // by return area pointer, while Cranelift will look at each IR level
737
- // return value independently and decide to pass it in a
738
- // register or not, which would result in the return value
739
- // being passed partially in registers and partially through a
740
- // return area pointer.
741
- //
742
- // While Cranelift may need to be fixed as the LLVM behavior is
743
- // generally more correct with respect to the surface language,
744
- // forcing this behavior in rustc itself makes it easier for
745
- // other backends to conform to the Rust ABI and for the C ABI
746
- // rustc already handles this behavior anyway.
747
- //
748
- // In addition LLVM's decision to pass the return value in
749
- // registers or using a return area pointer depends on how
750
- // exactly the return type is lowered to an LLVM IR type. For
751
- // example `Option<u128>` can be lowered as `{ i128, i128 }`
752
- // in which case the x86_64 backend would use a return area
753
- // pointer, or it could be passed as `{ i32, i128 }` in which
754
- // case the x86_64 backend would pass it in registers by taking
755
- // advantage of an LLVM ABI extension that allows using 3
756
- // registers for the x86_64 sysv call conv rather than the
757
- // officially specified 2 registers.
758
- //
759
- // FIXME: Technically we should look at the amount of available
760
- // return registers rather than guessing that there are 2
761
- // registers for return values. In practice only a couple of
762
- // architectures have less than 2 return registers. None of
763
- // which supported by Cranelift.
764
- //
765
- // NOTE: This adjustment is only necessary for the Rust ABI as
766
- // for other ABI's the calling convention implementations in
767
- // rustc_target already ensure any return value which doesn't
768
- // fit in the available amount of return registers is passed in
769
- // the right way for the current target.
770
- arg. make_indirect ( ) ;
771
- return ;
772
- }
773
-
774
- match arg. layout . abi {
775
- Abi :: Aggregate { .. } => { }
776
-
777
- // This is a fun case! The gist of what this is doing is
778
- // that we want callers and callees to always agree on the
779
- // ABI of how they pass SIMD arguments. If we were to *not*
780
- // make these arguments indirect then they'd be immediates
781
- // in LLVM, which means that they'd used whatever the
782
- // appropriate ABI is for the callee and the caller. That
783
- // means, for example, if the caller doesn't have AVX
784
- // enabled but the callee does, then passing an AVX argument
785
- // across this boundary would cause corrupt data to show up.
786
- //
787
- // This problem is fixed by unconditionally passing SIMD
788
- // arguments through memory between callers and callees
789
- // which should get them all to agree on ABI regardless of
790
- // target feature sets. Some more information about this
791
- // issue can be found in #44367.
792
- //
793
- // Note that the intrinsic ABI is exempt here as
794
- // that's how we connect up to LLVM and it's unstable
795
- // anyway, we control all calls to it in libstd.
796
- Abi :: Vector { .. }
797
- if abi != SpecAbi :: RustIntrinsic && tcx. sess . target . simd_types_indirect =>
798
- {
799
- arg. make_indirect ( ) ;
800
- return ;
801
- }
802
-
803
- _ => return ,
804
- }
805
- // Compute `Aggregate` ABI.
806
-
807
- let is_indirect_not_on_stack =
808
- matches ! ( arg. mode, PassMode :: Indirect { on_stack: false , .. } ) ;
809
- assert ! ( is_indirect_not_on_stack, "{:?}" , arg) ;
810
-
811
- let size = arg. layout . size ;
812
- if !arg. layout . is_unsized ( ) && size <= Pointer ( AddressSpace :: DATA ) . size ( cx) {
813
- // We want to pass small aggregates as immediates, but using
814
- // an LLVM aggregate type for this leads to bad optimizations,
815
- // so we pick an appropriately sized integer type instead.
816
- arg. cast_to ( Reg { kind : RegKind :: Integer , size } ) ;
694
+ continue ;
817
695
}
818
696
819
697
// If we deduced that this parameter was read-only, add that to the attribute list now.
820
698
//
821
699
// The `readonly` parameter only applies to pointers, so we can only do this if the
822
700
// argument was passed indirectly. (If the argument is passed directly, it's an SSA
823
701
// value, so it's implicitly immutable.)
824
- if let ( Some ( arg_idx) , & mut PassMode :: Indirect { ref mut attrs, .. } ) =
825
- ( arg_idx, & mut arg. mode )
826
- {
702
+ if let & mut PassMode :: Indirect { ref mut attrs, .. } = & mut arg. mode {
827
703
// The `deduced_param_attrs` list could be empty if this is a type of function
828
704
// we can't deduce any parameters for, so make sure the argument index is in
829
705
// bounds.
@@ -834,11 +710,6 @@ fn fn_abi_adjust_for_abi<'tcx>(
834
710
}
835
711
}
836
712
}
837
- } ;
838
-
839
- fixup ( & mut fn_abi. ret , None ) ;
840
- for ( arg_idx, arg) in fn_abi. args . iter_mut ( ) . enumerate ( ) {
841
- fixup ( arg, Some ( arg_idx) ) ;
842
713
}
843
714
} else {
844
715
fn_abi
0 commit comments