Skip to content

Commit d7274ac

Browse files
committed
Fix load and store for ByValPair values with differently sized components
1 parent 05307af commit d7274ac

File tree

2 files changed

+33
-44
lines changed

2 files changed

+33
-44
lines changed

example/std_example.rs

+15
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,25 @@ fn main() {
1717
ONCE.call_once(|| {});
1818

1919
LoopState::Continue(()) == LoopState::Break(());
20+
21+
// Make sure ByValPair values with differently sized components are correctly passed
22+
map(None::<(u8, Box<Instruction>)>);
2023
}
2124

2225
#[derive(PartialEq)]
2326
enum LoopState {
2427
Continue(()),
2528
Break(())
2629
}
30+
31+
pub enum Instruction {
32+
Increment,
33+
Loop,
34+
}
35+
36+
fn map(a: Option<(u8, Box<Instruction>)>) -> Option<Box<Instruction>> {
37+
match a {
38+
None => None,
39+
Some((_, instr)) => Some(instr),
40+
}
41+
}

src/value_and_place.rs

+18-44
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ fn codegen_field<'a, 'tcx: 'a>(
1818
}
1919
}
2020

21+
fn scalar_pair_calculate_b_offset(tcx: TyCtxt<'_>, a_scalar: &Scalar, b_scalar: &Scalar) -> i32 {
22+
let b_offset = a_scalar.value.size(&tcx).align_to(b_scalar.value.align(&tcx).abi);
23+
b_offset.bytes().try_into().unwrap()
24+
}
25+
2126
/// A read-only value
2227
#[derive(Debug, Copy, Clone)]
2328
pub struct CValue<'tcx>(CValueInner, TyLayout<'tcx>);
@@ -89,18 +94,19 @@ impl<'tcx> CValue<'tcx> {
8994
let layout = self.1;
9095
match self.0 {
9196
CValueInner::ByRef(addr) => {
92-
let (a, b) = match &layout.abi {
93-
layout::Abi::ScalarPair(a, b) => (a.clone(), b.clone()),
97+
let (a_scalar, b_scalar) = match &layout.abi {
98+
layout::Abi::ScalarPair(a, b) => (a, b),
9499
_ => unreachable!(),
95100
};
96-
let clif_ty1 = scalar_to_clif_type(fx.tcx, a.clone());
97-
let clif_ty2 = scalar_to_clif_type(fx.tcx, b);
101+
let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
102+
let clif_ty1 = scalar_to_clif_type(fx.tcx, a_scalar.clone());
103+
let clif_ty2 = scalar_to_clif_type(fx.tcx, b_scalar.clone());
98104
let val1 = fx.bcx.ins().load(clif_ty1, MemFlags::new(), addr, 0);
99105
let val2 = fx.bcx.ins().load(
100106
clif_ty2,
101107
MemFlags::new(),
102108
addr,
103-
a.value.size(&fx.tcx).bytes() as i32,
109+
b_offset,
104110
);
105111
(val1, val2)
106112
}
@@ -341,13 +347,14 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
341347
}
342348
CValueInner::ByValPair(value, extra) => {
343349
match dst_layout.abi {
344-
Abi::ScalarPair(ref a, _) => {
350+
Abi::ScalarPair(ref a_scalar, ref b_scalar) => {
351+
let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
345352
fx.bcx.ins().store(MemFlags::new(), value, addr, 0);
346353
fx.bcx.ins().store(
347354
MemFlags::new(),
348355
extra,
349356
addr,
350-
a.value.size(&fx.tcx).bytes() as u32 as i32,
357+
b_offset,
351358
);
352359
}
353360
_ => bug!(
@@ -415,26 +422,8 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
415422
if !inner_layout.is_unsized() {
416423
CPlace::Addr(self.to_cvalue(fx).load_scalar(fx), None, inner_layout)
417424
} else {
418-
match self.layout().abi {
419-
Abi::ScalarPair(ref a, ref b) => {
420-
let addr = self.to_addr(fx);
421-
let ptr =
422-
fx.bcx
423-
.ins()
424-
.load(scalar_to_clif_type(fx.tcx, a.clone()), MemFlags::new(), addr, 0);
425-
let extra = fx.bcx.ins().load(
426-
scalar_to_clif_type(fx.tcx, b.clone()),
427-
MemFlags::new(),
428-
addr,
429-
a.value.size(&fx.tcx).bytes() as u32 as i32,
430-
);
431-
CPlace::Addr(ptr, Some(extra), inner_layout)
432-
}
433-
_ => bug!(
434-
"Fat ptr doesn't have abi ScalarPair, but it has {:?}",
435-
self.layout().abi
436-
),
437-
}
425+
let (addr, extra) = self.to_cvalue(fx).load_scalar_pair(fx);
426+
CPlace::Addr(addr, Some(extra), inner_layout)
438427
}
439428
}
440429

@@ -444,23 +433,8 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
444433
dest.write_cvalue(fx, ptr);
445434
} else {
446435
let (value, extra) = self.to_addr_maybe_unsized(fx);
447-
448-
match dest.layout().abi {
449-
Abi::ScalarPair(ref a, _) => {
450-
let dest_addr = dest.to_addr(fx);
451-
fx.bcx.ins().store(MemFlags::new(), value, dest_addr, 0);
452-
fx.bcx.ins().store(
453-
MemFlags::new(),
454-
extra.expect("unsized type without metadata"),
455-
dest_addr,
456-
a.value.size(&fx.tcx).bytes() as u32 as i32,
457-
);
458-
}
459-
_ => bug!(
460-
"Non ScalarPair abi {:?} in write_place_ref dest",
461-
dest.layout().abi
462-
),
463-
}
436+
let ptr = CValue::by_val_pair(value, extra.expect("unsized type without metadata"), dest.layout());
437+
dest.write_cvalue(fx, ptr);
464438
}
465439
}
466440

0 commit comments

Comments
 (0)