Skip to content

Commit 4a873bf

Browse files
committed
Generate __BindgenLongDouble
1 parent 6e1fd43 commit 4a873bf

File tree

5 files changed

+63
-26
lines changed

5 files changed

+63
-26
lines changed

bindgen-tests/tests/headers/long_double.h

+2
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@
33
struct foo {
44
long double bar;
55
};
6+
7+
void take_ld(long double ld);

bindgen/codegen/helpers.rs

+1
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ pub mod ast_ty {
199199
(FloatKind::LongDouble, ..) => {
200200
// TODO(emilio): If rust ever gains f80/f128 we should
201201
// use it here and below.
202+
ctx.generated_bindgen_long_double(layout.expect("unknown layout for long double"));
202203
if ctx.options().enable_cxx_namespaces {
203204
quote! {
204205
root::__BindgenLongDouble

bindgen/codegen/mod.rs

+24-13
Original file line numberDiff line numberDiff line change
@@ -217,9 +217,6 @@ struct CodegenResult<'a> {
217217
/// Whether a bitfield allocation unit has been seen at least once.
218218
saw_bitfield_unit: bool,
219219

220-
/// Whether a long double has been seen at least once.
221-
saw_long_double: bool,
222-
223220
items_seen: HashSet<ItemId>,
224221
/// The set of generated function/var names, needed because in C/C++ is
225222
/// legal to do something like:
@@ -256,7 +253,6 @@ impl<'a> CodegenResult<'a> {
256253
saw_objc: false,
257254
saw_block: false,
258255
saw_bitfield_unit: false,
259-
saw_long_double: false,
260256
codegen_id,
261257
items_seen: Default::default(),
262258
functions_seen: Default::default(),
@@ -289,10 +285,6 @@ impl<'a> CodegenResult<'a> {
289285
self.saw_bitfield_unit = true;
290286
}
291287

292-
fn saw_long_double(&mut self) {
293-
self.saw_long_double = true;
294-
}
295-
296288
fn seen<Id: Into<ItemId>>(&self, item: Id) -> bool {
297289
self.items_seen.contains(&item.into())
298290
}
@@ -548,6 +540,9 @@ impl CodeGenerator for Module {
548540
if ctx.need_bindgen_complex_type() {
549541
utils::prepend_complex_type(&mut *result);
550542
}
543+
if let Some(layout) = ctx.need_bindgen_long_double() {
544+
utils::prepend_long_double(layout, &mut *result);
545+
}
551546
if result.saw_objc {
552547
utils::prepend_objc_header(ctx, &mut *result);
553548
}
@@ -2459,7 +2454,7 @@ impl Method {
24592454

24602455
let signature = match *signature_item.expect_type().kind() {
24612456
TypeKind::Function(ref sig) => sig,
2462-
_ => panic!("How in the world?"),
2457+
_ => unreachable!(),
24632458
};
24642459

24652460
if utils::sig_unsupported_types(ctx, signature) {
@@ -4513,6 +4508,7 @@ pub mod utils {
45134508
use crate::ir::context::BindgenContext;
45144509
use crate::ir::function::{Abi, ClangAbi, FunctionSig};
45154510
use crate::ir::item::{Item, ItemCanonicalPath};
4511+
use crate::ir::layout::Layout;
45164512
use crate::ir::ty::TypeKind;
45174513
use proc_macro2;
45184514
use std::borrow::Cow;
@@ -4785,6 +4781,21 @@ pub mod utils {
47854781
result.extend(old_items.into_iter());
47864782
}
47874783

4784+
pub fn prepend_long_double(
4785+
layout: Layout,
4786+
result: &mut Vec<proc_macro2::TokenStream>,
4787+
) {
4788+
let Layout { align, size, .. } = layout;
4789+
result.insert(
4790+
0,
4791+
quote! {
4792+
#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
4793+
#[repr(C, align(#align))]
4794+
pub struct __BindgenLongDouble([u8; #size]);
4795+
},
4796+
);
4797+
}
4798+
47884799
pub fn build_path(
47894800
item: &Item,
47904801
ctx: &BindgenContext,
@@ -5078,12 +5089,12 @@ pub mod utils {
50785089

50795090
pub fn sig_unsupported_types(
50805091
ctx: &BindgenContext,
5081-
sig: &FunctionSig
5092+
sig: &FunctionSig,
50825093
) -> bool {
5083-
sig.argument_types().iter()
5094+
sig.argument_types()
5095+
.iter()
50845096
.map(|(_, ty_id)| ty_id)
50855097
.chain(std::iter::once(&sig.return_type()))
5086-
.find(|ty_id| ctx.lookup_never_by_value(*ty_id))
5087-
.is_some()
5098+
.any(|ty_id| ctx.lookup_never_by_value(*ty_id))
50885099
}
50895100
}

bindgen/ir/analysis/never_by_value.rs

+15-11
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ impl<'ctx> NeverByValue<'ctx> {
7171
was_not_already_in_set,
7272
"We shouldn't try and insert {:?} twice because if it was \
7373
already in the set, `constrain` should have exited early.",
74-
id
74+
id
7575
);
7676

7777
ConstrainResult::Changed
@@ -128,9 +128,13 @@ impl<'ctx> MonotoneFramework for NeverByValue<'ctx> {
128128
}
129129

130130
TypeKind::Float(..) | TypeKind::Complex(..) => {
131-
let size = ty.layout(self.ctx).expect("float with unknown layout").size;
131+
let size = ty
132+
.layout(self.ctx)
133+
.expect("float with unknown layout")
134+
.size;
132135
match (ty.kind(), size) {
133-
(TypeKind::Float(..), 4 | 8) | (TypeKind::Complex(..), 8 | 16) => {
136+
(TypeKind::Float(..), 4 | 8) |
137+
(TypeKind::Complex(..), 8 | 16) => {
134138
info!(" skipped f32 or f64");
135139
ConstrainResult::Same
136140
}
@@ -156,10 +160,9 @@ impl<'ctx> MonotoneFramework for NeverByValue<'ctx> {
156160
}
157161

158162
TypeKind::Comp(ref info) => {
159-
let bases_have = info
160-
.base_members()
161-
.iter()
162-
.any(|base| self.never_by_value.contains(&base.ty.into()));
163+
let bases_have = info.base_members().iter().any(|base| {
164+
self.never_by_value.contains(&base.ty.into())
165+
});
163166
if bases_have {
164167
info!(" bases have float, so we also have");
165168
return self.insert(id);
@@ -168,10 +171,11 @@ impl<'ctx> MonotoneFramework for NeverByValue<'ctx> {
168171
Field::DataMember(ref data) => {
169172
self.never_by_value.contains(&data.ty().into())
170173
}
171-
Field::Bitfields(ref bfu) => bfu
172-
.bitfields()
173-
.iter()
174-
.any(|b| self.never_by_value.contains(&b.ty().into())),
174+
Field::Bitfields(ref bfu) => {
175+
bfu.bitfields().iter().any(|b| {
176+
self.never_by_value.contains(&b.ty().into())
177+
})
178+
}
175179
});
176180
if fields_have {
177181
info!(" fields have float, so we also have");

bindgen/ir/context.rs

+21-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use super::super::time::Timer;
44
use super::analysis::{
55
analyze, as_cannot_derive_set, CannotDerive, DeriveTrait,
66
HasDestructorAnalysis, HasFloat, HasTypeParameterInArray,
7-
HasVtableAnalysis, HasVtableResult, NeverByValue,
8-
SizednessAnalysis, SizednessResult, UsedTemplateParameters,
7+
HasVtableAnalysis, HasVtableResult, NeverByValue, SizednessAnalysis,
8+
SizednessResult, UsedTemplateParameters,
99
};
1010
use super::derive::{
1111
CanDerive, CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, CanDeriveEq,
@@ -20,6 +20,7 @@ use super::template::{TemplateInstantiation, TemplateParameters};
2020
use super::traversal::{self, Edge, ItemTraversal};
2121
use super::ty::{FloatKind, Type, TypeKind};
2222
use crate::clang::{self, Cursor};
23+
use crate::ir::layout::Layout;
2324
use crate::BindgenOptions;
2425
use crate::{Entry, HashMap, HashSet};
2526
use cexpr;
@@ -375,6 +376,9 @@ pub struct BindgenContext {
375376
/// Whether a bindgen complex was generated
376377
generated_bindgen_complex: Cell<bool>,
377378

379+
/// Whether a bindgen long double was generated
380+
generated_bindgen_long_double: Cell<Option<Layout>>,
381+
378382
/// The set of `ItemId`s that are allowlisted. This the very first thing
379383
/// computed after parsing our IR, and before running any of our analyses.
380384
allowlisted: Option<ItemSet>,
@@ -584,6 +588,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
584588
target_info,
585589
options,
586590
generated_bindgen_complex: Cell::new(false),
591+
generated_bindgen_long_double: Cell::new(None),
587592
allowlisted: None,
588593
blocklisted_types_implement_traits: Default::default(),
589594
codegen_items: None,
@@ -2504,6 +2509,20 @@ If you encounter an error missing from this list, please file an issue or a PR!"
25042509
self.generated_bindgen_complex.get()
25052510
}
25062511

2512+
/// Call if a bindgen long double is generated
2513+
pub fn generated_bindgen_long_double(&self, layout: Layout) {
2514+
if let Some(old) =
2515+
self.generated_bindgen_long_double.replace(Some(layout))
2516+
{
2517+
assert_eq!(layout, old, "long doubles had different layout");
2518+
}
2519+
}
2520+
2521+
/// Whether we need to generate the bindgen long double type (and if so, get its layout)
2522+
pub fn need_bindgen_long_double(&self) -> Option<Layout> {
2523+
self.generated_bindgen_long_double.get()
2524+
}
2525+
25072526
/// Compute which `enum`s have an associated `typedef` definition.
25082527
fn compute_enum_typedef_combos(&mut self) {
25092528
let _t = self.timer("compute_enum_typedef_combos");

0 commit comments

Comments
 (0)