diff --git a/Cargo.lock b/Cargo.lock index 8103283e..76d03f87 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -33,9 +33,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" [[package]] name = "cmov" @@ -64,14 +64,15 @@ dependencies = [ name = "cpufeatures" version = "0.3.0-pre" dependencies = [ + "cfg-if", "libc", ] [[package]] name = "crypto-common" -version = "0.2.0-rc.2" +version = "0.2.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "170d71b5b14dec99db7739f6fc7d6ec2db80b78c3acb77db48392ccc3d8a9ea0" +checksum = "8a23fa214dea9efd4dacee5a5614646b30216ae0f05d4bb51bafb50e9da1c5be" dependencies = [ "hybrid-array", ] @@ -85,9 +86,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.11.0-pre.10" +version = "0.11.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c478574b20020306f98d61c8ca3322d762e1ff08117422ac6106438605ea516" +checksum = "460dd7f37e4950526b54a5a6b1f41b6c8e763c58eb9a8fc8fc05ba5c2f44ca7b" dependencies = [ "block-buffer 0.11.0-rc.4 (registry+https://github.com/rust-lang/crates.io-index)", "const-oid", @@ -163,15 +164,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.172" +version = "0.2.175" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" +checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "opaque-debug" @@ -179,9 +180,9 @@ version = "0.4.0-pre" [[package]] name = "prettyplease" -version = "0.2.32" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "664ec5419c51e34154eec046ebcba56312d5a2fc3b09a06da188e1ad21afadf6" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", "syn", @@ -189,9 +190,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" dependencies = [ "unicode-ident", ] @@ -233,9 +234,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.143" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" dependencies = [ "itoa", "memchr", @@ -245,9 +246,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.11.0-pre.5" +version = "0.11.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b4241d1a56954dce82cecda5c8e9c794eef6f53abe5e5216bac0a0ea71ffa7" +checksum = "aa1d2e6b3cc4e43a8258a9a3b17aa5dfd2cc5186c7024bba8a64aa65b2c71a59" dependencies = [ "cfg-if", "cpufeatures 0.2.17", @@ -256,9 +257,9 @@ dependencies = [ [[package]] name = "sha3" -version = "0.11.0-pre.5" +version = "0.11.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bc997d7a5fa67cc1e352b2001124d28edb948b4e7a16567f9b3c1e51952524" +checksum = "b9e6a92fd180fd205defdc0b78288ce847c7309d329fd6647a814567e67db50e" dependencies = [ "digest", "keccak", @@ -266,9 +267,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.100" +version = "2.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" dependencies = [ "proc-macro2", "quote", diff --git a/cpufeatures/Cargo.toml b/cpufeatures/Cargo.toml index b3603d0a..fc2e61bc 100644 --- a/cpufeatures/Cargo.toml +++ b/cpufeatures/Cargo.toml @@ -15,6 +15,9 @@ readme = "README.md" edition = "2024" rust-version = "1.85" +[dependencies] +cfg-if = "1" + [target.'cfg(all(target_arch = "aarch64", target_vendor = "apple"))'.dependencies] libc = { version = "0.2.155", default-features = false } diff --git a/cpufeatures/src/aarch64.rs b/cpufeatures/src/aarch64.rs deleted file mode 100644 index 690fe221..00000000 --- a/cpufeatures/src/aarch64.rs +++ /dev/null @@ -1,169 +0,0 @@ -//! ARM64 CPU feature detection support. -//! -//! Unfortunately ARM instructions to detect CPU features cannot be called from -//! unprivileged userspace code, so this implementation relies on OS-specific -//! APIs for feature detection. - -// Evaluate the given `$body` expression any of the supplied target features -// are not enabled. Otherwise returns true. -#[macro_export] -#[doc(hidden)] -macro_rules! __unless_target_features { - ($($tf:tt),+ => $body:expr ) => { - { - #[cfg(not(all($(target_feature=$tf,)*)))] - $body - - #[cfg(all($(target_feature=$tf,)*))] - true - } - }; -} - -// Linux runtime detection of target CPU features using `getauxval`. -#[cfg(any(target_os = "linux", target_os = "android"))] -#[macro_export] -#[doc(hidden)] -macro_rules! __detect_target_features { - ($($tf:tt),+) => {{ - let hwcaps = $crate::aarch64::getauxval_hwcap(); - $($crate::check!(hwcaps, $tf) & )+ true - }}; -} - -/// Linux helper function for calling `getauxval` to get `AT_HWCAP`. -#[cfg(any(target_os = "linux", target_os = "android"))] -pub fn getauxval_hwcap() -> u64 { - unsafe { libc::getauxval(libc::AT_HWCAP) } -} - -// Apple platform's runtime detection of target CPU features using `sysctlbyname`. -#[cfg(target_vendor = "apple")] -#[macro_export] -#[doc(hidden)] -macro_rules! __detect_target_features { - ($($tf:tt),+) => {{ - $($crate::check!($tf) & )+ true - }}; -} - -// Linux `expand_check_macro` -#[cfg(any(target_os = "linux", target_os = "android"))] -macro_rules! __expand_check_macro { - ($(($name:tt, $hwcap:ident)),* $(,)?) => { - #[macro_export] - #[doc(hidden)] - macro_rules! check { - $( - ($hwcaps:expr, $name) => { - (($hwcaps & $crate::aarch64::hwcaps::$hwcap) != 0) - }; - )* - } - }; -} - -// Linux `expand_check_macro` -#[cfg(any(target_os = "linux", target_os = "android"))] -__expand_check_macro! { - ("aes", AES), // Enable AES support. - ("dit", DIT), // Enable DIT support. - ("sha2", SHA2), // Enable SHA1 and SHA256 support. - ("sha3", SHA3), // Enable SHA512 and SHA3 support. - ("sm4", SM4), // Enable SM3 and SM4 support. -} - -/// Linux hardware capabilities mapped to target features. -/// -/// Note that LLVM target features are coarser grained than what Linux supports -/// and imply more capabilities under each feature. This module attempts to -/// provide that mapping accordingly. -/// -/// See this issue for more info: -#[cfg(any(target_os = "linux", target_os = "android"))] -pub mod hwcaps { - use libc::c_ulong; - - pub const AES: c_ulong = libc::HWCAP_AES | libc::HWCAP_PMULL; - pub const DIT: c_ulong = libc::HWCAP_DIT; - pub const SHA2: c_ulong = libc::HWCAP_SHA2; - pub const SHA3: c_ulong = libc::HWCAP_SHA3 | libc::HWCAP_SHA512; - pub const SM4: c_ulong = libc::HWCAP_SM3 | libc::HWCAP_SM4; -} - -// Apple OS (macOS, iOS, watchOS, and tvOS) `check!` macro. -// -// NOTE: several of these instructions (e.g. `aes`, `sha2`) can be assumed to -// be present on all Apple ARM64 hardware. -// -// Newer CPU instructions now have nodes within sysctl's `hw.optional` -// namespace, however the ones that do not can safely be assumed to be -// present on all Apple ARM64 devices, now and for the foreseeable future. -// -// See discussion on this issue for more information: -// -#[cfg(target_vendor = "apple")] -#[macro_export] -#[doc(hidden)] -macro_rules! check { - ("aes") => { - true - }; - ("dit") => { - // https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Enable-DIT-for-constant-time-cryptographic-operations - unsafe { - $crate::aarch64::sysctlbyname(b"hw.optional.arm.FEAT_DIT\0") - } - }; - ("sha2") => { - true - }; - ("sha3") => { - unsafe { - // `sha3` target feature implies SHA-512 as well - $crate::aarch64::sysctlbyname(b"hw.optional.armv8_2_sha512\0") - && $crate::aarch64::sysctlbyname(b"hw.optional.armv8_2_sha3\0") - } - }; - ("sm4") => { - false - }; -} - -/// Apple helper function for calling `sysctlbyname`. -#[cfg(target_vendor = "apple")] -pub unsafe fn sysctlbyname(name: &[u8]) -> bool { - assert_eq!( - name.last().cloned(), - Some(0), - "name is not NUL terminated: {:?}", - name - ); - - let mut value: u32 = 0; - let mut size = core::mem::size_of::(); - - let rc = unsafe { - libc::sysctlbyname( - name.as_ptr() as *const i8, - &mut value as *mut _ as *mut libc::c_void, - &mut size, - core::ptr::null_mut(), - 0, - ) - }; - - assert_eq!(size, 4, "unexpected sysctlbyname(3) result size"); - assert_eq!(rc, 0, "sysctlbyname returned error code: {}", rc); - value != 0 -} - -// On other targets, runtime CPU feature detection is unavailable -#[cfg(not(any(target_vendor = "apple", target_os = "linux", target_os = "android",)))] -#[macro_export] -#[doc(hidden)] -macro_rules! __detect_target_features { - ($($tf:tt),+) => { - false - }; -} diff --git a/cpufeatures/src/aarch64_apple.rs b/cpufeatures/src/aarch64_apple.rs new file mode 100644 index 00000000..5988cb9b --- /dev/null +++ b/cpufeatures/src/aarch64_apple.rs @@ -0,0 +1,84 @@ +//! ARM64 CPU feature detection support. +//! +//! Unfortunately ARM instructions to detect CPU features cannot be called from +//! unprivileged userspace code, so this implementation relies on OS-specific +//! APIs for feature detection. + +use core::ffi::CStr; + +// Evaluate the given `$body` expression any of the supplied target features +// are not enabled. Otherwise returns true. +#[macro_export] +#[doc(hidden)] +macro_rules! __can_detect { + ($($tf:tt),+) => { + true + }; +} + +// Apple platform's runtime detection of target CPU features using `sysctlbyname`. +#[macro_export] +#[doc(hidden)] +macro_rules! __detect { + ($($tf:tt),+) => {{ + $($crate::check!($tf) & )+ true + }}; +} + +// Apple OS (macOS, iOS, watchOS, and tvOS) `check!` macro. +// +// NOTE: several of these instructions (e.g. `aes`, `sha2`) can be assumed to +// be present on all Apple ARM64 hardware. +// +// Newer CPU instructions now have nodes within sysctl's `hw.optional` +// namespace, however the ones that do not can safely be assumed to be +// present on all Apple ARM64 devices, now and for the foreseeable future. +// +// See discussion on this issue for more information: +// +#[macro_export] +#[doc(hidden)] +macro_rules! check { + ("aes") => { + true + }; + ("dit") => { + // https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Enable-DIT-for-constant-time-cryptographic-operations + unsafe { + $crate::aarch64_apple::sysctlbyname(c"hw.optional.arm.FEAT_DIT") + } + }; + ("sha2") => { + true + }; + ("sha3") => { + unsafe { + // `sha3` target feature implies SHA-512 as well + $crate::aarch64_apple::sysctlbyname(c"hw.optional.armv8_2_sha512") + && $crate::aarch64_apple::sysctlbyname(c"hw.optional.armv8_2_sha3") + } + }; + ("sm4") => { + false + }; +} + +/// Apple helper function for calling `sysctlbyname`. +pub unsafe fn sysctlbyname(name: &CStr) -> bool { + let mut value: u32 = 0; + let mut size = core::mem::size_of::(); + + let rc = unsafe { + libc::sysctlbyname( + name.as_ptr(), + &mut value as *mut _ as *mut libc::c_void, + &mut size, + core::ptr::null_mut(), + 0, + ) + }; + + assert_eq!(size, 4, "unexpected sysctlbyname(3) result size"); + assert_eq!(rc, 0, "sysctlbyname returned error code: {}", rc); + value != 0 +} diff --git a/cpufeatures/src/aarch64_linux.rs b/cpufeatures/src/aarch64_linux.rs new file mode 100644 index 00000000..4b65a5b1 --- /dev/null +++ b/cpufeatures/src/aarch64_linux.rs @@ -0,0 +1,71 @@ +//! ARM64 CPU feature detection support. +//! +//! Unfortunately ARM instructions to detect CPU features cannot be called from +//! unprivileged userspace code, so this implementation relies on OS-specific +//! APIs for feature detection. + +// Evaluate the given `$body` expression any of the supplied target features +// are not enabled. Otherwise returns true. +#[macro_export] +#[doc(hidden)] +macro_rules! __can_detect { + ($($tf:tt),+) => { + true + }; +} + +// Linux runtime detection of target CPU features using `getauxval`. +#[macro_export] +#[doc(hidden)] +macro_rules! __detect { + ($($tf:tt),+) => {{ + let hwcaps = $crate::aarch64_linux::getauxval_hwcap(); + $($crate::check!(hwcaps, $tf) & )+ true + }}; +} + +/// Linux helper function for calling `getauxval` to get `AT_HWCAP`. +pub fn getauxval_hwcap() -> u64 { + unsafe { libc::getauxval(libc::AT_HWCAP) } +} + +// Linux `expand_check_macro` +macro_rules! __expand_check_macro { + ($(($name:tt, $hwcap:ident)),* $(,)?) => { + #[macro_export] + #[doc(hidden)] + macro_rules! check { + $( + ($hwcaps:expr, $name) => { + (($hwcaps & $crate::aarch64_linux::hwcaps::$hwcap) != 0) + }; + )* + } + }; +} + +// Linux `expand_check_macro` +__expand_check_macro! { + ("aes", AES), // Enable AES support. + ("dit", DIT), // Enable DIT support. + ("sha2", SHA2), // Enable SHA1 and SHA256 support. + ("sha3", SHA3), // Enable SHA512 and SHA3 support. + ("sm4", SM4), // Enable SM3 and SM4 support. +} + +/// Linux hardware capabilities mapped to target features. +/// +/// Note that LLVM target features are coarser grained than what Linux supports +/// and imply more capabilities under each feature. This module attempts to +/// provide that mapping accordingly. +/// +/// See this issue for more info: +pub mod hwcaps { + use libc::c_ulong; + + pub const AES: c_ulong = libc::HWCAP_AES | libc::HWCAP_PMULL; + pub const DIT: c_ulong = libc::HWCAP_DIT; + pub const SHA2: c_ulong = libc::HWCAP_SHA2; + pub const SHA3: c_ulong = libc::HWCAP_SHA3 | libc::HWCAP_SHA512; + pub const SM4: c_ulong = libc::HWCAP_SM3 | libc::HWCAP_SM4; +} diff --git a/cpufeatures/src/fallback.rs b/cpufeatures/src/fallback.rs new file mode 100644 index 00000000..7c56111a --- /dev/null +++ b/cpufeatures/src/fallback.rs @@ -0,0 +1,17 @@ +//! Compile-time fallback based on `cfg(target_feature = "..")` + +#[macro_export] +#[doc(hidden)] +macro_rules! __can_detect { + ($($tf:tt),+) => { + false + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __detect { + ($($tf:tt),+) => { + false + }; +} diff --git a/cpufeatures/src/lib.rs b/cpufeatures/src/lib.rs index d8d4322d..c1cb0f1a 100644 --- a/cpufeatures/src/lib.rs +++ b/cpufeatures/src/lib.rs @@ -5,30 +5,32 @@ html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" )] -#[cfg(not(miri))] -#[cfg(target_arch = "aarch64")] -#[doc(hidden)] -pub mod aarch64; - -#[cfg(not(miri))] -#[cfg(target_arch = "loongarch64")] -#[doc(hidden)] -pub mod loongarch64; - -#[cfg(not(miri))] -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -mod x86; - -#[cfg(miri)] -mod miri; - -#[cfg(not(any( - target_arch = "aarch64", - target_arch = "loongarch64", - target_arch = "x86", - target_arch = "x86_64" -)))] -compile_error!("This crate works only on `aarch64`, `loongarch64`, `x86`, and `x86-64` targets."); +cfg_if::cfg_if!( + if #[cfg(miri)] { + mod fallback; + } else if #[cfg(all(target_arch = "aarch64", any(target_os = "linux", target_os = "android")))] { + #[doc(hidden)] + pub mod aarch64_linux; + } else if #[cfg(all(target_arch = "aarch64", target_vendor = "apple"))] { + #[doc(hidden)] + pub mod aarch64_apple; + } else if #[cfg(all(target_arch = "loongarch64", target_os = "linux"))] { + #[doc(hidden)] + pub mod loongarch64_linux; + } else if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] { + // CPUID is not available on SGX. Freestanding and UEFI targets + // do not support SIMD features with default compilation flags. + cfg_if::cfg_if!( + if #[cfg(any(target_env = "sgx", target_os = "none", target_os = "uefi"))] { + mod fallback; + } else { + mod x86; + } + ); + } else { + mod fallback; + } +); /// Create module with CPU feature detection code. #[macro_export] @@ -37,9 +39,18 @@ macro_rules! new { mod $mod_name { use core::sync::atomic::{AtomicU8, Ordering::Relaxed}; - const UNINIT: u8 = u8::max_value(); + const UNINIT: u8 = u8::MAX; static STORAGE: AtomicU8 = AtomicU8::new(UNINIT); + /// Performs run-time detection of the `$tf` target features, + /// stores result in `STORAGE` and returns it to the caller. + #[cold] + fn init_storage() -> bool { + let res = $crate::__detect!($($tf),+); + STORAGE.store(res as u8, Relaxed); + res + } + /// Initialization token #[derive(Copy, Clone, Debug)] pub struct InitToken(()); @@ -48,10 +59,12 @@ macro_rules! new { /// Get initialized value #[inline(always)] pub fn get(&self) -> bool { - $crate::__unless_target_features! { - $($tf),+ => { - STORAGE.load(Relaxed) == 1 - } + if cfg!(all($(target_feature=$tf,)*)) { + true + } else if $crate::__can_detect!($($tf),+) { + STORAGE.load(Relaxed) == 1 + } else { + false } } } @@ -60,24 +73,16 @@ macro_rules! new { /// initializing underlying storage if needed. #[inline] pub fn init_get() -> (InitToken, bool) { - let res = $crate::__unless_target_features! { - $($tf),+ => { - #[cold] - fn init_inner() -> bool { - let res = $crate::__detect_target_features!($($tf),+); - STORAGE.store(res as u8, Relaxed); - res - } - - // Relaxed ordering is fine, as we only have a single atomic variable. - let val = STORAGE.load(Relaxed); - - if val == UNINIT { - init_inner() - } else { - val == 1 - } + let res = if cfg!(all($(target_feature=$tf,)*)) { + true + } else if $crate::__can_detect!($($tf),+) { + // Relaxed ordering is fine, as we only have a single atomic variable. + match STORAGE.load(Relaxed) { + UNINIT => init_storage(), + val => val == 1, } + } else { + false }; (InitToken(()), res) diff --git a/cpufeatures/src/loongarch64.rs b/cpufeatures/src/loongarch64_linux.rs similarity index 83% rename from cpufeatures/src/loongarch64.rs rename to cpufeatures/src/loongarch64_linux.rs index e3155387..a307e261 100644 --- a/cpufeatures/src/loongarch64.rs +++ b/cpufeatures/src/loongarch64_linux.rs @@ -6,23 +6,16 @@ // are not enabled. Otherwise returns true. #[macro_export] #[doc(hidden)] -macro_rules! __unless_target_features { - ($($tf:tt),+ => $body:expr ) => { - { - #[cfg(not(all($(target_feature=$tf,)*)))] - $body - - #[cfg(all($(target_feature=$tf,)*))] - true - } +macro_rules! __can_detect { + ($($tf:tt),+) => { + true }; } // Linux runtime detection of target CPU features using `getauxval`. -#[cfg(target_os = "linux")] #[macro_export] #[doc(hidden)] -macro_rules! __detect_target_features { +macro_rules! __detect { ($($tf:tt),+) => {{ let cpucfg1: usize; let cpucfg2: usize; @@ -38,17 +31,11 @@ macro_rules! __detect_target_features { options(pure, nomem, preserves_flags, nostack) ); } - let hwcaps = $crate::loongarch64::getauxval_hwcap(); + let hwcaps = unsafe { libc::getauxval(libc::AT_HWCAP) }; $($crate::check!(cpucfg1, cpucfg2, cpucfg3, hwcaps, $tf) & )+ true }}; } -/// Linux helper function for calling `getauxval` to get `AT_HWCAP`. -#[cfg(target_os = "linux")] -pub fn getauxval_hwcap() -> u64 { - unsafe { libc::getauxval(libc::AT_HWCAP) } -} - #[macro_export] #[doc(hidden)] macro_rules! check { @@ -103,7 +90,6 @@ macro_rules! check { /// Note that LLVM target features are coarser grained than what Linux supports /// and imply more capabilities under each feature. This module attempts to /// provide that mapping accordingly. -#[cfg(target_os = "linux")] pub mod hwcaps { use libc::c_ulong; @@ -116,13 +102,3 @@ pub mod hwcaps { pub const LBT_ARM: c_ulong = libc::HWCAP_LOONGARCH_LBT_ARM; pub const LBT_MIPS: c_ulong = libc::HWCAP_LOONGARCH_LBT_MIPS; } - -// On other targets, runtime CPU feature detection is unavailable -#[cfg(not(target_os = "linux"))] -#[macro_export] -#[doc(hidden)] -macro_rules! __detect_target_features { - ($($tf:tt),+) => { - false - }; -} diff --git a/cpufeatures/src/miri.rs b/cpufeatures/src/miri.rs deleted file mode 100644 index 8dff21c1..00000000 --- a/cpufeatures/src/miri.rs +++ /dev/null @@ -1,20 +0,0 @@ -//! Minimal miri support. -//! -//! Miri is an interpreter, and though it tries to emulate the target CPU -//! it does not support any target features. - -#[macro_export] -#[doc(hidden)] -macro_rules! __unless_target_features { - ($($tf:tt),+ => $body:expr ) => { - false - }; -} - -#[macro_export] -#[doc(hidden)] -macro_rules! __detect_target_features { - ($($tf:tt),+) => { - false - }; -} diff --git a/cpufeatures/src/x86.rs b/cpufeatures/src/x86.rs index dc83f2fd..faa26977 100644 --- a/cpufeatures/src/x86.rs +++ b/cpufeatures/src/x86.rs @@ -10,44 +10,22 @@ /// on these targets unless *all* supplied target features are enabled. #[macro_export] #[doc(hidden)] -macro_rules! __unless_target_features { - ($($tf:tt),+ => $body:expr ) => {{ - #[cfg(not(all($(target_feature=$tf,)*)))] - { - #[cfg(not(any(target_env = "sgx", target_os = "none", target_os = "uefi")))] - $body - - // CPUID is not available on SGX. Freestanding and UEFI targets - // do not support SIMD features with default compilation flags. - #[cfg(any(target_env = "sgx", target_os = "none", target_os = "uefi"))] - false - } - - #[cfg(all($(target_feature=$tf,)*))] - true - }}; +macro_rules! __can_detect { + ($($tf:tt),+) => { true }; } /// Use CPUID to detect the presence of all supplied target features. #[macro_export] #[doc(hidden)] -macro_rules! __detect_target_features { +macro_rules! __detect { ($($tf:tt),+) => {{ #[cfg(target_arch = "x86")] use core::arch::x86::{__cpuid, __cpuid_count, CpuidResult}; #[cfg(target_arch = "x86_64")] use core::arch::x86_64::{__cpuid, __cpuid_count, CpuidResult}; - unsafe fn cpuid(leaf: u32) -> CpuidResult { - __cpuid(leaf) - } - - unsafe fn cpuid_count(leaf: u32, sub_leaf: u32) -> CpuidResult { - __cpuid_count(leaf, sub_leaf) - } - let cr = unsafe { - [cpuid(1), cpuid_count(7, 0), cpuid_count(7, 1)] + [__cpuid(1), __cpuid_count(7, 0), __cpuid_count(7, 1)] }; $($crate::check!(cr, $tf) & )+ true