Skip to content

Support u128/i128 c-variadic arguments#155429

Open
folkertdev wants to merge 2 commits intorust-lang:mainfrom
folkertdev:c-variadic-i128
Open

Support u128/i128 c-variadic arguments#155429
folkertdev wants to merge 2 commits intorust-lang:mainfrom
folkertdev:c-variadic-i128

Conversation

@folkertdev
Copy link
Copy Markdown
Contributor

@folkertdev folkertdev commented Apr 17, 2026

View all comments

The restriction on u128 is kind of arbitrary, so let's see what it would take to support it.

r? @ghost

@rustbot rustbot added A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. A-run-make Area: port run-make Makefiles to rmake.rs 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. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Apr 17, 2026
@folkertdev
Copy link
Copy Markdown
Contributor Author

@bors try jobs=dist-various-1,dist-various-2,aarch64-apple,x86_64-mingw-1

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Apr 17, 2026
Support `u128`/`i128` c-variadic arguments


try-job: dist-various-1
try-job: dist-various-2
try-job: aarch64-apple
try-job: x86_64-mingw-1
@rust-log-analyzer

This comment has been minimized.

@folkertdev folkertdev force-pushed the c-variadic-i128 branch 2 times, most recently from 3f2ff65 to 5e8c8b5 Compare April 17, 2026 13:27
@folkertdev
Copy link
Copy Markdown
Contributor Author

@bors try jobs=dist-various-1,dist-various-2,aarch64-apple,x86_64-mingw-1

rust-bors Bot pushed a commit that referenced this pull request Apr 17, 2026
Support `u128`/`i128` c-variadic arguments


try-job: dist-various-1
try-job: dist-various-2
try-job: aarch64-apple
try-job: x86_64-mingw-1
@rust-bors

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-bors rust-bors Bot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 17, 2026
@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors Bot commented Apr 17, 2026

💔 Test for d3bd26f failed: CI. Failed job:

@folkertdev
Copy link
Copy Markdown
Contributor Author

@bors try jobs=dist-various-1,dist-various-2,aarch64-apple,x86_64-mingw-1

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Apr 17, 2026
Support `u128`/`i128` c-variadic arguments


try-job: dist-various-1
try-job: dist-various-2
try-job: aarch64-apple
try-job: x86_64-mingw-1
@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors Bot commented Apr 18, 2026

☀️ Try build successful (CI)
Build commit: d505291 (d50529125c96155f22b48fab34b00ab49c79dcad, parent: f29256dd1420dc681bf4956e3012ffe9eccdc7e7)

@rustbot

This comment has been minimized.

Comment thread library/core/src/ffi/va_list.rs Outdated
Comment on lines +359 to +383
crate::cfg_select! {
target_pointer_width = "32" => {
// GCC says <https://gcc.gnu.org/onlinedocs/gcc-15.2.0/gcc/_005f_005fint128.html>
//
// > There is no support in GCC for expressing an integer constant of type __int128 for targets
// > with long long integer less than 128 bits wide.
}
target_env = "msvc" => {
// Per https://learn.microsoft.com/en-us/cpp/cpp/data-type-ranges?view=msvc-170, __int128 is
// not recognized by msvc.
}
any(
target_arch = "x86_64",
target_arch = "aarch64",
target_arch = "riscv64",
target_arch = "loongarch64",
target_arch = "s390x",
target_arch = "powerpc64"
) => {
unsafe impl VaArgSafe for i128 {}
unsafe impl VaArgSafe for u128 {}
}
_ => {
}
}
Copy link
Copy Markdown
Contributor Author

@folkertdev folkertdev Apr 21, 2026

Choose a reason for hiding this comment

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

cc @Amanieu @joshtriplett @workingjubilee thoughts on this as an initial set of targets to support i128 varargs on?

View changes since the review

