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

Conversation

folkertdev
Copy link
Contributor

tracking issue: #82232
closes #82232

Request for Stabilization

Summary

The fn_align feature has two parts:

  • the #[repr(align(N))] function attribute specifies the alignment of the generated code of a particular function
  • the -Zmin-function-alignment command line flag specifies the minimal alignment of the generated code of all compiled functions.

These could be stabilized separately, but share a lot of the same logic in the compiler and are tracked by the same tracking issue.

An example of specifying function alignment:

#[repr(align(32))]
pub fn align_this() {}

Specifying the alignment of a specific function occasionally comes up in embedded development. For instance in risc-v vector tables, the function pointers stored in it must be aligned to at least 4 bytes (see #75072).

Specifying a global alignment is more commonly done as a performance optimization. This functionality is used in the linux kernel and this feature flag was requested by Rust for Linux #128830.

Semantics

The -Zmin-function-alignment flag is a global mimimum function alignment. It is semantically equivalent to annotating every function with a #[repr(align(N))]. However, this minimum is only applied to functions that are actually codegened, so without -Zbuild-std or similar, this minimum alignment is not applied to standard library functions.

The function alignment is forwarded to the code generation backend, and behaves as follows:

  • the highest specified alignment is used
  • the alignment follows the same rule as for data types: it must be a power of 2 in the range 1 up to and including 2.pow(29).
  • the alignment is a minimum, the alignment may be higher in practice (e.g. x86_64 aligns to 16 by default)

Documentation

Pending resolving some of the open questions.

Tests

History

The -Zmin-function-alignment flag was requested by rust-for-linux #128830. It will be used soon (see #t-compiler/help > ✔ Alignment for function addresses).

Miri supports function alignment since #140072. In const-eval there is no way to observe the address of a function pointer, so no special attention is needed there (see #t-compiler/const-eval > function address alignment).

Notes

unresolved questions

r? @traviscross

@rustbot label +I-lang-nominated

@rustbot rustbot added A-attributes Area: Attributes (`#[…]`, `#![…]`) S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Apr 24, 2025
@rustbot
Copy link
Collaborator

rustbot commented Apr 24, 2025

Some changes occurred to the CTFE / Miri interpreter

cc @rust-lang/miri

Some changes occurred in compiler/rustc_codegen_ssa

cc @WaffleLapkin

Some changes occurred to the CTFE machinery

cc @RalfJung, @oli-obk, @lcnr

The Miri subtree was changed

cc @rust-lang/miri

Some changes occurred in compiler/rustc_passes/src/check_attr.rs

cc @jdonszelmann

@rustbot rustbot added the I-lang-nominated Nominated for discussion during a lang team meeting. label Apr 24, 2025
@jieyouxu jieyouxu added the F-fn_align `#![feature(fn_align)]` label Apr 24, 2025
@traviscross traviscross added the T-lang Relevant to the language team, which will review and decide on the PR/issue. label Apr 24, 2025
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@traviscross
Copy link
Contributor

We talked about this at some length in the @rust-lang/lang call today. In particular, we focused on whether to spell this #[repr(align(..))] or #[align(..)].

We looked at @Jules-Bertholet's pre-RFC here:

https://internals.rust-lang.org/t/pre-rfc-align-attribute/21004/27

We were interested, @Jules-Bertholet, in seeing that made into an RFC, and we'd invite you to submit that and nominate it for us.

It does feel to me that #[align(..)] makes more sense on a static than #[repr(align(..))], and in that context, functions seem more like statics to me -- and did to many on the call -- than they do structs.

We did discuss whether maybe it should just be #[align(..)] everywhere, but not all of us were sold on that and thought it possible there might be a distinction worth making. Niko outlined these thoughts in the meeting:

  • Observations:
    • It is "odd" to have repr(align) on a function. I don't know why, it just feels weird.
    • Most things in repr don't belong on functions (e.g., repr(C), repr(packed)).
    • But #[align] on functions is fairly niche.
    • It seems odd to write align in two different ways on structs/functions.
    • I think you could split out alignment from the rest of repr (e.g., it is about where the struct is placed vs the layout of its fields, align doesn't impact the latter).
    • I like having repr as the place to go lookup your options to control struct layout and alignment feels "close enough" to that.
  • Thought exercise:
    • Imagine the docs on repr if it applies to both functions and structs.
      • They'll say "repr can be used on many kinds of items but the relevant items are different depending on the kind of item". And functions will look totally different.
    • Imagine the docs on repr if align is not part of it.
      • They'll no doubt say "If you want to control alignment, you need the alignment attribute", which feels weird.
  • Conclusion:
    • Not sure yet.

For my part, I agree with all of those considerations.

We wanted to open it up for the thoughts of others to see what other good ideas or arguments here might emerge. What do you think?

@Jules-Bertholet
Copy link
Contributor

Jules-Bertholet commented Apr 30, 2025

We were interested in seeing that made into an RFC, and we'd invite you to submit that and nominate it for us.

I’m hesitant to do so at present because I don’t know enough about MSVC to be confident that its alignment-related weirdness won’t be a problem. I don't want the RFC comments to turn into a rehash of the same issues being debated at rust-lang/rfcs#3718. I would want to either see that settled and merged, or for the lang team to agree that they would be interested in the RFC even with those parts left explicitly unresolved.

@folkertdev
Copy link
Contributor Author

It is "odd" to have repr(align) on a function. I don't know why, it just feels weird.

Yes, 100%.

But #[align] on functions is fairly niche.

Yes, it's mostly embedded and OS projects from what I can tell. These same projects would also get a bunch of mileage out of #[align] on statics though, and I strongly agree that functions feel more like statics.

It seems odd to write align in two different ways on structs/functions.

Accepting #[align = 8] struct Foo; actually seems fine to me.


Imagine the docs on repr if it applies to both functions and structs.

I really like this framing!

Currently the reference for the repr(...) attribute lives here at type layout >> representations, and talks about the alignment modifiers. From that section:

For align, if the specified alignment is less than the alignment of the type without the align modifier, then the alignment is unaffected.

The language of this section is in terms of types. That makes sense, and is useful. It can be reworked, but I think including functions and statics here would get messy.

The align modifier can also be applied on an enum. When it is, the effect on the enum’s alignment is the same as if the enum was wrapped in a newtype struct with the same align modifier.

The existing text already has some trouble with struct, union and enum. Adding fn and static in there too in a coherent way would be challenging I think.

There is also https://doc.rust-lang.org/nomicon/other-reprs.html#repralignn, again under the "data layout" heading, but honestly that could probably use some work (an example, talking about addresses, maybe other things).


@Jules-Bertholet that's understandable. From my listening in to the conversation, it seemed like what T-lang is looking for is some sort of coherent design for #[align], and reasoning for why it is different from #[repr(align(n))]: adding #[align] just for functions seems like it doesn't pull its weight, but if it can also be use for statics, or even for individual fields, then maybe it is worth adding.


A procedural question, given that resolving these questions around the attribute will likely take a while: what would the process be for just stabilizing the -Cmin-function-alignment flag? So far there are no concerns about it, so could I just split that out? Then, would that just require FCP from the compiler team, or is T-lang still involved?

@traviscross
Copy link
Contributor

traviscross commented May 1, 2025

what would the process be for just stabilizing the -Cmin-function-alignment flag? So far there are no concerns about it, so could I just split that out? Then, would that just require FCP from the compiler team, or is T-lang still involved?

In my view, we'd still want lang on that, as it amounts to adding #[align(..)] to all functions, with all the user-visible semantic guarantees about the language doing that implies.

Probably I'd just suggest giving us a little while to see if we can sort this out as-is.

We were interested in seeing that made into an RFC, and we'd invite you to submit that and nominate it for us.

I’m hesitant to do so at present because I don’t know enough about MSVC to be confident that its alignment-related weirdness won’t be a problem. I don't want the RFC comments to turn into a rehash of the same issues being debated at rust-lang/rfcs#3718. I would want to either see that settled and merged, or for the lang team to agree that they would be interested in the RFC even with those parts left explicitly unresolved.

@Jules-Bertholet, like @folkertdev said, we're mostly interested here in whether there's a coherent notion of #[align(..)] that's separate from #[repr(align(..))], and if so, what that looks like. If perhaps there's a way to narrow the scope of the RFC to help with that and maybe sidestep the other problem, maybe that's worth doing. Otherwise, we can talk about what we might be able to say about the handling of the unresolved question you mention.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-attributes Area: Attributes (`#[…]`, `#![…]`) F-fn_align `#![feature(fn_align)]` I-lang-nominated Nominated for discussion during a lang team meeting. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Tracking Issue for #[repr(align(...))] on function items (fn_align)
6 participants