Skip to content

Commit

Permalink
Support destructors
Browse files Browse the repository at this point in the history
  • Loading branch information
weiznich committed Aug 7, 2017
1 parent dffcd59 commit b729aff
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 43 deletions.
1 change: 1 addition & 0 deletions src/bindgen/ir/alias.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ impl Specialization {
generic_params: self.generic_params.clone(),
documentation: aliased.documentation.clone(),
functions: Vec::new(),
destructor: None,
})))
}
PathValue::Enum(ref aliased) => {
Expand Down
19 changes: 18 additions & 1 deletion src/bindgen/ir/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use bindgen::library::*;
use bindgen::rename::*;
use bindgen::utilities::*;
use bindgen::writer::*;
use bindgen::mangle;

#[derive(Debug, Clone)]
pub struct Function {
Expand Down Expand Up @@ -50,7 +51,16 @@ impl Function {
if let Some(&(_, ref ty)) = self.args.get(0) {
match *ty {
Type::ConstPtr(ref t) | Type::Ptr(ref t) => {
out.entry((**t).clone())
let t = match **t {
Type::Path(ref t, ref g) if g.is_empty() => {
Type::Path(t.to_owned(), Vec::new())
}
Type::Path(ref p, ref g) => {
Type::Path(mangle::mangle_path(p, g), Vec::new())
}
_ => return
};
out.entry(t)
.or_insert_with(Vec::new)
.push(self.clone())
}
Expand Down Expand Up @@ -99,6 +109,13 @@ impl Function {
}
}

pub fn as_member(self) -> Self{
Function {
args: self.args[1..].to_owned(),
..self
}
}

pub fn write_formated<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>, add_semicolon: bool) {
fn write_1<W: Write>(func: &Function, config: &Config, out: &mut SourceWriter<W>, add_semicolon: bool) {
let prefix = config.function.prefix(&func.annotations);
Expand Down
127 changes: 102 additions & 25 deletions src/bindgen/ir/structure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub struct Struct {
pub generic_params: Vec<String>,
pub documentation: Documentation,
pub functions: Vec<Function>,
pub destructor: Option<Function>,
}

impl Struct {
Expand Down Expand Up @@ -65,6 +66,7 @@ impl Struct {
generic_params: generic_params,
documentation: Documentation::load(doc),
functions: Vec::new(),
destructor: None,
})
}

Expand Down Expand Up @@ -97,6 +99,7 @@ impl Struct {
generic_params: vec![],
documentation: self.documentation.clone(),
functions: vec![],
destructor: None,
};

for &(_, ref ty, _) in &monomorph.fields {
Expand Down Expand Up @@ -140,15 +143,100 @@ impl Struct {
x.2.clone()))
.collect();
}

for f in &mut self.functions {
f.rename_args(config);
}
if let Some(ref mut destructor) = self.destructor {
destructor.rename_args(config);
}
}

pub fn mangle_paths(&mut self, monomorphs: &Monomorphs) {
for &mut (_, ref mut ty, _) in &mut self.fields {
ty.mangle_paths(monomorphs);
}
for f in &mut self.functions {
f.mangle_paths(monomorphs);
}
if let Some(ref mut destructor) = self.destructor {
destructor.mangle_paths(monomorphs);
}
}

pub fn add_member_function(&mut self, function: Function) {

if function.annotations.bool("destructor").unwrap_or(false)
&& self.destructor.is_none() && function.args.is_empty()
{
self.destructor = Some(function);
} else if !function.annotations.bool("destructor").unwrap_or(false) {
self.functions.push(function);
} else {
warn!("Found double destructor annotation for struct {}", self.name);
}
}

pub fn as_opaque(&self) -> OpaqueItem {
OpaqueItem {
name: self.name.clone(),
generic_params: self.generic_params.clone(),
annotations: self.annotations.clone(),
documentation: self.documentation.clone(),
}
}

pub fn write_destructor<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
if let Some(ref destructor) = self.destructor {
if !destructor.extern_decl {
out.new_line();
out.new_line();

out.write(&format!("~{}()", self.name));
out.open_brace();
let option_1 = out.measure(|out| format_function_call_1(destructor, out, false));

if (config.function.args == Layout::Auto && option_1 <= config.line_length) ||
config.function.args == Layout::Horizontal {
format_function_call_1(destructor, out, false);
} else {
format_function_call_2(destructor, out, false);
}

out.close_brace(false);
}
}
}

pub fn write_functions<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
if !self.functions.is_empty() {
out.new_line();
out.new_line();
}
for f in &self.functions {
if f.extern_decl {
continue;
}
out.new_line();
f.write_formated(config, out, false);
out.open_brace();
let option_1 = out.measure(|out| format_function_call_1(f, out, true));

if (config.function.args == Layout::Auto && option_1 <= config.line_length) ||
config.function.args == Layout::Horizontal {
format_function_call_1(f, out, true);
} else {
format_function_call_2(f, out, true);
}

out.close_brace(false);
out.new_line();
}
}
}



