From 55380a5ffd72bb2ab601e911409cdd092a2740d9 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 22 Oct 2023 17:11:11 +0000 Subject: [PATCH] Dynamically realign local variables with large alignment This works around the lack of a way to specify the alignment of a stack slot in Cranelift. Fixes #1230 Fixes #1381 --- example/mini_core_hello_world.rs | 11 +++++++++++ src/common.rs | 29 ++++++++++++++++++++++------- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index 58670b33c7b..3e4edcf6f54 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -353,6 +353,17 @@ fn main() { let f = V([0.0, 1.0]); let _a = f.0[0]; + + stack_val_align(); +} + +#[inline(never)] +fn stack_val_align() { + #[repr(align(8192))] + struct Foo(u8); + + let a = Foo(0); + assert_eq!(&a as *const Foo as usize % 8192, 0); } #[cfg(all( diff --git a/src/common.rs b/src/common.rs index d306471e970..7a0b04c09cc 100644 --- a/src/common.rs +++ b/src/common.rs @@ -384,13 +384,28 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { } pub(crate) fn create_stack_slot(&mut self, size: u32, align: u32) -> Pointer { - let stack_slot = self.bcx.create_sized_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, - }); - Pointer::stack_slot(stack_slot) + if align <= 16 { + let stack_slot = self.bcx.create_sized_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, + }); + Pointer::stack_slot(stack_slot) + } else { + // Alignment is too big to handle using the above hack. Dynamically realign a stack slot + // instead. This wastes some space for the realignment. + let stack_slot = self.bcx.create_sized_stack_slot(StackSlotData { + kind: StackSlotKind::ExplicitSlot, + // FIXME is this calculation to ensure there is enough space to dyanmically realign + // as well as keep a 16 byte realignment for the other stack slots correct? + size: ((size + align - 1) + 16) / 16 * 16, + }); + let base_ptr = self.bcx.ins().stack_addr(self.pointer_type, stack_slot, 0); + let misalign_offset = self.bcx.ins().urem_imm(base_ptr, i64::from(align)); + let realign_offset = self.bcx.ins().irsub_imm(misalign_offset, i64::from(align)); + Pointer::new(self.bcx.ins().iadd(base_ptr, realign_offset)) + } } pub(crate) fn set_debug_loc(&mut self, source_info: mir::SourceInfo) {