2018-03-10 19:22:54 +01:00
|
|
|
//! This module implements run-time feature detection.
|
|
|
|
|
//!
|
|
|
|
|
//! The `is_{arch}_feature_detected!("feature-name")` macros take the name of a
|
|
|
|
|
//! feature as a string-literal, and return a boolean indicating whether the
|
|
|
|
|
//! feature is enabled at run-time or not.
|
|
|
|
|
//!
|
|
|
|
|
//! These macros do two things:
|
|
|
|
|
//! * map the string-literal into an integer stored as a `Feature` enum,
|
|
|
|
|
//! * call a `os::check_for(x: Feature)` function that returns `true` if the
|
|
|
|
|
//! feature is enabled.
|
|
|
|
|
//!
|
|
|
|
|
//! The `Feature` enums are also implemented in the `arch/{target_arch}.rs`
|
|
|
|
|
//! modules.
|
|
|
|
|
//!
|
|
|
|
|
//! The `check_for` functions are, in general, Operating System dependent. Most
|
|
|
|
|
//! architectures do not allow user-space programs to query the feature bits
|
|
|
|
|
//! due to security concerns (x86 is the big exception). These functions are
|
|
|
|
|
//! implemented in the `os/{target_os}.rs` modules.
|
2018-02-18 10:07:35 +09:00
|
|
|
|
2018-03-10 19:22:54 +01:00
|
|
|
#[macro_use]
|
|
|
|
|
mod error_macros;
|
2018-02-18 10:07:35 +09:00
|
|
|
|
2019-04-23 15:51:20 +02:00
|
|
|
#[macro_use]
|
|
|
|
|
mod macros;
|
|
|
|
|
|
2018-02-18 10:07:35 +09:00
|
|
|
cfg_if! {
|
|
|
|
|
if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
|
2018-03-10 19:22:54 +01:00
|
|
|
#[path = "arch/x86.rs"]
|
|
|
|
|
#[macro_use]
|
2018-02-18 10:07:35 +09:00
|
|
|
mod arch;
|
|
|
|
|
} else if #[cfg(target_arch = "arm")] {
|
2018-03-10 19:22:54 +01:00
|
|
|
#[path = "arch/arm.rs"]
|
|
|
|
|
#[macro_use]
|
2018-02-18 10:07:35 +09:00
|
|
|
mod arch;
|
|
|
|
|
} else if #[cfg(target_arch = "aarch64")] {
|
2018-03-10 19:22:54 +01:00
|
|
|
#[path = "arch/aarch64.rs"]
|
|
|
|
|
#[macro_use]
|
2018-02-18 10:07:35 +09:00
|
|
|
mod arch;
|
2018-05-16 22:19:13 +02:00
|
|
|
} else if #[cfg(target_arch = "powerpc")] {
|
|
|
|
|
#[path = "arch/powerpc.rs"]
|
|
|
|
|
#[macro_use]
|
|
|
|
|
mod arch;
|
2018-02-18 10:07:35 +09:00
|
|
|
} else if #[cfg(target_arch = "powerpc64")] {
|
2018-03-10 19:22:54 +01:00
|
|
|
#[path = "arch/powerpc64.rs"]
|
|
|
|
|
#[macro_use]
|
|
|
|
|
mod arch;
|
|
|
|
|
} else if #[cfg(target_arch = "mips")] {
|
|
|
|
|
#[path = "arch/mips.rs"]
|
|
|
|
|
#[macro_use]
|
|
|
|
|
mod arch;
|
|
|
|
|
} else if #[cfg(target_arch = "mips64")] {
|
|
|
|
|
#[path = "arch/mips64.rs"]
|
|
|
|
|
#[macro_use]
|
2018-02-18 10:07:35 +09:00
|
|
|
mod arch;
|
|
|
|
|
} else {
|
2018-03-10 19:22:54 +01:00
|
|
|
// Unimplemented architecture:
|
2018-02-18 10:07:35 +09:00
|
|
|
mod arch {
|
2019-09-16 17:58:36 +02:00
|
|
|
#[doc(hidden)]
|
2019-09-18 09:08:59 +02:00
|
|
|
pub(crate) enum Feature {
|
2018-02-18 10:07:35 +09:00
|
|
|
Null
|
|
|
|
|
}
|
2019-09-16 17:58:36 +02:00
|
|
|
#[doc(hidden)]
|
|
|
|
|
pub mod __is_feature_detected {}
|
2019-09-17 20:30:25 +02:00
|
|
|
|
|
|
|
|
impl Feature {
|
|
|
|
|
#[doc(hidden)]
|
2019-09-18 09:08:59 +02:00
|
|
|
pub(crate) fn from_str(_s: &str) -> Result<Feature, ()> { Err(()) }
|
2019-09-17 20:30:25 +02:00
|
|
|
#[doc(hidden)]
|
2019-09-18 09:08:59 +02:00
|
|
|
pub(crate) fn to_str(self) -> &'static str { "" }
|
2019-09-17 20:30:25 +02:00
|
|
|
}
|
2018-02-18 10:07:35 +09:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-09-18 09:08:59 +02:00
|
|
|
|
|
|
|
|
// This module needs to be public because the `is_{arch}_feature_detected!`
|
|
|
|
|
// macros expand calls to items within it in user crates.
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
|
pub use self::arch::__is_feature_detected;
|
|
|
|
|
|
|
|
|
|
pub(crate) use self::arch::Feature;
|
2018-02-18 10:07:35 +09:00
|
|
|
|
2018-04-15 10:53:38 -05:00
|
|
|
mod bit;
|
2018-06-06 00:17:14 +02:00
|
|
|
mod cache;
|
2018-04-15 10:53:38 -05:00
|
|
|
|
2018-03-10 19:22:54 +01:00
|
|
|
cfg_if! {
|
2019-08-31 09:30:10 +02:00
|
|
|
if #[cfg(miri)] {
|
2019-08-31 14:55:21 +02:00
|
|
|
// When running under miri all target-features that are not enabled at
|
|
|
|
|
// compile-time are reported as disabled at run-time.
|
|
|
|
|
//
|
|
|
|
|
// For features for which `cfg(target_feature)` returns true,
|
|
|
|
|
// this run-time detection logic is never called.
|
2019-08-31 09:30:10 +02:00
|
|
|
#[path = "os/other.rs"]
|
|
|
|
|
mod os;
|
|
|
|
|
} else if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
|
2018-03-10 19:22:54 +01:00
|
|
|
// On x86/x86_64 no OS specific functionality is required.
|
|
|
|
|
#[path = "os/x86.rs"]
|
|
|
|
|
mod os;
|
2019-01-21 16:59:10 +01:00
|
|
|
} else if #[cfg(all(target_os = "linux", feature = "use_std"))] {
|
2018-03-10 19:22:54 +01:00
|
|
|
#[path = "os/linux/mod.rs"]
|
|
|
|
|
mod os;
|
2018-12-08 16:56:19 +03:00
|
|
|
} else if #[cfg(target_os = "freebsd")] {
|
|
|
|
|
#[cfg(target_arch = "aarch64")]
|
|
|
|
|
#[path = "os/aarch64.rs"]
|
|
|
|
|
mod aarch64;
|
|
|
|
|
#[path = "os/freebsd/mod.rs"]
|
|
|
|
|
mod os;
|
2018-03-10 19:22:54 +01:00
|
|
|
} else {
|
|
|
|
|
#[path = "os/other.rs"]
|
|
|
|
|
mod os;
|
2018-03-08 09:59:21 +01:00
|
|
|
}
|
|
|
|
|
}
|
2019-09-09 11:45:41 +02:00
|
|
|
|
|
|
|
|
/// Performs run-time feature detection.
|
|
|
|
|
#[inline]
|
2019-09-18 09:08:59 +02:00
|
|
|
fn check_for(x: Feature) -> bool {
|
2019-09-09 11:45:41 +02:00
|
|
|
cache::test(x as u32, self::os::detect_features)
|
|
|
|
|
}
|
2019-04-23 15:51:20 +02:00
|
|
|
|
|
|
|
|
/// Returns an `Iterator<Item=(&'static str, bool)>` where
|
|
|
|
|
/// `Item.0` is the feature name, and `Item.1` is a `bool` which
|
|
|
|
|
/// is `true` if the feature is supported by the host and `false` otherwise.
|
|
|
|
|
#[unstable(feature = "stdsimd", issue = "27731")]
|
|
|
|
|
pub fn features() -> impl Iterator<Item = (&'static str, bool)> {
|
|
|
|
|
cfg_if! {
|
|
|
|
|
if #[cfg(any(
|
|
|
|
|
target_arch = "x86",
|
|
|
|
|
target_arch = "x86_64",
|
|
|
|
|
target_arch = "arm",
|
|
|
|
|
target_arch = "aarch64",
|
|
|
|
|
target_arch = "powerpc",
|
|
|
|
|
target_arch = "powerpc64",
|
|
|
|
|
target_arch = "mips",
|
|
|
|
|
target_arch = "mips64",
|
|
|
|
|
))] {
|
|
|
|
|
fn impl_() -> impl Iterator<Item=(&'static str, bool)> {
|
|
|
|
|
(0_u8..Feature::_last as u8).map(|discriminant: u8| {
|
|
|
|
|
let f: Feature = unsafe { crate::mem::transmute(discriminant) };
|
|
|
|
|
let name: &'static str = f.to_str();
|
|
|
|
|
let enabled: bool = check_for(f);
|
|
|
|
|
(name, enabled)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
fn impl_() -> impl Iterator<Item=(&'static str, bool)> {
|
|
|
|
|
(0_u8..0_u8).map(|_x: u8| ("", false))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
impl_()
|
|
|
|
|
}
|