1
1
use crate :: abi:: call:: { ArgAbi , FnAbi , Reg , RegKind , Uniform } ;
2
2
use crate :: abi:: { HasDataLayout , TyAbiInterface } ;
3
3
4
+ /// Given integer-types M and register width N (e.g. M=u16 and N=32 bits), the
5
+ /// `ParamExtension` policy specifies how a uM value should be treated when
6
+ /// passed via register or stack-slot of width N. See also rust-lang/rust#97463.
7
+ #[ derive( Copy , Clone , PartialEq ) ]
8
+ pub enum ParamExtension {
9
+ /// Indicates that when passing an i8/i16, either as a function argument or
10
+ /// as a return value, it must be sign-extended to 32 bits, and likewise a
11
+ /// u8/u16 must be zero-extended to 32-bits. (This variant is here to
12
+ /// accommodate Apple's deviation from the usual AArch64 ABI as defined by
13
+ /// ARM.)
14
+ ///
15
+ /// See also: <https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Pass-Arguments-to-Functions-Correctly>
16
+ ExtendTo32Bits ,
17
+
18
+ /// Indicates that no sign- nor zero-extension is performed: if a value of
19
+ /// type with bitwidth M is passed as function argument or return value,
20
+ /// then M bits are copied into the least significant M bits, and the
21
+ /// remaining bits of the register (or word of memory) are untouched.
22
+ NoExtension ,
23
+ }
24
+
4
25
fn is_homogeneous_aggregate < ' a , Ty , C > ( cx : & C , arg : & mut ArgAbi < ' a , Ty > ) -> Option < Uniform >
5
26
where
6
27
Ty : TyAbiInterface < ' a , C > + Copy ,
@@ -24,13 +45,16 @@ where
24
45
} )
25
46
}
26
47
27
- fn classify_ret < ' a , Ty , C > ( cx : & C , ret : & mut ArgAbi < ' a , Ty > )
48
+ fn classify_ret < ' a , Ty , C > ( cx : & C , ret : & mut ArgAbi < ' a , Ty > , param_policy : ParamExtension )
28
49
where
29
50
Ty : TyAbiInterface < ' a , C > + Copy ,
30
51
C : HasDataLayout ,
31
52
{
32
53
if !ret. layout . is_aggregate ( ) {
33
- ret. extend_integer_width_to ( 32 ) ;
54
+ match param_policy {
55
+ ParamExtension :: ExtendTo32Bits => ret. extend_integer_width_to ( 32 ) ,
56
+ ParamExtension :: NoExtension => { }
57
+ }
34
58
return ;
35
59
}
36
60
if let Some ( uniform) = is_homogeneous_aggregate ( cx, ret) {
@@ -46,13 +70,16 @@ where
46
70
ret. make_indirect ( ) ;
47
71
}
48
72
49
- fn classify_arg < ' a , Ty , C > ( cx : & C , arg : & mut ArgAbi < ' a , Ty > )
73
+ fn classify_arg < ' a , Ty , C > ( cx : & C , arg : & mut ArgAbi < ' a , Ty > , param_policy : ParamExtension )
50
74
where
51
75
Ty : TyAbiInterface < ' a , C > + Copy ,
52
76
C : HasDataLayout ,
53
77
{
54
78
if !arg. layout . is_aggregate ( ) {
55
- arg. extend_integer_width_to ( 32 ) ;
79
+ match param_policy {
80
+ ParamExtension :: ExtendTo32Bits => arg. extend_integer_width_to ( 32 ) ,
81
+ ParamExtension :: NoExtension => { }
82
+ }
56
83
return ;
57
84
}
58
85
if let Some ( uniform) = is_homogeneous_aggregate ( cx, arg) {
@@ -68,19 +95,19 @@ where
68
95
arg. make_indirect ( ) ;
69
96
}
70
97
71
- pub fn compute_abi_info < ' a , Ty , C > ( cx : & C , fn_abi : & mut FnAbi < ' a , Ty > )
98
+ pub fn compute_abi_info < ' a , Ty , C > ( cx : & C , fn_abi : & mut FnAbi < ' a , Ty > , param_policy : ParamExtension )
72
99
where
73
100
Ty : TyAbiInterface < ' a , C > + Copy ,
74
101
C : HasDataLayout ,
75
102
{
76
103
if !fn_abi. ret . is_ignore ( ) {
77
- classify_ret ( cx, & mut fn_abi. ret ) ;
104
+ classify_ret ( cx, & mut fn_abi. ret , param_policy ) ;
78
105
}
79
106
80
107
for arg in fn_abi. args . iter_mut ( ) {
81
108
if arg. is_ignore ( ) {
82
109
continue ;
83
110
}
84
- classify_arg ( cx, arg) ;
111
+ classify_arg ( cx, arg, param_policy ) ;
85
112
}
86
113
}
0 commit comments