Skip to content

Refactor the way cg_ssa handles indirect returns (returns via sret) — Take 2 - #160023

Merged
rust-bors[bot] merged 7 commits into
rust-lang:mainfrom
antoyo:ssa-indirect-return
Sep 11, 2026
Merged

Refactor the way cg_ssa handles indirect returns (returns via sret) — Take 2#160023
rust-bors[bot] merged 7 commits into
rust-lang:mainfrom
antoyo:ssa-indirect-return

Conversation

@antoyo

@antoyo antoyo commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

This continues the work that @FractalFir done in #144976.

I managed to make this work, so this confirms the original approach works and is ready to merge.

r? workingjubilee

(assigning the same reviewer as the original PR)

The problem

The current way cg_ssa handles PassMode::Indirect is fundamentally incompatible with the requirements of the GCC backend. This is currently worked around in a very brittle way, that breaks on ARM.

In order to function correctly, cg_gcc requires the sret(indirect return) pointer to be treated in a special way.

The solution

This PR separates the sret pointer from all the other arguments, allowing each backend to decide how it wants to handle that pointer. This will allow GCC to do it's own thing, while changing nothing on the LLVM side. Currently, the PR just makes both backends preappend the sret arg, mimicking the previous behaviour.

The PR is based on this zulip suggestion.

Assumptions I made.

The PR makes certain assumptions about the ABI handling.

  1. No LLVM intrinsic returns via sret. According to my sources, this is always true.
  2. Tail calls don't currently return via sret. From asking about, it seems like the tail call handling does not currently support indirect returns. So, I did not add support for that.
  3. TLS shims don't perform indirect returns, and asserts and drops also don't perform indirect returns(since they return nothing) - those assumptions seemed reasonable.
  4. Inline assembly calls don't use indirect returns. I assumed functions like inline_asm_call will not need the sret handling code. I am not 100% sure about this, tough.

@rustbot

rustbot commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

Some changes occurred in compiler/rustc_codegen_llvm/src/builder/autodiff.rs

cc @ZuseZ4

rustc_codegen_gcc is developed in its own repository. If possible, consider making this change to rust-lang/rustc_codegen_gcc instead.

cc @GuillaumeGomez

@rustbot rustbot added A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. F-autodiff `#![feature(autodiff)]` 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 Jul 27, 2026
@rustbot

rustbot commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

workingjubilee is currently at their maximum review capacity.
They may take a while to respond.

@rust-log-analyzer

This comment has been minimized.

@antoyo
antoyo force-pushed the ssa-indirect-return branch from 8a2ec6b to 25ec648 Compare July 27, 2026 17:46
@antoyo

antoyo commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

@bors try

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Jul 27, 2026
Refactor the way cg_ssa handles indirect returns (returns via `sret`) — Take 2
Comment thread compiler/rustc_codegen_llvm/src/builder.rs Outdated
Comment thread compiler/rustc_codegen_llvm/src/builder.rs Outdated
@rust-bors

rust-bors Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

☀️ Try build successful (CI)
Build commit: 3ae8918 (3ae8918f6a7874e42bc8432d0339e0d172a2daa6)
Base parent: 4fefe36 (4fefe3656700e5528edddc2336667818917dfc70)

@rust-bors

This comment has been minimized.

@rust-bors

This comment has been minimized.

@antoyo
antoyo force-pushed the ssa-indirect-return branch from 4cef956 to d2b0028 Compare August 21, 2026 11:51
@rustbot

This comment has been minimized.

@antoyo
antoyo force-pushed the ssa-indirect-return branch from d2b0028 to 47c07d8 Compare August 21, 2026 11:55
@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-bors

This comment has been minimized.

@antoyo
antoyo force-pushed the ssa-indirect-return branch from 1c68965 to cab1d5d Compare September 9, 2026 15:32
@rustbot

rustbot commented Sep 9, 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.

@antoyo
antoyo force-pushed the ssa-indirect-return branch from cab1d5d to 7d0d273 Compare September 9, 2026 16:00
// FIXME directly use the llvm intrinsic adjustment functions here
let llret = self.call(fn_ty, None, None, fn_ptr, &call_args, None, None);
let llret =
self.call(fn_ty, None, None, fn_ptr, ReturnSlot::Direct, &call_args, None, None);

@workingjubilee workingjubilee Sep 11, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ah, this is also a way to address my main concern of "why are we passing another mysterious Option-like thing that needs comments to explain it".

I'm not super-enthused about call in general but this is a tolerable change as a result.

View changes since the review

@workingjubilee

Copy link
Copy Markdown
Member

@bors r+ rollup

@rust-bors

rust-bors Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

📌 Commit 7d0d273 has been approved by workingjubilee

It is now in the queue for this repository.

