diff options
-rw-r--r-- | src/codegen/mod.rs | 3 | ||||
-rw-r--r-- | src/ir/comp.rs | 4 | ||||
-rw-r--r-- | src/ir/context.rs | 69 | ||||
-rw-r--r-- | src/ir/function.rs | 4 | ||||
-rw-r--r-- | src/ir/item.rs | 6 | ||||
-rw-r--r-- | src/ir/mod.rs | 1 | ||||
-rw-r--r-- | src/ir/traversal.rs | 78 | ||||
-rw-r--r-- | src/ir/ty.rs | 4 | ||||
-rw-r--r-- | src/ir/type_collector.rs | 7 |
9 files changed, 98 insertions, 78 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 99400f7a..6f9291f7 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -12,13 +12,12 @@ use ir::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault}; use ir::enum_ty::{Enum, EnumVariant, EnumVariantValue}; use ir::function::{Function, FunctionSig}; use ir::int::IntKind; -use ir::item::{Item, ItemAncestors, ItemCanonicalName, ItemCanonicalPath}; +use ir::item::{Item, ItemSet, ItemAncestors, ItemCanonicalName, ItemCanonicalPath}; use ir::item_kind::ItemKind; use ir::layout::Layout; use ir::module::Module; use ir::objc::ObjCInterface; use ir::ty::{Type, TypeKind}; -use ir::type_collector::ItemSet; use ir::var::Var; use std::borrow::Cow; diff --git a/src/ir/comp.rs b/src/ir/comp.rs index 7c58e233..2ca25479 100644 --- a/src/ir/comp.rs +++ b/src/ir/comp.rs @@ -3,10 +3,10 @@ use super::annotations::Annotations; use super::context::{BindgenContext, ItemId}; use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault}; -use super::item::Item; +use super::item::{Item, ItemSet}; use super::layout::Layout; use super::ty::{TemplateDeclaration, Type}; -use super::type_collector::{ItemSet, TypeCollector}; +use super::type_collector::TypeCollector; use clang; use parse::{ClangItemParser, ParseError}; use std::cell::Cell; diff --git a/src/ir/context.rs b/src/ir/context.rs index 91ce579c..e251f0c3 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -2,11 +2,12 @@ use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault}; use super::int::IntKind; -use super::item::{Item, ItemCanonicalPath}; +use super::item::{Item, ItemSet, ItemCanonicalPath}; use super::item_kind::ItemKind; use super::module::{Module, ModuleKind}; +use super::traversal::ItemTraversal; use super::ty::{FloatKind, TemplateDeclaration, Type, TypeKind}; -use super::type_collector::{ItemSet, TypeCollector}; +use super::type_collector::TypeCollector; use BindgenOptions; use cexpr; use chooser::TypeChooser; @@ -1203,7 +1204,7 @@ impl<'ctx> BindgenContext<'ctx> { /// If no items are explicitly whitelisted, then all items are considered /// whitelisted. pub fn whitelisted_items<'me>(&'me self) - -> WhitelistedItemsIter<'me, 'ctx> { + -> ItemTraversal<'me, 'ctx> { assert!(self.in_codegen_phase()); assert!(self.current_module == self.root_module); @@ -1268,18 +1269,7 @@ impl<'ctx> BindgenContext<'ctx> { }) .map(|(&id, _)| id); - let seen: ItemSet = roots.collect(); - - // The .rev() preserves the expected ordering traversal, resulting in - // more stable-ish bindgen-generated names for anonymous types (like - // unions). - let to_iterate = seen.iter().cloned().rev().collect(); - - WhitelistedItemsIter { - ctx: self, - seen: seen, - to_iterate: to_iterate, - } + ItemTraversal::new(self, roots) } /// Convenient method for getting the prefix to use for most traits in @@ -1365,55 +1355,6 @@ impl TemplateDeclaration for PartialType { } } -/// An iterator over whitelisted items. -/// -/// See `BindgenContext::whitelisted_items` for more information. -pub struct WhitelistedItemsIter<'ctx, 'gen> - where 'gen: 'ctx, -{ - ctx: &'ctx BindgenContext<'gen>, - - /// The set of whitelisted items we have seen. If you think of traversing - /// whitelisted items like GC tracing, this is the mark bits, and contains - /// both black and gray items. - seen: ItemSet, - - /// The set of whitelisted items that we have seen but have yet to iterate - /// over and collect transitive references from. To return to the GC analogy, - /// this is the mark stack, containing the set of gray items which we have - /// not finished tracing yet. - to_iterate: Vec<ItemId>, -} - -impl<'ctx, 'gen> Iterator for WhitelistedItemsIter<'ctx, 'gen> - where 'gen: 'ctx, -{ - type Item = ItemId; - - fn next(&mut self) -> Option<Self::Item> { - let id = match self.to_iterate.pop() { - None => return None, - Some(id) => id, - }; - - debug_assert!(self.seen.contains(&id)); - debug_assert!(self.ctx.items.contains_key(&id)); - - if self.ctx.options().whitelist_recursively { - let mut sub_types = ItemSet::new(); - id.collect_types(self.ctx, &mut sub_types, &()); - - for id in sub_types { - if self.seen.insert(id) { - self.to_iterate.push(id); - } - } - } - - Some(id) - } -} - /// An iterator to find any dangling items. /// /// See `BindgenContext::assert_no_dangling_item_traversal` for more diff --git a/src/ir/function.rs b/src/ir/function.rs index 6273de28..be8c49d5 100644 --- a/src/ir/function.rs +++ b/src/ir/function.rs @@ -1,9 +1,9 @@ //! Intermediate representation for C/C++ functions and methods. use super::context::{BindgenContext, ItemId}; -use super::item::Item; +use super::item::{Item, ItemSet}; use super::ty::TypeKind; -use super::type_collector::{ItemSet, TypeCollector}; +use super::type_collector::TypeCollector; use clang; use clang_sys::CXCallingConv; use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult}; diff --git a/src/ir/item.rs b/src/ir/item.rs index 83e2a41f..2717c792 100644 --- a/src/ir/item.rs +++ b/src/ir/item.rs @@ -7,11 +7,12 @@ use super::function::Function; use super::item_kind::ItemKind; use super::module::Module; use super::ty::{TemplateDeclaration, Type, TypeKind}; -use super::type_collector::{ItemSet, TypeCollector}; +use super::type_collector::TypeCollector; use clang; use clang_sys; use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult}; use std::cell::{Cell, RefCell}; +use std::collections::BTreeSet; use std::fmt::Write; use std::iter; @@ -902,6 +903,9 @@ impl Item { } } +/// A set of items. +pub type ItemSet = BTreeSet<ItemId>; + impl TemplateDeclaration for ItemId { fn template_params(&self, ctx: &BindgenContext) -> Option<Vec<ItemId>> { ctx.resolve_item_fallible(*self) diff --git a/src/ir/mod.rs b/src/ir/mod.rs index d424fcdf..9e53c184 100644 --- a/src/ir/mod.rs +++ b/src/ir/mod.rs @@ -14,6 +14,7 @@ pub mod item; pub mod item_kind; pub mod layout; pub mod module; +pub mod traversal; pub mod ty; pub mod type_collector; pub mod var; diff --git a/src/ir/traversal.rs b/src/ir/traversal.rs new file mode 100644 index 00000000..d8e9a6e2 --- /dev/null +++ b/src/ir/traversal.rs @@ -0,0 +1,78 @@ +//! Traversal of the graph of IR items and types. + +use super::context::{BindgenContext, ItemId}; +use super::item::ItemSet; +use super::type_collector::TypeCollector; + +/// An graph traversal of the transitive closure of references between items. +/// +/// See `BindgenContext::whitelisted_items` for more information. +pub struct ItemTraversal<'ctx, 'gen> + where 'gen: 'ctx, +{ + ctx: &'ctx BindgenContext<'gen>, + + /// The set of whitelisted items we have seen. If you think of traversing + /// whitelisted items like GC tracing, this is the mark bits, and contains + /// both black and gray items. + seen: ItemSet, + + /// The set of whitelisted items that we have seen but have yet to iterate + /// over and collect transitive references from. To return to the GC analogy, + /// this is the mark stack, containing the set of gray items which we have + /// not finished tracing yet. + to_iterate: Vec<ItemId>, +} + +impl<'ctx, 'gen> ItemTraversal<'ctx, 'gen> + where 'gen: 'ctx, +{ + /// Begin a new traversal, starting from the given roots. + pub fn new<R>(ctx: &'ctx BindgenContext<'gen>, + roots: R) + -> ItemTraversal<'ctx, 'gen> + where R: IntoIterator<Item = ItemId>, + { + // Construct the ItemSet first. Because its underlying storage is a + // BTreeSet, its iteration over its entries is ordered, and the roots + // end up ordered as well. This contributes enables stable, + // deterministic generated names in the bindings. + let seen: ItemSet = roots.into_iter().collect(); + let roots: Vec<_> = seen.iter().cloned().collect(); + + ItemTraversal { + ctx: ctx, + seen: seen, + to_iterate: roots, + } + } +} + +impl<'ctx, 'gen> Iterator for ItemTraversal<'ctx, 'gen> + where 'gen: 'ctx, +{ + type Item = ItemId; + + fn next(&mut self) -> Option<Self::Item> { + let id = match self.to_iterate.pop() { + None => return None, + Some(id) => id, + }; + + debug_assert!(self.seen.contains(&id)); + debug_assert!(self.ctx.resolve_item_fallible(id).is_some()); + + if self.ctx.options().whitelist_recursively { + let mut sub_types = ItemSet::new(); + id.collect_types(self.ctx, &mut sub_types, &()); + + for id in sub_types { + if self.seen.insert(id) { + self.to_iterate.push(id); + } + } + } + + Some(id) + } +} diff --git a/src/ir/ty.rs b/src/ir/ty.rs index a47c1470..b51054b7 100644 --- a/src/ir/ty.rs +++ b/src/ir/ty.rs @@ -6,10 +6,10 @@ use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault}; use super::enum_ty::Enum; use super::function::FunctionSig; use super::int::IntKind; -use super::item::Item; +use super::item::{Item, ItemSet}; use super::layout::Layout; use super::objc::ObjCInterface; -use super::type_collector::{ItemSet, TypeCollector}; +use super::type_collector::TypeCollector; use clang::{self, Cursor}; use parse::{ClangItemParser, ParseError, ParseResult}; use std::mem; diff --git a/src/ir/type_collector.rs b/src/ir/type_collector.rs index 25285b23..424007a1 100644 --- a/src/ir/type_collector.rs +++ b/src/ir/type_collector.rs @@ -1,10 +1,7 @@ //! Collecting type items. -use super::context::{BindgenContext, ItemId}; -use std::collections::BTreeSet; - -/// A set of items. -pub type ItemSet = BTreeSet<ItemId>; +use super::context::BindgenContext; +use super::item::ItemSet; /// Collect all the type items referenced by this item. pub trait TypeCollector { |