Skip to content

codegen: Generate u128 / i128 when available. #1391

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Sep 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 38 additions & 15 deletions src/codegen/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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!");
Expand All @@ -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! {
Expand All @@ -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 })
}
Expand Down Expand Up @@ -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;
Expand All @@ -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] }
}
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/codegen/impl_debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 }),
Expand Down
44 changes: 27 additions & 17 deletions src/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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! {
Expand All @@ -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 ,
});
Expand All @@ -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 ,
});
Expand Down Expand Up @@ -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,
});
Expand Down Expand Up @@ -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)
})
}
}
Expand All @@ -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)
}
}

Expand Down Expand Up @@ -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)
},
Expand Down Expand Up @@ -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 })
Expand All @@ -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 {
Expand Down
19 changes: 12 additions & 7 deletions src/codegen/struct_layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,26 +287,31 @@ 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 {
align_to(self.latest_offset, layout.align) - self.latest_offset
}

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;
Expand Down
6 changes: 6 additions & 0 deletions src/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ macro_rules! rust_target_base {
=> Stable_1_21 => 1.21;
/// Rust stable 1.25
=> Stable_1_25 => 1.25;
/// Rust stable 1.26
=> Stable_1_26 => 1.26;
/// Nightly rust
=> Nightly => nightly;
);
Expand Down Expand Up @@ -172,6 +174,10 @@ rust_feature_def!(
/// repr(align) ([PR](https://github.com/rust-lang/rust/pull/47006))
=> repr_align;
}
Stable_1_26 {
/// [i128 / u128 support](https://doc.rust-lang.org/std/primitive.i128.html)
=> i128_and_u128;
}
Nightly {
/// `thiscall` calling convention ([Tracking issue](https://github.com/rust-lang/rust/issues/42202))
=> thiscall_abi;
Expand Down
2 changes: 1 addition & 1 deletion src/ir/analysis/derive_copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveCopy<'ctx> {

if item.is_opaque(self.ctx, &()) {
let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| {
l.opaque().can_trivially_derive_copy()
l.opaque().can_trivially_derive_copy(self.ctx)
});
return if layout_can_derive {
trace!(" we can trivially derive Copy for the layout");
Expand Down
6 changes: 3 additions & 3 deletions src/ir/analysis/derive_debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveDebug<'ctx> {

if item.is_opaque(self.ctx, &()) {
let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| {
l.opaque().can_trivially_derive_debug()
l.opaque().can_trivially_derive_debug(self.ctx)
});
return if layout_can_derive &&
!(ty.is_union() &&
Expand Down Expand Up @@ -242,7 +242,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveDebug<'ctx> {
}

if ty.layout(self.ctx).map_or(true, |l| {
l.opaque().can_trivially_derive_debug()
l.opaque().can_trivially_derive_debug(self.ctx)
})
{
trace!(" union layout can trivially derive Debug");
Expand Down Expand Up @@ -299,7 +299,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveDebug<'ctx> {
let inner_type =
self.ctx.resolve_type(inner).canonical_type(self.ctx);
if let TypeKind::Function(ref sig) = *inner_type.kind() {
if !sig.can_trivially_derive_debug() {
if !sig.can_trivially_derive_debug(self.ctx) {
trace!(
" function pointer that can't trivially derive Debug"
);
Expand Down
4 changes: 2 additions & 2 deletions src/ir/analysis/derive_default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveDefault<'ctx> {

if item.is_opaque(self.ctx, &()) {
let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| {
l.opaque().can_trivially_derive_default()
l.opaque().can_trivially_derive_default(self.ctx)
});
return if layout_can_derive &&
!(ty.is_union() &&
Expand Down Expand Up @@ -278,7 +278,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveDefault<'ctx> {
}

if ty.layout(self.ctx).map_or(true, |l| {
l.opaque().can_trivially_derive_default()
l.opaque().can_trivially_derive_default(self.ctx)
})
{
trace!(" union layout can trivially derive Default");
Expand Down
8 changes: 4 additions & 4 deletions src/ir/analysis/derive_hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> {

if item.is_opaque(self.ctx, &()) {
let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| {
l.opaque().can_trivially_derive_hash()
l.opaque().can_trivially_derive_hash(self.ctx)
});
return if layout_can_derive &&
!(ty.is_union() &&
Expand Down Expand Up @@ -218,7 +218,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> {
let inner_type =
self.ctx.resolve_type(inner).canonical_type(self.ctx);
if let TypeKind::Function(ref sig) = *inner_type.kind() {
if !sig.can_trivially_derive_hash() {
if !sig.can_trivially_derive_hash(self.ctx) {
trace!(
" function pointer that can't trivially derive Hash"
);
Expand All @@ -230,7 +230,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> {
}

TypeKind::Function(ref sig) => {
if !sig.can_trivially_derive_hash() {
if !sig.can_trivially_derive_hash(self.ctx) {
trace!(" function that can't trivially derive Hash");
return self.insert(id);
}
Expand Down Expand Up @@ -275,7 +275,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> {
}

if ty.layout(self.ctx).map_or(true, |l| {
l.opaque().can_trivially_derive_hash()
l.opaque().can_trivially_derive_hash(self.ctx)
})
{
trace!(" union layout can trivially derive Hash");
Expand Down
Loading