1mod arch {
2 #[cfg(target_arch = "aarch64")]
3 pub use core::arch::aarch64::*;
4 #[cfg(target_arch = "wasm32")]
5 pub use core::arch::wasm32::*;
6 #[cfg(target_arch = "x86")]
7 pub use core::arch::x86::*;
8 #[cfg(target_arch = "x86_64")]
9 pub use core::arch::x86_64::*;
10
11 #[cfg(all(feature = "nightly", target_arch = "arm"))]
12 pub use core::arch::arm::*;
13 #[cfg(all(feature = "nightly", target_arch = "mips"))]
14 pub use core::arch::mips::*;
15 #[cfg(all(feature = "nightly", target_arch = "mips64"))]
16 pub use core::arch::mips64::*;
17 #[cfg(all(feature = "nightly", target_arch = "powerpc"))]
18 pub use core::arch::powerpc::*;
19 #[cfg(all(feature = "nightly", target_arch = "powerpc64"))]
20 pub use core::arch::powerpc64::*;
21 #[cfg(all(feature = "nightly", target_arch = "riscv32"))]
22 pub use core::arch::riscv32::*;
23 #[cfg(all(feature = "nightly", target_arch = "riscv64"))]
24 pub use core::arch::riscv64::*;
25 #[cfg(all(feature = "nightly", target_arch = "wasm64"))]
26 pub use core::arch::wasm64::*;
27}
28
29#[allow(unused_macros)]
30macro_rules! delegate {
31 ({$(
32 $(#[$attr: meta])*
33 $(const $($const: lifetime)?)?
34 $(unsafe $($unsafe: lifetime)?)?
35 fn $func: ident $(<$(const $generic: ident: $generic_ty: ty),* $(,)?>)?(
36 $($arg: ident: $ty: ty),* $(,)?
37 ) $(-> $ret: ty)?;
38 )*}) => {
39 $(
40 $(#[$attr])*
41 #[allow(clippy::missing_safety_doc)]
42 #[inline(always)]
43 pub $(const $($const)?)? $(unsafe $($unsafe)?)? fn $func $(<$(const $generic: $generic_ty,)*>)?(self, $($arg: $ty,)*) $(-> $ret)? {
44 #[allow(unused_unsafe)]
45 unsafe { arch::$func $(::<$($generic,)*>)?($($arg,)*) }
46 }
47 )*
48 };
49}
50
51#[cfg(all(feature = "std", any(target_arch = "x86", target_arch = "x86_64")))]
52#[macro_export]
53macro_rules! feature_detected {
54 ($feature: tt) => {
55 ::std::is_x86_feature_detected!($feature)
56 };
57}
58
59#[cfg(all(feature = "std", target_arch = "aarch64"))]
60#[macro_export]
61macro_rules! feature_detected {
62 ($feature: tt) => {
63 ::std::arch::is_aarch64_feature_detected!($feature)
64 };
65}
66
67#[cfg(target_arch = "wasm32")]
68#[macro_export]
69macro_rules! feature_detected {
70 ("simd128") => {
71 $crate::wasm::is_simd128_enabled()
72 };
73 ("relaxed-simd") => {{
74 #[cfg(feature = "relaxed-simd")]
75 {
76 $crate::wasm::is_relaxed_simd_enabled()
77 }
78 #[cfg(not(feature = "relaxed-simd"))]
79 {
80 false
81 }
82 }};
83}
84
85#[cfg(all(
86 not(feature = "std"),
87 any(
88 all(target_arch = "x86", not(target_env = "sgx"), target_feature = "sse"),
89 all(target_arch = "x86_64", not(target_env = "sgx"))
90 )
91))]
92#[doc(hidden)]
93pub mod raw_cpuid_detect;
94
95#[cfg(all(
96 not(feature = "std"),
97 any(
98 all(target_arch = "x86", not(target_env = "sgx"), target_feature = "sse"),
99 all(target_arch = "x86_64", not(target_env = "sgx")),
100 )
101))]
102#[macro_export]
103macro_rules! feature_detected {
104 ($feature: tt) => {
105 cfg!(target_feature = $feature)
106 || $crate::core_arch::raw_cpuid_detect::feature($crate::feature_idx!($feature))
107 };
108}
109
110#[cfg(not(any(
111 target_arch = "wasm32",
112 all(
113 feature = "std",
114 any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64")
115 ),
116 all(any(
117 all(target_arch = "x86", not(target_env = "sgx"), target_feature = "sse"),
118 all(target_arch = "x86_64", not(target_env = "sgx"))
119 )),
120)))]
121#[macro_export]
122macro_rules! feature_detected {
123 ($feature: tt) => {
124 cfg!(target_feature = $feature)
125 };
126}
127
128#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
129#[doc(hidden)]
130#[rustfmt::skip]
131#[macro_export]
132macro_rules! __impl_type {
133 ("aes") => { $crate::core_arch::x86::Aes };
134 ("pclmulqdq") => { $crate::core_arch::x86::Pclmulqdq };
135 ("rdrand") => { $crate::core_arch::x86::Rdrand };
136 ("rdseed") => { $crate::core_arch::x86::Rdseed };
137 ("tsc") => { $crate::core_arch::x86::Tsc };
138 ("mmx") => { $crate::core_arch::x86::Mmx };
139 ("sse") => { $crate::core_arch::x86::Sse };
140 ("sse2") => { $crate::core_arch::x86::Sse2 };
141 ("sse3") => { $crate::core_arch::x86::Sse3 };
142 ("ssse3") => { $crate::core_arch::x86::Ssse3 };
143 ("sse4.1") => { $crate::core_arch::x86::Sse4_1 };
144 ("sse4.2") => { $crate::core_arch::x86::Sse4_2 };
145 ("sse4a") => { $crate::core_arch::x86::Sse4a };
146 ("sha") => { $crate::core_arch::x86::Sha };
147 ("avx") => { $crate::core_arch::x86::Avx };
148 ("avx2") => { $crate::core_arch::x86::Avx2 };
149 ("gfni") => { $crate::core_arch::x86::Gfni };
150 ("vaes") => { $crate::core_arch::x86::Vaes };
151 ("vpclmulqdq") => { $crate::core_arch::x86::Vpclmulqdq };
152 ("avx512f") => { $crate::core_arch::x86::Avx512f };
153 ("avx512cd") => { $crate::core_arch::x86::Avx512cd };
154 ("avx512er") => { $crate::core_arch::x86::Avx512er };
155 ("avx512pf") => { $crate::core_arch::x86::Avx512pf };
156 ("avx512bw") => { $crate::core_arch::x86::Avx512bw };
157 ("avx512dq") => { $crate::core_arch::x86::Avx512dq };
158 ("avx512vl") => { $crate::core_arch::x86::Avx512f };
159 ("avx512ifma") => { $crate::core_arch::x86::Avx512ifma };
160 ("avx512vbmi") => { $crate::core_arch::x86::Avx512vbmi };
161 ("avx512vpopcntdq") => { $crate::core_arch::x86::Avx512vpopcntdq };
162 ("avx512vbmi2") => { $crate::core_arch::x86::Avx512vbmi2 };
163 ("avx512gfni") => { $crate::core_arch::x86::Avx512gfni };
164 ("avx512vaes") => { $crate::core_arch::x86::Avx512vaes };
165 ("avx512vpclmulqdq") => { $crate::core_arch::x86::Avx512vpclmulqdq };
166 ("avx512vnni") => { $crate::core_arch::x86::Avx512vnni };
167 ("avx512bitalg") => { $crate::core_arch::x86::Avx512bitalg };
168 ("avx512bf16") => { $crate::core_arch::x86::Avx512bf16 };
169 ("avx512vp2intersect") => { $crate::core_arch::x86::Avx512vp2intersect };
170 ("f16c") => { $crate::core_arch::x86::F16c };
171 ("fma") => { $crate::core_arch::x86::Fma };
172 ("bmi1") => { $crate::core_arch::x86::Bmi1 };
173 ("bmi2") => { $crate::core_arch::x86::Bmi2 };
174 ("lzcnt") => { $crate::core_arch::x86::Lzcnt };
175 ("tbm") => { $crate::core_arch::x86::Tbm };
176 ("popcnt") => { $crate::core_arch::x86::Popcnt };
177 ("fxsr") => { $crate::core_arch::x86::Fxsr };
178 ("xsave") => { $crate::core_arch::x86::Xsave };
179 ("xsaveopt") => { $crate::core_arch::x86::Xsaveopt };
180 ("xsaves") => { $crate::core_arch::x86::Xsaves };
181 ("xsavec") => { $crate::core_arch::x86::Xsavec };
182 ("cmpxchg16b") => { $crate::core_arch::x86::Cmpxchg16b };
183 ("adx") => { $crate::core_arch::x86::Adx };
184 ("rtm") => { $crate::core_arch::x86::Rtm };
185 ("abm") => { $crate::core_arch::x86::Abm };
186}
187
188#[cfg(target_arch = "aarch64")]
189#[doc(hidden)]
190#[rustfmt::skip]
191#[macro_export]
192macro_rules! __impl_type {
193 ("neon") => { $crate::core_arch::aarch64::Neon };
194 ("pmull") => { $crate::core_arch::aarch64::Pmull };
195 ("fp") => { $crate::core_arch::aarch64::Fp };
196 ("fp16") => { $crate::core_arch::aarch64::Fp16 };
197 ("sve") => { $crate::core_arch::aarch64::Sve };
198 ("crc") => { $crate::core_arch::aarch64::Crc };
199 ("lse") => { $crate::core_arch::aarch64::Lse };
200 ("lse2") => { $crate::core_arch::aarch64::Lse2 };
201 ("rdm") => { $crate::core_arch::aarch64::Rdm };
202 ("rcpc") => { $crate::core_arch::aarch64::Rcpc };
203 ("rcpc2") => { $crate::core_arch::aarch64::Rcpc2 };
204 ("dotprod") => { $crate::core_arch::aarch64::Dotprod };
205 ("tme") => { $crate::core_arch::aarch64::Tme };
206 ("fhm") => { $crate::core_arch::aarch64::Fhm };
207 ("dit") => { $crate::core_arch::aarch64::Dit };
208 ("flagm") => { $crate::core_arch::aarch64::Flagm };
209 ("ssbs") => { $crate::core_arch::aarch64::Ssbs };
210 ("sb") => { $crate::core_arch::aarch64::Sb };
211 ("paca") => { $crate::core_arch::aarch64::Paca };
212 ("pacg") => { $crate::core_arch::aarch64::Pacg };
213 ("dpb") => { $crate::core_arch::aarch64::Dpb };
214 ("dpb2") => { $crate::core_arch::aarch64::Dpb2 };
215 ("sve2") => { $crate::core_arch::aarch64::Sve2 };
216 ("sve2-aes") => { $crate::core_arch::aarch64::Sve2Aes };
217 ("sve2-sm4") => { $crate::core_arch::aarch64::Sve2Sm4 };
218 ("sve2-sha3") => { $crate::core_arch::aarch64::Sve2Sha3 };
219 ("sve2-bitperm") => { $crate::core_arch::aarch64::Sve2Bitperm };
220 ("frintts") => { $crate::core_arch::aarch64::Frintts };
221 ("i8mm") => { $crate::core_arch::aarch64::I8mm };
222 ("f32mm") => { $crate::core_arch::aarch64::F32mm };
223 ("f64mm") => { $crate::core_arch::aarch64::F64mm };
224 ("bf16") => { $crate::core_arch::aarch64::Bf16 };
225 ("rand") => { $crate::core_arch::aarch64::Rand };
226 ("bti") => { $crate::core_arch::aarch64::Bti };
227 ("mte") => { $crate::core_arch::aarch64::Mte };
228 ("jsconv") => { $crate::core_arch::aarch64::Jsconv };
229 ("fcma") => { $crate::core_arch::aarch64::Fcma };
230 ("aes") => { $crate::core_arch::aarch64::Aes };
231 ("sha2") => { $crate::core_arch::aarch64::Sha2 };
232 ("sha3") => { $crate::core_arch::aarch64::Sha3 };
233 ("sm4") => { $crate::core_arch::aarch64::Sm4 };
234 ("asimd") => { $crate::core_arch::aarch64::Asimd };
235}
236
237#[doc(hidden)]
238pub struct Unavailable<const N: usize>;
239
240#[cfg(all(target_arch = "wasm32", feature = "relaxed-simd"))]
241#[doc(hidden)]
242#[rustfmt::skip]
243#[macro_export]
244macro_rules! __impl_type {
245 ("simd128") => { $crate::core_arch::wasm::Simd128 };
246 ("relaxed-simd") => { $crate::core_arch::wasm::RelaxedSimd };
247}
248
249#[cfg(all(target_arch = "wasm32", not(feature = "relaxed-simd")))]
250#[doc(hidden)]
251#[rustfmt::skip]
252#[macro_export]
253macro_rules! __impl_type {
254 ("simd128") => { $crate::core_arch::wasm::Simd128 };
255 ("relaxed-simd") => { $crate::core_arch::Unavailable::<{compile_error!("enable the `relaxed-simd` feature to use wasm relaxed-simd")}> };
256}
257
258#[cfg(not(any(target_arch = "x86_64", target_arch = "x86", target_arch = "aarch64", target_arch = "wasm32")))]
259#[doc(hidden)]
260#[rustfmt::skip]
261#[macro_export]
262macro_rules! __impl_type {
263 ($tt: tt) => { $crate::core_arch::Unavailable::<{compile_error!("unsupported arch")}> }
264}
265
266#[macro_export]
267macro_rules! simd_type {
268 (
269 $(
270 $(#[$attr: meta])*
271 $vis: vis struct $name: ident {
272 $($feature_vis: vis $ident: ident: $feature: tt),* $(,)?
273 }
274 )*
275 ) => {
276 $crate::simd_type!({$(
277 $(#[$attr])*
278 $vis struct $name {
279 $($feature_vis $ident: target_feature!($feature),)*
280 }
281 )*});
282 };
283
284 ({
285 $(
286 $(#[$attr: meta])*
287 $vis: vis struct $name: ident {
288 $($feature_vis: vis $ident: ident: $_: ident!($feature: tt)),* $(,)?
289 }
290 )*
291 }) => {
292 $(
293 #[allow(dead_code)]
294 $(#[$attr])*
295 #[derive(Clone, Copy, Debug)]
296 $vis struct $name{
297 $($feature_vis $ident : $crate::core_arch::__impl_type!($feature),)*
298 }
299
300 #[allow(dead_code)]
301 $(#[$attr])*
302 impl $name {
303 #[inline]
309 pub const unsafe fn new_unchecked() -> Self {
310 #[allow(unused_unsafe)]
311 unsafe {
312 Self{
313 $($ident: <$crate::core_arch::__impl_type!($feature)>::new_unchecked(),)*
314 }
315 }
316 }
317
318 #[inline]
321 pub fn try_new() -> Option<Self> {
322 #[allow(unused_unsafe)]
323 if Self::is_available() {
324 Some(unsafe{Self{
325 $($ident: <$crate::core_arch::__impl_type!($feature)>::new_unchecked(),)*
326 }})
327 } else {
328 None
329 }
330 }
331
332 #[inline(always)]
333 fn __static_available() -> &'static ::core::sync::atomic::AtomicU8 {
334 static AVAILABLE: ::core::sync::atomic::AtomicU8 = ::core::sync::atomic::AtomicU8::new(u8::MAX);
335 &AVAILABLE
336 }
337
338 #[inline]
341 pub fn is_available() -> bool {
342 let mut available = Self::__static_available().load(::core::sync::atomic::Ordering::Relaxed);
343 if available == u8::MAX {
344 available = Self::__detect_is_available() as u8;
345 }
346
347 available != 0
348 }
349
350 #[inline(never)]
351 fn __detect_is_available() -> bool {
352 let out = true $(&& <$crate::core_arch::__impl_type!($feature)>::is_available())*;
353 Self::__static_available().store(out as u8, ::core::sync::atomic::Ordering::Relaxed);
354 out
355 }
356
357 #[inline(always)]
364 pub fn vectorize<F: $crate::NullaryFnOnce>(self, f: F) -> F::Output {
365 $(#[target_feature(enable = $feature)])*
366 #[inline]
367 #[allow(clippy::too_many_arguments)]
368 unsafe fn imp_fastcall<F: $crate::NullaryFnOnce>(
369 f0: ::core::mem::MaybeUninit<::core::primitive::usize>,
370 f1: ::core::mem::MaybeUninit<::core::primitive::usize>,
371 f2: ::core::mem::MaybeUninit<::core::primitive::usize>,
372 f3: ::core::mem::MaybeUninit<::core::primitive::usize>,
373 f4: ::core::mem::MaybeUninit<::core::primitive::usize>,
374 f5: ::core::mem::MaybeUninit<::core::primitive::usize>,
375 f6: ::core::mem::MaybeUninit<::core::primitive::usize>,
376 f7: ::core::mem::MaybeUninit<::core::primitive::usize>,
377 ) -> F::Output {
378 let f: F = core::mem::transmute_copy(&[f0, f1, f2, f3, f4, f5, f6, f7]);
379 f.call()
380 }
381
382 $(#[target_feature(enable = $feature)])*
383 #[inline]
384 unsafe fn imp<F: $crate::NullaryFnOnce>(f: F) -> F::Output {
385 f.call()
386 }
387
388 if const { ::core::mem::size_of::<F>() <= 8 * ::core::mem::size_of::<::core::primitive::usize>() } {
389 union Pad<T> {
390 t: ::core::mem::ManuallyDrop<T>,
391 __u: ::core::mem::MaybeUninit<[usize; 8]>,
392 }
393
394 let f = Pad {
395 t: ::core::mem::ManuallyDrop::new(f),
396 };
397 let p = (&f) as *const _ as *const ::core::mem::MaybeUninit<usize>;
398
399 unsafe {
400 imp_fastcall::<F>(
401 *p.add(0),
402 *p.add(1),
403 *p.add(2),
404 *p.add(3),
405 *p.add(4),
406 *p.add(5),
407 *p.add(6),
408 *p.add(7),
409 )
410 }
411 } else {
412 unsafe { imp(f) }
413 }
414 }
415
416 #[inline]
419 pub fn to_ref(self) -> &'static Self {
420 const __ASSERT_ZST: () = {
421 assert!(::core::mem::size_of::<$name>() == 0);
422 };
423 unsafe { &*::core::ptr::NonNull::dangling().as_ptr() }
424 }
425 }
426 )*
427 };
428}
429
430#[rustfmt::skip]
431#[doc(hidden)]
432pub use __impl_type as __impl_type;
433
434#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
435#[cfg_attr(docsrs, doc(cfg(any(target_arch = "x86", target_arch = "x86_64"))))]
436pub mod x86;
437
438#[cfg(target_arch = "aarch64")]
439#[cfg_attr(docsrs, doc(cfg(target_arch = "aarch64")))]
440pub mod aarch64;
441
442#[cfg(target_arch = "wasm32")]
443#[cfg_attr(docsrs, doc(cfg(target_arch = "wasm32")))]
444pub mod wasm;