naked_function/
lib.rs

1//! This crate provides the [`naked`] proc macro.
2#![no_std]
3
4#[doc(inline)]
5pub use naked_function_macro::naked;
6
7// Helper macros to deal with platform-specific differences in assembly code
8// between ELF, Mach-O and COFF file formats.
9//
10// We can't do this within the proc macro itself because Rust don't expose the
11// target cfgs to proc macros.
12
13cfg_if::cfg_if! {
14    if #[cfg(all(target_arch = "arm", is_thumb))] {
15        #[doc(hidden)]
16        #[macro_export]
17        macro_rules! __asm_arch_prefix {
18            () => { ".thumb\n.thumb_func" };
19            (arm::a32) => { ".arm" };
20            (arm::t32) => { ".thumb\n.thumb_func" };
21            ($isa:path) => { compile_error!("invalid instruction set") };
22        }
23        #[doc(hidden)]
24        #[macro_export]
25        macro_rules! __asm_arch_suffix {
26            () => { ".thumb" };
27        }
28    } else if #[cfg(all(target_arch = "arm", not(is_thumb)))] {
29        #[doc(hidden)]
30        #[macro_export]
31        macro_rules! __asm_arch_prefix {
32            () => { ".arm" };
33            (arm::a32) => { ".arm" };
34            (arm::t32) => { ".thumb\n.thumb_func" };
35            ($isa:path) => { compile_error!("invalid instruction set") };
36        }
37        #[doc(hidden)]
38        #[macro_export]
39        macro_rules! __asm_arch_suffix {
40            () => { ".arm" };
41        }
42    } else {
43        #[doc(hidden)]
44        #[macro_export]
45        macro_rules! __asm_arch_prefix {
46            () => { "" };
47            ($isa:path) => { compile_error!("invalid instruction set") };
48        }
49        #[doc(hidden)]
50        #[macro_export]
51        macro_rules! __asm_arch_suffix {
52            () => { "" };
53        }
54    }
55}
56cfg_if::cfg_if! {
57    if #[cfg(any(
58            target_vendor = "apple",
59            all(windows, target_arch = "x86"),
60        ))] {
61        #[doc(hidden)]
62        #[macro_export]
63        macro_rules! __asm_mangle {
64            ($symbol:expr) => { concat!("_", $symbol) };
65        }
66    } else {
67        #[doc(hidden)]
68        #[macro_export]
69        macro_rules! __asm_mangle {
70            ($symbol:expr) => { $symbol };
71        }
72    }
73}
74cfg_if::cfg_if! {
75    if #[cfg(windows)] {
76        // COFF
77        #[doc(hidden)]
78        #[macro_export]
79        macro_rules! __asm_function_begin {
80            ($symbol:expr, $section:expr, ($($instruction_set:tt)*)) => {
81                concat!(
82                    ".pushsection ", $section, ",\"xr\"\n",
83                    ".balign 4\n",
84                    ".globl ", $crate::__asm_mangle!($symbol), "\n",
85                    ".def ", $crate::__asm_mangle!($symbol), "\n",
86                    ".scl 2\n",
87                    ".type 32\n",
88                    ".endef ", $crate::__asm_mangle!($symbol), "\n",
89                    $crate::__asm_arch_prefix!($($instruction_set)*), "\n",
90                    $crate::__asm_mangle!($symbol), ":\n",
91                )
92            };
93        }
94        #[doc(hidden)]
95        #[macro_export]
96        macro_rules! __asm_function_end {
97            ($symbol:expr) => {
98                concat!(
99                    ".popsection\n",
100                    $crate::__asm_arch_suffix!(), "\n",
101                )
102            };
103        }
104        #[doc(hidden)]
105        #[macro_export]
106        macro_rules! __asm_default_section {
107            ($symbol:expr) => { concat!(".text.", $symbol) };
108        }
109    } else if #[cfg(target_vendor = "apple")] {
110        // Mach-O
111        #[doc(hidden)]
112        #[macro_export]
113        macro_rules! __asm_function_begin {
114            ($symbol:expr, $section:expr, ($($instruction_set:tt)*)) => {
115                concat!(
116                    ".pushsection ", $section, ",regular,pure_instructions\n",
117                    ".balign 4\n",
118                    ".globl ", $crate::__asm_mangle!($symbol), "\n",
119                    ".private_extern ", $crate::__asm_mangle!($symbol), "\n",
120                    $crate::__asm_arch_prefix!($($instruction_set)*), "\n",
121                    $crate::__asm_mangle!($symbol), ":\n",
122                )
123            };
124        }
125        #[doc(hidden)]
126        #[macro_export]
127        macro_rules! __asm_function_end {
128            ($symbol:expr) => {
129                concat!(
130                    ".popsection\n",
131                    $crate::__asm_arch_suffix!(), "\n",
132                )
133            };
134        }
135        #[doc(hidden)]
136        #[macro_export]
137        macro_rules! __asm_default_section {
138            ($symbol:expr) => { "__TEXT,__text" };
139        }
140    } else {
141        // Everything else uses ELF. ARM uses % instead of @ for some
142        // assembler directives.
143        #[cfg(not(target_arch = "arm"))]
144        #[doc(hidden)]
145        #[macro_export]
146        macro_rules! __asm_type {
147            ($ty:literal) => { concat!("@", $ty) }
148        }
149        #[cfg(target_arch = "arm")]
150        #[doc(hidden)]
151        #[macro_export]
152        macro_rules! __asm_type {
153            ($ty:literal) => { concat!("%", $ty) }
154        }
155        #[doc(hidden)]
156        #[macro_export]
157        macro_rules! __asm_function_begin {
158            ($symbol:expr, $section:expr, ($($instruction_set:tt)*)) => {
159                concat!(
160                    ".pushsection ", $section, ",\"ax\", ", $crate::__asm_type!("progbits"), "\n",
161                    ".balign 4\n",
162                    ".globl ", $crate::__asm_mangle!($symbol), "\n",
163                    ".hidden ", $crate::__asm_mangle!($symbol), "\n",
164                    ".type ", $crate::__asm_mangle!($symbol), ", ", $crate::__asm_type!("function"), "\n",
165                    $crate::__asm_arch_prefix!($($instruction_set)*), "\n",
166                    $crate::__asm_mangle!($symbol), ":\n",
167                )
168            };
169        }
170        #[doc(hidden)]
171        #[macro_export]
172        macro_rules! __asm_function_end {
173            ($symbol:expr) => {
174                concat!(
175                    ".size ", $crate::__asm_mangle!($symbol), ", . - ", $crate::__asm_mangle!($symbol), "\n",
176                    ".popsection\n",
177                    $crate::__asm_arch_suffix!(), "\n",
178                )
179            };
180        }
181        #[doc(hidden)]
182        #[macro_export]
183        macro_rules! __asm_default_section {
184            ($symbol:expr) => { concat!(".text.", $symbol) };
185        }
186    }
187}