Skip to content

Commit 55380a5

Browse files
committed
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
1 parent 38e8be9 commit 55380a5

File tree

2 files changed

+33
-7
lines changed

2 files changed

+33
-7
lines changed

example/mini_core_hello_world.rs

+11
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,17 @@ fn main() {
353353

354354
let f = V([0.0, 1.0]);
355355
let _a = f.0[0];
356+
357+
stack_val_align();
358+
}
359+
360+
#[inline(never)]
361+
fn stack_val_align() {
362+
#[repr(align(8192))]
363+
struct Foo(u8);
364+
365+
let a = Foo(0);
366+
assert_eq!(&a as *const Foo as usize % 8192, 0);
356367
}
357368

358369
#[cfg(all(

src/common.rs

+22-7
Original file line numberDiff line numberDiff line change
@@ -384,13 +384,28 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
384384
}
385385

386386
pub(crate) fn create_stack_slot(&mut self, size: u32, align: u32) -> Pointer {
387-
let stack_slot = self.bcx.create_sized_stack_slot(StackSlotData {
388-
kind: StackSlotKind::ExplicitSlot,
389-
// FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to
390-
// specify stack slot alignment.
391-
size: (size + 15) / 16 * 16,
392-
});
393-
Pointer::stack_slot(stack_slot)
387+
if align <= 16 {
388+
let stack_slot = self.bcx.create_sized_stack_slot(StackSlotData {
389+
kind: StackSlotKind::ExplicitSlot,
390+
// FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to
391+
// specify stack slot alignment.
392+
size: (size + 15) / 16 * 16,
393+
});
394+
Pointer::stack_slot(stack_slot)
395+
} else {
396+
// Alignment is too big to handle using the above hack. Dynamically realign a stack slot
397+
// instead. This wastes some space for the realignment.
398+
let stack_slot = self.bcx.create_sized_stack_slot(StackSlotData {
399+
kind: StackSlotKind::ExplicitSlot,
400+
// FIXME is this calculation to ensure there is enough space to dyanmically realign
401+
// as well as keep a 16 byte realignment for the other stack slots correct?
402+
size: ((size + align - 1) + 16) / 16 * 16,
403+
});
404+
let base_ptr = self.bcx.ins().stack_addr(self.pointer_type, stack_slot, 0);
405+
let misalign_offset = self.bcx.ins().urem_imm(base_ptr, i64::from(align));
406+
let realign_offset = self.bcx.ins().irsub_imm(misalign_offset, i64::from(align));
407+
Pointer::new(self.bcx.ins().iadd(base_ptr, realign_offset))
408+
}
394409
}
395410

396411
pub(crate) fn set_debug_loc(&mut self, source_info: mir::SourceInfo) {

0 commit comments

Comments
 (0)