about summary refs log tree commit diff
path: root/tests/ui/c-variadic
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/c-variadic')
-rw-r--r--tests/ui/c-variadic/naked.rs40
1 files changed, 40 insertions, 0 deletions
diff --git a/tests/ui/c-variadic/naked.rs b/tests/ui/c-variadic/naked.rs
new file mode 100644
index 00000000000..46b59395485
--- /dev/null
+++ b/tests/ui/c-variadic/naked.rs
@@ -0,0 +1,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));
+    }
+}