1- // FIXME: The assumes we're using the non-vector ABI, i.e., compiling
2- // for a pre-z13 machine or using -mno-vx.
1+ // Reference: ELF Application Binary Interface s390x Supplement
2+ // https://github.com/IBM/s390x-abi
33
4- use crate :: abi:: call:: { ArgAbi , FnAbi , Reg } ;
5- use crate :: abi:: { HasDataLayout , TyAbiInterface } ;
4+ use rustc_abi:: { BackendRepr , HasDataLayout , Size , TyAbiInterface , TyAndLayout } ;
5+
6+ use crate :: abi:: call:: { ArgAbi , FnAbi , Reg , RegKind } ;
67use crate :: spec:: HasTargetSpec ;
78
9+ fn contains_vector < ' a , Ty , C > ( cx : & C , layout : TyAndLayout < ' a , Ty > , expected_size : Size ) -> bool
10+ where
11+ Ty : TyAbiInterface < ' a , C > + Copy ,
12+ {
13+ match layout. backend_repr {
14+ BackendRepr :: Uninhabited | BackendRepr :: Scalar ( _) | BackendRepr :: ScalarPair ( ..) => false ,
15+ BackendRepr :: Vector { .. } => layout. size == expected_size,
16+ BackendRepr :: Memory { .. } => {
17+ if layout. fields . count ( ) != 1 {
18+ // Zero-sized members in C are not ignored.
19+ // See https://github.com/rust-lang/rust/pull/131586#discussion_r1836718798.
20+ return false ;
21+ }
22+ contains_vector ( cx, layout. field ( cx, 0 ) , expected_size)
23+ }
24+ }
25+ }
26+
827fn classify_ret < Ty > ( ret : & mut ArgAbi < ' _ , Ty > ) {
9- if !ret. layout . is_aggregate ( ) && ret. layout . size . bits ( ) <= 64 {
28+ let size = ret. layout . size ;
29+ if size. bits ( ) <= 128 && matches ! ( ret. layout. backend_repr, BackendRepr :: Vector { .. } ) {
30+ return ;
31+ }
32+ if !ret. layout . is_aggregate ( ) && size. bits ( ) <= 64 {
1033 ret. extend_integer_width_to ( 64 ) ;
11- } else {
12- ret. make_indirect ( ) ;
34+ return ;
1335 }
36+ ret. make_indirect ( ) ;
1437}
1538
1639fn classify_arg < ' a , Ty , C > ( cx : & C , arg : & mut ArgAbi < ' a , Ty > )
@@ -32,19 +55,25 @@ where
3255 }
3356 return ;
3457 }
35- if !arg. layout . is_aggregate ( ) && arg. layout . size . bits ( ) <= 64 {
58+
59+ let size = arg. layout . size ;
60+ if size. bits ( ) <= 128 && contains_vector ( cx, arg. layout , size) {
61+ arg. cast_to ( Reg { kind : RegKind :: Vector , size } ) ;
62+ return ;
63+ }
64+ if !arg. layout . is_aggregate ( ) && size. bits ( ) <= 64 {
3665 arg. extend_integer_width_to ( 64 ) ;
3766 return ;
3867 }
3968
4069 if arg. layout . is_single_fp_element ( cx) {
41- match arg . layout . size . bytes ( ) {
70+ match size. bytes ( ) {
4271 4 => arg. cast_to ( Reg :: f32 ( ) ) ,
4372 8 => arg. cast_to ( Reg :: f64 ( ) ) ,
4473 _ => arg. make_indirect ( ) ,
4574 }
4675 } else {
47- match arg . layout . size . bytes ( ) {
76+ match size. bytes ( ) {
4877 1 => arg. cast_to ( Reg :: i8 ( ) ) ,
4978 2 => arg. cast_to ( Reg :: i16 ( ) ) ,
5079 4 => arg. cast_to ( Reg :: i32 ( ) ) ,
0 commit comments