Skip to content

s390x: replace -Ctarget-feature=+backchain with -Cforce-frame-pointers - #163315

Open
fneddy wants to merge 1 commit into
rust-lang:mainfrom
fneddy:s390x_framepointer
Open

fneddy wants to merge 1 commit into
rust-lang:mainfrom
fneddy:s390x_framepointer

Conversation

@fneddy

@fneddy fneddy commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Summary

On s390x, the backchain LLVM function attribute saves the "unwind" (backchain) pointer (r15) into the caller's parameter area, enabling external stack unwinders (e.g. Linux perf) to walk the call chain. Previously this was enabled via -Ctarget-feature=+backchain, which piggy-backed on the target-feature machinery even though backchain is not a CPU or ISA feature.

This commit introduces a cleaner mechanism:

  • -Cforce-frame-pointers now enables the "backchain" LLVM function attribute on s390x, rather than the generic "frame-pointer" attribute used on other architectures.
  • -Ctarget-feature=+backchain emits a error pointing to the new mechanism.
  • Other reasons to set frame pointers (e.g. -Zinstrument-mcount) are unaffected and still emit "frame-pointer".
  • All s390x-specific frame-pointer/backchain/packed-stack logic is consolidated in s390x_fn_attrs() in attributes.rs.

This implements the proposed solution discussed in here on Zulip.

Background

Frame pointers on s390x

Setting -Cforce-frame-pointers=yes on s390x forces the "frame-pointer" LLVM attribute, but this does not form a traversable linked list. As [@uweigand] explained ([#150766 comment]):

Even if we force frame pointer registers to be used, those are not stored on the stack in a way that forms a linked list that can be followed. The -mbackchain option simply generates prolog code that manages an equivalent linked list of stack frames at runtime.

Therefore -Cforce-frame-pointers on s390x provides no stack-walking benefit.

Backchain

The s390x ELF ABI reserves backchain slot - a pointer back to the caller's frame. This can be used to walk the entire call chain without DWARF CFI. LLVM exposes this as the "backchain" function attribute, equivalent to GCC's -mbackchain.

Backchain is not a CPU capability. It is a whole-binary code-generation convention, similar in nature to -fno-omit-frame-pointer on x86. This is reflected in LLVM modelling it as a function attribute, not a target feature [#150766 comment 2].

Enabling backchain does not break ABI compatibility: backchain-enabled and -disabled functions can freely call each other.

The one notable exception is packed-stack: combining -Zpacked-stack with backchain on a non-softfloat target is rejected at compile time([#152432]).

rustc arg discussion

Initially backchain was introduced as an unstable target-feature mimicing the gcc and clang behavior. Within the grater effort of stabilizing arguments that are needed for Linux Kernel development, attempts where made to stabilize the target-feature=+backchain. This lead to discussions and the overall consent is that:

  1. on s390x, enabling normal frame-poitners will never be done by the user.
  2. if a user wants frome-pointers the user actually wants: stack-unwinding on x86 via frame-pointers but on s390x via backchain
  3. -Cforce-frame-pointers=yes should on s390x enable backchain and NOT the frame-pointer attribute
  4. the old -Ctarget-feature=+backchain pattern should emit a nice error and point to -Cforce-frame-pointers=yes
  5. the kernel folks are ok with an instant change of behaviour without a deprecation period

References

@rustbot rustbot added A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. 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 Sep 25, 2026
@rustbot

rustbot commented Sep 25, 2026

Copy link
Copy Markdown
Collaborator

r? @chenyukang

rustbot has assigned @chenyukang.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: compiler
  • compiler expanded to 77 candidates
  • Random selection from 22 candidates

@chenyukang

Copy link
Copy Markdown
Member

@rustbot reroll

@rustbot rustbot assigned beetrees and unassigned chenyukang Sep 25, 2026
@rust-log-analyzer

This comment has been minimized.

@fneddy

fneddy commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor Author

Ok. the problem is now: the ci runs the tests with --pass=check which will NOT run the codegen pass. Therefore obsolete warning is not emitted.

Either I add manual checking into an earlier stage.
Or I add a new target_feature pub enum Stability flag for deprecated/obsolete features.

Or I just move the warning to creation time of the codegen_llvm unit :)

@beetrees

Copy link
Copy Markdown
Contributor

@rustbot rustbot assigned davidtwco and unassigned beetrees Sep 25, 2026
@fneddy

fneddy commented Sep 25, 2026

Copy link
Copy Markdown
Contributor Author

my understanding is that we need the MCP as soon as the -Zunstable-options requirement is dropped. If we need it now for this I will take some days and update all mid next week.

@beetrees

Copy link
Copy Markdown
Contributor

My impression from the Zulip thread and the MCP RFC is that an MCP is generally for when the (unstable) flag is being added, with a rfcbot FCP required for stabilisation.

Comment thread compiler/rustc_codegen_llvm/src/attributes.rs Outdated
@dev-japo

dev-japo commented Sep 29, 2026 •

Copy link
Copy Markdown

Thanks for looking into this. From my perspective, a hard switch would be perfectly fine. The grace period actually caused some confusion on my side, and I don't think there's much value in carrying both variants for a transition period.

While enabling Rust support for s390 in the Linux kernel, I ended up using this argument as well, and I'd be happy to adapt to the new form directly. Redirecting the argument from one version to the next sounds like a good solution to me.

@Darksonn

Copy link
Copy Markdown
Member

I think it'd be very confusing for -Cforce-frame-pointers + -Zunstable-options to have different behavior from -Cforce-frame-pointers.

@rustbot

rustbot commented Sep 30, 2026

Copy link
Copy Markdown
Collaborator

Target features are being changed; ensure all ABI effects are being accounted for

cc @RalfJung

Comment thread compiler/rustc_target/src/target_features.rs
@rustbot

rustbot commented Sep 30, 2026

Copy link
Copy Markdown
Collaborator

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@rust-log-analyzer

This comment has been minimized.

Comment thread compiler/rustc_target/src/target_features.rs Outdated
On s390x, the `backchain` LLVM function attribute saves the "unwind"
(backchain) pointer (r15) into the caller's parameter area, enabling
external stack unwinders (e.g. Linux perf) to walk the call chain.
Previously this was enabled via `-Ctarget-feature=+backchain`, which
piggy-backed on the target-feature machinery even though backchain
is not a CPU or ISA feature.

This commit introduces a cleaner mechanism:

- `-Cforce-frame-pointers`  now enables the `"backchain"` LLVM
  *function attribute* on s390x, rather than the generic `"frame-pointer"`
  attribute used on other architectures.
- `-Ctarget-feature=+backchain` is completely removed and will be
  rejected.
- When the backchain opt-in is active, the `"frame-pointer"` attribute
  is suppressed on s390x. Other reasons to set frame pointers
  (e.g. `-Zinstrument-mcount`) are unaffected and still emit
  `"frame-pointer"`.
- All s390x-specific frame-pointer/backchain/packed-stack logic is
  consolidated in `s390x_fn_attrs()` in `attributes.rs`.

Co-authored-by: Ralf Jung <post@ralfj.de>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. 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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants