Skip to content

Commit 1dcc082

Browse files
committed
Block function bindings which pass extended floats by value rust-lang#2403
1 parent bf5e79b commit 1dcc082

12 files changed

+464
-41
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

+35-28
Original file line numberDiff line numberDiff line change
@@ -225,39 +225,46 @@ 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::Float, true) => syn::parse_quote! { f32 },
236-
(FloatKind::Double, true) => syn::parse_quote! { f64 },
237-
(FloatKind::Float, false) => raw_type(ctx, "c_float"),
238-
(FloatKind::Double, false) => raw_type(ctx, "c_double"),
239-
(FloatKind::LongDouble, _) => {
240-
match layout {
241-
Some(layout) => {
242-
match layout.size {
243-
4 => syn::parse_quote! { f32 },
244-
8 => syn::parse_quote! { f64 },
245-
// TODO(emilio): If rust ever gains f128 we should
246-
// use it here and below.
247-
_ => super::integer_type(ctx, layout)
248-
.unwrap_or(syn::parse_quote! { f64 }),
249-
}
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 (fk, ctx.options().convert_floats, bits) {
240+
// With convert_floats=True, turn 32-bit and 64-bit floats into
241+
// f32 and f64, regardless of whether they were written as float,
242+
// double, long double, etc.
243+
// TODO: What about narrower floats?
244+
(_, true, Some(32)) => syn::parse_quote! { f32 },
245+
(_, true, Some(64)) | (FloatKind::Double, true, None) => {
246+
syn::parse_quote! { f64 }
247+
}
248+
249+
(FloatKind::Float, ..) => raw_type(ctx, "c_float"),
250+
(FloatKind::Double, ..) => raw_type(ctx, "c_double"),
251+
(FloatKind::LongDouble, ..) => {
252+
// TODO(emilio): If rust ever gains f80/f128 we should
253+
// use it here and below.
254+
ctx.generated_bindgen_long_double(
255+
layout.expect("unknown layout for long double"),
256+
);
257+
if ctx.options().enable_cxx_namespaces {
258+
syn::parse_quote! {
259+
root::__BindgenLongDouble
250260
}
251-
None => {
252-
debug_assert!(
253-
false,
254-
"How didn't we know the layout for a primitive type?"
255-
);
256-
syn::parse_quote! { f64 }
261+
} else {
262+
syn::parse_quote! {
263+
__BindgenLongDouble
257264
}
258265
}
259266
}
260-
(FloatKind::Float128, _) => {
267+
(FloatKind::Float128, ..) => {
261268
if ctx.options().rust_features.i128_and_u128 {
262269
syn::parse_quote! { u128 }
263270
} else {

bindgen/codegen/mod.rs

+43-2
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,9 @@ impl CodeGenerator for Module {
580580
if ctx.need_bindgen_complex_type() {
581581
utils::prepend_complex_type(&mut *result);
582582
}
583+
if let Some(layout) = ctx.need_bindgen_long_double() {
584+
utils::prepend_long_double(layout, &mut *result);
585+
}
583586
if result.saw_objc {
584587
utils::prepend_objc_header(ctx, &mut *result);
585588
}
@@ -2604,6 +2607,10 @@ impl Method {
26042607
return;
26052608
}
26062609

2610+
if utils::sig_unsupported_types(ctx, signature) {
2611+
return;
2612+
}
2613+
26072614
// Do not generate variadic methods, since rust does not allow
26082615
// implementing them, and we don't do a good job at it anyway.
26092616
if signature.is_variadic() {
@@ -3848,11 +3855,11 @@ impl TryToRustTy for Type {
38483855
Ok(int_kind_rust_type(ctx, ik, self.layout(ctx)))
38493856
}
38503857
TypeKind::Float(fk) => {
3851-
Ok(float_kind_rust_type(ctx, fk, self.layout(ctx)))
3858+
Ok(float_kind_rust_type(ctx, fk, self.layout(ctx), 1))
38523859
}
38533860
TypeKind::Complex(fk) => {
38543861
let float_path =
3855-
float_kind_rust_type(ctx, fk, self.layout(ctx));
3862+
float_kind_rust_type(ctx, fk, self.layout(ctx), 2);
38563863

38573864
ctx.generated_bindgen_complex();
38583865
Ok(if ctx.options().enable_cxx_namespaces {
@@ -4197,6 +4204,11 @@ impl CodeGenerator for Function {
41974204
Ok(abi) => abi,
41984205
};
41994206

4207+
if utils::sig_unsupported_types(ctx, signature) {
4208+
warn!("Skipping function which passes or returns by value types not available in Rust.");
4209+
return None;
4210+
}
4211+
42004212
// Handle overloaded functions by giving each overload its own unique
42014213
// suffix.
42024214
let times_seen = result.overload_number(&canonical_name);
@@ -4745,6 +4757,7 @@ pub(crate) mod utils {
47454757
use crate::ir::context::TypeId;
47464758
use crate::ir::function::{Abi, ClangAbi, FunctionSig};
47474759
use crate::ir::item::{Item, ItemCanonicalPath};
4760+
use crate::ir::layout::Layout;
47484761
use crate::ir::ty::TypeKind;
47494762
use crate::{args_are_cpp, file_is_cpp};
47504763
use std::borrow::Cow;
@@ -5139,6 +5152,23 @@ pub(crate) mod utils {
51395152
result.extend(old_items);
51405153
}
51415154

5155+
pub(crate) fn prepend_long_double(
5156+
layout: Layout,
5157+
result: &mut Vec<proc_macro2::TokenStream>,
5158+
) {
5159+
let Layout { align, size, .. } = layout;
5160+
let align = proc_macro2::Literal::u64_unsuffixed(align as u64);
5161+
let size = proc_macro2::Literal::u64_unsuffixed(size as u64);
5162+
result.insert(
5163+
0,
5164+
quote! {
5165+
#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
5166+
#[repr(C, align(#align))]
5167+
pub struct __BindgenLongDouble([u8; #size]);
5168+
},
5169+
);
5170+
}
5171+
51425172
pub(crate) fn build_path(
51435173
item: &Item,
51445174
ctx: &BindgenContext,
@@ -5431,4 +5461,15 @@ pub(crate) mod utils {
54315461

54325462
true
54335463
}
5464+
5465+
pub(crate) fn sig_unsupported_types(
5466+
ctx: &BindgenContext,
5467+
sig: &FunctionSig,
5468+
) -> bool {
5469+
sig.argument_types()
5470+
.iter()
5471+
.map(|(_, ty_id)| ty_id)
5472+
.chain(std::iter::once(&sig.return_type()))
5473+
.any(|ty_id| ctx.lookup_never_by_value(*ty_id))
5474+
}
54345475
}

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)