Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/rust/kernel/bits.rs
48999 views
1
// SPDX-License-Identifier: GPL-2.0
2
3
//! Bit manipulation macros.
4
//!
5
//! C header: [`include/linux/bits.h`](srctree/include/linux/bits.h)
6
7
use crate::prelude::*;
8
use core::ops::RangeInclusive;
9
use macros::paste;
10
11
macro_rules! impl_bit_fn {
12
(
13
$ty:ty
14
) => {
15
paste! {
16
/// Computes `1 << n` if `n` is in bounds, i.e.: if `n` is smaller than
17
/// the maximum number of bits supported by the type.
18
///
19
/// Returns [`None`] otherwise.
20
#[inline]
21
pub fn [<checked_bit_ $ty>](n: u32) -> Option<$ty> {
22
(1 as $ty).checked_shl(n)
23
}
24
25
/// Computes `1 << n` by performing a compile-time assertion that `n` is
26
/// in bounds.
27
///
28
/// This version is the default and should be used if `n` is known at
29
/// compile time.
30
// Always inline to optimize out error path of `build_assert`.
31
#[inline(always)]
32
pub const fn [<bit_ $ty>](n: u32) -> $ty {
33
build_assert!(n < <$ty>::BITS);
34
(1 as $ty) << n
35
}
36
}
37
};
38
}
39
40
impl_bit_fn!(u64);
41
impl_bit_fn!(u32);
42
impl_bit_fn!(u16);
43
impl_bit_fn!(u8);
44
45
macro_rules! impl_genmask_fn {
46
(
47
$ty:ty,
48
$(#[$genmask_checked_ex:meta])*,
49
$(#[$genmask_ex:meta])*
50
) => {
51
paste! {
52
/// Creates a contiguous bitmask for the given range by validating
53
/// the range at runtime.
54
///
55
/// Returns [`None`] if the range is invalid, i.e.: if the start is
56
/// greater than the end or if the range is outside of the
57
/// representable range for the type.
58
$(#[$genmask_checked_ex])*
59
#[inline]
60
pub fn [<genmask_checked_ $ty>](range: RangeInclusive<u32>) -> Option<$ty> {
61
let start = *range.start();
62
let end = *range.end();
63
64
if start > end {
65
return None;
66
}
67
68
let high = [<checked_bit_ $ty>](end)?;
69
let low = [<checked_bit_ $ty>](start)?;
70
Some((high | (high - 1)) & !(low - 1))
71
}
72
73
/// Creates a compile-time contiguous bitmask for the given range by
74
/// performing a compile-time assertion that the range is valid.
75
///
76
/// This version is the default and should be used if the range is known
77
/// at compile time.
78
$(#[$genmask_ex])*
79
// Always inline to optimize out error path of `build_assert`.
80
#[inline(always)]
81
pub const fn [<genmask_ $ty>](range: RangeInclusive<u32>) -> $ty {
82
let start = *range.start();
83
let end = *range.end();
84
85
build_assert!(start <= end);
86
87
let high = [<bit_ $ty>](end);
88
let low = [<bit_ $ty>](start);
89
(high | (high - 1)) & !(low - 1)
90
}
91
}
92
};
93
}
94
95
impl_genmask_fn!(
96
u64,
97
/// # Examples
98
///
99
/// ```
100
/// # #![expect(clippy::reversed_empty_ranges)]
101
/// # use kernel::bits::genmask_checked_u64;
102
/// assert_eq!(genmask_checked_u64(0..=0), Some(0b1));
103
/// assert_eq!(genmask_checked_u64(0..=63), Some(u64::MAX));
104
/// assert_eq!(genmask_checked_u64(21..=39), Some(0x0000_00ff_ffe0_0000));
105
///
106
/// // `80` is out of the supported bit range.
107
/// assert_eq!(genmask_checked_u64(21..=80), None);
108
///
109
/// // Invalid range where the start is bigger than the end.
110
/// assert_eq!(genmask_checked_u64(15..=8), None);
111
/// ```
112
,
113
/// # Examples
114
///
115
/// ```
116
/// # use kernel::bits::genmask_u64;
117
/// assert_eq!(genmask_u64(21..=39), 0x0000_00ff_ffe0_0000);
118
/// assert_eq!(genmask_u64(0..=0), 0b1);
119
/// assert_eq!(genmask_u64(0..=63), u64::MAX);
120
/// ```
121
);
122
123
impl_genmask_fn!(
124
u32,
125
/// # Examples
126
///
127
/// ```
128
/// # #![expect(clippy::reversed_empty_ranges)]
129
/// # use kernel::bits::genmask_checked_u32;
130
/// assert_eq!(genmask_checked_u32(0..=0), Some(0b1));
131
/// assert_eq!(genmask_checked_u32(0..=31), Some(u32::MAX));
132
/// assert_eq!(genmask_checked_u32(21..=31), Some(0xffe0_0000));
133
///
134
/// // `40` is out of the supported bit range.
135
/// assert_eq!(genmask_checked_u32(21..=40), None);
136
///
137
/// // Invalid range where the start is bigger than the end.
138
/// assert_eq!(genmask_checked_u32(15..=8), None);
139
/// ```
140
,
141
/// # Examples
142
///
143
/// ```
144
/// # use kernel::bits::genmask_u32;
145
/// assert_eq!(genmask_u32(21..=31), 0xffe0_0000);
146
/// assert_eq!(genmask_u32(0..=0), 0b1);
147
/// assert_eq!(genmask_u32(0..=31), u32::MAX);
148
/// ```
149
);
150
151
impl_genmask_fn!(
152
u16,
153
/// # Examples
154
///
155
/// ```
156
/// # #![expect(clippy::reversed_empty_ranges)]
157
/// # use kernel::bits::genmask_checked_u16;
158
/// assert_eq!(genmask_checked_u16(0..=0), Some(0b1));
159
/// assert_eq!(genmask_checked_u16(0..=15), Some(u16::MAX));
160
/// assert_eq!(genmask_checked_u16(6..=15), Some(0xffc0));
161
///
162
/// // `20` is out of the supported bit range.
163
/// assert_eq!(genmask_checked_u16(6..=20), None);
164
///
165
/// // Invalid range where the start is bigger than the end.
166
/// assert_eq!(genmask_checked_u16(10..=5), None);
167
/// ```
168
,
169
/// # Examples
170
///
171
/// ```
172
/// # use kernel::bits::genmask_u16;
173
/// assert_eq!(genmask_u16(6..=15), 0xffc0);
174
/// assert_eq!(genmask_u16(0..=0), 0b1);
175
/// assert_eq!(genmask_u16(0..=15), u16::MAX);
176
/// ```
177
);
178
179
impl_genmask_fn!(
180
u8,
181
/// # Examples
182
///
183
/// ```
184
/// # #![expect(clippy::reversed_empty_ranges)]
185
/// # use kernel::bits::genmask_checked_u8;
186
/// assert_eq!(genmask_checked_u8(0..=0), Some(0b1));
187
/// assert_eq!(genmask_checked_u8(0..=7), Some(u8::MAX));
188
/// assert_eq!(genmask_checked_u8(6..=7), Some(0xc0));
189
///
190
/// // `10` is out of the supported bit range.
191
/// assert_eq!(genmask_checked_u8(6..=10), None);
192
///
193
/// // Invalid range where the start is bigger than the end.
194
/// assert_eq!(genmask_checked_u8(5..=2), None);
195
/// ```
196
,
197
/// # Examples
198
///
199
/// ```
200
/// # use kernel::bits::genmask_u8;
201
/// assert_eq!(genmask_u8(6..=7), 0xc0);
202
/// assert_eq!(genmask_u8(0..=0), 0b1);
203
/// assert_eq!(genmask_u8(0..=7), u8::MAX);
204
/// ```
205
);
206
207