11use crate :: abi:: call:: { ArgAbi , FnAbi , Reg , RegKind , Uniform } ;
22use crate :: abi:: { HasDataLayout , TyAbiInterface } ;
33
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+
425fn is_homogeneous_aggregate < ' a , Ty , C > ( cx : & C , arg : & mut ArgAbi < ' a , Ty > ) -> Option < Uniform >
526where
627 Ty : TyAbiInterface < ' a , C > + Copy ,
@@ -24,13 +45,16 @@ where
2445 } )
2546}
2647
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 )
2849where
2950 Ty : TyAbiInterface < ' a , C > + Copy ,
3051 C : HasDataLayout ,
3152{
3253 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+ }
3458 return ;
3559 }
3660 if let Some ( uniform) = is_homogeneous_aggregate ( cx, ret) {
@@ -46,13 +70,16 @@ where
4670 ret. make_indirect ( ) ;
4771}
4872
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 )
5074where
5175 Ty : TyAbiInterface < ' a , C > + Copy ,
5276 C : HasDataLayout ,
5377{
5478 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+ }
5683 return ;
5784 }
5885 if let Some ( uniform) = is_homogeneous_aggregate ( cx, arg) {
@@ -68,19 +95,19 @@ where
6895 arg. make_indirect ( ) ;
6996}
7097
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 )
7299where
73100 Ty : TyAbiInterface < ' a , C > + Copy ,
74101 C : HasDataLayout ,
75102{
76103 if !fn_abi. ret . is_ignore ( ) {
77- classify_ret ( cx, & mut fn_abi. ret ) ;
104+ classify_ret ( cx, & mut fn_abi. ret , param_policy ) ;
78105 }
79106
80107 for arg in fn_abi. args . iter_mut ( ) {
81108 if arg. is_ignore ( ) {
82109 continue ;
83110 }
84- classify_arg ( cx, arg) ;
111+ classify_arg ( cx, arg, param_policy ) ;
85112 }
86113}
0 commit comments