about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbjorn3 <bjorn3@users.noreply.github.com>2021-01-30 17:22:10 +0100
committerbjorn3 <bjorn3@users.noreply.github.com>2021-01-30 17:26:51 +0100
commitf3447682d0534f03f7b0195ea8e736f152095718 (patch)
treea3eaf0f1ec0e9c3cbd802f8c4aa4eda3d718688e
parent18de1b1fde169e76c3f4941b9c8b8c009221d618 (diff)
downloadrust-f3447682d0534f03f7b0195ea8e736f152095718.tar.gz
rust-f3447682d0534f03f7b0195ea8e736f152095718.zip
Handle PassMode::Cast in combination with #[repr(align)]
-rw-r--r--src/abi/pass_mode.rs10
1 files changed, 6 insertions, 4 deletions
diff --git a/src/abi/pass_mode.rs b/src/abi/pass_mode.rs
index 2f91e83386c..1202c23dbe7 100644
--- a/src/abi/pass_mode.rs
+++ b/src/abi/pass_mode.rs
@@ -227,17 +227,19 @@ pub(super) fn from_casted_value<'tcx>(
     cast: CastTarget,
 ) -> CValue<'tcx> {
     let abi_params = cast_target_to_abi_params(cast);
-    let size: u32 = abi_params
+    let abi_param_size: u32 = abi_params
         .iter()
         .map(|param| param.value_type.bytes())
         .sum();
-    // Stack slot size may be bigger for for example `[u8; 3]` which is packed into an `i32`.
-    assert!(u64::from(size) >= layout.size.bytes());
+    let layout_size = u32::try_from(layout.size.bytes()).unwrap();
     let stack_slot = fx.bcx.create_stack_slot(StackSlotData {
         kind: StackSlotKind::ExplicitSlot,
         // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to
         // specify stack slot alignment.
-        size: (size + 15) / 16 * 16,
+        // Stack slot size may be bigger for for example `[u8; 3]` which is packed into an `i32`.
+        // It may also be smaller for example when the type is a wrapper around an integer with a
+        // larger alignment than the integer.
+        size: (std::cmp::max(abi_param_size, layout_size) + 15) / 16 * 16,
         offset: None,
     });
     let ptr = Pointer::new(fx.bcx.ins().stack_addr(pointer_ty(fx.tcx), stack_slot, 0));