Skip to content

Commit 176cc81

Browse files
committed
Update for new intrinsics
1 parent 8a5a573 commit 176cc81

File tree

5 files changed

+110
-100
lines changed

5 files changed

+110
-100
lines changed

crates/core_simd/src/cast.rs

Lines changed: 21 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,23 @@
1-
use crate::simd::{intrinsics, LaneCount, Simd, SimdElement, SupportedLaneCount};
1+
use crate::simd::SimdElement;
22

33
/// Supporting trait for `Simd::cast`. Typically doesn't need to be used directly.
4-
pub unsafe trait SimdCast<Target: SimdElement>: SimdElement {
5-
#[doc(hidden)]
6-
fn cast<const LANES: usize>(x: Simd<Self, LANES>) -> Simd<Target, LANES>
7-
where
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-
}
23-
}
24-
25-
macro_rules! into_number {
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 {}
29-
};
30-
{ unsafe $($type:ty),* } => {
31-
$(
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 }
37-
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 }
43-
44-
into_number! { unsafe $type as f32 }
45-
into_number! { unsafe $type as f64 }
46-
)*
47-
}
48-
}
49-
50-
into_number! { unsafe i8, i16, i32, i64, isize, u8, u16, u32, u64, usize, f32, f64 }
51-
52-
// TODO uncomment pending PR to rustc
53-
/*
54-
macro_rules! into_pointer {
55-
{ unsafe $($type:ty),* } => {
56-
$(
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 {}
65-
)*
66-
}
67-
}
68-
69-
into_pointer! { unsafe i8, i16, i32, i64, isize, u8, u16, u32, u64, usize }
70-
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-
*/
4+
pub unsafe trait SimdCast: SimdElement {}
5+
6+
unsafe impl SimdCast for i8 {}
7+
unsafe impl SimdCast for i16 {}
8+
unsafe impl SimdCast for i32 {}
9+
unsafe impl SimdCast for i64 {}
10+
unsafe impl SimdCast for isize {}
11+
unsafe impl SimdCast for u8 {}
12+
unsafe impl SimdCast for u16 {}
13+
unsafe impl SimdCast for u32 {}
14+
unsafe impl SimdCast for u64 {}
15+
unsafe impl SimdCast for usize {}
16+
unsafe impl SimdCast for f32 {}
17+
unsafe impl SimdCast for f64 {}
18+
19+
/// Supporting trait for `Simd::cast_ptr`. Typically doesn't need to be used directly.
20+
pub unsafe trait SimdCastPtr: SimdElement {}
21+
22+
unsafe impl<T> SimdCastPtr for *const T {}
23+
unsafe impl<T> SimdCastPtr for *mut T {}

crates/core_simd/src/elements/const_ptr.rs

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,15 @@ pub trait SimdConstPtr: Copy + Sealed {
4040
/// Equivalent to calling [`pointer::with_addr`] on each lane.
4141
fn with_addr(self, addr: Self::Usize) -> Self;
4242

43+
/// Gets the "address" portion of the pointer, and "exposes" the provenance part for future use
44+
/// in [`from_exposed_addr`].
45+
fn expose_addr(self) -> Self::Usize;
46+
47+
/// Convert an address back to a pointer, picking up a previously "exposed" provenance.
48+
///
49+
/// Equivalent to calling [`pointer::from_exposed_addr`] on each lane.
50+
fn from_exposed_addr(addr: Self::Usize) -> Self;
51+
4352
/// Calculates the offset from a pointer using wrapping arithmetic.
4453
///
4554
/// Equivalent to calling [`pointer::wrapping_offset`] on each lane.
@@ -77,8 +86,7 @@ where
7786

7887
#[inline]
7988
fn as_mut(self) -> Self::MutPtr {
80-
unimplemented!()
81-
//self.cast()
89+
unsafe { intrinsics::simd_cast_ptr(self) }
8290
}
8391

8492
#[inline]
@@ -90,18 +98,25 @@ where
9098
}
9199

92100
#[inline]
93-
fn with_addr(self, _addr: Self::Usize) -> Self {
94-
unimplemented!()
95-
/*
101+
fn with_addr(self, addr: Self::Usize) -> Self {
96102
// FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic.
97103
//
98104
// In the mean-time, this operation is defined to be "as if" it was
99105
// a wrapping_offset, so we can emulate it as such. This should properly
100106
// restore pointer provenance even under today's compiler.
101-
self.cast::<*const u8>()
107+
self.cast_ptr::<*const u8>()
102108
.wrapping_offset(addr.cast::<isize>() - self.addr().cast::<isize>())
103-
.cast()
104-
*/
109+
.cast_ptr()
110+
}
111+
112+
#[inline]
113+
fn expose_addr(self) -> Self::Usize {
114+
unsafe { intrinsics::simd_expose_addr(self) }
115+
}
116+
117+
#[inline]
118+
fn from_exposed_addr(addr: Self::Usize) -> Self {
119+
unsafe { intrinsics::simd_from_exposed_addr(addr) }
105120
}
106121

107122
#[inline]

