Skip to content

Commit 82710ad

Browse files
committed
Block function bindings which pass extended floats by value #2403
1 parent 20aa65a commit 82710ad

12 files changed

+430
-39
lines changed

bindgen-tests/tests/expectations/tests/complex_global.rs

+4-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bindgen-tests/tests/expectations/tests/convert-floats-win64.rs

+41
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bindgen-tests/tests/expectations/tests/convert-floats.rs

+4-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bindgen-tests/tests/expectations/tests/long_double.rs

+4-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// bindgen-flags: -- --target=x86_64-pc-windows-msvc
2+
3+
struct foo {
4+
float bar, baz;
5+
double bazz;
6+
long double* bazzz;
7+
float _Complex complexFloat;
8+
double _Complex complexDouble;
9+
};

bindgen-tests/tests/headers/convert-floats.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// bindgen-flags: --no-convert-floats
1+
// bindgen-flags: --no-convert-floats -- --target=x86_64-unknown-linux-gnu
22

33
struct foo {
44
float bar, baz;

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

+31-26
Original file line numberDiff line numberDiff line change
@@ -243,14 +243,19 @@ pub(crate) mod ast_ty {
243243
pub(crate) fn float_kind_rust_type(
244244
ctx: &BindgenContext,
245245
fk: FloatKind,
246-
layout: Option<Layout>,
246+
mut layout: Option<Layout>,
247+
n_parts: usize,
247248
) -> syn::Type {
248-
// TODO: we probably should take the type layout into account more
249-
// often?
250-
//
251-
// Also, maybe this one shouldn't be the default?
252-
match (fk, ctx.options().convert_floats) {
253-
(FloatKind::Float16, _) => {
249+
// Convert the layout of complex numbers to the layout of its parts.
250+
let bits = match layout {
251+
Some(Layout { ref mut size, .. }) => {
252+
*size /= n_parts;
253+
Some(*size * 8)
254+
}
255+
None => None,
256+
};
257+
match dbg!(fk, ctx.options().convert_floats, bits) {
258+
(FloatKind::Float16, _, _) => {
254259
// TODO: do f16 when rust lands it
255260
ctx.generated_bindgen_float16();
256261
if ctx.options().enable_cxx_namespaces {
@@ -259,29 +264,29 @@ pub(crate) mod ast_ty {
259264
syn::parse_quote! { __BindgenFloat16 }
260265
}
261266
}
262-
(FloatKind::Float, true) => syn::parse_quote! { f32 },
263-
(FloatKind::Double, true) => syn::parse_quote! { f64 },
264-
(FloatKind::Float, false) => raw_type(ctx, "c_float"),
265-
(FloatKind::Double, false) => raw_type(ctx, "c_double"),
266-
(FloatKind::LongDouble, _) => {
267-
if let Some(layout) = layout {
268-
match layout.size {
269-
4 => syn::parse_quote! { f32 },
270-
8 => syn::parse_quote! { f64 },
271-
// TODO(emilio): If rust ever gains f128 we should
272-
// use it here and below.
273-
_ => super::integer_type(layout)
274-
.unwrap_or(syn::parse_quote! { f64 }),
267+
(_, true, Some(32)) => syn::parse_quote! { f32 },
268+
(_, true, Some(64)) | (FloatKind::Double, true, None) => {
269+
syn::parse_quote! { f64 }
270+
}
271+
(FloatKind::Float, ..) => raw_type(ctx, "c_float"),
272+
(FloatKind::Double, ..) => raw_type(ctx, "c_double"),
273+
(FloatKind::LongDouble, ..) => {
274+
// TODO(emilio): If rust ever gains f80/f128 we should
275+
// use it here and below.
276+
ctx.generated_bindgen_long_double(
277+
layout.expect("unknown layout for long double"),
278+
);
279+
if ctx.options().enable_cxx_namespaces {
280+
syn::parse_quote! {
281+
root::__BindgenLongDouble
275282
}
276283
} else {
277-
debug_assert!(
278-
false,
279-
"How didn't we know the layout for a primitive type?"
280-
);
281-
syn::parse_quote! { f64 }
284+
syn::parse_quote! {
285+
__BindgenLongDouble
286+
}
282287
}
283288
}
284-
(FloatKind::Float128, _) => {
289+
(FloatKind::Float128, ..) => {
285290
if true {
286291
syn::parse_quote! { u128 }
287292
} else {

bindgen/codegen/mod.rs

+43-2
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,9 @@ impl CodeGenerator for Module {
584584
if ctx.need_opaque_array_type() {
585585
utils::prepend_opaque_array_type(&mut *result);
586586
}
587+
if let Some(layout) = ctx.need_bindgen_long_double() {
588+
utils::prepend_long_double(layout, &mut *result);
589+
}
587590
if result.saw_objc {
588591
utils::prepend_objc_header(ctx, &mut *result);
589592
}
@@ -3043,6 +3046,10 @@ impl Method {
30433046
return;
30443047
}
30453048

3049+
if utils::sig_unsupported_types(ctx, signature) {
3050+
return;
3051+
}
3052+
30463053
// Do not generate variadic methods, since rust does not allow
30473054
// implementing them, and we don't do a good job at it anyway.
30483055
if signature.is_variadic() {
@@ -4287,11 +4294,11 @@ impl TryToRustTy for Type {
42874294
Ok(int_kind_rust_type(ctx, ik, self.layout(ctx)))
42884295
}
42894296
TypeKind::Float(fk) => {
4290-
Ok(float_kind_rust_type(ctx, fk, self.layout(ctx)))
4297+
Ok(float_kind_rust_type(ctx, fk, self.layout(ctx), 1))
42914298
}
42924299
TypeKind::Complex(fk) => {
42934300
let float_path =
4294-
float_kind_rust_type(ctx, fk, self.layout(ctx));
4301+
float_kind_rust_type(ctx, fk, self.layout(ctx), 2);
42954302

42964303
ctx.generated_bindgen_complex();
42974304
Ok(if ctx.options().enable_cxx_namespaces {
@@ -4644,6 +4651,11 @@ impl CodeGenerator for Function {
46444651
Ok(abi) => abi,
46454652
};
46464653

4654+
if utils::sig_unsupported_types(ctx, signature) {
4655+
warn!("Skipping function which passes or returns by value types not available in Rust.");
4656+
return None;
4657+
}
4658+
46474659
// Handle overloaded functions by giving each overload its own unique
46484660
// suffix.
46494661
let times_seen = result.overload_number(&canonical_name);
@@ -5193,6 +5205,7 @@ pub(crate) mod utils {
51935205
use crate::ir::context::TypeId;
51945206
use crate::ir::function::{Abi, ClangAbi, FunctionSig};
51955207
use crate::ir::item::{Item, ItemCanonicalPath};
5208+
use crate::ir::layout::Layout;
51965209
use crate::ir::ty::TypeKind;
51975210
use crate::{args_are_cpp, file_is_cpp};
51985211
use std::borrow::Cow;
@@ -5627,6 +5640,23 @@ pub(crate) mod utils {
56275640
result.insert(0, ty);
56285641
}
56295642

5643+
pub(crate) fn prepend_long_double(
5644+
layout: Layout,
5645+
result: &mut Vec<proc_macro2::TokenStream>,
5646+
) {
5647+
let Layout { align, size, .. } = layout;
5648+
let align = proc_macro2::Literal::u64_unsuffixed(align as u64);
5649+
let size = proc_macro2::Literal::u64_unsuffixed(size as u64);
5650+
result.insert(
5651+
0,
5652+
quote! {
5653+
#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
5654+
#[repr(C, align(#align))]
5655+
pub struct __BindgenLongDouble([u8; #size]);
5656+
},
5657+
);
5658+
}
5659+
56305660
pub(crate) fn build_path(
56315661
item: &Item,
56325662
ctx: &BindgenContext,
@@ -5918,4 +5948,15 @@ pub(crate) mod utils {
59185948

59195949
true
59205950
}
5951+
5952+
pub(crate) fn sig_unsupported_types(
5953+
ctx: &BindgenContext,
5954+
sig: &FunctionSig,
5955+
) -> bool {
5956+
sig.argument_types()
5957+
.iter()
5958+
.map(|(_, ty_id)| ty_id)
5959+
.chain(std::iter::once(&sig.return_type()))
5960+
.any(|ty_id| ctx.lookup_never_by_value(*ty_id))
5961+
}
59215962
}

bindgen/ir/analysis/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ mod has_type_param_in_array;
5353
pub(crate) use self::has_type_param_in_array::HasTypeParameterInArray;
5454
mod has_float;
5555
pub(crate) use self::has_float::HasFloat;
56+
mod never_by_value;
57+
pub use self::never_by_value::NeverByValue;
5658
mod sizedness;
5759
pub(crate) use self::sizedness::{
5860
Sizedness, SizednessAnalysis, SizednessResult,

0 commit comments

Comments
 (0)