@@ -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