crates/core_simd/src/elements/mut_ptr.rs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,15 @@ pub trait SimdMutPtr: Copy + Sealed {
3737
/// Equivalent to calling [`pointer::with_addr`] on each lane.
3838
fn with_addr(self, addr: Self::Usize) -> Self;
3939

40+
/// Gets the "address" portion of the pointer, and "exposes" the provenance part for future use
41+
/// in [`from_exposed_addr`].
42+
fn expose_addr(self) -> Self::Usize;
43+
44+
/// Convert an address back to a pointer, picking up a previously "exposed" provenance.
45+
///
46+
/// Equivalent to calling [`pointer::from_exposed_addr`] on each lane.
47+
fn from_exposed_addr(addr: Self::Usize) -> Self;
48+
4049
/// Calculates the offset from a pointer using wrapping arithmetic.
4150
///
4251
/// Equivalent to calling [`pointer::wrapping_offset`] on each lane.
@@ -85,18 +94,25 @@ where
8594
}
8695

8796
#[inline]
88-
fn with_addr(self, _addr: Self::Usize) -> Self {
89-
unimplemented!()
90-
/*
97+
fn with_addr(self, addr: Self::Usize) -> Self {
9198
// FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic.
9299
//
93100
// In the mean-time, this operation is defined to be "as if" it was
94101
// a wrapping_offset, so we can emulate it as such. This should properly
95102
// restore pointer provenance even under today's compiler.
96-
self.cast::<*mut u8>()
103+
self.cast_ptr::<*mut u8>()
97104
.wrapping_offset(addr.cast::<isize>() - self.addr().cast::<isize>())
98-
.cast()
99-
*/
105+
.cast_ptr()
106+
}
107+
108+
#[inline]
109+
fn expose_addr(self) -> Self::Usize {
110+
unsafe { intrinsics::simd_expose_addr(self) }
111+
}
112+
113+
#[inline]
114+
fn from_exposed_addr(addr: Self::Usize) -> Self {
115+
unsafe { intrinsics::simd_from_exposed_addr(addr) }
100116
}
101117

102118
#[inline]

crates/core_simd/src/intrinsics.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,4 +154,27 @@ extern "platform-intrinsic" {
154154

155155
// equivalent to wrapping_offset
156156
pub(crate) fn simd_arith_offset<T, U>(ptr: T, offset: U) -> T;
157+
158+
/*
159+
/// equivalent to `T as U` semantics, specifically for pointers
160+
pub(crate) fn simd_cast_ptr<T, U>(ptr: T) -> U;
161+
162+
/// expose a pointer as an address
163+
pub(crate) fn simd_expose_addr<T, U>(ptr: T) -> U;
164+
165+
/// convert an exposed address back to a pointer
166+
pub(crate) fn simd_from_exposed_addr<T, U>(addr: T) -> U;
167+
*/
168+
}
169+
170+
pub(crate) unsafe fn simd_cast_ptr<T, U>(_ptr: T) -> U {
171+
unimplemented!()
172+
}
173+
174+
pub(crate) unsafe fn simd_expose_addr<T, U>(_ptr: T) -> U {
175+
unimplemented!()
176+
}
177+
178+
pub(crate) unsafe fn simd_from_exposed_addr<T, U>(_addr: T) -> U {
179+
unimplemented!()
157180
}

crates/core_simd/src/vector.rs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::simd::{
2-
intrinsics, LaneCount, Mask, MaskElement, SimdCast, SimdConstPtr, SimdMutPtr, SimdPartialOrd,
3-
SupportedLaneCount, Swizzle,
2+
intrinsics, LaneCount, Mask, MaskElement, SimdCast, SimdCastPtr, SimdConstPtr, SimdMutPtr,
3+
SimdPartialOrd, SupportedLaneCount, Swizzle,
44
};
55

66
/// A SIMD vector of `LANES` elements of type `T`. `Simd<T, N>` has the same shape as [`[T; N]`](array), but operates like `T`.
@@ -209,11 +209,23 @@ where
209209
#[must_use]
210210
#[inline]
211211
#[cfg(not(bootstrap))]
212-
pub fn cast<U: SimdElement>(self) -> Simd<U, LANES>
212+
pub fn cast<U: SimdCast>(self) -> Simd<U, LANES>
213213
where
214-
T: SimdCast<U>,
214+
T: SimdCast,
215215
{
216-
SimdCast::cast(self)
216+
// Safety: supported types are guaranteed by SimdCast
217+
unsafe { intrinsics::simd_as(self) }
218+
}
219+
220+
/// Lanewise casts pointers to another pointer type.
221+
#[must_use]
222+
#[inline]
223+
pub fn cast_ptr<U: SimdCastPtr>(self) -> Simd<U, LANES>
224+
where
225+
T: SimdCastPtr,
226+
{
227+
// Safety: supported types are guaranteed by SimdCastPtr
228+
unsafe { intrinsics::simd_cast_ptr(self) }
217229
}
218230

219231
/// Rounds toward zero and converts to the same-width integer type, assuming that
@@ -234,11 +246,11 @@ where
234246
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
235247
pub unsafe fn to_int_unchecked<I>(self) -> Simd<I, LANES>
236248
where
237-
T: core::convert::FloatToInt<I> + SimdCast<I>,
238-
I: SimdElement,
249+
T: core::convert::FloatToInt<I> + SimdCast,
250+
I: SimdCast,
239251
{
240-
// Safety: the caller is responsible for the invariants
241-
unsafe { SimdCast::cast_unchecked(self) }
252+
// Safety: supported types are guaranteed by SimdCast, the caller is responsible for the extra invariants
253+
unsafe { intrinsics::simd_cast(self) }
242254
}
243255

244256
/// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector.

0 commit comments

Comments
 (0)