xref: /linux/rust/macros/lib.rs (revision 823d4737d4c226699f4378b71675822f5ebe78ba)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 //! Crate for all kernel procedural macros.
4 
5 #[macro_use]
6 mod quote;
7 mod concat_idents;
8 mod helpers;
9 mod module;
10 mod paste;
11 mod pin_data;
12 mod pinned_drop;
13 mod vtable;
14 
15 use proc_macro::TokenStream;
16 
17 /// Declares a kernel module.
18 ///
19 /// The `type` argument should be a type which implements the [`Module`]
20 /// trait. Also accepts various forms of kernel metadata.
21 ///
22 /// C header: [`include/linux/moduleparam.h`](../../../include/linux/moduleparam.h)
23 ///
24 /// [`Module`]: ../kernel/trait.Module.html
25 ///
26 /// # Examples
27 ///
28 /// ```ignore
29 /// use kernel::prelude::*;
30 ///
31 /// module!{
32 ///     type: MyModule,
33 ///     name: "my_kernel_module",
34 ///     author: "Rust for Linux Contributors",
35 ///     description: "My very own kernel module!",
36 ///     license: "GPL",
37 ///     params: {
38 ///        my_i32: i32 {
39 ///            default: 42,
40 ///            permissions: 0o000,
41 ///            description: "Example of i32",
42 ///        },
43 ///        writeable_i32: i32 {
44 ///            default: 42,
45 ///            permissions: 0o644,
46 ///            description: "Example of i32",
47 ///        },
48 ///    },
49 /// }
50 ///
51 /// struct MyModule;
52 ///
53 /// impl kernel::Module for MyModule {
54 ///     fn init() -> Result<Self> {
55 ///         // If the parameter is writeable, then the kparam lock must be
56 ///         // taken to read the parameter:
57 ///         {
58 ///             let lock = THIS_MODULE.kernel_param_lock();
59 ///             pr_info!("i32 param is:  {}\n", writeable_i32.read(&lock));
60 ///         }
61 ///         // If the parameter is read only, it can be read without locking
62 ///         // the kernel parameters:
63 ///         pr_info!("i32 param is:  {}\n", my_i32.read());
64 ///         Ok(Self)
65 ///     }
66 /// }
67 /// ```
68 ///
69 /// # Supported argument types
70 ///   - `type`: type which implements the [`Module`] trait (required).
71 ///   - `name`: byte array of the name of the kernel module (required).
72 ///   - `author`: byte array of the author of the kernel module.
73 ///   - `description`: byte array of the description of the kernel module.
74 ///   - `license`: byte array of the license of the kernel module (required).
75 ///   - `alias`: byte array of alias name of the kernel module.
76 #[proc_macro]
77 pub fn module(ts: TokenStream) -> TokenStream {
78     module::module(ts)
79 }
80 
81 /// Declares or implements a vtable trait.
82 ///
83 /// Linux's use of pure vtables is very close to Rust traits, but they differ
84 /// in how unimplemented functions are represented. In Rust, traits can provide
85 /// default implementation for all non-required methods (and the default
86 /// implementation could just return `Error::EINVAL`); Linux typically use C
87 /// `NULL` pointers to represent these functions.
88 ///
89 /// This attribute is intended to close the gap. Traits can be declared and
90 /// implemented with the `#[vtable]` attribute, and a `HAS_*` associated constant
91 /// will be generated for each method in the trait, indicating if the implementor
92 /// has overridden a method.
93 ///
94 /// This attribute is not needed if all methods are required.
95 ///
96 /// # Examples
97 ///
98 /// ```ignore
99 /// use kernel::prelude::*;
100 ///
101 /// // Declares a `#[vtable]` trait
102 /// #[vtable]
103 /// pub trait Operations: Send + Sync + Sized {
104 ///     fn foo(&self) -> Result<()> {
105 ///         Err(EINVAL)
106 ///     }
107 ///
108 ///     fn bar(&self) -> Result<()> {
109 ///         Err(EINVAL)
110 ///     }
111 /// }
112 ///
113 /// struct Foo;
114 ///
115 /// // Implements the `#[vtable]` trait
116 /// #[vtable]
117 /// impl Operations for Foo {
118 ///     fn foo(&self) -> Result<()> {
119 /// #        Err(EINVAL)
120 ///         // ...
121 ///     }
122 /// }
123 ///
124 /// assert_eq!(<Foo as Operations>::HAS_FOO, true);
125 /// assert_eq!(<Foo as Operations>::HAS_BAR, false);
126 /// ```
127 #[proc_macro_attribute]
128 pub fn vtable(attr: TokenStream, ts: TokenStream) -> TokenStream {
129     vtable::vtable(attr, ts)
130 }
131 
132 /// Concatenate two identifiers.
133 ///
134 /// This is useful in macros that need to declare or reference items with names
135 /// starting with a fixed prefix and ending in a user specified name. The resulting
136 /// identifier has the span of the second argument.
137 ///
138 /// # Examples
139 ///
140 /// ```ignore
141 /// use kernel::macro::concat_idents;
142 ///
143 /// macro_rules! pub_no_prefix {
144 ///     ($prefix:ident, $($newname:ident),+) => {
145 ///         $(pub(crate) const $newname: u32 = kernel::macros::concat_idents!($prefix, $newname);)+
146 ///     };
147 /// }
148 ///
149 /// pub_no_prefix!(
150 ///     binder_driver_return_protocol_,
151 ///     BR_OK,
152 ///     BR_ERROR,
153 ///     BR_TRANSACTION,
154 ///     BR_REPLY,
155 ///     BR_DEAD_REPLY,
156 ///     BR_TRANSACTION_COMPLETE,
157 ///     BR_INCREFS,
158 ///     BR_ACQUIRE,
159 ///     BR_RELEASE,
160 ///     BR_DECREFS,
161 ///     BR_NOOP,
162 ///     BR_SPAWN_LOOPER,
163 ///     BR_DEAD_BINDER,
164 ///     BR_CLEAR_DEATH_NOTIFICATION_DONE,
165 ///     BR_FAILED_REPLY
166 /// );
167 ///
168 /// assert_eq!(BR_OK, binder_driver_return_protocol_BR_OK);
169 /// ```
170 #[proc_macro]
171 pub fn concat_idents(ts: TokenStream) -> TokenStream {
172     concat_idents::concat_idents(ts)
173 }
174 
175 /// Used to specify the pinning information of the fields of a struct.
176 ///
177 /// This is somewhat similar in purpose as
178 /// [pin-project-lite](https://crates.io/crates/pin-project-lite).
179 /// Place this macro on a struct definition and then `#[pin]` in front of the attributes of each
180 /// field you want to structurally pin.
181 ///
182 /// This macro enables the use of the [`pin_init!`] macro. When pin-initializing a `struct`,
183 /// then `#[pin]` directs the type of initializer that is required.
184 ///
185 /// If your `struct` implements `Drop`, then you need to add `PinnedDrop` as arguments to this
186 /// macro, and change your `Drop` implementation to `PinnedDrop` annotated with
187 /// `#[`[`macro@pinned_drop`]`]`, since dropping pinned values requires extra care.
188 ///
189 /// # Examples
190 ///
191 /// ```rust,ignore
192 /// #[pin_data]
193 /// struct DriverData {
194 ///     #[pin]
195 ///     queue: Mutex<Vec<Command>>,
196 ///     buf: Box<[u8; 1024 * 1024]>,
197 /// }
198 /// ```
199 ///
200 /// ```rust,ignore
201 /// #[pin_data(PinnedDrop)]
202 /// struct DriverData {
203 ///     #[pin]
204 ///     queue: Mutex<Vec<Command>>,
205 ///     buf: Box<[u8; 1024 * 1024]>,
206 ///     raw_info: *mut Info,
207 /// }
208 ///
209 /// #[pinned_drop]
210 /// impl PinnedDrop for DriverData {
211 ///     fn drop(self: Pin<&mut Self>) {
212 ///         unsafe { bindings::destroy_info(self.raw_info) };
213 ///     }
214 /// }
215 /// ```
216 ///
217 /// [`pin_init!`]: ../kernel/macro.pin_init.html
218 //  ^ cannot use direct link, since `kernel` is not a dependency of `macros`.
219 #[proc_macro_attribute]
220 pub fn pin_data(inner: TokenStream, item: TokenStream) -> TokenStream {
221     pin_data::pin_data(inner, item)
222 }
223 
224 /// Used to implement `PinnedDrop` safely.
225 ///
226 /// Only works on structs that are annotated via `#[`[`macro@pin_data`]`]`.
227 ///
228 /// # Examples
229 ///
230 /// ```rust,ignore
231 /// #[pin_data(PinnedDrop)]
232 /// struct DriverData {
233 ///     #[pin]
234 ///     queue: Mutex<Vec<Command>>,
235 ///     buf: Box<[u8; 1024 * 1024]>,
236 ///     raw_info: *mut Info,
237 /// }
238 ///
239 /// #[pinned_drop]
240 /// impl PinnedDrop for DriverData {
241 ///     fn drop(self: Pin<&mut Self>) {
242 ///         unsafe { bindings::destroy_info(self.raw_info) };
243 ///     }
244 /// }
245 /// ```
246 #[proc_macro_attribute]
247 pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
248     pinned_drop::pinned_drop(args, input)
249 }
250 
251 /// Paste identifiers together.
252 ///
253 /// Within the `paste!` macro, identifiers inside `[<` and `>]` are concatenated together to form a
254 /// single identifier.
255 ///
256 /// This is similar to the [`paste`] crate, but with pasting feature limited to identifiers
257 /// (literals, lifetimes and documentation strings are not supported). There is a difference in
258 /// supported modifiers as well.
259 ///
260 /// # Example
261 ///
262 /// ```ignore
263 /// use kernel::macro::paste;
264 ///
265 /// macro_rules! pub_no_prefix {
266 ///     ($prefix:ident, $($newname:ident),+) => {
267 ///         paste! {
268 ///             $(pub(crate) const $newname: u32 = [<$prefix $newname>];)+
269 ///         }
270 ///     };
271 /// }
272 ///
273 /// pub_no_prefix!(
274 ///     binder_driver_return_protocol_,
275 ///     BR_OK,
276 ///     BR_ERROR,
277 ///     BR_TRANSACTION,
278 ///     BR_REPLY,
279 ///     BR_DEAD_REPLY,
280 ///     BR_TRANSACTION_COMPLETE,
281 ///     BR_INCREFS,
282 ///     BR_ACQUIRE,
283 ///     BR_RELEASE,
284 ///     BR_DECREFS,
285 ///     BR_NOOP,
286 ///     BR_SPAWN_LOOPER,
287 ///     BR_DEAD_BINDER,
288 ///     BR_CLEAR_DEATH_NOTIFICATION_DONE,
289 ///     BR_FAILED_REPLY
290 /// );
291 ///
292 /// assert_eq!(BR_OK, binder_driver_return_protocol_BR_OK);
293 /// ```
294 ///
295 /// # Modifiers
296 ///
297 /// For each identifier, it is possible to attach one or multiple modifiers to
298 /// it.
299 ///
300 /// Currently supported modifiers are:
301 /// * `span`: change the span of concatenated identifier to the span of the specified token. By
302 /// default the span of the `[< >]` group is used.
303 /// * `lower`: change the identifier to lower case.
304 /// * `upper`: change the identifier to upper case.
305 ///
306 /// ```ignore
307 /// use kernel::macro::paste;
308 ///
309 /// macro_rules! pub_no_prefix {
310 ///     ($prefix:ident, $($newname:ident),+) => {
311 ///         kernel::macros::paste! {
312 ///             $(pub(crate) const fn [<$newname:lower:span>]: u32 = [<$prefix $newname:span>];)+
313 ///         }
314 ///     };
315 /// }
316 ///
317 /// pub_no_prefix!(
318 ///     binder_driver_return_protocol_,
319 ///     BR_OK,
320 ///     BR_ERROR,
321 ///     BR_TRANSACTION,
322 ///     BR_REPLY,
323 ///     BR_DEAD_REPLY,
324 ///     BR_TRANSACTION_COMPLETE,
325 ///     BR_INCREFS,
326 ///     BR_ACQUIRE,
327 ///     BR_RELEASE,
328 ///     BR_DECREFS,
329 ///     BR_NOOP,
330 ///     BR_SPAWN_LOOPER,
331 ///     BR_DEAD_BINDER,
332 ///     BR_CLEAR_DEATH_NOTIFICATION_DONE,
333 ///     BR_FAILED_REPLY
334 /// );
335 ///
336 /// assert_eq!(br_ok(), binder_driver_return_protocol_BR_OK);
337 /// ```
338 ///
339 /// [`paste`]: https://docs.rs/paste/
340 #[proc_macro]
341 pub fn paste(input: TokenStream) -> TokenStream {
342     let mut tokens = input.into_iter().collect();
343     paste::expand(&mut tokens);
344     tokens.into_iter().collect()
345 }
346