1use proc_macro2::{
6 Group,
7 Literal,
8 Span,
9 TokenStream, };
11use quote::{
12 quote,
13 quote_spanned, };
15use 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, };
32
33mod kw {
34 syn::custom_keyword!(base);
35 syn::custom_keyword!(stride);
36}
37
38struct RegArrayDef {
42 size: Expr,
43 stride: Option<Expr>,
44}
45
46enum RegOffset {
53 Fixed { offset: Literal },
55 Alias { alias: Path },
57 ElementAlias { alias: Path, idx: Expr },
59}
60
61struct 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
73impl 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 (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 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
173pub(crate) struct RegDef {
174 base: Type,
175 regs: Vec<Reg>,
176}
177
178impl 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
199pub(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 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)]
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}