proof_token/
proof-token.rs1#![allow(unused, unused_macros, unused_imports)]
6
7use target_features::TargetFeatures;
8
9mod unconstructible {
11 pub struct Unconstructible(());
12 impl Unconstructible {
13 pub unsafe fn new() -> Self {
14 Self(())
15 }
16 }
17}
18use unconstructible::Unconstructible;
19
20unsafe trait Proof: Sized {
26 const TARGET: TargetFeatures;
28
29 fn detect() -> Option<Self>;
31
32 unsafe fn assume() -> Self;
37}
38
39macro_rules! make_target_proof {
41 { $vis:vis struct $proof:ident($($feature:tt),*); } => {
42 $vis struct $proof(Unconstructible);
43
44 unsafe impl Proof for $proof {
45 const TARGET: TargetFeatures =
47 TargetFeatures::enabled_for_target()
48 .with(target_features::target_features!($($feature),*));
49
50 fn detect() -> Option<Self> {
51 if true $(&& is_x86_feature_detected!($feature))* {
52 unsafe { Some(Self::assume()) }
53 } else {
54 None
55 }
56 }
57
58 unsafe fn assume() -> Self {
59 Self(Unconstructible::new())
60 }
61 }
62 }
63}
64
65#[cfg(target_arch = "x86_64")]
67fn safe_avx_fn<P: Proof>(_: P) {
68 #[target_feature(enable = "avx")]
69 unsafe fn unsafe_avx_fn() {
70 println!("called an avx function")
71 }
72
73 assert!(
76 P::TARGET.contains(target_features::x86_64::AVX),
77 "avx feature not supported"
78 );
79 unsafe { unsafe_avx_fn() }
80}
81
82#[cfg(target_arch = "x86_64")]
83fn main() {
84 make_target_proof! {
86 struct Avx("avx");
87 }
88 if let Some(proof) = Avx::detect() {
89 safe_avx_fn(proof);
90 }
91
92 make_target_proof! {
94 struct Avx2("avx2");
95 }
96 if let Some(proof) = Avx2::detect() {
97 safe_avx_fn(proof);
98 }
99
100 make_target_proof! {
102 struct Aes("aes");
103 }
104 if let Some(proof) = Aes::detect() {
105 safe_avx_fn(proof);
106 }
107}
108
109#[cfg(not(target_arch = "x86_64"))]
110fn main() {}