diff --git a/docs.md b/docs.md index 3e06838..cc2176a 100644 --- a/docs.md +++ b/docs.md @@ -591,6 +591,14 @@ private: void cppMethod() const; """ +# Configuration for name mangling +[export.mangle] +# Whether the types should be renamed during mangling, for example +# c_char -> CChar, etc. +rename_types = "PascalCase" +# Whether the underscores from the mangled name should be omitted. +remove_underscores = false + [layout] # A string that should come before the name of any type which has been marked # as `#[repr(packed)]`. For instance, "__attribute__((packed))" would be a diff --git a/src/bindgen/config.rs b/src/bindgen/config.rs index ce8b6d9..266d92b 100644 --- a/src/bindgen/config.rs +++ b/src/bindgen/config.rs @@ -287,8 +287,6 @@ pub struct ExportConfig { pub include: Vec, /// A list of items to not include in the generated bindings pub exclude: Vec, - /// The rename rule to apply to the type names - pub rename_types: Option, /// Table of name conversions to apply to item names pub rename: HashMap, /// Table of raw strings to prepend to the body of items. @@ -301,7 +299,19 @@ pub struct ExportConfig { pub item_types: Vec, /// Whether renaming overrides or extends prefixing. pub renaming_overrides_prefixing: bool, - /// Remove the underscores used for name mangling + /// Mangling configuration. + pub mangle: MangleConfig, +} + +/// Mangling-specific configuration. +#[derive(Debug, Clone, Deserialize, Default)] +#[serde(rename_all = "snake_case")] +#[serde(deny_unknown_fields)] +#[serde(default)] +pub struct MangleConfig { + /// The rename rule to apply to the type names mangled. + pub rename_types: Option, + /// Remove the underscores used for name mangling. pub remove_underscores: bool, } diff --git a/src/bindgen/ir/enumeration.rs b/src/bindgen/ir/enumeration.rs index 2b43b33..6907e84 100644 --- a/src/bindgen/ir/enumeration.rs +++ b/src/bindgen/ir/enumeration.rs @@ -236,12 +236,7 @@ impl EnumVariant { config: &Config, ) -> Self { Self::new( - mangle::mangle_name( - &self.name, - generic_values, - config.export.remove_underscores, - config.export.rename_types, - ), + mangle::mangle_name(&self.name, generic_values, &config.export.mangle), self.discriminant, self.body.specialize(generic_values, mappings, config), self.cfg.clone(), @@ -562,8 +557,7 @@ impl Item for Enum { let mangled_path = mangle::mangle_path( &self.path, generic_values, - library.get_config().export.remove_underscores, - library.get_config().export.rename_types, + &library.get_config().export.mangle, ); let monomorph = Enum::new( diff --git a/src/bindgen/ir/opaque.rs b/src/bindgen/ir/opaque.rs index bc49c89..5a9c36a 100644 --- a/src/bindgen/ir/opaque.rs +++ b/src/bindgen/ir/opaque.rs @@ -122,8 +122,7 @@ impl Item for OpaqueItem { let mangled_path = mangle::mangle_path( &self.path, generic_values, - library.get_config().export.remove_underscores, - library.get_config().export.rename_types, + &library.get_config().export.mangle, ); let monomorph = OpaqueItem::new( diff --git a/src/bindgen/ir/structure.rs b/src/bindgen/ir/structure.rs index 6d10734..a4fd27e 100644 --- a/src/bindgen/ir/structure.rs +++ b/src/bindgen/ir/structure.rs @@ -177,12 +177,7 @@ impl Struct { mappings: &[(&Path, &Type)], config: &Config, ) -> Self { - let mangled_path = mangle::mangle_path( - &self.path, - generic_values, - config.export.remove_underscores, - config.export.rename_types, - ); + let mangled_path = mangle::mangle_path(&self.path, generic_values, &config.export.mangle); Struct::new( mangled_path, GenericParams::default(), diff --git a/src/bindgen/ir/typedef.rs b/src/bindgen/ir/typedef.rs index 4026da0..e6ae072 100644 --- a/src/bindgen/ir/typedef.rs +++ b/src/bindgen/ir/typedef.rs @@ -175,8 +175,7 @@ impl Item for Typedef { let mangled_path = mangle::mangle_path( &self.path, generic_values, - library.get_config().export.remove_underscores, - library.get_config().export.rename_types, + &library.get_config().export.mangle, ); let monomorph = Typedef::new( diff --git a/src/bindgen/ir/union.rs b/src/bindgen/ir/union.rs index eb91643..77a4096 100644 --- a/src/bindgen/ir/union.rs +++ b/src/bindgen/ir/union.rs @@ -238,8 +238,7 @@ impl Item for Union { let mangled_path = mangle::mangle_path( &self.path, generic_values, - library.get_config().export.remove_underscores, - library.get_config().export.rename_types, + &library.get_config().export.mangle, ); let monomorph = Union::new( diff --git a/src/bindgen/mangle.rs b/src/bindgen/mangle.rs index 9f17630..8c0602d 100644 --- a/src/bindgen/mangle.rs +++ b/src/bindgen/mangle.rs @@ -2,38 +2,17 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use crate::bindgen::config::MangleConfig; use crate::bindgen::ir::{Path, Type}; use crate::bindgen::rename::IdentifierType; use crate::bindgen::rename::RenameRule; -pub fn mangle_path( - path: &Path, - generic_values: &[Type], - remove_underscores: bool, - rename_types: Option, -) -> Path { - Path::new(mangle_name( - path.name(), - generic_values, - remove_underscores, - rename_types, - )) +pub fn mangle_path(path: &Path, generic_values: &[Type], config: &MangleConfig) -> Path { + Path::new(mangle_name(path.name(), generic_values, config)) } -pub fn mangle_name( - name: &str, - generic_values: &[Type], - remove_underscores: bool, - rename_types: Option, -) -> String { - Mangler::new( - name, - generic_values, - /* last = */ true, - remove_underscores, - rename_types, - ) - .mangle() +pub fn mangle_name(name: &str, generic_values: &[Type], config: &MangleConfig) -> String { + Mangler::new(name, generic_values, /* last = */ true, config).mangle() } enum Separator { @@ -49,8 +28,7 @@ struct Mangler<'a> { generic_values: &'a [Type], output: String, last: bool, - remove_underscores: bool, - rename_types: Option, + config: &'a MangleConfig, } impl<'a> Mangler<'a> { @@ -58,16 +36,14 @@ impl<'a> Mangler<'a> { input: &'a str, generic_values: &'a [Type], last: bool, - remove_underscores: bool, - type_rename_rule: Option, + config: &'a MangleConfig, ) -> Self { Self { input, generic_values, output: String::new(), last, - remove_underscores, - rename_types: type_rename_rule, + config, } } @@ -78,36 +54,35 @@ impl<'a> Mangler<'a> { fn push(&mut self, id: Separator) { let count = id as usize; - let separator = if self.remove_underscores { "" } else { "_" }; + let separator = if self.config.remove_underscores { + "" + } else { + "_" + }; self.output.extend(std::iter::repeat(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, - self.remove_underscores, - self.rename_types, - ) - .mangle(); + let sub_path = + Mangler::new(generic.export_name(), generic.generics(), last, self.config) + .mangle(); self.output.push_str( &self + .config .rename_types - .as_ref() - .unwrap_or(&RenameRule::None) + .unwrap_or(RenameRule::None) .apply(&sub_path, IdentifierType::Type), ); } Type::Primitive(ref primitive) => { self.output.push_str( &self + .config .rename_types - .as_ref() - .unwrap_or(&RenameRule::None) + .unwrap_or(RenameRule::None) .apply(primitive.to_repr_rust(), IdentifierType::Type), ); } @@ -179,7 +154,7 @@ fn generics() { // Foo => Foo_f32 assert_eq!( - mangle_path(&Path::new("Foo"), &vec![float()], false, None), + mangle_path(&Path::new("Foo"), &vec![float()], &MangleConfig::default()), Path::new("Foo_f32") ); @@ -188,21 +163,27 @@ fn generics() { mangle_path( &Path::new("Foo"), &vec![generic_path("Bar", &[float()])], - false, - None, + &MangleConfig::default(), ), Path::new("Foo_Bar_f32") ); // Foo => Foo_Bar assert_eq!( - mangle_path(&Path::new("Foo"), &[path("Bar")], false, None), + mangle_path(&Path::new("Foo"), &[path("Bar")], &MangleConfig::default()), Path::new("Foo_Bar") ); // Foo => FooBar assert_eq!( - mangle_path(&Path::new("Foo"), &[path("Bar")], true, None), + mangle_path( + &Path::new("Foo"), + &[path("Bar")], + &MangleConfig { + remove_underscores: true, + rename_types: None, + } + ), Path::new("FooBar") ); @@ -211,8 +192,10 @@ fn generics() { mangle_path( &Path::new("Foo"), &vec![generic_path("Bar", &[float()])], - true, - Some(PascalCase), + &MangleConfig { + remove_underscores: true, + rename_types: Some(PascalCase), + }, ), Path::new("FooBarF32") ); @@ -222,8 +205,10 @@ fn generics() { mangle_path( &Path::new("Foo"), &vec![generic_path("Bar", &[c_char()])], - true, - Some(PascalCase), + &MangleConfig { + remove_underscores: true, + rename_types: Some(PascalCase), + }, ), Path::new("FooBarCChar") ); @@ -233,8 +218,7 @@ fn generics() { mangle_path( &Path::new("Foo"), &[generic_path("Bar", &[path("T")])], - false, - None, + &MangleConfig::default(), ), Path::new("Foo_Bar_T") ); @@ -244,8 +228,7 @@ fn generics() { mangle_path( &Path::new("Foo"), &[generic_path("Bar", &[path("T")]), path("E")], - false, - None, + &MangleConfig::default(), ), Path::new("Foo_Bar_T_____E") ); @@ -258,8 +241,7 @@ fn generics() { generic_path("Bar", &[path("T")]), generic_path("Bar", &[path("E")]), ], - false, - None, + &MangleConfig::default(), ), Path::new("Foo_Bar_T_____Bar_E") ); @@ -269,8 +251,10 @@ fn generics() { mangle_path( &Path::new("Foo"), &[generic_path("Bar", &[path("T")]), path("E")], - true, - Some(PascalCase), + &MangleConfig { + remove_underscores: true, + rename_types: Some(PascalCase), + }, ), Path::new("FooBarTE") ); @@ -283,8 +267,10 @@ fn generics() { generic_path("Bar", &[path("T")]), generic_path("Bar", &[path("E")]), ], - true, - Some(PascalCase), + &MangleConfig { + remove_underscores: true, + rename_types: Some(PascalCase), + }, ), Path::new("FooBarTBarE") ); diff --git a/template.toml b/template.toml index 01e77fc..0e515fd 100644 --- a/template.toml +++ b/template.toml @@ -68,6 +68,7 @@ renaming_overrides_prefixing = false [export.body] +[export.mangle] [fn] diff --git a/tests/expectations/both/mangle.c b/tests/expectations/both/mangle.c new file mode 100644 index 0000000..6dd670e --- /dev/null +++ b/tests/expectations/both/mangle.c @@ -0,0 +1,12 @@ +#include +#include +#include +#include + +typedef struct FooU8 { + uint8_t a; +} FooU8; + +typedef FooU8 Boo; + +void root(Boo x); diff --git a/tests/expectations/both/mangle.compat.c b/tests/expectations/both/mangle.compat.c new file mode 100644 index 0000000..841b145 --- /dev/null +++ b/tests/expectations/both/mangle.compat.c @@ -0,0 +1,20 @@ +#include +#include +#include +#include + +typedef struct FooU8 { + uint8_t a; +} FooU8; + +typedef FooU8 Boo; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(Boo x); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/mangle.c b/tests/expectations/mangle.c new file mode 100644 index 0000000..4da7082 --- /dev/null +++ b/tests/expectations/mangle.c @@ -0,0 +1,12 @@ +#include +#include +#include +#include + +typedef struct { + uint8_t a; +} FooU8; + +typedef FooU8 Boo; + +void root(Boo x); diff --git a/tests/expectations/mangle.compat.c b/tests/expectations/mangle.compat.c new file mode 100644 index 0000000..fe1a74d --- /dev/null +++ b/tests/expectations/mangle.compat.c @@ -0,0 +1,20 @@ +#include +#include +#include +#include + +typedef struct { + uint8_t a; +} FooU8; + +typedef FooU8 Boo; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(Boo x); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/mangle.cpp b/tests/expectations/mangle.cpp new file mode 100644 index 0000000..91bdbcf --- /dev/null +++ b/tests/expectations/mangle.cpp @@ -0,0 +1,17 @@ +#include +#include +#include +#include + +template +struct Foo { + T a; +}; + +using Boo = Foo; + +extern "C" { + +void root(Boo x); + +} // extern "C" diff --git a/tests/expectations/tag/mangle.c b/tests/expectations/tag/mangle.c new file mode 100644 index 0000000..6165110 --- /dev/null +++ b/tests/expectations/tag/mangle.c @@ -0,0 +1,12 @@ +#include +#include +#include +#include + +struct FooU8 { + uint8_t a; +}; + +typedef struct FooU8 Boo; + +void root(Boo x); diff --git a/tests/expectations/tag/mangle.compat.c b/tests/expectations/tag/mangle.compat.c new file mode 100644 index 0000000..3b94dfa --- /dev/null +++ b/tests/expectations/tag/mangle.compat.c @@ -0,0 +1,20 @@ +#include +#include +#include +#include + +struct FooU8 { + uint8_t a; +}; + +typedef struct FooU8 Boo; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(Boo x); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/rust/mangle.rs b/tests/rust/mangle.rs new file mode 100644 index 0000000..b4aa46d --- /dev/null +++ b/tests/rust/mangle.rs @@ -0,0 +1,11 @@ +#[repr(C)] +pub struct Foo { + a: T, +} + +pub type Boo = Foo; + +#[no_mangle] +pub extern "C" fn root( + x: Boo, +) { } diff --git a/tests/rust/mangle.toml b/tests/rust/mangle.toml new file mode 100644 index 0000000..a5d6b65 --- /dev/null +++ b/tests/rust/mangle.toml @@ -0,0 +1,3 @@ +[export.mangle] +remove_underscores = true +rename_types = "PascalCase"