summaryrefslogtreecommitdiff
path: root/src/codegen/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen/mod.rs')
-rw-r--r--src/codegen/mod.rs121
1 files changed, 120 insertions, 1 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index fdf61f40..28cddb5d 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -1020,6 +1020,108 @@ impl<'a> FieldCodegen<'a> for FieldData {
}
}
+impl BitfieldUnit {
+ /// Get the constructor name for this bitfield unit.
+ fn ctor_name(&self, ctx: &BindgenContext) -> ast::Ident {
+ let ctor_name = format!("new_bitfield_{}", self.nth());
+ ctx.ext_cx().ident_of(&ctor_name)
+ }
+
+ /// Get the initial bitfield unit constructor that just returns 0. This will
+ /// then be extended by each bitfield in the unit. See `extend_ctor_impl`
+ /// below.
+ fn initial_ctor_impl(&self,
+ ctx: &BindgenContext,
+ unit_field_int_ty: &P<ast::Ty>)
+ -> P<ast::Item> {
+ let ctor_name = self.ctor_name(ctx);
+
+ // If we're generating unstable Rust, add the const.
+ let fn_prefix = if ctx.options().unstable_rust {
+ quote_tokens!(ctx.ext_cx(), pub const fn)
+ } else {
+ quote_tokens!(ctx.ext_cx(), pub fn)
+ };
+
+ quote_item!(
+ ctx.ext_cx(),
+ impl XxxUnused {
+ #[inline]
+ $fn_prefix $ctor_name() -> $unit_field_int_ty {
+ 0
+ }
+ }
+ ).unwrap()
+ }
+}
+
+impl Bitfield {
+ /// Extend an under construction bitfield unit constructor with this
+ /// bitfield. This involves two things:
+ ///
+ /// 1. Adding a parameter with this bitfield's name and its type.
+ ///
+ /// 2. Bitwise or'ing the parameter into the final value of the constructed
+ /// bitfield unit.
+ fn extend_ctor_impl(&self,
+ ctx: &BindgenContext,
+ parent: &CompInfo,
+ ctor_impl: P<ast::Item>,
+ ctor_name: &ast::Ident,
+ unit_field_int_ty: &P<ast::Ty>)
+ -> P<ast::Item> {
+ match ctor_impl.unwrap().node {
+ ast::ItemKind::Impl(_, _, _, _, _, ref items) => {
+ assert_eq!(items.len(), 1);
+
+ match items.get(0).unwrap().node {
+ ast::ImplItemKind::Method(ref sig, ref body) => {
+ let params = sig.decl.clone().unwrap().inputs;
+ let param_name = bitfield_getter_name(ctx, parent, self.name());
+
+ let bitfield_ty_item = ctx.resolve_item(self.ty());
+ let bitfield_ty = bitfield_ty_item.expect_type();
+ let bitfield_ty_layout = bitfield_ty.layout(ctx)
+ .expect("Bitfield without layout? Gah!");
+ let bitfield_int_ty = BlobTyBuilder::new(bitfield_ty_layout).build();
+ let bitfield_ty = bitfield_ty
+ .to_rust_ty_or_opaque(ctx, bitfield_ty_item);
+
+ let offset = self.offset_into_unit();
+ let mask = self.mask();
+
+ // If we're generating unstable Rust, add the const.
+ let fn_prefix = if ctx.options().unstable_rust {
+ quote_tokens!(ctx.ext_cx(), pub const fn)
+ } else {
+ quote_tokens!(ctx.ext_cx(), pub fn)
+ };
+
+ quote_item!(
+ ctx.ext_cx(),
+ impl XxxUnused {
+ #[inline]
+ $fn_prefix $ctor_name($params $param_name : $bitfield_ty)
+ -> $unit_field_int_ty {
+ let bitfield_unit_val = $body;
+ let $param_name = $param_name
+ as $bitfield_int_ty
+ as $unit_field_int_ty;
+ let mask = $mask as $unit_field_int_ty;
+ let $param_name = ($param_name << $offset) & mask;
+ bitfield_unit_val | $param_name
+ }
+ }
+ ).unwrap()
+ }
+ _ => unreachable!(),
+ }
+ }
+ _ => unreachable!(),
+ }
+ }
+}
+
impl<'a> FieldCodegen<'a> for BitfieldUnit {
type Extra = ();
@@ -1058,6 +1160,9 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
}
};
+ let ctor_name = self.ctor_name(ctx);
+ let mut ctor_impl = self.initial_ctor_impl(ctx, &unit_field_int_ty);
+
for bf in self.bitfields() {
bf.codegen(ctx,
fields_should_be_private,
@@ -1069,8 +1174,22 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
fields,
methods,
(&unit_field_name, unit_field_int_ty.clone()));
+
+ ctor_impl = bf.extend_ctor_impl(ctx,
+ parent,
+ ctor_impl,
+ &ctor_name,
+ &unit_field_int_ty);
}
+ match ctor_impl.unwrap().node {
+ ast::ItemKind::Impl(_, _, _, _, _, items) => {
+ assert_eq!(items.len(), 1);
+ methods.extend(items.into_iter());
+ },
+ _ => unreachable!(),
+ };
+
struct_layout.saw_bitfield_unit(self.layout());
}
}
@@ -1154,7 +1273,7 @@ impl<'a> FieldCodegen<'a> for Bitfield {
let bitfield_ty = bitfield_ty.to_rust_ty_or_opaque(ctx, bitfield_ty_item);
let offset = self.offset_into_unit();
- let mask: usize = ((1usize << self.width()) - 1usize) << offset;
+ let mask: usize = self.mask();
let impl_item = quote_item!(
ctx.ext_cx(),