2
2
3
3
use super :: MaskElement ;
4
4
use crate :: simd:: intrinsics;
5
- use crate :: simd:: { LaneCount , Simd , SupportedLaneCount } ;
5
+ use crate :: simd:: { LaneCount , Simd , SupportedLaneCount , ToBitMask , ToBitMaskArray } ;
6
6
7
7
#[ repr( transparent) ]
8
8
pub struct Mask < T , const LANES : usize > ( Simd < T , LANES > )
@@ -126,12 +126,26 @@ where
126
126
unsafe { Mask ( intrinsics:: simd_cast ( self . 0 ) ) }
127
127
}
128
128
129
- // Safety: N must be the exact number of bytes required to hold the bitmask for this mask
130
129
#[ inline]
131
130
#[ must_use = "method returns a new array and does not mutate the original value" ]
132
- pub unsafe fn to_bitmask_array < const N : usize > ( self ) -> [ u8 ; N ] {
131
+ pub fn to_bitmask_array < const N : usize > ( self ) -> [ u8 ; N ]
132
+ where
133
+ super :: Mask < T , LANES > : ToBitMaskArray ,
134
+ [ ( ) ; <super :: Mask < T , LANES > as ToBitMaskArray >:: BYTES ] : Sized ,
135
+ {
136
+ assert_eq ! ( <super :: Mask <T , LANES > as ToBitMaskArray >:: BYTES , N ) ;
137
+
138
+ // Safety: N is the correct bitmask size
139
+ //
140
+ // The transmute below allows this function to be marked safe, since it will prevent
141
+ // monomorphization errors in the case of an incorrect size.
133
142
unsafe {
134
- let mut bitmask: [ u8 ; N ] = intrinsics:: simd_bitmask ( self . 0 ) ;
143
+ // Compute the bitmask
144
+ let bitmask: [ u8 ; <super :: Mask < T , LANES > as ToBitMaskArray >:: BYTES ] =
145
+ intrinsics:: simd_bitmask ( self . 0 ) ;
146
+
147
+ // Transmute to the return type, previously asserted to be the same size
148
+ let mut bitmask: [ u8 ; N ] = core:: mem:: transmute_copy ( & bitmask) ;
135
149
136
150
// There is a bug where LLVM appears to implement this operation with the wrong
137
151
// bit order.
@@ -146,10 +160,19 @@ where
146
160
}
147
161
}
148
162
149
- // Safety: N must be the exact number of bytes required to hold the bitmask for this mask
150
163
#[ inline]
151
164
#[ must_use = "method returns a new mask and does not mutate the original value" ]
152
- pub unsafe fn from_bitmask_array < const N : usize > ( mut bitmask : [ u8 ; N ] ) -> Self {
165
+ pub fn from_bitmask_array < const N : usize > ( mut bitmask : [ u8 ; N ] ) -> Self
166
+ where
167
+ super :: Mask < T , LANES > : ToBitMaskArray ,
168
+ [ ( ) ; <super :: Mask < T , LANES > as ToBitMaskArray >:: BYTES ] : Sized ,
169
+ {
170
+ assert_eq ! ( <super :: Mask <T , LANES > as ToBitMaskArray >:: BYTES , N ) ;
171
+
172
+ // Safety: N is the correct bitmask size
173
+ //
174
+ // The transmute below allows this function to be marked safe, since it will prevent
175
+ // monomorphization errors in the case of an incorrect size.
153
176
unsafe {
154
177
// There is a bug where LLVM appears to implement this operation with the wrong
155
178
// bit order.
@@ -160,6 +183,11 @@ where
160
183
}
161
184
}
162
185
186
+ // Transmute to the bitmask type, previously asserted to be the same size
187
+ let bitmask: [ u8 ; <super :: Mask < T , LANES > as ToBitMaskArray >:: BYTES ] =
188
+ core:: mem:: transmute_copy ( & bitmask) ;
189
+
190
+ // Compute the regular mask
163
191
Self :: from_int_unchecked ( intrinsics:: simd_select_bitmask (
164
192
bitmask,
165
193
Self :: splat ( true ) . to_int ( ) ,
@@ -168,11 +196,12 @@ where
168
196
}
169
197
}
170
198
171
- // Safety: U must be the integer with the exact number of bits required to hold the bitmask for
172
- // this mask
173
199
#[ inline]
174
- pub ( crate ) unsafe fn to_bitmask_integer < U : ReverseBits > ( self ) -> U {
175
- // Safety: caller must only return bitmask types
200
+ pub ( crate ) fn to_bitmask_integer < U : ReverseBits > ( self ) -> U
201
+ where
202
+ super :: Mask < T , LANES > : ToBitMask < BitMask = U > ,
203
+ {
204
+ // Safety: U is required to be the appropriate bitmask type
176
205
let bitmask: U = unsafe { intrinsics:: simd_bitmask ( self . 0 ) } ;
177
206
178
207
// There is a bug where LLVM appears to implement this operation with the wrong
@@ -188,7 +217,10 @@ where
188
217
// Safety: U must be the integer with the exact number of bits required to hold the bitmask for
189
218
// this mask
190
219
#[ inline]
191
- pub ( crate ) unsafe fn from_bitmask_integer < U : ReverseBits > ( bitmask : U ) -> Self {
220
+ pub ( crate ) fn from_bitmask_integer < U : ReverseBits > ( bitmask : U ) -> Self
221
+ where
222
+ super :: Mask < T , LANES > : ToBitMask < BitMask = U > ,
223
+ {
192
224
// There is a bug where LLVM appears to implement this operation with the wrong
193
225
// bit order.
194
226
// TODO fix this in a better way
@@ -198,7 +230,7 @@ where
198
230
bitmask
199
231
} ;
200
232
201
- // Safety: caller must only pass bitmask types
233
+ // Safety: U is required to be the appropriate bitmask type
202
234
unsafe {
203
235
Self :: from_int_unchecked ( intrinsics:: simd_select_bitmask (
204
236
bitmask,
0 commit comments