@@ -40,7 +40,18 @@ fn apply_attrs_to_abi_param(param: AbiParam, arg_attrs: ArgAttributes) -> AbiPar
4040    } 
4141} 
4242
43- fn  cast_target_to_abi_params ( cast :  & CastTarget )  -> SmallVec < [ AbiParam ;  2 ] >  { 
43+ fn  cast_target_to_abi_params ( cast :  & CastTarget )  -> SmallVec < [ ( Size ,  AbiParam ) ;  2 ] >  { 
44+     if  let  Some ( offset_from_start)  = cast. rest_offset  { 
45+         assert ! ( cast. prefix[ 1 ..] . iter( ) . all( |p| p. is_none( ) ) ) ; 
46+         assert_eq ! ( cast. rest. unit. size,  cast. rest. total) ; 
47+         let  first = cast. prefix [ 0 ] . unwrap ( ) ; 
48+         let  second = cast. rest . unit ; 
49+         return  smallvec ! [ 
50+             ( Size :: ZERO ,  reg_to_abi_param( first) ) , 
51+             ( offset_from_start,  reg_to_abi_param( second) ) 
52+         ] ; 
53+     } 
54+ 
4455    let  ( rest_count,  rem_bytes)  = if  cast. rest . unit . size . bytes ( )  == 0  { 
4556        ( 0 ,  0 ) 
4657    }  else  { 
@@ -55,25 +66,32 @@ fn cast_target_to_abi_params(cast: &CastTarget) -> SmallVec<[AbiParam; 2]> {
5566    // different types in Cranelift IR. Instead a single array of primitive types is used. 
5667
5768    // Create list of fields in the main structure 
58-     let  mut   args = cast
69+     let  args = cast
5970        . prefix 
6071        . iter ( ) 
6172        . flatten ( ) 
6273        . map ( |& reg| reg_to_abi_param ( reg) ) 
63-         . chain ( ( 0 ..rest_count) . map ( |_| reg_to_abi_param ( cast. rest . unit ) ) ) 
64-         . collect :: < SmallVec < _ > > ( ) ; 
74+         . chain ( ( 0 ..rest_count) . map ( |_| reg_to_abi_param ( cast. rest . unit ) ) ) ; 
75+ 
76+     let  mut  res = SmallVec :: new ( ) ; 
77+     let  mut  offset = Size :: ZERO ; 
78+ 
79+     for  arg in  args { 
80+         res. push ( ( offset,  arg) ) ; 
81+         offset += Size :: from_bytes ( arg. value_type . bytes ( ) ) ; 
82+     } 
6583
6684    // Append final integer 
6785    if  rem_bytes != 0  { 
6886        // Only integers can be really split further. 
6987        assert_eq ! ( cast. rest. unit. kind,  RegKind :: Integer ) ; 
70-         args . push ( reg_to_abi_param ( Reg   { 
71-             kind :   RegKind :: Integer , 
72-             size :  Size :: from_bytes ( rem_bytes) , 
73-         } ) ) ; 
88+         res . push ( ( 
89+             offset , 
90+             reg_to_abi_param ( Reg   {   kind :   RegKind :: Integer ,   size :  Size :: from_bytes ( rem_bytes)   } ) , 
91+         ) ) ; 
7492    } 
7593
76-     args 
94+     res 
7795} 
7896
7997impl < ' tcx >  ArgAbiExt < ' tcx >  for  ArgAbi < ' tcx ,  Ty < ' tcx > >  { 
@@ -104,7 +122,7 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
104122            } , 
105123            PassMode :: Cast  {  ref  cast,  pad_i32 }  => { 
106124                assert ! ( !pad_i32,  "padding support not yet implemented" ) ; 
107-                 cast_target_to_abi_params ( cast) 
125+                 cast_target_to_abi_params ( cast) . into_iter ( ) . map ( | ( _ ,  param ) | param ) . collect ( ) 
108126            } 
109127            PassMode :: Indirect  {  attrs,  meta_attrs :  None ,  on_stack }  => { 
110128                if  on_stack { 
@@ -160,9 +178,10 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
160178                } 
161179                _ => unreachable ! ( "{:?}" ,  self . layout. backend_repr) , 
162180            } , 
163-             PassMode :: Cast  {  ref  cast,  .. }  => { 
164-                 ( None ,  cast_target_to_abi_params ( cast) . into_iter ( ) . collect ( ) ) 
165-             } 
181+             PassMode :: Cast  {  ref  cast,  .. }  => ( 
182+                 None , 
183+                 cast_target_to_abi_params ( cast) . into_iter ( ) . map ( |( _,  param) | param) . collect ( ) , 
184+             ) , 
166185            PassMode :: Indirect  {  attrs,  meta_attrs :  None ,  on_stack }  => { 
167186                assert ! ( !on_stack) ; 
168187                ( 
@@ -187,12 +206,14 @@ pub(super) fn to_casted_value<'tcx>(
187206)  -> SmallVec < [ Value ;  2 ] >  { 
188207    let  ( ptr,  meta)  = arg. force_stack ( fx) ; 
189208    assert ! ( meta. is_none( ) ) ; 
190-     let  mut  offset = 0 ; 
191209    cast_target_to_abi_params ( cast) 
192210        . into_iter ( ) 
193-         . map ( |param| { 
194-             let  val = ptr. offset_i64 ( fx,  offset) . load ( fx,  param. value_type ,  MemFlags :: new ( ) ) ; 
195-             offset += i64:: from ( param. value_type . bytes ( ) ) ; 
211+         . map ( |( offset,  param) | { 
212+             let  val = ptr. offset_i64 ( fx,  offset. bytes ( )  as  i64 ) . load ( 
213+                 fx, 
214+                 param. value_type , 
215+                 MemFlags :: new ( ) , 
216+             ) ; 
196217            val
197218        } ) 
198219        . collect ( ) 
@@ -205,7 +226,7 @@ pub(super) fn from_casted_value<'tcx>(
205226    cast :  & CastTarget , 
206227)  -> CValue < ' tcx >  { 
207228    let  abi_params = cast_target_to_abi_params ( cast) ; 
208-     let  abi_param_size:  u32  = abi_params. iter ( ) . map ( |param| param. value_type . bytes ( ) ) . sum ( ) ; 
229+     let  abi_param_size:  u32  = abi_params. iter ( ) . map ( |( _ ,   param) | param. value_type . bytes ( ) ) . sum ( ) ; 
209230    let  layout_size = u32:: try_from ( layout. size . bytes ( ) ) . unwrap ( ) ; 
210231    let  ptr = fx. create_stack_slot ( 
211232        // Stack slot size may be bigger for example `[u8; 3]` which is packed into an `i32`. 
@@ -214,16 +235,13 @@ pub(super) fn from_casted_value<'tcx>(
214235        std:: cmp:: max ( abi_param_size,  layout_size) , 
215236        u32:: try_from ( layout. align . abi . bytes ( ) ) . unwrap ( ) , 
216237    ) ; 
217-     let  mut  offset = 0 ; 
218238    let  mut  block_params_iter = block_params. iter ( ) . copied ( ) ; 
219-     for  param  in  abi_params { 
220-         let  val =  ptr. offset_i64 ( fx,  offset) . store ( 
239+     for  ( offset ,  _ )  in  abi_params { 
240+         ptr. offset_i64 ( fx,  offset. bytes ( )   as   i64 ) . store ( 
221241            fx, 
222242            block_params_iter. next ( ) . unwrap ( ) , 
223243            MemFlags :: new ( ) , 
224-         ) ; 
225-         offset += i64:: from ( param. value_type . bytes ( ) ) ; 
226-         val
244+         ) 
227245    } 
228246    assert_eq ! ( block_params_iter. next( ) ,  None ,  "Leftover block param" ) ; 
229247    CValue :: by_ref ( ptr,  layout) 
0 commit comments