Comment thread compiler/rustc_codegen_llvm/src/va_arg.rs Outdated
Primitive::Int(integer, _) => match integer {
Integer::I8 | Integer::I16 => unreachable!(),
Integer::I32 | Integer::I64 => { /* fall through */ }
Integer::I128 => return Align::EIGHT,
Copy link
Copy Markdown
Contributor Author

@folkertdev folkertdev Apr 21, 2026

Choose a reason for hiding this comment

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

It has custom behavior, the va_arg implementation for powerpc64 is here

https://github.com/llvm/llvm-project/blob/c7eea85b8046660f0a1fd4a1c5c41b44475f8caf/clang/lib/CodeGen/Targets/PPC.cpp#L998

and it uses the implementation here

https://github.com/llvm/llvm-project/blob/c7eea85b8046660f0a1fd4a1c5c41b44475f8caf/clang/lib/CodeGen/Targets/PPC.cpp#L765

The logic falls through to the last line for i128, returning 8. For f128 it curiously does use an alignment of 16, so I've just added that already because it would be easy to miss down the line.

View changes since the review

Comment thread library/core/src/ffi/va_list.rs
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
@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@folkertdev folkertdev force-pushed the c-variadic-i128 branch 3 times, most recently from ccdec2f to 50b74c4 Compare April 25, 2026 13:01
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 looks big but only really because I added a lot more assembly tests to check that the 128-bit implementation is correct. Due to its alignment it sometimes requires some additonal logic, so I thought it best to lock the behavior in via assembly tests.

r? tgross35

View changes since this review

Comment on lines +814 to +818
let overflow_arg_area_v = if layout.layout.align.bytes() > 8 {
round_pointer_up_to_alignment(bx, overflow_arg_area_v, layout.layout.align.abi)
} else {
overflow_arg_area_v
};
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.

Comment on lines +4 to +10
//@ revisions: WINDOWS_GNU WINDOWS_MSVC
//@ [WINDOWS_GNU] compile-flags: -Copt-level=3 -Cllvm-args=-x86-asm-syntax=intel
//@ [WINDOWS_GNU] compile-flags: --target x86_64-pc-windows-gnu
//@ [WINDOWS_GNU] needs-llvm-components: x86
//@ [WINDOWS_MSVC] compile-flags: -Copt-level=3 -Cllvm-args=-x86-asm-syntax=intel
//@ [WINDOWS_MSVC] compile-flags: --target x86_64-pc-windows-msvc
//@ [WINDOWS_MSVC] needs-llvm-components: x86
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.

Calling this out explicitly: we do implement the trait even on -msvc targets, because clang provides __int128 there. If MSVC itself ever did support the type (which, from my understanding, is unlikely), clang would kind of have to follow whatever it does, and we would too. Until then we're compatible with clang.

Comment on lines +175 to +179
// Clang and Rustc use a different ABI for i128 on wasm32, and LLVM optimizes differently if we use
// a mutable reference instead of just a pointer. With this setup we match the equivalent Clang
// input exactly.
#[unsafe(no_mangle)]
unsafe extern "C" fn read_i128(out: *mut i128, ap: *mut VaList<'_>) {
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.

just calling attention to this difference. Based on #135532 we actually follow the spec here.

Comment on lines +4 to +12
//@ revisions: POWERPC POWERPC64 POWERPC64LE AIX
//@ [POWERPC] compile-flags: -Copt-level=3 --target powerpc-unknown-linux-gnu
//@ [POWERPC] needs-llvm-components: powerpc
//@ [POWERPC64] compile-flags: -Copt-level=3 --target powerpc64-unknown-linux-gnu
//@ [POWERPC64] needs-llvm-components: powerpc
//@ [POWERPC64LE] compile-flags: -Copt-level=3 --target powerpc64le-unknown-linux-gnu
//@ [POWERPC64LE] needs-llvm-components: powerpc
//@ [AIX] compile-flags: -Copt-level=3 --target powerpc64-ibm-aix
//@ [AIX] needs-llvm-components: powerpc
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.

included because powerpc has some special behavior for i128, which is only aligned to 8 bytes in c-variadic arguments.

// assembly.
//
// For aarch64-apple-darwin LLVM is able to optimize our output better, because we effectively
// desugar va_arg early, hence we don't actually match Clang there.
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 played around with our codegen for a while, but LLVM is too clever. But, these are both tier-1 targets so we test the implementation versus C in CI, and the generated IR does look reasonable.

Comment on lines +365 to +378
// Implement `VaArgSafe` for 128-bit integers on targets where clang provides `__int128`.
//
// GCC does not implement `__int128` for any 16-bit/32-bit target:
//
// https://gcc.gnu.org/onlinedocs/gcc-15.2.0/gcc/_005f_005fint128.html
//
// > There is no support in GCC for expressing an integer constant of type __int128 for targets
// > with long long integer less than 128 bits wide.
//
// Per https://learn.microsoft.com/en-us/cpp/cpp/data-type-ranges?view=msvc-170, MSVC does not
// define `__int128`.
//
// Clang is slightly more permissive: it defines `__int128` on wasm32 (a 32-bit target) and also
// does provide `__int128` on 64-bit `*-pc-windows-msvc`, and we follow suit.
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.

calling this out: the implementation now follows clang: if it defines __int128, we impl the trait.

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.

cc @Amanieu @joshtriplett if you have objections to that.

@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 25, 2026

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

@folkertdev
Copy link
Copy Markdown
Contributor Author

may as well

@bors try jobs=dist-various-1,dist-various-2,aarch64-apple,x86_64-mingw-1

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Apr 25, 2026
Support `u128`/`i128` c-variadic arguments


try-job: dist-various-1
try-job: dist-various-2
try-job: aarch64-apple
try-job: x86_64-mingw-1
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

) -> &'ll Value {
if layout.layout.align.abi > src_align {
let tmp = bx.alloca(layout.layout.size(), layout.layout.align().abi);
let tmp = bx.alloca_with_ty(layout);
Copy link
Copy Markdown
Contributor Author

@folkertdev folkertdev Apr 25, 2026

Choose a reason for hiding this comment

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

Using a typed alloca solves an issue with the memcpy not being optimized out, see llvm/llvm-project#194158. Normally rust type erases allocas (e.g. [16 x i8]) and that confuses LLVM apparently.

View changes since the review

@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors Bot commented Apr 25, 2026

💔 Test for 9d4c015 failed: CI. Failed job:

@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 25, 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.

@folkertdev
Copy link
Copy Markdown
Contributor Author

@bors try jobs=dist-various-1,dist-various-2,aarch64-apple,x86_64-mingw-1

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Apr 25, 2026
Support `u128`/`i128` c-variadic arguments


try-job: dist-various-1
try-job: dist-various-2
try-job: aarch64-apple
try-job: x86_64-mingw-1
@rust-log-analyzer
Copy link
Copy Markdown
Collaborator

The job x86_64-gnu-tools failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
  local time: Sat Apr 25 19:56:33 UTC 2026
  network time: Sat, 25 Apr 2026 19:56:33 GMT
##[endgroup]
sccache: Starting the server...
sccache: error: Server startup failed: cache storage failed to read: ConfigInvalid (permanent) at read => S3Error { code: "NoSuchBucket", message: "The specified bucket does not exist", resource: "", request_id: "7NYD4ZBX1S25EXT6" }

Context:
   uri: https://s3.us-west-1.amazonaws.com/rust-lang-ci-sccache2/.sccache_check
   response: Parts { status: 404, version: HTTP/1.1, headers: {"x-amz-request-id": "7NYD4ZBX1S25EXT6", "x-amz-id-2": "TCTIuXSx35IiQG4YZeVPkG0eSEUu4l4am3AcI+pRfrZmG4z12GY2QxIceBlh+1YiZou48WuvDtBRFpVbj9CZs/5YWl2bZHir", "content-type": "application/xml", "transfer-encoding": "chunked", "date": "Sat, 25 Apr 2026 19:56:33 GMT", "server": "AmazonS3"} }
   service: s3
   path: .sccache_check
   range: 0-

Backtrace:
---
[TIMING:end] compile::StdLink { compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, target_compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, target: x86_64-unknown-linux-gnu, crates: [], force_recompile: false } -- 0.002
##[group]Building stage1 compiler artifacts (stage0 -> stage1, x86_64-unknown-linux-gnu)
error: process didn't exit successfully: `sccache /checkout/obj/build/bootstrap/debug/rustc -vV` (exit status: 2)
--- stderr
sccache: error: Server startup failed: cache storage failed to read: ConfigInvalid (permanent) at read => S3Error { code: "NoSuchBucket", message: "The specified bucket does not exist", resource: "", request_id: "P9QZ3T9GM252SX4F" }

Context:
   uri: https://s3.us-west-1.amazonaws.com/rust-lang-ci-sccache2/.sccache_check
   response: Parts { status: 404, version: HTTP/1.1, headers: {"x-amz-request-id": "P9QZ3T9GM252SX4F", "x-amz-id-2": "MDIWLYYftGkaYgIACHwBQvrR0RrPq+l+OQnkygHUZzJmjdQ5r82bLHI1M9rew1e/kVfOVLFAC6I=", "content-type": "application/xml", "transfer-encoding": "chunked", "date": "Sat, 25 Apr 2026 19:57:32 GMT", "server": "AmazonS3"} }
   service: s3
   path: .sccache_check
   range: 0-

Backtrace:
---
  11: <unknown>
  12: <unknown>


Run with SCCACHE_LOG=debug SCCACHE_NO_DAEMON=1 to get more information

Bootstrap failed while executing `build --stage 2 compiler rustdoc`
Build completed unsuccessfully in 0:00:25
  local time: Sat Apr 25 19:57:33 UTC 2026
  network time: Sat, 25 Apr 2026 19:57:33 GMT

@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors Bot commented Apr 25, 2026

☀️ Try build successful (CI)
Build commit: aee82fa (aee82fa5d127ed3da73b856690b5b55cbfd0efd3, parent: 9838411cb723b60dc62b1625751075c4d933b992)

@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors Bot commented Apr 26, 2026

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

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. A-run-make Area: port run-make Makefiles to rmake.rs F-c_variadic `#![feature(c_variadic)]` S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants