Clean up `ostd-macros`
This commit is contained in:
parent
5f8b019369
commit
b86d74344a
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue