Skip to content

Commit 5851026

Browse files
committed
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.
1 parent c2e7f46 commit 5851026

File tree

3 files changed

+68
-7
lines changed

3 files changed

+68
-7
lines changed

src/codegen/mod.rs

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use self::helpers::{BlobTyBuilder, attributes};
2121
use std::borrow::Cow;
2222
use std::collections::HashSet;
2323
use std::collections::hash_map::{Entry, HashMap};
24+
use std::fmt::Write;
2425
use std::mem;
2526
use std::ops;
2627
use syntax::abi::Abi;
@@ -57,6 +58,11 @@ struct CodegenResult {
5758
/// Being these two different declarations.
5859
functions_seen: HashSet<String>,
5960
vars_seen: HashSet<String>,
61+
62+
/// Used for making bindings to overloaded functions. Maps from a canonical
63+
/// function name to the number of overloads we have already codegen'd for
64+
/// that name. This lets us give each overload a unique suffix.
65+
overload_counters: HashMap<String, u32>,
6066
}
6167

6268
impl CodegenResult {
@@ -67,6 +73,7 @@ impl CodegenResult {
6773
items_seen: Default::default(),
6874
functions_seen: Default::default(),
6975
vars_seen: Default::default(),
76+
overload_counters: Default::default(),
7077
}
7178
}
7279

@@ -90,6 +97,16 @@ impl CodegenResult {
9097
self.functions_seen.insert(name.into());
9198
}
9299

100+
/// Get the overload number for the given function name. Increments the
101+
/// counter internally so the next time we ask for the overload for this
102+
/// name, we get the incremented value, and so on.
103+
fn overload_number(&mut self, name: &str) -> u32 {
104+
let mut counter = self.overload_counters.entry(name.into()).or_insert(0);
105+
let number = *counter;
106+
*counter += 1;
107+
number
108+
}
109+
93110
fn seen_var(&self, name: &str) -> bool {
94111
self.vars_seen.contains(name)
95112
}
@@ -1803,14 +1820,19 @@ impl CodeGenerator for Function {
18031820
result: &mut CodegenResult,
18041821
item: &Item) {
18051822
let name = self.name();
1806-
let canonical_name = item.canonical_name(ctx);
1823+
let mut canonical_name = item.canonical_name(ctx);
1824+
let mangled_name = self.mangled_name();
18071825

1808-
// TODO: Maybe warn here if there's a type/argument mismatch, or
1809-
// something?
1810-
if result.seen_function(&canonical_name) {
1811-
return;
1826+
{
1827+
let seen_symbol_name = mangled_name.unwrap_or(&canonical_name);
1828+
1829+
// TODO: Maybe warn here if there's a type/argument mismatch, or
1830+
// something?
1831+
if result.seen_function(seen_symbol_name) {
1832+
return;
1833+
}
1834+
result.saw_function(seen_symbol_name);
18121835
}
1813-
result.saw_function(&canonical_name);
18141836

18151837
let signature_item = ctx.resolve_item(self.signature());
18161838
let signature = signature_item.kind().expect_type();
@@ -1827,7 +1849,7 @@ impl CodeGenerator for Function {
18271849
attributes.push(attributes::doc(comment));
18281850
}
18291851

1830-
if let Some(mangled) = self.mangled_name() {
1852+
if let Some(mangled) = mangled_name {
18311853
attributes.push(attributes::link_name(mangled));
18321854
} else if name != canonical_name {
18331855
attributes.push(attributes::link_name(name));
@@ -1836,6 +1858,13 @@ impl CodeGenerator for Function {
18361858
let foreign_item_kind =
18371859
ast::ForeignItemKind::Fn(fndecl, ast::Generics::default());
18381860

1861+
// Handle overloaded functions by giving each overload its own unique
1862+
// suffix.
1863+
let times_seen = result.overload_number(&canonical_name);
1864+
if times_seen > 0 {
1865+
write!(&mut canonical_name, "{}", times_seen).unwrap();
1866+
}
1867+
18391868
let foreign_item = ast::ForeignItem {
18401869
ident: ctx.rust_ident_raw(&canonical_name),
18411870
attrs: attributes,
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
4+
#![allow(non_snake_case)]
5+
6+
7+
extern "C" {
8+
#[link_name = "_Z8Evaluatec"]
9+
pub fn Evaluate(r: ::std::os::raw::c_char) -> bool;
10+
}
11+
extern "C" {
12+
#[link_name = "_Z8Evaluateii"]
13+
pub fn Evaluate1(x: ::std::os::raw::c_int, y: ::std::os::raw::c_int)
14+
-> bool;
15+
}
16+
extern "C" {
17+
#[link_name = "_ZN3foo10MyFunctionEv"]
18+
pub fn MyFunction();
19+
}
20+
extern "C" {
21+
#[link_name = "_ZN3bar10MyFunctionEv"]
22+
pub fn MyFunction1();
23+
}

tests/headers/overloading.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
extern bool Evaluate(char r);
2+
extern bool Evaluate(int x, int y);
3+
4+
namespace foo {
5+
extern void MyFunction();
6+
}
7+
namespace bar {
8+
extern void MyFunction();
9+
}

0 commit comments

Comments
 (0)