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