about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJacob Pratt <jacob@jhpratt.dev>2025-07-26 22:42:34 -0400
committerGitHub <noreply@github.com>2025-07-26 22:42:34 -0400
commitc96c80250e39412f480bca0e9ea2121252d08ac5 (patch)
treedb50d59a344b9e1ced637bce2646bce15aa0b63a
parente2c2d1a493e5893b80dc02ae6efd9de9ffefa450 (diff)
parent69ebf7049f2ecb3b6d65c6b6343f94361ca28c6d (diff)
downloadrust-c96c80250e39412f480bca0e9ea2121252d08ac5.tar.gz
rust-c96c80250e39412f480bca0e9ea2121252d08ac5.zip
Rollup merge of #144379 - folkertdev:c-variadic-same-program-multiple-abis, r=RalfJung
test using multiple c-variadic ABIs in the same program

tracking issue: https://github.com/rust-lang/rust/issues/100189

Check that multiple c-variadic calling conventions can be used in the same program.

Clang and gcc reject defining functions with a non-default calling convention and a variable
argument list, so C programs that use multiple c-variadic calling conventions are unlikely
to come up. Here we validate that our codegen backends do in fact generate correct code.

(CI will not run this test because it runs on aarch64, I would like to at least test that this runs on windows)

try-job: `x86_64-gnu`
try-job: `x86_64-msvc-*`
try-job: `x86_64-apple-2`
-rw-r--r--tests/ui/c-variadic/same-program-multiple-abis.rs112
1 files changed, 112 insertions, 0 deletions
diff --git a/tests/ui/c-variadic/same-program-multiple-abis.rs b/tests/ui/c-variadic/same-program-multiple-abis.rs
new file mode 100644
index 00000000000..b21accb999e
--- /dev/null
+++ b/tests/ui/c-variadic/same-program-multiple-abis.rs
@@ -0,0 +1,112 @@
+#![feature(extended_varargs_abi_support)]
+//@ run-pass
+//@ only-x86_64
+
+// Check that multiple c-variadic calling conventions can be used in the same program.
+//
+// Clang and gcc reject defining functions with a non-default calling convention and a variable
+// argument list, so C programs that use multiple c-variadic calling conventions are unlikely
+// to come up. Here we validate that our codegen backends do in fact generate correct code.
+
+extern "sysv64" {
+    fn variadic_sysv64(_: u32, _: ...) -> u32;
+}
+
+extern "win64" {
+    fn variadic_win64(_: u32, _: ...) -> u32;
+}
+
+fn main() {
+    unsafe {
+        assert_eq!(variadic_win64(1, 2, 3), 1 + 2 + 3);
+        assert_eq!(variadic_sysv64(1, 2, 3), 1 + 2 + 3);
+    }
+}
+
+// This assembly was generated using https://godbolt.org/z/dbTGanoh6, and corresponds to the
+// following code compiled for the `x86_64-unknown-linux-gnu` and `x86_64-pc-windows-gnu`
+// targets, respectively:
+//
+// ```rust
+// #![feature(c_variadic)]
+//
+// #[unsafe(no_mangle)]
+// unsafe extern "C" fn variadic(a: u32, mut args: ...) -> u32 {
+//     let b = args.arg::<u32>();
+//     let c = args.arg::<u32>();
+//
+//     a + b + c
+// }
+// ```
+core::arch::global_asm!(
+    r#"
+{variadic_sysv64}:
+        sub     rsp, 88
+        test    al, al
+        je      .LBB0_7
+        movaps  xmmword ptr [rsp - 48], xmm0
+        movaps  xmmword ptr [rsp - 32], xmm1
+        movaps  xmmword ptr [rsp - 16], xmm2
+        movaps  xmmword ptr [rsp], xmm3
+        movaps  xmmword ptr [rsp + 16], xmm4
+        movaps  xmmword ptr [rsp + 32], xmm5
+        movaps  xmmword ptr [rsp + 48], xmm6
+        movaps  xmmword ptr [rsp + 64], xmm7
+.LBB0_7:
+        mov     qword ptr [rsp - 88], rsi
+        mov     qword ptr [rsp - 80], rdx
+        mov     qword ptr [rsp - 72], rcx
+        mov     qword ptr [rsp - 64], r8
+        mov     qword ptr [rsp - 56], r9
+        movabs  rax, 206158430216
+        mov     qword ptr [rsp - 120], rax
+        lea     rax, [rsp + 96]
+        mov     qword ptr [rsp - 112], rax
+        lea     rax, [rsp - 96]
+        mov     qword ptr [rsp - 104], rax
+        mov     edx, 8
+        cmp     rdx, 41
+        jae     .LBB0_1
+        mov     rax, qword ptr [rsp - 104]
+        mov     ecx, 8
+        add     rcx, 8
+        mov     dword ptr [rsp - 120], ecx
+        mov     eax, dword ptr [rax + rdx]
+        cmp     edx, 32
+        ja      .LBB0_2
+        add     rcx, qword ptr [rsp - 104]
+        add     edx, 16
+        mov     dword ptr [rsp - 120], edx
+        add     eax, edi
+        add     eax, dword ptr [rcx]
+        add     rsp, 88
+        ret
+.LBB0_1:
+        mov     rax, qword ptr [rsp - 112]
+        lea     rcx, [rax + 8]
+        mov     qword ptr [rsp - 112], rcx
+        mov     eax, dword ptr [rax]
+.LBB0_2:
+        mov     rcx, qword ptr [rsp - 112]
+        lea     rdx, [rcx + 8]
+        mov     qword ptr [rsp - 112], rdx
+        add     eax, edi
+        add     eax, dword ptr [rcx]
+        add     rsp, 88
+        ret
+
+{variadic_win64}:
+        push    rax
+        mov     qword ptr [rsp + 40], r9
+        mov     qword ptr [rsp + 24], rdx
+        mov     qword ptr [rsp + 32], r8
+        lea     rax, [rsp + 40]
+        mov     qword ptr [rsp], rax
+        lea     eax, [rdx + rcx]
+        add     eax, r8d
+        pop     rcx
+        ret
+    "#,
+    variadic_win64 = sym variadic_win64,
+    variadic_sysv64 = sym variadic_sysv64,
+);