Skip to content

Commit

Permalink
Block function bindings which pass extended floats by value #2403
Browse files Browse the repository at this point in the history
  • Loading branch information
GKFX committed Mar 23, 2024
1 parent 3b5ce9c commit 5ee4bb7
Show file tree
Hide file tree
Showing 12 changed files with 458 additions and 42 deletions.
5 changes: 4 additions & 1 deletion bindgen-tests/tests/expectations/tests/complex_global.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

71 changes: 71 additions & 0 deletions bindgen-tests/tests/expectations/tests/convert-floats-win64.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion bindgen-tests/tests/expectations/tests/convert-floats.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion bindgen-tests/tests/expectations/tests/long_double.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions bindgen-tests/tests/headers/convert-floats-win64.h
@@ -0,0 +1,9 @@
// bindgen-flags: -- --target=x86_64-pc-windows-msvc

struct foo {
float bar, baz;
double bazz;
long double* bazzz;
float _Complex complexFloat;
double _Complex complexDouble;
};
2 changes: 1 addition & 1 deletion bindgen-tests/tests/headers/convert-floats.h
@@ -1,4 +1,4 @@
// bindgen-flags: --no-convert-floats
// bindgen-flags: --no-convert-floats -- --target=x86_64-unknown-linux-gnu

struct foo {
float bar, baz;
Expand Down
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);
58 changes: 29 additions & 29 deletions bindgen/codegen/helpers.rs
Expand Up @@ -225,14 +225,19 @@ pub(crate) mod ast_ty {
pub(crate) fn float_kind_rust_type(
ctx: &BindgenContext,
fk: FloatKind,
layout: Option<Layout>,
mut layout: Option<Layout>,
n_parts: usize,
) -> syn::Type {
// TODO: we probably should take the type layout into account more
// often?
//
// Also, maybe this one shouldn't be the default?
match (fk, ctx.options().convert_floats) {
(FloatKind::Float16, _) => {
// Convert the layout of complex numbers to the layout of its parts.
let bits = match layout {
Some(Layout { ref mut size, .. }) => {
*size /= n_parts;
Some(*size * 8)
}
None => None,
};
match dbg!(fk, ctx.options().convert_floats, bits) {
(FloatKind::Float16, _, _) => {
// TODO: do f16 when rust lands it
ctx.generated_bindgen_float16();
if ctx.options().enable_cxx_namespaces {
Expand All @@ -241,32 +246,27 @@ pub(crate) mod ast_ty {
syn::parse_quote! { __BindgenFloat16 }
}
}
(FloatKind::Float, true) => syn::parse_quote! { f32 },
(FloatKind::Double, true) => syn::parse_quote! { f64 },
(FloatKind::Float, false) => raw_type(ctx, "c_float"),
(FloatKind::Double, false) => raw_type(ctx, "c_double"),
(FloatKind::LongDouble, _) => {
match layout {
Some(layout) => {
match layout.size {
4 => syn::parse_quote! { f32 },
8 => syn::parse_quote! { f64 },
// TODO(emilio): If rust ever gains f128 we should
// use it here and below.
_ => super::integer_type(ctx, layout)
.unwrap_or(syn::parse_quote! { f64 }),
}
(_, true, Some(32)) => syn::parse_quote! { f32 },
(_, true, Some(64)) | (FloatKind::Double, true, None) => syn::parse_quote! { f64 },
(FloatKind::Float, ..) => raw_type(ctx, "c_float"),
(FloatKind::Double, ..) => raw_type(ctx, "c_double"),
(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 {
syn::parse_quote! {
root::__BindgenLongDouble
}
None => {
debug_assert!(
false,
"How didn't we know the layout for a primitive type?"
);
syn::parse_quote! { f64 }
} else {
syn::parse_quote! {
__BindgenLongDouble
}
}
}
(FloatKind::Float128, _) => {
(FloatKind::Float128, ..) => {
if ctx.options().rust_features.i128_and_u128 {
syn::parse_quote! { u128 }
} else {
Expand Down
45 changes: 43 additions & 2 deletions bindgen/codegen/mod.rs
Expand Up @@ -584,6 +584,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 @@ -2629,6 +2632,10 @@ impl Method {
return;
}

if utils::sig_unsupported_types(ctx, signature) {
return;
}

// Do not generate variadic methods, since rust does not allow
// implementing them, and we don't do a good job at it anyway.
if signature.is_variadic() {
Expand Down Expand Up @@ -3873,11 +3880,11 @@ impl TryToRustTy for Type {
Ok(int_kind_rust_type(ctx, ik, self.layout(ctx)))
}
TypeKind::Float(fk) => {
Ok(float_kind_rust_type(ctx, fk, self.layout(ctx)))
Ok(float_kind_rust_type(ctx, fk, self.layout(ctx), 1))
}
TypeKind::Complex(fk) => {
let float_path =
float_kind_rust_type(ctx, fk, self.layout(ctx));
float_kind_rust_type(ctx, fk, self.layout(ctx), 2);

ctx.generated_bindgen_complex();
Ok(if ctx.options().enable_cxx_namespaces {
Expand Down Expand Up @@ -4232,6 +4239,11 @@ impl CodeGenerator for Function {
Ok(abi) => abi,
};

if utils::sig_unsupported_types(ctx, signature) {
warn!("Skipping function which passes or returns by value types not available in Rust.");
return None;
}

// Handle overloaded functions by giving each overload its own unique
// suffix.
let times_seen = result.overload_number(&canonical_name);
Expand Down Expand Up @@ -4780,6 +4792,7 @@ pub(crate) mod utils {
use crate::ir::context::TypeId;
use crate::ir::function::{Abi, ClangAbi, FunctionSig};
use crate::ir::item::{Item, ItemCanonicalPath};
use crate::ir::layout::Layout;
use crate::ir::ty::TypeKind;
use crate::{args_are_cpp, file_is_cpp};
use std::borrow::Cow;
Expand Down Expand Up @@ -5188,6 +5201,23 @@ pub(crate) mod utils {
result.extend(old_items);
}

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

pub(crate) fn build_path(
item: &Item,
ctx: &BindgenContext,
Expand Down Expand Up @@ -5481,4 +5511,15 @@ pub(crate) mod utils {

true
}

pub(crate) fn sig_unsupported_types(
ctx: &BindgenContext,
sig: &FunctionSig,
) -> bool {
sig.argument_types()
.iter()
.map(|(_, ty_id)| ty_id)
.chain(std::iter::once(&sig.return_type()))
.any(|ty_id| ctx.lookup_never_by_value(*ty_id))
}
}
2 changes: 2 additions & 0 deletions bindgen/ir/analysis/mod.rs
Expand Up @@ -53,6 +53,8 @@ mod has_type_param_in_array;
pub(crate) use self::has_type_param_in_array::HasTypeParameterInArray;
mod has_float;
pub(crate) use self::has_float::HasFloat;
mod never_by_value;
pub use self::never_by_value::NeverByValue;
mod sizedness;
pub(crate) use self::sizedness::{
Sizedness, SizednessAnalysis, SizednessResult,
Expand Down

0 comments on commit 5ee4bb7

Please sign in to comment.