summaryrefslogtreecommitdiff
path: root/src/codegen/helpers.rs
diff options
context:
space:
mode:
authorNick Fitzgerald <fitzgen@gmail.com>2017-10-25 17:31:21 -0700
committerGlyn Normington <gnormington@pivotal.io>2017-11-21 13:55:00 +0000
commitf0e05310b43e88e541ed011d20994c02fdcc1a3a (patch)
treebe05ee8a3fa1a1d7f696daa630e48a824276ff61 /src/codegen/helpers.rs
parent5e0cf9c356960e0459fea22cf0754dbec66f58b4 (diff)
Support bitfield allocation units larger than 64 bits
Individual bitfields are still limited to at most 64 bits, but this restriction can be weakened when Rust supports u128. This implements issue #816. Usage notes: * Since common code is added to each generated binding, a program which uses more than one binding may need to work around the duplication by including each binding in its own module. * The values created by bitfield allocation unit constructors can be assigned directly to the corresponding struct fields with no need for transmutation. Implementation notes: __BindgenBitfieldUnit represents a bitfield allocation unit using a Storage type accessible as a slice of u8. The alignment of the unit is inherited from an Align type by virtue of the field: align: [Align; 0], The position of this field in the struct is irrelevant. The alignment of the Storage type is intended to be no larger than the alignment of the Align type, which will be true if the Storage type is, for example, an array of u8. Although the double underscore (__) prefix is reserved for implementations of C++, there are precedents for this convention elsewhere in bindgen and so the convention is adopted here too. Acknowledgement: Thanks to @fitzgen for an initial implementation of __BindgenBitfieldUnit and code to integrate it into bindgen.
Diffstat (limited to 'src/codegen/helpers.rs')
-rw-r--r--src/codegen/helpers.rs42
1 files changed, 35 insertions, 7 deletions
diff --git a/src/codegen/helpers.rs b/src/codegen/helpers.rs
index 4ff398c4..99054305 100644
--- a/src/codegen/helpers.rs
+++ b/src/codegen/helpers.rs
@@ -1,7 +1,9 @@
//! Helpers for code generation that don't need macro expansion.
+use ir::context::BindgenContext;
use ir::layout::Layout;
use quote;
+use std::mem;
pub mod attributes {
use quote;
@@ -86,6 +88,39 @@ pub fn blob(layout: Layout) -> quote::Tokens {
}
}
+/// Integer type of the same size as the given `Layout`.
+pub fn integer_type(layout: Layout) -> Option<quote::Tokens> {
+ // This guard can be weakened when Rust implements u128.
+ if layout.size > mem::size_of::<u64>() {
+ None
+ } else {
+ Some(blob(layout))
+ }
+}
+
+/// Generates a bitfield allocation unit type for a type with the given `Layout`.
+pub fn bitfield_unit(ctx: &BindgenContext, layout: Layout) -> quote::Tokens {
+ let mut tokens = quote! {};
+
+ if ctx.options().enable_cxx_namespaces {
+ tokens.append(quote! { root:: });
+ }
+
+ let align = match layout.align {
+ n if n >= 8 => quote! { u64 },
+ 4 => quote! { u32 },
+ 2 => quote! { u16 },
+ _ => quote! { u8 },
+ };
+
+ let size = layout.size;
+ tokens.append(quote! {
+ __BindgenBitfieldUnit<[u8; #size], #align>
+ });
+
+ tokens
+}
+
pub mod ast_ty {
use ir::context::BindgenContext;
use ir::function::FunctionSig;
@@ -143,13 +178,6 @@ pub mod ast_ty {
tokens
}
- /// Returns hex representation of the given value.
- pub fn hex_expr(val: u64) -> quote::Tokens {
- let mut tokens = quote! {};
- tokens.append(format!("{:#x}", val));
- tokens
- }
-
pub fn byte_array_expr(bytes: &[u8]) -> quote::Tokens {
let mut bytes: Vec<_> = bytes.iter().cloned().collect();
bytes.push(0);