Skip to content

Commit 107f04d

Browse files
authored
Rollup merge of #140072 - folkertdev:miri-fn-align, r=RalfJung
handle function alignment in miri tracking issue: #82232 Fixes rust-lang/miri#4282 The `#[repr(align(N))]` attribute on functions was ignored when using miri. For such a function, its address should be a multiple of `N`. There is some further discussion in the thread [#t-compiler/const-eval > function address alignment](https://rust-lang.zulipchat.com/#narrow/channel/146212-t-compiler.2Fconst-eval/topic/function.20address.20alignment) on how `dyn Fn` should be handled. The behavior there appears to be consistent between miri and nightly, though both may be incorrect. In any case, that can be resolved separately.
2 parents c046a43 + 47a1278 commit 107f04d

File tree

2 files changed

+36
-2
lines changed

2 files changed

+36
-2
lines changed

compiler/rustc_const_eval/src/interpret/memory.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -872,8 +872,21 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
872872

873873
// # Function pointers
874874
// (both global from `alloc_map` and local from `extra_fn_ptr_map`)
875-
if self.get_fn_alloc(id).is_some() {
876-
return AllocInfo::new(Size::ZERO, Align::ONE, AllocKind::Function, Mutability::Not);
875+
if let Some(fn_val) = self.get_fn_alloc(id) {
876+
let align = match fn_val {
877+
FnVal::Instance(instance) => {
878+
// Function alignment can be set globally with the `-Zmin-function-alignment=<n>` flag;
879+
// the alignment from a `#[repr(align(<n>))]` is used if it specifies a higher alignment.
880+
let fn_align = self.tcx.codegen_fn_attrs(instance.def_id()).alignment;
881+
let global_align = self.tcx.sess.opts.unstable_opts.min_function_alignment;
882+
883+
Ord::max(global_align, fn_align).unwrap_or(Align::ONE)
884+
}
885+
// Machine-specific extra functions currently do not support alignment restrictions.
886+
FnVal::Other(_) => Align::ONE,
887+
};
888+
889+
return AllocInfo::new(Size::ZERO, align, AllocKind::Function, Mutability::Not);
877890
}
878891

879892
// # Global allocations

src/tools/miri/tests/pass/fn_align.rs

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//@compile-flags: -Zmin-function-alignment=8
2+
#![feature(fn_align)]
3+
4+
// When a function uses `repr(align(N))`, the function address should be a multiple of `N`.
5+
6+
#[repr(align(256))]
7+
fn foo() {}
8+
9+
#[repr(align(16))]
10+
fn bar() {}
11+
12+
#[repr(align(4))]
13+
fn baz() {}
14+
15+
fn main() {
16+
assert!((foo as usize).is_multiple_of(256));
17+
assert!((bar as usize).is_multiple_of(16));
18+
19+
// The maximum of `repr(align(N))` and `-Zmin-function-alignment=N` is used.
20+
assert!((baz as usize).is_multiple_of(8));
21+
}

0 commit comments

Comments
 (0)