diff options
Diffstat (limited to 'tests/codegen-llvm/naked-fn')
| -rw-r--r-- | tests/codegen-llvm/naked-fn/aligned.rs | 21 | ||||
| -rw-r--r-- | tests/codegen-llvm/naked-fn/generics.rs | 111 | ||||
| -rw-r--r-- | tests/codegen-llvm/naked-fn/instruction-set.rs | 53 | ||||
| -rw-r--r-- | tests/codegen-llvm/naked-fn/min-function-alignment.rs | 47 | ||||
| -rw-r--r-- | tests/codegen-llvm/naked-fn/naked-functions.rs | 165 |
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"); +} |
