Skip to content

Commit 7ce4d16

Browse files
authored
Merge pull request #270 from rust-osdev/align
Make align_up and align_down const
2 parents 134cacd + 45d7c84 commit 7ce4d16

File tree

3 files changed

+28
-13
lines changed

3 files changed

+28
-13
lines changed

src/addr.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -531,21 +531,25 @@ impl Sub<PhysAddr> for PhysAddr {
531531

532532
/// Align address downwards.
533533
///
534-
/// Returns the greatest x with alignment `align` so that x <= addr. The alignment must be
535-
/// a power of 2.
534+
/// Returns the greatest `x` with alignment `align` so that `x <= addr`.
535+
///
536+
/// Panics if the alignment is not a power of two. Without the `const_fn`
537+
/// feature, the panic message will be "index out of bounds".
536538
#[inline]
537-
pub fn align_down(addr: u64, align: u64) -> u64 {
538-
assert!(align.is_power_of_two(), "`align` must be a power of two");
539+
pub const fn align_down(addr: u64, align: u64) -> u64 {
540+
const_assert!(align.is_power_of_two(), "`align` must be a power of two");
539541
addr & !(align - 1)
540542
}
541543

542544
/// Align address upwards.
543545
///
544-
/// Returns the smallest x with alignment `align` so that x >= addr. The alignment must be
545-
/// a power of 2.
546+
/// Returns the smallest `x` with alignment `align` so that `x >= addr`.
547+
///
548+
/// Panics if the alignment is not a power of two. Without the `const_fn`
549+
/// feature, the panic message will be "index out of bounds".
546550
#[inline]
547-
pub fn align_up(addr: u64, align: u64) -> u64 {
548-
assert!(align.is_power_of_two(), "`align` must be a power of two");
551+
pub const fn align_up(addr: u64, align: u64) -> u64 {
552+
const_assert!(align.is_power_of_two(), "`align` must be a power of two");
549553
let align_mask = align - 1;
550554
if addr & align_mask == 0 {
551555
addr // already aligned

src/lib.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,19 @@ macro_rules! const_fn {
4545
};
4646
}
4747

48+
// Helper method for assert! in const fn. Uses out of bounds indexing if an
49+
// assertion fails and the "const_fn" feature is not enabled.
50+
#[cfg(feature = "const_fn")]
51+
macro_rules! const_assert {
52+
($cond:expr, $($arg:tt)+) => { assert!($cond, $($arg)*) };
53+
}
54+
#[cfg(not(feature = "const_fn"))]
55+
macro_rules! const_assert {
56+
($cond:expr, $($arg:tt)+) => {
57+
[(); 1][!($cond as bool) as usize]
58+
};
59+
}
60+
4861
#[cfg(all(feature = "instructions", feature = "external_asm"))]
4962
pub(crate) mod asm;
5063

src/structures/gdt.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,13 +117,10 @@ impl GlobalDescriptorTable {
117117
let mut table = [0; 8];
118118
let mut idx = 0;
119119

120-
#[cfg(feature = "const_fn")]
121-
assert!(
120+
const_assert!(
122121
next_free <= 8,
123122
"initializing a GDT from a slice requires it to be **at most** 8 elements."
124123
);
125-
#[cfg(not(feature = "const_fn"))]
126-
[(); 1][!(next_free <= 8) as usize];
127124

128125
while idx != next_free {
129126
table[idx] = slice[idx];
@@ -144,7 +141,8 @@ impl GlobalDescriptorTable {
144141
const_fn! {
145142
/// Adds the given segment descriptor to the GDT, returning the segment selector.
146143
///
147-
/// Panics if the GDT has no free entries left.
144+
/// Panics if the GDT has no free entries left. Without the `const_fn`
145+
/// feature, the panic message will be "index out of bounds".
148146
#[inline]
149147
pub fn add_entry(&mut self, entry: Descriptor) -> SegmentSelector {
150148
let index = match entry {

0 commit comments

Comments
 (0)