From ae18cc432302cdc521e491ad75f519042362a024 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 21 Jun 2025 12:41:40 +0200 Subject: [PATCH 1/2] limit -Zmin-function-alignment to at most 8192 bytes Higher alignments are not supported in COFF --- compiler/rustc_session/src/options.rs | 8 +++++++- .../min-function-alignment.not-power-of-2.stderr | 2 ++ tests/ui/invalid-compile-flags/min-function-alignment.rs | 6 ++++++ .../min-function-alignment.too-high.stderr | 2 ++ 4 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 tests/ui/invalid-compile-flags/min-function-alignment.not-power-of-2.stderr create mode 100644 tests/ui/invalid-compile-flags/min-function-alignment.rs create mode 100644 tests/ui/invalid-compile-flags/min-function-alignment.too-high.stderr diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 7fef942525b96..6e795deffe9d7 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -811,7 +811,7 @@ mod desc { pub(crate) const parse_wasm_c_abi: &str = "`spec`"; pub(crate) const parse_mir_include_spans: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or `nll` (default: `nll`)"; - pub(crate) const parse_align: &str = "a number that is a power of 2 between 1 and 2^29"; + pub(crate) const parse_align: &str = "a number that is a power of 2 between 1 and 8192"; } pub mod parse { @@ -1925,6 +1925,12 @@ pub mod parse { return false; } + // Limit the alignment to 8192 (i.e. 0x2000, or 1 << 13) bytes. It is the highest function + // alignment that works on all target platforms. COFF does not support higher alignments. + if bytes > 8192 { + return false; + } + let Ok(align) = Align::from_bytes(bytes) else { return false; }; diff --git a/tests/ui/invalid-compile-flags/min-function-alignment.not-power-of-2.stderr b/tests/ui/invalid-compile-flags/min-function-alignment.not-power-of-2.stderr new file mode 100644 index 0000000000000..44d1a91d215c4 --- /dev/null +++ b/tests/ui/invalid-compile-flags/min-function-alignment.not-power-of-2.stderr @@ -0,0 +1,2 @@ +error: incorrect value `3` for unstable option `min-function-alignment` - a number that is a power of 2 between 1 and 8192 was expected + diff --git a/tests/ui/invalid-compile-flags/min-function-alignment.rs b/tests/ui/invalid-compile-flags/min-function-alignment.rs new file mode 100644 index 0000000000000..09a8fcb74c84e --- /dev/null +++ b/tests/ui/invalid-compile-flags/min-function-alignment.rs @@ -0,0 +1,6 @@ +//@ revisions: too-high not-power-of-2 +// +//@ [too-high] compile-flags: -Zmin-function-alignment=16384 +//@ [not-power-of-2] compile-flags: -Zmin-function-alignment=3 + +//~? ERROR a number that is a power of 2 between 1 and 8192 was expected diff --git a/tests/ui/invalid-compile-flags/min-function-alignment.too-high.stderr b/tests/ui/invalid-compile-flags/min-function-alignment.too-high.stderr new file mode 100644 index 0000000000000..fe4c99cae9e8f --- /dev/null +++ b/tests/ui/invalid-compile-flags/min-function-alignment.too-high.stderr @@ -0,0 +1,2 @@ +error: incorrect value `16384` for unstable option `min-function-alignment` - a number that is a power of 2 between 1 and 8192 was expected + From 2010f9a8096233902034f6fc45344b7d5bb6e557 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 19 Apr 2025 20:04:35 +0200 Subject: [PATCH 2/2] stabilize `-Cmin-function-aligmnent` --- compiler/rustc_codegen_cranelift/src/lib.rs | 2 +- .../rustc_codegen_ssa/src/codegen_attrs.rs | 2 +- compiler/rustc_interface/src/tests.rs | 2 +- compiler/rustc_session/src/options.rs | 4 ++-- src/doc/rustc/src/codegen-options/index.md | 22 +++++++++++++++++ .../compiler-flags/min-function-alignment.md | 24 ------------------- src/tools/miri/tests/pass/fn_align.rs | 2 +- tests/codegen/min-function-alignment.rs | 6 ++--- .../naked-fn/min-function-alignment.rs | 4 ++-- ...n-function-alignment.not-power-of-2.stderr | 2 +- .../min-function-alignment.rs | 4 ++-- .../min-function-alignment.too-high.stderr | 2 +- 12 files changed, 37 insertions(+), 39 deletions(-) delete mode 100644 src/doc/unstable-book/src/compiler-flags/min-function-alignment.md diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 8e34436fb5e0a..a466ab880440f 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -309,7 +309,7 @@ fn build_isa(sess: &Session, jit: bool) -> Arc { flags_builder.set("enable_llvm_abi_extensions", "true").unwrap(); - if let Some(align) = sess.opts.unstable_opts.min_function_alignment { + if let Some(align) = sess.opts.cg.min_function_alignment { flags_builder .set("log2_min_function_alignment", &align.bytes().ilog2().to_string()) .unwrap(); diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index f769b3935281c..09b4be13bd10d 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -450,7 +450,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { // Apply the minimum function alignment here, so that individual backends don't have to. codegen_fn_attrs.alignment = - Ord::max(codegen_fn_attrs.alignment, tcx.sess.opts.unstable_opts.min_function_alignment); + Ord::max(codegen_fn_attrs.alignment, tcx.sess.opts.cg.min_function_alignment); let inline_span; (codegen_fn_attrs.inline, inline_span) = if let Some((inline_attr, span)) = diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index a0012b04c4f29..e0c33cc5644cf 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -624,6 +624,7 @@ fn test_codegen_options_tracking_hash() { tracked!(llvm_args, vec![String::from("1"), String::from("2")]); tracked!(lto, LtoCli::Fat); tracked!(metadata, vec![String::from("A"), String::from("B")]); + tracked!(min_function_alignment, Some(Align::EIGHT)); tracked!(no_prepopulate_passes, true); tracked!(no_redzone, Some(true)); tracked!(no_vectorize_loops, true); @@ -818,7 +819,6 @@ fn test_unstable_options_tracking_hash() { tracked!(location_detail, LocationDetail { file: true, line: false, column: false }); tracked!(maximal_hir_to_mir_coverage, true); tracked!(merge_functions, Some(MergeFunctions::Disabled)); - tracked!(min_function_alignment, Some(Align::EIGHT)); tracked!(mir_emit_retag, true); tracked!(mir_enable_passes, vec![("DestProp".to_string(), false)]); tracked!(mir_opt_level, Some(4)); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 6e795deffe9d7..9cad7517996a3 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2020,6 +2020,8 @@ options! { "perform LLVM link-time optimizations"), metadata: Vec = (Vec::new(), parse_list, [TRACKED], "metadata to mangle symbol names with"), + min_function_alignment: Option = (None, parse_align, [TRACKED], + "align all functions to at least this many bytes. Must be a power of 2"), no_prepopulate_passes: bool = (false, parse_no_value, [TRACKED], "give an empty list of passes to the pass manager"), no_redzone: Option = (None, parse_opt_bool, [TRACKED], @@ -2333,8 +2335,6 @@ options! { "gather metadata statistics (default: no)"), metrics_dir: Option = (None, parse_opt_pathbuf, [UNTRACKED], "the directory metrics emitted by rustc are dumped into (implicitly enables default set of metrics)"), - min_function_alignment: Option = (None, parse_align, [TRACKED], - "align all functions to at least this many bytes. Must be a power of 2"), mir_emit_retag: bool = (false, parse_bool, [TRACKED], "emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 \ (default: no)"), diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index bb109adf76f41..20937aaba93e3 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -346,6 +346,28 @@ opt-level=0`](#opt-level)). That is: See also [linker-plugin-lto](#linker-plugin-lto) for cross-language LTO. +## min-function-alignment + +The `-Cmin-function-alignment=` flag specifies the minimum alignment of functions for which code is generated. +The `align` value must be a power of 2, other values are rejected. + +Note that `-Zbuild-std` (or similar) is required to apply this minimum alignment to standard library functions. +By default, these functions come precompiled and their alignments won't respect the `min-function-alignment` flag. + +This flag is equivalent to: + +- `-fmin-function-alignment` for [GCC](https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-fmin-function-alignment_003dn) +- `-falign-functions` for [Clang](https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang1-falign-functions) + +The specified alignment is a minimum. A higher alignment can be specified for specific functions by annotating the function with a `#[align()]` attribute. +The attribute's value is ignored when it is lower than the value passed to `min-function-alignment`. + +There are two additional edge cases for this flag: + +- targets have a minimum alignment for functions (e.g. on x86_64 the lowest that LLVM generates is 16 bytes). + A `min-function-alignment` value lower than the target's minimum has no effect. +- the maximum alignment supported by this flag is `8192`. Trying to set a higher value results in an error. + ## metadata This option allows you to control the metadata used for symbol mangling. This diff --git a/src/doc/unstable-book/src/compiler-flags/min-function-alignment.md b/src/doc/unstable-book/src/compiler-flags/min-function-alignment.md deleted file mode 100644 index 03e576e3e300f..0000000000000 --- a/src/doc/unstable-book/src/compiler-flags/min-function-alignment.md +++ /dev/null @@ -1,24 +0,0 @@ -# `min-function-alignment` - -The tracking issue for this feature is: https://github.com/rust-lang/rust/issues/82232. - ------------------------- - -The `-Zmin-function-alignment=` flag specifies the minimum alignment of functions for which code is generated. -The `align` value must be a power of 2, other values are rejected. - -Note that `-Zbuild-std` (or similar) is required to apply this minimum alignment to standard library functions. -By default, these functions come precompiled and their alignments won't respect the `min-function-alignment` flag. - -This flag is equivalent to: - -- `-fmin-function-alignment` for [GCC](https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-fmin-function-alignment_003dn) -- `-falign-functions` for [Clang](https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang1-falign-functions) - -The specified alignment is a minimum. A higher alignment can be specified for specific functions by using the [`align(...)`](https://github.com/rust-lang/rust/issues/82232) feature and annotating the function with a `#[align()]` attribute. The attribute's value is ignored when it is lower than the value passed to `min-function-alignment`. - -There are two additional edge cases for this flag: - -- targets have a minimum alignment for functions (e.g. on x86_64 the lowest that LLVM generates is 16 bytes). - A `min-function-alignment` value lower than the target's minimum has no effect. -- the maximum alignment supported by rust (and LLVM) is `2^29`. Trying to set a higher value results in an error. diff --git a/src/tools/miri/tests/pass/fn_align.rs b/src/tools/miri/tests/pass/fn_align.rs index 28f9299588003..6c07abc369e92 100644 --- a/src/tools/miri/tests/pass/fn_align.rs +++ b/src/tools/miri/tests/pass/fn_align.rs @@ -1,4 +1,4 @@ -//@compile-flags: -Zmin-function-alignment=8 +//@compile-flags: -Cmin-function-alignment=8 #![feature(fn_align)] // When a function uses `align(N)`, the function address should be a multiple of `N`. diff --git a/tests/codegen/min-function-alignment.rs b/tests/codegen/min-function-alignment.rs index 78989ec5df236..1673b76aa9c7c 100644 --- a/tests/codegen/min-function-alignment.rs +++ b/tests/codegen/min-function-alignment.rs @@ -1,7 +1,7 @@ //@ revisions: align16 align1024 //@ compile-flags: -C no-prepopulate-passes -Z mir-opt-level=0 -Clink-dead-code -//@ [align16] compile-flags: -Zmin-function-alignment=16 -//@ [align1024] compile-flags: -Zmin-function-alignment=1024 +//@ [align16] compile-flags: -Cmin-function-alignment=16 +//@ [align1024] compile-flags: -Cmin-function-alignment=1024 #![crate_type = "lib"] #![feature(fn_align)] @@ -35,7 +35,7 @@ pub fn higher_align() {} // cold functions follow the same rules as other functions // // in GCC, the `-falign-functions` does not apply to cold functions, but -// `-Zmin-function-alignment` applies to all functions. +// `-Cmin-function-alignment` applies to all functions. // // CHECK-LABEL: @no_explicit_align_cold // align16: align 16 diff --git a/tests/codegen/naked-fn/min-function-alignment.rs b/tests/codegen/naked-fn/min-function-alignment.rs index 59554c1cae554..8a7cf43bcb92a 100644 --- a/tests/codegen/naked-fn/min-function-alignment.rs +++ b/tests/codegen/naked-fn/min-function-alignment.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -C no-prepopulate-passes -Copt-level=0 -Zmin-function-alignment=16 +//@ compile-flags: -C no-prepopulate-passes -Copt-level=0 -Cmin-function-alignment=16 //@ needs-asm-support //@ ignore-arm no "ret" mnemonic @@ -33,7 +33,7 @@ pub extern "C" fn naked_higher_align() { // cold functions follow the same rules as other functions // // in GCC, the `-falign-functions` does not apply to cold functions, but -// `-Zmin-function-alignment` applies to all functions. +// `-Cmin-function-alignment` applies to all functions. // // CHECK: .balign 16 #[no_mangle] diff --git a/tests/ui/invalid-compile-flags/min-function-alignment.not-power-of-2.stderr b/tests/ui/invalid-compile-flags/min-function-alignment.not-power-of-2.stderr index 44d1a91d215c4..f3cb5e99a7687 100644 --- a/tests/ui/invalid-compile-flags/min-function-alignment.not-power-of-2.stderr +++ b/tests/ui/invalid-compile-flags/min-function-alignment.not-power-of-2.stderr @@ -1,2 +1,2 @@ -error: incorrect value `3` for unstable option `min-function-alignment` - a number that is a power of 2 between 1 and 8192 was expected +error: incorrect value `3` for codegen option `min-function-alignment` - a number that is a power of 2 between 1 and 8192 was expected diff --git a/tests/ui/invalid-compile-flags/min-function-alignment.rs b/tests/ui/invalid-compile-flags/min-function-alignment.rs index 09a8fcb74c84e..8a1bc76e6b678 100644 --- a/tests/ui/invalid-compile-flags/min-function-alignment.rs +++ b/tests/ui/invalid-compile-flags/min-function-alignment.rs @@ -1,6 +1,6 @@ //@ revisions: too-high not-power-of-2 // -//@ [too-high] compile-flags: -Zmin-function-alignment=16384 -//@ [not-power-of-2] compile-flags: -Zmin-function-alignment=3 +//@ [too-high] compile-flags: -Cmin-function-alignment=16384 +//@ [not-power-of-2] compile-flags: -Cmin-function-alignment=3 //~? ERROR a number that is a power of 2 between 1 and 8192 was expected diff --git a/tests/ui/invalid-compile-flags/min-function-alignment.too-high.stderr b/tests/ui/invalid-compile-flags/min-function-alignment.too-high.stderr index fe4c99cae9e8f..4bc7b219c6690 100644 --- a/tests/ui/invalid-compile-flags/min-function-alignment.too-high.stderr +++ b/tests/ui/invalid-compile-flags/min-function-alignment.too-high.stderr @@ -1,2 +1,2 @@ -error: incorrect value `16384` for unstable option `min-function-alignment` - a number that is a power of 2 between 1 and 8192 was expected +error: incorrect value `16384` for codegen option `min-function-alignment` - a number that is a power of 2 between 1 and 8192 was expected