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