summaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2018-09-19 18:07:51 -0400
committerGitHub <noreply@github.com>2018-09-19 18:07:51 -0400
commit6fc0a31febb63d77da1a38aa2eea9d10fbea0d0d (patch)
treecb09d8cb35d94b1af4e3cf4f4bdf447d29a76029 /src/codegen
parenta54a9dc796372478d26fa5b165c3b4d129cbcfce (diff)
parentc09c74e18b6ce8b69626a59737d8e82a3eb1d1b8 (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.rs53
-rw-r--r--src/codegen/impl_debug.rs2
-rw-r--r--src/codegen/mod.rs44
-rw-r--r--src/codegen/struct_layout.rs19
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;