Skip to content

c-variadic: use emit_ptr_va_arg for mips#152576

Merged
rust-bors[bot] merged 2 commits intorust-lang:mainfrom
folkertdev:mips-va-arg
Apr 23, 2026
Merged

c-variadic: use emit_ptr_va_arg for mips#152576
rust-bors[bot] merged 2 commits intorust-lang:mainfrom
folkertdev:mips-va-arg

Conversation

@folkertdev
Copy link
Copy Markdown
Contributor

@folkertdev folkertdev commented Feb 13, 2026

View all comments

tracking issue: #44930

After reading the implementation carefully, I believe it really is just emit_ptr_va_arg.

The LLVM implementation can be found here: https://github.com/llvm/llvm-project/blob/289a3292be0c6a3df86bcdf5be7dd05b79a5570c/llvm/lib/Target/Mips/MipsISelLowering.cpp#L2338.

r? workingjubilee

@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 Feb 13, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Feb 13, 2026

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

bx,
addr,
target_ty,
PassMode::Direct,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Nothing in the LLVM implementation suggests a double load. byval is not handled.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

and there is no conditional logic based on the size either

Comment on lines +1178 to +1182
match bx.tcx().sess.target.pointer_width {
32 => SlotSize::Bytes4,
64 => SlotSize::Bytes8,
_ => unreachable!(),
},
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

based on

  unsigned ArgSlotSizeInBytes = (ABI.IsN32() || ABI.IsN64()) ? 8 : 4;

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.

...Hm, but

(ABI.IsN32() || ABI.IsN64()) ? 8 : 4;

evaluates to 8 if N32 or N64 is true, no? And N32 is an ILP32 ABI despite having 64-bit registers available, if I understand correctly.

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.

Is this correct anyways for the targets we actually support? A comment might be desired about the frumious "N32" ABI, if so.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It is correct for our current targets, but we can match the LLVM logic more based on

https://github.com/llvm/llvm-project/blob/67e47fb5317cabd82317379baf8e31d61984d43d/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp#L64-L78

I've implemented that now.

64 => SlotSize::Bytes8,
_ => unreachable!(),
},
AllowHigherAlign::Yes,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Because the code allows, and corrects for, a higher alignment

