Skip to content

Commit c88f7c5

Browse files
wezburrbull
authored andcommitted
remove dep on untagged unions
This removes any observable side effect of the --nightly switch by removing the use of unions and the untagged_unions feature gate. Unions are replaced with accessor functions that return the appropriate register block reference. Here's a playground link that shows that the pointer calculation looks reasonable: https://play.integer32.com/?version=stable&mode=debug&edition=2018&gist=cd56444abc03e6781e526bbddc7082bc This commit is a breaking change. This is based on this WIP PR branch: #256 It implements the easiest standalone portion of this issue: #218 and also makes accessing the unions "safe" too, which is requested here: #230
1 parent e74ecbd commit c88f7c5

File tree

2 files changed

+37
-88
lines changed

2 files changed

+37
-88
lines changed

src/generate/device.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,6 @@ pub fn render(
4848
#![no_std]
4949
});
5050

51-
if nightly {
52-
out.push(quote! {
53-
#![feature(untagged_unions)]
54-
});
55-
}
56-
5751
match target {
5852
Target::CortexM => {
5953
out.push(quote! {

src/generate/peripheral.rs

Lines changed: 37 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -358,85 +358,10 @@ fn register_or_cluster_block(
358358
ercs: &[RegisterCluster],
359359
defs: &Defaults,
360360
name: Option<&str>,
361-
nightly: bool,
362-
) -> Result<Tokens> {
363-
if nightly {
364-
register_or_cluster_block_nightly(ercs, defs, name)
365-
} else {
366-
register_or_cluster_block_stable(ercs, defs, name)
367-
}
368-
}
369-
370-
fn register_or_cluster_block_stable(
371-
ercs: &[RegisterCluster],
372-
defs: &Defaults,
373-
name: Option<&str>,
374-
) -> Result<Tokens> {
375-
let mut fields = Tokens::new();
376-
// enumeration of reserved fields
377-
let mut i = 0;
378-
// offset from the base address, in bytes
379-
let mut offset = 0;
380-
381-
let ercs_expanded = expand(ercs, defs, name)?;
382-
383-
for reg_block_field in ercs_expanded {
384-
let pad = if let Some(pad) = reg_block_field.offset.checked_sub(offset) {
385-
pad
386-
} else {
387-
warn!(
388-
"{:?} overlaps with another register block at offset {}. \
389-
Ignoring.",
390-
reg_block_field.field.ident, reg_block_field.offset
391-
);
392-
continue;
393-
};
394-
395-
if pad != 0 {
396-
let name = Ident::new(format!("_reserved{}", i));
397-
let pad = pad as usize;
398-
fields.append(quote! {
399-
#name : [u8; #pad],
400-
});
401-
i += 1;
402-
}
403-
404-
let comment = &format!(
405-
"0x{:02x} - {}",
406-
reg_block_field.offset,
407-
util::escape_brackets(util::respace(&reg_block_field.description).as_ref()),
408-
)[..];
409-
410-
fields.append(quote! {
411-
#[doc = #comment]
412-
});
413-
414-
reg_block_field.field.to_tokens(&mut fields);
415-
Ident::new(",").to_tokens(&mut fields);
416-
417-
offset = reg_block_field.offset + reg_block_field.size / BITS_PER_BYTE;
418-
}
419-
420-
let name = Ident::new(match name {
421-
Some(name) => name.to_sanitized_upper_case(),
422-
None => "RegisterBlock".into(),
423-
});
424-
425-
Ok(quote! {
426-
/// Register block
427-
#[repr(C)]
428-
pub struct #name {
429-
#fields
430-
}
431-
})
432-
}
433-
434-
fn register_or_cluster_block_nightly(
435-
ercs: &[RegisterCluster],
436-
defs: &Defaults,
437-
name: Option<&str>,
361+
_nightly: bool,
438362
) -> Result<Tokens> {
439363
let mut fields = Tokens::new();
364+
let mut accessors = Tokens::new();
440365
let mut helper_types = Tokens::new();
441366

442367
let ercs_expanded = expand(ercs, defs, name)?;
@@ -484,15 +409,39 @@ fn register_or_cluster_block_nightly(
484409
util::escape_brackets(util::respace(&reg_block_field.description).as_ref()),
485410
)[..];
486411

412+
if block_is_union {
413+
let name = &reg_block_field.field.ident;
414+
let mut_name = Ident::new(format!("{}_mut", name.as_ref().unwrap()));
415+
let ty = &reg_block_field.field.ty;
416+
let offset = reg_block_field.offset;
417+
accessors.append(quote! {
418+
pub fn #name(&self) -> &#ty {
419+
unsafe {
420+
&*(((self as *const Self) as *const u8).add(#offset) as *const #ty)
421+
}
422+
}
423+
pub fn #mut_name(&self) -> &mut #ty {
424+
unsafe {
425+
&mut *(((self as *const Self) as *mut u8).add(#offset) as *mut #ty)
426+
}
427+
}
428+
});
429+
430+
} else {
431+
487432
region_fields.append(quote! {
488433
#[doc = #comment]
489434
});
490435

491436
reg_block_field.field.to_tokens(&mut region_fields);
492437
Ident::new(",").to_tokens(&mut region_fields);
438+
}
493439
}
494440

495-
if region.fields.len() > 1 && !block_is_union {
441+
if block_is_union {
442+
continue
443+
}
444+
if region.fields.len() > 1 {
496445
let (type_name, name) = match region.ident.clone() {
497446
Some(prefix) => (
498447
Ident::new(format!("{}_UNION", prefix.to_sanitized_upper_case())),
@@ -531,19 +480,25 @@ fn register_or_cluster_block_nightly(
531480
None => "RegisterBlock".into(),
532481
});
533482

534-
let block_type = if block_is_union {
535-
Ident::new("union")
483+
let accessors = if block_is_union {
484+
quote! {
485+
impl #name {
486+
#accessors
487+
}
488+
}
536489
} else {
537-
Ident::new("struct")
490+
quote! {}
538491
};
539492

540493
Ok(quote! {
541494
/// Register block
542495
#[repr(C)]
543-
pub #block_type #name {
496+
pub struct #name {
544497
#fields
545498
}
546499

500+
#accessors
501+
547502
#helper_types
548503
})
549504
}

0 commit comments

Comments
 (0)