Add option for mangling_separator in ExportConfig (#502)

This commit is contained in:
Adam Wilson 2020-08-18 20:45:30 +01:00 committed by GitHub
parent d652d29ae2
commit 030916e399
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 116 additions and 29 deletions

View File

@ -246,6 +246,8 @@ pub struct ExportConfig {
pub item_types: Vec<ItemType>,
/// Whether renaming overrides or extends prefixing.
pub renaming_overrides_prefixing: bool,
/// Name mangling character. Defaults to `_`
pub mangle_separator: Option<String>,
}
impl ExportConfig {

View File

@ -51,12 +51,17 @@ impl VariantBody {
}
}
fn specialize(&self, generic_values: &[Type], mappings: &[(&Path, &Type)]) -> Self {
fn specialize(
&self,
generic_values: &[Type],
mappings: &[(&Path, &Type)],
config: &Config,
) -> Self {
match *self {
Self::Empty(ref annos) => Self::Empty(annos.clone()),
Self::Body { ref name, ref body } => Self::Body {
name: name.clone(),
body: body.specialize(generic_values, mappings),
body: body.specialize(generic_values, mappings, config),
},
}
}
@ -225,11 +230,20 @@ impl EnumVariant {
}
}
fn specialize(&self, generic_values: &[Type], mappings: &[(&Path, &Type)]) -> Self {
fn specialize(
&self,
generic_values: &[Type],
mappings: &[(&Path, &Type)],
config: &Config,
) -> Self {
Self::new(
mangle::mangle_name(&self.name, generic_values),
mangle::mangle_name(
&self.name,
generic_values,
config.export.mangle_separator.as_deref(),
),
self.discriminant,
self.body.specialize(generic_values, mappings),
self.body.specialize(generic_values, mappings, config),
self.cfg.clone(),
self.documentation.clone(),
)
@ -544,14 +558,19 @@ impl Item for Enum {
}
}
let mangled_path = mangle::mangle_path(&self.path, generic_values);
let mangled_path = mangle::mangle_path(
&self.path,
generic_values,
library.get_config().export.mangle_separator.as_deref(),
);
let monomorph = Enum::new(
mangled_path,
GenericParams::default(),
self.repr,
self.variants
.iter()
.map(|v| v.specialize(generic_values, &mappings))
.map(|v| v.specialize(generic_values, &mappings, library.get_config()))
.collect(),
self.tag.clone(),
self.cfg.clone(),

View File

@ -101,7 +101,7 @@ impl Item for OpaqueItem {
fn instantiate_monomorph(
&self,
generic_values: &[Type],
_library: &Library,
library: &Library,
out: &mut Monomorphs,
) {
assert!(
@ -121,7 +121,12 @@ impl Item for OpaqueItem {
generic_values.len(),
);
let mangled_path = mangle::mangle_path(&self.path, generic_values);
let mangled_path = mangle::mangle_path(
&self.path,
generic_values,
library.get_config().export.mangle_separator.as_deref(),
);
let monomorph = OpaqueItem::new(
mangled_path,
GenericParams::default(),

View File

@ -172,8 +172,17 @@ impl Struct {
}
}
pub fn specialize(&self, generic_values: &[Type], mappings: &[(&Path, &Type)]) -> Self {
let mangled_path = mangle::mangle_path(&self.path, generic_values);
pub fn specialize(
&self,
generic_values: &[Type],
mappings: &[(&Path, &Type)],
config: &Config,
) -> Self {
let mangled_path = mangle::mangle_path(
&self.path,
generic_values,
config.export.mangle_separator.as_deref(),
);
Struct::new(
mangled_path,
GenericParams::default(),
@ -377,7 +386,7 @@ impl Item for Struct {
.zip(generic_values.iter())
.collect::<Vec<_>>();
let monomorph = self.specialize(generic_values, &mappings);
let monomorph = self.specialize(generic_values, &mappings, library.get_config());
// Instantiate any monomorphs for any generic paths we may have just created.
monomorph.add_monomorphs(library, out);

View File

@ -174,7 +174,12 @@ impl Item for Typedef {
.zip(generic_values.iter())
.collect::<Vec<_>>();
let mangled_path = mangle::mangle_path(&self.path, generic_values);
let mangled_path = mangle::mangle_path(
&self.path,
generic_values,
library.get_config().export.mangle_separator.as_deref(),
);
let monomorph = Typedef::new(
mangled_path,
GenericParams::default(),

View File

@ -236,7 +236,12 @@ impl Item for Union {
.zip(generic_values.iter())
.collect::<Vec<_>>();
let mangled_path = mangle::mangle_path(&self.path, generic_values);
let mangled_path = mangle::mangle_path(
&self.path,
generic_values,
library.get_config().export.mangle_separator.as_deref(),
);
let monomorph = Union::new(
mangled_path,
GenericParams::default(),

View File

@ -149,6 +149,10 @@ impl Library {
None
}
pub fn get_config(&self) -> &Config {
&self.config
}
fn remove_excluded(&mut self) {
let config = &self.config;
// FIXME: interpret `config.export.exclude` as `Path`s.

View File

@ -4,12 +4,18 @@
use crate::bindgen::ir::{Path, Type};
pub fn mangle_path(path: &Path, generic_values: &[Type]) -> Path {
Path::new(mangle_name(path.name(), generic_values))
pub fn mangle_path(path: &Path, generic_values: &[Type], mangle_separator: Option<&str>) -> Path {
Path::new(mangle_name(path.name(), generic_values, mangle_separator))
}
pub fn mangle_name(name: &str, generic_values: &[Type]) -> String {
Mangler::new(name, generic_values, /* last = */ true).mangle()
pub fn mangle_name(name: &str, generic_values: &[Type], mangle_separator: Option<&str>) -> String {
Mangler::new(
name,
generic_values,
/* last = */ true,
mangle_separator,
)
.mangle()
}
enum Separator {
@ -25,15 +31,26 @@ struct Mangler<'a> {
generic_values: &'a [Type],
output: String,
last: bool,
mangle_separator: &'a str,
}
impl<'a> Mangler<'a> {
fn new(input: &'a str, generic_values: &'a [Type], last: bool) -> Self {
fn new(
input: &'a str,
generic_values: &'a [Type],
last: bool,
mangle_separator: Option<&'a str>,
) -> Self {
let separator = match mangle_separator {
Some(s) => s,
None => "_",
};
Self {
input,
generic_values,
output: String::new(),
last,
mangle_separator: separator,
}
}
@ -43,16 +60,21 @@ impl<'a> Mangler<'a> {
}
fn push(&mut self, id: Separator) {
let separator = '_';
let count = id as usize;
self.output.extend(std::iter::repeat(separator).take(count));
self.output
.extend(std::iter::repeat(self.mangle_separator).take(count));
}
fn append_mangled_type(&mut self, ty: &Type, last: bool) {
match *ty {
Type::Path(ref generic) => {
let sub_path =
Mangler::new(generic.export_name(), generic.generics(), last).mangle();
let sub_path = Mangler::new(
generic.export_name(),
generic.generics(),
last,
Some(self.mangle_separator),
)
.mangle();
self.output.push_str(&sub_path);
}
Type::Primitive(ref primitive) => {
@ -121,25 +143,39 @@ fn generics() {
// Foo<f32> => Foo_f32
assert_eq!(
mangle_path(&Path::new("Foo"), &vec![float()]),
mangle_path(&Path::new("Foo"), &vec![float()], None),
Path::new("Foo_f32")
);
// Foo<Bar<f32>> => Foo_Bar_f32
assert_eq!(
mangle_path(&Path::new("Foo"), &vec![generic_path("Bar", &[float()])]),
mangle_path(
&Path::new("Foo"),
&vec![generic_path("Bar", &[float()])],
None
),
Path::new("Foo_Bar_f32")
);
// Foo<Bar> => Foo_Bar
assert_eq!(
mangle_path(&Path::new("Foo"), &[path("Bar")]),
mangle_path(&Path::new("Foo"), &[path("Bar")], None),
Path::new("Foo_Bar")
);
// Foo<Bar> => FooBar
assert_eq!(
mangle_path(&Path::new("Foo"), &[path("Bar")], Some("")),
Path::new("FooBar")
);
// Foo<Bar<T>> => Foo_Bar_T
assert_eq!(
mangle_path(&Path::new("Foo"), &[generic_path("Bar", &[path("T")])]),
mangle_path(
&Path::new("Foo"),
&[generic_path("Bar", &[path("T")])],
None
),
Path::new("Foo_Bar_T")
);
@ -147,7 +183,8 @@ fn generics() {
assert_eq!(
mangle_path(
&Path::new("Foo"),
&[generic_path("Bar", &[path("T")]), path("E")]
&[generic_path("Bar", &[path("T")]), path("E")],
None,
),
Path::new("Foo_Bar_T_____E")
);
@ -159,7 +196,8 @@ fn generics() {
&[
generic_path("Bar", &[path("T")]),
generic_path("Bar", &[path("E")]),
]
],
None,
),
Path::new("Foo_Bar_T_____Bar_E")
);