@rust-bors rust-bors Bot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Sep 11, 2026
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Sep 11, 2026
…ingjubilee

Refactor the way cg_ssa handles indirect returns (returns via `sret`) — Take 2

This continues the work that @FractalFir done in rust-lang#144976.

**I managed to make this work, so this confirms the original approach works and is ready to merge.**

r? workingjubilee

(assigning the same reviewer as the original PR)

# The problem

The current way `cg_ssa` handles `PassMode::Indirect` is fundamentally incompatible with the requirements of the GCC backend. This is currently worked around in a very brittle way, that breaks on ARM.

In order to function correctly, `cg_gcc` requires the `sret`(indirect return) pointer to be treated in a special way.

# The solution

This PR separates the `sret` pointer from all the other arguments, allowing each backend to decide how it wants to handle that pointer. This will allow GCC to do it's own thing, while changing nothing on the LLVM side. Currently, the PR just makes both backends preappend the sret arg, mimicking the previous behaviour.

The PR is based on this [zulip suggestion](https://rust-lang.zulipchat.com/#narrow/channel/421156-gsoc/topic/Project.3A.20Bootstrap.20of.20rustc.20with.20rustc_codegen_gcc/near/526487725).

# Assumptions I made.

The PR makes certain assumptions about the ABI handling.

1. No LLVM intrinsic returns via sret. [According to my sources](https://rust-lang.zulipchat.com/#narrow/channel/182449-t-compiler.2Fhelp/topic/Can.20LLVM.20intrinsics.20return.20via.20PassMode.3A.3AIndirect.3F), this is always true.
2. Tail calls don't currently return via `sret`. From [asking about](https://rust-lang.zulipchat.com/#narrow/channel/182449-t-compiler.2Fhelp/topic/Can.20tail.20calls.20return.20indirectly.28via.20a.20pointer.29.3F/near/532984507), it seems like the tail call handling does not currently support indirect returns. So, I did not add support for that.
3. TLS shims don't perform indirect returns, and asserts and drops also don't perform indirect returns(since they return nothing) - those assumptions seemed reasonable.
4. Inline assembly calls don't use indirect returns. I *assumed* functions like `inline_asm_call` will not need the `sret` handling code. I am not 100% sure about this, tough.
rust-bors Bot pushed a commit that referenced this pull request Sep 11, 2026
…uwer

Rollup of 10 pull requests

Successful merges:

 - #162126 (Rename various resolving functions for consistency, and document them)
 - #162520 (Refactor `HygieneEncodeContext`)
 - #154373 (Skip linting unused braces for FunctionArg and MethodArg context for 2024 later )
 - #160023 (Refactor the way cg_ssa handles indirect returns (returns via `sret`) — Take 2)
 - #161482 (Use attribute parser for `#[non_exhaustive]` attribute check)
 - #161867 (deeper `rustc_builtin_macros` cleanups)
 - #162099 (small refactor of doc attribute arguments warnings)
 - #162541 (split `macroless_generic_const_args` in two)
 - #162549 (The fuchsia team maintains `riscv64gc-unknown-fuchsia`)
 - #162577 (Fix `i686-pc-windows-msvc` platform support docs and target spec metadata)
Zalathar added a commit to Zalathar/rust that referenced this pull request Sep 11, 2026
…ingjubilee

Refactor the way cg_ssa handles indirect returns (returns via `sret`) — Take 2

This continues the work that @FractalFir done in rust-lang#144976.

**I managed to make this work, so this confirms the original approach works and is ready to merge.**

r? workingjubilee

(assigning the same reviewer as the original PR)

# The problem

The current way `cg_ssa` handles `PassMode::Indirect` is fundamentally incompatible with the requirements of the GCC backend. This is currently worked around in a very brittle way, that breaks on ARM.

In order to function correctly, `cg_gcc` requires the `sret`(indirect return) pointer to be treated in a special way.

# The solution

This PR separates the `sret` pointer from all the other arguments, allowing each backend to decide how it wants to handle that pointer. This will allow GCC to do it's own thing, while changing nothing on the LLVM side. Currently, the PR just makes both backends preappend the sret arg, mimicking the previous behaviour.

The PR is based on this [zulip suggestion](https://rust-lang.zulipchat.com/#narrow/channel/421156-gsoc/topic/Project.3A.20Bootstrap.20of.20rustc.20with.20rustc_codegen_gcc/near/526487725).

# Assumptions I made.

The PR makes certain assumptions about the ABI handling.

1. No LLVM intrinsic returns via sret. [According to my sources](https://rust-lang.zulipchat.com/#narrow/channel/182449-t-compiler.2Fhelp/topic/Can.20LLVM.20intrinsics.20return.20via.20PassMode.3A.3AIndirect.3F), this is always true.
2. Tail calls don't currently return via `sret`. From [asking about](https://rust-lang.zulipchat.com/#narrow/channel/182449-t-compiler.2Fhelp/topic/Can.20tail.20calls.20return.20indirectly.28via.20a.20pointer.29.3F/near/532984507), it seems like the tail call handling does not currently support indirect returns. So, I did not add support for that.
3. TLS shims don't perform indirect returns, and asserts and drops also don't perform indirect returns(since they return nothing) - those assumptions seemed reasonable.
4. Inline assembly calls don't use indirect returns. I *assumed* functions like `inline_asm_call` will not need the `sret` handling code. I am not 100% sure about this, tough.
rust-bors Bot pushed a commit that referenced this pull request Sep 11, 2026
…uwer

Rollup of 11 pull requests

Successful merges:

 - #162520 (Refactor `HygieneEncodeContext`)
 - #154373 (Skip linting unused braces for FunctionArg and MethodArg context for 2024 later )
 - #160023 (Refactor the way cg_ssa handles indirect returns (returns via `sret`) — Take 2)
 - #160860 (Implement arbitrary casts in custom mir)
 - #161482 (Use attribute parser for `#[non_exhaustive]` attribute check)
 - #161867 (deeper `rustc_builtin_macros` cleanups)
 - #162099 (small refactor of doc attribute arguments warnings)
 - #162541 (split `macroless_generic_const_args` in two)
 - #162549 (The fuchsia team maintains `riscv64gc-unknown-fuchsia`)
 - #162577 (Fix `i686-pc-windows-msvc` platform support docs and target spec metadata)
 - #162624 (regression test for opaque field projection in closure capture)
@rust-bors
rust-bors Bot merged commit 7cd747d into rust-lang:main Sep 11, 2026
13 checks passed
@rustbot rustbot added this to the 1.100.0 milestone Sep 11, 2026
rust-bors Bot pushed a commit that referenced this pull request Sep 11, 2026
Rollup merge of #160023 - antoyo:ssa-indirect-return, r=workingjubilee

Refactor the way cg_ssa handles indirect returns (returns via `sret`) — Take 2

This continues the work that @FractalFir done in #144976.

**I managed to make this work, so this confirms the original approach works and is ready to merge.**

r? workingjubilee

(assigning the same reviewer as the original PR)

# The problem

The current way `cg_ssa` handles `PassMode::Indirect` is fundamentally incompatible with the requirements of the GCC backend. This is currently worked around in a very brittle way, that breaks on ARM.

In order to function correctly, `cg_gcc` requires the `sret`(indirect return) pointer to be treated in a special way.

# The solution

This PR separates the `sret` pointer from all the other arguments, allowing each backend to decide how it wants to handle that pointer. This will allow GCC to do it's own thing, while changing nothing on the LLVM side. Currently, the PR just makes both backends preappend the sret arg, mimicking the previous behaviour.

The PR is based on this [zulip suggestion](https://rust-lang.zulipchat.com/#narrow/channel/421156-gsoc/topic/Project.3A.20Bootstrap.20of.20rustc.20with.20rustc_codegen_gcc/near/526487725).

# Assumptions I made.

The PR makes certain assumptions about the ABI handling.

1. No LLVM intrinsic returns via sret. [According to my sources](https://rust-lang.zulipchat.com/#narrow/channel/182449-t-compiler.2Fhelp/topic/Can.20LLVM.20intrinsics.20return.20via.20PassMode.3A.3AIndirect.3F), this is always true.
2. Tail calls don't currently return via `sret`. From [asking about](https://rust-lang.zulipchat.com/#narrow/channel/182449-t-compiler.2Fhelp/topic/Can.20tail.20calls.20return.20indirectly.28via.20a.20pointer.29.3F/near/532984507), it seems like the tail call handling does not currently support indirect returns. So, I did not add support for that.
3. TLS shims don't perform indirect returns, and asserts and drops also don't perform indirect returns(since they return nothing) - those assumptions seemed reasonable.
4. Inline assembly calls don't use indirect returns. I *assumed* functions like `inline_asm_call` will not need the `sret` handling code. I am not 100% sure about this, tough.
@rust-timer

Copy link
Copy Markdown
Collaborator

Note

This PR was benchmarked as part of triage of its containing rollup: triage URL.

Finished benchmarking commit (51474fd): comparison URL.

Overall result: no relevant changes - no action needed

@rustbot label: -perf-regression

Instruction count

This perf run didn't have relevant results for this metric.

Max RSS (memory usage)

This perf run didn't have relevant results for this metric.

Cycles

This perf run didn't have relevant results for this metric.

Binary size

This perf run didn't have relevant results for this metric.

Bootstrap: missing data
Artifact size: 407.63 MiB -> 406.94 MiB (-0.17%)

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. F-autodiff `#![feature(autodiff)]` S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. 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.

7 participants