Skip to content

Stabilize fn_align: #[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

@folkertdev folkertdev commented Apr 24, 2025

tracking issue: #82232
closes #82232

Request for Stabilization

Summary

The fn_align feature has two parts:

  • the #[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:

#[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 #[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

reference PR: rust-lang/reference#1866

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).

In rust-lang/rfcs#3806 it was decided to use #[align] for the attribute, rather than the earlier #[repr(align)].

Notes

Resolved questions

Support for per-function alignment in cranelift is blocked on bytecodealliance/wasmtime#1104. The -Zmin-function-alignment flag does work. If that's a problem, should we pull apart the global and per-function alignment?

Cranelift support is not required. There are already many features that it does not support, support for this feature will land eventually.

What should #[align(N)] do for an async fn, maybe this should not be supported for now?

rust-lang/rfcs#3806 specifies that the #[align] is applied to the function that returns the Future.

alignments larger than a page size are not supported for all targets (see #82232 (comment), #70022, #70144). The current upper bound of 2.pow(29) is what LLVM accepts, but maybe we should cap it at a lower number (that can be raised later if the need arises).

This was discussed in rust-lang/rfcs#3806 (comment), but the final RFC text says to mirror #[repr(align(...))]. If the rules for #[repr(align(...))] ever change, #[align] will have to follow suit.

unresolved questions

None

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 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.

@Jules-Bertholet
Copy link
Contributor

RFC is up: rust-lang/rfcs#3806

@traviscross
Copy link
Contributor

@rustbot labels -I-lang-nominated +I-lang-radar

Let's drop the nomination temporarily to first tackle rust-lang/rfcs#3806.

@rustbot rustbot added I-lang-radar Items that are on lang's radar and will need eventual work or consideration. and removed I-lang-nominated Nominated for discussion during a lang team meeting. labels May 7, 2025
@apiraino apiraino added S-waiting-on-team Status: Awaiting decision from the relevant subteam (see the T-<team> label). and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jun 5, 2025
@bors
Copy link
Collaborator

bors commented Jun 19, 2025

☔ The latest upstream changes (presumably #142697) made this pull request unmergeable. Please resolve the merge conflicts.

@folkertdev folkertdev force-pushed the stabilize-fn-align branch from 3613a1f to 55341da Compare June 19, 2025 10:05
@rustbot rustbot added the A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. label Jun 19, 2025
@rust-log-analyzer

This comment has been minimized.

@folkertdev folkertdev force-pushed the stabilize-fn-align branch from 55341da to 9fb0416 Compare June 19, 2025 10:25
@rustbot
Copy link
Collaborator

rustbot commented Jun 19, 2025

Some changes occurred in compiler/rustc_attr_parsing

cc @jdonszelmann

@rust-log-analyzer

This comment has been minimized.

@folkertdev folkertdev force-pushed the stabilize-fn-align branch from 9fb0416 to fe31811 Compare June 19, 2025 16:48
@rustbot
Copy link
Collaborator

rustbot commented Jun 19, 2025

Some changes occurred in compiler/rustc_codegen_cranelift

cc @bjorn3

@folkertdev
Copy link
Contributor Author

Now that we've agreed on using #[align] for functions, I think we can move forward here?

I've made a reference PR at rust-lang/reference#1866, and split out one final change to an error message into #142715 so that the stabilization PR can be a bit cleaner.

@folkertdev folkertdev changed the title Stabilize fn_align: #[repr(align(N))] on functions and -Zmin-function-alignment Stabilize fn_align: #[align(N)] on functions and -Zmin-function-alignment Jun 19, 2025
@traviscross
Copy link
Contributor

If you could, let's please answer each of the unresolved questions in the PR description, or link to the answer for each.

@folkertdev
Copy link
Contributor Author

I've provided the answers, linking back to the RFC text/discussion.

For the cranelift question I've used my judgement: nobody has objected to going ahead here without cranelift support, that backend has many unsupported features, and support will arrive eventually (i.e. there is no fundamental limitation, it's just not supported yet).

@traviscross
Copy link
Contributor

traviscross commented Jun 19, 2025

@Jules-Bertholet: I'm interested in seeing your approving review that everything in this stabilization is what you'd expect given the RFC.

@traviscross traviscross added S-waiting-on-documentation Status: Waiting on approved PRs to documentation before merging T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. and removed T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jun 19, 2025
Copy link
Contributor

@Jules-Bertholet Jules-Bertholet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@traviscross LGTM, as far as #[align(…)] goes. (-Cmin-function-alignment isn’t part of the RFC, so I have nothing to say about that.)

@traviscross
Copy link
Contributor

traviscross commented Jun 19, 2025

@wesleywiser / @davidtwco / @apiraino: If you could, I'd be interested in your confirmation that all the necessary steps have been taken to lead up to proposing -Cmin-function-alignment=<n> for stabilization. Are you happy handling this together with the lang stabilization in this PR with a dual lang / compiler proposed FCP, or would you prefer to see this broken out or handled otherwise?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-attributes Area: Attributes (`#[…]`, `#![…]`) A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. F-fn_align `#![feature(fn_align)]` I-lang-radar Items that are on lang's radar and will need eventual work or consideration. S-waiting-on-documentation Status: Waiting on approved PRs to documentation before merging S-waiting-on-team Status: Awaiting decision from the relevant subteam (see the T-<team> label). T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

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