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 ty: Type, 67 array: Option<RegArrayDef>, 68 relative_base: Option<Path>, 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 (ty, bitfield_storage) = if lh.peek(Token![:]) { 81 let _: Token![:] = input.parse()?; 82 (input.parse()?, None) 83 } else if lh.peek(token::Paren) { 84 let content; 85 parenthesized!(content in input); 86 let bitfield_storage = Some(content.parse()?); 87 88 // For bitfields, bitfield macro will generate a type with the same name as `name`. 89 (parse_quote!(#name), bitfield_storage) 90 } else { 91 Err(lh.error())? 92 }; 93 94 let array = if input.peek(token::Bracket) { 95 let content; 96 bracketed!(content in input); 97 let size = content.parse()?; 98 let stride = if content.peek(Token![,]) { 99 let _: Token![,] = content.parse()?; 100 let _: kw::stride = content.parse()?; 101 let _: Token![=] = content.parse()?; 102 Some(content.parse()?) 103 } else { 104 None 105 }; 106 Some(RegArrayDef { size, stride }) 107 } else { 108 None 109 }; 110 111 // Parse offset and the base it's relative to. 112 let lh = input.lookahead1(); 113 let mut relative_base = None; 114 let offset = if lh.peek(Token![@]) { 115 let _: Token![@] = input.parse()?; 116 117 if input.peek(Ident) { 118 relative_base = Some(input.parse()?); 119 let _: Token![+] = input.parse()?; 120 } 121 122 RegOffset::Fixed { 123 offset: input.parse()?, 124 } 125 } else if lh.peek(Token![=>]) { 126 let _: Token![=>] = input.parse()?; 127 let mut alias: Path = input.parse()?; 128 if input.peek(Token![+]) { 129 let _: Token![+] = input.parse()?; 130 relative_base = Some(alias); 131 alias = input.parse()?; 132 } 133 134 if input.peek(token::Bracket) { 135 let content; 136 bracketed!(content in input); 137 RegOffset::ElementAlias { 138 alias, 139 idx: content.parse()?, 140 } 141 } else { 142 RegOffset::Alias { alias } 143 } 144 } else { 145 Err(lh.error())? 146 }; 147 148 let bitfield = if let Some(storage) = bitfield_storage { 149 let lh = input.lookahead1(); 150 let args = if lh.peek(token::Brace) { 151 input.parse()? 152 } else { 153 Err(lh.error())? 154 }; 155 Some((storage, args)) 156 } else { 157 let _: Token![;] = input.parse()?; 158 None 159 }; 160 161 Ok(Self { 162 attrs, 163 vis, 164 name, 165 ty, 166 array, 167 relative_base, 168 offset, 169 bitfield, 170 }) 171 } 172 } 173 174 pub(crate) struct RegDef { 175 base: Type, 176 regs: Vec<Reg>, 177 } 178 179 impl Parse for RegDef { 180 fn parse(input: syn::parse::ParseStream<'_>) -> Result<Self> { 181 let _: kw::base = input.parse().map_err(|e| { 182 Error::new( 183 e.span(), 184 "a base type needs to be specified for `register!` invocation with `base: ty;`", 185 ) 186 })?; 187 188 let _: Token![:] = input.parse()?; 189 let base = input.parse()?; 190 let _: Token![;] = input.parse()?; 191 192 let mut regs = Vec::new(); 193 while !input.is_empty() { 194 regs.push(input.parse()?); 195 } 196 Ok(RegDef { base, regs }) 197 } 198 } 199 200 pub(crate) fn register(def: RegDef) -> Result<TokenStream> { 201 let mut outputs = TokenStream::new(); 202 203 let base = &def.base; 204 for reg in def.regs { 205 let Reg { 206 attrs, 207 vis, 208 name, 209 ty, 210 array, 211 relative_base, 212 offset, 213 bitfield, 214 } = reg; 215 216 // Use register name's span for generated code, so error messages (if any) can point to it 217 // instead of the entire register allocation. 218 let span = name.span().resolved_at(Span::mixed_site()); 219 220 let offset = match offset { 221 RegOffset::Fixed { offset } => quote!(#offset), 222 RegOffset::Alias { alias } => { 223 quote_spanned!(alias.span().resolved_at(span) => 224 ::kernel::io::register::alias_offset::<#base, #alias>() 225 ) 226 } 227 RegOffset::ElementAlias { alias, idx } => { 228 quote_spanned!(alias.span().resolved_at(span) => 229 ::kernel::io::register::element_alias_offset::<#base, #alias>(#idx) 230 ) 231 } 232 }; 233 234 if let Some((storage, args)) = &bitfield { 235 outputs.extend(quote_spanned!(span => 236 ::kernel::bitfield!( 237 // `#[allow(non_camel_case_types)]` is added since register names typically use 238 // `SCREAMING_CASE`. 239 #[allow(non_camel_case_types)] 240 #(#attrs)* #vis struct #name(#storage) #args 241 ); 242 243 impl ::kernel::io::register::Register for #name { 244 type Base = #base; 245 const OFFSET: usize = #offset; 246 } 247 )); 248 } 249 250 match array { 251 None if bitfield.is_none() && relative_base.is_none() => outputs.extend(quote!( 252 #(#attrs)* #vis const #name: ::kernel::io::register::OffsetLoc<#base, #ty> = 253 ::kernel::io::register::OffsetLoc::new(#offset); 254 )), 255 256 _ if bitfield.is_none() => Err(Error::new_spanned( 257 ty, 258 "defining without bitfield is not yet supported for this type of register", 259 ))?, 260 261 None => match relative_base { 262 None => outputs.extend(quote_spanned!(span => 263 impl ::kernel::io::register::FixedRegister for #name {} 264 265 #(#attrs)* #vis const #name: ::kernel::io::register::FixedRegisterLoc<#name> = 266 ::kernel::io::register::FixedRegisterLoc::<#name>::new(); 267 )), 268 Some(relative_base) => outputs.extend(quote_spanned!(span => 269 impl ::kernel::io::register::WithBase for #name { 270 type BaseFamily = #relative_base; 271 } 272 273 impl ::kernel::io::register::RelativeRegister for #name {} 274 )), 275 }, 276 277 Some(def) => { 278 let size = &def.size; 279 let stride = if let Some(stride) = &def.stride { 280 outputs.extend(quote_spanned!(stride.span().resolved_at(span) => 281 ::kernel::build_assert::static_assert!( 282 ::core::mem::size_of::<#ty>() <= #stride 283 ); 284 )); 285 quote!(#stride) 286 } else { 287 quote_spanned!(span => ::core::mem::size_of::<#ty>()) 288 }; 289 290 outputs.extend(quote_spanned!(span => 291 impl ::kernel::io::register::RegisterArray for #name { 292 const SIZE: usize = #size; 293 const STRIDE: usize = #stride; 294 } 295 )); 296 297 match relative_base { 298 None => outputs.extend(quote_spanned!(span => 299 impl ::kernel::io::register::Array for #name {} 300 )), 301 Some(relative_base) => outputs.extend(quote_spanned!(span => 302 impl ::kernel::io::register::WithBase for #name { 303 type BaseFamily = #relative_base; 304 } 305 306 impl ::kernel::io::register::RelativeRegisterArray for #name {} 307 )), 308 } 309 } 310 }; 311 } 312 313 Ok(outputs) 314 } 315