about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbjorn3 <bjorn3@users.noreply.github.com>2019-06-23 15:14:26 +0200
committerbjorn3 <bjorn3@users.noreply.github.com>2019-06-23 15:23:06 +0200
commitd7274ac5fdf84452cdfd09727e106bac2bf50e36 (patch)
tree6851bbf0442d565ad9295ec48f091c9a9bfa9f78
parent05307af6729a9df0375f063c4b2417366057e058 (diff)
downloadrust-d7274ac5fdf84452cdfd09727e106bac2bf50e36.tar.gz
rust-d7274ac5fdf84452cdfd09727e106bac2bf50e36.zip
Fix load and store for ByValPair values with differently sized components
-rw-r--r--example/std_example.rs15
-rw-r--r--src/value_and_place.rs62
2 files changed, 33 insertions, 44 deletions
diff --git a/example/std_example.rs b/example/std_example.rs
index ce74efee8a8..805a51ec219 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<Instruction>)>);
 }
 
 #[derive(PartialEq)]
@@ -24,3 +27,15 @@ enum LoopState {
     Continue(()),
     Break(())
 }
+
+pub enum Instruction {
+    Increment,
+    Loop,
+}
+
+fn map(a: Option<(u8, Box<Instruction>)>) -> Option<Box<Instruction>> {
+    match a {
+        None => None,
+        Some((_, instr)) => Some(instr),
+    }
+}
diff --git a/src/value_and_place.rs b/src/value_and_place.rs
index bf027dd3e88..716a81c5d8a 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);
         }
     }