Skip to content

Commit

Permalink
Dynamically realign local variables with large alignment
Browse files Browse the repository at this point in the history
This works around the lack of a way to specify the alignment of a stack
slot in Cranelift.

Fixes rust-lang#1230
Fixes rust-lang#1381
  • Loading branch information
bjorn3 committed Oct 22, 2023
1 parent 38e8be9 commit 55380a5
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 7 deletions.
11 changes: 11 additions & 0 deletions example/mini_core_hello_world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
29 changes: 22 additions & 7 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit 55380a5

Please sign in to comment.