Skip to content

Commit f676846

Browse files
committed
Add --nightly flag to gate untagged unions feature
1 parent 7690adf commit f676846

File tree

3 files changed

+100
-8
lines changed

3 files changed

+100
-8
lines changed

src/generate/device.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use Target;
99
use generate::{interrupt, peripheral};
1010

1111
/// Whole device generation
12-
pub fn render(d: &Device, target: &Target) -> Result<Vec<Tokens>> {
12+
pub fn render(d: &Device, target: &Target, nightly: bool) -> Result<Vec<Tokens>> {
1313
let mut out = vec![];
1414

1515
let doc = format!(
@@ -43,10 +43,15 @@ 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)]
4746
#![no_std]
4847
});
4948

49+
if nightly {
50+
out.push(quote! {
51+
#![feature(untagged_unions)]
52+
});
53+
}
54+
5055
match *target {
5156
Target::CortexM => {
5257
out.push(quote! {
@@ -128,7 +133,7 @@ pub fn render(d: &Device, target: &Target) -> Result<Vec<Tokens>> {
128133
}
129134

130135

131-
out.extend(peripheral::render(p, &d.peripherals, &d.defaults)?);
136+
out.extend(peripheral::render(p, &d.peripherals, &d.defaults, nightly)?);
132137

133138
if p.registers
134139
.as_ref()

src/generate/peripheral.rs

Lines changed: 84 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub fn render(
1515
p: &Peripheral,
1616
all_peripherals: &[Peripheral],
1717
defaults: &Defaults,
18+
nightly: bool,
1819
) -> Result<Vec<Tokens>> {
1920
let mut out = vec![];
2021

@@ -76,11 +77,11 @@ pub fn render(
7677

7778
// Push any register or cluster blocks into the output
7879
let mut mod_items = vec![];
79-
mod_items.push(register_or_cluster_block(ercs, defaults, None)?);
80+
mod_items.push(register_or_cluster_block(ercs, defaults, None, nightly)?);
8081

8182
// Push all cluster related information into the peripheral module
8283
for c in &clusters {
83-
mod_items.push(cluster_block(c, defaults, p, all_peripherals)?);
84+
mod_items.push(cluster_block(c, defaults, p, all_peripherals, nightly)?);
8485
}
8586

8687
// Push all regsiter realted information into the peripheral module
@@ -348,6 +349,84 @@ fn register_or_cluster_block(
348349
ercs: &[Either<Register, Cluster>],
349350
defs: &Defaults,
350351
name: Option<&str>,
352+
nightly: bool,
353+
) -> Result<Tokens> {
354+
if nightly {
355+
register_or_cluster_block_nightly(ercs, defs, name)
356+
} else {
357+
register_or_cluster_block_stable(ercs, defs, name)
358+
}
359+
}
360+
361+
fn register_or_cluster_block_stable(
362+
ercs: &[Either<Register, Cluster>],
363+
defs: &Defaults,
364+
name: Option<&str>,
365+
) -> Result<Tokens> {
366+
let mut fields = Tokens::new();
367+
// enumeration of reserved fields
368+
let mut i = 0;
369+
// offset from the base address, in bytes
370+
let mut offset = 0;
371+
372+
let ercs_expanded = expand(ercs, defs, name)?;
373+
374+
for reg_block_field in ercs_expanded {
375+
let pad = if let Some(pad) = reg_block_field.offset.checked_sub(offset) {
376+
pad
377+
} else {
378+
eprintln!(
379+
"WARNING {:?} overlaps with another register block at offset {}. \
380+
Ignoring.",
381+
reg_block_field.field.ident,
382+
reg_block_field.offset
383+
);
384+
continue;
385+
};
386+
387+
if pad != 0 {
388+
let name = Ident::new(format!("_reserved{}", i));
389+
let pad = pad as usize;
390+
fields.append(quote! {
391+
#name : [u8; #pad],
392+
});
393+
i += 1;
394+
}
395+
396+
let comment = &format!(
397+
"0x{:02x} - {}",
398+
reg_block_field.offset,
399+
util::respace(&reg_block_field.description),
400+
)[..];
401+
402+
fields.append(quote! {
403+
#[doc = #comment]
404+
});
405+
406+
reg_block_field.field.to_tokens(&mut fields);
407+
Ident::new(",").to_tokens(&mut fields);
408+
409+
offset = reg_block_field.offset + reg_block_field.size / BITS_PER_BYTE;
410+
}
411+
412+
let name = Ident::new(match name {
413+
Some(name) => name.to_sanitized_upper_case(),
414+
None => "RegisterBlock".into(),
415+
});
416+
417+
Ok(quote! {
418+
/// Register block
419+
#[repr(C)]
420+
pub struct #name {
421+
#fields
422+
}
423+
})
424+
}
425+
426+
fn register_or_cluster_block_nightly(
427+
ercs: &[Either<Register, Cluster>],
428+
defs: &Defaults,
429+
name: Option<&str>,
351430
) -> Result<Tokens> {
352431
let mut fields = Tokens::new();
353432
let mut helper_types = Tokens::new();
@@ -636,6 +715,7 @@ fn cluster_block(
636715
defaults: &Defaults,
637716
p: &Peripheral,
638717
all_peripherals: &[Peripheral],
718+
nightly: bool,
639719
) -> Result<Tokens> {
640720
let mut mod_items: Vec<Tokens> = vec![];
641721

@@ -649,7 +729,7 @@ fn cluster_block(
649729
}.replace("[%s]", "")
650730
.replace("%s", "");
651731
let name_sc = Ident::new(&*mod_name.to_sanitized_snake_case());
652-
let reg_block = register_or_cluster_block(&c.children, defaults, Some(&mod_name))?;
732+
let reg_block = register_or_cluster_block(&c.children, defaults, Some(&mod_name), nightly)?;
653733

654734
// Generate definition for each of the registers.
655735
let registers = util::only_registers(&c.children);
@@ -666,7 +746,7 @@ fn cluster_block(
666746
// Generate the sub-cluster blocks.
667747
let clusters = util::only_clusters(&c.children);
668748
for c in &clusters {
669-
mod_items.push(cluster_block(c, defaults, p, all_peripherals)?);
749+
mod_items.push(cluster_block(c, defaults, p, all_peripherals, nightly)?);
670750
}
671751

672752
Ok(quote! {

src/main.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ fn run() -> Result<()> {
6161
.takes_value(true)
6262
.value_name("ARCH"),
6363
)
64+
.arg(
65+
Arg::with_name("nightly_features")
66+
.long("nightly")
67+
.help("Enable features only available to nightly rustc")
68+
)
6469
.version(concat!(
6570
env!("CARGO_PKG_VERSION"),
6671
include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt"))
@@ -91,7 +96,9 @@ fn run() -> Result<()> {
9196

9297
let device = svd::parse(xml);
9398

94-
let items = generate::device::render(&device, &target)?;
99+
let nightly = matches.is_present("nightly_features");
100+
101+
let items = generate::device::render(&device, &target, nightly)?;
95102

96103
println!(
97104
"{}",

0 commit comments

Comments
 (0)