From d13e5c96a633f1c2c12c3d2228f66ca67db38fff Mon Sep 17 00:00:00 2001 From: Jimo Jung Date: Mon, 10 Oct 2022 00:35:08 +0000 Subject: [PATCH] Added big endian feature for little endian CPU --- c2rust-bitfields-derive/src/lib.rs | 19 +++++++++++++++++-- c2rust-bitfields/src/lib.rs | 26 +++++++++++++++++++------- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/c2rust-bitfields-derive/src/lib.rs b/c2rust-bitfields-derive/src/lib.rs index 29444c9ca..dd2a4c2c0 100644 --- a/c2rust-bitfields-derive/src/lib.rs +++ b/c2rust-bitfields-derive/src/lib.rs @@ -21,6 +21,7 @@ struct BFFieldAttr { name: String, ty: String, bits: (String, proc_macro2::Span), + endian: Option, } fn parse_bitfield_attr( @@ -31,6 +32,7 @@ fn parse_bitfield_attr( let mut ty = None; let mut bits = None; let mut bits_span = None; + let mut endian = None; if let Meta::List(meta_list) = attr.parse_meta()? { for nested_meta in meta_list.nested { @@ -53,6 +55,7 @@ fn parse_bitfield_attr( bits = Some(rhs_string); bits_span = Some(meta_name_value.path.span()); } + "endian" => endian = Some(rhs_string), // This one shouldn't ever occur here, // but we're handling it just to be safe "padding" => { @@ -97,6 +100,7 @@ fn parse_bitfield_attr( name: name.unwrap(), ty: ty.unwrap(), bits: (bits.unwrap(), bits_span.unwrap()), + endian: endian, })) } @@ -228,6 +232,17 @@ fn bitfield_struct_impl(struct_item: ItemStruct) -> Result { let field_bit_info = field_bit_info?; let field_bit_info_setters = &field_bit_info; let field_bit_info_getters = &field_bit_info; + let field_endians: Vec<_> = bitfields + .iter() + .map(|field| { + field + .endian + .as_ref() + .map_or(false, |endian| endian == "big") + }) + .collect(); + let field_endians_setters = &field_endians; + let field_endians_getters = &field_endians; // TODO: Method visibility determined by struct field visibility? let q = quote! { @@ -240,7 +255,7 @@ fn bitfield_struct_impl(struct_item: ItemStruct) -> Result { let field = &mut self.#field_names_setters; let (lhs_bit, rhs_bit) = #field_bit_info_setters; - int.set_field(field, (lhs_bit, rhs_bit)); + int.set_field(field, (lhs_bit, rhs_bit), #field_endians_setters); } /// This method allows you to read from a bitfield to a value @@ -251,7 +266,7 @@ fn bitfield_struct_impl(struct_item: ItemStruct) -> Result { let field = &self.#field_names_getters; let (lhs_bit, rhs_bit) = #field_bit_info_getters; - ::get_field(field, (lhs_bit, rhs_bit)) + ::get_field(field, (lhs_bit, rhs_bit), #field_endians_getters) } )* } diff --git a/c2rust-bitfields/src/lib.rs b/c2rust-bitfields/src/lib.rs index 8eb3099ae..8c487f551 100644 --- a/c2rust-bitfields/src/lib.rs +++ b/c2rust-bitfields/src/lib.rs @@ -12,7 +12,7 @@ pub trait FieldType: Sized { fn get_bit(&self, bit: usize) -> bool; - fn set_field(&self, field: &mut [u8], bit_range: (usize, usize)) { + fn set_field(&self, field: &mut [u8], bit_range: (usize, usize), big_endian: bool) { fn zero_bit(byte: &mut u8, n_bit: u64) { let bit = 1 << n_bit; @@ -28,7 +28,11 @@ pub trait FieldType: Sized { let (lhs_bit, rhs_bit) = bit_range; for (i, bit_index) in (lhs_bit..=rhs_bit).enumerate() { - let byte_index = bit_index / 8; + let byte_index = if big_endian { + field.len() - 1 - (bit_index / 8) + } else { + bit_index / 8 + }; let byte = &mut field[byte_index]; if self.get_bit(i) { @@ -39,7 +43,7 @@ pub trait FieldType: Sized { } } - fn get_field(field: &[u8], bit_range: (usize, usize)) -> Self; + fn get_field(field: &[u8], bit_range: (usize, usize), big_endian: bool) -> Self; } macro_rules! impl_int { @@ -52,12 +56,16 @@ macro_rules! impl_int { ((*self >> bit) & 1) == 1 } - fn get_field(field: &[u8], bit_range: (usize, usize)) -> Self { + fn get_field(field: &[u8], bit_range: (usize, usize), big_endian: bool) -> Self { let (lhs_bit, rhs_bit) = bit_range; let mut val = 0; for (i, bit_index) in (lhs_bit..=rhs_bit).enumerate() { - let byte_index = bit_index / 8; + let byte_index = if big_endian { + field.len() - 1 - (bit_index / 8) + } else { + bit_index / 8 + }; let byte = field[byte_index]; let bit = 1 << (bit_index % 8); let read_bit = byte & bit; @@ -94,12 +102,16 @@ impl FieldType for bool { *self } - fn get_field(field: &[u8], bit_range: (usize, usize)) -> Self { + fn get_field(field: &[u8], bit_range: (usize, usize), big_endian: bool) -> Self { let (lhs_bit, rhs_bit) = bit_range; let mut val = false; for bit_index in lhs_bit..=rhs_bit { - let byte_index = bit_index / 8; + let byte_index = if big_endian { + field.len() - 1 - (bit_index / 8) + } else { + bit_index / 8 + }; let byte = field[byte_index]; let bit = 1 << (bit_index % 8); let read_bit = byte & bit;