@@ -39,7 +39,18 @@ fn apply_arg_attrs_to_abi_param(mut param: AbiParam, arg_attrs: ArgAttributes) -
39
39
param
40
40
}
41
41
42
- fn cast_target_to_abi_params ( cast : & CastTarget ) -> SmallVec < [ AbiParam ; 2 ] > {
42
+ fn cast_target_to_abi_params ( cast : & CastTarget ) -> SmallVec < [ ( Size , AbiParam ) ; 2 ] > {
43
+ if let Some ( offset_from_start) = cast. rest_offset {
44
+ assert ! ( cast. prefix[ 1 ..] . iter( ) . all( |p| p. is_none( ) ) ) ;
45
+ assert_eq ! ( cast. rest. unit. size, cast. rest. total) ;
46
+ let first = cast. prefix [ 0 ] . unwrap ( ) ;
47
+ let second = cast. rest . unit ;
48
+ return smallvec ! [
49
+ ( Size :: ZERO , reg_to_abi_param( first) ) ,
50
+ ( offset_from_start, reg_to_abi_param( second) )
51
+ ] ;
52
+ }
53
+
43
54
let ( rest_count, rem_bytes) = if cast. rest . unit . size . bytes ( ) == 0 {
44
55
( 0 , 0 )
45
56
} else {
@@ -54,25 +65,31 @@ fn cast_target_to_abi_params(cast: &CastTarget) -> SmallVec<[AbiParam; 2]> {
54
65
// different types in Cranelift IR. Instead a single array of primitive types is used.
55
66
56
67
// Create list of fields in the main structure
57
- let mut args = cast
68
+ let args = cast
58
69
. prefix
59
70
. iter ( )
60
71
. flatten ( )
61
72
. map ( |& reg| reg_to_abi_param ( reg) )
62
- . chain ( ( 0 ..rest_count) . map ( |_| reg_to_abi_param ( cast. rest . unit ) ) )
63
- . collect :: < SmallVec < _ > > ( ) ;
73
+ . chain ( ( 0 ..rest_count) . map ( |_| reg_to_abi_param ( cast. rest . unit ) ) ) ;
64
74
65
75
// Append final integer
66
- if rem_bytes != 0 {
76
+ let args = args . chain ( if rem_bytes != 0 {
67
77
// Only integers can be really split further.
68
78
assert_eq ! ( cast. rest. unit. kind, RegKind :: Integer ) ;
69
- args. push ( reg_to_abi_param ( Reg {
70
- kind : RegKind :: Integer ,
71
- size : Size :: from_bytes ( rem_bytes) ,
72
- } ) ) ;
79
+ Some ( reg_to_abi_param ( Reg { kind : RegKind :: Integer , size : Size :: from_bytes ( rem_bytes) } ) )
80
+ } else {
81
+ None
82
+ } ) ;
83
+
84
+ let mut res = SmallVec :: new ( ) ;
85
+ let mut offset = Size :: ZERO ;
86
+
87
+ for arg in args {
88
+ res. push ( ( offset, arg) ) ;
89
+ offset += Size :: from_bytes ( arg. value_type . bytes ( ) ) ;
73
90
}
74
91
75
- args
92
+ res
76
93
}
77
94
78
95
impl < ' tcx > ArgAbiExt < ' tcx > for ArgAbi < ' tcx , Ty < ' tcx > > {
@@ -103,7 +120,7 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
103
120
} ,
104
121
PassMode :: Cast { ref cast, pad_i32 } => {
105
122
assert ! ( !pad_i32, "padding support not yet implemented" ) ;
106
- cast_target_to_abi_params ( cast)
123
+ cast_target_to_abi_params ( cast) . into_iter ( ) . map ( | ( _ , param ) | param ) . collect ( )
107
124
}
108
125
PassMode :: Indirect { attrs, meta_attrs : None , on_stack } => {
109
126
if on_stack {
@@ -149,9 +166,10 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
149
166
}
150
167
_ => unreachable ! ( "{:?}" , self . layout. backend_repr) ,
151
168
} ,
152
- PassMode :: Cast { ref cast, .. } => {
153
- ( None , cast_target_to_abi_params ( cast) . into_iter ( ) . collect ( ) )
154
- }
169
+ PassMode :: Cast { ref cast, .. } => (
170
+ None ,
171
+ cast_target_to_abi_params ( cast) . into_iter ( ) . map ( |( _, param) | param) . collect ( ) ,
172
+ ) ,
155
173
PassMode :: Indirect { attrs : _, meta_attrs : None , on_stack } => {
156
174
assert ! ( !on_stack) ;
157
175
( Some ( AbiParam :: special ( pointer_ty ( tcx) , ArgumentPurpose :: StructReturn ) ) , vec ! [ ] )
@@ -170,12 +188,14 @@ pub(super) fn to_casted_value<'tcx>(
170
188
) -> SmallVec < [ Value ; 2 ] > {
171
189
let ( ptr, meta) = arg. force_stack ( fx) ;
172
190
assert ! ( meta. is_none( ) ) ;
173
- let mut offset = 0 ;
174
191
cast_target_to_abi_params ( cast)
175
192
. into_iter ( )
176
- . map ( |param| {
177
- let val = ptr. offset_i64 ( fx, offset) . load ( fx, param. value_type , MemFlags :: new ( ) ) ;
178
- offset += i64:: from ( param. value_type . bytes ( ) ) ;
193
+ . map ( |( offset, param) | {
194
+ let val = ptr. offset_i64 ( fx, offset. bytes ( ) as i64 ) . load (
195
+ fx,
196
+ param. value_type ,
197
+ MemFlags :: new ( ) ,
198
+ ) ;
179
199
val
180
200
} )
181
201
. collect ( )
@@ -188,7 +208,7 @@ pub(super) fn from_casted_value<'tcx>(
188
208
cast : & CastTarget ,
189
209
) -> CValue < ' tcx > {
190
210
let abi_params = cast_target_to_abi_params ( cast) ;
191
- let abi_param_size: u32 = abi_params. iter ( ) . map ( |param| param. value_type . bytes ( ) ) . sum ( ) ;
211
+ let abi_param_size: u32 = abi_params. iter ( ) . map ( |( _ , param) | param. value_type . bytes ( ) ) . sum ( ) ;
192
212
let layout_size = u32:: try_from ( layout. size . bytes ( ) ) . unwrap ( ) ;
193
213
let ptr = fx. create_stack_slot (
194
214
// Stack slot size may be bigger for example `[u8; 3]` which is packed into an `i32`.
@@ -197,16 +217,13 @@ pub(super) fn from_casted_value<'tcx>(
197
217
std:: cmp:: max ( abi_param_size, layout_size) ,
198
218
u32:: try_from ( layout. align . abi . bytes ( ) ) . unwrap ( ) ,
199
219
) ;
200
- let mut offset = 0 ;
201
220
let mut block_params_iter = block_params. iter ( ) . copied ( ) ;
202
- for param in abi_params {
203
- let val = ptr. offset_i64 ( fx, offset) . store (
221
+ for ( offset , _ ) in abi_params {
222
+ ptr. offset_i64 ( fx, offset. bytes ( ) as i64 ) . store (
204
223
fx,
205
224
block_params_iter. next ( ) . unwrap ( ) ,
206
225
MemFlags :: new ( ) ,
207
- ) ;
208
- offset += i64:: from ( param. value_type . bytes ( ) ) ;
209
- val
226
+ )
210
227
}
211
228
assert_eq ! ( block_params_iter. next( ) , None , "Leftover block param" ) ;
212
229
CValue :: by_ref ( ptr, layout)
0 commit comments