Skip to content

Commit

Permalink
Use a graph the represend the dependencies between exported items
Browse files Browse the repository at this point in the history
  • Loading branch information
weiznich committed Aug 21, 2017
1 parent 5f317d3 commit 784b8fc
Show file tree
Hide file tree
Showing 22 changed files with 658 additions and 762 deletions.
23 changes: 23 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ serde_derive = "0.9"
serde_json = "0.9"
tempdir = "0.3"
toml = "0.3"
petgraph = "0.4"

[dependencies.syn]
version = "0.11"
Expand Down
13 changes: 13 additions & 0 deletions compile-tests/cycle.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#[repr(C)]
pub struct Foo {
a: i32,
b: *const Bar,
}

#[repr(C)]
pub struct Bar {
a: *mut Foo,
}

#[no_mangle]
pub extern "C" fn foo(f: Foo) {}
73 changes: 7 additions & 66 deletions src/bindgen/bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,20 @@ use std::path;
use std::fs;

use bindgen::config::{Config, Language};
use bindgen::ir::{Item, Function};
use bindgen::monomorph::TemplateSpecialization;
use bindgen::writer::{ListType, Source, SourceWriter};
use bindgen::ir::Item;
use bindgen::writer::{Source, SourceWriter};

pub struct Bindings {
config: Config,
items: Vec<Item>,
functions: Vec<Function>,
template_specializations: Vec<TemplateSpecialization>,
}

impl Bindings {
pub fn new(config: Config,
items: Vec<Item>,
functions: Vec<Function>,
template_specializations: Vec<TemplateSpecialization>) -> Bindings {
items: Vec<Item>) -> Bindings {
Bindings {
config: config,
items: items,
functions: functions,
template_specializations: template_specializations,
config,
items,
}
}

Expand Down Expand Up @@ -83,77 +76,25 @@ impl Bindings {

if self.config.language == Language::Cxx {
out.new_line_if_not_start();
out.write("extern \"C\" {");
out.new_line();

self.open_namespaces(&mut out);
}

for item in &self.items {
out.new_line_if_not_start();
match item {
&Item::Enum(ref x) => x.write(&self.config, &mut out),
&Item::Struct(ref x) => x.write(&self.config, &mut out),
&Item::OpaqueItem(ref x) => x.write(&self.config, &mut out),
&Item::Typedef(ref x) => x.write(&self.config, &mut out),
&Item::Specialization(_) => {
unreachable!("should not encounter a specialization in a generated library")
}
}
out.new_line();
}

if let Some(ref f) = self.config.autogen_warning {
out.new_line_if_not_start();
out.write(&f);
out.new_line();
}

for function in &self.functions {
for item in &self.items {
out.new_line_if_not_start();
function.write(&self.config, &mut out);
item.write(&self.config, &mut out);
out.new_line();
}

if self.config.language == Language::Cxx {
self.close_namespaces(&mut out);

out.new_line_if_not_start();
out.write("} // extern \"C\"");
out.new_line();
}

if self.config.structure.generic_template_specialization &&
self.config.language == Language::Cxx {
self.open_namespaces(&mut out);
for template in &self.template_specializations {
out.new_line_if_not_start();
out.write("template<");
for (i, param) in template.generic.generic_params.iter().enumerate() {
if i != 0 {
out.write(", ")
}
out.write("typename ");
out.write(param);
}
out.write(">");
out.new_line();
out.write(&format!("struct {};", template.generic.name));
out.new_line();

for &(ref monomorph_path, ref generic_values) in &template.monomorphs {
out.new_line();
out.write("template<>");
out.new_line();
out.write(&format!("struct {}<", template.generic.name));
out.write_horizontal_source_list(generic_values, ListType::Join(", "));
out.write(&format!("> : public {}", monomorph_path));
out.open_brace();
out.close_brace(true);
out.new_line();
}
}
self.close_namespaces(&mut out);
}

if let Some(ref f) = self.config.autogen_warning {
Expand Down
54 changes: 15 additions & 39 deletions src/bindgen/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use syn;
use bindgen::cargo::Cargo;
use bindgen::config::Config;
use bindgen::ir::{AnnotationSet, Cfg, Documentation, Enum, Function};
use bindgen::ir::{OpaqueItem, Specialization, Struct, Typedef};
use bindgen::ir::{OpaqueItem, Struct, Typedef};
use bindgen::library::Library;
use bindgen::rust_lib;
use bindgen::utilities::{SynAbiHelpers, SynItemHelpers};
Expand All @@ -25,7 +25,6 @@ pub struct LibraryBuilder {
structs: BTreeMap<String, Struct>,
opaque_items: BTreeMap<String, OpaqueItem>,
typedefs: BTreeMap<String, Typedef>,
specializations: BTreeMap<String, Specialization>,
functions: Vec<Function>,
}

Expand All @@ -39,7 +38,6 @@ impl LibraryBuilder {
structs: BTreeMap::new(),
opaque_items: BTreeMap::new(),
typedefs: BTreeMap::new(),
specializations: BTreeMap::new(),
functions: Vec::new(),
}
}
Expand Down Expand Up @@ -115,14 +113,11 @@ impl LibraryBuilder {
})?;
}

self.functions.sort_by(|x, y| x.name.cmp(&y.name));

Ok(Library::new(self.config,
self.enums,
self.structs,
self.opaque_items,
self.typedefs,
self.specializations,
self.functions))
}

Expand Down Expand Up @@ -333,42 +328,23 @@ impl LibraryBuilder {
generics: &syn::Generics) {
let alias_name = item.ident.to_string();

let fail1 = if generics.lifetimes.is_empty() &&
generics.ty_params.is_empty()
match Typedef::load(alias_name.clone(),
&item.attrs,
generics,
ty,
mod_cfg)
{
match Typedef::load(alias_name.clone(),
ty,
&item.attrs,
mod_cfg)
{
Ok(typedef) => {
info!("take {}::{}", crate_name, &item.ident);
self.typedefs.insert(alias_name, typedef);
return;
}
Err(msg) => msg,
}
} else {
format!("cannot have generics in typedef")
};

let fail2 = match Specialization::load(alias_name.clone(),
generics,
ty,
&item.attrs,
mod_cfg) {
Ok(spec) => {
Ok(typedef) => {
info!("take {}::{}", crate_name, &item.ident);
self.specializations.insert(alias_name, spec);
self.typedefs.insert(alias_name, typedef);
return;
}
Err(msg) => msg,
};

info!("skip {}::{} - ({} and {})",
crate_name,
&item.ident,
fail1,
fail2);
Err(msg) => {
info!("skip {}::{} - ({})",
crate_name,
&item.ident,
msg);
},
}
}
}
5 changes: 1 addition & 4 deletions src/bindgen/cdecl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,14 @@ impl CDecl {
fn build_type(&mut self, t: &Type, is_const: bool) {
match t {
&Type::Path(ref path) => {
// We should be assured that there are no generics by instantiating
// monomorphs and mangling paths.
assert!(path.generics.len() == 0);

if is_const {
assert!(self.type_qualifers.len() == 0);
self.type_qualifers = "const".to_owned();
}

assert!(self.type_name.len() == 0);
self.type_name = path.name.clone();
self.type_name = path.mangle();
}
&Type::Primitive(ref p) => {
if is_const {
Expand Down
Loading

0 comments on commit 784b8fc

Please sign in to comment.