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

bindings: Peel through typedefs for struct constant generation #768

Merged
merged 2 commits into from Jun 9, 2022
Merged
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
37 changes: 34 additions & 3 deletions src/bindgen/bindings.rs
Expand Up @@ -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;
Expand All @@ -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};

Expand All @@ -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<Struct>,
typedef_map: ItemMap<Typedef>,
struct_fileds_memo: RefCell<HashMap<BindgenPath, Rc<Vec<String>>>>,
globals: Vec<Static>,
constants: Vec<Constant>,
Expand All @@ -39,9 +41,11 @@ enum NamespaceOperation {
}

impl Bindings {
#[allow(clippy::too_many_arguments)]
pub(crate) fn new(
config: Config,
struct_map: ItemMap<Struct>,
typedef_map: ItemMap<Typedef>,
constants: Vec<Constant>,
globals: Vec<Static>,
items: Vec<ItemContainer>,
Expand All @@ -51,6 +55,7 @@ impl Bindings {
Bindings {
config,
struct_map,
typedef_map,
struct_fileds_memo: Default::default(),
globals,
constants,
Expand All @@ -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
}

Expand All @@ -79,8 +105,10 @@ impl Bindings {
return memo.clone();
}

let resolved_path = self.resolved_struct_path(path);

let mut fields = Vec::<String>::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) {
Expand All @@ -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
}

Expand Down
2 changes: 2 additions & 0 deletions src/bindgen/library.rs
Expand Up @@ -67,6 +67,7 @@ impl Library {
Default::default(),
Default::default(),
Default::default(),
Default::default(),
true,
));
}
Expand Down Expand Up @@ -147,6 +148,7 @@ impl Library {
Ok(Bindings::new(
self.config,
self.structs,
self.typedefs,
constants,
globals,
items,
Expand Down
19 changes: 19 additions & 0 deletions tests/expectations/const_generics_constant.both.c
@@ -0,0 +1,19 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

#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);
27 changes: 27 additions & 0 deletions tests/expectations/const_generics_constant.both.compat.c
@@ -0,0 +1,27 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

#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
19 changes: 19 additions & 0 deletions tests/expectations/const_generics_constant.c
@@ -0,0 +1,19 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

#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);
27 changes: 27 additions & 0 deletions tests/expectations/const_generics_constant.compat.c
@@ -0,0 +1,27 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

#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
25 changes: 25 additions & 0 deletions tests/expectations/const_generics_constant.cpp
@@ -0,0 +1,25 @@
#include <cstdarg>
#include <cstdint>
#include <cstdlib>
#include <ostream>
#include <new>

constexpr static const uint16_t FONT_WEIGHT_FRACTION_BITS = 6;

template<uint16_t FRACTION_BITS>
struct FixedPoint {
uint16_t value;
};

using FontWeightFixedPoint = FixedPoint<FONT_WEIGHT_FRACTION_BITS>;

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"
20 changes: 20 additions & 0 deletions 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 # = <FontWeight>{ <FontWeightFixedPoint>{ (400 << FONT_WEIGHT_FRACTION_BITS) } }

void root(FontWeight w);
19 changes: 19 additions & 0 deletions tests/expectations/const_generics_constant.tag.c
@@ -0,0 +1,19 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

#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);
27 changes: 27 additions & 0 deletions tests/expectations/const_generics_constant.tag.compat.c
@@ -0,0 +1,27 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

#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
20 changes: 20 additions & 0 deletions 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 # = <FontWeight>{ <FontWeightFixedPoint>{ (400 << FONT_WEIGHT_FRACTION_BITS) } }

void root(FontWeight w);
18 changes: 18 additions & 0 deletions tests/rust/const_generics_constant.rs
@@ -0,0 +1,18 @@
#[repr(C)]
pub struct FixedPoint<const FRACTION_BITS: u16> {
value: u16,
}

pub const FONT_WEIGHT_FRACTION_BITS: u16 = 6;

pub type FontWeightFixedPoint = FixedPoint<FONT_WEIGHT_FRACTION_BITS>;

#[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) {}