Skip to content

Commit 64bd867

Browse files
committed
Basic support for emitting unions
1 parent cadbbef commit 64bd867

File tree

2 files changed

+42
-22
lines changed

2 files changed

+42
-22
lines changed

src/generate/device.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ pub fn render(d: &Device, target: &Target) -> Result<Vec<Tokens>> {
4343
#![allow(non_camel_case_types)]
4444
#![feature(const_fn)]
4545
#![feature(try_from)]
46+
#![feature(untagged_unions)]
4647
#![no_std]
4748
});
4849

src/generate/peripheral.rs

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ fn register_or_cluster_block(
202202
name: Option<&str>,
203203
) -> Result<Tokens> {
204204
let mut fields = Tokens::new();
205+
let mut helper_types = Tokens::new();
205206

206207
let ercs_expanded = expand(ercs, defs, name)?;
207208

@@ -230,32 +231,48 @@ fn register_or_cluster_block(
230231

231232
last_end = Some(region.end);
232233

233-
if region.fields.len() > 1 {
234-
// TODO: this is where we'd emit a union container
235-
eprintln!("WARNING: overlaps for region offset={}-{}. \
236-
Using the first one of these:",
237-
region.offset, region.end-1);
238-
239-
for f in &region.fields {
240-
eprintln!(" {:?} {}-{}", f.field.ident, f.offset,
241-
(f.offset + f.size / BITS_PER_BYTE)-1);
242-
}
243-
}
234+
let mut region_fields = Tokens::new();
235+
236+
for reg_block_field in &region.fields {
237+
let comment = &format!(
238+
"0x{:02x} - {}",
239+
reg_block_field.offset,
240+
util::respace(&reg_block_field.description),
241+
)[..];
244242

245-
let reg_block_field = &region.fields[0];
243+
region_fields.append(quote! {
244+
#[doc = #comment]
245+
});
246246

247-
let comment = &format!(
248-
"0x{:02x} - {}",
249-
reg_block_field.offset,
250-
util::respace(&reg_block_field.description),
251-
)[..];
252247

253-
fields.append(quote! {
254-
#[doc = #comment]
255-
});
248+
reg_block_field.field.to_tokens(&mut region_fields);
249+
Ident::new(",").to_tokens(&mut region_fields);
250+
}
251+
252+
if region.fields.len() > 1 {
253+
// TODO: come up with nicer naming. Right now we're using the
254+
// region index as a unique-within-this-block identifier counter.
255+
let name = Ident::new(format!("u{}", i));
256+
257+
// TODO: if we only have a single region and that region is a
258+
// union, the overall RegisterBlock could be a union
259+
260+
helper_types.append(quote! {
261+
/// Union container for a set of overlapping registers
262+
#[repr(C)]
263+
pub union #name {
264+
#region_fields
265+
}
266+
});
267+
268+
fields.append(quote! {
269+
#name: #name
270+
});
271+
Ident::new(",").to_tokens(&mut fields);
256272

257-
reg_block_field.field.to_tokens(&mut fields);
258-
Ident::new(",").to_tokens(&mut fields);
273+
} else {
274+
fields.append(&region_fields);
275+
}
259276
}
260277

261278
let name = Ident::new(match name {
@@ -269,6 +286,8 @@ fn register_or_cluster_block(
269286
pub struct #name {
270287
#fields
271288
}
289+
290+
#helper_types
272291
})
273292
}
274293

0 commit comments

Comments
 (0)