Skip to content

Commit 5ee4bb7

Browse files
committed
Block function bindings which pass extended floats by value #2403
1 parent 3b5ce9c commit 5ee4bb7

12 files changed

+458
-42
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

+71
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

+29-29
Original file line numberDiff line numberDiff line change
@@ -225,14 +225,19 @@ pub(crate) mod ast_ty {
225225
pub(crate) fn float_kind_rust_type(
226226
ctx: &BindgenContext,
227227
fk: FloatKind,
228-
layout: Option<Layout>,
228+
mut layout: Option<Layout>,
229+
n_parts: usize,
229230
) -> syn::Type {
230-
// TODO: we probably should take the type layout into account more
231-
// often?
232-
//
233-
// Also, maybe this one shouldn't be the default?
234-
match (fk, ctx.options().convert_floats) {
235-
(FloatKind::Float16, _) => {
231+
// Convert the layout of complex numbers to the layout of its parts.
232+
let bits = match layout {
233+
Some(Layout { ref mut size, .. }) => {
234+
*size /= n_parts;
235+
Some(*size * 8)
236+
}
237+
None => None,
238+
};
239+
match dbg!(fk, ctx.options().convert_floats, bits) {
240+
(FloatKind::Float16, _, _) => {
236241
// TODO: do f16 when rust lands it
237242
ctx.generated_bindgen_float16();
238243
if ctx.options().enable_cxx_namespaces {
@@ -241,32 +246,27 @@ pub(crate) mod ast_ty {
241246
syn::parse_quote! { __BindgenFloat16 }
242247
}
243248
}
244-
(FloatKind::Float, true) => syn::parse_quote! { f32 },
245-
(FloatKind::Double, true) => syn::parse_quote! { f64 },
246-
(FloatKind::Float, false) => raw_type(ctx, "c_float"),
247-
(FloatKind::Double, false) => raw_type(ctx, "c_double"),
248-
(FloatKind::LongDouble, _) => {
249-
match layout {
250-
Some(layout) => {
251-
match layout.size {
252-
4 => syn::parse_quote! { f32 },
253-
8 => syn::parse_quote! { f64 },
254-
// TODO(emilio): If rust ever gains f128 we should
255-
// use it here and below.
256-
_ => super::integer_type(ctx, layout)
257-
.unwrap_or(syn::parse_quote! { f64 }),
258-
}
249+
(_, true, Some(32)) => syn::parse_quote! { f32 },
250+
(_, true, Some(64)) | (FloatKind::Double, true, None) => syn::parse_quote! { f64 },
251+
(FloatKind::Float, ..) => raw_type(ctx, "c_float"),
252+
(FloatKind::Double, ..) => raw_type(ctx, "c_double"),
253+
(FloatKind::LongDouble, ..) => {
254+
// TODO(emilio): If rust ever gains f80/f128 we should
255+
// use it here and below.
256+
ctx.generated_bindgen_long_double(
257+
layout.expect("unknown layout for long double"),
258+
);
259+
if ctx.options().enable_cxx_namespaces {
260+
syn::parse_quote! {
261+
root::__BindgenLongDouble
259262
}
260-
None => {
261-
debug_assert!(
262-
false,
263-
"How didn't we know the layout for a primitive type?"
264-
);
265-
syn::parse_quote! { f64 }
263+
} else {
264+
syn::parse_quote! {
265+
__BindgenLongDouble
266266
}
267267
}
268268
}
269-
(FloatKind::Float128, _) => {
269+
(FloatKind::Float128, ..) => {
270270
if ctx.options().rust_features.i128_and_u128 {
271271
syn::parse_quote! { u128 }
272272
} 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_bindgen_complex_type() {
585585
utils::prepend_complex_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
}
@@ -2629,6 +2632,10 @@ impl Method {
26292632
return;
26302633
}
26312634

2635+
if utils::sig_unsupported_types(ctx, signature) {
2636+
return;
2637+
}
2638+
26322639
// Do not generate variadic methods, since rust does not allow
26332640
// implementing them, and we don't do a good job at it anyway.
26342641
if signature.is_variadic() {
@@ -3873,11 +3880,11 @@ impl TryToRustTy for Type {
38733880
Ok(int_kind_rust_type(ctx, ik, self.layout(ctx)))
38743881
}
38753882
TypeKind::Float(fk) => {
3876-
Ok(float_kind_rust_type(ctx, fk, self.layout(ctx)))
3883+
Ok(float_kind_rust_type(ctx, fk, self.layout(ctx), 1))
38773884
}
38783885
TypeKind::Complex(fk) => {
38793886
let float_path =
3880-
float_kind_rust_type(ctx, fk, self.layout(ctx));
3887+
float_kind_rust_type(ctx, fk, self.layout(ctx), 2);
38813888

38823889
ctx.generated_bindgen_complex();
38833890
Ok(if ctx.options().enable_cxx_namespaces {
@@ -4232,6 +4239,11 @@ impl CodeGenerator for Function {
42324239
Ok(abi) => abi,
42334240
};
42344241

4242+
if utils::sig_unsupported_types(ctx, signature) {
4243+
warn!("Skipping function which passes or returns by value types not available in Rust.");
4244+
return None;
4245+
}
4246+
42354247
// Handle overloaded functions by giving each overload its own unique
42364248
// suffix.
42374249
let times_seen = result.overload_number(&canonical_name);
@@ -4780,6 +4792,7 @@ pub(crate) mod utils {
47804792
use crate::ir::context::TypeId;
47814793
use crate::ir::function::{Abi, ClangAbi, FunctionSig};
47824794
use crate::ir::item::{Item, ItemCanonicalPath};
4795+
use crate::ir::layout::Layout;
47834796
use crate::ir::ty::TypeKind;
47844797
use crate::{args_are_cpp, file_is_cpp};
47854798
use std::borrow::Cow;
@@ -5188,6 +5201,23 @@ pub(crate) mod utils {
51885201
result.extend(old_items);
51895202
}
51905203

5204+
pub(crate) fn prepend_long_double(
5205+
layout: Layout,
5206+
result: &mut Vec<proc_macro2::TokenStream>,
5207+
) {
5208+
let Layout { align, size, .. } = layout;
5209+
let align = proc_macro2::Literal::u64_unsuffixed(align as u64);
5210+
let size = proc_macro2::Literal::u64_unsuffixed(size as u64);
5211+
result.insert(
5212+
0,
5213+
quote! {
5214+
#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
5215+
#[repr(C, align(#align))]
5216+
pub struct __BindgenLongDouble([u8; #size]);
5217+
},
5218+
);
5219+
}
5220+
51915221
pub(crate) fn build_path(
51925222
item: &Item,
51935223
ctx: &BindgenContext,
@@ -5481,4 +5511,15 @@ pub(crate) mod utils {
54815511

54825512
true
54835513
}
5514+
5515+
pub(crate) fn sig_unsupported_types(
5516+
ctx: &BindgenContext,
5517+
sig: &FunctionSig,
5518+
) -> bool {
5519+
sig.argument_types()
5520+
.iter()
5521+
.map(|(_, ty_id)| ty_id)
5522+
.chain(std::iter::once(&sig.return_type()))
5523+
.any(|ty_id| ctx.lookup_never_by_value(*ty_id))
5524+
}
54845525
}

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)