Skip to content

Stabilize fn_align: #[repr(align(N))] on functions and -Zmin-function-alignment #140261

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_llvm/src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -475,10 +475,10 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
let allocated_pointer = AttributeKind::AllocatedPointer.create_attr(cx.llcx);
attributes::apply_to_llfn(llfn, AttributePlace::Argument(0), &[allocated_pointer]);
}
// function alignment can be set globally with the `-Zmin-function-alignment=<n>` flag;
// function alignment can be set globally with the `-Cmin-function-alignment=<n>` flag;
// the alignment from a `#[repr(align(<n>))]` is used if it specifies a higher alignment.
if let Some(align) =
Ord::max(cx.tcx.sess.opts.unstable_opts.min_function_alignment, codegen_fn_attrs.alignment)
Ord::max(cx.tcx.sess.opts.cg.min_function_alignment, codegen_fn_attrs.alignment)
{
llvm::set_alignment(llfn, align);
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,10 @@ fn prefix_and_suffix<'tcx>(
let attrs = tcx.codegen_fn_attrs(instance.def_id());
let link_section = attrs.link_section.map(|symbol| symbol.as_str().to_string());

// function alignment can be set globally with the `-Zmin-function-alignment=<n>` flag;
// Function alignment can be set globally with the `-Cmin-function-alignment=<n>` flag;
// the alignment from a `#[repr(align(<n>))]` is used if it specifies a higher alignment.
// if no alignment is specified, an alignment of 4 bytes is used.
let min_function_alignment = tcx.sess.opts.unstable_opts.min_function_alignment;
let min_function_alignment = tcx.sess.opts.cg.min_function_alignment;
let align_bytes =
Ord::max(min_function_alignment, attrs.alignment).map(|a| a.bytes()).unwrap_or(4);

Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_const_eval/src/interpret/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -875,10 +875,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
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=<n>` flag;
// Function alignment can be set globally with the `-Cmin-function-alignment=<n>` flag;
// the alignment from a `#[repr(align(<n>))]` 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;
let global_align = self.tcx.sess.opts.cg.min_function_alignment;

Ord::max(global_align, fn_align).unwrap_or(Align::ONE)
}
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/accepted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,8 @@ declare_features! (
(accepted, f16c_target_feature, "1.68.0", Some(44839)),
/// Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
(accepted, field_init_shorthand, "1.17.0", Some(37340)),
/// Allows using `#[repr(align(...))]` on function items
(accepted, fn_align, "CURRENT_RUSTC_VERSION", Some(82232)),
/// Allows `#[must_use]` on functions, and introduces must-use operators (RFC 1940).
(accepted, fn_must_use, "1.27.0", Some(43302)),
/// Allows capturing variables in scope using format_args!
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -496,8 +496,6 @@ declare_features! (
(unstable, ffi_pure, "1.45.0", Some(58329)),
/// Controlling the behavior of fmt::Debug
(unstable, fmt_debug, "1.82.0", Some(129709)),
/// Allows using `#[repr(align(...))]` on function items
(unstable, fn_align, "1.53.0", Some(82232)),
/// Support delegating implementation of functions to other already implemented functions.
(incomplete, fn_delegation, "1.76.0", Some(118212)),
/// Allows impls for the Freeze trait.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_interface/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -815,7 +816,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));
Expand Down
3 changes: 0 additions & 3 deletions compiler/rustc_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -629,9 +629,6 @@ passes_remove_fields =
*[other] fields
}

passes_repr_align_function =
`repr(align)` attributes on functions are unstable

passes_repr_align_greater_than_target_max =
alignment must not be greater than `isize::MAX` bytes
.note = `isize::MAX` is {$size} for the current target
Expand Down
22 changes: 2 additions & 20 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1975,17 +1975,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
ReprAttr::ReprAlign(align) => {
match target {
Target::Struct | Target::Union | Target::Enum => {}
Target::Fn | Target::Method(_) => {
if !self.tcx.features().fn_align() {
feature_err(
&self.tcx.sess,
sym::fn_align,
*repr_span,
fluent::passes_repr_align_function,
)
.emit();
}
}
Target::Fn | Target::Method(_) => {}
_ => {
self.dcx().emit_err(
errors::AttrApplication::StructEnumFunctionMethodUnion {
Expand Down Expand Up @@ -2049,15 +2039,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
if item.is_some() {
match target {
Target::Struct | Target::Union | Target::Enum => continue,
Target::Fn | Target::Method(_) => {
feature_err(
&self.tcx.sess,
sym::fn_align,
*repr_span,
fluent::passes_repr_align_function,
)
.emit();
}
Target::Fn | Target::Method(_) => continue,
_ => {
self.dcx().emit_err(
errors::AttrApplication::StructEnumFunctionMethodUnion {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2004,6 +2004,8 @@ options! {
"perform LLVM link-time optimizations"),
metadata: Vec<String> = (Vec::new(), parse_list, [TRACKED],
"metadata to mangle symbol names with"),
min_function_alignment: Option<Align> = (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<bool> = (None, parse_opt_bool, [TRACKED],
Expand Down Expand Up @@ -2309,8 +2311,6 @@ options! {
"gather metadata statistics (default: no)"),
metrics_dir: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
"the directory metrics emitted by rustc are dumped into (implicitly enables default set of metrics)"),
min_function_alignment: Option<Align> = (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)"),
Expand Down
22 changes: 22 additions & 0 deletions src/doc/rustc/src/codegen-options/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,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=<align>` 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 `#[repr(align(<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.

## metadata

This option allows you to control the metadata used for symbol mangling. This
Expand Down
24 changes: 0 additions & 24 deletions src/doc/unstable-book/src/compiler-flags/min-function-alignment.md

This file was deleted.

5 changes: 2 additions & 3 deletions src/tools/miri/tests/pass/fn_align.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//@compile-flags: -Zmin-function-alignment=8
#![feature(fn_align)]
//@compile-flags: -Cmin-function-alignment=8

// When a function uses `repr(align(N))`, the function address should be a multiple of `N`.

Expand All @@ -16,6 +15,6 @@ 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.
// The maximum of `repr(align(N))` and `-Cmin-function-alignment=N` is used.
assert!((baz as usize).is_multiple_of(8));
}
2 changes: 1 addition & 1 deletion tests/assembly/naked-functions/aix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
//@[aix] needs-llvm-components: powerpc

#![crate_type = "lib"]
#![feature(no_core, asm_experimental_arch, f128, linkage, fn_align)]
#![feature(no_core, asm_experimental_arch, f128, linkage)]
#![no_core]

// tests that naked functions work for the `powerpc64-ibm-aix` target.
Expand Down
2 changes: 1 addition & 1 deletion tests/assembly/naked-functions/wasm32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
//@ [wasm32-wasip1] needs-llvm-components: webassembly

#![crate_type = "lib"]
#![feature(no_core, asm_experimental_arch, f128, linkage, fn_align)]
#![feature(no_core, asm_experimental_arch, f128, linkage)]
#![no_core]

extern crate minicore;
Expand Down
1 change: 0 additions & 1 deletion tests/codegen/align-fn.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//@ compile-flags: -C no-prepopulate-passes -Z mir-opt-level=0

#![crate_type = "lib"]
#![feature(fn_align)]

// CHECK: align 16
#[no_mangle]
Expand Down
7 changes: 3 additions & 4 deletions tests/codegen/min-function-alignment.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
//@ revisions: align16 align1024
//@ compile-flags: -C no-prepopulate-passes -Z mir-opt-level=0
//@ [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)]

// functions without explicit alignment use the global minimum
//
Expand Down Expand Up @@ -33,7 +32,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
Expand Down
1 change: 0 additions & 1 deletion tests/codegen/naked-fn/aligned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
//@ ignore-arm no "ret" mnemonic

#![crate_type = "lib"]
#![feature(fn_align)]
use std::arch::naked_asm;

// CHECK: .balign 16
Expand Down
5 changes: 2 additions & 3 deletions tests/codegen/naked-fn/min-function-alignment.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
//@ 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

#![feature(fn_align)]
#![crate_type = "lib"]

// functions without explicit alignment use the global minimum
Expand Down Expand Up @@ -33,7 +32,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]
Expand Down
1 change: 0 additions & 1 deletion tests/ui/asm/naked-with-invalid-repr-attr.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//@ needs-asm-support
#![feature(fn_align)]
#![crate_type = "lib"]
use std::arch::naked_asm;

Expand Down
12 changes: 6 additions & 6 deletions tests/ui/asm/naked-with-invalid-repr-attr.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0517]: attribute should be applied to a struct, enum, or union
--> $DIR/naked-with-invalid-repr-attr.rs:6:8
--> $DIR/naked-with-invalid-repr-attr.rs:5:8
|
LL | #[repr(C)]
| ^
Expand All @@ -11,7 +11,7 @@ LL | | }
| |_- not a struct, enum, or union

error[E0517]: attribute should be applied to a struct, enum, or union
--> $DIR/naked-with-invalid-repr-attr.rs:14:8
--> $DIR/naked-with-invalid-repr-attr.rs:13:8
|
LL | #[repr(transparent)]
| ^^^^^^^^^^^
Expand All @@ -23,7 +23,7 @@ LL | | }
| |_- not a struct, enum, or union

error[E0517]: attribute should be applied to a struct, enum, or union
--> $DIR/naked-with-invalid-repr-attr.rs:22:19
--> $DIR/naked-with-invalid-repr-attr.rs:21:19
|
LL | #[repr(align(16), C)]
| ^
Expand All @@ -35,7 +35,7 @@ LL | | }
| |_- not a struct, enum, or union

error[E0517]: attribute should be applied to a struct, enum, or union
--> $DIR/naked-with-invalid-repr-attr.rs:31:8
--> $DIR/naked-with-invalid-repr-attr.rs:30:8
|
LL | #[repr(C, packed)]
| ^
Expand All @@ -48,7 +48,7 @@ LL | | }
| |_- not a struct, enum, or union

error[E0517]: attribute should be applied to a struct or union
--> $DIR/naked-with-invalid-repr-attr.rs:31:11
--> $DIR/naked-with-invalid-repr-attr.rs:30:11
|
LL | #[repr(C, packed)]
| ^^^^^^
Expand All @@ -61,7 +61,7 @@ LL | | }
| |_- not a struct or union

error[E0517]: attribute should be applied to an enum
--> $DIR/naked-with-invalid-repr-attr.rs:41:8
--> $DIR/naked-with-invalid-repr-attr.rs:40:8
|
LL | #[repr(u8)]
| ^^
Expand Down
6 changes: 4 additions & 2 deletions tests/ui/attributes/malformed-fn-align.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#![feature(fn_align)]
#![crate_type = "lib"]

trait MyTrait {
#[repr(align)] //~ ERROR invalid `repr(align)` attribute: `align` needs an argument
fn myfun();
fn myfun1();

#[repr(align(1, 2))] //~ ERROR incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
fn myfun2();
}
13 changes: 10 additions & 3 deletions tests/ui/attributes/malformed-fn-align.stderr
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
error[E0589]: invalid `repr(align)` attribute: `align` needs an argument
--> $DIR/malformed-fn-align.rs:5:12
--> $DIR/malformed-fn-align.rs:4:12
|
LL | #[repr(align)]
| ^^^^^ help: supply an argument here: `align(...)`

error: aborting due to 1 previous error
error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
--> $DIR/malformed-fn-align.rs:7:12
|
LL | #[repr(align(1, 2))]
| ^^^^^^^^^^^

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0589`.
Some errors have detailed explanations: E0589, E0693.
For more information about an error, try `rustc --explain E0589`.
9 changes: 0 additions & 9 deletions tests/ui/feature-gates/feature-gate-fn_align.rs

This file was deleted.

Loading
Loading