|
| 1 | +#![feature(extended_varargs_abi_support)] |
| 2 | +//@ run-pass |
| 3 | +//@ only-x86_64 |
| 4 | + |
| 5 | +// Check that multiple c-variadic calling conventions can be used in the same program. |
| 6 | +// |
| 7 | +// Clang and gcc reject defining functions with a non-default calling convention and a variable |
| 8 | +// argument list, so C programs that use multiple c-variadic calling conventions are unlikely |
| 9 | +// to come up. Here we validate that our codegen backends do in fact generate correct code. |
| 10 | + |
| 11 | +extern "sysv64" { |
| 12 | + fn variadic_sysv64(_: u32, _: ...) -> u32; |
| 13 | +} |
| 14 | + |
| 15 | +extern "win64" { |
| 16 | + fn variadic_win64(_: u32, _: ...) -> u32; |
| 17 | +} |
| 18 | + |
| 19 | +fn main() { |
| 20 | + unsafe { |
| 21 | + assert_eq!(variadic_win64(1, 2, 3), 1 + 2 + 3); |
| 22 | + assert_eq!(variadic_sysv64(1, 2, 3), 1 + 2 + 3); |
| 23 | + } |
| 24 | +} |
| 25 | + |
| 26 | +// This assembly was generated using https://godbolt.org/z/dbTGanoh6, and corresponds to the |
| 27 | +// following code compiled for the `x86_64-unknown-linux-gnu` and `x86_64-pc-windows-gnu` |
| 28 | +// targets, respectively: |
| 29 | +// |
| 30 | +// ```rust |
| 31 | +// #![feature(c_variadic)] |
| 32 | +// |
| 33 | +// #[unsafe(no_mangle)] |
| 34 | +// unsafe extern "C" fn variadic(a: u32, mut args: ...) -> u32 { |
| 35 | +// let b = args.arg::<u32>(); |
| 36 | +// let c = args.arg::<u32>(); |
| 37 | +// |
| 38 | +// a + b + c |
| 39 | +// } |
| 40 | +// ``` |
| 41 | +core::arch::global_asm!( |
| 42 | + r#" |
| 43 | +variadic_sysv64: |
| 44 | + sub rsp, 88 |
| 45 | + test al, al |
| 46 | + je .LBB0_7 |
| 47 | + movaps xmmword ptr [rsp - 48], xmm0 |
| 48 | + movaps xmmword ptr [rsp - 32], xmm1 |
| 49 | + movaps xmmword ptr [rsp - 16], xmm2 |
| 50 | + movaps xmmword ptr [rsp], xmm3 |
| 51 | + movaps xmmword ptr [rsp + 16], xmm4 |
| 52 | + movaps xmmword ptr [rsp + 32], xmm5 |
| 53 | + movaps xmmword ptr [rsp + 48], xmm6 |
| 54 | + movaps xmmword ptr [rsp + 64], xmm7 |
| 55 | +.LBB0_7: |
| 56 | + mov qword ptr [rsp - 88], rsi |
| 57 | + mov qword ptr [rsp - 80], rdx |
| 58 | + mov qword ptr [rsp - 72], rcx |
| 59 | + mov qword ptr [rsp - 64], r8 |
| 60 | + mov qword ptr [rsp - 56], r9 |
| 61 | + movabs rax, 206158430216 |
| 62 | + mov qword ptr [rsp - 120], rax |
| 63 | + lea rax, [rsp + 96] |
| 64 | + mov qword ptr [rsp - 112], rax |
| 65 | + lea rax, [rsp - 96] |
| 66 | + mov qword ptr [rsp - 104], rax |
| 67 | + mov edx, 8 |
| 68 | + cmp rdx, 41 |
| 69 | + jae .LBB0_1 |
| 70 | + mov rax, qword ptr [rsp - 104] |
| 71 | + mov ecx, 8 |
| 72 | + add rcx, 8 |
| 73 | + mov dword ptr [rsp - 120], ecx |
| 74 | + mov eax, dword ptr [rax + rdx] |
| 75 | + cmp edx, 32 |
| 76 | + ja .LBB0_2 |
| 77 | + add rcx, qword ptr [rsp - 104] |
| 78 | + add edx, 16 |
| 79 | + mov dword ptr [rsp - 120], edx |
| 80 | + add eax, edi |
| 81 | + add eax, dword ptr [rcx] |
| 82 | + add rsp, 88 |
| 83 | + ret |
| 84 | +.LBB0_1: |
| 85 | + mov rax, qword ptr [rsp - 112] |
| 86 | + lea rcx, [rax + 8] |
| 87 | + mov qword ptr [rsp - 112], rcx |
| 88 | + mov eax, dword ptr [rax] |
| 89 | +.LBB0_2: |
| 90 | + mov rcx, qword ptr [rsp - 112] |
| 91 | + lea rdx, [rcx + 8] |
| 92 | + mov qword ptr [rsp - 112], rdx |
| 93 | + add eax, edi |
| 94 | + add eax, dword ptr [rcx] |
| 95 | + add rsp, 88 |
| 96 | + ret |
| 97 | +
|
| 98 | +variadic_win64: |
| 99 | + push rax |
| 100 | + mov qword ptr [rsp + 40], r9 |
| 101 | + mov qword ptr [rsp + 24], rdx |
| 102 | + mov qword ptr [rsp + 32], r8 |
| 103 | + lea rax, [rsp + 40] |
| 104 | + mov qword ptr [rsp], rax |
| 105 | + lea eax, [rdx + rcx] |
| 106 | + add eax, r8d |
| 107 | + pop rcx |
| 108 | + ret |
| 109 | + "# |
| 110 | +); |
0 commit comments