|
5 | 5 | #[path = "third_party/rust/layout.rs"] |
6 | 6 | pub(crate) mod core_layout; |
7 | 7 |
|
8 | | -use core::mem; |
| 8 | +use core::{mem, num::NonZeroUsize}; |
9 | 9 |
|
10 | 10 | pub(crate) trait AsAddress { |
11 | 11 | fn addr(self) -> usize; |
@@ -56,6 +56,27 @@ pub(crate) fn aligned_to<T: AsAddress, U>(t: T) -> bool { |
56 | 56 | remainder == 0 |
57 | 57 | } |
58 | 58 |
|
| 59 | +/// Round `n` down to the largest value `m` such that `m <= n` and `m % align == |
| 60 | +/// 0`. |
| 61 | +/// |
| 62 | +/// # Panics |
| 63 | +/// |
| 64 | +/// May panic if `align` is not a power of two. Even if it doesn't panic in this |
| 65 | +/// case, it will produce nonsense results. |
| 66 | +#[inline(always)] |
| 67 | +pub(crate) const fn _round_down_to_next_multiple_of_alignment( |
| 68 | + n: usize, |
| 69 | + align: NonZeroUsize, |
| 70 | +) -> usize { |
| 71 | + let align = align.get(); |
| 72 | + debug_assert!(align.is_power_of_two()); |
| 73 | + |
| 74 | + // Subtraction can't underflow because `align.get() >= 1`. |
| 75 | + #[allow(clippy::arithmetic_side_effects)] |
| 76 | + let mask = !(align - 1); |
| 77 | + n & mask |
| 78 | +} |
| 79 | + |
59 | 80 | #[cfg(test)] |
60 | 81 | pub(crate) mod testutil { |
61 | 82 | use core::fmt::{self, Display, Formatter}; |
@@ -106,3 +127,25 @@ pub(crate) mod testutil { |
106 | 127 |
|
107 | 128 | impl_known_layout!(AU64); |
108 | 129 | } |
| 130 | + |
| 131 | +#[cfg(test)] |
| 132 | +mod tests { |
| 133 | + use super::*; |
| 134 | + |
| 135 | + #[test] |
| 136 | + fn test_round_down_to_next_multiple_of_alignment() { |
| 137 | + fn alt_impl(n: usize, align: NonZeroUsize) -> usize { |
| 138 | + let mul = n / align.get(); |
| 139 | + mul * align.get() |
| 140 | + } |
| 141 | + |
| 142 | + for align in [1, 2, 4, 8, 16] { |
| 143 | + for n in 0..256 { |
| 144 | + let align = NonZeroUsize::new(align).unwrap(); |
| 145 | + let want = alt_impl(n, align); |
| 146 | + let got = _round_down_to_next_multiple_of_alignment(n, align); |
| 147 | + assert_eq!(got, want, "round_down_to_next_multiple_of_alignment({n}, {align})"); |
| 148 | + } |
| 149 | + } |
| 150 | + } |
| 151 | +} |
0 commit comments