From dbad8b814e99d3c4790a202e03aca8a0402e9f04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 9 Jun 2022 19:47:23 +0200 Subject: [PATCH 1/2] bindings: Peel through typedefs for struct constant generation. This allows the workaround in #767 to work. --- src/bindgen/bindings.rs | 37 ++++++++++++++++++++++++++++++++++--- src/bindgen/library.rs | 2 ++ 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/bindgen/bindings.rs b/src/bindgen/bindings.rs index 2b0f86a9a..845a4c69c 100644 --- a/src/bindgen/bindings.rs +++ b/src/bindgen/bindings.rs @@ -2,6 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use std::borrow::Cow; use std::cell::RefCell; use std::collections::HashMap; use std::fs; @@ -12,7 +13,7 @@ use std::rc::Rc; use crate::bindgen::config::{Config, Language}; use crate::bindgen::ir::{ - Constant, Function, ItemContainer, ItemMap, Path as BindgenPath, Static, Struct, + Constant, Function, ItemContainer, ItemMap, Path as BindgenPath, Static, Struct, Typedef, }; use crate::bindgen::writer::{Source, SourceWriter}; @@ -22,6 +23,7 @@ pub struct Bindings { /// The map from path to struct, used to lookup whether a given type is a /// transparent struct. This is needed to generate code for constants. struct_map: ItemMap, + typedef_map: ItemMap, struct_fileds_memo: RefCell>>>, globals: Vec, constants: Vec, @@ -39,9 +41,11 @@ enum NamespaceOperation { } impl Bindings { + #[allow(clippy::too_many_arguments)] pub(crate) fn new( config: Config, struct_map: ItemMap, + typedef_map: ItemMap, constants: Vec, globals: Vec, items: Vec, @@ -51,6 +55,7 @@ impl Bindings { Bindings { config, struct_map, + typedef_map, struct_fileds_memo: Default::default(), globals, constants, @@ -67,9 +72,30 @@ impl Bindings { any } + /// Peels through typedefs to allow resolving structs. + fn resolved_struct_path<'a>(&self, path: &'a BindgenPath) -> Cow<'a, BindgenPath> { + use crate::bindgen::ir::Type; + + let mut resolved_path = Cow::Borrowed(path); + loop { + let mut found = None; + self.typedef_map.for_items(&resolved_path, |item| { + if let Type::Path(ref p) = item.aliased { + found = Some(p.path().clone()); + } + }); + resolved_path = match found { + Some(p) => Cow::Owned(p), + None => break, + } + } + resolved_path + } + pub fn struct_exists(&self, path: &BindgenPath) -> bool { let mut any = false; - self.struct_map.for_items(path, |_| any = true); + self.struct_map + .for_items(&self.resolved_struct_path(path), |_| any = true); any } @@ -79,8 +105,10 @@ impl Bindings { return memo.clone(); } + let resolved_path = self.resolved_struct_path(path); + let mut fields = Vec::::new(); - self.struct_map.for_items(path, |st| { + self.struct_map.for_items(&resolved_path, |st| { let mut pos: usize = 0; for field in &st.fields { if let Some(found_pos) = fields.iter().position(|v| *v == field.name) { @@ -94,6 +122,9 @@ impl Bindings { let fields = Rc::new(fields); memos.insert(path.clone(), fields.clone()); + if let Cow::Owned(p) = resolved_path { + memos.insert(p, fields.clone()); + } fields } diff --git a/src/bindgen/library.rs b/src/bindgen/library.rs index e7a1891e2..23ec38dc6 100644 --- a/src/bindgen/library.rs +++ b/src/bindgen/library.rs @@ -67,6 +67,7 @@ impl Library { Default::default(), Default::default(), Default::default(), + Default::default(), true, )); } @@ -147,6 +148,7 @@ impl Library { Ok(Bindings::new( self.config, self.structs, + self.typedefs, constants, globals, items, From 39eb7782af1d3d95f7ea177bac830ee38395591e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 9 Jun 2022 19:48:16 +0200 Subject: [PATCH 2/2] tests: Add a test for struct constants going through typedefs. --- .../const_generics_constant.both.c | 19 +++++++++++++ .../const_generics_constant.both.compat.c | 27 +++++++++++++++++++ tests/expectations/const_generics_constant.c | 19 +++++++++++++ .../const_generics_constant.compat.c | 27 +++++++++++++++++++ .../expectations/const_generics_constant.cpp | 25 +++++++++++++++++ .../expectations/const_generics_constant.pyx | 20 ++++++++++++++ .../const_generics_constant.tag.c | 19 +++++++++++++ .../const_generics_constant.tag.compat.c | 27 +++++++++++++++++++ .../const_generics_constant.tag.pyx | 20 ++++++++++++++ tests/rust/const_generics_constant.rs | 18 +++++++++++++ 10 files changed, 221 insertions(+) create mode 100644 tests/expectations/const_generics_constant.both.c create mode 100644 tests/expectations/const_generics_constant.both.compat.c create mode 100644 tests/expectations/const_generics_constant.c create mode 100644 tests/expectations/const_generics_constant.compat.c create mode 100644 tests/expectations/const_generics_constant.cpp create mode 100644 tests/expectations/const_generics_constant.pyx create mode 100644 tests/expectations/const_generics_constant.tag.c create mode 100644 tests/expectations/const_generics_constant.tag.compat.c create mode 100644 tests/expectations/const_generics_constant.tag.pyx create mode 100644 tests/rust/const_generics_constant.rs diff --git a/tests/expectations/const_generics_constant.both.c b/tests/expectations/const_generics_constant.both.c new file mode 100644 index 000000000..42a992455 --- /dev/null +++ b/tests/expectations/const_generics_constant.both.c @@ -0,0 +1,19 @@ +#include +#include +#include +#include + +#define FONT_WEIGHT_FRACTION_BITS 6 + +typedef struct FixedPoint_FONT_WEIGHT_FRACTION_BITS { + uint16_t value; +} FixedPoint_FONT_WEIGHT_FRACTION_BITS; + +typedef struct FixedPoint_FONT_WEIGHT_FRACTION_BITS FontWeightFixedPoint; + +typedef struct FontWeight { + FontWeightFixedPoint _0; +} FontWeight; +#define FontWeight_NORMAL (FontWeight){ ._0 = (FontWeightFixedPoint){ .value = (400 << FONT_WEIGHT_FRACTION_BITS) } } + +void root(struct FontWeight w); diff --git a/tests/expectations/const_generics_constant.both.compat.c b/tests/expectations/const_generics_constant.both.compat.c new file mode 100644 index 000000000..ce880aeb0 --- /dev/null +++ b/tests/expectations/const_generics_constant.both.compat.c @@ -0,0 +1,27 @@ +#include +#include +#include +#include + +#define FONT_WEIGHT_FRACTION_BITS 6 + +typedef struct FixedPoint_FONT_WEIGHT_FRACTION_BITS { + uint16_t value; +} FixedPoint_FONT_WEIGHT_FRACTION_BITS; + +typedef struct FixedPoint_FONT_WEIGHT_FRACTION_BITS FontWeightFixedPoint; + +typedef struct FontWeight { + FontWeightFixedPoint _0; +} FontWeight; +#define FontWeight_NORMAL (FontWeight){ ._0 = (FontWeightFixedPoint){ .value = (400 << FONT_WEIGHT_FRACTION_BITS) } } + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(struct FontWeight w); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/const_generics_constant.c b/tests/expectations/const_generics_constant.c new file mode 100644 index 000000000..dd2494087 --- /dev/null +++ b/tests/expectations/const_generics_constant.c @@ -0,0 +1,19 @@ +#include +#include +#include +#include + +#define FONT_WEIGHT_FRACTION_BITS 6 + +typedef struct { + uint16_t value; +} FixedPoint_FONT_WEIGHT_FRACTION_BITS; + +typedef FixedPoint_FONT_WEIGHT_FRACTION_BITS FontWeightFixedPoint; + +typedef struct { + FontWeightFixedPoint _0; +} FontWeight; +#define FontWeight_NORMAL (FontWeight){ ._0 = (FontWeightFixedPoint){ .value = (400 << FONT_WEIGHT_FRACTION_BITS) } } + +void root(FontWeight w); diff --git a/tests/expectations/const_generics_constant.compat.c b/tests/expectations/const_generics_constant.compat.c new file mode 100644 index 000000000..14ebfa2d4 --- /dev/null +++ b/tests/expectations/const_generics_constant.compat.c @@ -0,0 +1,27 @@ +#include +#include +#include +#include + +#define FONT_WEIGHT_FRACTION_BITS 6 + +typedef struct { + uint16_t value; +} FixedPoint_FONT_WEIGHT_FRACTION_BITS; + +typedef FixedPoint_FONT_WEIGHT_FRACTION_BITS FontWeightFixedPoint; + +typedef struct { + FontWeightFixedPoint _0; +} FontWeight; +#define FontWeight_NORMAL (FontWeight){ ._0 = (FontWeightFixedPoint){ .value = (400 << FONT_WEIGHT_FRACTION_BITS) } } + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(FontWeight w); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/const_generics_constant.cpp b/tests/expectations/const_generics_constant.cpp new file mode 100644 index 000000000..715a071a0 --- /dev/null +++ b/tests/expectations/const_generics_constant.cpp @@ -0,0 +1,25 @@ +#include +#include +#include +#include +#include + +constexpr static const uint16_t FONT_WEIGHT_FRACTION_BITS = 6; + +template +struct FixedPoint { + uint16_t value; +}; + +using FontWeightFixedPoint = FixedPoint; + +struct FontWeight { + FontWeightFixedPoint _0; +}; +constexpr static const FontWeight FontWeight_NORMAL = FontWeight{ /* ._0 = */ FontWeightFixedPoint{ /* .value = */ (400 << FONT_WEIGHT_FRACTION_BITS) } }; + +extern "C" { + +void root(FontWeight w); + +} // extern "C" diff --git a/tests/expectations/const_generics_constant.pyx b/tests/expectations/const_generics_constant.pyx new file mode 100644 index 000000000..4e2282932 --- /dev/null +++ b/tests/expectations/const_generics_constant.pyx @@ -0,0 +1,20 @@ +from libc.stdint cimport int8_t, int16_t, int32_t, int64_t, intptr_t +from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t, uintptr_t +cdef extern from *: + ctypedef bint bool + ctypedef struct va_list + +cdef extern from *: + + const uint16_t FONT_WEIGHT_FRACTION_BITS # = 6 + + ctypedef struct FixedPoint_FONT_WEIGHT_FRACTION_BITS: + uint16_t value; + + ctypedef FixedPoint_FONT_WEIGHT_FRACTION_BITS FontWeightFixedPoint; + + ctypedef struct FontWeight: + FontWeightFixedPoint _0; + const FontWeight FontWeight_NORMAL # = { { (400 << FONT_WEIGHT_FRACTION_BITS) } } + + void root(FontWeight w); diff --git a/tests/expectations/const_generics_constant.tag.c b/tests/expectations/const_generics_constant.tag.c new file mode 100644 index 000000000..5ffb2a1c5 --- /dev/null +++ b/tests/expectations/const_generics_constant.tag.c @@ -0,0 +1,19 @@ +#include +#include +#include +#include + +#define FONT_WEIGHT_FRACTION_BITS 6 + +struct FixedPoint_FONT_WEIGHT_FRACTION_BITS { + uint16_t value; +}; + +typedef struct FixedPoint_FONT_WEIGHT_FRACTION_BITS FontWeightFixedPoint; + +struct FontWeight { + FontWeightFixedPoint _0; +}; +#define FontWeight_NORMAL (FontWeight){ ._0 = (FontWeightFixedPoint){ .value = (400 << FONT_WEIGHT_FRACTION_BITS) } } + +void root(struct FontWeight w); diff --git a/tests/expectations/const_generics_constant.tag.compat.c b/tests/expectations/const_generics_constant.tag.compat.c new file mode 100644 index 000000000..fc115cff1 --- /dev/null +++ b/tests/expectations/const_generics_constant.tag.compat.c @@ -0,0 +1,27 @@ +#include +#include +#include +#include + +#define FONT_WEIGHT_FRACTION_BITS 6 + +struct FixedPoint_FONT_WEIGHT_FRACTION_BITS { + uint16_t value; +}; + +typedef struct FixedPoint_FONT_WEIGHT_FRACTION_BITS FontWeightFixedPoint; + +struct FontWeight { + FontWeightFixedPoint _0; +}; +#define FontWeight_NORMAL (FontWeight){ ._0 = (FontWeightFixedPoint){ .value = (400 << FONT_WEIGHT_FRACTION_BITS) } } + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(struct FontWeight w); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/const_generics_constant.tag.pyx b/tests/expectations/const_generics_constant.tag.pyx new file mode 100644 index 000000000..f42ed410e --- /dev/null +++ b/tests/expectations/const_generics_constant.tag.pyx @@ -0,0 +1,20 @@ +from libc.stdint cimport int8_t, int16_t, int32_t, int64_t, intptr_t +from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t, uintptr_t +cdef extern from *: + ctypedef bint bool + ctypedef struct va_list + +cdef extern from *: + + const uint16_t FONT_WEIGHT_FRACTION_BITS # = 6 + + cdef struct FixedPoint_FONT_WEIGHT_FRACTION_BITS: + uint16_t value; + + ctypedef FixedPoint_FONT_WEIGHT_FRACTION_BITS FontWeightFixedPoint; + + cdef struct FontWeight: + FontWeightFixedPoint _0; + const FontWeight FontWeight_NORMAL # = { { (400 << FONT_WEIGHT_FRACTION_BITS) } } + + void root(FontWeight w); diff --git a/tests/rust/const_generics_constant.rs b/tests/rust/const_generics_constant.rs new file mode 100644 index 000000000..83ed86085 --- /dev/null +++ b/tests/rust/const_generics_constant.rs @@ -0,0 +1,18 @@ +#[repr(C)] +pub struct FixedPoint { + value: u16, +} + +pub const FONT_WEIGHT_FRACTION_BITS: u16 = 6; + +pub type FontWeightFixedPoint = FixedPoint; + +#[repr(C)] +pub struct FontWeight(FontWeightFixedPoint); + +impl FontWeight { + pub const NORMAL: FontWeight = FontWeight(FontWeightFixedPoint { value: 400 << FONT_WEIGHT_FRACTION_BITS }); +} + +#[no_mangle] +pub extern "C" fn root(w: FontWeight) {}