Macro compiler_builtins::macros::intrinsics
source · macro_rules! intrinsics { () => { ... }; ( #[cfg_attr($e:meta, $($attr:tt)*)] $(#[$($attrs:tt)*])* pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { $($body:tt)* } $($rest:tt)* ) => { ... }; ( #[cfg_attr($e:meta, $($attr:tt)*)] $(#[$($attrs:tt)*])* pub unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { $($body:tt)* } $($rest:tt)* ) => { ... }; ( #[weak] $(#[$($attr:tt)*])* pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { $($body:tt)* } $($rest:tt)* ) => { ... }; ( #[weak] $(#[$($attr:tt)*])* pub unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { $($body:tt)* } $($rest:tt)* ) => { ... }; ( #[maybe_use_optimized_c_shim] $(#[$($attr:tt)*])* pub $(unsafe $(@ $empty:tt)? )? extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { $($body:tt)* } $($rest:tt)* ) => { ... }; ( #[aapcs_on_arm] $(#[$($attr:tt)*])* pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { $($body:tt)* } $($rest:tt)* ) => { ... }; ( #[unadjusted_on_win64] $(#[$($attr:tt)*])* pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { $($body:tt)* } $($rest:tt)* ) => { ... }; ( #[win64_128bit_abi_hack] $(#[$($attr:tt)*])* pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { $($body:tt)* } $($rest:tt)* ) => { ... }; ( #[arm_aeabi_alias = $alias:ident] $(#[$($attr:tt)*])* pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { $($body:tt)* } $($rest:tt)* ) => { ... }; ( #[mem_builtin] $(#[$($attr:tt)*])* pub unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { $($body:tt)* } $($rest:tt)* ) => { ... }; ( #[naked] $(#[$($attr:tt)*])* pub unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { $($body:tt)* } $($rest:tt)* ) => { ... }; ( #[avr_skip] $(#[$($attr:tt)*])* pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { $($body:tt)* } $($rest:tt)* ) => { ... }; ( $(#[$($attr:tt)*])* pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { $($body:tt)* } $($rest:tt)* ) => { ... }; ( $(#[$($attr:tt)*])* pub unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { $($body:tt)* } $($rest:tt)* ) => { ... }; }
Expand description
The “main macro” used for defining intrinsics.
The compiler-builtins library is super platform-specific with tons of crazy little tweaks for various platforms. As a result it could involve a lot of #cfg and macro soup, but the intention is that this macro alleviates a lot of that complexity. Ideally this macro has all the weird ABI things platforms need and elsewhere in this library it just looks like normal Rust code.
When the weak-intrinsics feature is enabled, all intrinsics functions are marked with #[linkage = “weak”] so that they can be replaced by another implementation at link time. This is particularly useful for mixed Rust/C++ binaries that want to use the C++ intrinsics, otherwise linking against the Rust stdlib will replace those from the compiler-rt library.
This macro is structured to be invoked with a bunch of functions that looks like:
intrinsics! {
pub extern "C" fn foo(a: i32) -> u32 {
// ...
}
#[nonstandard_attribute]
pub extern "C" fn bar(a: i32) -> u32 {
// ...
}
}
Each function is defined in a manner that looks like a normal Rust function. The macro then accepts a few nonstandard attributes that can decorate various functions. Each of the attributes is documented below with what it can do, and each of them slightly tweaks how further expansion happens.
A quick overview of attributes supported right now are:
weak
- indicates that the function should always be given weak linkage. This attribute must come before other attributes, as the other attributes will generate the final output function and need to haveweak
modify them.maybe_use_optimized_c_shim
- indicates that the Rust implementation is ignored if an optimized C version was compiled.aapcs_on_arm
- forces the ABI of the function to be"aapcs"
on ARM and the specified ABI everywhere else.unadjusted_on_win64
- likeaapcs_on_arm
this switches to the"unadjusted"
abi on Win64 and the specified abi elsewhere.win64_128bit_abi_hack
- this attribute is used for 128-bit integer intrinsics where the ABI is slightly tweaked on Windows platforms, but it’s a normal ABI elsewhere for returning a 128 bit integer.arm_aeabi_alias
- handles the “aliasing” of various intrinsics on ARM their otherwise typical names to other prefixed ones.