safe_unaligned_simd/lib.rs
1//! Safe wrappers for unaligned SIMD load and store operations.
2//!
3//! ## Overview
4//!
5//! The goal of this crate is to remove the need for "unnecessary `unsafe`" code
6//! when using vector intrinsics to access memory, with no alignment
7//! requirements.
8//!
9//! Platform-intrinsics that take raw pointers have been wrapped in functions
10//! that receive Rust reference types as arguments.
11//!
12//! ## Safely using platform intrinsics
13//!
14//! Users are responsible for ensuring that the CPU supports the intended target feature.
15//!
16//! Feature detection can be done at compile-time by using `#[cfg]` attributes on functions or at runtime using an `is_[arch]_feature_detected!` macro from `std::arch`.
17//!
18//! `unsafe` is needed to call into functions annotated with `#[target_feature]`, but [it's safe to call other functions with the same target features][rustc-1.86].
19//!
20//! See [the `std::arch` module documentation][stdarch] for a full explanation and [the `rustc` 1.87 release notes][rustc-1.87] for a simple example of runtime feature detection with fallback.
21//!
22//! [rustc-1.86]: https://blog.rust-lang.org/2025/04/03/Rust-1.86.0/#allow-safe-functions-to-be-marked-with-the-target-feature-attribute
23//! [rustc-1.87]: https://blog.rust-lang.org/2025/05/15/Rust-1.87.0/#safe-architecture-intrinsics
24//! [stdarch]: https://doc.rust-lang.org/stable/std/arch/index.html#overview
25//!
26//! ## Supported target architectures
27//!
28//! ### `x86` / `x86_64`
29//! - `sse`, `sse2`, `avx`, `avx512f`, `avx512vl`, `avx512bw`, `avx512vbmi2`
30//!
31//! Some functions have variants that are generic over `Cell` array types,
32//! which allow for mutation of shared references.
33//!
34//! Currently, there is no plan to implement gather/scatter or `avx2` masked
35//! load/store intrinsics for this platform.
36//!
37//! ### `aarch64`, `arm64ec`
38//! - `neon`
39//!
40//! Intrinsics that load / store individual lanes are not designed yet.
41//!
42//! ### `wasm32`
43//! - `simd128`
44//!
45//! ## A note on creating mutable array references from slices
46//!
47//! **_tl;dr:_ Use [`as_mut_array`][as_mut_array] to avoid this bug, stable since `1.93`.**
48//!
49//! Beware of accidentally creating mutable references to temporary arrays.
50//!
51//! Rust will implicitly clone an array from a slice and return a mutable reference to that clone if not wrapped properly in parentheses.
52//!
53//! ```rust,ignore
54//! # let mut chunk = [0u8; 8];
55//! // Valid mutable array reference creation
56//! let out_data: &mut [u8; 4] = chunk[..4].as_mut_array().unwrap(); // since 1.93
57//! let out_data: &mut [u8; 4] = (&mut chunk[..4]).try_into().unwrap();
58//! let out_data = TryInto::<&mut [u8; 4]>::try_into(&mut chunk[..4]).unwrap();
59//!
60//! // Incorrect creation of a mutable reference: this clones the chunk and returns
61//! // a mutable reference to the copy. If we modify `out_data` after this point,
62//! // the changes will not reflect back in our original `chunk` slice.
63//! // 🚫🈲⛔❌ - Do not use the following line
64//! let out_data = &mut chunk[..4].try_into().unwrap();
65//! # *out_data = [1u8; 4];
66//! ```
67//!
68//! The now-stable [`as_mut_array`][as_mut_array] sidesteps this issue entirely.<br>
69//!
70//! [as_mut_array]: https://doc.rust-lang.org/1.93.0/std/primitive.slice.html#method.as_mut_array
71#![forbid(missing_docs, non_ascii_idents)]
72#![cfg_attr(not(test), no_std)]
73
74#[cfg(any(target_arch = "x86", target_arch = "x86_64", target_arch = "wasm32",))]
75mod common_traits;
76
77#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))]
78pub mod aarch64;
79
80#[cfg(target_arch = "wasm32")]
81pub mod wasm32;
82
83#[cfg(target_arch = "x86")]
84pub mod x86;
85
86#[cfg(target_arch = "x86_64")]
87mod x86;
88#[cfg(target_arch = "x86_64")]
89pub mod x86_64 {
90 //! Platform-specific intrinsics for `x86_64`.
91
92 #[cfg(target_arch = "x86_64")]
93 pub use crate::x86::*;
94}