explicit tail calls: support indirect arguments#151143
explicit tail calls: support indirect arguments#151143rust-bors[bot] merged 2 commits intorust-lang:mainfrom
Conversation
8a1cd78 to
6f7eede
Compare
| PassMode::Indirect { on_stack: true, .. } => { | ||
| // FIXME: some LLVM backends (notably x86) do not correctly pass byval | ||
| // arguments to tail calls (as of LLVM 21). See also: | ||
| // | ||
| // - https://github.com/rust-lang/rust/pull/144232#discussion_r2218543841 | ||
| // - https://github.com/rust-lang/rust/issues/144855 | ||
| span_bug!( | ||
| fn_span, | ||
| "arguments using PassMode::Indirect {{ on_stack: true, .. }} are currently not supported for tail calls" | ||
| ) |
There was a problem hiding this comment.
I've kept the span_bug! for now.
It looks like a fix for x86 might get cherry-picked into LLVM 22. If so, I think that is enough support to allow this variant too. At that point riscv would be the next most commonly used target that would miscompile.
This comment has been minimized.
This comment has been minimized.
6f7eede to
a904f16
Compare
This comment has been minimized.
This comment has been minimized.
a904f16 to
fc79542
Compare
This comment has been minimized.
This comment has been minimized.
029786e to
414b969
Compare
|
@bors try=x86_64-msvc-1,x86_64-msvc-2 |
|
Unknown command "try". Run |
|
@bors try job=x86_64-msvc-1,x86_64-msvc-2 |
This comment has been minimized.
This comment has been minimized.
explicit tail calls: support indirect arguments try-job: x86_64-msvc-1 try-job: x86_64-msvc-2
This comment has been minimized.
This comment has been minimized.
|
💔 Test for e8cb9bb failed: CI. Failed job:
|
414b969 to
33942c6
Compare
|
@bors try job=x86_64-msvc-1,x86_64-msvc-2 |
This comment has been minimized.
This comment has been minimized.
explicit tail calls: support indirect arguments try-job: x86_64-msvc-1 try-job: x86_64-msvc-2
33942c6 to
2e004e1
Compare
|
This seems to work, though we should probably run a bunch of try jobs once the code looks good. |
|
|
|
We actually run these tests using webassembly (a tier 2 target)? @bors try job=test-various |
This comment has been minimized.
This comment has been minimized.
explicit tail calls: support indirect arguments try-job: test-various
|
@bors try cancel github is doing something weird, my latest push is not showing up... |
|
Try build cancelled. Cancelled workflows: |
c495956 to
106ccdb
Compare
|
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. |
|
@bors try job=test-various |
This comment has been minimized.
This comment has been minimized.
explicit tail calls: support indirect arguments try-job: test-various
This comment has been minimized.
This comment has been minimized.
106ccdb to
e6cf5a2
Compare
|
@bors try job=test-various |
This comment has been minimized.
This comment has been minimized.
explicit tail calls: support indirect arguments try-job: test-various
|
@bors r=WaffleLapkin |
…affleLapkin explicit tail calls: support indirect arguments tracking issue: rust-lang#112788 After discussion in rust-lang#144855, I was wrong and it is actually possible to support tail calls with `PassMode::Indirect { on_stack: false, .. }` arguments. Normally an indirect argument with `on_stack: false` would be passed as a pointer into the caller's stack frame. For tail calls, that would be unsound, because the caller's stack frame is overwritten by the callee's stack frame. Therefore we store the argument for the callee in the corresponding caller's slot. Because guaranteed tail calls demand that the caller's signature matches the callee's, the corresponding slot has the correct type. To handle cases like the one below, the tail call arguments must first be copied to a temporary, and can only then be copied to the caller's argument slots. ```rust // A struct big enough that it is not passed via registers. pub struct Big([u64; 4]); fn swapper(a: Big, b: Big) -> (Big, Big) { become swapper_helper(b, a); } ``` --- I'm not really familiar with MIR and what tricks/helpers we have, so I'm just cobbling this together. Hopefully we can arrive at something more elegant.
…uwer Rollup of 12 pull requests Successful merges: - #151143 (explicit tail calls: support indirect arguments) - #153012 (Stop using `LinkedGraph` in `lexical_region_resolve`) - #153175 (Clarify a confusing green-path function) - #153179 (Force a CI LLVM stamp bump) - #150828 (Improved security section in rustdoc for `current_exe`) - #152673 (rustc_public: rewrite `bridge_impl` to reduce boilerplate) - #152674 (rustc_public: remove the `CrateDefItems` trait) - #153073 (Fix mem::conjure_zst panic message to use any::type_name instead) - #153117 (Remove mutation from macro path URL construction) - #153128 (Recover feature lang_items for emscripten) - #153138 (Print path root when printing path) - #153159 (Work around a false `err.emit();` type error in rust-analyzer)
…uwer Rollup of 12 pull requests Successful merges: - #151143 (explicit tail calls: support indirect arguments) - #153012 (Stop using `LinkedGraph` in `lexical_region_resolve`) - #153175 (Clarify a confusing green-path function) - #153179 (Force a CI LLVM stamp bump) - #150828 (Improved security section in rustdoc for `current_exe`) - #152673 (rustc_public: rewrite `bridge_impl` to reduce boilerplate) - #152674 (rustc_public: remove the `CrateDefItems` trait) - #153073 (Fix mem::conjure_zst panic message to use any::type_name instead) - #153117 (Remove mutation from macro path URL construction) - #153128 (Recover feature lang_items for emscripten) - #153138 (Print path root when printing path) - #153159 (Work around a false `err.emit();` type error in rust-analyzer)
Rollup merge of #151143 - folkertdev:tail-call-indirect, r=WaffleLapkin explicit tail calls: support indirect arguments tracking issue: #112788 After discussion in #144855, I was wrong and it is actually possible to support tail calls with `PassMode::Indirect { on_stack: false, .. }` arguments. Normally an indirect argument with `on_stack: false` would be passed as a pointer into the caller's stack frame. For tail calls, that would be unsound, because the caller's stack frame is overwritten by the callee's stack frame. Therefore we store the argument for the callee in the corresponding caller's slot. Because guaranteed tail calls demand that the caller's signature matches the callee's, the corresponding slot has the correct type. To handle cases like the one below, the tail call arguments must first be copied to a temporary, and can only then be copied to the caller's argument slots. ```rust // A struct big enough that it is not passed via registers. pub struct Big([u64; 4]); fn swapper(a: Big, b: Big) -> (Big, Big) { become swapper_helper(b, a); } ``` --- I'm not really familiar with MIR and what tricks/helpers we have, so I'm just cobbling this together. Hopefully we can arrive at something more elegant.
View all comments
tracking issue: #112788
After discussion in #144855, I was wrong and it is actually possible to support tail calls with
PassMode::Indirect { on_stack: false, .. }arguments.Normally an indirect argument with
on_stack: falsewould be passed as a pointer into the caller's stack frame. For tail calls, that would be unsound, because the caller's stack frame is overwritten by the callee's stack frame.Therefore we store the argument for the callee in the corresponding caller's slot. Because guaranteed tail calls demand that the caller's signature matches the callee's, the corresponding slot has the correct type.
To handle cases like the one below, the tail call arguments must first be copied to a temporary, and can only then be copied to the caller's argument slots.
I'm not really familiar with MIR and what tricks/helpers we have, so I'm just cobbling this together. Hopefully we can arrive at something more elegant.