xref: /linux/rust/kernel/mem.rs (revision ef605a433d80987e97fcf62a41bdf437abc61e2c)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 //! Basic utilities for dealing with memory, values, and types.
4 
5 use crate::prelude::*;
6 
7 /// Transmute between two types.
8 ///
9 /// Use this instead of [`core::mem::transmute`] when it is known that sizes are identical but this
10 /// cannot be proven by the compiler.
11 ///
12 /// This is equivalent to Rust's `transmute_unchecked` intrinsics.
13 ///
14 /// # Safety
15 ///
16 /// All safety requirements of [`core::mem::transmute`] apply, plus that the size `Src` and `Dst`
17 /// must match.
18 ///
19 /// # Examples
20 ///
21 /// This can be used when types are known to have the same size, but only at runtime.
22 ///
23 /// ```no_run
24 /// # use core::any::TypeId;
25 /// fn to_u32<T: 'static>(v: T) -> Option<u32> {
26 ///     if TypeId::of::<T>() != TypeId::of::<u32>() {
27 ///         return None;
28 ///     }
29 ///
30 ///     // `core::mem::transmute` won't work here.
31 ///     // SAFETY: We've checked that `T` is `u32`!
32 ///     Some(unsafe { kernel::mem::transmute_unchecked(v) })
33 /// }
34 ///
35 /// to_u32(1u32);
36 /// ```
37 #[inline(always)]
38 pub const unsafe fn transmute_unchecked<Src, Dst>(val: Src) -> Dst {
39     // SAFETY: This is identical to `transmute` except that we bypassed the size check; which is
40     // true per safety requirement.
41     unsafe { core::mem::transmute_copy(&core::mem::ManuallyDrop::new(val)) }
42 }
43 
44 /// Version of `transmute` that performs size check at monomorphization-time.
45 ///
46 /// Use this instead of [`core::mem::transmute`] when it is known that sizes are identical but this
47 /// cannot be proven by the compiler during type checking and can be proven during monomorphization.
48 ///
49 /// The signature is equivalent to Rust standard library's unstable `transmute_neo` and that of
50 /// [RFC 3844](https://github.com/rust-lang/rfcs/pull/3844).
51 ///
52 /// # Safety
53 ///
54 /// Same as [`core::mem::transmute`].
55 ///
56 /// # Examples
57 ///
58 /// This is typically used in generic code where it's known that type will have the same size, but
59 /// the compiler cannot prove it generically.
60 ///
61 /// ```no_run
62 /// trait IsU32 {}
63 /// impl IsU32 for u32 {}
64 ///
65 /// fn to_u32<T: IsU32>(v: T) -> u32 {
66 ///     // `core::mem::transmute` won't work here.
67 ///     // SAFETY: We know that `v` is u32!
68 ///     unsafe { kernel::mem::transmute(v) }
69 /// }
70 ///
71 /// to_u32(1u32);
72 /// ```
73 #[inline(always)]
74 pub const unsafe fn transmute<Src, Dst>(val: Src) -> Dst {
75     const_assert!(size_of::<Src>() == size_of::<Dst>());
76 
77     // SAFETY: Size is checked above. Other safety requirements follow those of the function.
78     unsafe { transmute_unchecked(val) }
79 }
80 
81 /// Safely transmutes a value of one type to a value of another type of the same size.
82 ///
83 /// The sizes are checked during monomorphization.
84 ///
85 /// This can be considered as generic version of [`zerocopy::transmute!`] macro that defers the size
86 /// check and thus can be used in more cases.
87 ///
88 /// # Examples
89 ///
90 /// ```no_run
91 /// fn to_u32<T: FromBytes + IntoBytes>(v: T) -> u32 {
92 ///     // `zerocopy::transmute!` won't work here.
93 ///     kernel::mem::safe_transmute(v)
94 /// }
95 ///
96 /// to_u32(1i32);
97 /// ```
98 #[inline(always)]
99 pub const fn safe_transmute<Src: IntoBytes, Dst: FromBytes>(val: Src) -> Dst {
100     // SAFETY: `transmute` is safe with `IntoBytes` and `FromBytes` bounds.
101     unsafe { transmute(val) }
102 }
103 
104 /// Type that is layout-compatible with a primitive representation.
105 ///
106 /// # Safety
107 ///
108 /// - [`Self`] must have the same size and alignment as [`Self::Repr`].
109 /// - [`Self`] must be [transmutable] to [`Self::Repr`].
110 /// - Neither [`Self`] nor [`Self::Repr`] contains interior mutability.
111 ///
112 /// The above basically says that `&Self` can be transmuted to `&Self::Repr`.
113 ///
114 /// [transmutable]: core::mem::transmute
115 pub unsafe trait AsRepr: Sized {
116     /// Primitive representation of this type.
117     type Repr;
118 
119     /// Convert from [`&Self`](Self) to [`&Self::Repr`](AsRepr::Repr).
120     #[inline(always)]
121     fn as_repr(this: &Self) -> &Self::Repr {
122         // SAFETY: Per safety requirement of the trait.
123         unsafe { core::mem::transmute(this) }
124     }
125 
126     /// Convert from [`Self`] to [`Self::Repr`].
127     #[inline(always)]
128     fn into_repr(this: Self) -> Self::Repr {
129         // SAFETY: Per safety requirement of the trait.
130         unsafe { transmute(this) }
131     }
132 
133     /// Convert from [`Self::Repr`] to [`Self`].
134     ///
135     /// # Safety
136     ///
137     /// `repr` must be a valid bit pattern of [`Self`] and satisfy type-specific invariants of it.
138     ///
139     /// Alternatively, if `repr` is previously obtained using [`Self::into_repr`], and each
140     /// `from_repr_unchecked` should correspond to a unique `into_repr` call, then it is safe to
141     /// call as well (this means that we're undoing a `into_repr` call getting the exact bytes
142     /// back).
143     ///
144     /// No guarantee is made if the result of a `into_repr` is passed to multiple
145     /// `from_repr_unchecked` (i.e. copies are made), to allow for cases where `Repr` is a pointer
146     /// and the user of the API wants ownership transfer. Users that want the ability to call
147     /// `from_repr_unchecked` after copying can require `Copy` bound explicitly.
148     #[inline(always)]
149     unsafe fn from_repr_unchecked(repr: Self::Repr) -> Self {
150         // SAFETY: Per safety requirement, `repr` is valid repr of `Self`, or it is previously from
151         // `into_repr`, in which case we're undoing the transmute so it is also safe.
152         unsafe { transmute(repr) }
153     }
154 }
155 
156 /// Type that is bi-directionally transmutable with a primitive representation.
157 ///
158 /// # Safety
159 ///
160 /// - [`Self`] must be [transmutable] from [`Self::Repr`].
161 ///
162 /// [transmutable]: core::mem::transmute
163 /// [`Self::Repr`]: AsRepr::Repr
164 pub unsafe trait AsReprMut: AsRepr {
165     /// Convert from `&mut Self` to [`&mut Self::Repr`](AsRepr::Repr).
166     #[inline(always)]
167     fn as_repr_mut(this: &mut Self) -> &mut Self::Repr {
168         // SAFETY: Per safety requirement of the trait.
169         unsafe { core::mem::transmute(this) }
170     }
171 
172     /// Convert from [`Self::Repr`](AsRepr::Repr) to `Self`.
173     #[inline(always)]
174     fn from_repr(repr: Self::Repr) -> Self {
175         // SAFETY: Per safety requirement of the trait.
176         unsafe { transmute(repr) }
177     }
178 }
179 
180 // SAFETY: `bool` has the same size and alignment as `u8`, and Rust guarantees that `bool` has
181 // only two valid bit patterns: 0 (`false`) and 1 (`true`). Thus `bool` can be transmuted to `u8`.
182 // Neither types contain interior mutability.
183 unsafe impl AsRepr for bool {
184     type Repr = u8;
185 }
186 
187 // SAFETY: `*mut T` has the same size and alignment with `*const c_void`, and thus `*mut T` is
188 // transmutable to `*const c_void`. Neither types contain interior mutability.
189 unsafe impl<T> AsRepr for *mut T {
190     type Repr = *const c_void;
191 }
192 
193 // SAFETY: `*mut T` is transmutable from `*const c_void`.
194 unsafe impl<T> AsReprMut for *mut T {}
195 
196 // SAFETY: `*const T` has the same size and alignment with `*const c_void`, and is transmutable to
197 // `*const c_void`. Neither types contain interior mutability.
198 unsafe impl<T> AsRepr for *const T {
199     type Repr = *const c_void;
200 }
201 
202 // SAFETY: `*const T` is transmutable from `*const c_void`.
203 unsafe impl<T> AsReprMut for *const T {}
204 
205 macro_rules! int_impl {
206     ($($unsigned:ident $signed:ident ,)*) => {$(
207         // SAFETY: `$unsigned` has the same size and alignment with itself, and is transmutable to
208         // itself. It does not contain interior mutability.
209         unsafe impl AsRepr for $unsigned {
210             type Repr = $unsigned;
211         }
212 
213         // SAFETY: `$unsigned` is transmutable from itself.
214         unsafe impl AsReprMut for $unsigned {}
215 
216         // SAFETY: `$signed` has the same size and alignment with `$unsigned`, and is transmutable
217         // to it Neither types contain interior mutability.
218         unsafe impl AsRepr for $signed {
219             type Repr = $unsigned;
220         }
221 
222         // SAFETY: `$signed` is transmutable from `$unsigned`.
223         unsafe impl AsReprMut for $signed {}
224     )*};
225 }
226 
227 int_impl! {
228     u8 i8,
229     u16 i16,
230     u32 i32,
231     u64 i64,
232     // `usize` is not normalized to particular integer for portability.
233     usize isize,
234 }
235