Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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