From 8758b75aac12cfec471032d704bb44447e8aa091 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 10 Jul 2022 16:13:01 +0200 Subject: [PATCH] Re-implement concat_idents! in libmacros MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This removes an unstable feature used by kernel modules. The new proc macro also has different behavior with respect to macro hygiene. Unlike the unstable concat_idents! macro it for example allows referring to local variables by taking the span of the second macro as span for the output identifier. Signed-off-by: Björn Roy Baron --- drivers/android/defs.rs | 2 +- rust/kernel/lib.rs | 3 ++- rust/macros/concat_idents.rs | 23 +++++++++++++++++++ rust/macros/lib.rs | 44 ++++++++++++++++++++++++++++++++++++ scripts/Makefile.build | 2 +- 5 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 rust/macros/concat_idents.rs diff --git a/drivers/android/defs.rs b/drivers/android/defs.rs index ec2dde9b3dd84c..925e751a2564a5 100644 --- a/drivers/android/defs.rs +++ b/drivers/android/defs.rs @@ -9,7 +9,7 @@ use kernel::{ macro_rules! pub_no_prefix { ($prefix:ident, $($newname:ident),+) => { - $(pub(crate) const $newname: u32 = concat_idents!($prefix, $newname);)+ + $(pub(crate) const $newname: u32 = kernel::macros::concat_idents!($prefix, $newname);)+ }; } diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index d752b6f6352f2a..efb0dd3ca06cfa 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -14,7 +14,6 @@ #![no_std] #![feature(allocator_api)] #![feature(associated_type_defaults)] -#![feature(concat_idents)] #![feature(const_mut_refs)] #![feature(const_ptr_offset_from)] #![feature(const_refs_to_cell)] @@ -41,6 +40,8 @@ mod allocator; #[doc(hidden)] pub use bindings; +pub use macros; + #[cfg(CONFIG_ARM_AMBA)] pub mod amba; pub mod chrdev; diff --git a/rust/macros/concat_idents.rs b/rust/macros/concat_idents.rs new file mode 100644 index 00000000000000..3b5a9dd70e8a2b --- /dev/null +++ b/rust/macros/concat_idents.rs @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0 + +use proc_macro::{token_stream, Ident, TokenStream, TokenTree}; + +use crate::helpers::expect_punct; + +fn expect_ident(it: &mut token_stream::IntoIter) -> Ident { + if let Some(TokenTree::Ident(ident)) = it.next() { + ident + } else { + panic!("Expected Ident") + } +} + +pub(crate) fn concat_idents(ts: TokenStream) -> TokenStream { + let mut it = ts.into_iter(); + let a = expect_ident(&mut it); + assert_eq!(expect_punct(&mut it), ','); + let b = expect_ident(&mut it); + assert!(it.next().is_none(), "only two idents can be concatenated"); + let res = Ident::new(&(a.to_string() + &b.to_string()), b.span()); + TokenStream::from_iter([TokenTree::Ident(res)]) +} diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs index 43e07b259a2d56..4f1b44b23e7593 100644 --- a/rust/macros/lib.rs +++ b/rust/macros/lib.rs @@ -2,6 +2,7 @@ //! Crate for all kernel procedural macros. +mod concat_idents; mod helpers; mod module; mod vtable; @@ -144,3 +145,46 @@ pub fn module(ts: TokenStream) -> TokenStream { pub fn vtable(attr: TokenStream, ts: TokenStream) -> TokenStream { vtable::vtable(attr, ts) } + +/// Concatenate two identifiers. +/// +/// This is useful in macros that need to declare or reference items with names +/// starting with a fixed prefix and ending in a user specified name. The resulting +/// identifier has the span of the second argument. +/// +/// # Examples +/// +/// ```ignore +/// use kernel::macro::concat_idents; +/// +/// macro_rules! pub_no_prefix { +/// ($prefix:ident, $($newname:ident),+) => { +/// $(pub(crate) const $newname: u32 = kernel::macros::concat_idents!($prefix, $newname);)+ +/// }; +/// } +/// +/// pub_no_prefix!( +/// binder_driver_return_protocol_, +/// BR_OK, +/// BR_ERROR, +/// BR_TRANSACTION, +/// BR_REPLY, +/// BR_DEAD_REPLY, +/// BR_TRANSACTION_COMPLETE, +/// BR_INCREFS, +/// BR_ACQUIRE, +/// BR_RELEASE, +/// BR_DECREFS, +/// BR_NOOP, +/// BR_SPAWN_LOOPER, +/// BR_DEAD_BINDER, +/// BR_CLEAR_DEATH_NOTIFICATION_DONE, +/// BR_FAILED_REPLY +/// ); +/// +/// assert_eq!(BR_OK, binder_driver_return_protocol_BR_OK); +/// ``` +#[proc_macro] +pub fn concat_idents(ts: TokenStream) -> TokenStream { + concat_idents::concat_idents(ts) +} diff --git a/scripts/Makefile.build b/scripts/Makefile.build index a9e6b51485b234..86c5260631c9b7 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -275,7 +275,7 @@ $(obj)/%.lst: $(src)/%.c FORCE # Compile Rust sources (.rs) # --------------------------------------------------------------------------- -rust_allowed_features := allocator_api,bench_black_box,concat_idents,core_ffi_c,generic_associated_types,const_ptr_offset_from,const_refs_to_cell +rust_allowed_features := allocator_api,bench_black_box,core_ffi_c,generic_associated_types,const_ptr_offset_from,const_refs_to_cell rust_common_cmd = \ RUST_MODFILE=$(modfile) $(RUSTC_OR_CLIPPY) $(rust_flags) \