Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Block function bindings which pass extended floats by value #2403

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.

41 changes: 41 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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@
struct foo {
long double bar;
};

void take_ld(long double ld);
57 changes: 31 additions & 26 deletions bindgen/codegen/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,14 +243,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 (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 @@ -259,29 +264,29 @@ 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, _) => {
if let Some(layout) = 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(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
}
} else {
debug_assert!(
false,
"How didn't we know the layout for a primitive type?"
);
syn::parse_quote! { f64 }
syn::parse_quote! {
__BindgenLongDouble
}
}
}
(FloatKind::Float128, _) => {
(FloatKind::Float128, ..) => {
if true {
syn::parse_quote! { u128 }
} else {
Expand Down
44 changes: 42 additions & 2 deletions bindgen/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,9 @@ impl CodeGenerator for Module {
if ctx.need_opaque_array_type() {
utils::prepend_opaque_array_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 @@ -3043,6 +3046,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 @@ -4287,11 +4294,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 @@ -4644,6 +4651,10 @@ impl CodeGenerator for Function {
Ok(abi) => abi,
};

if utils::sig_unsupported_types(ctx, signature) {
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 @@ -5193,6 +5204,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 @@ -5627,6 +5639,23 @@ pub(crate) mod utils {
result.insert(0, ty);
}

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 @@ -5918,4 +5947,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
Original file line number Diff line number Diff line change
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
Loading
Loading