Skip to content

Commit

Permalink
Merge pull request #270 from rust-osdev/align
Browse files Browse the repository at this point in the history
Make align_up and align_down const
  • Loading branch information
josephlr authored Jul 16, 2021
2 parents 134cacd + 45d7c84 commit 7ce4d16
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 13 deletions.
20 changes: 12 additions & 8 deletions src/addr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -531,21 +531,25 @@ impl Sub<PhysAddr> for PhysAddr {

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

/// Align address upwards.
///
/// Returns the smallest x with alignment `align` so that x >= addr. The alignment must be
/// a power of 2.
/// Returns the smallest `x` with alignment `align` so that `x >= addr`.
///
/// Panics if the alignment is not a power of two. Without the `const_fn`
/// feature, the panic message will be "index out of bounds".
#[inline]
pub fn align_up(addr: u64, align: u64) -> u64 {
assert!(align.is_power_of_two(), "`align` must be a power of two");
pub const fn align_up(addr: u64, align: u64) -> u64 {
const_assert!(align.is_power_of_two(), "`align` must be a power of two");
let align_mask = align - 1;
if addr & align_mask == 0 {
addr // already aligned
Expand Down
13 changes: 13 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,19 @@ macro_rules! const_fn {
};
}

// Helper method for assert! in const fn. Uses out of bounds indexing if an
// assertion fails and the "const_fn" feature is not enabled.
#[cfg(feature = "const_fn")]
macro_rules! const_assert {
($cond:expr, $($arg:tt)+) => { assert!($cond, $($arg)*) };
}
#[cfg(not(feature = "const_fn"))]
macro_rules! const_assert {
($cond:expr, $($arg:tt)+) => {
[(); 1][!($cond as bool) as usize]
};
}

#[cfg(all(feature = "instructions", feature = "external_asm"))]
pub(crate) mod asm;

Expand Down
8 changes: 3 additions & 5 deletions src/structures/gdt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,10 @@ impl GlobalDescriptorTable {
let mut table = [0; 8];
let mut idx = 0;

#[cfg(feature = "const_fn")]
assert!(
const_assert!(
next_free <= 8,
"initializing a GDT from a slice requires it to be **at most** 8 elements."
);
#[cfg(not(feature = "const_fn"))]
[(); 1][!(next_free <= 8) as usize];

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

0 comments on commit 7ce4d16

Please sign in to comment.