1
+ use std:: iter;
2
+
3
+ use rustc_abi:: { BackendRepr , Primitive } ;
4
+
1
5
use crate :: abi:: call:: { ArgAbi , FnAbi , Reg , RegKind , Uniform } ;
2
6
use crate :: abi:: { HasDataLayout , TyAbiInterface } ;
7
+ use crate :: spec:: { HasTargetSpec , Target } ;
3
8
4
9
/// Indicates the variant of the AArch64 ABI we are compiling for.
5
10
/// Used to accommodate Apple and Microsoft's deviations from the usual AAPCS ABI.
@@ -15,7 +20,7 @@ pub(crate) enum AbiKind {
15
20
fn is_homogeneous_aggregate < ' a , Ty , C > ( cx : & C , arg : & mut ArgAbi < ' a , Ty > ) -> Option < Uniform >
16
21
where
17
22
Ty : TyAbiInterface < ' a , C > + Copy ,
18
- C : HasDataLayout ,
23
+ C : HasDataLayout + HasTargetSpec ,
19
24
{
20
25
arg. layout . homogeneous_aggregate ( cx) . ok ( ) . and_then ( |ha| ha. unit ( ) ) . and_then ( |unit| {
21
26
let size = arg. layout . size ;
@@ -27,18 +32,40 @@ where
27
32
28
33
let valid_unit = match unit. kind {
29
34
RegKind :: Integer => false ,
30
- RegKind :: Float => true ,
35
+ RegKind :: Float => cx . target_spec ( ) . abi != "softfloat" ,
31
36
RegKind :: Vector => size. bits ( ) == 64 || size. bits ( ) == 128 ,
32
37
} ;
33
38
34
39
valid_unit. then_some ( Uniform :: consecutive ( unit, size) )
35
40
} )
36
41
}
37
42
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
+
38
65
fn classify_ret < ' a , Ty , C > ( cx : & C , ret : & mut ArgAbi < ' a , Ty > , kind : AbiKind )
39
66
where
40
67
Ty : TyAbiInterface < ' a , C > + Copy ,
41
- C : HasDataLayout ,
68
+ C : HasDataLayout + HasTargetSpec ,
42
69
{
43
70
if !ret. layout . is_sized ( ) {
44
71
// Not touching this...
51
78
// See also: <https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Pass-Arguments-to-Functions-Correctly>
52
79
ret. extend_integer_width_to ( 32 )
53
80
}
81
+ softfloat_float_abi ( cx. target_spec ( ) , ret) ;
54
82
return ;
55
83
}
56
84
if let Some ( uniform) = is_homogeneous_aggregate ( cx, ret) {
69
97
fn classify_arg < ' a , Ty , C > ( cx : & C , arg : & mut ArgAbi < ' a , Ty > , kind : AbiKind )
70
98
where
71
99
Ty : TyAbiInterface < ' a , C > + Copy ,
72
- C : HasDataLayout ,
100
+ C : HasDataLayout + HasTargetSpec ,
73
101
{
74
102
if !arg. layout . is_sized ( ) {
75
103
// Not touching this...
82
110
// See also: <https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Pass-Arguments-to-Functions-Correctly>
83
111
arg. extend_integer_width_to ( 32 ) ;
84
112
}
113
+ softfloat_float_abi ( cx. target_spec ( ) , arg) ;
114
+
85
115
return ;
86
116
}
87
117
if let Some ( uniform) = is_homogeneous_aggregate ( cx, arg) {
@@ -112,7 +142,7 @@ where
112
142
pub ( crate ) fn compute_abi_info < ' a , Ty , C > ( cx : & C , fn_abi : & mut FnAbi < ' a , Ty > , kind : AbiKind )
113
143
where
114
144
Ty : TyAbiInterface < ' a , C > + Copy ,
115
- C : HasDataLayout ,
145
+ C : HasDataLayout + HasTargetSpec ,
116
146
{
117
147
if !fn_abi. ret . is_ignore ( ) {
118
148
classify_ret ( cx, & mut fn_abi. ret , kind) ;
@@ -125,3 +155,13 @@ where
125
155
classify_arg ( cx, arg, kind) ;
126
156
}
127
157
}
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