about summary refs log tree commit diff
path: root/tests/ui/c-variadic/naked.rs
blob: 46b59395485c53eb0680d52845ad289a863b5012 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//@ run-pass
//@ only-x86_64
//@ only-linux
#![feature(c_variadic)]

#[repr(C)]
#[derive(Debug, PartialEq)]
struct Data(i32, f64);

#[unsafe(naked)]
unsafe extern "C" fn c_variadic(_: ...) -> Data {
    // This assembly was generated with GCC, because clang/LLVM is unable to
    // optimize out the spilling of all registers to the stack.
    core::arch::naked_asm!(
        "        sub     rsp, 96",
        "        mov     QWORD PTR [rsp-88], rdi",
        "        test    al, al",
        "        je      .L7",
        "        movaps  XMMWORD PTR [rsp-40], xmm0",
        ".L7:",
        "        lea     rax, [rsp+104]",
        "        mov     rcx, QWORD PTR [rsp-40]",
        "        mov     DWORD PTR [rsp-112], 0",
        "        mov     QWORD PTR [rsp-104], rax",
        "        lea     rax, [rsp-88]",
        "        mov     QWORD PTR [rsp-96], rax",
        "        movq    xmm0, rcx",
        "        mov     eax, DWORD PTR [rsp-88]",
        "        mov     DWORD PTR [rsp-108], 48",
        "        add     rsp, 96",
        "        ret",
    )
}

fn main() {
    unsafe {
        assert_eq!(c_variadic(1, 2.0), Data(1, 2.0));
        assert_eq!(c_variadic(123, 4.56), Data(123, 4.56));
    }
}