]> git.proxmox.com Git - rustc.git/blame - vendor/compiler_builtins/src/macros.rs
New upstream version 1.63.0+dfsg1
[rustc.git] / vendor / compiler_builtins / src / macros.rs
CommitLineData
041b39d2
XL
1//! Macros shared throughout the compiler-builtins implementation
2
17df50a5
XL
3/// Changes the visibility to `pub` if feature "public-test-deps" is set
4#[cfg(not(feature = "public-test-deps"))]
5macro_rules! public_test_dep {
6 ($(#[$($meta:meta)*])* pub(crate) $ident:ident $($tokens:tt)*) => {
7 $(#[$($meta)*])* pub(crate) $ident $($tokens)*
8 };
9}
10
11/// Changes the visibility to `pub` if feature "public-test-deps" is set
12#[cfg(feature = "public-test-deps")]
13macro_rules! public_test_dep {
14 {$(#[$($meta:meta)*])* pub(crate) $ident:ident $($tokens:tt)*} => {
15 $(#[$($meta)*])* pub $ident $($tokens)*
16 };
17}
18
041b39d2
XL
19/// The "main macro" used for defining intrinsics.
20///
21/// The compiler-builtins library is super platform-specific with tons of crazy
22/// little tweaks for various platforms. As a result it *could* involve a lot of
23/// #[cfg] and macro soup, but the intention is that this macro alleviates a lot
24/// of that complexity. Ideally this macro has all the weird ABI things
25/// platforms need and elsewhere in this library it just looks like normal Rust
26/// code.
27///
28/// This macro is structured to be invoked with a bunch of functions that looks
29/// like:
30///
31/// intrinsics! {
32/// pub extern "C" fn foo(a: i32) -> u32 {
33/// // ...
34/// }
35///
36/// #[nonstandard_attribute]
37/// pub extern "C" fn bar(a: i32) -> u32 {
38/// // ...
39/// }
40/// }
41///
42/// Each function is defined in a manner that looks like a normal Rust function.
43/// The macro then accepts a few nonstandard attributes that can decorate
44/// various functions. Each of the attributes is documented below with what it
45/// can do, and each of them slightly tweaks how further expansion happens.
46///
47/// A quick overview of attributes supported right now are:
48///
48663c56
XL
49/// * `maybe_use_optimized_c_shim` - indicates that the Rust implementation is
50/// ignored if an optimized C version was compiled.
041b39d2
XL
51/// * `aapcs_on_arm` - forces the ABI of the function to be `"aapcs"` on ARM and
52/// the specified ABI everywhere else.
53/// * `unadjusted_on_win64` - like `aapcs_on_arm` this switches to the
54/// `"unadjusted"` abi on Win64 and the specified abi elsewhere.
55/// * `win64_128bit_abi_hack` - this attribute is used for 128-bit integer
56/// intrinsics where the ABI is slightly tweaked on Windows platforms, but
57/// it's a normal ABI elsewhere for returning a 128 bit integer.
58/// * `arm_aeabi_alias` - handles the "aliasing" of various intrinsics on ARM
59/// their otherwise typical names to other prefixed ones.
60///
61macro_rules! intrinsics {
62 () => ();
63
923072b8
FG
64 // Support cfg_attr:
65 (
66 #[cfg_attr($e:meta, $($attr:tt)*)]
67 $(#[$($attrs:tt)*])*
68 pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? {
69 $($body:tt)*
70 }
71 $($rest:tt)*
72 ) => (
73 #[cfg($e)]
74 intrinsics! {
75 #[$($attr)*]
76 $(#[$($attrs)*])*
77 pub extern $abi fn $name($($argname: $ty),*) $(-> $ret)? {
78 $($body)*
79 }
80 }
81
82 #[cfg(not($e))]
83 intrinsics! {
84 $(#[$($attrs)*])*
85 pub extern $abi fn $name($($argname: $ty),*) $(-> $ret)? {
86 $($body)*
87 }
88 }
89
90 intrinsics!($($rest)*);
91 );
92
041b39d2
XL
93 // Right now there's a bunch of architecture-optimized intrinsics in the
94 // stock compiler-rt implementation. Not all of these have been ported over
95 // to Rust yet so when the `c` feature of this crate is enabled we fall back
96 // to the architecture-specific versions which should be more optimized. The
97 // purpose of this macro is to easily allow specifying this.
98 //
48663c56
XL
99 // The `#[maybe_use_optimized_c_shim]` attribute indicates that this
100 // intrinsic may have an optimized C version. In these situations the build
101 // script, if the C code is enabled and compiled, will emit a cfg directive
102 // to get passed to rustc for our compilation. If that cfg is set we skip
103 // the Rust implementation, but if the attribute is not enabled then we
104 // compile in the Rust implementation.
041b39d2 105 (
48663c56 106 #[maybe_use_optimized_c_shim]
041b39d2 107 $(#[$($attr:tt)*])*
5099ac24 108 pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? {
041b39d2
XL
109 $($body:tt)*
110 }
111
112 $($rest:tt)*
113 ) => (
48663c56 114 #[cfg($name = "optimized-c")]
5099ac24 115 pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
041b39d2 116 extern $abi {
5099ac24 117 fn $name($($argname: $ty),*) $(-> $ret)?;
041b39d2
XL
118 }
119 unsafe {
120 $name($($argname),*)
121 }
122 }
123
48663c56 124 #[cfg(not($name = "optimized-c"))]
041b39d2
XL
125 intrinsics! {
126 $(#[$($attr)*])*
5099ac24 127 pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
041b39d2
XL
128 $($body)*
129 }
130 }
131
132 intrinsics!($($rest)*);
133 );
134
135 // We recognize the `#[aapcs_on_arm]` attribute here and generate the
136 // same intrinsic but force it to have the `"aapcs"` calling convention on
137 // ARM and `"C"` elsewhere.
138 (
139 #[aapcs_on_arm]
140 $(#[$($attr:tt)*])*
5099ac24 141 pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? {
041b39d2
XL
142 $($body:tt)*
143 }
144
145 $($rest:tt)*
146 ) => (
147 #[cfg(target_arch = "arm")]
148 intrinsics! {
149 $(#[$($attr)*])*
5099ac24 150 pub extern "aapcs" fn $name( $($argname: $ty),* ) $(-> $ret)? {
041b39d2
XL
151 $($body)*
152 }
153 }
154
155 #[cfg(not(target_arch = "arm"))]
156 intrinsics! {
157 $(#[$($attr)*])*
5099ac24 158 pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
041b39d2
XL
159 $($body)*
160 }
161 }
162
163 intrinsics!($($rest)*);
164 );
165
166 // Like aapcs above we recognize an attribute for the "unadjusted" abi on
167 // win64 for some methods.
168 (
169 #[unadjusted_on_win64]
170 $(#[$($attr:tt)*])*
5099ac24 171 pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? {
041b39d2
XL
172 $($body:tt)*
173 }
174
175 $($rest:tt)*
176 ) => (
177 #[cfg(all(windows, target_pointer_width = "64"))]
178 intrinsics! {
179 $(#[$($attr)*])*
5099ac24 180 pub extern "unadjusted" fn $name( $($argname: $ty),* ) $(-> $ret)? {
041b39d2
XL
181 $($body)*
182 }
183 }
184
185 #[cfg(not(all(windows, target_pointer_width = "64")))]
186 intrinsics! {
187 $(#[$($attr)*])*
5099ac24 188 pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
041b39d2
XL
189 $($body)*
190 }
191 }
192
193 intrinsics!($($rest)*);
194 );
195
196 // Some intrinsics on win64 which return a 128-bit integer have an.. unusual
197 // calling convention. That's managed here with this "abi hack" which alters
198 // the generated symbol's ABI.
199 //
200 // This will still define a function in this crate with the given name and
201 // signature, but the actual symbol for the intrinsic may have a slightly
202 // different ABI on win64.
203 (
204 #[win64_128bit_abi_hack]
205 $(#[$($attr:tt)*])*
5099ac24 206 pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? {
041b39d2
XL
207 $($body:tt)*
208 }
209
210 $($rest:tt)*
211 ) => (
dfeec247 212 #[cfg(all(windows, target_arch = "x86_64"))]
041b39d2 213 $(#[$($attr)*])*
5099ac24 214 pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
041b39d2
XL
215 $($body)*
216 }
217
dfeec247 218 #[cfg(all(windows, target_arch = "x86_64"))]
041b39d2 219 pub mod $name {
ba9703b0
XL
220 #[cfg_attr(not(feature = "mangled-names"), no_mangle)]
221 pub extern $abi fn $name( $($argname: $ty),* )
222 -> ::macros::win64_128bit_abi_hack::U64x2
223 {
5099ac24 224 let e: $($ret)? = super::$name($($argname),*);
ba9703b0 225 ::macros::win64_128bit_abi_hack::U64x2::from(e)
041b39d2
XL
226 }
227 }
228
dfeec247 229 #[cfg(not(all(windows, target_arch = "x86_64")))]
041b39d2
XL
230 intrinsics! {
231 $(#[$($attr)*])*
5099ac24 232 pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
041b39d2
XL
233 $($body)*
234 }
235 }
236
237 intrinsics!($($rest)*);
238 );
239
240 // A bunch of intrinsics on ARM are aliased in the standard compiler-rt
241 // build under `__aeabi_*` aliases, and LLVM will call these instead of the
242 // original function. The aliasing here is used to generate these symbols in
243 // the object file.
244 (
245 #[arm_aeabi_alias = $alias:ident]
246 $(#[$($attr:tt)*])*
5099ac24 247 pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? {
041b39d2
XL
248 $($body:tt)*
249 }
250
251 $($rest:tt)*
252 ) => (
253 #[cfg(target_arch = "arm")]
5099ac24 254 pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
041b39d2
XL
255 $($body)*
256 }
257
258 #[cfg(target_arch = "arm")]
259 pub mod $name {
ba9703b0 260 #[cfg_attr(not(feature = "mangled-names"), no_mangle)]
5099ac24 261 pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
ba9703b0
XL
262 super::$name($($argname),*)
263 }
264 }
265
266 #[cfg(target_arch = "arm")]
267 pub mod $alias {
268 #[cfg_attr(not(feature = "mangled-names"), no_mangle)]
5099ac24 269 pub extern "aapcs" fn $alias( $($argname: $ty),* ) $(-> $ret)? {
ba9703b0 270 super::$name($($argname),*)
041b39d2
XL
271 }
272 }
273
274 #[cfg(not(target_arch = "arm"))]
275 intrinsics! {
276 $(#[$($attr)*])*
5099ac24
FG
277 pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
278 $($body)*
279 }
280 }
281
282 intrinsics!($($rest)*);
283 );
284
285 // C mem* functions are only generated when the "mem" feature is enabled.
286 (
287 #[mem_builtin]
288 $(#[$($attr:tt)*])*
289 pub unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? {
290 $($body:tt)*
291 }
292
293 $($rest:tt)*
294 ) => (
295 $(#[$($attr)*])*
296 pub unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
297 $($body)*
298 }
299
300 #[cfg(feature = "mem")]
301 pub mod $name {
302 $(#[$($attr)*])*
303 #[cfg_attr(not(feature = "mangled-names"), no_mangle)]
304 pub unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
305 super::$name($($argname),*)
306 }
307 }
308
309 intrinsics!($($rest)*);
310 );
311
312 // Naked functions are special: we can't generate wrappers for them since
313 // they use a custom calling convention.
314 (
315 #[naked]
316 $(#[$($attr:tt)*])*
317 pub unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? {
318 $($body:tt)*
319 }
320
321 $($rest:tt)*
322 ) => (
323 pub mod $name {
324 #[naked]
325 $(#[$($attr)*])*
326 #[cfg_attr(not(feature = "mangled-names"), no_mangle)]
327 pub unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
041b39d2
XL
328 $($body)*
329 }
330 }
331
332 intrinsics!($($rest)*);
333 );
334
923072b8
FG
335 // For division and modulo, AVR uses a custom calling convention¹ that does
336 // not match our definitions here. Ideally we would just use hand-written
337 // naked functions, but that's quite a lot of code to port² - so for the
338 // time being we are just ignoring the problematic functions, letting
339 // avr-gcc (which is required to compile to AVR anyway) link them from
340 // libgcc.
341 //
342 // ¹ https://gcc.gnu.org/wiki/avr-gcc (see "Exceptions to the Calling
343 // Convention")
344 // ² https://github.com/gcc-mirror/gcc/blob/31048012db98f5ec9c2ba537bfd850374bdd771f/libgcc/config/avr/lib1funcs.S
345 (
346 #[avr_skip]
347 $(#[$($attr:tt)*])*
348 pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? {
349 $($body:tt)*
350 }
351
352 $($rest:tt)*
353 ) => (
354 #[cfg(not(target_arch = "avr"))]
355 intrinsics! {
356 $(#[$($attr)*])*
357 pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
358 $($body)*
359 }
360 }
361
362 intrinsics!($($rest)*);
363 );
364
ba9703b0 365 // This is the final catch-all rule. At this point we generate an
041b39d2 366 // intrinsic with a conditional `#[no_mangle]` directive to avoid
ba9703b0
XL
367 // interfering with duplicate symbols and whatnot during testing.
368 //
369 // The implementation is placed in a separate module, to take advantage
370 // of the fact that rustc partitions functions into code generation
371 // units based on module they are defined in. As a result we will have
372 // a separate object file for each intrinsic. For further details see
373 // corresponding PR in rustc https://github.com/rust-lang/rust/pull/70846
041b39d2
XL
374 //
375 // After the intrinsic is defined we just continue with the rest of the
376 // input we were given.
377 (
378 $(#[$($attr:tt)*])*
5099ac24
FG
379 pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? {
380 $($body:tt)*
381 }
382
383 $($rest:tt)*
384 ) => (
385 $(#[$($attr)*])*
386 pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
387 $($body)*
388 }
389
390 pub mod $name {
391 $(#[$($attr)*])*
392 #[cfg_attr(not(feature = "mangled-names"), no_mangle)]
393 pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
394 super::$name($($argname),*)
395 }
396 }
397
398 intrinsics!($($rest)*);
399 );
400
401 // Same as the above for unsafe functions.
402 (
403 $(#[$($attr:tt)*])*
404 pub unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? {
041b39d2
XL
405 $($body:tt)*
406 }
407
408 $($rest:tt)*
409 ) => (
410 $(#[$($attr)*])*
5099ac24 411 pub unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
041b39d2
XL
412 $($body)*
413 }
414
ba9703b0
XL
415 pub mod $name {
416 $(#[$($attr)*])*
417 #[cfg_attr(not(feature = "mangled-names"), no_mangle)]
5099ac24 418 pub unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
ba9703b0
XL
419 super::$name($($argname),*)
420 }
421 }
422
041b39d2
XL
423 intrinsics!($($rest)*);
424 );
425}
426
427// Hack for LLVM expectations for ABI on windows. This is used by the
428// `#[win64_128bit_abi_hack]` attribute recognized above
48663c56 429#[cfg(all(windows, target_pointer_width = "64"))]
041b39d2
XL
430pub mod win64_128bit_abi_hack {
431 #[repr(simd)]
432 pub struct U64x2(u64, u64);
433
434 impl From<i128> for U64x2 {
435 fn from(i: i128) -> U64x2 {
5869c6ff 436 use int::DInt;
041b39d2 437 let j = i as u128;
5869c6ff 438 U64x2(j.lo(), j.hi())
041b39d2
XL
439 }
440 }
441
442 impl From<u128> for U64x2 {
443 fn from(i: u128) -> U64x2 {
5869c6ff
XL
444 use int::DInt;
445 U64x2(i.lo(), i.hi())
041b39d2
XL
446 }
447 }
448}