about summary refs log tree commit diff
path: root/tests/codegen-llvm/naked-fn
diff options
context:
space:
mode:
Diffstat (limited to 'tests/codegen-llvm/naked-fn')
-rw-r--r--tests/codegen-llvm/naked-fn/aligned.rs21
-rw-r--r--tests/codegen-llvm/naked-fn/generics.rs111
-rw-r--r--tests/codegen-llvm/naked-fn/instruction-set.rs53
-rw-r--r--tests/codegen-llvm/naked-fn/min-function-alignment.rs47
-rw-r--r--tests/codegen-llvm/naked-fn/naked-functions.rs165
5 files changed, 397 insertions, 0 deletions
diff --git a/tests/codegen-llvm/naked-fn/aligned.rs b/tests/codegen-llvm/naked-fn/aligned.rs
new file mode 100644
index 00000000000..d7281c4219a
--- /dev/null
+++ b/tests/codegen-llvm/naked-fn/aligned.rs
@@ -0,0 +1,21 @@
+//@ compile-flags: -C no-prepopulate-passes -Copt-level=0
+//@ needs-asm-support
+//@ ignore-arm no "ret" mnemonic
+//@ ignore-wasm32 aligning functions is not currently supported on wasm (#143368)
+
+#![crate_type = "lib"]
+// FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity
+#![feature(rustc_attrs)]
+#![feature(fn_align)]
+
+use std::arch::naked_asm;
+
+// CHECK: .balign 16
+// CHECK-LABEL: naked_empty:
+#[rustc_align(16)]
+#[no_mangle]
+#[unsafe(naked)]
+pub extern "C" fn naked_empty() {
+    // CHECK: ret
+    naked_asm!("ret")
+}
diff --git a/tests/codegen-llvm/naked-fn/generics.rs b/tests/codegen-llvm/naked-fn/generics.rs
new file mode 100644
index 00000000000..865be00d91e
--- /dev/null
+++ b/tests/codegen-llvm/naked-fn/generics.rs
@@ -0,0 +1,111 @@
+//@ compile-flags: -Copt-level=3
+//@ only-x86_64
+
+#![crate_type = "lib"]
+
+use std::arch::naked_asm;
+
+#[no_mangle]
+fn test(x: u64) {
+    // just making sure these symbols get used
+    using_const_generics::<1>(x);
+    using_const_generics::<2>(x);
+
+    generic_function::<i64>(x as i64);
+
+    let foo = Foo(x);
+
+    foo.method();
+    foo.trait_method();
+}
+
+// CHECK: .balign 4
+// CHECK: add rax, 2
+// CHECK: add rax, 42
+
+// CHECK: .balign 4
+// CHECK: add rax, 1
+// CHECK: add rax, 42
+
+#[unsafe(naked)]
+pub extern "C" fn using_const_generics<const N: u64>(x: u64) -> u64 {
+    const M: u64 = 42;
+
+    naked_asm!(
+        "xor rax, rax",
+        "add rax, rdi",
+        "add rax, {}",
+        "add rax, {}",
+        "ret",
+        const N,
+        const M,
+    )
+}
+
+trait Invert {
+    fn invert(self) -> Self;
+}
+
+impl Invert for i64 {
+    fn invert(self) -> Self {
+        -1 * self
+    }
+}
+
+// CHECK: .balign 4
+// CHECK-LABEL: generic_function:
+// CHECK: call
+// CHECK: ret
+
+#[unsafe(naked)]
+#[no_mangle]
+pub extern "C" fn generic_function<T: Invert>(x: i64) -> i64 {
+    naked_asm!(
+        "call {}",
+        "ret",
+        sym <T as Invert>::invert,
+    )
+}
+
+#[derive(Copy, Clone)]
+#[repr(transparent)]
+struct Foo(u64);
+
+// CHECK: .balign 4
+// CHECK-LABEL: method:
+// CHECK: mov rax, rdi
+
+impl Foo {
+    #[unsafe(naked)]
+    #[no_mangle]
+    extern "C" fn method(self) -> u64 {
+        naked_asm!("mov rax, rdi", "ret")
+    }
+}
+
+// CHECK: .balign 4
+// CHECK-LABEL: trait_method:
+// CHECK: mov rax, rdi
+
+trait Bar {
+    extern "C" fn trait_method(self) -> u64;
+}
+
+impl Bar for Foo {
+    #[unsafe(naked)]
+    #[no_mangle]
+    extern "C" fn trait_method(self) -> u64 {
+        naked_asm!("mov rax, rdi", "ret")
+    }
+}
+
+// CHECK: .balign 4
+// CHECK-LABEL: naked_with_args_and_return:
+// CHECK: lea rax, [rdi + rsi]
+
+// this previously ICE'd, see https://github.com/rust-lang/rust/issues/124375
+#[unsafe(naked)]
+#[no_mangle]
+pub unsafe extern "C" fn naked_with_args_and_return(a: isize, b: isize) -> isize {
+    naked_asm!("lea rax, [rdi + rsi]", "ret");
+}
diff --git a/tests/codegen-llvm/naked-fn/instruction-set.rs b/tests/codegen-llvm/naked-fn/instruction-set.rs
new file mode 100644
index 00000000000..67560c5aba7
--- /dev/null
+++ b/tests/codegen-llvm/naked-fn/instruction-set.rs
@@ -0,0 +1,53 @@
+//@ add-core-stubs
+//@ revisions: arm-mode thumb-mode
+//@ [arm-mode] compile-flags: --target armv5te-none-eabi
+//@ [thumb-mode] compile-flags: --target thumbv5te-none-eabi
+//@ [arm-mode] needs-llvm-components: arm
+//@ [thumb-mode] needs-llvm-components: arm
+
+#![crate_type = "lib"]
+#![feature(no_core, lang_items, rustc_attrs)]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+// arm-mode: .arm
+// thumb-mode: .thumb
+// CHECK-LABEL: test_unspecified:
+// CHECK: bx lr
+// CHECK: .popsection
+// arm-mode: .arm
+// thumb-mode: .thumb
+#[no_mangle]
+#[unsafe(naked)]
+extern "C" fn test_unspecified() {
+    naked_asm!("bx lr");
+}
+
+// CHECK: .thumb
+// CHECK: .thumb_func
+// CHECK-LABEL: test_thumb:
+// CHECK: bx lr
+// CHECK: .popsection
+// arm-mode: .arm
+// thumb-mode: .thumb
+#[no_mangle]
+#[unsafe(naked)]
+#[instruction_set(arm::t32)]
+extern "C" fn test_thumb() {
+    naked_asm!("bx lr");
+}
+
+// CHECK: .arm
+// CHECK-LABEL: test_arm:
+// CHECK: bx lr
+// CHECK: .popsection
+// arm-mode: .arm
+// thumb-mode: .thumb
+#[no_mangle]
+#[unsafe(naked)]
+#[instruction_set(arm::a32)]
+extern "C" fn test_arm() {
+    naked_asm!("bx lr");
+}
diff --git a/tests/codegen-llvm/naked-fn/min-function-alignment.rs b/tests/codegen-llvm/naked-fn/min-function-alignment.rs
new file mode 100644
index 00000000000..406e9334fa5
--- /dev/null
+++ b/tests/codegen-llvm/naked-fn/min-function-alignment.rs
@@ -0,0 +1,47 @@
+//@ compile-flags: -C no-prepopulate-passes -Copt-level=0 -Zmin-function-alignment=16
+//@ needs-asm-support
+//@ ignore-arm no "ret" mnemonic
+//@ ignore-wasm32 aligning functions is not currently supported on wasm (#143368)
+
+// FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity
+#![feature(rustc_attrs)]
+#![feature(fn_align)]
+#![crate_type = "lib"]
+
+// functions without explicit alignment use the global minimum
+//
+// CHECK: .balign 16
+#[no_mangle]
+#[unsafe(naked)]
+pub extern "C" fn naked_no_explicit_align() {
+    core::arch::naked_asm!("ret")
+}
+
+// CHECK: .balign 16
+#[no_mangle]
+#[rustc_align(8)]
+#[unsafe(naked)]
+pub extern "C" fn naked_lower_align() {
+    core::arch::naked_asm!("ret")
+}
+
+// CHECK: .balign 32
+#[no_mangle]
+#[rustc_align(32)]
+#[unsafe(naked)]
+pub extern "C" fn naked_higher_align() {
+    core::arch::naked_asm!("ret")
+}
+
+// cold functions follow the same rules as other functions
+//
+// in GCC, the `-falign-functions` does not apply to cold functions, but
+// `-Zmin-function-alignment` applies to all functions.
+//
+// CHECK: .balign 16
+#[no_mangle]
+#[cold]
+#[unsafe(naked)]
+pub extern "C" fn no_explicit_align_cold() {
+    core::arch::naked_asm!("ret")
+}
diff --git a/tests/codegen-llvm/naked-fn/naked-functions.rs b/tests/codegen-llvm/naked-fn/naked-functions.rs
new file mode 100644
index 00000000000..344af6eb42f
--- /dev/null
+++ b/tests/codegen-llvm/naked-fn/naked-functions.rs
@@ -0,0 +1,165 @@
+//@ add-core-stubs
+//@ revisions: linux win_x86 win_i686 macos thumb
+//
+//@[linux] compile-flags: --target x86_64-unknown-linux-gnu
+//@[linux] needs-llvm-components: x86
+//@[win_x86] compile-flags: --target x86_64-pc-windows-gnu
+//@[win_x86] needs-llvm-components: x86
+//@[win_i686] compile-flags: --target i686-pc-windows-gnu
+//@[win_i686] needs-llvm-components: x86
+//@[macos] compile-flags: --target aarch64-apple-darwin
+//@[macos] needs-llvm-components: arm
+//@[thumb] compile-flags: --target thumbv7em-none-eabi
+//@[thumb] needs-llvm-components: arm
+
+#![crate_type = "lib"]
+#![feature(no_core, lang_items, rustc_attrs)]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+// linux,win: .intel_syntax
+//
+// linux:    .pushsection .text.naked_empty,\22ax\22, @progbits
+// macos:    .pushsection __TEXT,__text,regular,pure_instructions
+// win_x86:  .pushsection .text.naked_empty,\22xr\22
+// win_i686: .pushsection .text._naked_empty,\22xr\22
+// thumb:    .pushsection .text.naked_empty,\22ax\22, %progbits
+//
+// CHECK: .balign 4
+//
+// linux,win,thumb: .globl naked_empty
+// macos: .globl _naked_empty
+//
+// CHECK-NOT: .private_extern
+// CHECK-NOT: .hidden
+//
+// linux: .type naked_empty, @function
+//
+// win_x86:  .def naked_empty
+// win_i686: .def _naked_empty
+//
+// win_x86,win_i686: .scl 2
+// win_x86,win_i686: .type 32
+// win_x86,win_i686: .endef
+//
+// thumb: .type naked_empty, %function
+// thumb: .thumb
+// thumb: .thumb_func
+//
+// CHECK-LABEL: naked_empty:
+//
+// linux,macos,win: ret
+// thumb: bx lr
+//
+// CHECK: .popsection
+//
+// thumb: .thumb
+//
+// linux,win: .att_syntax
+
+#[no_mangle]
+#[unsafe(naked)]
+pub extern "C" fn naked_empty() {
+    #[cfg(not(all(target_arch = "arm", target_feature = "thumb-mode")))]
+    naked_asm!("ret");
+
+    #[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))]
+    naked_asm!("bx lr");
+}
+
+// linux,win: .intel_syntax
+//
+// linux:    .pushsection .text.naked_with_args_and_return,\22ax\22, @progbits
+// macos:    .pushsection __TEXT,__text,regular,pure_instructions
+// win_x86:  .pushsection .text.naked_with_args_and_return,\22xr\22
+// win_i686: .pushsection .text._naked_with_args_and_return,\22xr\22
+// thumb:    .pushsection .text.naked_with_args_and_return,\22ax\22, %progbits
+//
+// CHECK: .balign 4
+//
+// linux,win,thumb: .globl naked_with_args_and_return
+// macos: .globl _naked_with_args_and_return
+//
+// CHECK-NOT: .private_extern
+// CHECK-NOT: .hidden
+//
+// linux: .type naked_with_args_and_return, @function
+//
+// win_x86:  .def naked_with_args_and_return
+// win_i686: .def _naked_with_args_and_return
+//
+// win_x86,win_i686: .scl 2
+// win_x86,win_i686: .type 32
+// win_x86,win_i686: .endef
+//
+// thumb: .type naked_with_args_and_return, %function
+// thumb: .thumb
+// thumb: .thumb_func
+//
+// CHECK-LABEL: naked_with_args_and_return:
+//
+// linux, win_x86,win_i686: lea rax, [rdi + rsi]
+// macos: add x0, x0, x1
+// thumb: adds r0, r0, r1
+//
+// linux,macos,win: ret
+// thumb: bx lr
+//
+// CHECK: .popsection
+//
+// thumb: .thumb
+//
+// linux,win: .att_syntax
+
+#[no_mangle]
+#[unsafe(naked)]
+pub extern "C" fn naked_with_args_and_return(a: isize, b: isize) -> isize {
+    #[cfg(any(target_os = "windows", target_os = "linux"))]
+    {
+        naked_asm!("lea rax, [rdi + rsi]", "ret")
+    }
+
+    #[cfg(target_os = "macos")]
+    {
+        naked_asm!("add x0, x0, x1", "ret")
+    }
+
+    #[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))]
+    {
+        naked_asm!("adds r0, r0, r1", "bx lr")
+    }
+}
+
+// linux:            .pushsection .text.some_different_name,\22ax\22, @progbits
+// macos:            .pushsection .text.some_different_name,regular,pure_instructions
+// win_x86,win_i686: .pushsection .text.some_different_name,\22xr\22
+// thumb:            .pushsection .text.some_different_name,\22ax\22, %progbits
+// CHECK-LABEL: test_link_section:
+#[no_mangle]
+#[unsafe(naked)]
+#[link_section = ".text.some_different_name"]
+pub extern "C" fn test_link_section() {
+    #[cfg(not(all(target_arch = "arm", target_feature = "thumb-mode")))]
+    naked_asm!("ret");
+
+    #[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))]
+    naked_asm!("bx lr");
+}
+
+// win_x86:  .def fastcall_cc
+// win_i686: .def @fastcall_cc@4
+//
+// win_x86,win_i686: .scl 2
+// win_x86,win_i686: .type 32
+// win_x86,win_i686: .endef
+//
+// win_x86-LABEL: fastcall_cc:
+// win_i686-LABEL: @fastcall_cc@4:
+#[cfg(target_os = "windows")]
+#[no_mangle]
+#[unsafe(naked)]
+pub extern "fastcall" fn fastcall_cc(x: i32) -> i32 {
+    naked_asm!("ret");
+}