From 2d21c140154c5387712938dbc2ca427e2df4dfc2 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 20 Apr 2025 12:52:50 +0200 Subject: [PATCH 1/2] respect `repr(align(N))` on functions in miri --- .../rustc_const_eval/src/interpret/memory.rs | 16 ++++++++++++-- src/tools/miri/tests/pass/fn_align.rs | 21 +++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 src/tools/miri/tests/pass/fn_align.rs diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index d077900587e9c..3bde7457ad607 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -872,8 +872,20 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // # Function pointers // (both global from `alloc_map` and local from `extra_fn_ptr_map`) - if self.get_fn_alloc(id).is_some() { - return AllocInfo::new(Size::ZERO, Align::ONE, AllocKind::Function, Mutability::Not); + if let Some(fn_val) = self.get_fn_alloc(id) { + let align = match fn_val { + FnVal::Instance(instance) => { + // Function alignment can be set globally with the `-Zmin-function-alignment=` flag; + // the alignment from a `#[repr(align())]` is used if it specifies a higher alignment. + let fn_align = self.tcx.codegen_fn_attrs(instance.def_id()).alignment; + let global_align = self.tcx.sess.opts.unstable_opts.min_function_alignment; + + Ord::max(global_align, fn_align).unwrap_or(Align::ONE) + } + FnVal::Other(_) => Align::ONE, + }; + + return AllocInfo::new(Size::ZERO, align, AllocKind::Function, Mutability::Not); } // # Global allocations diff --git a/src/tools/miri/tests/pass/fn_align.rs b/src/tools/miri/tests/pass/fn_align.rs new file mode 100644 index 0000000000000..550bb1cb4d718 --- /dev/null +++ b/src/tools/miri/tests/pass/fn_align.rs @@ -0,0 +1,21 @@ +//@compile-flags: -Zmin-function-alignment=8 +#![feature(fn_align)] + +// When a function uses `repr(align(N))`, the function address should be a multiple of `N`. + +#[repr(align(256))] +fn foo() {} + +#[repr(align(16))] +fn bar() {} + +#[repr(align(4))] +fn baz() {} + +fn main() { + assert!((foo as usize).is_multiple_of(256)); + assert!((bar as usize).is_multiple_of(16)); + + // The maximum of `repr(align(N))` and `-Zmin-function-alignment=N` is used. + assert!((baz as usize).is_multiple_of(8)); +} From 47a127884135771ae557eca71f964a5db655c2ea Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 22 Apr 2025 11:40:48 +0200 Subject: [PATCH 2/2] add comment for "Other" case --- compiler/rustc_const_eval/src/interpret/memory.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 3bde7457ad607..9d8130661b04d 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -882,6 +882,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { Ord::max(global_align, fn_align).unwrap_or(Align::ONE) } + // Machine-specific extra functions currently do not support alignment restrictions. FnVal::Other(_) => Align::ONE, };