core/stdarch/crates/core_arch/src/
macros.rs

1//! Utility macros.
2
3#[allow(unused)]
4macro_rules! static_assert {
5    ($e:expr) => {
6        const {
7            assert!($e);
8        }
9    };
10    ($e:expr, $msg:expr) => {
11        const {
12            assert!($e, $msg);
13        }
14    };
15}
16
17#[allow(unused_macros)]
18macro_rules! static_assert_uimm_bits {
19    ($imm:ident, $bits:expr) => {
20        // `0 <= $imm` produces a warning if the immediate has an unsigned type
21        #[allow(unused_comparisons)]
22        {
23            static_assert!(
24                0 <= $imm && $imm < (1 << $bits),
25                concat!(
26                    stringify!($imm),
27                    " doesn't fit in ",
28                    stringify!($bits),
29                    " bits",
30                )
31            )
32        }
33    };
34}
35
36#[allow(unused_macros)]
37macro_rules! static_assert_simm_bits {
38    ($imm:ident, $bits:expr) => {
39        static_assert!(
40            (-1 << ($bits - 1)) - 1 <= $imm && $imm < (1 << ($bits - 1)),
41            concat!(
42                stringify!($imm),
43                " doesn't fit in ",
44                stringify!($bits),
45                " bits",
46            )
47        )
48    };
49}
50
51#[allow(unused)]
52macro_rules! types {
53    (
54        #![$stability_first:meta]
55        $(
56            #![$stability_more:meta]
57        )*
58
59        $(
60            $(#[$doc:meta])*
61            $(stability: [$stability_already: meta])*
62            pub struct $name:ident($len:literal x $v:vis $elem_type:ty);
63        )*
64    ) => (types! {
65        $(
66            #![$stability_more]
67        )*
68
69        $(
70            $(#[$doc])*
71            $(stability: [$stability_already])*
72            stability: [$stability_first]
73            pub struct $name($len x $v $elem_type);
74        )*
75    });
76
77    (
78        $(
79            $(#[$doc:meta])*
80            $(stability: [$stability: meta])+
81            pub struct $name:ident($len:literal x $v:vis $elem_type:ty);
82        )*
83    ) => ($(
84        $(#[$doc])*
85        $(#[$stability])+
86        #[derive(Copy, Clone)]
87        #[allow(non_camel_case_types)]
88        #[repr(simd)]
89        #[allow(clippy::missing_inline_in_public_items)]
90        pub struct $name($v [$elem_type; $len]);
91
92        impl $name {
93            /// Using `my_simd([x; N])` seemingly fails tests,
94            /// so use this internal helper for it instead.
95            #[inline(always)]
96            $v fn splat(value: $elem_type) -> $name {
97                #[derive(Copy, Clone)]
98                #[repr(simd)]
99                struct JustOne([$elem_type; 1]);
100                let one = JustOne([value]);
101                // SAFETY: 0 is always in-bounds because we're shuffling
102                // a simd type with exactly one element.
103                unsafe { simd_shuffle!(one, one, [0; $len]) }
104            }
105
106            /// Returns an array reference containing the entire SIMD vector.
107            $v const fn as_array(&self) -> &[$elem_type; $len] {
108                // SAFETY: this type is just an overaligned `[T; N]` with
109                // potential padding at the end, so pointer casting to a
110                // `&[T; N]` is safe.
111                //
112                // NOTE: This deliberately doesn't just use `&self.0` because it may soon be banned
113                // see https://github.com/rust-lang/compiler-team/issues/838
114                unsafe { &*(self as *const Self as *const [$elem_type; $len]) }
115
116            }
117
118            /// Returns a mutable array reference containing the entire SIMD vector.
119            #[inline]
120            $v fn as_mut_array(&mut self) -> &mut [$elem_type; $len] {
121                // SAFETY: this type is just an overaligned `[T; N]` with
122                // potential padding at the end, so pointer casting to a
123                // `&mut [T; N]` is safe.
124                //
125                // NOTE: This deliberately doesn't just use `&mut self.0` because it may soon be banned
126                // see https://github.com/rust-lang/compiler-team/issues/838
127                unsafe { &mut *(self as *mut Self as *mut [$elem_type; $len]) }
128            }
129        }
130
131        $(#[$stability])+
132        impl crate::fmt::Debug for $name {
133            #[inline]
134            fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result {
135                crate::core_arch::simd::debug_simd_finish(f, stringify!($name), self.0)
136            }
137        }
138    )*);
139}
140
141#[allow(unused)]
142#[repr(simd)]
143pub(crate) struct SimdShuffleIdx<const LEN: usize>(pub(crate) [u32; LEN]);
144
145#[allow(unused)]
146macro_rules! simd_shuffle {
147    ($x:expr, $y:expr, $idx:expr $(,)?) => {{
148        $crate::intrinsics::simd::simd_shuffle(
149            $x,
150            $y,
151            const { $crate::core_arch::macros::SimdShuffleIdx($idx) },
152        )
153    }};
154}
155
156#[allow(unused)]
157macro_rules! simd_insert {
158    ($x:expr, $idx:expr, $val:expr $(,)?) => {{ $crate::intrinsics::simd::simd_insert($x, const { $idx }, $val) }};
159}
160
161#[allow(unused)]
162macro_rules! simd_extract {
163    ($x:expr, $idx:expr $(,)?) => {{ $crate::intrinsics::simd::simd_extract($x, const { $idx }) }};
164    ($x:expr, $idx:expr, $ty:ty $(,)?) => {{ $crate::intrinsics::simd::simd_extract::<_, $ty>($x, const { $idx }) }};
165}