@@ -8,16 +8,16 @@ use crate::spec::HasTargetSpec;
88
99#[ derive( Copy , Clone ) ]
1010enum RegPassKind {
11- Float ( Reg ) ,
12- Integer ( Reg ) ,
11+ Float { offset_from_start : Size , ty : Reg } ,
12+ Integer { offset_from_start : Size , ty : Reg } ,
1313 Unknown ,
1414}
1515
1616#[ derive( Copy , Clone ) ]
1717enum FloatConv {
18- FloatPair ( Reg , Reg ) ,
18+ FloatPair { first_ty : Reg , second_ty_offset_from_start : Size , second_ty : Reg } ,
1919 Float ( Reg ) ,
20- MixedPair ( Reg , Reg ) ,
20+ MixedPair { first_ty : Reg , second_ty_offset_from_start : Size , second_ty : Reg } ,
2121}
2222
2323#[ derive( Copy , Clone ) ]
@@ -37,6 +37,7 @@ fn should_use_fp_conv_helper<'a, Ty, C>(
3737 flen : u64 ,
3838 field1_kind : & mut RegPassKind ,
3939 field2_kind : & mut RegPassKind ,
40+ offset_from_start : Size ,
4041) -> Result < ( ) , CannotUseFpConv >
4142where
4243 Ty : TyAbiInterface < ' a , C > + Copy ,
@@ -49,16 +50,16 @@ where
4950 }
5051 match ( * field1_kind, * field2_kind) {
5152 ( 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+ } ;
5657 }
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+ } ;
6263 }
6364 _ => return Err ( CannotUseFpConv ) ,
6465 }
@@ -69,12 +70,16 @@ where
6970 }
7071 match ( * field1_kind, * field2_kind) {
7172 ( 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+ } ;
7477 }
7578 ( _, 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+ } ;
7883 }
7984 _ => return Err ( CannotUseFpConv ) ,
8085 }
@@ -96,13 +101,14 @@ where
96101 flen,
97102 field1_kind,
98103 field2_kind,
104+ offset_from_start,
99105 ) ;
100106 }
101107 return Err ( CannotUseFpConv ) ;
102108 }
103109 }
104110 FieldsShape :: Array { count, .. } => {
105- for _ in 0 ..count {
111+ for i in 0 ..count {
106112 let elem_layout = arg_layout. field ( cx, 0 ) ;
107113 should_use_fp_conv_helper (
108114 cx,
@@ -111,6 +117,7 @@ where
111117 flen,
112118 field1_kind,
113119 field2_kind,
120+ offset_from_start + elem_layout. size * i,
114121 ) ?;
115122 }
116123 }
@@ -121,7 +128,15 @@ where
121128 }
122129 for i in arg_layout. fields . index_by_increasing_offset ( ) {
123130 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+ ) ?;
125140 }
126141 }
127142 } ,
@@ -140,14 +155,52 @@ where
140155{
141156 let mut field1_kind = RegPassKind :: Unknown ;
142157 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+ {
144169 return None ;
145170 }
146171 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) ) ,
151204 _ => None ,
152205 }
153206}
@@ -165,11 +218,19 @@ where
165218 FloatConv :: Float ( f) => {
166219 arg. cast_to ( f) ;
167220 }
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+ ) ) ;
170227 }
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+ ) ) ;
173234 }
174235 }
175236 return false ;
@@ -233,15 +294,27 @@ fn classify_arg<'a, Ty, C>(
233294 arg. cast_to ( f) ;
234295 return ;
235296 }
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+ {
237300 * 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+ ) ) ;
239306 return ;
240307 }
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+ {
242311 * avail_gprs -= 1 ;
243312 * 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+ ) ) ;
245318 return ;
246319 }
247320 _ => ( ) ,
0 commit comments