@@ -8,16 +8,16 @@ use crate::spec::HasTargetSpec;
8
8
9
9
#[ derive( Copy , Clone ) ]
10
10
enum RegPassKind {
11
- Float ( Reg ) ,
12
- Integer ( Reg ) ,
11
+ Float { offset_from_start : Size , ty : Reg } ,
12
+ Integer { offset_from_start : Size , ty : Reg } ,
13
13
Unknown ,
14
14
}
15
15
16
16
#[ derive( Copy , Clone ) ]
17
17
enum FloatConv {
18
- FloatPair ( Reg , Reg ) ,
18
+ FloatPair { first_ty : Reg , second_ty_offset_from_start : Size , second_ty : Reg } ,
19
19
Float ( Reg ) ,
20
- MixedPair ( Reg , Reg ) ,
20
+ MixedPair { first_ty : Reg , second_ty_offset_from_start : Size , second_ty : Reg } ,
21
21
}
22
22
23
23
#[ derive( Copy , Clone ) ]
@@ -37,6 +37,7 @@ fn should_use_fp_conv_helper<'a, Ty, C>(
37
37
flen : u64 ,
38
38
field1_kind : & mut RegPassKind ,
39
39
field2_kind : & mut RegPassKind ,
40
+ offset_from_start : Size ,
40
41
) -> Result < ( ) , CannotUseFpConv >
41
42
where
42
43
Ty : TyAbiInterface < ' a , C > + Copy ,
@@ -49,16 +50,16 @@ where
49
50
}
50
51
match ( * field1_kind, * field2_kind) {
51
52
( RegPassKind :: Unknown , _) => {
52
- * field1_kind = RegPassKind :: Integer ( Reg {
53
- kind : RegKind :: Integer ,
54
- size : arg_layout. size ,
55
- } ) ;
53
+ * field1_kind = RegPassKind :: Integer {
54
+ offset_from_start ,
55
+ ty : Reg { kind : RegKind :: Integer , size : arg_layout. size } ,
56
+ } ;
56
57
}
57
- ( RegPassKind :: Float ( _ ) , RegPassKind :: Unknown ) => {
58
- * field2_kind = RegPassKind :: Integer ( Reg {
59
- kind : RegKind :: Integer ,
60
- size : arg_layout. size ,
61
- } ) ;
58
+ ( RegPassKind :: Float { .. } , RegPassKind :: Unknown ) => {
59
+ * field2_kind = RegPassKind :: Integer {
60
+ offset_from_start ,
61
+ ty : Reg { kind : RegKind :: Integer , size : arg_layout. size } ,
62
+ } ;
62
63
}
63
64
_ => return Err ( CannotUseFpConv ) ,
64
65
}
@@ -69,12 +70,16 @@ where
69
70
}
70
71
match ( * field1_kind, * field2_kind) {
71
72
( RegPassKind :: Unknown , _) => {
72
- * field1_kind =
73
- RegPassKind :: Float ( Reg { kind : RegKind :: Float , size : arg_layout. size } ) ;
73
+ * field1_kind = RegPassKind :: Float {
74
+ offset_from_start,
75
+ ty : Reg { kind : RegKind :: Float , size : arg_layout. size } ,
76
+ } ;
74
77
}
75
78
( _, RegPassKind :: Unknown ) => {
76
- * field2_kind =
77
- RegPassKind :: Float ( Reg { kind : RegKind :: Float , size : arg_layout. size } ) ;
79
+ * field2_kind = RegPassKind :: Float {
80
+ offset_from_start,
81
+ ty : Reg { kind : RegKind :: Float , size : arg_layout. size } ,
82
+ } ;
78
83
}
79
84
_ => return Err ( CannotUseFpConv ) ,
80
85
}
@@ -96,13 +101,14 @@ where
96
101
flen,
97
102
field1_kind,
98
103
field2_kind,
104
+ offset_from_start,
99
105
) ;
100
106
}
101
107
return Err ( CannotUseFpConv ) ;
102
108
}
103
109
}
104
110
FieldsShape :: Array { count, .. } => {
105
- for _ in 0 ..count {
111
+ for i in 0 ..count {
106
112
let elem_layout = arg_layout. field ( cx, 0 ) ;
107
113
should_use_fp_conv_helper (
108
114
cx,
@@ -111,6 +117,7 @@ where
111
117
flen,
112
118
field1_kind,
113
119
field2_kind,
120
+ offset_from_start + elem_layout. size * i,
114
121
) ?;
115
122
}
116
123
}
@@ -121,7 +128,15 @@ where
121
128
}
122
129
for i in arg_layout. fields . index_by_increasing_offset ( ) {
123
130
let field = arg_layout. field ( cx, i) ;
124
- should_use_fp_conv_helper ( cx, & field, xlen, flen, field1_kind, field2_kind) ?;
131
+ should_use_fp_conv_helper (
132
+ cx,
133
+ & field,
134
+ xlen,
135
+ flen,
136
+ field1_kind,
137
+ field2_kind,
138
+ offset_from_start + arg_layout. fields . offset ( i) ,
139
+ ) ?;
125
140
}
126
141
}
127
142
} ,
@@ -140,14 +155,52 @@ where
140
155
{
141
156
let mut field1_kind = RegPassKind :: Unknown ;
142
157
let mut field2_kind = RegPassKind :: Unknown ;
143
- if should_use_fp_conv_helper ( cx, arg, xlen, flen, & mut field1_kind, & mut field2_kind) . is_err ( ) {
158
+ if should_use_fp_conv_helper (
159
+ cx,
160
+ arg,
161
+ xlen,
162
+ flen,
163
+ & mut field1_kind,
164
+ & mut field2_kind,
165
+ Size :: ZERO ,
166
+ )
167
+ . is_err ( )
168
+ {
144
169
return None ;
145
170
}
146
171
match ( field1_kind, field2_kind) {
147
- ( RegPassKind :: Integer ( l) , RegPassKind :: Float ( r) ) => Some ( FloatConv :: MixedPair ( l, r) ) ,
148
- ( RegPassKind :: Float ( l) , RegPassKind :: Integer ( r) ) => Some ( FloatConv :: MixedPair ( l, r) ) ,
149
- ( RegPassKind :: Float ( l) , RegPassKind :: Float ( r) ) => Some ( FloatConv :: FloatPair ( l, r) ) ,
150
- ( RegPassKind :: Float ( f) , RegPassKind :: Unknown ) => Some ( FloatConv :: Float ( f) ) ,
172
+ (
173
+ RegPassKind :: Integer { offset_from_start, .. }
174
+ | RegPassKind :: Float { offset_from_start, .. } ,
175
+ _,
176
+ ) if offset_from_start != Size :: ZERO => {
177
+ panic ! ( "type {:?} has a first field with non-zero offset {offset_from_start:?}" , arg. ty)
178
+ }
179
+ (
180
+ RegPassKind :: Integer { ty : first_ty, .. } ,
181
+ RegPassKind :: Float { offset_from_start, ty : second_ty } ,
182
+ ) => Some ( FloatConv :: MixedPair {
183
+ first_ty,
184
+ second_ty_offset_from_start : offset_from_start,
185
+ second_ty,
186
+ } ) ,
187
+ (
188
+ RegPassKind :: Float { ty : first_ty, .. } ,
189
+ RegPassKind :: Integer { offset_from_start, ty : second_ty } ,
190
+ ) => Some ( FloatConv :: MixedPair {
191
+ first_ty,
192
+ second_ty_offset_from_start : offset_from_start,
193
+ second_ty,
194
+ } ) ,
195
+ (
196
+ RegPassKind :: Float { ty : first_ty, .. } ,
197
+ RegPassKind :: Float { offset_from_start, ty : second_ty } ,
198
+ ) => Some ( FloatConv :: FloatPair {
199
+ first_ty,
200
+ second_ty_offset_from_start : offset_from_start,
201
+ second_ty,
202
+ } ) ,
203
+ ( RegPassKind :: Float { ty, .. } , RegPassKind :: Unknown ) => Some ( FloatConv :: Float ( ty) ) ,
151
204
_ => None ,
152
205
}
153
206
}
@@ -165,11 +218,19 @@ where
165
218
FloatConv :: Float ( f) => {
166
219
arg. cast_to ( f) ;
167
220
}
168
- FloatConv :: FloatPair ( l, r) => {
169
- arg. cast_to ( CastTarget :: pair ( l, r) ) ;
221
+ FloatConv :: FloatPair { first_ty, second_ty_offset_from_start, second_ty } => {
222
+ arg. cast_to ( CastTarget :: offset_pair (
223
+ first_ty,
224
+ second_ty_offset_from_start,
225
+ second_ty,
226
+ ) ) ;
170
227
}
171
- FloatConv :: MixedPair ( l, r) => {
172
- arg. cast_to ( CastTarget :: pair ( l, r) ) ;
228
+ FloatConv :: MixedPair { first_ty, second_ty_offset_from_start, second_ty } => {
229
+ arg. cast_to ( CastTarget :: offset_pair (
230
+ first_ty,
231
+ second_ty_offset_from_start,
232
+ second_ty,
233
+ ) ) ;
173
234
}
174
235
}
175
236
return false ;
@@ -233,15 +294,27 @@ fn classify_arg<'a, Ty, C>(
233
294
arg. cast_to ( f) ;
234
295
return ;
235
296
}
236
- Some ( FloatConv :: FloatPair ( l, r) ) if * avail_fprs >= 2 => {
297
+ Some ( FloatConv :: FloatPair { first_ty, second_ty_offset_from_start, second_ty } )
298
+ if * avail_fprs >= 2 =>
299
+ {
237
300
* avail_fprs -= 2 ;
238
- arg. cast_to ( CastTarget :: pair ( l, r) ) ;
301
+ arg. cast_to ( CastTarget :: offset_pair (
302
+ first_ty,
303
+ second_ty_offset_from_start,
304
+ second_ty,
305
+ ) ) ;
239
306
return ;
240
307
}
241
- Some ( FloatConv :: MixedPair ( l, r) ) if * avail_fprs >= 1 && * avail_gprs >= 1 => {
308
+ Some ( FloatConv :: MixedPair { first_ty, second_ty_offset_from_start, second_ty } )
309
+ if * avail_fprs >= 1 && * avail_gprs >= 1 =>
310
+ {
242
311
* avail_gprs -= 1 ;
243
312
* avail_fprs -= 1 ;
244
- arg. cast_to ( CastTarget :: pair ( l, r) ) ;
313
+ arg. cast_to ( CastTarget :: offset_pair (
314
+ first_ty,
315
+ second_ty_offset_from_start,
316
+ second_ty,
317
+ ) ) ;
245
318
return ;
246
319
}
247
320
_ => ( ) ,
0 commit comments