diff --git a/build/cg/struct.rs b/build/cg/struct.rs index e2020868965..d649ceef99f 100644 --- a/build/cg/struct.rs +++ b/build/cg/struct.rs @@ -1622,7 +1622,10 @@ impl CodeGen { " let ptr = self.wire_ptr().add(offset) as *const {};", q_rs_typ )?; - writeln!(out, " let val = *ptr as u32;")?; + writeln!( + out, + " let val = base::value_from_ptr(ptr) as u32;" + )?; writeln!( out, " std::mem::transmute::(val)", @@ -1711,7 +1714,7 @@ impl CodeGen { cg::ind(3), q_rs_typ )?; - writeln!(out, " *ptr")?; + writeln!(out, "{}base::value_from_ptr(ptr)", cg::ind(3),)?; writeln!(out, " }}")?; writeln!(out, " }}")?; } diff --git a/src/base.rs b/src/base.rs index 391cf1361d2..93d5b2ef36f 100644 --- a/src/base.rs +++ b/src/base.rs @@ -1750,6 +1750,17 @@ pub(crate) fn align_pad(base: usize, align: usize) -> usize { (-base & (align - 1)) as usize } +/// Get a value from a pointer, using ptr::copy_nonoverlapping to avoid alignment issues +/// +/// # Safety +/// The pointer must point to a valid `T` value +#[inline] +pub(crate) unsafe fn value_from_ptr(ptr: *const T) -> T { + let mut val = mem::MaybeUninit::::uninit(); + ptr::copy_nonoverlapping(ptr, val.as_mut_ptr(), 1); + val.assume_init() +} + #[test] fn test_align_pad() { // align 1