Skip to content

Commit f916add

Browse files
2 parents ceb2611 + f1b86ba commit f916add

File tree

2 files changed

+46
-8
lines changed

2 files changed

+46
-8
lines changed

crates/core_simd/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![no_std]
22
#![feature(
33
const_ptr_read,
4+
const_refs_to_cell,
45
convert_float_to_int,
56
decl_macro,
67
intra_doc_pointers,

crates/core_simd/src/vector.rs

+45-8
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ use crate::simd::{
7676
/// [`read`]: pointer::read
7777
/// [`write`]: pointer::write
7878
/// [as_simd]: slice::as_simd
79+
//
80+
// NOTE: Accessing the inner array directly in any way (e.g. by using the `.0` field syntax) or
81+
// directly constructing an instance of the type (i.e. `let vector = Simd(array)`) should be
82+
// avoided, as it will likely become illegal on `#[repr(simd)]` structs in the future. It also
83+
// causes rustc to emit illegal LLVM IR in some cases.
7984
#[repr(simd)]
8085
pub struct Simd<T, const LANES: usize>([T; LANES])
8186
where
@@ -135,22 +140,54 @@ where
135140
/// assert_eq!(v.as_array(), &[0, 1, 2, 3]);
136141
/// ```
137142
pub const fn as_array(&self) -> &[T; LANES] {
138-
&self.0
143+
// SAFETY: Transmuting between `Simd<T, LANES>` and `[T; LANES]`
144+
// is always valid and `Simd<T, LANES>` never has a lower alignment
145+
// than `[T; LANES]`.
146+
//
147+
// NOTE: This deliberately doesn't just use `&self.0`, see the comment
148+
// on the struct definition for details.
149+
unsafe { &*(self as *const Self as *const [T; LANES]) }
139150
}
140151

141152
/// Returns a mutable array reference containing the entire SIMD vector.
142153
pub fn as_mut_array(&mut self) -> &mut [T; LANES] {
143-
&mut self.0
154+
// SAFETY: Transmuting between `Simd<T, LANES>` and `[T; LANES]`
155+
// is always valid and `Simd<T, LANES>` never has a lower alignment
156+
// than `[T; LANES]`.
157+
//
158+
// NOTE: This deliberately doesn't just use `&mut self.0`, see the comment
159+
// on the struct definition for details.
160+
unsafe { &mut *(self as *mut Self as *mut [T; LANES]) }
144161
}
145162

146163
/// Converts an array to a SIMD vector.
147164
pub const fn from_array(array: [T; LANES]) -> Self {
148-
Self(array)
165+
// SAFETY: Transmuting between `Simd<T, LANES>` and `[T; LANES]`
166+
// is always valid. We need to use `read_unaligned` here, since
167+
// the array may have a lower alignment than the vector.
168+
//
169+
// FIXME: We currently use a pointer read instead of `transmute_copy` because
170+
// it results in better codegen with optimizations disabled, but we should
171+
// probably just use `transmute` once that works on const generic types.
172+
//
173+
// NOTE: This deliberately doesn't just use `Self(array)`, see the comment
174+
// on the struct definition for details.
175+
unsafe { (&array as *const [T; LANES] as *const Self).read_unaligned() }
149176
}
150177

151178
/// Converts a SIMD vector to an array.
152179
pub const fn to_array(self) -> [T; LANES] {
153-
self.0
180+
// SAFETY: Transmuting between `Simd<T, LANES>` and `[T; LANES]`
181+
// is always valid. No need to use `read_unaligned` here, since
182+
// the vector never has a lower alignment than the array.
183+
//
184+
// FIXME: We currently use a pointer read instead of `transmute_copy` because
185+
// it results in better codegen with optimizations disabled, but we should
186+
// probably just use `transmute` once that works on const generic types.
187+
//
188+
// NOTE: This deliberately doesn't just use `self.0`, see the comment
189+
// on the struct definition for details.
190+
unsafe { (&self as *const Self as *const [T; LANES]).read() }
154191
}
155192

156193
/// Converts a slice to a SIMD vector containing `slice[..LANES]`.
@@ -735,7 +772,7 @@ where
735772
{
736773
#[inline]
737774
fn as_ref(&self) -> &[T; LANES] {
738-
&self.0
775+
self.as_array()
739776
}
740777
}
741778

@@ -746,7 +783,7 @@ where
746783
{
747784
#[inline]
748785
fn as_mut(&mut self) -> &mut [T; LANES] {
749-
&mut self.0
786+
self.as_mut_array()
750787
}
751788
}
752789

@@ -758,7 +795,7 @@ where
758795
{
759796
#[inline]
760797
fn as_ref(&self) -> &[T] {
761-
&self.0
798+
self.as_array()
762799
}
763800
}
764801

@@ -769,7 +806,7 @@ where
769806
{
770807
#[inline]
771808
fn as_mut(&mut self) -> &mut [T] {
772-
&mut self.0
809+
self.as_mut_array()
773810
}
774811
}
775812

0 commit comments

Comments
 (0)