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
3
3
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 } ;
6
7
use crate :: spec:: HasTargetSpec ;
7
8
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
+
8
27
fn 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 {
10
33
ret. extend_integer_width_to ( 64 ) ;
11
- } else {
12
- ret. make_indirect ( ) ;
34
+ return ;
13
35
}
36
+ ret. make_indirect ( ) ;
14
37
}
15
38
16
39
fn classify_arg < ' a , Ty , C > ( cx : & C , arg : & mut ArgAbi < ' a , Ty > )
@@ -32,19 +55,25 @@ where
32
55
}
33
56
return ;
34
57
}
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 {
36
65
arg. extend_integer_width_to ( 64 ) ;
37
66
return ;
38
67
}
39
68
40
69
if arg. layout . is_single_fp_element ( cx) {
41
- match arg . layout . size . bytes ( ) {
70
+ match size. bytes ( ) {
42
71
4 => arg. cast_to ( Reg :: f32 ( ) ) ,
43
72
8 => arg. cast_to ( Reg :: f64 ( ) ) ,
44
73
_ => arg. make_indirect ( ) ,
45
74
}
46
75
} else {
47
- match arg . layout . size . bytes ( ) {
76
+ match size. bytes ( ) {
48
77
1 => arg. cast_to ( Reg :: i8 ( ) ) ,
49
78
2 => arg. cast_to ( Reg :: i16 ( ) ) ,
50
79
4 => arg. cast_to ( Reg :: i32 ( ) ) ,
0 commit comments