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