Skip to content

Commit

Permalink
Handle enum associated constants and reduce memory usage
Browse files Browse the repository at this point in the history
  • Loading branch information
grovesNL authored and eqrion committed Jan 11, 2019
1 parent 0de44ed commit 8c3e264
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 55 deletions.
31 changes: 17 additions & 14 deletions src/bindgen/ir/constant.rs
Expand Up @@ -195,25 +195,28 @@ impl Constant {
return Err("Cannot have a zero sized const definition.".to_owned());
}
let ty = ty.unwrap();
if !ty.is_primitive_or_ptr_primitive()
&& match item.expr {
syn::Expr::Struct(_) => false,
_ => true,
}

let can_handle_const_expr = match item.expr {
syn::Expr::Struct(_) => true,
_ => false,
};

if !ty.is_primitive_or_ptr_primitive() && !can_handle_const_expr
{
return Err("Unhanded const definition".to_owned());
return Err("Unhandled const definition".to_owned());
}

let expr = Literal::load(
if let syn::Expr::Struct(syn::ExprStruct { ref fields, .. }) = item.expr {
if is_transparent && fields.len() == 1 {
&fields[0].expr
} else {
&item.expr
match item.expr {
syn::Expr::Struct(syn::ExprStruct { ref fields, .. }) => {
if is_transparent && fields.len() == 1 {
&fields[0].expr
} else {
&item.expr
}
}
} else {
&item.expr
},
_ => &item.expr,
}
)?;

let full_name = Path::new(format!("{}_{}", struct_path, name));
Expand Down
93 changes: 56 additions & 37 deletions src/bindgen/parser.rs
Expand Up @@ -490,7 +490,7 @@ impl Parse {
mod_cfg: &Option<Cfg>,
items: &[syn::Item],
) {
let mut impls = Vec::new();
let mut impls_with_assoc_consts = Vec::new();

for item in items {
if item.has_test_attr() {
Expand Down Expand Up @@ -522,17 +522,27 @@ impl Parse {
self.load_syn_ty(crate_name, mod_cfg, item);
}
syn::Item::Impl(ref item_impl) => {
impls.push(item_impl);
let has_assoc_const = item_impl.items
.iter()
.any(|item| match item {
syn::ImplItem::Const(_) => true,
_ => false,
});
if has_assoc_const {
impls_with_assoc_consts.push(item_impl);
}
}
_ => {}
}
}

for item_impl in impls {
let associated_constants = item_impl.items.iter().filter_map(|item| match item {
syn::ImplItem::Const(ref associated_constant) => Some(associated_constant),
_ => None,
});
for item_impl in impls_with_assoc_consts {
let associated_constants = item_impl.items
.iter()
.filter_map(|item| match item {
syn::ImplItem::Const(ref associated_constant) => Some(associated_constant),
_ => None,
});
self.load_syn_assoc_consts(
binding_crate_name,
crate_name,
Expand Down Expand Up @@ -638,6 +648,37 @@ impl Parse {
}
}

fn is_assoc_const_of_transparent_struct(&self, const_item: &syn::ImplItemConst) -> Result<bool, ()> {
let ty = match Type::load(&const_item.ty) {
Ok(Some(t)) => t,
_ => return Ok(false),
};
let path = match ty.get_root_path() {
Some(p) => p,
_ => return Ok(false),
};

match self.structs.get_items(&path) {
Some(items) => {
if items.len() != 1 {
error!(
"Expected one struct to match path {}, but found {}",
path,
items.len(),
);
return Err(());
}

Ok(if let ItemContainer::Struct(ref s) = items[0] {
s.is_transparent
} else {
false
})
}
_ => Ok(false),
}
}

/// Loads associated `const` declarations
fn load_syn_assoc_consts<'a, I>(
&mut self,
Expand All @@ -654,36 +695,14 @@ impl Parse {
return;
}

let impl_struct_path = ty.unwrap().get_root_path().unwrap();

let is_transparent = if let Some(ref impl_items) = self.structs.get_items(&impl_struct_path)
{
if impl_items.len() != 1 {
error!(
"Expected one struct to match path {}, but found {}",
impl_struct_path,
impl_items.len()
);
return;
}
if let ItemContainer::Struct(ref s) = impl_items[0] {
s.is_transparent
} else {
info!(
"Skip impl block for {}::{} (impl blocks for associated constants are only defined for structs).",
crate_name, impl_struct_path
);
return;
}
} else {
error!(
"Cannot find type for {}::{} (impl blocks require the struct declaration to be known).",
crate_name, impl_struct_path
);
return;
};
let impl_path = ty.unwrap().get_root_path().unwrap();

for item in items.into_iter() {
let is_assoc_const_of_transparent_struct = match self.is_assoc_const_of_transparent_struct(&item) {
Ok(b) => b,
Err(_) => continue,
};

if crate_name != binding_crate_name {
info!(
"Skip {}::{} - (const's outside of the binding crate are not used).",
Expand All @@ -698,8 +717,8 @@ impl Parse {
const_name.clone(),
item,
mod_cfg,
is_transparent,
&impl_struct_path,
is_assoc_const_of_transparent_struct,
&impl_path,
) {
Ok(constant) => {
info!("Take {}::{}.", crate_name, &item.ident);
Expand Down
7 changes: 6 additions & 1 deletion tests/expectations/both/transparent.c
Expand Up @@ -5,6 +5,8 @@

typedef struct DummyStruct DummyStruct;

typedef struct EnumWithAssociatedConstantInImpl EnumWithAssociatedConstantInImpl;

typedef DummyStruct TransparentComplexWrappingStructTuple;

typedef uint32_t TransparentPrimitiveWrappingStructTuple;
Expand All @@ -19,6 +21,8 @@ typedef uint32_t TransparentPrimitiveWrapper_i32;

typedef uint32_t TransparentPrimitiveWithAssociatedConstants;

#define EnumWithAssociatedConstantInImpl_TEN 10

#define TransparentPrimitiveWithAssociatedConstants_ONE 1

#define TransparentPrimitiveWithAssociatedConstants_ZERO 0
Expand All @@ -29,4 +33,5 @@ void root(TransparentComplexWrappingStructTuple a,
TransparentPrimitiveWrappingStructure d,
TransparentComplexWrapper_i32 e,
TransparentPrimitiveWrapper_i32 f,
TransparentPrimitiveWithAssociatedConstants g);
TransparentPrimitiveWithAssociatedConstants g,
EnumWithAssociatedConstantInImpl h);
7 changes: 6 additions & 1 deletion tests/expectations/tag/transparent.c
Expand Up @@ -5,6 +5,8 @@

struct DummyStruct;

struct EnumWithAssociatedConstantInImpl;

typedef struct DummyStruct TransparentComplexWrappingStructTuple;

typedef uint32_t TransparentPrimitiveWrappingStructTuple;
Expand All @@ -19,6 +21,8 @@ typedef uint32_t TransparentPrimitiveWrapper_i32;

typedef uint32_t TransparentPrimitiveWithAssociatedConstants;

#define EnumWithAssociatedConstantInImpl_TEN 10

#define TransparentPrimitiveWithAssociatedConstants_ONE 1

#define TransparentPrimitiveWithAssociatedConstants_ZERO 0
Expand All @@ -29,4 +33,5 @@ void root(TransparentComplexWrappingStructTuple a,
TransparentPrimitiveWrappingStructure d,
TransparentComplexWrapper_i32 e,
TransparentPrimitiveWrapper_i32 f,
TransparentPrimitiveWithAssociatedConstants g);
TransparentPrimitiveWithAssociatedConstants g,
struct EnumWithAssociatedConstantInImpl h);
7 changes: 6 additions & 1 deletion tests/expectations/transparent.c
Expand Up @@ -5,6 +5,8 @@

typedef struct DummyStruct DummyStruct;

typedef struct EnumWithAssociatedConstantInImpl EnumWithAssociatedConstantInImpl;

typedef DummyStruct TransparentComplexWrappingStructTuple;

typedef uint32_t TransparentPrimitiveWrappingStructTuple;
Expand All @@ -19,6 +21,8 @@ typedef uint32_t TransparentPrimitiveWrapper_i32;

typedef uint32_t TransparentPrimitiveWithAssociatedConstants;

#define EnumWithAssociatedConstantInImpl_TEN 10

#define TransparentPrimitiveWithAssociatedConstants_ONE 1

#define TransparentPrimitiveWithAssociatedConstants_ZERO 0
Expand All @@ -29,4 +33,5 @@ void root(TransparentComplexWrappingStructTuple a,
TransparentPrimitiveWrappingStructure d,
TransparentComplexWrapper_i32 e,
TransparentPrimitiveWrapper_i32 f,
TransparentPrimitiveWithAssociatedConstants g);
TransparentPrimitiveWithAssociatedConstants g,
EnumWithAssociatedConstantInImpl h);
7 changes: 6 additions & 1 deletion tests/expectations/transparent.cpp
Expand Up @@ -4,6 +4,8 @@

struct DummyStruct;

struct EnumWithAssociatedConstantInImpl;

using TransparentComplexWrappingStructTuple = DummyStruct;

using TransparentPrimitiveWrappingStructTuple = uint32_t;
Expand All @@ -20,6 +22,8 @@ using TransparentPrimitiveWrapper = uint32_t;

using TransparentPrimitiveWithAssociatedConstants = uint32_t;

static const TransparentPrimitiveWrappingStructure EnumWithAssociatedConstantInImpl_TEN = 10;

static const TransparentPrimitiveWithAssociatedConstants TransparentPrimitiveWithAssociatedConstants_ONE = 1;

static const TransparentPrimitiveWithAssociatedConstants TransparentPrimitiveWithAssociatedConstants_ZERO = 0;
Expand All @@ -32,6 +36,7 @@ void root(TransparentComplexWrappingStructTuple a,
TransparentPrimitiveWrappingStructure d,
TransparentComplexWrapper<int32_t> e,
TransparentPrimitiveWrapper<int32_t> f,
TransparentPrimitiveWithAssociatedConstants g);
TransparentPrimitiveWithAssociatedConstants g,
EnumWithAssociatedConstantInImpl h);

} // extern "C"
7 changes: 7 additions & 0 deletions tests/rust/transparent.rs
Expand Up @@ -48,6 +48,12 @@ impl TransparentPrimitiveWithAssociatedConstants {
};
}

enum EnumWithAssociatedConstantInImpl { A }

impl EnumWithAssociatedConstantInImpl {
pub const TEN: TransparentPrimitiveWrappingStructure = TransparentPrimitiveWrappingStructure { only_field: 10 };
}

#[no_mangle]
pub extern "C" fn root(
a: TransparentComplexWrappingStructTuple,
Expand All @@ -57,4 +63,5 @@ pub extern "C" fn root(
e: TransparentComplexWrapper<i32>,
f: TransparentPrimitiveWrapper<i32>,
g: TransparentPrimitiveWithAssociatedConstants,
h: EnumWithAssociatedConstantInImpl,
) { }

0 comments on commit 8c3e264

Please sign in to comment.