1#![unstable(feature = "kernel_feature_detect", issue = "none")]
2
3#[cfg(target_arch = "x86_64")]
4mod x86;
5
6#[cfg(target_arch = "x86_64")]
7#[doc(hidden)]
8pub use x86::*;
9
10mod cache;
11
12macro_rules! features_macro {
13 (
14 @TARGET: $target:ident;
15 @CFG: $cfg:meta;
16 @MACRO_NAME: $macro_name:ident;
17 @MACRO_ATTRS: $(#[$macro_attrs:meta])*
18 $(@BIND_FEATURE_NAME: $bind_feature:tt; $feature_impl:tt;)*
19 $(@FEATURE: $feature:ident: $feature_lit:tt;)*
20 ) => {
21 #[macro_export]
22 $(#[$macro_attrs])*
23 macro_rules! $macro_name {
24 $(
25 ($feature_lit) => {
26 $crate::detect::__detected::$feature()
27 };
28 )*
29 $(
30 ($bind_feature) => {
31 $crate::detect::__detected::$feature_impl()
32 };
33 )*
34 ($t:tt,) => {
35 $crate::$macro_name!($t);
36 };
37 ($t:tt) => {
38 compile_error!(
39 concat!(
40 concat!("unknown ", stringify!($target)),
41 concat!(" target feature: ", $t)
42 )
43 )
44 };
45 }
46
47 #[doc(hidden)]
48 #[allow(non_camel_case_types)]
49 #[derive(Copy, Clone, Debug)]
50 #[repr(u32)]
51 #[cfg($cfg)]
52 pub(crate) enum Feature {
53 $(
54 $feature,
55 )*
56 _last
57 }
58
59 #[cfg($cfg)]
60 impl Feature {
61 pub(crate) fn to_str(self) -> &'static str {
62 match self {
63 $(Feature::$feature => $feature_lit,)*
64 Feature::_last => unreachable!(),
65 }
66 }
67 }
68
69 #[doc(hidden)]
70 #[cfg($cfg)]
71 pub mod __detected {
72 $(
73 #[inline]
74 #[doc(hidden)]
75 #[stable(feature = "kernel_core_api", since = "1.0.0")]
76 pub fn $feature() -> bool {
77 $crate::detect::cache::test($crate::detect::Feature::$feature)
78 }
79 )*
80 }
81 };
82}
83
84pub(crate) use features_macro;
85
86pub fn features() -> impl Iterator<Item = (&'static str, bool)> {
87 (0_u32..Feature::_last as u32).map(|discriminant: u32| {
88 let f: Feature = unsafe { core::mem::transmute(discriminant) };
89 let name: &'static str = f.to_str();
90 let enabled: bool = cache::test(f);
91 (name, enabled)
92 })
93}