]> git.proxmox.com Git - rustc.git/blame - vendor/compiler_builtins/src/macros.rs
New upstream version 1.71.1+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///
49aad941
FG
28/// When the weak-intrinsics feature is enabled, all intrinsics functions are
29/// marked with #[linkage = "weak"] so that they can be replaced by another
30/// implementation at link time. This is particularly useful for mixed Rust/C++
31/// binaries that want to use the C++ intrinsics, otherwise linking against the
32/// Rust stdlib will replace those from the compiler-rt library.
33///
041b39d2
XL
34/// This macro is structured to be invoked with a bunch of functions that looks
35/// like:
36///
37/// intrinsics! {
38/// pub extern "C" fn foo(a: i32) -> u32 {
39/// // ...
40/// }
41///
42/// #[nonstandard_attribute]
43/// pub extern "C" fn bar(a: i32) -> u32 {
44/// // ...
45/// }
46/// }
47///
48/// Each function is defined in a manner that looks like a normal Rust function.
49/// The macro then accepts a few nonstandard attributes that can decorate
50/// various functions. Each of the attributes is documented below with what it
51/// can do, and each of them slightly tweaks how further expansion happens.
52///
53/// A quick overview of attributes supported right now are:
54///
49aad941
FG
55/// * `weak` - indicates that the function should always be given weak linkage.
56/// This attribute must come before other attributes, as the other attributes
57/// will generate the final output function and need to have `weak` modify
58/// them.
48663c56
XL
59/// * `maybe_use_optimized_c_shim` - indicates that the Rust implementation is
60/// ignored if an optimized C version was compiled.
041b39d2
XL
61/// * `aapcs_on_arm` - forces the ABI of the function to be `"aapcs"` on ARM and
62/// the specified ABI everywhere else.
63/// * `unadjusted_on_win64` - like `aapcs_on_arm` this switches to the
64/// `"unadjusted"` abi on Win64 and the specified abi elsewhere.
65/// * `win64_128bit_abi_hack` - this attribute is used for 128-bit integer
66/// intrinsics where the ABI is slightly tweaked on Windows platforms, but
67/// it's a normal ABI elsewhere for returning a 128 bit integer.
68/// * `arm_aeabi_alias` - handles the "aliasing" of various intrinsics on ARM
69/// their otherwise typical names to other prefixed ones.
041b39d2
XL
70macro_rules! intrinsics {
71 () => ();
72
923072b8
FG
73 // Support cfg_attr:
74 (
75 #[cfg_attr($e:meta, $($attr:tt)*)]
76 $(#[$($attrs:tt)*])*
77 pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? {
78 $($body:tt)*
79 }
80 $($rest:tt)*
81 ) => (
82 #[cfg($e)]
83 intrinsics! {
84 #[$($attr)*]
85 $(#[$($attrs)*])*
86 pub extern $abi fn $name($($argname: $ty),*) $(-> $ret)? {
87 $($body)*
88 }
89 }
90
91 #[cfg(not($e))]
92 intrinsics! {
93 $(#[$($attrs)*])*
94 pub extern $abi fn $name($($argname: $ty),*) $(-> $ret)? {
95 $($body)*
96 }
97 }
98
99 intrinsics!($($rest)*);
100 );
49aad941
FG
101 // Same as above but for unsafe.
102 (
103 #[cfg_attr($e:meta, $($attr:tt)*)]
104 $(#[$($attrs:tt)*])*
105 pub unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? {
106 $($body:tt)*
107 }
108 $($rest:tt)*
109 ) => (
110 #[cfg($e)]
111 intrinsics! {
112 #[$($attr)*]
113 $(#[$($attrs)*])*
114 pub unsafe extern $abi fn $name($($argname: $ty),*) $(-> $ret)? {
115 $($body)*
116 }
117 }
118
119 #[cfg(not($e))]
120 intrinsics! {
121 $(#[$($attrs)*])*
122 pub unsafe extern $abi fn $name($($argname: $ty),*) $(-> $ret)? {
123 $($body)*
124 }
125 }
126
127 intrinsics!($($rest)*);
128 );
129
130 // Explicit weak linkage gets dropped when weak-intrinsics is on since it
131 // will be added unconditionally to all intrinsics and would conflict
132 // otherwise.
133 (
134 #[weak]
135 $(#[$($attr:tt)*])*
136 pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? {
137 $($body:tt)*
138 }
139
140 $($rest:tt)*
141 ) => (
142 #[cfg(feature = "weak-intrinsics")]
143 intrinsics! {
144 $(#[$($attr)*])*
145 pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
146 $($body)*
147 }
148 }
149
150 #[cfg(not(feature = "weak-intrinsics"))]
151 intrinsics! {
152 $(#[$($attr)*])*
153 #[linkage = "weak"]
154 pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
155 $($body)*
156 }
157 }
158
159 intrinsics!($($rest)*);
160 );
161 // Same as above but for unsafe.
162 (
163 #[weak]
164 $(#[$($attr:tt)*])*
165 pub unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? {
166 $($body:tt)*
167 }
168
169 $($rest:tt)*
170 ) => (
171 #[cfg(feature = "weak-intrinsics")]
172 intrinsics! {
173 $(#[$($attr)*])*
174 pub unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
175 $($body)*
176 }
177 }
178
179 #[cfg(not(feature = "weak-intrinsics"))]
180 intrinsics! {
181 $(#[$($attr)*])*
182 #[linkage = "weak"]
183 pub unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
184 $($body)*
185 }
186 }
187
188 intrinsics!($($rest)*);
189 );
923072b8 190
041b39d2
XL
191 // Right now there's a bunch of architecture-optimized intrinsics in the
192 // stock compiler-rt implementation. Not all of these have been ported over
193 // to Rust yet so when the `c` feature of this crate is enabled we fall back
194 // to the architecture-specific versions which should be more optimized. The
195 // purpose of this macro is to easily allow specifying this.
196 //
48663c56
XL
197 // The `#[maybe_use_optimized_c_shim]` attribute indicates that this
198 // intrinsic may have an optimized C version. In these situations the build
199 // script, if the C code is enabled and compiled, will emit a cfg directive
200 // to get passed to rustc for our compilation. If that cfg is set we skip
201 // the Rust implementation, but if the attribute is not enabled then we
202 // compile in the Rust implementation.
041b39d2 203 (
48663c56 204 #[maybe_use_optimized_c_shim]
041b39d2 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 ) => (
48663c56 212 #[cfg($name = "optimized-c")]
49aad941 213 #[cfg_attr(feature = "weak-intrinsics", linkage = "weak")]
5099ac24 214 pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
041b39d2 215 extern $abi {
5099ac24 216 fn $name($($argname: $ty),*) $(-> $ret)?;
041b39d2
XL
217 }
218 unsafe {
219 $name($($argname),*)
220 }
221 }
222
48663c56 223 #[cfg(not($name = "optimized-c"))]
041b39d2
XL
224 intrinsics! {
225 $(#[$($attr)*])*
5099ac24 226 pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
041b39d2
XL
227 $($body)*
228 }
229 }
230
231 intrinsics!($($rest)*);
232 );
233
234 // We recognize the `#[aapcs_on_arm]` attribute here and generate the
235 // same intrinsic but force it to have the `"aapcs"` calling convention on
236 // ARM and `"C"` elsewhere.
237 (
238 #[aapcs_on_arm]
239 $(#[$($attr:tt)*])*
5099ac24 240 pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? {
041b39d2
XL
241 $($body:tt)*
242 }
243
244 $($rest:tt)*
245 ) => (
246 #[cfg(target_arch = "arm")]
247 intrinsics! {
248 $(#[$($attr)*])*
5099ac24 249 pub extern "aapcs" fn $name( $($argname: $ty),* ) $(-> $ret)? {
041b39d2
XL
250 $($body)*
251 }
252 }
253
254 #[cfg(not(target_arch = "arm"))]
255 intrinsics! {
256 $(#[$($attr)*])*
5099ac24 257 pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
041b39d2
XL
258 $($body)*
259 }
260 }
261
262 intrinsics!($($rest)*);
263 );
264
265 // Like aapcs above we recognize an attribute for the "unadjusted" abi on
266 // win64 for some methods.
267 (
268 #[unadjusted_on_win64]
269 $(#[$($attr:tt)*])*
5099ac24 270 pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? {
041b39d2
XL
271 $($body:tt)*
272 }
273
274 $($rest:tt)*
275 ) => (
f2b60f7d 276 #[cfg(all(any(windows, all(target_os = "uefi", target_arch = "x86_64")), target_pointer_width = "64"))]
041b39d2
XL
277 intrinsics! {
278 $(#[$($attr)*])*
5099ac24 279 pub extern "unadjusted" fn $name( $($argname: $ty),* ) $(-> $ret)? {
041b39d2
XL
280 $($body)*
281 }
282 }
283
f2b60f7d 284 #[cfg(not(all(any(windows, all(target_os = "uefi", target_arch = "x86_64")), target_pointer_width = "64")))]
041b39d2
XL
285 intrinsics! {
286 $(#[$($attr)*])*
5099ac24 287 pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
041b39d2
XL
288 $($body)*
289 }
290 }
291
292 intrinsics!($($rest)*);
293 );
294
295 // Some intrinsics on win64 which return a 128-bit integer have an.. unusual
296 // calling convention. That's managed here with this "abi hack" which alters
297 // the generated symbol's ABI.
298 //
299 // This will still define a function in this crate with the given name and
300 // signature, but the actual symbol for the intrinsic may have a slightly
301 // different ABI on win64.
302 (
303 #[win64_128bit_abi_hack]
304 $(#[$($attr:tt)*])*
5099ac24 305 pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? {
041b39d2
XL
306 $($body:tt)*
307 }
308
309 $($rest:tt)*
310 ) => (
f2b60f7d 311 #[cfg(all(any(windows, target_os = "uefi"), target_arch = "x86_64"))]
041b39d2 312 $(#[$($attr)*])*
49aad941 313 #[cfg_attr(feature = "weak-intrinsics", linkage = "weak")]
5099ac24 314 pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
041b39d2
XL
315 $($body)*
316 }
317
f2b60f7d 318 #[cfg(all(any(windows, target_os = "uefi"), target_arch = "x86_64"))]
041b39d2 319 pub mod $name {
ba9703b0 320 #[cfg_attr(not(feature = "mangled-names"), no_mangle)]
49aad941 321 #[cfg_attr(feature = "weak-intrinsics", linkage = "weak")]
ba9703b0
XL
322 pub extern $abi fn $name( $($argname: $ty),* )
323 -> ::macros::win64_128bit_abi_hack::U64x2
324 {
5099ac24 325 let e: $($ret)? = super::$name($($argname),*);
ba9703b0 326 ::macros::win64_128bit_abi_hack::U64x2::from(e)
041b39d2
XL
327 }
328 }
329
f2b60f7d 330 #[cfg(not(all(any(windows, target_os = "uefi"), target_arch = "x86_64")))]
041b39d2
XL
331 intrinsics! {
332 $(#[$($attr)*])*
5099ac24 333 pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
041b39d2
XL
334 $($body)*
335 }
336 }
337
338 intrinsics!($($rest)*);
339 );
340
341 // A bunch of intrinsics on ARM are aliased in the standard compiler-rt
342 // build under `__aeabi_*` aliases, and LLVM will call these instead of the
343 // original function. The aliasing here is used to generate these symbols in
344 // the object file.
345 (
346 #[arm_aeabi_alias = $alias:ident]
347 $(#[$($attr:tt)*])*
5099ac24 348 pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? {
041b39d2
XL
349 $($body:tt)*
350 }
351
352 $($rest:tt)*
353 ) => (
354 #[cfg(target_arch = "arm")]
5099ac24 355 pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
041b39d2
XL
356 $($body)*
357 }
358
359 #[cfg(target_arch = "arm")]
360 pub mod $name {
ba9703b0 361 #[cfg_attr(not(feature = "mangled-names"), no_mangle)]
49aad941 362 #[cfg_attr(feature = "weak-intrinsics", linkage = "weak")]
5099ac24 363 pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
ba9703b0
XL
364 super::$name($($argname),*)
365 }
366 }
367
368 #[cfg(target_arch = "arm")]
369 pub mod $alias {
370 #[cfg_attr(not(feature = "mangled-names"), no_mangle)]
49aad941 371 #[cfg_attr(any(all(not(windows), not(target_vendor="apple"), feature = "weak-intrinsics")), linkage = "weak")]
5099ac24 372 pub extern "aapcs" fn $alias( $($argname: $ty),* ) $(-> $ret)? {
ba9703b0 373 super::$name($($argname),*)
041b39d2
XL
374 }
375 }
376
377 #[cfg(not(target_arch = "arm"))]
378 intrinsics! {
379 $(#[$($attr)*])*
5099ac24
FG
380 pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
381 $($body)*
382 }
383 }
384
385 intrinsics!($($rest)*);
386 );
387
388 // C mem* functions are only generated when the "mem" feature is enabled.
389 (
390 #[mem_builtin]
391 $(#[$($attr:tt)*])*
392 pub unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? {
393 $($body:tt)*
394 }
395
396 $($rest:tt)*
397 ) => (
398 $(#[$($attr)*])*
399 pub unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
400 $($body)*
401 }
402
403 #[cfg(feature = "mem")]
404 pub mod $name {
405 $(#[$($attr)*])*
406 #[cfg_attr(not(feature = "mangled-names"), no_mangle)]
49aad941 407 #[cfg_attr(feature = "weak-intrinsics", linkage = "weak")]
5099ac24
FG
408 pub unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
409 super::$name($($argname),*)
410 }
411 }
412
413 intrinsics!($($rest)*);
414 );
415
416 // Naked functions are special: we can't generate wrappers for them since
417 // they use a custom calling convention.
418 (
419 #[naked]
420 $(#[$($attr:tt)*])*
421 pub unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? {
422 $($body:tt)*
423 }
424
425 $($rest:tt)*
426 ) => (
427 pub mod $name {
428 #[naked]
429 $(#[$($attr)*])*
430 #[cfg_attr(not(feature = "mangled-names"), no_mangle)]
49aad941 431 #[cfg_attr(feature = "weak-intrinsics", linkage = "weak")]
5099ac24 432 pub unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
041b39d2
XL
433 $($body)*
434 }
435 }
436
437 intrinsics!($($rest)*);
438 );
439
923072b8
FG
440 // For division and modulo, AVR uses a custom calling convention¹ that does
441 // not match our definitions here. Ideally we would just use hand-written
442 // naked functions, but that's quite a lot of code to port² - so for the
443 // time being we are just ignoring the problematic functions, letting
444 // avr-gcc (which is required to compile to AVR anyway) link them from
445 // libgcc.
446 //
447 // ¹ https://gcc.gnu.org/wiki/avr-gcc (see "Exceptions to the Calling
448 // Convention")
449 // ² https://github.com/gcc-mirror/gcc/blob/31048012db98f5ec9c2ba537bfd850374bdd771f/libgcc/config/avr/lib1funcs.S
450 (
451 #[avr_skip]
452 $(#[$($attr:tt)*])*
453 pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? {
454 $($body:tt)*
455 }
456
457 $($rest:tt)*
458 ) => (
459 #[cfg(not(target_arch = "avr"))]
460 intrinsics! {
461 $(#[$($attr)*])*
462 pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
463 $($body)*
464 }
465 }
466
467 intrinsics!($($rest)*);
468 );
469
ba9703b0 470 // This is the final catch-all rule. At this point we generate an
041b39d2 471 // intrinsic with a conditional `#[no_mangle]` directive to avoid
ba9703b0
XL
472 // interfering with duplicate symbols and whatnot during testing.
473 //
474 // The implementation is placed in a separate module, to take advantage
475 // of the fact that rustc partitions functions into code generation
476 // units based on module they are defined in. As a result we will have
477 // a separate object file for each intrinsic. For further details see
478 // corresponding PR in rustc https://github.com/rust-lang/rust/pull/70846
041b39d2
XL
479 //
480 // After the intrinsic is defined we just continue with the rest of the
481 // input we were given.
482 (
483 $(#[$($attr:tt)*])*
5099ac24
FG
484 pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? {
485 $($body:tt)*
486 }
487
488 $($rest:tt)*
489 ) => (
490 $(#[$($attr)*])*
491 pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
492 $($body)*
493 }
494
495 pub mod $name {
496 $(#[$($attr)*])*
497 #[cfg_attr(not(feature = "mangled-names"), no_mangle)]
49aad941 498 #[cfg_attr(feature = "weak-intrinsics", linkage = "weak")]
5099ac24
FG
499 pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
500 super::$name($($argname),*)
501 }
502 }
503
504 intrinsics!($($rest)*);
505 );
506
507 // Same as the above for unsafe functions.
508 (
509 $(#[$($attr:tt)*])*
510 pub unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? {
041b39d2
XL
511 $($body:tt)*
512 }
513
514 $($rest:tt)*
515 ) => (
516 $(#[$($attr)*])*
5099ac24 517 pub unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
041b39d2
XL
518 $($body)*
519 }
520
ba9703b0
XL
521 pub mod $name {
522 $(#[$($attr)*])*
523 #[cfg_attr(not(feature = "mangled-names"), no_mangle)]
49aad941 524 #[cfg_attr(feature = "weak-intrinsics", linkage = "weak")]
5099ac24 525 pub unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
ba9703b0
XL
526 super::$name($($argname),*)
527 }
528 }
529
041b39d2
XL
530 intrinsics!($($rest)*);
531 );
532}
533
534// Hack for LLVM expectations for ABI on windows. This is used by the
535// `#[win64_128bit_abi_hack]` attribute recognized above
f2b60f7d 536#[cfg(all(any(windows, target_os = "uefi"), target_pointer_width = "64"))]
041b39d2
XL
537pub mod win64_128bit_abi_hack {
538 #[repr(simd)]
539 pub struct U64x2(u64, u64);
540
541 impl From<i128> for U64x2 {
542 fn from(i: i128) -> U64x2 {
5869c6ff 543 use int::DInt;
041b39d2 544 let j = i as u128;
5869c6ff 545 U64x2(j.lo(), j.hi())
041b39d2
XL
546 }
547 }
548
549 impl From<u128> for U64x2 {
550 fn from(i: u128) -> U64x2 {
5869c6ff
XL
551 use int::DInt;
552 U64x2(i.lo(), i.hi())
041b39d2
XL
553 }
554 }
555}