Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0
2
3//! Bitfield library for Rust structures
4//!
5//! Support for defining bitfields in Rust structures. Also used by the [`register!`] macro.
6
7/// Defines a struct with accessors to access bits within an inner unsigned integer.
8///
9/// # Syntax
10///
11/// ```rust
12/// use nova_core::bitfield;
13///
14/// #[derive(Debug, Clone, Copy, Default)]
15/// enum Mode {
16/// #[default]
17/// Low = 0,
18/// High = 1,
19/// Auto = 2,
20/// }
21///
22/// impl TryFrom<u8> for Mode {
23/// type Error = u8;
24/// fn try_from(value: u8) -> Result<Self, Self::Error> {
25/// match value {
26/// 0 => Ok(Mode::Low),
27/// 1 => Ok(Mode::High),
28/// 2 => Ok(Mode::Auto),
29/// _ => Err(value),
30/// }
31/// }
32/// }
33///
34/// impl From<Mode> for u8 {
35/// fn from(mode: Mode) -> u8 {
36/// mode as u8
37/// }
38/// }
39///
40/// #[derive(Debug, Clone, Copy, Default)]
41/// enum State {
42/// #[default]
43/// Inactive = 0,
44/// Active = 1,
45/// }
46///
47/// impl From<bool> for State {
48/// fn from(value: bool) -> Self {
49/// if value { State::Active } else { State::Inactive }
50/// }
51/// }
52///
53/// impl From<State> for bool {
54/// fn from(state: State) -> bool {
55/// match state {
56/// State::Inactive => false,
57/// State::Active => true,
58/// }
59/// }
60/// }
61///
62/// bitfield! {
63/// pub struct ControlReg(u32) {
64/// 7:7 state as bool => State;
65/// 3:0 mode as u8 ?=> Mode;
66/// }
67/// }
68/// ```
69///
70/// This generates a struct with:
71/// - Field accessors: `mode()`, `state()`, etc.
72/// - Field setters: `set_mode()`, `set_state()`, etc. (supports chaining with builder pattern).
73/// Note that the compiler will error out if the size of the setter's arg exceeds the
74/// struct's storage size.
75/// - Debug and Default implementations.
76///
77/// Note: Field accessors and setters inherit the same visibility as the struct itself.
78/// In the example above, both `mode()` and `set_mode()` methods will be `pub`.
79///
80/// Fields are defined as follows:
81///
82/// - `as <type>` simply returns the field value casted to <type>, typically `u32`, `u16`, `u8` or
83/// `bool`. Note that `bool` fields must have a range of 1 bit.
84/// - `as <type> => <into_type>` calls `<into_type>`'s `From::<<type>>` implementation and returns
85/// the result.
86/// - `as <type> ?=> <try_into_type>` calls `<try_into_type>`'s `TryFrom::<<type>>` implementation
87/// and returns the result. This is useful with fields for which not all values are valid.
88macro_rules! bitfield {
89 // Main entry point - defines the bitfield struct with fields
90 ($vis:vis struct $name:ident($storage:ty) $(, $comment:literal)? { $($fields:tt)* }) => {
91 bitfield!(@core $vis $name $storage $(, $comment)? { $($fields)* });
92 };
93
94 // All rules below are helpers.
95
96 // Defines the wrapper `$name` type, as well as its relevant implementations (`Debug`,
97 // `Default`, and conversion to the value type) and field accessor methods.
98 (@core $vis:vis $name:ident $storage:ty $(, $comment:literal)? { $($fields:tt)* }) => {
99 $(
100 #[doc=$comment]
101 )?
102 #[repr(transparent)]
103 #[derive(Clone, Copy)]
104 $vis struct $name($storage);
105
106 impl ::core::convert::From<$name> for $storage {
107 fn from(val: $name) -> $storage {
108 val.0
109 }
110 }
111
112 bitfield!(@fields_dispatcher $vis $name $storage { $($fields)* });
113 };
114
115 // Captures the fields and passes them to all the implementers that require field information.
116 //
117 // Used to simplify the matching rules for implementers, so they don't need to match the entire
118 // complex fields rule even though they only make use of part of it.
119 (@fields_dispatcher $vis:vis $name:ident $storage:ty {
120 $($hi:tt:$lo:tt $field:ident as $type:tt
121 $(?=> $try_into_type:ty)?
122 $(=> $into_type:ty)?
123 $(, $comment:literal)?
124 ;
125 )*
126 }
127 ) => {
128 bitfield!(@field_accessors $vis $name $storage {
129 $(
130 $hi:$lo $field as $type
131 $(?=> $try_into_type)?
132 $(=> $into_type)?
133 $(, $comment)?
134 ;
135 )*
136 });
137 bitfield!(@debug $name { $($field;)* });
138 bitfield!(@default $name { $($field;)* });
139 };
140
141 // Defines all the field getter/setter methods for `$name`.
142 (
143 @field_accessors $vis:vis $name:ident $storage:ty {
144 $($hi:tt:$lo:tt $field:ident as $type:tt
145 $(?=> $try_into_type:ty)?
146 $(=> $into_type:ty)?
147 $(, $comment:literal)?
148 ;
149 )*
150 }
151 ) => {
152 $(
153 bitfield!(@check_field_bounds $hi:$lo $field as $type);
154 )*
155
156 #[allow(dead_code)]
157 impl $name {
158 $(
159 bitfield!(@field_accessor $vis $name $storage, $hi:$lo $field as $type
160 $(?=> $try_into_type)?
161 $(=> $into_type)?
162 $(, $comment)?
163 ;
164 );
165 )*
166 }
167 };
168
169 // Boolean fields must have `$hi == $lo`.
170 (@check_field_bounds $hi:tt:$lo:tt $field:ident as bool) => {
171 #[allow(clippy::eq_op)]
172 const _: () = {
173 ::kernel::build_assert!(
174 $hi == $lo,
175 concat!("boolean field `", stringify!($field), "` covers more than one bit")
176 );
177 };
178 };
179
180 // Non-boolean fields must have `$hi >= $lo`.
181 (@check_field_bounds $hi:tt:$lo:tt $field:ident as $type:tt) => {
182 #[allow(clippy::eq_op)]
183 const _: () = {
184 ::kernel::build_assert!(
185 $hi >= $lo,
186 concat!("field `", stringify!($field), "`'s MSB is smaller than its LSB")
187 );
188 };
189 };
190
191 // Catches fields defined as `bool` and convert them into a boolean value.
192 (
193 @field_accessor $vis:vis $name:ident $storage:ty, $hi:tt:$lo:tt $field:ident as bool
194 => $into_type:ty $(, $comment:literal)?;
195 ) => {
196 bitfield!(
197 @leaf_accessor $vis $name $storage, $hi:$lo $field
198 { |f| <$into_type>::from(f != 0) }
199 bool $into_type => $into_type $(, $comment)?;
200 );
201 };
202
203 // Shortcut for fields defined as `bool` without the `=>` syntax.
204 (
205 @field_accessor $vis:vis $name:ident $storage:ty, $hi:tt:$lo:tt $field:ident as bool
206 $(, $comment:literal)?;
207 ) => {
208 bitfield!(
209 @field_accessor $vis $name $storage, $hi:$lo $field as bool => bool $(, $comment)?;
210 );
211 };
212
213 // Catches the `?=>` syntax for non-boolean fields.
214 (
215 @field_accessor $vis:vis $name:ident $storage:ty, $hi:tt:$lo:tt $field:ident as $type:tt
216 ?=> $try_into_type:ty $(, $comment:literal)?;
217 ) => {
218 bitfield!(@leaf_accessor $vis $name $storage, $hi:$lo $field
219 { |f| <$try_into_type>::try_from(f as $type) } $type $try_into_type =>
220 ::core::result::Result<
221 $try_into_type,
222 <$try_into_type as ::core::convert::TryFrom<$type>>::Error
223 >
224 $(, $comment)?;);
225 };
226
227 // Catches the `=>` syntax for non-boolean fields.
228 (
229 @field_accessor $vis:vis $name:ident $storage:ty, $hi:tt:$lo:tt $field:ident as $type:tt
230 => $into_type:ty $(, $comment:literal)?;
231 ) => {
232 bitfield!(@leaf_accessor $vis $name $storage, $hi:$lo $field
233 { |f| <$into_type>::from(f as $type) } $type $into_type => $into_type $(, $comment)?;);
234 };
235
236 // Shortcut for non-boolean fields defined without the `=>` or `?=>` syntax.
237 (
238 @field_accessor $vis:vis $name:ident $storage:ty, $hi:tt:$lo:tt $field:ident as $type:tt
239 $(, $comment:literal)?;
240 ) => {
241 bitfield!(
242 @field_accessor $vis $name $storage, $hi:$lo $field as $type => $type $(, $comment)?;
243 );
244 };
245
246 // Generates the accessor methods for a single field.
247 (
248 @leaf_accessor $vis:vis $name:ident $storage:ty, $hi:tt:$lo:tt $field:ident
249 { $process:expr } $prim_type:tt $to_type:ty => $res_type:ty $(, $comment:literal)?;
250 ) => {
251 ::kernel::macros::paste!(
252 const [<$field:upper _RANGE>]: ::core::ops::RangeInclusive<u8> = $lo..=$hi;
253 const [<$field:upper _MASK>]: $storage = {
254 // Generate mask for shifting
255 match ::core::mem::size_of::<$storage>() {
256 1 => ::kernel::bits::genmask_u8($lo..=$hi) as $storage,
257 2 => ::kernel::bits::genmask_u16($lo..=$hi) as $storage,
258 4 => ::kernel::bits::genmask_u32($lo..=$hi) as $storage,
259 8 => ::kernel::bits::genmask_u64($lo..=$hi) as $storage,
260 _ => ::kernel::build_error!("Unsupported storage type size")
261 }
262 };
263 const [<$field:upper _SHIFT>]: u32 = $lo;
264 );
265
266 $(
267 #[doc="Returns the value of this field:"]
268 #[doc=$comment]
269 )?
270 #[inline(always)]
271 $vis fn $field(self) -> $res_type {
272 ::kernel::macros::paste!(
273 const MASK: $storage = $name::[<$field:upper _MASK>];
274 const SHIFT: u32 = $name::[<$field:upper _SHIFT>];
275 );
276 let field = ((self.0 & MASK) >> SHIFT);
277
278 $process(field)
279 }
280
281 ::kernel::macros::paste!(
282 $(
283 #[doc="Sets the value of this field:"]
284 #[doc=$comment]
285 )?
286 #[inline(always)]
287 $vis fn [<set_ $field>](mut self, value: $to_type) -> Self {
288 const MASK: $storage = $name::[<$field:upper _MASK>];
289 const SHIFT: u32 = $name::[<$field:upper _SHIFT>];
290 let value = ($storage::from($prim_type::from(value)) << SHIFT) & MASK;
291 self.0 = (self.0 & !MASK) | value;
292
293 self
294 }
295 );
296 };
297
298 // Generates the `Debug` implementation for `$name`.
299 (@debug $name:ident { $($field:ident;)* }) => {
300 impl ::kernel::fmt::Debug for $name {
301 fn fmt(&self, f: &mut ::kernel::fmt::Formatter<'_>) -> ::kernel::fmt::Result {
302 f.debug_struct(stringify!($name))
303 .field("<raw>", &::kernel::prelude::fmt!("{:#x}", &self.0))
304 $(
305 .field(stringify!($field), &self.$field())
306 )*
307 .finish()
308 }
309 }
310 };
311
312 // Generates the `Default` implementation for `$name`.
313 (@default $name:ident { $($field:ident;)* }) => {
314 /// Returns a value for the bitfield where all fields are set to their default value.
315 impl ::core::default::Default for $name {
316 fn default() -> Self {
317 #[allow(unused_mut)]
318 let mut value = Self(Default::default());
319
320 ::kernel::macros::paste!(
321 $(
322 value.[<set_ $field>](Default::default());
323 )*
324 );
325
326 value
327 }
328 }
329 };
330}