From 455d45ea26779aa4a36fc2a53166903d1509e743 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 18 Apr 2018 12:17:13 -0400 Subject: [PATCH] Add support for bitfields --- src/analysis/rust_type.rs | 16 +++++++++---- src/analysis/types.rs | 5 ---- src/codegen/sys/fields.rs | 49 +++++++++++++++++++++++++++++++++------ 3 files changed, 54 insertions(+), 16 deletions(-) diff --git a/src/analysis/rust_type.rs b/src/analysis/rust_type.rs index 7f19ee031..c1cdb96a5 100644 --- a/src/analysis/rust_type.rs +++ b/src/analysis/rust_type.rs @@ -22,14 +22,22 @@ fn into_inner(res: Result) -> String { } } -impl IntoString for Result { +impl IntoString for TypeError { fn into_string(self) -> String { use self::TypeError::*; + match self { + Ignored(s) => format!("/*Ignored*/{}", s), + Mismatch(s) => format!("/*Metadata mismatch*/{}", s), + Unimplemented(s) => format!("/*Unimplemented*/{}", s), + } + } +} + +impl IntoString for Result { + fn into_string(self) -> String { match self { Ok(s) => s, - Err(Ignored(s)) => format!("/*Ignored*/{}", s), - Err(Mismatch(s)) => format!("/*Metadata mismatch*/{}", s), - Err(Unimplemented(s)) => format!("/*Unimplemented*/{}", s), + Err(e) => e.into_string(), } } } diff --git a/src/analysis/types.rs b/src/analysis/types.rs index bbc140879..cc85742c3 100644 --- a/src/analysis/types.rs +++ b/src/analysis/types.rs @@ -72,11 +72,6 @@ impl IsIncomplete for Alias { impl IsIncomplete for Field { fn is_incomplete(&self, lib: &Library) -> bool { - if self.bits.is_some() { - // Bitfields are unrepresentable in Rust, - // so from our perspective they are incomplete. - return true; - } if self.is_ptr() { // Pointers are always complete. return false; diff --git a/src/codegen/sys/fields.rs b/src/codegen/sys/fields.rs index e89cd47e7..118afcd14 100644 --- a/src/codegen/sys/fields.rs +++ b/src/codegen/sys/fields.rs @@ -93,15 +93,50 @@ pub fn from_union(env: &Env, union: &Union) -> Fields { fn analyze_fields(env: &Env, unsafe_access: bool, fields: &[Field]) -> (Vec, Option) { let mut truncated = None; let mut infos = Vec::with_capacity(fields.len()); + let mut skip_bits = false; - for field in fields { - let typ = match field_ffi_type(env, field) { - e @ Err(..) => { - truncated = Some(e.into_string()); - break; + for (i, field) in fields.iter().enumerate() { + let typ = + if field.bits.is_some() { + if skip_bits { + continue; + } + skip_bits = true; + let mut bits = 0; + for i in i..fields.len() { + if let Some(bs) = fields[i].bits { + bits += bs; + } + } + let typ = + if bits <= 8 { + "u8" + } + else if bits <= 16 { + "u16" + } + else if bits <= 32 { + "u32" + } + else if bits <= 64 { + "u64" + } + else { + truncated = Some("Bit fields too large".to_string()); + break; + }; + typ.to_string() } - Ok(typ) => typ, - }; + else { + skip_bits = false; + match field_ffi_type(env, field) { + Err(e) => { + truncated = Some(e.into_string()); + break; + } + Ok(typ) => typ, + } + }; // Skip private fields from Debug impl. Ignore volatile as well, // they are usually used as synchronization primites, // so we wouldn't want to introduce additional reads.