From d7274ac5fdf84452cdfd09727e106bac2bf50e36 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sun, 23 Jun 2019 15:14:26 +0200 Subject: [PATCH] Fix load and store for ByValPair values with differently sized components --- example/std_example.rs | 15 ++++++++++ src/value_and_place.rs | 62 ++++++++++++------------------------------ 2 files changed, 33 insertions(+), 44 deletions(-) diff --git a/example/std_example.rs b/example/std_example.rs index ce74efee8a88..805a51ec219d 100644 --- a/example/std_example.rs +++ b/example/std_example.rs @@ -17,6 +17,9 @@ fn main() { ONCE.call_once(|| {}); LoopState::Continue(()) == LoopState::Break(()); + + // Make sure ByValPair values with differently sized components are correctly passed + map(None::<(u8, Box)>); } #[derive(PartialEq)] @@ -24,3 +27,15 @@ enum LoopState { Continue(()), Break(()) } + +pub enum Instruction { + Increment, + Loop, +} + +fn map(a: Option<(u8, Box)>) -> Option> { + match a { + None => None, + Some((_, instr)) => Some(instr), + } +} diff --git a/src/value_and_place.rs b/src/value_and_place.rs index bf027dd3e88a..716a81c5d8af 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -18,6 +18,11 @@ fn codegen_field<'a, 'tcx: 'a>( } } +fn scalar_pair_calculate_b_offset(tcx: TyCtxt<'_>, a_scalar: &Scalar, b_scalar: &Scalar) -> i32 { + let b_offset = a_scalar.value.size(&tcx).align_to(b_scalar.value.align(&tcx).abi); + b_offset.bytes().try_into().unwrap() +} + /// A read-only value #[derive(Debug, Copy, Clone)] pub struct CValue<'tcx>(CValueInner, TyLayout<'tcx>); @@ -89,18 +94,19 @@ impl<'tcx> CValue<'tcx> { let layout = self.1; match self.0 { CValueInner::ByRef(addr) => { - let (a, b) = match &layout.abi { - layout::Abi::ScalarPair(a, b) => (a.clone(), b.clone()), + let (a_scalar, b_scalar) = match &layout.abi { + layout::Abi::ScalarPair(a, b) => (a, b), _ => unreachable!(), }; - let clif_ty1 = scalar_to_clif_type(fx.tcx, a.clone()); - let clif_ty2 = scalar_to_clif_type(fx.tcx, b); + let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar); + let clif_ty1 = scalar_to_clif_type(fx.tcx, a_scalar.clone()); + let clif_ty2 = scalar_to_clif_type(fx.tcx, b_scalar.clone()); let val1 = fx.bcx.ins().load(clif_ty1, MemFlags::new(), addr, 0); let val2 = fx.bcx.ins().load( clif_ty2, MemFlags::new(), addr, - a.value.size(&fx.tcx).bytes() as i32, + b_offset, ); (val1, val2) } @@ -341,13 +347,14 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> { } CValueInner::ByValPair(value, extra) => { match dst_layout.abi { - Abi::ScalarPair(ref a, _) => { + Abi::ScalarPair(ref a_scalar, ref b_scalar) => { + let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar); fx.bcx.ins().store(MemFlags::new(), value, addr, 0); fx.bcx.ins().store( MemFlags::new(), extra, addr, - a.value.size(&fx.tcx).bytes() as u32 as i32, + b_offset, ); } _ => bug!( @@ -415,26 +422,8 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> { if !inner_layout.is_unsized() { CPlace::Addr(self.to_cvalue(fx).load_scalar(fx), None, inner_layout) } else { - match self.layout().abi { - Abi::ScalarPair(ref a, ref b) => { - let addr = self.to_addr(fx); - let ptr = - fx.bcx - .ins() - .load(scalar_to_clif_type(fx.tcx, a.clone()), MemFlags::new(), addr, 0); - let extra = fx.bcx.ins().load( - scalar_to_clif_type(fx.tcx, b.clone()), - MemFlags::new(), - addr, - a.value.size(&fx.tcx).bytes() as u32 as i32, - ); - CPlace::Addr(ptr, Some(extra), inner_layout) - } - _ => bug!( - "Fat ptr doesn't have abi ScalarPair, but it has {:?}", - self.layout().abi - ), - } + let (addr, extra) = self.to_cvalue(fx).load_scalar_pair(fx); + CPlace::Addr(addr, Some(extra), inner_layout) } } @@ -444,23 +433,8 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> { dest.write_cvalue(fx, ptr); } else { let (value, extra) = self.to_addr_maybe_unsized(fx); - - match dest.layout().abi { - Abi::ScalarPair(ref a, _) => { - let dest_addr = dest.to_addr(fx); - fx.bcx.ins().store(MemFlags::new(), value, dest_addr, 0); - fx.bcx.ins().store( - MemFlags::new(), - extra.expect("unsized type without metadata"), - dest_addr, - a.value.size(&fx.tcx).bytes() as u32 as i32, - ); - } - _ => bug!( - "Non ScalarPair abi {:?} in write_place_ref dest", - dest.layout().abi - ), - } + let ptr = CValue::by_val_pair(value, extra.expect("unsized type without metadata"), dest.layout()); + dest.write_cvalue(fx, ptr); } }