blob: b21accb999e9b545b50590c5f34af5d2a1e8a517 [file] [log] [blame]
#![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,
);