Clean up `ostd-macros`

This commit is contained in:
Ruihan Li 2026-02-07 22:30:09 +08:00 committed by Tate, Hongliang Tian
parent 5f8b019369
commit b86d74344a
3 changed files with 70 additions and 53 deletions

View File

@ -39,8 +39,9 @@ mod default_heap_allocator {
// SAFETY: The name does not collide with other symbols. // SAFETY: The name does not collide with other symbols.
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
#[linkage = "weak"] #[linkage = "weak"]
#[expect(non_snake_case)] fn __global_heap_slot_info_from_layout(
fn __GLOBAL_HEAP_SLOT_INFO_FROM_LAYOUT(layout: core::alloc::Layout) -> Option<ostd::mm::heap::SlotInfo> { layout: core::alloc::Layout,
) -> Option<ostd::mm::heap::SlotInfo> {
type_from_layout(layout) type_from_layout(layout)
} }
} }

View File

@ -9,11 +9,9 @@ use syn::{Expr, Ident, ItemFn, parse_macro_input};
/// A macro attribute to mark the kernel entry point. /// A macro attribute to mark the kernel entry point.
/// ///
/// # Example /// # Examples
/// ///
/// ```ignore /// ```ignore
/// #![no_std]
///
/// use ostd::prelude::*; /// use ostd::prelude::*;
/// ///
/// #[ostd::main] /// #[ostd::main]
@ -33,8 +31,8 @@ pub fn main(_attr: TokenStream, item: TokenStream) -> TokenStream {
extern "Rust" fn __ostd_main() -> ! { extern "Rust" fn __ostd_main() -> ! {
let _: () = #main_fn_name(); let _: () = #main_fn_name();
ostd::task::Task::yield_now(); ::ostd::task::Task::yield_now();
unreachable!("`yield_now` in the boot context should not return"); ::core::unreachable!("`yield_now` in the boot context should not return");
} }
#[expect(unused)] #[expect(unused)]
@ -43,10 +41,11 @@ pub fn main(_attr: TokenStream, item: TokenStream) -> TokenStream {
.into() .into()
} }
/// A macro attribute for the unit test kernel entry point. /// A macro attribute to mark the unit test kernel entry point.
/// ///
/// This macro is used for internal OSDK implementation. Do not use it /// This macro is used for internal OSDK implementation. Do not use it
/// directly. /// directly.
#[doc(hidden)]
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn test_main(_attr: TokenStream, item: TokenStream) -> TokenStream { pub fn test_main(_attr: TokenStream, item: TokenStream) -> TokenStream {
let main_fn = parse_macro_input!(item as ItemFn); let main_fn = parse_macro_input!(item as ItemFn);
@ -58,8 +57,8 @@ pub fn test_main(_attr: TokenStream, item: TokenStream) -> TokenStream {
extern "Rust" fn __ostd_main() -> ! { extern "Rust" fn __ostd_main() -> ! {
let _: () = #main_fn_name(); let _: () = #main_fn_name();
ostd::task::Task::yield_now(); ::ostd::task::Task::yield_now();
unreachable!("`yield_now` in the boot context should not return"); ::core::unreachable!("`yield_now` in the boot context should not return");
} }
#main_fn #main_fn
@ -72,7 +71,7 @@ pub fn test_main(_attr: TokenStream, item: TokenStream) -> TokenStream {
/// The attributed static variable will be used to provide frame allocation /// The attributed static variable will be used to provide frame allocation
/// for the kernel. /// for the kernel.
/// ///
/// # Example /// # Examples
/// ///
/// ```ignore /// ```ignore
/// use core::alloc::Layout; /// use core::alloc::Layout;
@ -94,13 +93,16 @@ pub fn test_main(_attr: TokenStream, item: TokenStream) -> TokenStream {
pub fn global_frame_allocator(_attr: TokenStream, item: TokenStream) -> TokenStream { pub fn global_frame_allocator(_attr: TokenStream, item: TokenStream) -> TokenStream {
// Make a `static __GLOBAL_FRAME_ALLOCATOR_REF: &'static dyn GlobalFrameAllocator` // Make a `static __GLOBAL_FRAME_ALLOCATOR_REF: &'static dyn GlobalFrameAllocator`
// That points to the annotated static variable. // That points to the annotated static variable.
let item = parse_macro_input!(item as syn::ItemStatic); let item = parse_macro_input!(item as syn::ItemStatic);
let static_name = &item.ident; let static_name = &item.ident;
quote!( quote!(
// SAFETY: The name does not collide with other symbols. // SAFETY: The name does not collide with other symbols.
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
static __GLOBAL_FRAME_ALLOCATOR_REF: &'static dyn ostd::mm::frame::GlobalFrameAllocator = &#static_name; static __GLOBAL_FRAME_ALLOCATOR_REF: &'static dyn ::ostd::mm::frame::GlobalFrameAllocator =
&#static_name;
#item #item
) )
.into() .into()
@ -118,7 +120,7 @@ pub fn global_frame_allocator(_attr: TokenStream, item: TokenStream) -> TokenStr
/// implement an unsafe trait. [`macro@global_heap_allocator`] eventually relies on /// implement an unsafe trait. [`macro@global_heap_allocator`] eventually relies on
/// [`global_allocator`] to customize Rust's heap allocator. /// [`global_allocator`] to customize Rust's heap allocator.
/// ///
/// # Example /// # Examples
/// ///
/// ```ignore /// ```ignore
/// use core::alloc::{AllocError, Layout}; /// use core::alloc::{AllocError, Layout};
@ -140,13 +142,16 @@ pub fn global_frame_allocator(_attr: TokenStream, item: TokenStream) -> TokenStr
pub fn global_heap_allocator(_attr: TokenStream, item: TokenStream) -> TokenStream { pub fn global_heap_allocator(_attr: TokenStream, item: TokenStream) -> TokenStream {
// Make a `static __GLOBAL_HEAP_ALLOCATOR_REF: &'static dyn GlobalHeapAllocator` // Make a `static __GLOBAL_HEAP_ALLOCATOR_REF: &'static dyn GlobalHeapAllocator`
// That points to the annotated static variable. // That points to the annotated static variable.
let item = parse_macro_input!(item as syn::ItemStatic); let item = parse_macro_input!(item as syn::ItemStatic);
let static_name = &item.ident; let static_name = &item.ident;
quote!( quote!(
// SAFETY: The name does not collide with other symbols. // SAFETY: The name does not collide with other symbols.
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
static __GLOBAL_HEAP_ALLOCATOR_REF: &'static dyn ostd::mm::heap::GlobalHeapAllocator = &#static_name; static __GLOBAL_HEAP_ALLOCATOR_REF: &'static dyn ::ostd::mm::heap::GlobalHeapAllocator =
&#static_name;
#item #item
) )
.into() .into()
@ -170,9 +175,12 @@ pub fn global_heap_allocator(_attr: TokenStream, item: TokenStream) -> TokenStre
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn global_heap_allocator_slot_map(_attr: TokenStream, item: TokenStream) -> TokenStream { pub fn global_heap_allocator_slot_map(_attr: TokenStream, item: TokenStream) -> TokenStream {
// Rewrite the input `const fn __any_name__(layout: Layout) -> Option<SlotInfo> { ... }` to // Rewrite the input `const fn __any_name__(layout: Layout) -> Option<SlotInfo> { ... }` to
// `const extern "Rust" fn __GLOBAL_HEAP_SLOT_INFO_FROM_LAYOUT(layout: Layout) -> Option<SlotInfo> { ... }`. // `const extern "Rust" fn __global_heap_slot_info_from_layout(layout: Layout) -> Option<SlotInfo> { ... }`.
// Reject if the input is not a `const fn`.
let item = parse_macro_input!(item as syn::ItemFn); let item = parse_macro_input!(item as syn::ItemFn);
let fn_name = &item.sig.ident;
// Reject if the input is not a `const fn`.
assert!( assert!(
item.sig.constness.is_some(), item.sig.constness.is_some(),
"the annotated function must be `const`" "the annotated function must be `const`"
@ -180,7 +188,13 @@ pub fn global_heap_allocator_slot_map(_attr: TokenStream, item: TokenStream) ->
quote!( quote!(
/// SAFETY: The name does not collide with other symbols. /// SAFETY: The name does not collide with other symbols.
#[unsafe(export_name = "__GLOBAL_HEAP_SLOT_INFO_FROM_LAYOUT")] #[unsafe(no_mangle)]
const extern "Rust" fn __global_heap_slot_info_from_layout(
layout: ::core::alloc::Layout,
) -> ::core::option::Option<::ostd::mm::heap::SlotInfo> {
#fn_name(layout)
}
#item #item
) )
.into() .into()
@ -200,7 +214,7 @@ pub fn panic_handler(_attr: TokenStream, item: TokenStream) -> TokenStream {
#[cfg(not(ktest))] #[cfg(not(ktest))]
// SAFETY: The name does not collide with other symbols. // SAFETY: The name does not collide with other symbols.
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
extern "Rust" fn __ostd_panic_handler(info: &core::panic::PanicInfo) -> ! { extern "Rust" fn __ostd_panic_handler(info: &::core::panic::PanicInfo) -> ! {
#handler_fn_name(info); #handler_fn_name(info);
} }
@ -210,10 +224,11 @@ pub fn panic_handler(_attr: TokenStream, item: TokenStream) -> TokenStream {
.into() .into()
} }
/// A macro attribute for the panic handler. /// A macro attribute for the unit test panic handler.
/// ///
/// This macro is used for internal OSDK implementation. Do not use it /// This macro is used for internal OSDK implementation. Do not use it
/// directly. /// directly.
#[doc(hidden)]
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn test_panic_handler(_attr: TokenStream, item: TokenStream) -> TokenStream { pub fn test_panic_handler(_attr: TokenStream, item: TokenStream) -> TokenStream {
let handler_fn = parse_macro_input!(item as ItemFn); let handler_fn = parse_macro_input!(item as ItemFn);
@ -222,7 +237,7 @@ pub fn test_panic_handler(_attr: TokenStream, item: TokenStream) -> TokenStream
quote!( quote!(
// SAFETY: The name does not collide with other symbols. // SAFETY: The name does not collide with other symbols.
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
extern "Rust" fn __ostd_panic_handler(info: &core::panic::PanicInfo) -> ! { extern "Rust" fn __ostd_panic_handler(info: &::core::panic::PanicInfo) -> ! {
#handler_fn_name(info); #handler_fn_name(info);
} }
@ -233,9 +248,9 @@ pub fn test_panic_handler(_attr: TokenStream, item: TokenStream) -> TokenStream
/// The test attribute macro to mark a test function. /// The test attribute macro to mark a test function.
/// ///
/// # Example /// # Examples
/// ///
/// For crates other than ostd, /// For crates other than `ostd`,
/// this macro can be used in the following form. /// this macro can be used in the following form.
/// ///
/// ```ignore /// ```ignore
@ -247,7 +262,7 @@ pub fn test_panic_handler(_attr: TokenStream, item: TokenStream) -> TokenStream
/// } /// }
/// ``` /// ```
/// ///
/// For ostd crate itself, /// For `ostd` crate itself,
/// this macro can be used in the form /// this macro can be used in the form
/// ///
/// ```ignore /// ```ignore
@ -264,11 +279,11 @@ pub fn ktest(_attr: TokenStream, item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as ItemFn); let input = parse_macro_input!(item as ItemFn);
assert!( assert!(
input.sig.inputs.is_empty(), input.sig.inputs.is_empty(),
"ostd::test function should have no arguments" "test functions should have no arguments"
); );
assert!( assert!(
matches!(input.sig.output, syn::ReturnType::Default), matches!(input.sig.output, syn::ReturnType::Default),
"ostd::test function should return `()`" "test functions should return `()`"
); );
// Generate a random identifier to avoid name conflicts. // Generate a random identifier to avoid name conflicts.
@ -300,16 +315,17 @@ pub fn ktest(_attr: TokenStream, item: TokenStream) -> TokenStream {
); );
match &attr.meta { match &attr.meta {
syn::Meta::List(l) => { syn::Meta::List(l) => {
let arg_err_message = "`should_panic` attribute should only have zero or one `expected` argument, with the format of `expected = \"<panic message>\"`"; if let Ok(expected_assign) = syn::parse2::<syn::ExprAssign>(l.tokens.clone())
let expected_assign = && let Expr::Lit(s) = *expected_assign.right
syn::parse2::<syn::ExprAssign>(l.tokens.clone()).expect(arg_err_message); && let syn::Lit::Str(expectation) = s.lit
let Expr::Lit(s) = *expected_assign.right else { {
panic!("{}", arg_err_message);
};
let syn::Lit::Str(expectation) = s.lit else {
panic!("{}", arg_err_message);
};
(true, Some(expectation)) (true, Some(expectation))
} else {
panic!(
"`should_panic` attributes should only have zero or one `expected` argument, \
with the format of `expected = \"<panic message>\"`"
);
}
} }
_ => (true, None), _ => (true, None),
} }
@ -337,14 +353,14 @@ pub fn ktest(_attr: TokenStream, item: TokenStream) -> TokenStream {
#[used] #[used]
// SAFETY: This is properly handled in the linker script. // SAFETY: This is properly handled in the linker script.
#[unsafe(link_section = ".ktest_array")] #[unsafe(link_section = ".ktest_array")]
static #fn_ktest_item_name: ostd_test::KtestItem = ostd_test::KtestItem::new( static #fn_ktest_item_name: ::ostd_test::KtestItem = ::ostd_test::KtestItem::new(
#fn_name, #fn_name,
(#should_panic, #expectation_tokens), (#should_panic, #expectation_tokens),
ostd_test::KtestItemInfo { ::ostd_test::KtestItemInfo {
module_path: module_path!(), module_path: ::core::module_path!(),
fn_name: stringify!(#fn_name), fn_name: ::core::stringify!(#fn_name),
package: #package_name, package: #package_name,
source: file!(), source: ::core::file!(),
line: #line, line: #line,
col: #col, col: #col,
}, },
@ -356,14 +372,14 @@ pub fn ktest(_attr: TokenStream, item: TokenStream) -> TokenStream {
#[used] #[used]
// SAFETY: This is properly handled in the linker script. // SAFETY: This is properly handled in the linker script.
#[unsafe(link_section = ".ktest_array")] #[unsafe(link_section = ".ktest_array")]
static #fn_ktest_item_name: ostd::ktest::KtestItem = ostd::ktest::KtestItem::new( static #fn_ktest_item_name: ::ostd::ktest::KtestItem = ::ostd::ktest::KtestItem::new(
#fn_name, #fn_name,
(#should_panic, #expectation_tokens), (#should_panic, #expectation_tokens),
ostd::ktest::KtestItemInfo { ::ostd::ktest::KtestItemInfo {
module_path: module_path!(), module_path: ::core::module_path!(),
fn_name: stringify!(#fn_name), fn_name: ::core::stringify!(#fn_name),
package: #package_name, package: #package_name,
source: file!(), source: ::core::file!(),
line: #line, line: #line,
col: #col, col: #col,
}, },

View File

@ -58,7 +58,7 @@ unsafe extern "Rust" {
/// Gets the size and type of heap slots to serve allocations of the layout. /// Gets the size and type of heap slots to serve allocations of the layout.
/// See [`crate::global_heap_allocator_slot_map`]. /// See [`crate::global_heap_allocator_slot_map`].
fn __GLOBAL_HEAP_SLOT_INFO_FROM_LAYOUT(layout: Layout) -> Option<SlotInfo>; fn __global_heap_slot_info_from_layout(layout: Layout) -> Option<SlotInfo>;
} }
/// Gets the reference to the user-defined global heap allocator. /// Gets the reference to the user-defined global heap allocator.
@ -75,7 +75,7 @@ fn get_global_heap_allocator() -> &'static dyn GlobalHeapAllocator {
/// See [`crate::global_heap_allocator_slot_map`]. /// See [`crate::global_heap_allocator_slot_map`].
fn slot_size_from_layout(layout: Layout) -> Option<SlotInfo> { fn slot_size_from_layout(layout: Layout) -> Option<SlotInfo> {
// SAFETY: This up-call is redirected safely to Rust code by OSDK. // SAFETY: This up-call is redirected safely to Rust code by OSDK.
unsafe { __GLOBAL_HEAP_SLOT_INFO_FROM_LAYOUT(layout) } unsafe { __global_heap_slot_info_from_layout(layout) }
} }
macro_rules! abort_with_message { macro_rules! abort_with_message {