@@ -41,7 +41,18 @@ fn apply_arg_attrs_to_abi_param(mut param: AbiParam, arg_attrs: ArgAttributes) -
4141 param
4242}
4343
44- fn cast_target_to_abi_params ( cast : & CastTarget ) -> SmallVec < [ AbiParam ; 2 ] > {
44+ fn cast_target_to_abi_params ( cast : & CastTarget ) -> SmallVec < [ ( Size , AbiParam ) ; 2 ] > {
45+ if let Some ( offset_from_start) = cast. rest_offset {
46+ assert ! ( cast. prefix[ 1 ..] . iter( ) . all( |p| p. is_none( ) ) ) ;
47+ assert_eq ! ( cast. rest. unit. size, cast. rest. total) ;
48+ let first = cast. prefix [ 0 ] . unwrap ( ) ;
49+ let second = cast. rest . unit ;
50+ return smallvec ! [
51+ ( Size :: ZERO , reg_to_abi_param( first) ) ,
52+ ( offset_from_start, reg_to_abi_param( second) )
53+ ] ;
54+ }
55+
4556 let ( rest_count, rem_bytes) = if cast. rest . unit . size . bytes ( ) == 0 {
4657 ( 0 , 0 )
4758 } else {
@@ -56,25 +67,32 @@ fn cast_target_to_abi_params(cast: &CastTarget) -> SmallVec<[AbiParam; 2]> {
5667 // different types in Cranelift IR. Instead a single array of primitive types is used.
5768
5869 // Create list of fields in the main structure
59- let mut args = cast
70+ let args = cast
6071 . prefix
6172 . iter ( )
6273 . flatten ( )
6374 . map ( |& reg| reg_to_abi_param ( reg) )
64- . chain ( ( 0 ..rest_count) . map ( |_| reg_to_abi_param ( cast. rest . unit ) ) )
65- . collect :: < SmallVec < _ > > ( ) ;
75+ . chain ( ( 0 ..rest_count) . map ( |_| reg_to_abi_param ( cast. rest . unit ) ) ) ;
76+
77+ let mut res = SmallVec :: new ( ) ;
78+ let mut offset = Size :: ZERO ;
79+
80+ for arg in args {
81+ res. push ( ( offset, arg) ) ;
82+ offset += Size :: from_bytes ( arg. value_type . bytes ( ) ) ;
83+ }
6684
6785 // Append final integer
6886 if rem_bytes != 0 {
6987 // Only integers can be really split further.
7088 assert_eq ! ( cast. rest. unit. kind, RegKind :: Integer ) ;
71- args . push ( reg_to_abi_param ( Reg {
72- kind : RegKind :: Integer ,
73- size : Size :: from_bytes ( rem_bytes) ,
74- } ) ) ;
89+ res . push ( (
90+ offset ,
91+ reg_to_abi_param ( Reg { kind : RegKind :: Integer , size : Size :: from_bytes ( rem_bytes) } ) ,
92+ ) ) ;
7593 }
7694
77- args
95+ res
7896}
7997
8098impl < ' tcx > ArgAbiExt < ' tcx > for ArgAbi < ' tcx , Ty < ' tcx > > {
@@ -105,7 +123,7 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
105123 } ,
106124 PassMode :: Cast { ref cast, pad_i32 } => {
107125 assert ! ( !pad_i32, "padding support not yet implemented" ) ;
108- cast_target_to_abi_params ( cast)
126+ cast_target_to_abi_params ( cast) . into_iter ( ) . map ( | ( _ , param ) | param ) . collect ( )
109127 }
110128 PassMode :: Indirect { attrs, meta_attrs : None , on_stack } => {
111129 if on_stack {
@@ -151,9 +169,10 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
151169 }
152170 _ => unreachable ! ( "{:?}" , self . layout. backend_repr) ,
153171 } ,
154- PassMode :: Cast { ref cast, .. } => {
155- ( None , cast_target_to_abi_params ( cast) . into_iter ( ) . collect ( ) )
156- }
172+ PassMode :: Cast { ref cast, .. } => (
173+ None ,
174+ cast_target_to_abi_params ( cast) . into_iter ( ) . map ( |( _, param) | param) . collect ( ) ,
175+ ) ,
157176 PassMode :: Indirect { attrs : _, meta_attrs : None , on_stack } => {
158177 assert ! ( !on_stack) ;
159178 ( Some ( AbiParam :: special ( pointer_ty ( tcx) , ArgumentPurpose :: StructReturn ) ) , vec ! [ ] )
@@ -172,12 +191,14 @@ pub(super) fn to_casted_value<'tcx>(
172191) -> SmallVec < [ Value ; 2 ] > {
173192 let ( ptr, meta) = arg. force_stack ( fx) ;
174193 assert ! ( meta. is_none( ) ) ;
175- let mut offset = 0 ;
176194 cast_target_to_abi_params ( cast)
177195 . into_iter ( )
178- . map ( |param| {
179- let val = ptr. offset_i64 ( fx, offset) . load ( fx, param. value_type , MemFlags :: new ( ) ) ;
180- offset += i64:: from ( param. value_type . bytes ( ) ) ;
196+ . map ( |( offset, param) | {
197+ let val = ptr. offset_i64 ( fx, offset. bytes ( ) as i64 ) . load (
198+ fx,
199+ param. value_type ,
200+ MemFlags :: new ( ) ,
201+ ) ;
181202 val
182203 } )
183204 . collect ( )
@@ -190,7 +211,7 @@ pub(super) fn from_casted_value<'tcx>(
190211 cast : & CastTarget ,
191212) -> CValue < ' tcx > {
192213 let abi_params = cast_target_to_abi_params ( cast) ;
193- let abi_param_size: u32 = abi_params. iter ( ) . map ( |param| param. value_type . bytes ( ) ) . sum ( ) ;
214+ let abi_param_size: u32 = abi_params. iter ( ) . map ( |( _ , param) | param. value_type . bytes ( ) ) . sum ( ) ;
194215 let layout_size = u32:: try_from ( layout. size . bytes ( ) ) . unwrap ( ) ;
195216 let ptr = fx. create_stack_slot (
196217 // Stack slot size may be bigger for example `[u8; 3]` which is packed into an `i32`.
@@ -199,16 +220,13 @@ pub(super) fn from_casted_value<'tcx>(
199220 std:: cmp:: max ( abi_param_size, layout_size) ,
200221 u32:: try_from ( layout. align . abi . bytes ( ) ) . unwrap ( ) ,
201222 ) ;
202- let mut offset = 0 ;
203223 let mut block_params_iter = block_params. iter ( ) . copied ( ) ;
204- for param in abi_params {
205- let val = ptr. offset_i64 ( fx, offset) . store (
224+ for ( offset , _ ) in abi_params {
225+ ptr. offset_i64 ( fx, offset. bytes ( ) as i64 ) . store (
206226 fx,
207227 block_params_iter. next ( ) . unwrap ( ) ,
208228 MemFlags :: new ( ) ,
209- ) ;
210- offset += i64:: from ( param. value_type . bytes ( ) ) ;
211- val
229+ )
212230 }
213231 assert_eq ! ( block_params_iter. next( ) , None , "Leftover block param" ) ;
214232 CValue :: by_ref ( ptr, layout)
0 commit comments