1
1
// reference: https://github.com/MabezDev/llvm-project/blob/xtensa_release_9.0.1_with_rust_patches-31-05-2020-cherry-pick/clang/lib/CodeGen/TargetInfo.cpp#L9668-L9767
2
2
3
3
use crate :: abi:: call:: { ArgAbi , FnAbi , Reg , Uniform } ;
4
- use crate :: abi:: { Abi , HasDataLayout , Size , TyAbiInterface } ;
4
+ use crate :: abi:: { Abi , Align , FieldsShape , HasDataLayout , Size , TyAbiInterface } ;
5
5
use crate :: spec:: HasTargetSpec ;
6
6
7
7
const NUM_ARG_GPRS : u64 = 6 ;
@@ -12,27 +12,41 @@ where
12
12
Ty : TyAbiInterface < ' a , C > + Copy ,
13
13
{
14
14
let mut arg_gprs_left = NUM_RET_ARG_GPRS ;
15
- classify_arg_ty ( arg, & mut arg_gprs_left, NUM_RET_ARG_GPRS ) ;
16
-
17
- // classify_arg_ty can make the arg indirect by value which is not valid for ret args
18
- match arg. mode {
19
- super :: PassMode :: Indirect { attrs : _, extra_attrs : _, ref mut on_stack } => * on_stack = false ,
20
- _ => { }
15
+
16
+ let size = arg. layout . size . align_to ( Align :: from_bits ( 32 ) . unwrap ( ) ) ;
17
+
18
+ // The rules for return and argument with type size more then 4 bytes
19
+ // are the same, so defer to classifyArgumentType.
20
+ if size. bits ( ) > 32 {
21
+ classify_arg_ty ( arg, & mut arg_gprs_left, NUM_RET_ARG_GPRS ) ;
22
+
23
+ // classify_arg_ty can make the arg indirect by value which is not valid for ret args
24
+ match arg. mode {
25
+ super :: PassMode :: Indirect { attrs : _, extra_attrs : _, ref mut on_stack } => {
26
+ * on_stack = false
27
+ }
28
+ _ => { }
29
+ }
30
+ } else {
31
+ // LLVM DefaultABIInfo::classifyReturnType
32
+ if arg. layout . is_aggregate ( ) {
33
+ arg. make_indirect ( )
34
+ } else {
35
+ arg. extend_integer_width_to ( 32 )
36
+ }
21
37
}
22
38
}
23
39
24
40
fn classify_arg_ty < ' a , Ty , C > ( arg : & mut ArgAbi < ' _ , Ty > , arg_gprs_left : & mut u64 , num_gprs : u64 )
25
41
where
26
42
Ty : TyAbiInterface < ' a , C > + Copy ,
27
43
{
28
- assert ! ( * arg_gprs_left <= num_gprs, "Arg GPR tracking underflow" ) ;
44
+ assert ! ( * arg_gprs_left <= num_gprs, "GPR tracking underflow" ) ;
29
45
30
46
if arg. layout . is_zst ( ) {
31
47
return ; // ignore args that take no size
32
48
}
33
49
34
- // TODO check is arg has non-trvial constructor
35
-
36
50
let size = arg. layout . size . bits ( ) ;
37
51
let align = arg. layout . align . abi . bits ( ) ;
38
52
let mut must_use_stack = false ;
@@ -43,40 +57,51 @@ where
43
57
required_gprs += * arg_gprs_left % 2 ;
44
58
}
45
59
46
- // Put on stack objects which are not fit to 6 registers,
60
+ // Put on stack objects which are not fit to num_gprs registers,
47
61
// also on stack object which alignment more then 16 bytes and
48
62
// object with 16-byte alignment if it isn't the first argument.
49
- if required_gprs > * arg_gprs_left || align > 128 || * arg_gprs_left < 6 && align == 128 {
63
+ if required_gprs > * arg_gprs_left || align > 128 || * arg_gprs_left < num_gprs && align == 128 {
50
64
must_use_stack = true ;
51
65
required_gprs = * arg_gprs_left;
52
66
}
53
67
* arg_gprs_left -= required_gprs;
54
68
55
- if arg. layout . is_aggregate ( ) && !matches ! ( arg. layout. abi, Abi :: Vector { element: _ , count: _ } ) && !must_use_stack {
56
- if size < 32 && !must_use_stack {
57
- arg. extend_integer_width_to ( 32 ) ;
58
- } else if size == 64 {
59
- arg. cast_to ( Reg :: i64 ( ) ) ;
69
+ if must_use_stack {
70
+ arg. make_indirect_byval ( ) ;
71
+ } else {
72
+ if arg. layout . is_aggregate ( )
73
+ && !matches ! ( arg. layout. abi, Abi :: Vector { element: _, count: _ } )
74
+ {
75
+ if size < 32 && matches ! ( arg. layout. fields, FieldsShape :: Primitive ) {
76
+ arg. extend_integer_width_to ( 32 ) ;
77
+ } else if size == 64 {
78
+ arg. cast_to ( Reg :: i64 ( ) ) ;
79
+ } else {
80
+ arg. cast_to ( Uniform {
81
+ unit : Reg :: i32 ( ) ,
82
+ total : Size :: from_bits ( required_gprs * 32 ) ,
83
+ } ) ;
84
+ }
85
+ } else if size <= num_gprs * 32 {
86
+ // Aggregates which are <= num_gprs*32 will be passed in registers if possible,
87
+ // so coerce to integers.
88
+ if size <= 32 {
89
+ arg. cast_to ( Reg :: i32 ( ) )
90
+ } else if align == 64 {
91
+ arg. cast_to ( Uniform {
92
+ unit : Reg :: i64 ( ) ,
93
+ total : Size :: from_bits ( ( required_gprs / 2 ) * 32 ) ,
94
+ } ) ;
95
+ } else {
96
+ arg. cast_to ( Uniform {
97
+ unit : Reg :: i32 ( ) ,
98
+ total : Size :: from_bits ( required_gprs * 32 ) ,
99
+ } ) ;
100
+ }
60
101
} else {
61
- arg . cast_to ( Reg :: i32 ( ) ) ;
102
+ panic ! ( "unhandled GPR" )
62
103
}
63
- return ;
64
104
}
65
-
66
- // Aggregates which are <= 6*32 will be passed in registers if possible,
67
- // so coerce to integers.
68
- if size <= ( num_gprs * 32 ) && !must_use_stack {
69
- if size <= 32 {
70
- arg. cast_to ( Reg :: i32 ( ) )
71
- } else if align == 64 {
72
- arg. cast_to ( Uniform { unit : Reg :: i64 ( ) , total : Size :: from_bits ( ( required_gprs / 2 ) * 32 ) } ) ;
73
- } else {
74
- arg. cast_to ( Uniform { unit : Reg :: i32 ( ) , total : Size :: from_bits ( required_gprs * 32 ) } ) ;
75
- }
76
- return ;
77
- }
78
-
79
- arg. make_indirect_byval ( )
80
105
}
81
106
82
107
pub fn compute_abi_info < ' a , Ty , C > ( _cx : & C , fn_abi : & mut FnAbi < ' a , Ty > )
@@ -87,17 +112,13 @@ where
87
112
if !fn_abi. ret . is_ignore ( ) {
88
113
classify_ret_ty ( & mut fn_abi. ret ) ;
89
114
}
90
-
115
+
91
116
let mut avail_gprs = NUM_ARG_GPRS ;
92
117
93
- for arg in fn_abi. args . iter_mut ( ) {
118
+ for arg in fn_abi. args . iter_mut ( ) {
94
119
if arg. is_ignore ( ) {
95
120
continue ;
96
121
}
97
- classify_arg_ty (
98
- arg,
99
- & mut avail_gprs,
100
- NUM_ARG_GPRS
101
- ) ;
122
+ classify_arg_ty ( arg, & mut avail_gprs, NUM_ARG_GPRS ) ;
102
123
}
103
124
}
0 commit comments