1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
use super::sealed::Sealed;
use crate::simd::{intrinsics, LaneCount, Mask, Simd, SimdPartialEq, SupportedLaneCount};

/// 对常量指针的 SIMD vectors 的操作。
pub trait SimdConstPtr: Copy + Sealed {
    /// `usize` 的 Vector 与 lanes 的数量相同。
    type Usize;

    /// `isize` 的 Vector 与 lanes 的数量相同。
    type Isize;

    /// Vector 的可变指针指向同一类型。
    type MutPtr;

    /// 用于操作此 SIMD vector 类型的掩码类型。
    type Mask;

    /// 为每个为空的 lane 返回 `true`。
    fn is_null(self) -> Self::Mask;

    /// 更改常量而不更改类型。
    ///
    /// 相当于在每个 lane 上调用 [`pointer::cast_mut`]。
    fn cast_mut(self) -> Self::MutPtr;

    /// 获取指针的 "address" 部分。
    ///
    /// 该方法丢弃了指针语义元数据,因此不能将结果直接转换为有效指针。
    ///
    ///
    /// 此方法在语义上丢弃了*provenance* 和*address-space* 信息。
    /// 要正确恢复该信息,请使用 [`Self::with_addr`]。
    ///
    /// 相当于在每个 lane 上调用 [`pointer::addr`]。
    fn addr(self) -> Self::Usize;

    /// 使用给定地址创建一个新指针。
    ///
    /// 这执行与强制转换相同的操作,但将 `self` 的*address-space* 和*provenance* 复制到新指针。
    ///
    ///
    /// 相当于在每个 lane 上调用 [`pointer::with_addr`]。
    fn with_addr(self, addr: Self::Usize) -> Self;

    /// 获取指针的 "address" 部分,"exposes" 是 future 在 [`Self::from_exposed_addr`] 中使用的出处部分。
    ///
    fn expose_addr(self) -> Self::Usize;

    /// 将地址转换回指针,获取以前的 "exposed" 出处。
    ///
    /// 相当于在每个 lane 上调用 [`core::ptr::from_exposed_addr`]。
    fn from_exposed_addr(addr: Self::Usize) -> Self;

    /// 使用换行算法计算与指针的偏移量。
    ///
    /// 相当于在每个 lane 上调用 [`pointer::wrapping_offset`]。
    fn wrapping_offset(self, offset: Self::Isize) -> Self;

    /// 使用换行算法计算与指针的偏移量。
    ///
    /// 相当于在每个 lane 上调用 [`pointer::wrapping_add`]。
    fn wrapping_add(self, count: Self::Usize) -> Self;

    /// 使用换行算法计算与指针的偏移量。
    ///
    /// 相当于在每个 lane 上调用 [`pointer::wrapping_sub`]。
    fn wrapping_sub(self, count: Self::Usize) -> Self;
}

impl<T, const LANES: usize> Sealed for Simd<*const T, LANES> where
    LaneCount<LANES>: SupportedLaneCount
{
}

impl<T, const LANES: usize> SimdConstPtr for Simd<*const T, LANES>
where
    LaneCount<LANES>: SupportedLaneCount,
{
    type Usize = Simd<usize, LANES>;
    type Isize = Simd<isize, LANES>;
    type MutPtr = Simd<*mut T, LANES>;
    type Mask = Mask<isize, LANES>;

    #[inline]
    fn is_null(self) -> Self::Mask {
        Simd::splat(core::ptr::null()).simd_eq(self)
    }

    #[inline]
    fn cast_mut(self) -> Self::MutPtr {
        self.cast_ptr()
    }

    #[inline]
    fn addr(self) -> Self::Usize {
        // FIXME(strict_provenance_magic): 我是魔法,应该是编译器内部函数。
        // SAFETY: 指针到整数的转换是有效的 (如果您同意丢失出处的话)。
        //
        unsafe { core::mem::transmute_copy(&self) }
    }

    #[inline]
    fn with_addr(self, addr: Self::Usize) -> Self {
        // FIXME(strict_provenance_magic): 我是魔法,应该是编译器内部函数。
        //
        // 同时,这个操作被定义为 "as if",它是一个 wrapping_offset,所以我们可以模拟它。
        // 即使在今天的编译器下,这也应该正确地恢复指针 Provenance。
        //
        self.cast_ptr::<*const u8>()
            .wrapping_offset(addr.cast::<isize>() - self.addr().cast::<isize>())
            .cast_ptr()
    }

    #[inline]
    fn expose_addr(self) -> Self::Usize {
        // 安全性: `self` 是指针 vector
        unsafe { intrinsics::simd_expose_addr(self) }
    }

    #[inline]
    fn from_exposed_addr(addr: Self::Usize) -> Self {
        // 安全性: `self` 是指针 vector
        unsafe { intrinsics::simd_from_exposed_addr(addr) }
    }

    #[inline]
    fn wrapping_offset(self, count: Self::Isize) -> Self {
        // 安全性: simd_arith_offset 采用 vector 指针和 vector 偏移量
        unsafe { intrinsics::simd_arith_offset(self, count) }
    }

    #[inline]
    fn wrapping_add(self, count: Self::Usize) -> Self {
        self.wrapping_offset(count.cast())
    }

    #[inline]
    fn wrapping_sub(self, count: Self::Usize) -> Self {
        self.wrapping_offset(-count.cast::<isize>())
    }
}