@@ -40,7 +40,18 @@ fn apply_attrs_to_abi_param(param: AbiParam, arg_attrs: ArgAttributes) -> AbiPar
40
40
}
41
41
}
42
42
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
+
44
55
let (rest_count, rem_bytes) = if cast.rest.unit.size.bytes() == 0 {
45
56
(0, 0)
46
57
} else {
@@ -55,25 +66,32 @@ fn cast_target_to_abi_params(cast: &CastTarget) -> SmallVec<[AbiParam; 2]> {
55
66
// different types in Cranelift IR. Instead a single array of primitive types is used.
56
67
57
68
// Create list of fields in the main structure
58
- let mut args = cast
69
+ let args = cast
59
70
.prefix
60
71
.iter()
61
72
.flatten()
62
73
.map(|®| 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
+ }
65
83
66
84
// Append final integer
67
85
if rem_bytes != 0 {
68
86
// Only integers can be really split further.
69
87
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
+ ));
74
92
}
75
93
76
- args
94
+ res
77
95
}
78
96
79
97
impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
@@ -104,7 +122,7 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
104
122
},
105
123
PassMode::Cast { ref cast, pad_i32 } => {
106
124
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()
108
126
}
109
127
PassMode::Indirect { attrs, meta_attrs: None, on_stack } => {
110
128
if on_stack {
@@ -160,9 +178,10 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
160
178
}
161
179
_ => unreachable!("{:?}", self.layout.backend_repr),
162
180
},
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
+ ),
166
185
PassMode::Indirect { attrs, meta_attrs: None, on_stack } => {
167
186
assert!(!on_stack);
168
187
(
@@ -187,12 +206,14 @@ pub(super) fn to_casted_value<'tcx>(
187
206
) -> SmallVec<[Value; 2]> {
188
207
let (ptr, meta) = arg.force_stack(fx);
189
208
assert!(meta.is_none());
190
- let mut offset = 0;
191
209
cast_target_to_abi_params(cast)
192
210
.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
+ );
196
217
val
197
218
})
198
219
.collect()
@@ -205,7 +226,7 @@ pub(super) fn from_casted_value<'tcx>(
205
226
cast: &CastTarget,
206
227
) -> CValue<'tcx> {
207
228
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();
209
230
let layout_size = u32::try_from(layout.size.bytes()).unwrap();
210
231
let ptr = fx.create_stack_slot(
211
232
// 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>(
214
235
std::cmp::max(abi_param_size, layout_size),
215
236
u32::try_from(layout.align.abi.bytes()).unwrap(),
216
237
);
217
- let mut offset = 0;
218
238
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(
221
241
fx,
222
242
block_params_iter.next().unwrap(),
223
243
MemFlags::new(),
224
- );
225
- offset += i64::from(param.value_type.bytes());
226
- val
244
+ )
227
245
}
228
246
assert_eq!(block_params_iter.next(), None, "Leftover block param");
229
247
CValue::by_ref(ptr, layout)
0 commit comments