diff options
| author | gnzlbg <gonzalobg88@gmail.com> | 2019-04-23 15:51:20 +0200 |
|---|---|---|
| committer | gnzlbg <gnzlbg@users.noreply.github.com> | 2019-09-16 23:43:01 +0200 |
| commit | 1f44c1407dc6e6f91600f9303739ca8acbcc8194 (patch) | |
| tree | fb4d4c554ce3aaceccc1ce679c33fc9003a259bc /library/stdarch/crates | |
| parent | f3140f4b25860a1aa6257c6afc064efe177b0b67 (diff) | |
| download | rust-1f44c1407dc6e6f91600f9303739ca8acbcc8194.tar.gz rust-1f44c1407dc6e6f91600f9303739ca8acbcc8194.zip | |
Add std_detect::detect::features() -> impl Iterator<Item=(&'static str, bool)> API
Diffstat (limited to 'library/stdarch/crates')
11 files changed, 314 insertions, 558 deletions
diff --git a/library/stdarch/crates/std_detect/src/detect/arch/aarch64.rs b/library/stdarch/crates/std_detect/src/detect/arch/aarch64.rs index ebae2bd2854..73e54052b82 100644 --- a/library/stdarch/crates/std_detect/src/detect/arch/aarch64.rs +++ b/library/stdarch/crates/std_detect/src/detect/arch/aarch64.rs @@ -1,106 +1,36 @@ //! Aarch64 run-time features. -/// Checks if `aarch64` feature is enabled. -#[macro_export] -#[unstable(feature = "stdsimd", issue = "27731")] -#[allow_internal_unstable(stdsimd_internal,stdsimd)] -macro_rules! is_aarch64_feature_detected { - ("neon") => { - // FIXME: this should be removed once we rename Aarch64 neon to asimd - cfg!(target_feature = "neon") || - $crate::detect::check_for($crate::detect::Feature::asimd) - }; - ("asimd") => { - cfg!(target_feature = "neon") || - $crate::detect::check_for($crate::detect::Feature::asimd) - }; - ("pmull") => { - cfg!(target_feature = "pmull") || - $crate::detect::check_for($crate::detect::Feature::pmull) - }; - ("fp") => { - cfg!(target_feature = "fp") || - $crate::detect::check_for($crate::detect::Feature::fp) - }; - ("fp16") => { - cfg!(target_feature = "fp16") || - $crate::detect::check_for($crate::detect::Feature::fp16) - }; - ("sve") => { - cfg!(target_feature = "sve") || - $crate::detect::check_for($crate::detect::Feature::sve) - }; - ("crc") => { - cfg!(target_feature = "crc") || - $crate::detect::check_for($crate::detect::Feature::crc) - }; - ("crypto") => { - cfg!(target_feature = "crypto") || - $crate::detect::check_for($crate::detect::Feature::crypto) - }; - ("lse") => { - cfg!(target_feature = "lse") || - $crate::detect::check_for($crate::detect::Feature::lse) - }; - ("rdm") => { - cfg!(target_feature = "rdm") || - $crate::detect::check_for($crate::detect::Feature::rdm) - }; - ("rcpc") => { - cfg!(target_feature = "rcpc") || - $crate::detect::check_for($crate::detect::Feature::rcpc) - }; - ("dotprod") => { - cfg!(target_feature = "dotprod") || - $crate::detect::check_for($crate::detect::Feature::dotprod) - }; - ("ras") => { - compile_error!("\"ras\" feature cannot be detected at run-time") - }; - ("v8.1a") => { - compile_error!("\"v8.1a\" feature cannot be detected at run-time") - }; - ("v8.2a") => { - compile_error!("\"v8.2a\" feature cannot be detected at run-time") - }; - ("v8.3a") => { - compile_error!("\"v8.3a\" feature cannot be detected at run-time") - }; - ($t:tt,) => { - is_aarch64_feature_detected!($t); - }; - ($t:tt) => { compile_error!(concat!("unknown aarch64 target feature: ", $t)) }; -} - -/// ARM Aarch64 CPU Feature enum. Each variant denotes a position in a bitset -/// for a particular feature. -/// -/// PLEASE: do not use this, it is an implementation detail subject to change. -#[doc(hidden)] -#[allow(non_camel_case_types)] -#[repr(u8)] -#[unstable(feature = "stdsimd_internal", issue = "0")] -pub enum Feature { +features! { + @TARGET: aarch64; + @MACRO_NAME: is_aarch64_feature_detected; + @MACRO_ATTRS: + /// Checks if `aarch64` feature is enabled. + #[unstable(feature = "stdsimd", issue = "27731")] + @BIND_FEATURE_NAME: "asimd"; "neon"; + @NO_RUNTIME_DETECTION: "ras"; + @NO_RUNTIME_DETECTION: "v8.1a"; + @NO_RUNTIME_DETECTION: "v8.2a"; + @NO_RUNTIME_DETECTION: "v8.3a"; + @FEATURE: asimd: "neon"; /// ARM Advanced SIMD (ASIMD) - asimd, + @FEATURE: pmull: "pmull"; /// Polynomial Multiply - pmull, + @FEATURE: fp: "fp"; /// Floating point support - fp, + @FEATURE: fp16: "fp16"; /// Half-float support. - fp16, + @FEATURE: sve: "sve"; /// Scalable Vector Extension (SVE) - sve, + @FEATURE: crc: "crc"; /// CRC32 (Cyclic Redundancy Check) - crc, + @FEATURE: crypto: "crypto"; /// Crypto: AES + PMULL + SHA1 + SHA2 - crypto, + @FEATURE: lse: "lse"; /// Atomics (Large System Extension) - lse, + @FEATURE: rdm: "rdm"; /// Rounding Double Multiply (ASIMDRDM) - rdm, + @FEATURE: rcpc: "rcpc"; /// Release consistent Processor consistent (RcPc) - rcpc, + @FEATURE: dotprod: "dotprod"; /// Vector Dot-Product (ASIMDDP) - dotprod, } diff --git a/library/stdarch/crates/std_detect/src/detect/arch/arm.rs b/library/stdarch/crates/std_detect/src/detect/arch/arm.rs index b2626bf2923..86dc6dbbf23 100644 --- a/library/stdarch/crates/std_detect/src/detect/arch/arm.rs +++ b/library/stdarch/crates/std_detect/src/detect/arch/arm.rs @@ -1,39 +1,17 @@ //! Run-time feature detection on ARM Aarch32. -/// Checks if `arm` feature is enabled. -#[macro_export] -#[unstable(feature = "stdsimd", issue = "27731")] -#[allow_internal_unstable(stdsimd_internal,stdsimd)] -macro_rules! is_arm_feature_detected { - ("neon") => { - cfg!(target_feature = "neon") || - $crate::detect::check_for($crate::detect::Feature::neon) - }; - ("pmull") => { - cfg!(target_feature = "pmull") || - $crate::detect::check_for($crate::detect::Feature::pmull) - }; - ("v7") => { compile_error!("\"v7\" feature cannot be detected at run-time") }; - ("vfp2") => { compile_error!("\"vfp2\" feature cannot be detected at run-time") }; - ("vfp3") => { compile_error!("\"vfp3\" feature cannot be detected at run-time") }; - ("vfp4") => { compile_error!("\"vfp4\" feature cannot be detected at run-time") }; - ($t:tt,) => { - is_arm_feature_detected!($t); - }; - ($t:tt) => { compile_error!(concat!("unknown arm target feature: ", $t)) }; -} - -/// ARM CPU Feature enum. Each variant denotes a position in a bitset for a -/// particular feature. -/// -/// PLEASE: do not use this, it is an implementation detail subject to change. -#[doc(hidden)] -#[allow(non_camel_case_types)] -#[repr(u8)] -#[unstable(feature = "stdsimd_internal", issue = "0")] -pub enum Feature { +features! { + @TARGET: arm; + @MACRO_NAME: is_arm_feature_detected; + @MACRO_ATTRS: + /// Checks if `arm` feature is enabled. + #[unstable(feature = "stdsimd", issue = "27731")] + @NO_RUNTIME_DETECTION: "v7"; + @NO_RUNTIME_DETECTION: "vfp2"; + @NO_RUNTIME_DETECTION: "vfp3"; + @NO_RUNTIME_DETECTION: "vfp4"; + @FEATURE: neon: "neon"; /// ARM Advanced SIMD (NEON) - Aarch32 - neon, + @FEATURE: pmull: "pmull"; /// Polynomial Multiply - pmull, } diff --git a/library/stdarch/crates/std_detect/src/detect/arch/mips.rs b/library/stdarch/crates/std_detect/src/detect/arch/mips.rs index f4381b811cd..1ac540ef737 100644 --- a/library/stdarch/crates/std_detect/src/detect/arch/mips.rs +++ b/library/stdarch/crates/std_detect/src/detect/arch/mips.rs @@ -1,29 +1,11 @@ //! Run-time feature detection on MIPS. -/// Checks if `mips` feature is enabled. -#[macro_export] -#[unstable(feature = "stdsimd", issue = "27731")] -#[allow_internal_unstable(stdsimd_internal,stdsimd)] -macro_rules! is_mips_feature_detected { - ("msa") => { - cfg!(target_feature = "msa") || - $crate::detect::check_for($crate::detect::Feature::msa) - }; - ($t:tt,) => { - is_mips_feature_detected!($t); - }; - ($t:tt) => { compile_error!(concat!("unknown mips target feature: ", $t)) }; -} - -/// MIPS CPU Feature enum. Each variant denotes a position in a bitset for a -/// particular feature. -/// -/// PLEASE: do not use this, it is an implementation detail subject to change. -#[doc(hidden)] -#[allow(non_camel_case_types)] -#[repr(u8)] -#[unstable(feature = "stdsimd_internal", issue = "0")] -pub enum Feature { +features! { + @TARGET: mips; + @MACRO_NAME: is_mips_feature_detected; + @MACRO_ATTRS: + /// Checks if `mips` feature is enabled. + #[unstable(feature = "stdsimd", issue = "27731")] + @FEATURE: msa: "msa"; /// MIPS SIMD Architecture (MSA) - msa, } diff --git a/library/stdarch/crates/std_detect/src/detect/arch/mips64.rs b/library/stdarch/crates/std_detect/src/detect/arch/mips64.rs index 2663bc68ba9..33ad3bca768 100644 --- a/library/stdarch/crates/std_detect/src/detect/arch/mips64.rs +++ b/library/stdarch/crates/std_detect/src/detect/arch/mips64.rs @@ -1,29 +1,11 @@ //! Run-time feature detection on MIPS64. -/// Checks if `mips64` feature is enabled. -#[macro_export] -#[unstable(feature = "stdsimd", issue = "27731")] -#[allow_internal_unstable(stdsimd_internal,stdsimd)] -macro_rules! is_mips64_feature_detected { - ("msa") => { - cfg!(target_feature = "msa") || - $crate::detect::check_for($crate::detect::Feature::msa) - }; - ($t:tt,) => { - is_mips64_feature_detected!($t); - }; - ($t:tt) => { compile_error!(concat!("unknown mips64 target feature: ", $t)) }; -} - -/// MIPS64 CPU Feature enum. Each variant denotes a position in a bitset -/// for a particular feature. -/// -/// PLEASE: do not use this, it is an implementation detail subject to change. -#[doc(hidden)] -#[allow(non_camel_case_types)] -#[repr(u8)] -#[unstable(feature = "stdsimd_internal", issue = "0")] -pub enum Feature { +features! { + @TARGET: mips64; + @MACRO_NAME: is_mips64_feature_detected; + @MACRO_ATTRS: + /// Checks if `mips64` feature is enabled. + #[unstable(feature = "stdsimd", issue = "27731")] + @FEATURE: msa: "msa"; /// MIPS SIMD Architecture (MSA) - msa, } diff --git a/library/stdarch/crates/std_detect/src/detect/arch/powerpc.rs b/library/stdarch/crates/std_detect/src/detect/arch/powerpc.rs index a342dc1aacc..6cc35a24110 100644 --- a/library/stdarch/crates/std_detect/src/detect/arch/powerpc.rs +++ b/library/stdarch/crates/std_detect/src/detect/arch/powerpc.rs @@ -1,42 +1,15 @@ //! Run-time feature detection on PowerPC. -/// Checks if `powerpc` feature is enabled. -#[macro_export] -#[unstable(feature = "stdsimd", issue = "27731")] -#[allow_internal_unstable(stdsimd_internal,stdsimd)] -macro_rules! is_powerpc_feature_detected { - ("altivec") => { - cfg!(target_feature = "altivec") || - $crate::detect::check_for($crate::detect::Feature::altivec) - }; - ("vsx") => { - cfg!(target_feature = "vsx") || - $crate::detect::check_for($crate::detect::Feature::vsx) - }; - ("power8") => { - cfg!(target_feature = "power8") || - $crate::detect::check_for($crate::detect::Feature::power8) - }; - ($t:tt,) => { - is_powerpc_feature_detected!($t); - }; - ($t:tt) => { compile_error!(concat!("unknown powerpc target feature: ", $t)) }; -} - - -/// PowerPC CPU Feature enum. Each variant denotes a position in a bitset -/// for a particular feature. -/// -/// PLEASE: do not use this, it is an implementation detail subject to change. -#[doc(hidden)] -#[allow(non_camel_case_types)] -#[repr(u8)] -#[unstable(feature = "stdsimd_internal", issue = "0")] -pub enum Feature { +features! { + @TARGET: powerpc; + @MACRO_NAME: is_powerpc_feature_detected; + @MACRO_ATTRS: + /// Checks if `powerpc` feature is enabled. + #[unstable(feature = "stdsimd", issue = "27731")] + @FEATURE: altivec: "altivec"; /// Altivec - altivec, + @FEATURE: vsx: "vsx"; /// VSX - vsx, + @FEATURE: power8: "power8"; /// Power8 - power8, } diff --git a/library/stdarch/crates/std_detect/src/detect/arch/powerpc64.rs b/library/stdarch/crates/std_detect/src/detect/arch/powerpc64.rs index 2e82c569252..a075c94190e 100644 --- a/library/stdarch/crates/std_detect/src/detect/arch/powerpc64.rs +++ b/library/stdarch/crates/std_detect/src/detect/arch/powerpc64.rs @@ -1,42 +1,15 @@ //! Run-time feature detection on PowerPC64. -/// Checks if `powerpc64` feature is enabled. -#[macro_export] -#[unstable(feature = "stdsimd", issue = "27731")] -#[allow_internal_unstable(stdsimd_internal,stdsimd)] -macro_rules! is_powerpc64_feature_detected { - ("altivec") => { - cfg!(target_feature = "altivec") || - $crate::detect::check_for($crate::detect::Feature::altivec) - }; - ("vsx") => { - cfg!(target_feature = "vsx") || - $crate::detect::check_for($crate::detect::Feature::vsx) - }; - ("power8") => { - cfg!(target_feature = "power8") || - $crate::detect::check_for($crate::detect::Feature::power8) - }; - ($t:tt,) => { - is_powerpc64_feature_detected!($t); - }; - ($t:tt) => { compile_error!(concat!("unknown powerpc64 target feature: ", $t)) }; -} - - -/// PowerPC64 CPU Feature enum. Each variant denotes a position in a bitset -/// for a particular feature. -/// -/// PLEASE: do not use this, it is an implementation detail subject to change. -#[doc(hidden)] -#[allow(non_camel_case_types)] -#[repr(u8)] -#[unstable(feature = "stdsimd_internal", issue = "0")] -pub enum Feature { +features! { + @TARGET: powerpc64; + @MACRO_NAME: is_powerpc64_feature_detected; + @MACRO_ATTRS: + /// Checks if `powerpc` feature is enabled. + #[unstable(feature = "stdsimd", issue = "27731")] + @FEATURE: altivec: "altivec"; /// Altivec - altivec, + @FEATURE: vsx: "vsx"; /// VSX - vsx, + @FEATURE: power8: "power8"; /// Power8 - power8, } diff --git a/library/stdarch/crates/std_detect/src/detect/arch/x86.rs b/library/stdarch/crates/std_detect/src/detect/arch/x86.rs index 50d5cfa87c4..470b8978dbc 100644 --- a/library/stdarch/crates/std_detect/src/detect/arch/x86.rs +++ b/library/stdarch/crates/std_detect/src/detect/arch/x86.rs @@ -15,334 +15,154 @@ //! in a global `AtomicUsize` variable. The query is performed by just checking //! whether the feature bit in this global variable is set or cleared. -/// A macro to test at *runtime* whether a CPU feature is available on -/// x86/x86-64 platforms. -/// -/// This macro is provided in the standard library and will detect at runtime -/// whether the specified CPU feature is detected. This does **not** resolve at -/// compile time unless the specified feature is already enabled for the entire -/// crate. Runtime detection currently relies mostly on the `cpuid` instruction. -/// -/// This macro only takes one argument which is a string literal of the feature -/// being tested for. The feature names supported are the lowercase versions of -/// the ones defined by Intel in [their documentation][docs]. -/// -/// ## Supported arguments -/// -/// This macro supports the same names that `#[target_feature]` supports. Unlike -/// `#[target_feature]`, however, this macro does not support names separated -/// with a comma. Instead testing for multiple features must be done through -/// separate macro invocations for now. -/// -/// Supported arguments are: -/// -/// * `"aes"` -/// * `"pclmulqdq"` -/// * `"rdrand"` -/// * `"rdseed"` -/// * `"tsc"` -/// * `"mmx"` -/// * `"sse"` -/// * `"sse2"` -/// * `"sse3"` -/// * `"ssse3"` -/// * `"sse4.1"` -/// * `"sse4.2"` -/// * `"sse4a"` -/// * `"sha"` -/// * `"avx"` -/// * `"avx2"` -/// * `"avx512f"` -/// * `"avx512cd"` -/// * `"avx512er"` -/// * `"avx512pf"` -/// * `"avx512bw"` -/// * `"avx512dq"` -/// * `"avx512vl"` -/// * `"avx512ifma"` -/// * `"avx512vbmi"` -/// * `"avx512vpopcntdq"` -/// * `"f16c"` -/// * `"fma"` -/// * `"bmi1"` -/// * `"bmi2"` -/// * `"abm"` -/// * `"lzcnt"` -/// * `"tbm"` -/// * `"popcnt"` -/// * `"fxsr"` -/// * `"xsave"` -/// * `"xsaveopt"` -/// * `"xsaves"` -/// * `"xsavec"` -/// * `"adx"` -/// * `"rtm"` -/// -/// [docs]: https://software.intel.com/sites/landingpage/IntrinsicsGuide -#[macro_export] -#[stable(feature = "simd_x86", since = "1.27.0")] -#[allow_internal_unstable(stdsimd_internal,stdsimd)] -macro_rules! is_x86_feature_detected { - ("aes") => { - cfg!(target_feature = "aes") || $crate::detect::check_for( - $crate::detect::Feature::aes) }; - ("pclmulqdq") => { - cfg!(target_feature = "pclmulqdq") || $crate::detect::check_for( - $crate::detect::Feature::pclmulqdq) }; - ("rdrand") => { - cfg!(target_feature = "rdrand") || $crate::detect::check_for( - $crate::detect::Feature::rdrand) }; - ("rdseed") => { - cfg!(target_feature = "rdseed") || $crate::detect::check_for( - $crate::detect::Feature::rdseed) }; - ("tsc") => { - cfg!(target_feature = "tsc") || $crate::detect::check_for( - $crate::detect::Feature::tsc) }; - ("mmx") => { - cfg!(target_feature = "mmx") || $crate::detect::check_for( - $crate::detect::Feature::mmx) }; - ("sse") => { - cfg!(target_feature = "sse") || $crate::detect::check_for( - $crate::detect::Feature::sse) }; - ("sse2") => { - cfg!(target_feature = "sse2") || $crate::detect::check_for( - $crate::detect::Feature::sse2) - }; - ("sse3") => { - cfg!(target_feature = "sse3") || $crate::detect::check_for( - $crate::detect::Feature::sse3) - }; - ("ssse3") => { - cfg!(target_feature = "ssse3") || $crate::detect::check_for( - $crate::detect::Feature::ssse3) - }; - ("sse4.1") => { - cfg!(target_feature = "sse4.1") || $crate::detect::check_for( - $crate::detect::Feature::sse4_1) - }; - ("sse4.2") => { - cfg!(target_feature = "sse4.2") || $crate::detect::check_for( - $crate::detect::Feature::sse4_2) - }; - ("sse4a") => { - cfg!(target_feature = "sse4a") || $crate::detect::check_for( - $crate::detect::Feature::sse4a) - }; - ("sha") => { - cfg!(target_feature = "sha") || $crate::detect::check_for( - $crate::detect::Feature::sha) - }; - ("avx") => { - cfg!(target_feature = "avx") || $crate::detect::check_for( - $crate::detect::Feature::avx) - }; - ("avx2") => { - cfg!(target_feature = "avx2") || $crate::detect::check_for( - $crate::detect::Feature::avx2) - }; - ("avx512f") => { - cfg!(target_feature = "avx512f") || $crate::detect::check_for( - $crate::detect::Feature::avx512f) - }; - ("avx512cd") => { - cfg!(target_feature = "avx512cd") || $crate::detect::check_for( - $crate::detect::Feature::avx512cd) - }; - ("avx512er") => { - cfg!(target_feature = "avx512er") || $crate::detect::check_for( - $crate::detect::Feature::avx512er) - }; - ("avx512pf") => { - cfg!(target_feature = "avx512pf") || $crate::detect::check_for( - $crate::detect::Feature::avx512pf) - }; - ("avx512bw") => { - cfg!(target_feature = "avx512bw") || $crate::detect::check_for( - $crate::detect::Feature::avx512bw) - }; - ("avx512dq") => { - cfg!(target_feature = "avx512dq") || $crate::detect::check_for( - $crate::detect::Feature::avx512dq) - }; - ("avx512vl") => { - cfg!(target_Feature = "avx512vl") || $crate::detect::check_for( - $crate::detect::Feature::avx512vl) - }; - ("avx512ifma") => { - cfg!(target_feature = "avx512ifma") || $crate::detect::check_for( - $crate::detect::Feature::avx512_ifma) - }; - ("avx512vbmi") => { - cfg!(target_feature = "avx512vbmi") || $crate::detect::check_for( - $crate::detect::Feature::avx512_vbmi) - }; - ("avx512vpopcntdq") => { - cfg!(target_feature = "avx512vpopcntdq") || $crate::detect::check_for( - $crate::detect::Feature::avx512_vpopcntdq) - }; - ("f16c") => { - cfg!(target_feature = "f16c") || $crate::detect::check_for( - $crate::detect::Feature::f16c) - }; - ("fma") => { - cfg!(target_feature = "fma") || $crate::detect::check_for( - $crate::detect::Feature::fma) - }; - ("bmi1") => { - cfg!(target_feature = "bmi1") || $crate::detect::check_for( - $crate::detect::Feature::bmi) - }; - ("bmi2") => { - cfg!(target_feature = "bmi2") || $crate::detect::check_for( - $crate::detect::Feature::bmi2) - }; - ("abm") => { - cfg!(target_feature = "abm") || $crate::detect::check_for( - $crate::detect::Feature::abm) - }; - ("lzcnt") => { - cfg!(target_feature = "lzcnt") || $crate::detect::check_for( - $crate::detect::Feature::abm) - }; - ("tbm") => { - cfg!(target_feature = "tbm") || $crate::detect::check_for( - $crate::detect::Feature::tbm) - }; - ("popcnt") => { - cfg!(target_feature = "popcnt") || $crate::detect::check_for( - $crate::detect::Feature::popcnt) - }; - ("fxsr") => { - cfg!(target_feature = "fxsr") || $crate::detect::check_for( - $crate::detect::Feature::fxsr) - }; - ("xsave") => { - cfg!(target_feature = "xsave") || $crate::detect::check_for( - $crate::detect::Feature::xsave) - }; - ("xsaveopt") => { - cfg!(target_feature = "xsaveopt") || $crate::detect::check_for( - $crate::detect::Feature::xsaveopt) - }; - ("xsaves") => { - cfg!(target_feature = "xsaves") || $crate::detect::check_for( - $crate::detect::Feature::xsaves) - }; - ("xsavec") => { - cfg!(target_feature = "xsavec") || $crate::detect::check_for( - $crate::detect::Feature::xsavec) - }; - ("cmpxchg16b") => { - cfg!(target_feature = "cmpxchg16b") || $crate::detect::check_for( - $crate::detect::Feature::cmpxchg16b) - }; - ("adx") => { - cfg!(target_feature = "adx") || $crate::detect::check_for( - $crate::detect::Feature::adx) - }; - ("rtm") => { - cfg!(target_feature = "rtm") || $crate::detect::check_for( - $crate::detect::Feature::rtm) - }; - ($t:tt,) => { - is_x86_feature_detected!($t); - }; - ($t:tt) => { - compile_error!(concat!("unknown target feature: ", $t)) - }; -} - -/// X86 CPU Feature enum. Each variant denotes a position in a bitset for a -/// particular feature. -/// -/// This is an unstable implementation detail subject to change. -#[allow(non_camel_case_types)] -#[repr(u8)] -#[doc(hidden)] -#[unstable(feature = "stdsimd_internal", issue = "0")] -pub enum Feature { +features! { + @TARGET: x86; + @MACRO_NAME: is_x86_feature_detected; + @MACRO_ATTRS: + /// A macro to test at *runtime* whether a CPU feature is available on + /// x86/x86-64 platforms. + /// + /// This macro is provided in the standard library and will detect at runtime + /// whether the specified CPU feature is detected. This does **not** resolve at + /// compile time unless the specified feature is already enabled for the entire + /// crate. Runtime detection currently relies mostly on the `cpuid` instruction. + /// + /// This macro only takes one argument which is a string literal of the feature + /// being tested for. The feature names supported are the lowercase versions of + /// the ones defined by Intel in [their documentation][docs]. + /// + /// ## Supported arguments + /// + /// This macro supports the same names that `#[target_feature]` supports. Unlike + /// `#[target_feature]`, however, this macro does not support names separated + /// with a comma. Instead testing for multiple features must be done through + /// separate macro invocations for now. + /// + /// Supported arguments are: + /// + /// * `"aes"` + /// * `"pclmulqdq"` + /// * `"rdrand"` + /// * `"rdseed"` + /// * `"tsc"` + /// * `"mmx"` + /// * `"sse"` + /// * `"sse2"` + /// * `"sse3"` + /// * `"ssse3"` + /// * `"sse4.1"` + /// * `"sse4.2"` + /// * `"sse4a"` + /// * `"sha"` + /// * `"avx"` + /// * `"avx2"` + /// * `"avx512f"` + /// * `"avx512cd"` + /// * `"avx512er"` + /// * `"avx512pf"` + /// * `"avx512bw"` + /// * `"avx512dq"` + /// * `"avx512vl"` + /// * `"avx512ifma"` + /// * `"avx512vbmi"` + /// * `"avx512vpopcntdq"` + /// * `"fma"` + /// * `"bmi1"` + /// * `"bmi2"` + /// * `"abm"` + /// * `"lzcnt"` + /// * `"tbm"` + /// * `"popcnt"` + /// * `"fxsr"` + /// * `"xsave"` + /// * `"xsaveopt"` + /// * `"xsaves"` + /// * `"xsavec"` + /// + /// [docs]: https://software.intel.com/sites/landingpage/IntrinsicsGuide + #[stable(feature = "simd_x86", since = "1.27.0")] + @BIND_FEATURE_NAME: "abm"; "lzcnt"; // abm is a synonym for lzcnt + @FEATURE: aes: "aes"; /// AES (Advanced Encryption Standard New Instructions AES-NI) - aes, + @FEATURE: pclmulqdq: "pclmulqdq"; /// CLMUL (Carry-less Multiplication) - pclmulqdq, + @FEATURE: rdrand: "rdrand"; /// RDRAND - rdrand, + @FEATURE: rdseed: "rdseed"; /// RDSEED - rdseed, + @FEATURE: tsc: "tsc"; /// TSC (Time Stamp Counter) - tsc, - /// MMX - mmx, + @FEATURE: mmx: "mmx"; + /// MMX (MultiMedia eXtensions) + @FEATURE: sse: "sse"; /// SSE (Streaming SIMD Extensions) - sse, + @FEATURE: sse2: "sse2"; /// SSE2 (Streaming SIMD Extensions 2) - sse2, + @FEATURE: sse3: "sse3"; /// SSE3 (Streaming SIMD Extensions 3) - sse3, + @FEATURE: ssse3: "ssse3"; /// SSSE3 (Supplemental Streaming SIMD Extensions 3) - ssse3, + @FEATURE: sse4_1: "sse4.1"; /// SSE4.1 (Streaming SIMD Extensions 4.1) - sse4_1, + @FEATURE: sse4_2: "sse4.2"; /// SSE4.2 (Streaming SIMD Extensions 4.2) - sse4_2, + @FEATURE: sse4a: "sse4a"; /// SSE4a (Streaming SIMD Extensions 4a) - sse4a, + @FEATURE: sha: "sha"; /// SHA - sha, + @FEATURE: avx: "avx"; /// AVX (Advanced Vector Extensions) - avx, + @FEATURE: avx2: "avx2"; /// AVX2 (Advanced Vector Extensions 2) - avx2, + @FEATURE: avx512f: "avx512f" ; /// AVX-512 F (Foundation) - avx512f, + @FEATURE: avx512cd: "avx512cd" ; /// AVX-512 CD (Conflict Detection Instructions) - avx512cd, - /// AVX-512 ER (Exponential and Reciprocal Instructions) - avx512er, + @FEATURE: avx512er: "avx512er"; + /// AVX-512 ER (Expo nential and Reciprocal Instructions) + @FEATURE: avx512pf: "avx512pf"; /// AVX-512 PF (Prefetch Instructions) - avx512pf, + @FEATURE: avx512bw: "avx512bw"; /// AVX-512 BW (Byte and Word Instructions) - avx512bw, + @FEATURE: avx512dq: "avx512dq"; /// AVX-512 DQ (Doubleword and Quadword) - avx512dq, + @FEATURE: avx512vl: "avx512vl"; /// AVX-512 VL (Vector Length Extensions) - avx512vl, + @FEATURE: avx512ifma: "avx512ifma"; /// AVX-512 IFMA (Integer Fused Multiply Add) - avx512_ifma, + @FEATURE: avx512vbmi: "avx512vbmi"; /// AVX-512 VBMI (Vector Byte Manipulation Instructions) - avx512_vbmi, + @FEATURE: avx512vpopcntdq: "avx512vpopcntdq"; /// AVX-512 VPOPCNTDQ (Vector Population Count Doubleword and /// Quadword) - avx512_vpopcntdq, + @FEATURE: f16c: "f16c"; /// F16C (Conversions between IEEE-754 `binary16` and `binary32` formats) - f16c, + @FEATURE: fma: "fma"; /// FMA (Fused Multiply Add) - fma, + @FEATURE: bmi1: "bmi1" ; /// BMI1 (Bit Manipulation Instructions 1) - bmi, - /// BMI1 (Bit Manipulation Instructions 2) - bmi2, - /// ABM (Advanced Bit Manipulation) on AMD / LZCNT (Leading Zero - /// Count) on Intel - abm, + @FEATURE: bmi2: "bmi2" ; + /// BMI2 (Bit Manipulation Instructions 2) + @FEATURE: lzcnt: "lzcnt"; + /// ABM (Advanced Bit Manipulation) / LZCNT (Leading Zero Count) + @FEATURE: tbm: "tbm"; /// TBM (Trailing Bit Manipulation) - tbm, + @FEATURE: popcnt: "popcnt"; /// POPCNT (Population Count) - popcnt, + @FEATURE: fxsr: "fxsr"; /// FXSR (Floating-point context fast save and restor) - fxsr, + @FEATURE: xsave: "xsave"; /// XSAVE (Save Processor Extended States) - xsave, + @FEATURE: xsaveopt: "xsaveopt"; /// XSAVEOPT (Save Processor Extended States Optimized) - xsaveopt, + @FEATURE: xsaves: "xsaves"; /// XSAVES (Save Processor Extended States Supervisor) - xsaves, + @FEATURE: xsavec: "xsavec"; /// XSAVEC (Save Processor Extended States Compacted) - xsavec, - /// CMPXCH16B, a 16-byte compare-and-swap instruction - cmpxchg16b, + @FEATURE: cmpxchg16b: "cmpxchg16b"; + /// CMPXCH16B (16-byte compare-and-swap instruction) + @FEATURE: adx: "adx"; /// ADX, Intel ADX (Multi-Precision Add-Carry Instruction Extensions) - adx, + @FEATURE: rtm: "rtm"; /// RTM, Intel (Restricted Transactional Memory) - rtm, } diff --git a/library/stdarch/crates/std_detect/src/detect/macros.rs b/library/stdarch/crates/std_detect/src/detect/macros.rs new file mode 100644 index 00000000000..09f9f524b52 --- /dev/null +++ b/library/stdarch/crates/std_detect/src/detect/macros.rs @@ -0,0 +1,74 @@ +macro_rules! features { + ( + @TARGET: $target:ident; + @MACRO_NAME: $macro_name:ident; + @MACRO_ATTRS: $(#[$macro_attrs:meta])* + $(@BIND_FEATURE_NAME: $bind_feature:tt; $feature_impl:tt; )* + $(@NO_RUNTIME_DETECTION: $nort_feature:tt; )* + $(@FEATURE: $feature:ident: $feature_lit:tt; $(#[$feature_comment:meta])*)* + ) => { + #[macro_export] + $(#[$macro_attrs])* + #[allow_internal_unstable(stdsimd_internal,stdsimd)] + macro_rules! $macro_name { + $( + ($feature_lit) => { + cfg!(target_feature = $feature_lit) || + $crate::detect::check_for($crate::detect::Feature::$feature) + }; + )* + $( + ($bind_feature) => { $macro_name!($feature_impl); }; + )* + $( + ($nort_feature) => { + compile_error!( + concat!( + stringify!(nort_feature), + " feature cannot be detected at run-time" + ) + ) + }; + )* + ($t:tt,) => { + $macro_name!($t); + }; + ($t:tt) => { + compile_error!( + concat!( + concat!("unknown ", stringify!($target)), + concat!(" target feature: ", $t) + ) + ) + }; + } + + /// Each variant denotes a position in a bitset for a particular feature. + /// + /// PLEASE: do not use this, it is an implementation detail subject + /// to change. + #[doc(hidden)] + #[allow(non_camel_case_types)] + #[derive(Copy, Clone)] + #[repr(u8)] + #[unstable(feature = "stdsimd_internal", issue = "0")] + pub enum Feature { + $( + $(#[$feature_comment])* + $feature, + )* + + // Do not add variants after last: + _last + } + + impl Feature { + pub fn to_str(self) -> &'static str { + match self { + $(Feature::$feature => $feature_lit,)* + Feature::_last => unreachable!(), + } + } + } + }; +} diff --git a/library/stdarch/crates/std_detect/src/detect/mod.rs b/library/stdarch/crates/std_detect/src/detect/mod.rs index 3e00c205547..21062782b71 100644 --- a/library/stdarch/crates/std_detect/src/detect/mod.rs +++ b/library/stdarch/crates/std_detect/src/detect/mod.rs @@ -20,6 +20,9 @@ #[macro_use] mod error_macros; +#[macro_use] +mod macros; + cfg_if! { if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] { #[path = "arch/x86.rs"] @@ -96,3 +99,36 @@ cfg_if! { pub fn check_for(x: Feature) -> bool { cache::test(x as u32, self::os::detect_features) } + +/// 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_() +} diff --git a/library/stdarch/crates/std_detect/src/detect/os/x86.rs b/library/stdarch/crates/std_detect/src/detect/os/x86.rs index d9d286071a2..6daeb2d1a1e 100644 --- a/library/stdarch/crates/std_detect/src/detect/os/x86.rs +++ b/library/stdarch/crates/std_detect/src/detect/os/x86.rs @@ -126,7 +126,7 @@ pub(crate) fn detect_features() -> cache::Initializer { enable(proc_info_edx, 26, Feature::sse2); enable(extended_features_ebx, 29, Feature::sha); - enable(extended_features_ebx, 3, Feature::bmi); + enable(extended_features_ebx, 3, Feature::bmi1); enable(extended_features_ebx, 8, Feature::bmi2); // `XSAVE` and `AVX` support: @@ -203,17 +203,17 @@ pub(crate) fn detect_features() -> cache::Initializer { if os_avx512_support { enable(extended_features_ebx, 16, Feature::avx512f); enable(extended_features_ebx, 17, Feature::avx512dq); - enable(extended_features_ebx, 21, Feature::avx512_ifma); + enable(extended_features_ebx, 21, Feature::avx512ifma); enable(extended_features_ebx, 26, Feature::avx512pf); enable(extended_features_ebx, 27, Feature::avx512er); enable(extended_features_ebx, 28, Feature::avx512cd); enable(extended_features_ebx, 30, Feature::avx512bw); enable(extended_features_ebx, 31, Feature::avx512vl); - enable(extended_features_ecx, 1, Feature::avx512_vbmi); + enable(extended_features_ecx, 1, Feature::avx512vbmi); enable( extended_features_ecx, 14, - Feature::avx512_vpopcntdq, + Feature::avx512vpopcntdq, ); } } @@ -227,7 +227,8 @@ pub(crate) fn detect_features() -> cache::Initializer { // // The `is_x86_feature_detected!("lzcnt")` macro then // internally maps to Feature::abm. - enable(extended_proc_info_ecx, 5, Feature::abm); + enable(extended_proc_info_ecx, 5, Feature::lzcnt); + // As Hygon Dhyana originates from AMD technology and shares most of the architecture with // AMD's family 17h, but with different CPU Vendor ID("HygonGenuine")/Family series // number(Family 18h). diff --git a/library/stdarch/crates/std_detect/tests/cpu-detection.rs b/library/stdarch/crates/std_detect/tests/cpu-detection.rs index d0c9901c4cd..d441f4e1eff 100644 --- a/library/stdarch/crates/std_detect/tests/cpu-detection.rs +++ b/library/stdarch/crates/std_detect/tests/cpu-detection.rs @@ -1,7 +1,6 @@ #![feature(stdsimd)] #![allow(clippy::option_unwrap_used, clippy::use_debug, clippy::print_stdout)] - -#[cfg(any( +#![cfg(any( target_arch = "arm", target_arch = "aarch64", target_arch = "x86", @@ -9,10 +8,18 @@ target_arch = "powerpc", target_arch = "powerpc64" ))] + #[macro_use] extern crate std_detect; #[test] +fn all() { + for (f, e) in std_detect::detect::features() { + println!("{}: {}", f, e); + } +} + +#[test] #[cfg(all(target_arch = "arm", any(target_os = "linux", target_os = "android")))] fn arm_linux() { println!("neon: {}", is_arm_feature_detected!("neon")); @@ -73,17 +80,17 @@ fn x86_all() { println!("sha: {:?}", is_x86_feature_detected!("sha")); println!("avx: {:?}", is_x86_feature_detected!("avx")); println!("avx2: {:?}", is_x86_feature_detected!("avx2")); - println!("avx512f {:?}", is_x86_feature_detected!("avx512f")); - println!("avx512cd {:?}", is_x86_feature_detected!("avx512cd")); - println!("avx512er {:?}", is_x86_feature_detected!("avx512er")); - println!("avx512pf {:?}", is_x86_feature_detected!("avx512pf")); - println!("avx512bw {:?}", is_x86_feature_detected!("avx512bw")); - println!("avx512dq {:?}", is_x86_feature_detected!("avx512dq")); - println!("avx512vl {:?}", is_x86_feature_detected!("avx512vl")); - println!("avx512_ifma {:?}", is_x86_feature_detected!("avx512ifma")); - println!("avx512_vbmi {:?}", is_x86_feature_detected!("avx512vbmi")); + println!("avx512f: {:?}", is_x86_feature_detected!("avx512f")); + println!("avx512cd: {:?}", is_x86_feature_detected!("avx512cd")); + println!("avx512er: {:?}", is_x86_feature_detected!("avx512er")); + println!("avx512pf: {:?}", is_x86_feature_detected!("avx512pf")); + println!("avx512bw: {:?}", is_x86_feature_detected!("avx512bw")); + println!("avx512dq: {:?}", is_x86_feature_detected!("avx512dq")); + println!("avx512vl: {:?}", is_x86_feature_detected!("avx512vl")); + println!("avx512ifma: {:?}", is_x86_feature_detected!("avx512ifma")); + println!("avx512vbmi: {:?}", is_x86_feature_detected!("avx512vbmi")); println!( - "avx512_vpopcntdq {:?}", + "avx512vpopcntdq: {:?}", is_x86_feature_detected!("avx512vpopcntdq") ); println!("f16c: {:?}", is_x86_feature_detected!("f16c")); |
