Skip to content

Commit

Permalink
Generate __BindgenLongDouble
Browse files Browse the repository at this point in the history
  • Loading branch information
GKFX committed Feb 3, 2023
1 parent 6e1fd43 commit 4a873bf
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 26 deletions.
2 changes: 2 additions & 0 deletions bindgen-tests/tests/headers/long_double.h
Expand Up @@ -3,3 +3,5 @@
struct foo {
long double bar;
};

void take_ld(long double ld);
1 change: 1 addition & 0 deletions bindgen/codegen/helpers.rs
Expand Up @@ -199,6 +199,7 @@ pub mod ast_ty {
(FloatKind::LongDouble, ..) => {
// TODO(emilio): If rust ever gains f80/f128 we should
// use it here and below.
ctx.generated_bindgen_long_double(layout.expect("unknown layout for long double"));
if ctx.options().enable_cxx_namespaces {
quote! {
root::__BindgenLongDouble
Expand Down
37 changes: 24 additions & 13 deletions bindgen/codegen/mod.rs
Expand Up @@ -217,9 +217,6 @@ struct CodegenResult<'a> {
/// Whether a bitfield allocation unit has been seen at least once.
saw_bitfield_unit: bool,

/// Whether a long double has been seen at least once.
saw_long_double: bool,

items_seen: HashSet<ItemId>,
/// The set of generated function/var names, needed because in C/C++ is
/// legal to do something like:
Expand Down Expand Up @@ -256,7 +253,6 @@ impl<'a> CodegenResult<'a> {
saw_objc: false,
saw_block: false,
saw_bitfield_unit: false,
saw_long_double: false,
codegen_id,
items_seen: Default::default(),
functions_seen: Default::default(),
Expand Down Expand Up @@ -289,10 +285,6 @@ impl<'a> CodegenResult<'a> {
self.saw_bitfield_unit = true;
}

fn saw_long_double(&mut self) {
self.saw_long_double = true;
}

fn seen<Id: Into<ItemId>>(&self, item: Id) -> bool {
self.items_seen.contains(&item.into())
}
Expand Down Expand Up @@ -548,6 +540,9 @@ impl CodeGenerator for Module {
if ctx.need_bindgen_complex_type() {
utils::prepend_complex_type(&mut *result);
}
if let Some(layout) = ctx.need_bindgen_long_double() {
utils::prepend_long_double(layout, &mut *result);
}
if result.saw_objc {
utils::prepend_objc_header(ctx, &mut *result);
}
Expand Down Expand Up @@ -2459,7 +2454,7 @@ impl Method {

let signature = match *signature_item.expect_type().kind() {
TypeKind::Function(ref sig) => sig,
_ => panic!("How in the world?"),
_ => unreachable!(),
};

if utils::sig_unsupported_types(ctx, signature) {
Expand Down Expand Up @@ -4513,6 +4508,7 @@ pub mod utils {
use crate::ir::context::BindgenContext;
use crate::ir::function::{Abi, ClangAbi, FunctionSig};
use crate::ir::item::{Item, ItemCanonicalPath};
use crate::ir::layout::Layout;
use crate::ir::ty::TypeKind;
use proc_macro2;
use std::borrow::Cow;
Expand Down Expand Up @@ -4785,6 +4781,21 @@ pub mod utils {
result.extend(old_items.into_iter());
}

pub fn prepend_long_double(
layout: Layout,
result: &mut Vec<proc_macro2::TokenStream>,
) {
let Layout { align, size, .. } = layout;
result.insert(
0,
quote! {
#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
#[repr(C, align(#align))]
pub struct __BindgenLongDouble([u8; #size]);
},
);
}

pub fn build_path(
item: &Item,
ctx: &BindgenContext,
Expand Down Expand Up @@ -5078,12 +5089,12 @@ pub mod utils {

pub fn sig_unsupported_types(
ctx: &BindgenContext,
sig: &FunctionSig
sig: &FunctionSig,
) -> bool {
sig.argument_types().iter()
sig.argument_types()
.iter()
.map(|(_, ty_id)| ty_id)
.chain(std::iter::once(&sig.return_type()))
.find(|ty_id| ctx.lookup_never_by_value(*ty_id))
.is_some()
.any(|ty_id| ctx.lookup_never_by_value(*ty_id))
}
}
26 changes: 15 additions & 11 deletions bindgen/ir/analysis/never_by_value.rs
Expand Up @@ -71,7 +71,7 @@ impl<'ctx> NeverByValue<'ctx> {
was_not_already_in_set,
"We shouldn't try and insert {:?} twice because if it was \
already in the set, `constrain` should have exited early.",
id
id
);

ConstrainResult::Changed
Expand Down Expand Up @@ -128,9 +128,13 @@ impl<'ctx> MonotoneFramework for NeverByValue<'ctx> {
}

TypeKind::Float(..) | TypeKind::Complex(..) => {
let size = ty.layout(self.ctx).expect("float with unknown layout").size;
let size = ty
.layout(self.ctx)
.expect("float with unknown layout")
.size;
match (ty.kind(), size) {
(TypeKind::Float(..), 4 | 8) | (TypeKind::Complex(..), 8 | 16) => {
(TypeKind::Float(..), 4 | 8) |
(TypeKind::Complex(..), 8 | 16) => {
info!(" skipped f32 or f64");
ConstrainResult::Same
}
Expand All @@ -156,10 +160,9 @@ impl<'ctx> MonotoneFramework for NeverByValue<'ctx> {
}

TypeKind::Comp(ref info) => {
let bases_have = info
.base_members()
.iter()
.any(|base| self.never_by_value.contains(&base.ty.into()));
let bases_have = info.base_members().iter().any(|base| {
self.never_by_value.contains(&base.ty.into())
});
if bases_have {
info!(" bases have float, so we also have");
return self.insert(id);
Expand All @@ -168,10 +171,11 @@ impl<'ctx> MonotoneFramework for NeverByValue<'ctx> {
Field::DataMember(ref data) => {
self.never_by_value.contains(&data.ty().into())
}
Field::Bitfields(ref bfu) => bfu
.bitfields()
.iter()
.any(|b| self.never_by_value.contains(&b.ty().into())),
Field::Bitfields(ref bfu) => {
bfu.bitfields().iter().any(|b| {
self.never_by_value.contains(&b.ty().into())
})
}
});
if fields_have {
info!(" fields have float, so we also have");
Expand Down
23 changes: 21 additions & 2 deletions bindgen/ir/context.rs
Expand Up @@ -4,8 +4,8 @@ use super::super::time::Timer;
use super::analysis::{
analyze, as_cannot_derive_set, CannotDerive, DeriveTrait,
HasDestructorAnalysis, HasFloat, HasTypeParameterInArray,
HasVtableAnalysis, HasVtableResult, NeverByValue,
SizednessAnalysis, SizednessResult, UsedTemplateParameters,
HasVtableAnalysis, HasVtableResult, NeverByValue, SizednessAnalysis,
SizednessResult, UsedTemplateParameters,
};
use super::derive::{
CanDerive, CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, CanDeriveEq,
Expand All @@ -20,6 +20,7 @@ use super::template::{TemplateInstantiation, TemplateParameters};
use super::traversal::{self, Edge, ItemTraversal};
use super::ty::{FloatKind, Type, TypeKind};
use crate::clang::{self, Cursor};
use crate::ir::layout::Layout;
use crate::BindgenOptions;
use crate::{Entry, HashMap, HashSet};
use cexpr;
Expand Down Expand Up @@ -375,6 +376,9 @@ pub struct BindgenContext {
/// Whether a bindgen complex was generated
generated_bindgen_complex: Cell<bool>,

/// Whether a bindgen long double was generated
generated_bindgen_long_double: Cell<Option<Layout>>,

/// The set of `ItemId`s that are allowlisted. This the very first thing
/// computed after parsing our IR, and before running any of our analyses.
allowlisted: Option<ItemSet>,
Expand Down Expand Up @@ -584,6 +588,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
target_info,
options,
generated_bindgen_complex: Cell::new(false),
generated_bindgen_long_double: Cell::new(None),
allowlisted: None,
blocklisted_types_implement_traits: Default::default(),
codegen_items: None,
Expand Down Expand Up @@ -2504,6 +2509,20 @@ If you encounter an error missing from this list, please file an issue or a PR!"
self.generated_bindgen_complex.get()
}

/// Call if a bindgen long double is generated
pub fn generated_bindgen_long_double(&self, layout: Layout) {
if let Some(old) =
self.generated_bindgen_long_double.replace(Some(layout))
{
assert_eq!(layout, old, "long doubles had different layout");
}
}

/// Whether we need to generate the bindgen long double type (and if so, get its layout)
pub fn need_bindgen_long_double(&self) -> Option<Layout> {
self.generated_bindgen_long_double.get()
}

/// Compute which `enum`s have an associated `typedef` definition.
fn compute_enum_typedef_combos(&mut self) {
let _t = self.timer("compute_enum_typedef_combos");
Expand Down

0 comments on commit 4a873bf

Please sign in to comment.