xref: /linux/rust/macros/io/register.rs (revision 5d7f3375cd574fc83f0cd30839b21455c0e79ae2)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 //! Documentation and usage example of the macro can be found at `rust/kernel/io/register.rs`.
4 
5 use proc_macro2::{
6     Group,
7     Literal,
8     Span,
9     TokenStream, //
10 };
11 use quote::{
12     quote,
13     quote_spanned, //
14 };
15 use syn::{
16     bracketed,
17     parenthesized,
18     parse::Parse,
19     parse_quote,
20     spanned::Spanned,
21     token,
22     Attribute,
23     Error,
24     Expr,
25     Ident,
26     Path,
27     Result,
28     Token,
29     Type,
30     Visibility, //
31 };
32 
33 mod kw {
34     syn::custom_keyword!(base);
35     syn::custom_keyword!(stride);
36 }
37 
38 /// Definition of a register array.
39 ///
40 /// Specify a size, and optionally a stride. Syntax is of form `[EXPR $(, stride = EXPR)?]`.
41 struct RegArrayDef {
42     size: Expr,
43     stride: Option<Expr>,
44 }
45 
46 /// Offset of a register.
47 ///
48 /// Can be either of form
49 /// * `@ offset` for fixed offset
50 /// * `=> alias` for alias of register `alias`.
51 /// * `=> alias[idx]` for alias of register array `alias`'s `idx`-th element.
52 enum RegOffset {
53     /// Register is located at fixed address.
54     Fixed { offset: Literal },
55     /// Register is an alias of a fixed register.
56     Alias { alias: Path },
57     /// Register is an alias of an element of a register array.
58     ElementAlias { alias: Path, idx: Expr },
59 }
60 
61 /// Definition of a single register.
62 struct Reg {
63     attrs: Vec<Attribute>,
64     vis: Visibility,
65     name: Ident,
66     unique: bool,
67     ty: Type,
68     array: Option<RegArrayDef>,
69     offset: RegOffset,
70     bitfield: Option<(Type, Group)>,
71 }
72 
73 impl Parse for Reg {
74     fn parse(input: syn::parse::ParseStream<'_>) -> Result<Self> {
75         let attrs = input.call(Attribute::parse_outer)?;
76         let vis = input.parse()?;
77         let name = input.parse()?;
78 
79         let lh = input.lookahead1();
80         let (unique, ty, bitfield_storage) = if lh.peek(Token![:]) {
81             let _: Token![:] = input.parse()?;
82 
83             let mut attrs = input.call(Attribute::parse_outer)?;
84             let unique = attrs
85                 .extract_if(.., |attr| attr.path().is_ident("unique"))
86                 .count()
87                 != 0;
88             if !attrs.is_empty() {
89                 Err(Error::new_spanned(&attrs[0], "unexpected attributes"))?
90             }
91 
92             (unique, input.parse()?, None)
93         } else if lh.peek(token::Paren) {
94             let content;
95             parenthesized!(content in input);
96             let bitfield_storage = Some(content.parse()?);
97 
98             // For bitfields, bitfield macro will generate a type with the same name as `name`.
99             (true, parse_quote!(#name), bitfield_storage)
100         } else {
101             Err(lh.error())?
102         };
103 
104         let array = if input.peek(token::Bracket) {
105             let content;
106             bracketed!(content in input);
107             let size = content.parse()?;
108             let stride = if content.peek(Token![,]) {
109                 let _: Token![,] = content.parse()?;
110                 let _: kw::stride = content.parse()?;
111                 let _: Token![=] = content.parse()?;
112                 Some(content.parse()?)
113             } else {
114                 None
115             };
116             Some(RegArrayDef { size, stride })
117         } else {
118             None
119         };
120 
121         // Parse offset and the base it's relative to.
122         let lh = input.lookahead1();
123         let offset = if lh.peek(Token![@]) {
124             let _: Token![@] = input.parse()?;
125 
126             RegOffset::Fixed {
127                 offset: input.parse()?,
128             }
129         } else if lh.peek(Token![=>]) {
130             let _: Token![=>] = input.parse()?;
131             let alias: Path = input.parse()?;
132 
133             if input.peek(token::Bracket) {
134                 let content;
135                 bracketed!(content in input);
136                 RegOffset::ElementAlias {
137                     alias,
138                     idx: content.parse()?,
139                 }
140             } else {
141                 RegOffset::Alias { alias }
142             }
143         } else {
144             Err(lh.error())?
145         };
146 
147         let bitfield = if let Some(storage) = bitfield_storage {
148             let lh = input.lookahead1();
149             let args = if lh.peek(token::Brace) {
150                 input.parse()?
151             } else {
152                 Err(lh.error())?
153             };
154             Some((storage, args))
155         } else {
156             let _: Token![;] = input.parse()?;
157             None
158         };
159 
160         Ok(Self {
161             attrs,
162             vis,
163             name,
164             unique,
165             ty,
166             array,
167             offset,
168             bitfield,
169         })
170     }
171 }
172 
173 pub(crate) struct RegDef {
174     base: Type,
175     regs: Vec<Reg>,
176 }
177 
178 impl Parse for RegDef {
179     fn parse(input: syn::parse::ParseStream<'_>) -> Result<Self> {
180         let _: kw::base = input.parse().map_err(|e| {
181             Error::new(
182                 e.span(),
183                 "a base type needs to be specified for `register!` invocation with `base: ty;`",
184             )
185         })?;
186 
187         let _: Token![:] = input.parse()?;
188         let base = input.parse()?;
189         let _: Token![;] = input.parse()?;
190 
191         let mut regs = Vec::new();
192         while !input.is_empty() {
193             regs.push(input.parse()?);
194         }
195         Ok(RegDef { base, regs })
196     }
197 }
198 
199 pub(crate) fn register(def: RegDef) -> Result<TokenStream> {
200     let mut outputs = TokenStream::new();
201 
202     let base = &def.base;
203     for reg in def.regs {
204         let Reg {
205             attrs,
206             vis,
207             name,
208             unique,
209             ty,
210             array,
211             offset,
212             bitfield,
213         } = reg;
214 
215         // Use register name's span for generated code, so error messages (if any) can point to it
216         // instead of the entire register allocation.
217         let span = name.span().resolved_at(Span::mixed_site());
218 
219         let offset = match offset {
220             RegOffset::Fixed { offset } => quote!(#offset),
221             RegOffset::Alias { alias } => {
222                 quote_spanned!(alias.span().resolved_at(span) =>
223                     ::kernel::io::register::OffsetLoc::<#base, _>::const_offset(#alias)
224                 )
225             }
226             RegOffset::ElementAlias { alias, idx } => {
227                 quote_spanned!(alias.span().resolved_at(span) =>
228                     ::kernel::io::register::element_alias_offset::<#base, #alias>(#idx)
229                 )
230             }
231         };
232 
233         if let Some((storage, args)) = &bitfield {
234             outputs.extend(quote_spanned!(span =>
235                 ::kernel::bitfield!(
236                     // `#[allow(non_camel_case_types)]` is added since register names typically use
237                     // `SCREAMING_CASE`.
238                     #[allow(non_camel_case_types)]
239                     #(#attrs)* #vis struct #name(#storage) #args
240                 );
241             ));
242         }
243 
244         match array {
245             None => {
246                 if unique {
247                     outputs.extend(quote!(
248                         impl ::kernel::io::register::FixedIoLoc<#base> for #ty {
249                             type Location = ::kernel::io::register::OffsetLoc<#base, #ty>;
250                             const LOCATION: Self::Location = #name;
251                         }
252                     ))
253                 }
254 
255                 outputs.extend(quote_spanned!(span =>
256                     #(#attrs)* #vis const #name: ::kernel::io::register::OffsetLoc<#base, #ty> =
257                         ::kernel::io::register::OffsetLoc::new(#offset);
258                 ));
259             }
260 
261             Some(def) => {
262                 if bitfield.is_none() {
263                     Err(Error::new_spanned(
264                         &ty,
265                         "defining without bitfield is not yet supported for this type of register",
266                     ))?
267                 }
268 
269                 let size = &def.size;
270                 let stride = if let Some(stride) = &def.stride {
271                     outputs.extend(quote_spanned!(stride.span().resolved_at(span) =>
272                         ::kernel::build_assert::static_assert!(
273                             ::core::mem::size_of::<#ty>() <= #stride
274                         );
275                     ));
276                     quote!(#stride)
277                 } else {
278                     quote_spanned!(span => ::core::mem::size_of::<#ty>())
279                 };
280 
281                 outputs.extend(quote_spanned!(span =>
282                     impl ::kernel::io::register::Array for #name {}
283 
284                     impl ::kernel::io::register::RegisterArray for #name {
285                         type Base = #base;
286                         const OFFSET: usize = #offset;
287                         const SIZE: usize = #size;
288                         const STRIDE: usize = #stride;
289                     }
290                 ));
291             }
292         };
293     }
294 
295     Ok(outputs)
296 }
297