diff options
Diffstat (limited to 'src/codegen/mod.rs')
-rw-r--r-- | src/codegen/mod.rs | 110 |
1 files changed, 88 insertions, 22 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 8f9f0ee7..d926f02b 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -23,7 +23,7 @@ use ir::item_kind::ItemKind; use ir::layout::Layout; use ir::module::Module; use ir::objc::{ObjCInterface, ObjCMethod}; -use ir::template::{AsNamed, TemplateInstantiation, TemplateParameters}; +use ir::template::{AsTemplateParam, TemplateInstantiation, TemplateParameters}; use ir::ty::{Type, TypeKind}; use ir::var::Var; @@ -437,6 +437,16 @@ impl CodeGenerator for Var { } result.saw_var(&canonical_name); + // We can't generate bindings to static variables of templates. The + // number of actual variables for a single declaration are open ended + // and we don't know what instantiations do or don't exist. + let type_params = item.all_template_params(ctx); + if let Some(params) = type_params { + if !params.is_empty() { + return; + } + } + let ty = self.ty().to_rust_ty_or_opaque(ctx, &()); if let Some(val) = self.val() { @@ -643,7 +653,7 @@ impl CodeGenerator for Type { if let Some(ref params) = used_template_params { for template_param in params { if let Some(id) = - template_param.as_named(ctx, &()) { + template_param.as_template_param(ctx, &()) { let template_param = ctx.resolve_type(id); if template_param.is_invalid_named_type() { warn!("Item contained invalid template \ @@ -754,6 +764,13 @@ impl CodeGenerator for TemplateInstantiation { return } + // If there are any unbound type parameters, then we can't generate a + // layout test because we aren't dealing with a concrete type with a + // concrete size and alignment. + if ctx.uses_any_template_parameters(item.id()) { + return; + } + let layout = item.kind().expect_type().layout(ctx); if let Some(layout) = layout { @@ -761,8 +778,11 @@ impl CodeGenerator for TemplateInstantiation { let align = layout.align; let name = item.canonical_name(ctx); - let fn_name = format!("__bindgen_test_layout_{}_instantiation_{}", - name, item.exposed_id(ctx)); + let mut fn_name = format!("__bindgen_test_layout_{}_instantiation", name); + let times_seen = result.overload_number(&fn_name); + if times_seen > 0 { + write!(&mut fn_name, "_{}", times_seen).unwrap(); + } let fn_name = ctx.rust_ident_raw(&fn_name); @@ -1115,9 +1135,9 @@ impl Bitfield { #[inline] $fn_prefix $ctor_name($params $param_name : $bitfield_ty) -> $unit_field_int_ty { - ($body | - (($param_name as $bitfield_int_ty as $unit_field_int_ty) << $offset) & - ($mask as $unit_field_int_ty)) + ($body | + (($param_name as $bitfield_int_ty as $unit_field_int_ty) << $offset) & + ($mask as $unit_field_int_ty)) } } ).unwrap() @@ -1149,12 +1169,18 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit { .build_ty(field_ty.clone()); fields.extend(Some(field)); - let unit_field_int_ty = match self.layout().size { + let mut field_int_size = self.layout().size; + if !field_int_size.is_power_of_two() { + field_int_size = field_int_size.next_power_of_two(); + } + + let unit_field_int_ty = match field_int_size { 8 => quote_ty!(ctx.ext_cx(), u64), 4 => quote_ty!(ctx.ext_cx(), u32), 2 => quote_ty!(ctx.ext_cx(), u16), 1 => quote_ty!(ctx.ext_cx(), u8), - _ => { + size => { + debug_assert!(size > 8); // Can't generate bitfield accessors for unit sizes larget than // 64 bits at the moment. struct_layout.saw_bitfield_unit(self.layout()); @@ -1275,17 +1301,26 @@ 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 = self.mask(); + let mask = self.mask(); let impl_item = quote_item!( ctx.ext_cx(), impl XxxIgnored { #[inline] pub fn $getter_name(&self) -> $bitfield_ty { - let mask = $mask as $unit_field_int_ty; - let unit_field_val: $unit_field_int_ty = unsafe { - ::$prefix::mem::transmute(self.$unit_field_ident) + let mut unit_field_val: $unit_field_int_ty = unsafe { + ::$prefix::mem::uninitialized() + }; + + unsafe { + ::$prefix::ptr::copy_nonoverlapping( + &self.$unit_field_ident as *const _ as *const u8, + &mut unit_field_val as *mut $unit_field_int_ty as *mut u8, + ::$prefix::mem::size_of::<$unit_field_int_ty>(), + ) }; + + let mask = $mask as $unit_field_int_ty; let val = (unit_field_val & mask) >> $offset; unsafe { ::$prefix::mem::transmute(val as $bitfield_int_ty) @@ -1298,14 +1333,27 @@ impl<'a> FieldCodegen<'a> for Bitfield { let val = val as $bitfield_int_ty as $unit_field_int_ty; let mut unit_field_val: $unit_field_int_ty = unsafe { - ::$prefix::mem::transmute(self.$unit_field_ident) + ::$prefix::mem::uninitialized() }; + + unsafe { + ::$prefix::ptr::copy_nonoverlapping( + &self.$unit_field_ident as *const _ as *const u8, + &mut unit_field_val as *mut $unit_field_int_ty as *mut u8, + ::$prefix::mem::size_of::<$unit_field_int_ty>(), + ) + }; + unit_field_val &= !mask; unit_field_val |= (val << $offset) & mask; - self.$unit_field_ident = unsafe { - ::$prefix::mem::transmute(unit_field_val) - }; + unsafe { + ::$prefix::ptr::copy_nonoverlapping( + &unit_field_val as *const _ as *const u8, + &mut self.$unit_field_ident as *mut _ as *mut u8, + ::$prefix::mem::size_of::<$unit_field_int_ty>(), + ); + } } } ).unwrap(); @@ -2323,7 +2371,8 @@ impl CodeGenerator for Enum { builder = builder.with_attr(derives); } - fn add_constant<'a>(enum_: &Type, + fn add_constant<'a>(ctx: &BindgenContext, + enum_: &Type, // Only to avoid recomputing every time. enum_canonical_name: &str, // May be the same as "variant" if it's because the @@ -2334,7 +2383,11 @@ impl CodeGenerator for Enum { enum_rust_ty: P<ast::Ty>, result: &mut CodegenResult<'a>) { let constant_name = if enum_.name().is_some() { - format!("{}_{}", enum_canonical_name, variant_name) + if ctx.options().prepend_enum_name { + format!("{}_{}", enum_canonical_name, variant_name) + } else { + variant_name.into() + } } else { variant_name.into() }; @@ -2418,7 +2471,8 @@ impl CodeGenerator for Enum { }; let existing_variant_name = entry.get(); - add_constant(enum_ty, + add_constant(ctx, + enum_ty, &name, &*mangled_name, existing_variant_name, @@ -2457,7 +2511,8 @@ impl CodeGenerator for Enum { variant_name)) }; - add_constant(enum_ty, + add_constant(ctx, + enum_ty, &name, &mangled_name, &variant_name, @@ -2769,7 +2824,7 @@ impl TryToRustTy for Type { let template_params = item.used_template_params(ctx) .unwrap_or(vec![]) .into_iter() - .filter(|param| param.is_named(ctx, &())) + .filter(|param| param.is_template_param(ctx, &())) .collect::<Vec<_>>(); let spelling = self.name().expect("Unnamed alias?"); @@ -2960,6 +3015,17 @@ impl CodeGenerator for Function { item: &Item) { debug!("<Function as CodeGenerator>::codegen: item = {:?}", item); + // Similar to static member variables in a class template, we can't + // generate bindings to template functions, because the set of + // instantiations is open ended and we have no way of knowing which + // monomorphizations actually exist. + let type_params = item.all_template_params(ctx); + if let Some(params) = type_params { + if !params.is_empty() { + return; + } + } + let name = self.name(); let mut canonical_name = item.canonical_name(ctx); let mangled_name = self.mangled_name(); |