summaryrefslogtreecommitdiff
path: root/src/codegen/mod.rs
diff options
context:
space:
mode:
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,