diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2018-09-19 18:07:51 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-09-19 18:07:51 -0400 |
commit | 6fc0a31febb63d77da1a38aa2eea9d10fbea0d0d (patch) | |
tree | cb09d8cb35d94b1af4e3cf4f4bdf447d29a76029 /src/codegen | |
parent | a54a9dc796372478d26fa5b165c3b4d129cbcfce (diff) | |
parent | c09c74e18b6ce8b69626a59737d8e82a3eb1d1b8 (diff) |
Auto merge of #1391 - emilio:u128, r=fitzgen
codegen: Generate u128 / i128 when available.
This is the first step to fix #1370 / #1338 / etc.
Fix for that will build up on this.
Diffstat (limited to 'src/codegen')
-rw-r--r-- | src/codegen/helpers.rs | 53 | ||||
-rw-r--r-- | src/codegen/impl_debug.rs | 2 | ||||
-rw-r--r-- | src/codegen/mod.rs | 44 | ||||
-rw-r--r-- | src/codegen/struct_layout.rs | 19 |
4 files changed, 78 insertions, 40 deletions
diff --git a/src/codegen/helpers.rs b/src/codegen/helpers.rs index b7c3df7f..343f1e30 100644 --- a/src/codegen/helpers.rs +++ b/src/codegen/helpers.rs @@ -59,14 +59,14 @@ pub mod attributes { /// Generates a proper type for a field or type with a given `Layout`, that is, /// a type with the correct size and alignment restrictions. -pub fn blob(layout: Layout) -> quote::Tokens { +pub fn blob(ctx: &BindgenContext, layout: Layout) -> quote::Tokens { let opaque = layout.opaque(); // FIXME(emilio, #412): We fall back to byte alignment, but there are // some things that legitimately are more than 8-byte aligned. // // Eventually we should be able to `unwrap` here, but... - let ty_name = match opaque.known_rust_type_for_array() { + let ty_name = match opaque.known_rust_type_for_array(ctx) { Some(ty) => ty, None => { warn!("Found unknown alignment on code generation!"); @@ -76,7 +76,7 @@ pub fn blob(layout: Layout) -> quote::Tokens { let ty_name = Term::new(ty_name, Span::call_site()); - let data_len = opaque.array_size().unwrap_or(layout.size); + let data_len = opaque.array_size(ctx).unwrap_or(layout.size); if data_len == 1 { quote! { @@ -90,8 +90,8 @@ 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> { - let name = Layout::known_type_for_size(layout.size)?; +pub fn integer_type(ctx: &BindgenContext, layout: Layout) -> Option<quote::Tokens> { + let name = Layout::known_type_for_size(ctx, layout.size)?; let name = Term::new(name, Span::call_site()); Some(quote! { #name }) } @@ -122,6 +122,7 @@ pub fn bitfield_unit(ctx: &BindgenContext, layout: Layout) -> quote::Tokens { pub mod ast_ty { use ir::context::BindgenContext; use ir::function::FunctionSig; + use ir::layout::Layout; use ir::ty::FloatKind; use quote; use proc_macro2; @@ -144,22 +145,44 @@ pub mod ast_ty { pub fn float_kind_rust_type( ctx: &BindgenContext, fk: FloatKind, + layout: Option<Layout>, ) -> quote::Tokens { - // TODO: we probably should just take the type layout into - // account? + // TODO: we probably should take the type layout into account more + // often? // // Also, maybe this one shouldn't be the default? - // - // FIXME: `c_longdouble` doesn't seem to be defined in some - // systems, so we use `c_double` directly. match (fk, ctx.options().convert_floats) { (FloatKind::Float, true) => quote! { f32 }, - (FloatKind::Double, true) | - (FloatKind::LongDouble, true) => quote! { f64 }, + (FloatKind::Double, true) => quote! { f64 }, (FloatKind::Float, false) => raw_type(ctx, "c_float"), - (FloatKind::Double, false) | - (FloatKind::LongDouble, false) => raw_type(ctx, "c_double"), - (FloatKind::Float128, _) => quote! { [u8; 16] }, + (FloatKind::Double, false) => raw_type(ctx, "c_double"), + (FloatKind::LongDouble, _) => { + match layout { + Some(layout) => { + match layout.size { + 4 => quote! { f32 }, + 8 => quote! { f64 }, + // TODO(emilio): If rust ever gains f128 we should + // use it here and below. + _ => super::integer_type(ctx, layout).unwrap_or(quote! { f64 }), + } + } + None => { + debug_assert!( + false, + "How didn't we know the layout for a primitive type?" + ); + quote! { f64 } + } + } + } + (FloatKind::Float128, _) => { + if ctx.options().rust_features.i128_and_u128 { + quote! { u128 } + } else { + quote! { [u64; 2] } + } + } } } diff --git a/src/codegen/impl_debug.rs b/src/codegen/impl_debug.rs index 0f8e4d96..2c6d36d9 100644 --- a/src/codegen/impl_debug.rs +++ b/src/codegen/impl_debug.rs @@ -236,7 +236,7 @@ impl<'a> ImplDebug<'a> for Item { let inner_type = ctx.resolve_type(inner).canonical_type(ctx); match *inner_type.kind() { TypeKind::Function(ref sig) - if !sig.can_trivially_derive_debug() => { + if !sig.can_trivially_derive_debug(ctx) => { Some((format!("{}: FunctionPointer", name), vec![])) } _ => debug_print(name, quote! { #name_ident }), diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 8aa8d348..67d6b6d5 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -1185,7 +1185,7 @@ impl Bitfield { let bitfield_ty_layout = bitfield_ty.layout(ctx).expect( "Bitfield without layout? Gah!", ); - let bitfield_int_ty = helpers::blob(bitfield_ty_layout); + let bitfield_int_ty = helpers::blob(ctx, bitfield_ty_layout); let offset = self.offset_into_unit(); let width = self.width() as u8; @@ -1367,7 +1367,7 @@ impl<'a> FieldCodegen<'a> for Bitfield { let bitfield_ty_layout = bitfield_ty.layout(ctx).expect( "Bitfield without layout? Gah!", ); - let bitfield_int_ty = match helpers::integer_type(bitfield_ty_layout) { + let bitfield_int_ty = match helpers::integer_type(ctx, bitfield_ty_layout) { Some(int_ty) => { *bitfield_representable_as_int = true; int_ty @@ -1547,7 +1547,7 @@ impl CodeGenerator for CompInfo { } let layout = layout.expect("Unable to get layout information?"); - let ty = helpers::blob(layout); + let ty = helpers::blob(ctx, layout); fields.push(if self.can_be_rust_union(ctx) { quote! { @@ -1572,7 +1572,7 @@ impl CodeGenerator for CompInfo { Some(l) => { explicit_align = Some(l.align); - let ty = helpers::blob(l); + let ty = helpers::blob(ctx, l); fields.push(quote! { pub _bindgen_opaque_blob: #ty , }); @@ -1595,7 +1595,7 @@ impl CodeGenerator for CompInfo { } else { explicit_align = Some(layout.align); if !ctx.options().rust_features.repr_align { - let ty = helpers::blob(Layout::new(0, layout.align)); + let ty = helpers::blob(ctx, Layout::new(0, layout.align)); fields.push(quote! { pub __bindgen_align: #ty , }); @@ -1629,7 +1629,7 @@ impl CodeGenerator for CompInfo { }; if has_address { - let ty = helpers::blob(Layout::new(1, 1)); + let ty = helpers::blob(ctx, Layout::new(1, 1)); fields.push(quote! { pub _address: #ty, }); @@ -2800,7 +2800,7 @@ trait TryToOpaque { extra: &Self::Extra, ) -> error::Result<quote::Tokens> { self.try_get_layout(ctx, extra).map(|layout| { - helpers::blob(layout) + helpers::blob(ctx, layout) }) } } @@ -2827,7 +2827,7 @@ trait ToOpaque: TryToOpaque { extra: &Self::Extra, ) -> quote::Tokens { let layout = self.get_layout(ctx, extra); - helpers::blob(layout) + helpers::blob(ctx, layout) } } @@ -2885,7 +2885,7 @@ where |_| if let Ok(layout) = self.try_get_layout(ctx, extra) { - Ok(helpers::blob(layout)) + Ok(helpers::blob(ctx, layout)) } else { Err(error::Error::NoLayoutForOpaqueBlob) }, @@ -3037,7 +3037,7 @@ impl TryToRustTy for Type { IntKind::LongLong => Ok(raw_type(ctx, "c_longlong")), IntKind::ULongLong => Ok(raw_type(ctx, "c_ulonglong")), IntKind::WChar { size } => { - let ty = Layout::known_type_for_size(size) + let ty = Layout::known_type_for_size(ctx, size) .expect("Non-representable wchar_t?"); let ident = ctx.rust_ident_raw(ty); Ok(quote! { #ident }) @@ -3059,17 +3059,27 @@ impl TryToRustTy for Type { #ident }) } - // FIXME: This doesn't generate the proper alignment, but we - // can't do better right now. We should be able to use - // i128/u128 when they're available. - IntKind::U128 | IntKind::I128 => { - Ok(quote! { [u64; 2] }) + IntKind::U128 => { + Ok(if ctx.options().rust_features.i128_and_u128 { + quote! { u128 } + } else { + // Best effort thing, but wrong alignment + // unfortunately. + quote! { [u64; 2] } + }) + } + IntKind::I128 => { + Ok(if ctx.options().rust_features.i128_and_u128 { + quote! { i128 } + } else { + quote! { [u64; 2] } + }) } } } - TypeKind::Float(fk) => Ok(float_kind_rust_type(ctx, fk)), + TypeKind::Float(fk) => Ok(float_kind_rust_type(ctx, fk, self.layout(ctx))), TypeKind::Complex(fk) => { - let float_path = float_kind_rust_type(ctx, fk); + let float_path = float_kind_rust_type(ctx, fk, self.layout(ctx)); ctx.generated_bindgen_complex(); Ok(if ctx.options().enable_cxx_namespaces { diff --git a/src/codegen/struct_layout.rs b/src/codegen/struct_layout.rs index 6de7e030..0ea23ddf 100644 --- a/src/codegen/struct_layout.rs +++ b/src/codegen/struct_layout.rs @@ -287,18 +287,23 @@ impl<'a> StructLayoutTracker<'a> { } pub fn requires_explicit_align(&self, layout: Layout) -> bool { + let repr_align = self.ctx.options().rust_features().repr_align; + + // Always force explicit repr(align) for stuff more than 16-byte aligned + // to work-around https://github.com/rust-lang/rust/issues/54341. + // + // Worst-case this just generates redundant alignment attributes. + if repr_align && self.max_field_align >= 16 { + return true; + } + if self.max_field_align >= layout.align { return false; } - // At this point we require explicit alignment, but we may not be able - // to generate the right bits, let's double check. - if self.ctx.options().rust_features().repr_align { - return true; - } // We can only generate up-to a word of alignment unless we support // repr(align). - layout.align <= self.ctx.target_pointer_size() + repr_align || layout.align <= self.ctx.target_pointer_size() } fn padding_bytes(&self, layout: Layout) -> usize { @@ -306,7 +311,7 @@ impl<'a> StructLayoutTracker<'a> { } fn padding_field(&mut self, layout: Layout) -> quote::Tokens { - let ty = helpers::blob(layout); + let ty = helpers::blob(self.ctx, layout); let padding_count = self.padding_count; self.padding_count += 1; |