| #![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, |
| ); |