summaryrefslogtreecommitdiff
path: root/src/codegen/mod.rs
diff options
context:
space:
mode:
authorNick Fitzgerald <fitzgen@gmail.com>2016-11-11 16:20:36 -0800
committerNick Fitzgerald <fitzgen@gmail.com>2016-11-11 16:20:36 -0800
commit5851026f744ddf2807f3eafa8c9341134ae7f4f2 (patch)
tree1425b4eb42bfa33fc24d708226fc7f10a79bb87c /src/codegen/mod.rs
parentc2e7f46a326eb7e7ec99dbe9f68d8f4020223541 (diff)
Add support for bindings to overloaded functions
This commit (re)adds support for generating bindings to overloaded functions. First, we use the symbol name instead of the canonical name when checking if we have already generated bindings for a given function. Second, we add a map from canonical names to number of times we have generated a function with that canonical name. We increment this number every time we generate a function. When the number is greater than zero, we append it to the function name so that overloaded functions get a unique Rust symbol.
Diffstat (limited to 'src/codegen/mod.rs')
-rwxr-xr-xsrc/codegen/mod.rs43
1 files changed, 36 insertions, 7 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index 3bee69b6..5ced46a1 100755
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -21,6 +21,7 @@ use self::helpers::{BlobTyBuilder, attributes};
use std::borrow::Cow;
use std::collections::HashSet;
use std::collections::hash_map::{Entry, HashMap};
+use std::fmt::Write;
use std::mem;
use std::ops;
use syntax::abi::Abi;
@@ -57,6 +58,11 @@ struct CodegenResult {
/// Being these two different declarations.
functions_seen: HashSet<String>,
vars_seen: HashSet<String>,
+
+ /// Used for making bindings to overloaded functions. Maps from a canonical
+ /// function name to the number of overloads we have already codegen'd for
+ /// that name. This lets us give each overload a unique suffix.
+ overload_counters: HashMap<String, u32>,
}
impl CodegenResult {
@@ -67,6 +73,7 @@ impl CodegenResult {
items_seen: Default::default(),
functions_seen: Default::default(),
vars_seen: Default::default(),
+ overload_counters: Default::default(),
}
}
@@ -90,6 +97,16 @@ impl CodegenResult {
self.functions_seen.insert(name.into());
}
+ /// Get the overload number for the given function name. Increments the
+ /// counter internally so the next time we ask for the overload for this
+ /// name, we get the incremented value, and so on.
+ fn overload_number(&mut self, name: &str) -> u32 {
+ let mut counter = self.overload_counters.entry(name.into()).or_insert(0);
+ let number = *counter;
+ *counter += 1;
+ number
+ }
+
fn seen_var(&self, name: &str) -> bool {
self.vars_seen.contains(name)
}
@@ -1803,14 +1820,19 @@ impl CodeGenerator for Function {
result: &mut CodegenResult,
item: &Item) {
let name = self.name();
- let canonical_name = item.canonical_name(ctx);
+ let mut canonical_name = item.canonical_name(ctx);
+ let mangled_name = self.mangled_name();
- // TODO: Maybe warn here if there's a type/argument mismatch, or
- // something?
- if result.seen_function(&canonical_name) {
- return;
+ {
+ let seen_symbol_name = mangled_name.unwrap_or(&canonical_name);
+
+ // TODO: Maybe warn here if there's a type/argument mismatch, or
+ // something?
+ if result.seen_function(seen_symbol_name) {
+ return;
+ }
+ result.saw_function(seen_symbol_name);
}
- result.saw_function(&canonical_name);
let signature_item = ctx.resolve_item(self.signature());
let signature = signature_item.kind().expect_type();
@@ -1827,7 +1849,7 @@ impl CodeGenerator for Function {
attributes.push(attributes::doc(comment));
}
- if let Some(mangled) = self.mangled_name() {
+ if let Some(mangled) = mangled_name {
attributes.push(attributes::link_name(mangled));
} else if name != canonical_name {
attributes.push(attributes::link_name(name));
@@ -1836,6 +1858,13 @@ impl CodeGenerator for Function {
let foreign_item_kind =
ast::ForeignItemKind::Fn(fndecl, ast::Generics::default());
+ // Handle overloaded functions by giving each overload its own unique
+ // suffix.
+ let times_seen = result.overload_number(&canonical_name);
+ if times_seen > 0 {
+ write!(&mut canonical_name, "{}", times_seen).unwrap();
+ }
+
let foreign_item = ast::ForeignItem {
ident: ctx.rust_ident_raw(&canonical_name),
attrs: attributes,