mut_ptr.rs - source
Description: Source of the Rust file `library/core/src/../../portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs`.

#
core/portable-simd/crates/core_simd/src/simd/ptr/
mut_ptr.rs

    1use super::sealed::Sealed;
    2use crate::simd::{LaneCount, Mask, Simd, SupportedLaneCount, cmp::SimdPartialEq, num::SimdUint};
    3
    4/// Operations on SIMD vectors of mutable pointers.
    5pub trait SimdMutPtr: Copy + Sealed {
    6    /// Vector of `usize` with the same number of elements.
    7    type Usize;
    8
    9    /// Vector of `isize` with the same number of elements.
    10    type Isize;
    11
    12    /// Vector of const pointers with the same number of elements.
    13    type CastPtr<T>;
    14
    15    /// Vector of constant pointers to the same type.
    16    type ConstPtr;
    17
    18    /// Mask type used for manipulating this SIMD vector type.
    19    type Mask;
    20
    21    /// Returns `true` for each element that is null.
    22    fn is_null(self) -> Self::Mask;
    23
    24    /// Casts to a pointer of another type.
    25    ///
    26    /// Equivalent to calling [`pointer::cast`] on each element.
    27    fn cast<T>(self) -> Self::CastPtr<T>;
    28
    29    /// Changes constness without changing the type.
    30    ///
    31    /// Equivalent to calling [`pointer::cast_const`] on each element.
    32    fn cast_const(self) -> Self::ConstPtr;
    33
    34    /// Gets the "address" portion of the pointer.
    35    ///
    36    /// This method discards pointer semantic metadata, so the result cannot be
    37    /// directly cast into a valid pointer.
    38    ///
    39    /// Equivalent to calling [`pointer::addr`] on each element.
    40    fn addr(self) -> Self::Usize;
    41
    42    /// Converts an address to a pointer without giving it any provenance.
    43    ///
    44    /// Without provenance, this pointer is not associated with any actual allocation. Such a
    45    /// no-provenance pointer may be used for zero-sized memory accesses (if suitably aligned), but
    46    /// non-zero-sized memory accesses with a no-provenance pointer are UB. No-provenance pointers
    47    /// are little more than a usize address in disguise.
    48    ///
    49    /// This is different from [`Self::with_exposed_provenance`], which creates a pointer that picks up a
    50    /// previously exposed provenance.
    51    ///
    52    /// Equivalent to calling [`core::ptr::without_provenance`] on each element.
    53    fn without_provenance(addr: Self::Usize) -> Self;
    54
    55    /// Creates a new pointer with the given address.
    56    ///
    57    /// This performs the same operation as a cast, but copies the *address-space* and
    58    /// *provenance* of `self` to the new pointer.
    59    ///
    60    /// Equivalent to calling [`pointer::with_addr`] on each element.
    61    fn with_addr(self, addr: Self::Usize) -> Self;
    62
    63    /// Exposes the "provenance" part of the pointer for future use in
    64    /// [`Self::with_exposed_provenance`] and returns the "address" portion.
    65    fn expose_provenance(self) -> Self::Usize;
    66
    67    /// Converts an address back to a pointer, picking up a previously "exposed" provenance.
    68    ///
    69    /// Equivalent to calling [`core::ptr::with_exposed_provenance_mut`] on each element.
    70    fn with_exposed_provenance(addr: Self::Usize) -> Self;
    71
    72    /// Calculates the offset from a pointer using wrapping arithmetic.
    73    ///
    74    /// Equivalent to calling [`pointer::wrapping_offset`] on each element.
    75    fn wrapping_offset(self, offset: Self::Isize) -> Self;
    76
    77    /// Calculates the offset from a pointer using wrapping arithmetic.
    78    ///
    79    /// Equivalent to calling [`pointer::wrapping_add`] on each element.
    80    fn wrapping_add(self, count: Self::Usize) -> Self;
    81
    82    /// Calculates the offset from a pointer using wrapping arithmetic.
    83    ///
    84    /// Equivalent to calling [`pointer::wrapping_sub`] on each element.
    85    fn wrapping_sub(self, count: Self::Usize) -> Self;
    86}
    87
    88impl<T, const N: usize> Sealed for Simd<*mut T, N> where LaneCount<N>: SupportedLaneCount {}
    89
    90impl<T, const N: usize> SimdMutPtr for Simd<*mut T, N>
    91where
    92    LaneCount<N>: SupportedLaneCount,
    93{
    94    type Usize = Simd<usize, N>;
    95    type Isize = Simd<isize, N>;
    96    type CastPtr<U> = Simd<*mut U, N>;
    97    type ConstPtr = Simd<*const T, N>;
    98    type Mask = Mask<isize, N>;
    99
    100    #[inline]
    101    fn is_null(self) -> Self::Mask {
    102        Simd::splat(core::ptr::null_mut()).simd_eq(self)
    103    }
    104
    105    #[inline]
    106    fn cast<U>(self) -> Self::CastPtr<U> {
    107        // SimdElement currently requires zero-sized metadata, so this should never fail.
    108        // If this ever changes, `simd_cast_ptr` should produce a post-mono error.
    109        use core::ptr::Pointee;
    110        assert_eq!(size_of::<<T as Pointee>::Metadata>(), 0);
    111        assert_eq!(size_of::<<U as Pointee>::Metadata>(), 0);
    112
    113        // Safety: pointers can be cast
    114        unsafe { core::intrinsics::simd::simd_cast_ptr(self) }
    115    }
    116
    117    #[inline]
    118    fn cast_const(self) -> Self::ConstPtr {
    119        // Safety: pointers can be cast
    120        unsafe { core::intrinsics::simd::simd_cast_ptr(self) }
    121    }
    122
    123    #[inline]
    124    fn addr(self) -> Self::Usize {
    125        // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic.
    126        // SAFETY: Pointer-to-integer transmutes are valid (if you are okay with losing the
    127        // provenance).
    128        unsafe { core::mem::transmute_copy(&self) }
    129    }
    130
    131    #[inline]
    132    fn without_provenance(addr: Self::Usize) -> Self {
    133        // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic.
    134        // SAFETY: Integer-to-pointer transmutes are valid (if you are okay with not getting any
    135        // provenance).
    136        unsafe { core::mem::transmute_copy(&addr) }
    137    }
    138
    139    #[inline]
    140    fn with_addr(self, addr: Self::Usize) -> Self {
    141        // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic.
    142        //
    143        // In the mean-time, this operation is defined to be "as if" it was
    144        // a wrapping_offset, so we can emulate it as such. This should properly
    145        // restore pointer provenance even under today's compiler.
    146        self.cast::<u8>()
    147            .wrapping_offset(addr.cast::<isize>() - self.addr().cast::<isize>())
    148            .cast()
    149    }
    150
    151    #[inline]
    152    fn expose_provenance(self) -> Self::Usize {
    153        // Safety: `self` is a pointer vector
    154        unsafe { core::intrinsics::simd::simd_expose_provenance(self) }
    155    }
    156
    157    #[inline]
    158    fn with_exposed_provenance(addr: Self::Usize) -> Self {
    159        // Safety: `self` is a pointer vector
    160        unsafe { core::intrinsics::simd::simd_with_exposed_provenance(addr) }
    161    }
    162
    163    #[inline]
    164    fn wrapping_offset(self, count: Self::Isize) -> Self {
    165        // Safety: simd_arith_offset takes a vector of pointers and a vector of offsets
    166        unsafe { core::intrinsics::simd::simd_arith_offset(self, count) }
    167    }
    168
    169    #[inline]
    170    fn wrapping_add(self, count: Self::Usize) -> Self {
    171        self.wrapping_offset(count.cast())
    172    }
    173
    174    #[inline]
    175    fn wrapping_sub(self, count: Self::Usize) -> Self {
    176        self.wrapping_offset(-count.cast::<isize>())
    177    }
    178}