From b045090f77965516d17cff14fb0dd188ed9d29d9 Mon Sep 17 00:00:00 2001 From: sagudev <16504129+sagudev@users.noreply.github.com> Date: Fri, 20 Oct 2023 18:50:54 +0200 Subject: [PATCH] Support float16 --- .../tests/expectations/tests/float16.rs | 66 +++++++++++++++++++ bindgen-tests/tests/headers/float16.h | 36 ++++++++++ bindgen/codegen/helpers.rs | 9 +++ bindgen/codegen/mod.rs | 17 +++++ bindgen/codegen/serialize.rs | 2 + bindgen/ir/context.rs | 16 +++++ bindgen/ir/ty.rs | 2 + 7 files changed, 148 insertions(+) create mode 100644 bindgen-tests/tests/expectations/tests/float16.rs create mode 100644 bindgen-tests/tests/headers/float16.h diff --git a/bindgen-tests/tests/expectations/tests/float16.rs b/bindgen-tests/tests/expectations/tests/float16.rs new file mode 100644 index 0000000000..8683c297aa --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/float16.rs @@ -0,0 +1,66 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)] +#[repr(C)] +pub struct __BindgenFloat16(pub u16); +extern "C" { + pub static mut global: __BindgenFloat16; +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct Test__Float16 { + pub f: __BindgenFloat16, +} +#[test] +fn bindgen_test_layout_Test__Float16() { + const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 2usize, + concat!("Size of: ", stringify!(Test__Float16)), + ); + assert_eq!( + ::std::mem::align_of::(), + 2usize, + concat!("Alignment of ", stringify!(Test__Float16)), + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).f) as usize - ptr as usize }, + 0usize, + concat!("Offset of field: ", stringify!(Test__Float16), "::", stringify!(f)), + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Test__Float16Ref { + pub f: *mut __BindgenFloat16, +} +#[test] +fn bindgen_test_layout_Test__Float16Ref() { + const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 8usize, + concat!("Size of: ", stringify!(Test__Float16Ref)), + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(Test__Float16Ref)), + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).f) as usize - ptr as usize }, + 0usize, + concat!("Offset of field: ", stringify!(Test__Float16Ref), "::", stringify!(f)), + ); +} +impl Default for Test__Float16Ref { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/headers/float16.h b/bindgen-tests/tests/headers/float16.h new file mode 100644 index 0000000000..3b1058591d --- /dev/null +++ b/bindgen-tests/tests/headers/float16.h @@ -0,0 +1,36 @@ +// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq + +static __fp16 global; + +struct Test__Float16 +{ + __fp16 f; +}; + +struct Test__Float16Ref +{ + __fp16 *f; +}; + +/* +// This options are currently supported only on specific targets (eg. x86 with sse2) +_Float16 returns_f16(); + +void gets_f16(_Float16 arg); + +struct Test__Float16_Complex +{ + _Float16 _Complex mMember; +}; + +struct Test__Float16_ComplexPtr +{ + _Float16 _Complex *mMember; +}; + +_Float16 _Complex globalValueHalf; + +_Float16 _Complex returns_f16_complex(); + +void gets_f16_complex(_Float16 _Complex arg); +*/ \ No newline at end of file diff --git a/bindgen/codegen/helpers.rs b/bindgen/codegen/helpers.rs index 7ef44fe099..48bfe56dde 100644 --- a/bindgen/codegen/helpers.rs +++ b/bindgen/codegen/helpers.rs @@ -232,6 +232,15 @@ pub(crate) mod ast_ty { // // Also, maybe this one shouldn't be the default? match (fk, ctx.options().convert_floats) { + (FloatKind::Float16, _) => { + // TODO: do f16 when rust lands it + ctx.generated_bindgen_float16(); + if ctx.options().enable_cxx_namespaces { + syn::parse_quote! { root::__BindgenFloat16 } + } else { + 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"), diff --git a/bindgen/codegen/mod.rs b/bindgen/codegen/mod.rs index 8e13606345..c1dd45bbcd 100644 --- a/bindgen/codegen/mod.rs +++ b/bindgen/codegen/mod.rs @@ -578,6 +578,9 @@ impl CodeGenerator for Module { if result.saw_incomplete_array { utils::prepend_incomplete_array_types(ctx, &mut *result); } + if ctx.need_bindgen_float16_type() { + utils::prepend_float16_type(&mut *result); + } if ctx.need_bindgen_complex_type() { utils::prepend_complex_type(&mut *result); } @@ -5136,6 +5139,20 @@ pub(crate) mod utils { result.extend(old_items); } + pub(crate) fn prepend_float16_type( + result: &mut Vec, + ) { + let float16_type = quote! { + #[derive(PartialEq, Copy, Clone, Hash, Debug, Default)] + #[repr(C)] + pub struct __BindgenFloat16(pub u16); + }; + + let items = vec![float16_type]; + let old_items = mem::replace(result, items); + result.extend(old_items); + } + pub(crate) fn prepend_complex_type( result: &mut Vec, ) { diff --git a/bindgen/codegen/serialize.rs b/bindgen/codegen/serialize.rs index 02c4680263..9765a8bdf2 100644 --- a/bindgen/codegen/serialize.rs +++ b/bindgen/codegen/serialize.rs @@ -270,6 +270,7 @@ impl<'a> CSerialize<'a> for Type { write!(writer, "const ")?; } match float_kind { + FloatKind::Float16 => write!(writer, "_Float16")?, FloatKind::Float => write!(writer, "float")?, FloatKind::Double => write!(writer, "double")?, FloatKind::LongDouble => write!(writer, "long double")?, @@ -281,6 +282,7 @@ impl<'a> CSerialize<'a> for Type { write!(writer, "const ")?; } match float_kind { + FloatKind::Float16 => write!(writer, "_Float16 complex")?, FloatKind::Float => write!(writer, "float complex")?, FloatKind::Double => write!(writer, "double complex")?, FloatKind::LongDouble => { diff --git a/bindgen/ir/context.rs b/bindgen/ir/context.rs index c5e2832cc9..11048b70c8 100644 --- a/bindgen/ir/context.rs +++ b/bindgen/ir/context.rs @@ -386,6 +386,9 @@ pub(crate) struct BindgenContext { /// Whether a bindgen complex was generated generated_bindgen_complex: Cell, + /// Whether a bindgen float16 was generated + generated_bindgen_float16: Cell, + /// The set of `ItemId`s that are allowlisted. This the very first thing /// computed after parsing our IR, and before running any of our analyses. allowlisted: Option, @@ -585,6 +588,7 @@ If you encounter an error missing from this list, please file an issue or a PR!" target_info, options, generated_bindgen_complex: Cell::new(false), + generated_bindgen_float16: Cell::new(false), allowlisted: None, blocklisted_types_implement_traits: Default::default(), codegen_items: None, @@ -2005,6 +2009,7 @@ If you encounter an error missing from this list, please file an issue or a PR!" CXType_ULongLong => TypeKind::Int(IntKind::ULongLong), CXType_Int128 => TypeKind::Int(IntKind::I128), CXType_UInt128 => TypeKind::Int(IntKind::U128), + CXType_Float16 | CXType_Half => TypeKind::Float(FloatKind::Float16), CXType_Float => TypeKind::Float(FloatKind::Float), CXType_Double => TypeKind::Float(FloatKind::Double), CXType_LongDouble => TypeKind::Float(FloatKind::LongDouble), @@ -2013,6 +2018,7 @@ If you encounter an error missing from this list, please file an issue or a PR!" let float_type = ty.elem_type().expect("Not able to resolve complex type?"); let float_kind = match float_type.kind() { + CXType_Float16 | CXType_Half => FloatKind::Float16, CXType_Float => FloatKind::Float, CXType_Double => FloatKind::Double, CXType_LongDouble => FloatKind::LongDouble, @@ -2528,6 +2534,16 @@ If you encounter an error missing from this list, please file an issue or a PR!" self.generated_bindgen_complex.get() } + /// Call if a bindgen float16 is generated + pub(crate) fn generated_bindgen_float16(&self) { + self.generated_bindgen_float16.set(true) + } + + /// Whether we need to generate the bindgen float16 type + pub(crate) fn need_bindgen_float16_type(&self) -> bool { + self.generated_bindgen_float16.get() + } + /// Compute which `enum`s have an associated `typedef` definition. fn compute_enum_typedef_combos(&mut self) { let _t = self.timer("compute_enum_typedef_combos"); diff --git a/bindgen/ir/ty.rs b/bindgen/ir/ty.rs index 1aee065970..b7a429323e 100644 --- a/bindgen/ir/ty.rs +++ b/bindgen/ir/ty.rs @@ -558,6 +558,8 @@ impl TemplateParameters for TypeKind { /// The kind of float this type represents. #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub(crate) enum FloatKind { + /// A half (`_Float16` or `__fp16`) + Float16, /// A `float`. Float, /// A `double`.