|
1 | 1 | use crate::simd::{intrinsics, LaneCount, Simd, SimdElement, SupportedLaneCount};
|
2 | 2 |
|
3 | 3 | /// Supporting trait for `Simd::cast`. Typically doesn't need to be used directly.
|
4 |
| -pub trait SimdCast<Target: SimdElement>: SimdElement { |
| 4 | +pub unsafe trait SimdCast<Target: SimdElement>: SimdElement { |
5 | 5 | #[doc(hidden)]
|
6 | 6 | fn cast<const LANES: usize>(x: Simd<Self, LANES>) -> Simd<Target, LANES>
|
7 | 7 | where
|
8 |
| - LaneCount<LANES>: SupportedLaneCount; |
| 8 | + LaneCount<LANES>: SupportedLaneCount, |
| 9 | + { |
| 10 | + // Safety: implementing this trait indicates that the types are supported by `simd_as` |
| 11 | + unsafe { intrinsics::simd_as(x) } |
| 12 | + } |
| 13 | + |
| 14 | + #[doc(hidden)] |
| 15 | + unsafe fn cast_unchecked<const LANES: usize>(x: Simd<Self, LANES>) -> Simd<Target, LANES> |
| 16 | + where |
| 17 | + LaneCount<LANES>: SupportedLaneCount, |
| 18 | + { |
| 19 | + // Safety: implementing this trait indicates that the types are supported by `simd_cast` |
| 20 | + // The caller is responsible for the conversion invariants. |
| 21 | + unsafe { intrinsics::simd_cast(x) } |
| 22 | + } |
9 | 23 | }
|
10 | 24 |
|
11 | 25 | macro_rules! into_number {
|
12 |
| - { $from:ty, $to:ty } => { |
13 |
| - impl SimdCast<$to> for $from { |
14 |
| - fn cast<const LANES: usize>(x: Simd<Self, LANES>) -> Simd<$to, LANES> |
15 |
| - where |
16 |
| - LaneCount<LANES>: SupportedLaneCount, |
17 |
| - { |
18 |
| - // Safety: simd_as can handle numeric conversions |
19 |
| - unsafe { intrinsics::simd_as(x) } |
20 |
| - } |
21 |
| - } |
| 26 | + { unsafe $from:ty as $to:ty } => { |
| 27 | + // Safety: casting between numbers is supported by `simd_cast` and `simd_as` |
| 28 | + unsafe impl SimdCast<$to> for $from {} |
22 | 29 | };
|
23 |
| - { $($type:ty),* } => { |
| 30 | + { unsafe $($type:ty),* } => { |
24 | 31 | $(
|
25 |
| - into_number! { $type, i8 } |
26 |
| - into_number! { $type, i16 } |
27 |
| - into_number! { $type, i32 } |
28 |
| - into_number! { $type, i64 } |
29 |
| - into_number! { $type, isize } |
| 32 | + into_number! { unsafe $type as i8 } |
| 33 | + into_number! { unsafe $type as i16 } |
| 34 | + into_number! { unsafe $type as i32 } |
| 35 | + into_number! { unsafe $type as i64 } |
| 36 | + into_number! { unsafe $type as isize } |
30 | 37 |
|
31 |
| - into_number! { $type, u8 } |
32 |
| - into_number! { $type, u16 } |
33 |
| - into_number! { $type, u32 } |
34 |
| - into_number! { $type, u64 } |
35 |
| - into_number! { $type, usize } |
| 38 | + into_number! { unsafe $type as u8 } |
| 39 | + into_number! { unsafe $type as u16 } |
| 40 | + into_number! { unsafe $type as u32 } |
| 41 | + into_number! { unsafe $type as u64 } |
| 42 | + into_number! { unsafe $type as usize } |
36 | 43 |
|
37 |
| - into_number! { $type, f32 } |
38 |
| - into_number! { $type, f64 } |
| 44 | + into_number! { unsafe $type as f32 } |
| 45 | + into_number! { unsafe $type as f64 } |
39 | 46 | )*
|
40 | 47 | }
|
41 | 48 | }
|
42 | 49 |
|
43 |
| -into_number! { i8, i16, i32, i64, isize, u8, u16, u32, u64, usize, f32, f64 } |
| 50 | +into_number! { unsafe i8, i16, i32, i64, isize, u8, u16, u32, u64, usize, f32, f64 } |
44 | 51 |
|
| 52 | +// TODO uncomment pending PR to rustc |
| 53 | +/* |
45 | 54 | macro_rules! into_pointer {
|
46 |
| - { $($type:ty),* } => { |
| 55 | + { unsafe $($type:ty),* } => { |
47 | 56 | $(
|
48 |
| - impl<T> SimdCast<$type> for *const T { |
49 |
| - fn cast<const LANES: usize>(x: Simd<Self, LANES>) -> Simd<$type, LANES> |
50 |
| - where |
51 |
| - LaneCount<LANES>: SupportedLaneCount, |
52 |
| - { |
53 |
| - // Safety: transmuting isize to pointers is safe |
54 |
| - let x: Simd<isize, LANES> = unsafe { core::mem::transmute_copy(&x) }; |
55 |
| - x.cast() |
56 |
| - } |
57 |
| - } |
58 |
| - impl<T> SimdCast<$type> for *mut T { |
59 |
| - fn cast<const LANES: usize>(x: Simd<Self, LANES>) -> Simd<$type, LANES> |
60 |
| - where |
61 |
| - LaneCount<LANES>: SupportedLaneCount, |
62 |
| - { |
63 |
| - // Safety: transmuting isize to pointers is safe |
64 |
| - let x: Simd<isize, LANES> = unsafe { core::mem::transmute_copy(&x) }; |
65 |
| - x.cast() |
66 |
| - } |
67 |
| - } |
68 |
| - impl<T> SimdCast<*const T> for $type { |
69 |
| - fn cast<const LANES: usize>(x: Simd<$type, LANES>) -> Simd<*const T, LANES> |
70 |
| - where |
71 |
| - LaneCount<LANES>: SupportedLaneCount, |
72 |
| - { |
73 |
| - let x: Simd<isize, LANES> = x.cast(); |
74 |
| - // Safety: transmuting isize to pointers is safe |
75 |
| - unsafe { core::mem::transmute_copy(&x) } |
76 |
| - } |
77 |
| - } |
78 |
| - impl<T> SimdCast<*mut T> for $type { |
79 |
| - fn cast<const LANES: usize>(x: Simd<$type, LANES>) -> Simd<*mut T, LANES> |
80 |
| - where |
81 |
| - LaneCount<LANES>: SupportedLaneCount, |
82 |
| - { |
83 |
| - let x: Simd<isize, LANES> = x.cast(); |
84 |
| - // Safety: transmuting isize to pointers is safe |
85 |
| - unsafe { core::mem::transmute_copy(&x) } |
86 |
| - } |
87 |
| - } |
| 57 | + // Safety: casting between numbers and pointers is supported by `simd_cast` and `simd_as` |
| 58 | + unsafe impl<T> SimdCast<$type> for *const T {} |
| 59 | + // Safety: casting between numbers and pointers is supported by `simd_cast` and `simd_as` |
| 60 | + unsafe impl<T> SimdCast<$type> for *mut T {} |
| 61 | + // Safety: casting between numbers and pointers is supported by `simd_cast` and `simd_as` |
| 62 | + unsafe impl<T> SimdCast<*const T> for $type {} |
| 63 | + // Safety: casting between numbers and pointers is supported by `simd_cast` and `simd_as` |
| 64 | + unsafe impl<T> SimdCast<*mut T> for $type {} |
88 | 65 | )*
|
89 | 66 | }
|
90 | 67 | }
|
91 | 68 |
|
92 |
| -into_pointer! { i8, i16, i32, i64, isize, u8, u16, u32, u64, usize } |
| 69 | +into_pointer! { unsafe i8, i16, i32, i64, isize, u8, u16, u32, u64, usize } |
93 | 70 |
|
94 |
| -impl<T, U> SimdCast<*const T> for *const U { |
95 |
| - fn cast<const LANES: usize>(x: Simd<*const U, LANES>) -> Simd<*const T, LANES> |
96 |
| - where |
97 |
| - LaneCount<LANES>: SupportedLaneCount, |
98 |
| - { |
99 |
| - // Safety: transmuting pointers is safe |
100 |
| - unsafe { core::mem::transmute_copy(&x) } |
101 |
| - } |
102 |
| -} |
103 |
| -impl<T, U> SimdCast<*const T> for *mut U { |
104 |
| - fn cast<const LANES: usize>(x: Simd<*mut U, LANES>) -> Simd<*const T, LANES> |
105 |
| - where |
106 |
| - LaneCount<LANES>: SupportedLaneCount, |
107 |
| - { |
108 |
| - // Safety: transmuting pointers is safe |
109 |
| - unsafe { core::mem::transmute_copy(&x) } |
110 |
| - } |
111 |
| -} |
112 |
| -impl<T, U> SimdCast<*mut T> for *const U { |
113 |
| - fn cast<const LANES: usize>(x: Simd<*const U, LANES>) -> Simd<*mut T, LANES> |
114 |
| - where |
115 |
| - LaneCount<LANES>: SupportedLaneCount, |
116 |
| - { |
117 |
| - // Safety: transmuting pointers is safe |
118 |
| - unsafe { core::mem::transmute_copy(&x) } |
119 |
| - } |
120 |
| -} |
121 |
| -impl<T, U> SimdCast<*mut T> for *mut U { |
122 |
| - fn cast<const LANES: usize>(x: Simd<*mut U, LANES>) -> Simd<*mut T, LANES> |
123 |
| - where |
124 |
| - LaneCount<LANES>: SupportedLaneCount, |
125 |
| - { |
126 |
| - // Safety: transmuting pointers is safe |
127 |
| - unsafe { core::mem::transmute_copy(&x) } |
128 |
| - } |
129 |
| -} |
| 71 | +// Safety: casting between pointers is supported by `simd_cast` and `simd_as` |
| 72 | +unsafe impl<T, U> SimdCast<*const T> for *const U {} |
| 73 | +// Safety: casting between pointers is supported by `simd_cast` and `simd_as` |
| 74 | +unsafe impl<T, U> SimdCast<*const T> for *mut U {} |
| 75 | +// Safety: casting between pointers is supported by `simd_cast` and `simd_as` |
| 76 | +unsafe impl<T, U> SimdCast<*mut T> for *const U {} |
| 77 | +// Safety: casting between pointers is supported by `simd_cast` and `simd_as` |
| 78 | +unsafe impl<T, U> SimdCast<*mut T> for *mut U {} |
| 79 | +*/ |
0 commit comments