Shore up docs in the macros module
This commit is contained in:
parent
7de57cd4f9
commit
eabb6fab4a
@ -1,10 +1,63 @@
|
||||
//! Macros shared throughout the compiler-builtins implementation
|
||||
|
||||
/// 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 fo
|
||||
/// #[cfg] and macro soup, but the intention is that this macro alleviates a lof
|
||||
/// 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.
|
||||
///
|
||||
/// 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:
|
||||
///
|
||||
/// * `use_c_shim_if` - takes a #[cfg] directive and falls back to the
|
||||
/// C-compiled version if `feature = "c"` is specified.
|
||||
/// * `aapcs_on_arm` - forces the ABI of the function to be `"aapcs"` on ARM and
|
||||
/// the specified ABI everywhere else.
|
||||
/// * `unadjusted_on_win64` - like `aapcs_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.
|
||||
///
|
||||
macro_rules! intrinsics {
|
||||
() => ();
|
||||
|
||||
// Anything which has a `not(feature = "c")` we'll generate a shim function
|
||||
// which calls out to the C function if the `c` feature is enabled.
|
||||
// Otherwise if the `c` feature isn't enabled then we'll just have a normal
|
||||
// intrinsic.
|
||||
// Right now there's a bunch of architecture-optimized intrinsics in the
|
||||
// stock compiler-rt implementation. Not all of these have been ported over
|
||||
// to Rust yet so when the `c` feature of this crate is enabled we fall back
|
||||
// to the architecture-specific versions which should be more optimized. The
|
||||
// purpose of this macro is to easily allow specifying this.
|
||||
//
|
||||
// The argument to `use_c_shim_if` is a `#[cfg]` directive which, when true,
|
||||
// will cause this crate's exported version of `$name` to just redirect to
|
||||
// the C implementation. No symbol named `$name` will be in the object file
|
||||
// for this crate itself.
|
||||
//
|
||||
// When the `#[cfg]` directive is false, or when the `c` feature is
|
||||
// disabled, the provided implementation is used instead.
|
||||
(
|
||||
#[use_c_shim_if($($cfg_clause:tt)*)]
|
||||
$(#[$($attr:tt)*])*
|
||||
@ -97,8 +150,13 @@ macro_rules! intrinsics {
|
||||
intrinsics!($($rest)*);
|
||||
);
|
||||
|
||||
// Another attribute we recognize is an "abi hack" for win64 to get the 128
|
||||
// bit calling convention correct.
|
||||
// Some intrinsics on win64 which return a 128-bit integer have an.. unusual
|
||||
// calling convention. That's managed here with this "abi hack" which alters
|
||||
// the generated symbol's ABI.
|
||||
//
|
||||
// This will still define a function in this crate with the given name and
|
||||
// signature, but the actual symbol for the intrinsic may have a slightly
|
||||
// different ABI on win64.
|
||||
(
|
||||
#[win64_128bit_abi_hack]
|
||||
$(#[$($attr:tt)*])*
|
||||
@ -119,10 +177,10 @@ macro_rules! intrinsics {
|
||||
|
||||
intrinsics! {
|
||||
pub extern $abi fn $name( $($argname: $ty),* )
|
||||
-> ::macros::win64_abi_hack::U64x2
|
||||
-> ::macros::win64_128bit_abi_hack::U64x2
|
||||
{
|
||||
let e: $ret = super::$name($($argname),*);
|
||||
::macros::win64_abi_hack::U64x2::from(e)
|
||||
::macros::win64_128bit_abi_hack::U64x2::from(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -140,7 +198,8 @@ macro_rules! intrinsics {
|
||||
|
||||
// A bunch of intrinsics on ARM are aliased in the standard compiler-rt
|
||||
// build under `__aeabi_*` aliases, and LLVM will call these instead of the
|
||||
// original function. Handle that here
|
||||
// original function. The aliasing here is used to generate these symbols in
|
||||
// the object file.
|
||||
(
|
||||
#[arm_aeabi_alias = $alias:ident]
|
||||
$(#[$($attr:tt)*])*
|
||||
@ -151,7 +210,6 @@ macro_rules! intrinsics {
|
||||
$($rest:tt)*
|
||||
) => (
|
||||
#[cfg(target_arch = "arm")]
|
||||
$(#[$($attr)*])*
|
||||
pub extern $abi fn $name( $($argname: $ty),* ) -> $ret {
|
||||
$($body)*
|
||||
}
|
||||
@ -180,6 +238,12 @@ macro_rules! intrinsics {
|
||||
intrinsics!($($rest)*);
|
||||
);
|
||||
|
||||
// This is the final catch-all rule. At this point we just generate an
|
||||
// intrinsic with a conditional `#[no_mangle]` directive to avoid
|
||||
// interfereing with duplicate symbols and whatnot.
|
||||
//
|
||||
// After the intrinsic is defined we just continue with the rest of the
|
||||
// input we were given.
|
||||
(
|
||||
$(#[$($attr:tt)*])*
|
||||
pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty {
|
||||
@ -198,9 +262,10 @@ macro_rules! intrinsics {
|
||||
);
|
||||
}
|
||||
|
||||
// Hack for LLVM expectations for ABI on windows
|
||||
// Hack for LLVM expectations for ABI on windows. This is used by the
|
||||
// `#[win64_128bit_abi_hack]` attribute recognized above
|
||||
#[cfg(all(windows, target_pointer_width="64"))]
|
||||
pub mod win64_abi_hack {
|
||||
pub mod win64_128bit_abi_hack {
|
||||
#[repr(simd)]
|
||||
pub struct U64x2(u64, u64);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user