impl Source for Struct {
fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
assert!(self.generic_params.is_empty());
Expand All @@ -172,27 +260,8 @@ impl Source for Struct {
String::from("other")
};

out.new_line();
for f in &self.functions {
if f.extern_decl {
continue;
}
out.new_line();
f.write_formated(config, out, false);
out.open_brace();
out.new_line();
let option_1 = out.measure(|out| format_function_call_1(f, out));

if (config.function.args == Layout::Auto && option_1 <= config.line_length) ||
config.function.args == Layout::Horizontal {
format_function_call_1(f, out);
} else {
format_function_call_2(f, out);
}

out.close_brace(false);
out.new_line();
}
self.write_destructor(config, out);
self.write_functions(config, out);

let mut emit_op = |op, conjuc| {
if !wrote_start_newline {
Expand Down Expand Up @@ -248,8 +317,12 @@ impl Source for Struct {
}
}

fn format_function_call_1<W: Write>(f: &Function, out: &mut SourceWriter<W>) {
out.write("return ::");
fn format_function_call_1<W: Write>(f: &Function, out: &mut SourceWriter<W>, with_return: bool) {
if with_return {
out.write("return ::");
} else {
out.write("::");
}
out.write(&f.name);
out.write("(this");
for &(ref name, _) in &f.args {
Expand All @@ -259,8 +332,12 @@ fn format_function_call_1<W: Write>(f: &Function, out: &mut SourceWriter<W>) {
out.write(");");
}

fn format_function_call_2<W: Write>(f: &Function, out: &mut SourceWriter<W>) {
out.write("return ::");
fn format_function_call_2<W: Write>(f: &Function, out: &mut SourceWriter<W>, with_return: bool) {
if with_return {
out.write("return ::");
} else {
out.write("::");
}
out.write(&f.name);
out.write("(");
let align_lenght = out.line_length_for_align();
Expand Down
26 changes: 9 additions & 17 deletions src/bindgen/library.rs
Original file line number Diff line number Diff line change
Expand Up @@ -719,24 +719,11 @@ impl Library {
PathValue::Struct(mut s) => {
let ty = Type::Path(s.name.clone(), Vec::new());
if let Some(functions) = oop.remove(&ty) {
let opaque = OpaqueItem {
name:s.name.clone(),
generic_params: s.generic_params.clone(),
annotations: s.annotations.clone(),
documentation: s.documentation.clone(),
};
let opaque = s.as_opaque();
result.items.push(PathValue::OpaqueItem(opaque));
s.functions = functions.into_iter()
.map(|f| {
Function {
name: f.name,
annotations: f.annotations,
ret: f.ret,
args: f.args[1..].to_owned(),
extern_decl: f.extern_decl,
documentation: f.documentation.clone(),
}
}).collect();
for f in functions {
s.add_member_function(f.as_member());
}
result.full_objects.push(s);
} else {
result.items.push(PathValue::Struct(s));
Expand All @@ -758,6 +745,11 @@ impl Library {
item.rename_fields(&self.config);
}

for item in &mut result.full_objects {
item.mangle_paths(&monomorphs);
item.rename_fields(&self.config);
}

// Rename all the arguments according to their rules and mangle any
// paths that refer to generic structs that have been monomorph'ed.
for func in &mut result.functions {
Expand Down

0 comments on commit b729aff

Please sign in to comment.