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.
Jump to
Jump to file
Failed to load files.
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.

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);
60 changes: 31 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,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, _) => {
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 @@
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 Expand Up @@ -216,7 +218,7 @@
#[cfg(test)]
mod tests {
use super::*;
use crate::{HashMap, HashSet};

Check warning on line 221 in bindgen/ir/analysis/mod.rs

View workflow job for this annotation

GitHub Actions / rustfmt-clippy

the item `HashMap` is imported redundantly

// Here we find the set of nodes that are reachable from any given
// node. This is a lattice mapping nodes to subsets of all nodes. Our join
Expand Down