1+ use std:: iter;
2+
3+ use rustc_abi:: { BackendRepr , Primitive } ;
4+
15use crate :: abi:: call:: { ArgAbi , FnAbi , Reg , RegKind , Uniform } ;
26use crate :: abi:: { HasDataLayout , TyAbiInterface } ;
7+ use crate :: spec:: { HasTargetSpec , Target } ;
38
49/// Indicates the variant of the AArch64 ABI we are compiling for.
510/// Used to accommodate Apple and Microsoft's deviations from the usual AAPCS ABI.
@@ -15,7 +20,7 @@ pub(crate) enum AbiKind {
1520fn is_homogeneous_aggregate < ' a , Ty , C > ( cx : & C , arg : & mut ArgAbi < ' a , Ty > ) -> Option < Uniform >
1621where
1722 Ty : TyAbiInterface < ' a , C > + Copy ,
18- C : HasDataLayout ,
23+ C : HasDataLayout + HasTargetSpec ,
1924{
2025 arg. layout . homogeneous_aggregate ( cx) . ok ( ) . and_then ( |ha| ha. unit ( ) ) . and_then ( |unit| {
2126 let size = arg. layout . size ;
@@ -27,18 +32,40 @@ where
2732
2833 let valid_unit = match unit. kind {
2934 RegKind :: Integer => false ,
30- RegKind :: Float => true ,
35+ RegKind :: Float => cx . target_spec ( ) . abi != "softfloat" ,
3136 RegKind :: Vector => size. bits ( ) == 64 || size. bits ( ) == 128 ,
3237 } ;
3338
3439 valid_unit. then_some ( Uniform :: consecutive ( unit, size) )
3540 } )
3641}
3742
43+ fn softfloat_float_abi < Ty > ( target : & Target , arg : & mut ArgAbi < ' _ , Ty > ) {
44+ if target. abi != "softfloat" {
45+ return ;
46+ }
47+ if let BackendRepr :: Scalar ( s) = arg. layout . backend_repr
48+ && let Primitive :: Float ( f) = s. primitive ( )
49+ {
50+ // Do *not* use the floag registers for passing arguments, as that would make
51+ // the ABI depend on whether `neon` instructions are enabled.
52+ // Apparently there is no standard ABI here [1], so we can do whatever we want.
53+ // We choose to pass floats via equal-sized integer registers.
54+ // [1]: https://github.com/rust-lang/rust/issues/131058#issuecomment-2384960972
55+ arg. cast_to ( Reg { kind : RegKind :: Integer , size : f. size ( ) } ) ;
56+ } else if let BackendRepr :: ScalarPair ( s1, s2) = arg. layout . backend_repr
57+ && ( matches ! ( s1. primitive( ) , Primitive :: Float ( _) )
58+ || matches ! ( s2. primitive( ) , Primitive :: Float ( _) ) )
59+ {
60+ // For now just pass this indirectly, that definitely avoids all trouble.
61+ arg. make_indirect ( ) ;
62+ }
63+ }
64+
3865fn classify_ret < ' a , Ty , C > ( cx : & C , ret : & mut ArgAbi < ' a , Ty > , kind : AbiKind )
3966where
4067 Ty : TyAbiInterface < ' a , C > + Copy ,
41- C : HasDataLayout ,
68+ C : HasDataLayout + HasTargetSpec ,
4269{
4370 if !ret. layout . is_sized ( ) {
4471 // Not touching this...
5178 // See also: <https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Pass-Arguments-to-Functions-Correctly>
5279 ret. extend_integer_width_to ( 32 )
5380 }
81+ softfloat_float_abi ( cx. target_spec ( ) , ret) ;
5482 return ;
5583 }
5684 if let Some ( uniform) = is_homogeneous_aggregate ( cx, ret) {
6997fn classify_arg < ' a , Ty , C > ( cx : & C , arg : & mut ArgAbi < ' a , Ty > , kind : AbiKind )
7098where
7199 Ty : TyAbiInterface < ' a , C > + Copy ,
72- C : HasDataLayout ,
100+ C : HasDataLayout + HasTargetSpec ,
73101{
74102 if !arg. layout . is_sized ( ) {
75103 // Not touching this...
82110 // See also: <https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Pass-Arguments-to-Functions-Correctly>
83111 arg. extend_integer_width_to ( 32 ) ;
84112 }
113+ softfloat_float_abi ( cx. target_spec ( ) , arg) ;
114+
85115 return ;
86116 }
87117 if let Some ( uniform) = is_homogeneous_aggregate ( cx, arg) {
@@ -112,7 +142,7 @@ where
112142pub ( crate ) fn compute_abi_info < ' a , Ty , C > ( cx : & C , fn_abi : & mut FnAbi < ' a , Ty > , kind : AbiKind )
113143where
114144 Ty : TyAbiInterface < ' a , C > + Copy ,
115- C : HasDataLayout ,
145+ C : HasDataLayout + HasTargetSpec ,
116146{
117147 if !fn_abi. ret . is_ignore ( ) {
118148 classify_ret ( cx, & mut fn_abi. ret , kind) ;
@@ -125,3 +155,13 @@ where
125155 classify_arg ( cx, arg, kind) ;
126156 }
127157}
158+
159+ pub ( crate ) fn compute_rust_abi_info < ' a , Ty , C > ( cx : & C , fn_abi : & mut FnAbi < ' a , Ty > )
160+ where
161+ Ty : TyAbiInterface < ' a , C > + Copy ,
162+ C : HasDataLayout + HasTargetSpec ,
163+ {
164+ for arg in fn_abi. args . iter_mut ( ) . chain ( iter:: once ( & mut fn_abi. ret ) ) {
165+ softfloat_float_abi ( cx. target_spec ( ) , arg) ;
166+ }
167+ }
0 commit comments