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