if (Align > getMinStackArgumentAlignment()) {

Comment on lines +1184 to +1187
match bx.tcx().sess.target.endian {
Endian::Big => ForceRightAdjust::Yes,
Endian::Little => ForceRightAdjust::No,
},
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

there is a whole comment about this

  // In big-endian mode we must adjust the pointer when the load size is smaller
  // than the argument slot size. We must also reduce the known alignment to
  // match. For example in the N64 ABI, we must add 4 bytes to the offset to get
  // the correct half of the slot, and reduce the alignment from 8 (slot
  // alignment) down to 4 (type alignment).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Something to this effect seems rather helpful to have in a code comment rather than a review comment? Ditto for align comment, I don't think that's all going to be obvious when somebody reads this code.

ForceRightAdjust could also use some documentation, I needed to dig a bit to figure out its intended purpose. (same for AllowHigherAlign though that one is more obvious)

@folkertdev folkertdev added the F-c_variadic `#![feature(c_variadic)]` label Feb 13, 2026
@folkertdev folkertdev changed the title Mips va arg c-variadic: use emit_ptr_va_arg for mips Feb 13, 2026
@folkertdev
Copy link
Copy Markdown
Contributor Author

Pinging some target maintainers:

@Gelbpunkt @wzssyqa @chenx97 @709924470 @Cyanoxygen @Fearyncess

Mostly this is just a heads-up. You could try to run (with your target) this test to be sure that it all works:

./x test tests/run-make/c-link-to-rust-va-list-fn --target mipsel-unknown-linux-gnu

this likely needs some sort of config in bootstrap.toml, I have

[target.mips64-unknown-linux-gnuabi64]
runner = "qemu-mips64 -L /usr/mips64-linux-gnuabi64"

[target.mipsel-unknown-linux-gnu]
runner = "qemu-mipsel -cpu 24Kf -L /usr/mipsel-linux-gnu"

[target.mips-unknown-linux-gnu]
runner = "qemu-mips -L /usr/mips-linux-gnu"

@rustbot

This comment has been minimized.

@folkertdev
Copy link
Copy Markdown
Contributor Author

r? tgross35

@rustbot rustbot assigned tgross35 and unassigned workingjubilee Apr 21, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 21, 2026

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

@tgross35
Copy link
Copy Markdown
Contributor

Do we have any asm tests for varargs that could be extended to this target? Unfortunately I don't know much about this area of code and I'm not positive what effects I should actually be looking for.

@folkertdev
Copy link
Copy Markdown
Contributor Author

We don't, but I could add some.

Really I think what we're looking for is whether the mips implementation subtly deviates from what emit_ptr_va_arg does. E.g. by changing the alignment for some type.

I'll also just extract the non-mips changes, they were combined for convenience but not it probably makes more sense to split them up.

@rustbot

This comment has been minimized.

Copy link
Copy Markdown
Contributor Author

@folkertdev folkertdev left a comment

Choose a reason for hiding this comment

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

this will need a rebase after the currently in flight PR merges, so it's not quite ready yet, but I added an extra commit that captures what assembly LLVM generates, and then an updated version with the rustc implementation.

on 32-bit mips that leads to a slightly nasty diff no matter what I do, but I believe it is in fact equivalent.

View changes since this review

Comment thread tests/assembly-llvm/c-variadic-mips.rs Outdated
Comment on lines +91 to +95
// mips64el-NEXT: lw $1, 0($1)
// mips64el-NEXT: lw $2, 0($1)
// mips64el-NEXT: jr $ra
// mips64el-NEXT: sll $2, $1, 0
// mips64el-NEXT: nop
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

the rust versions stores the value into $2 directly, clang emits this weird "shift by zero" instruction, essentially a move, that has the same effect.

Comment thread tests/assembly-llvm/c-variadic-mips.rs Outdated
Comment on lines 103 to 114
// mips: lw $1, 0($4)
// mips-NEXT: addiu $2, $zero, 4
// mips-NEXT: addiu $1, $1, 7
// mips-NEXT: move $3, $1
// mips-NEXT: ins $3, $2, 0, 3
// mips-NEXT: addiu $2, $zero, -8
// mips-NEXT: addiu $1, $1, 7
// mips-NEXT: and $2, $1, $2
// mips-NEXT: addiu $3, $2, 8
// mips-NEXT: sw $3, 0($4)
// mips-NEXT: and $1, $1, $2
// mips-NEXT: lw $2, 0($1)
// mips-NEXT: addiu $1, $3, 4
// mips-NEXT: sw $1, 0($4)
// mips-NEXT: lw $3, 0($3)
// mips-NEXT: addiu $3, $zero, 4
// mips-NEXT: lw $2, 0($2)
// mips-NEXT: ins $1, $3, 0, 3
// mips-NEXT: lw $3, 0($1)
// mips-NEXT: jr $ra
// mips-NEXT: nop
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I stared at this for a long time, and am fairly confident these are equivalent. The equivalence is easier to see on godbolt which compiles this slightly differently (I don't know why, but both should be valid compilations for the target)

https://godbolt.org/z/h7WxPE58n

The original version calculates a pointer to the second word, and writes that back into ap, but the value is never used and ap is later overwritten.

ori     $2, $1, 4 # $2 = aligned + 4
addiu   $3, $1, 8 # $3 = aligned + 8
sw      $2, 0($4) # *ap = aligned + 4
lw      $2, 0($1) # $2 = *$1
sw      $3, 0($4) # *ap = aligned + 8
lw      $3, 4($1) # $3 = *($1 + 4)

versus

addiu   $2, $1, 8 # $2 = aligned + 8
sw      $2, 0($4) # *ap = aligned + 8
lw      $2, 0($1) # $2 = *$1
lw      $3, 4($1) # $3 = *($1 + 4)

@rust-log-analyzer

This comment has been minimized.

JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Apr 22, 2026
…ross35

c-variadic: `va_arg` fixes

tracking issue: rust-lang#44930

extracts some generic LLVM `va_arg` fixes from rust-lang#152576 and rust-lang#155429.

r? tgross35
rust-timer added a commit that referenced this pull request Apr 22, 2026
Rollup merge of #155622 - folkertdev:va-arg-llvm-fixes, r=tgross35

c-variadic: `va_arg` fixes

tracking issue: #44930

extracts some generic LLVM `va_arg` fixes from #152576 and #155429.

r? tgross35
@rust-bors

This comment has been minimized.

Copy link
Copy Markdown
Contributor

@tgross35 tgross35 left a comment

Choose a reason for hiding this comment

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

I can barely read the mips assembly but think it serves the purpose of making sure we don't accidentally change implementations. One request here with the naming, and the request above to turn the review notes into comments, then r=me.

(Thanks for separating test addition from doing the update, made it easy to see what changed)

View changes since this review

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Any thought on making this c-variadic.rs and then eventually merging in the ARM version and others? Since many arches need the same test cases I'm not sure it's worth duplicating the setup.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'd rather keep them separate per-arch, working with these files is already not that fun when they do need updating. We could put them in their own directory

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reasonable enough, +1 to a variadic directory.

How did you update these by the way? As far as I know we don't have anything like LLVM's python script.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Right, so conveniently we do write the whole generated asm file to disk (for each revision), and then it's some vim stuff (retab to get rid of tabs, multiple cursors for adding the NEXT lines). But, pretty tedious still.

Especially because it took a couple of tries to land on the right thing to even test. For any real program, our version gets optimized differently because we provide LLVM with the separate loads early, while LLVM itself only expands va_arg quite late.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Reasonable enough, +1 to a variadic directory.

I'll look at that in the sparc PR

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Oof, that's pretty brutal. It would be nice if we could have --bless work something like the LLVM script tbh, but that sounds like a bit of a pain to build.

Comment thread tests/assembly-llvm/c-variadic-mips.rs Outdated
Comment on lines +4 to +10
//@ revisions: mips mips64 mips64el
//@ [mips] compile-flags: -Copt-level=3 --target mips-unknown-linux-gnu
//@ [mips] needs-llvm-components: mips
//@ [mips64] compile-flags: -Copt-level=3 --target mipsisa64r6-unknown-linux-gnuabi64
//@ [mips64] needs-llvm-components: mips
//@ [mips64el] compile-flags: -Copt-level=3 --target mips64el-unknown-linux-gnuabi64
//@ [mips64el] needs-llvm-components: mips
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nit, I think we've been using more uppercase revisions for the codegen tests to match CHECK and the NEXT suffixes

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

really? I though it was because there is some lowercase revision name that doesn't work (windows maybe? some common name like that). But I'm happy to change them

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It's just for consistency with filecheck AFAIK, we've talked about auto-uppercasing vs. just using uppercase names before to make things match. But everything is totally inconsistent so also a complete 🤷‍♂️ if you don't feel like changing it

@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 22, 2026

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.

Copy link
Copy Markdown
Contributor

@tgross35 tgross35 left a comment

Choose a reason for hiding this comment

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

@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors Bot commented Apr 22, 2026

📌 Commit e9ab558 has been approved by tgross35

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 Apr 22, 2026
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Apr 23, 2026
c-variadic: use `emit_ptr_va_arg` for  mips

tracking issue: rust-lang#44930

After reading the implementation carefully, I believe it really is just `emit_ptr_va_arg`.

The LLVM implementation can be found here: https://github.com/llvm/llvm-project/blob/289a3292be0c6a3df86bcdf5be7dd05b79a5570c/llvm/lib/Target/Mips/MipsISelLowering.cpp#L2338.

r? workingjubilee
rust-bors Bot pushed a commit that referenced this pull request Apr 23, 2026
…uwer

Rollup of 10 pull requests

Successful merges:

 - #146544 (mir-opt: Remove the workaround in UnreachableEnumBranching)
 - #154819 (Fix ICE for inherent associated type mismatches)
 - #155265 (Improved assumptions relating to isqrt)
 - #152576 (c-variadic: use `emit_ptr_va_arg` for  mips)
 - #154481 (Mark a function only used in nightly as nightly only)
 - #155614 (c-variadic: rename `VaList::arg` to `VaList::next_arg`)
 - #155630 (Make `//@ skip-filecheck` a normal compiletest directive)
 - #155641 (Remove non-working code for "running" mir-opt tests)
 - #155652 (Expand `Path::is_empty` docs)
 - #155656 (rustc_llvm: update opt-level handling for LLVM 23)
@rust-bors rust-bors Bot merged commit 6cc506c into rust-lang:main Apr 23, 2026
11 checks passed
@rustbot rustbot added this to the 1.97.0 milestone Apr 23, 2026
rust-timer added a commit that referenced this pull request Apr 23, 2026
Rollup merge of #152576 - folkertdev:mips-va-arg, r=tgross35

c-variadic: use `emit_ptr_va_arg` for  mips

tracking issue: #44930

After reading the implementation carefully, I believe it really is just `emit_ptr_va_arg`.

The LLVM implementation can be found here: https://github.com/llvm/llvm-project/blob/289a3292be0c6a3df86bcdf5be7dd05b79a5570c/llvm/lib/Target/Mips/MipsISelLowering.cpp#L2338.

r? workingjubilee
pull Bot pushed a commit to LeeeeeeM/miri that referenced this pull request Apr 24, 2026
…uwer

Rollup of 10 pull requests

Successful merges:

 - rust-lang/rust#146544 (mir-opt: Remove the workaround in UnreachableEnumBranching)
 - rust-lang/rust#154819 (Fix ICE for inherent associated type mismatches)
 - rust-lang/rust#155265 (Improved assumptions relating to isqrt)
 - rust-lang/rust#152576 (c-variadic: use `emit_ptr_va_arg` for  mips)
 - rust-lang/rust#154481 (Mark a function only used in nightly as nightly only)
 - rust-lang/rust#155614 (c-variadic: rename `VaList::arg` to `VaList::next_arg`)
 - rust-lang/rust#155630 (Make `//@ skip-filecheck` a normal compiletest directive)
 - rust-lang/rust#155641 (Remove non-working code for "running" mir-opt tests)
 - rust-lang/rust#155652 (Expand `Path::is_empty` docs)
 - rust-lang/rust#155656 (rustc_llvm: update opt-level handling for LLVM 23)
github-actions Bot pushed a commit to rust-lang/rustc-dev-guide that referenced this pull request Apr 24, 2026
c-variadic: `va_arg` fixes

tracking issue: rust-lang/rust#44930

extracts some generic LLVM `va_arg` fixes from rust-lang/rust#152576 and rust-lang/rust#155429.

r? tgross35
github-actions Bot pushed a commit to rust-lang/rustc-dev-guide that referenced this pull request Apr 24, 2026
…uwer

Rollup of 10 pull requests

Successful merges:

 - rust-lang/rust#146544 (mir-opt: Remove the workaround in UnreachableEnumBranching)
 - rust-lang/rust#154819 (Fix ICE for inherent associated type mismatches)
 - rust-lang/rust#155265 (Improved assumptions relating to isqrt)
 - rust-lang/rust#152576 (c-variadic: use `emit_ptr_va_arg` for  mips)
 - rust-lang/rust#154481 (Mark a function only used in nightly as nightly only)
 - rust-lang/rust#155614 (c-variadic: rename `VaList::arg` to `VaList::next_arg`)
 - rust-lang/rust#155630 (Make `//@ skip-filecheck` a normal compiletest directive)
 - rust-lang/rust#155641 (Remove non-working code for "running" mir-opt tests)
 - rust-lang/rust#155652 (Expand `Path::is_empty` docs)
 - rust-lang/rust#155656 (rustc_llvm: update opt-level handling for LLVM 23)
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-c_variadic `#![feature(c_variadic)]` 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.

5 participants