Skip to content

Commit e08782d

Browse files
committed
Improve mangled name deduplication
1 parent fdaa397 commit e08782d

2 files changed

Lines changed: 74 additions & 32 deletions

File tree

src/compiler_top.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,11 @@ impl Linker {
9999
}
100100

101101
pub fn add_file(&mut self, path: &Path) {
102-
assert!(path.is_file());
102+
assert!(
103+
path.is_file(),
104+
"Path is not a file??? {}",
105+
path.to_string_lossy()
106+
);
103107
match UniqueFileID::from_path(path, path.to_string_lossy().to_string()) {
104108
Ok(file_identifier) => {
105109
self.add_or_update_file_from_disk(file_identifier);

src/instantiation/instantiator.rs

Lines changed: 69 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ use crate::{
2121
#[derive(Debug, Default)]
2222
pub struct Instantiator {
2323
cache: BTreeMap<Rc<ConcreteGlobalReference<ModuleUUID>>, InstantiatorCacheElem>,
24+
/// Some mangled names may map to the same mangled name: `MyMod#(STR: "%")` and `MyMod#(STR: "/")` map to `MyMod_STR`.
25+
mangled_name_deconflicter: HashSet<String>,
2426
stack: Vec<Rc<ConcreteGlobalReference<ModuleUUID>>>,
2527
pub tops: Vec<ConcreteGlobalReference<ModuleUUID>>,
2628
}
@@ -46,13 +48,55 @@ impl Instantiator {
4648
pub fn new() -> Self {
4749
Self {
4850
cache: BTreeMap::new(),
51+
mangled_name_deconflicter: HashSet::new(),
4952
stack: Vec::new(),
5053
tops: Vec::new(),
5154
}
5255
}
5356

5457
pub fn clear_instances(&mut self) {
55-
self.cache.clear()
58+
self.cache.clear();
59+
self.mangled_name_deconflicter.clear();
60+
}
61+
62+
/// Mangle the module name for use in code generation
63+
fn mangle_name(&mut self, name: &str) -> String {
64+
let mut result = String::with_capacity(name.len());
65+
66+
let mut last_was_underscore = false;
67+
for c in name.chars() {
68+
if c.is_alphanumeric() {
69+
result.push(c);
70+
last_was_underscore = false;
71+
} else if c == '-' {
72+
result.push('N');
73+
last_was_underscore = false;
74+
} else {
75+
// Max 1 underscore at a time, as some tools don't like it (#128)
76+
if !last_was_underscore {
77+
result.push('_');
78+
}
79+
last_was_underscore = true;
80+
}
81+
}
82+
result = result.trim_matches('_').to_owned();
83+
84+
if self.mangled_name_deconflicter.insert(result.clone()) {
85+
// Try the non-deduplicated version first
86+
result
87+
} else {
88+
let mut dedup_idx = 2;
89+
loop {
90+
let deduplicated_name = format!("{result}_Dedup_{dedup_idx}");
91+
if self
92+
.mangled_name_deconflicter
93+
.insert(deduplicated_name.clone())
94+
{
95+
return deduplicated_name;
96+
} // Else, this deduplicated name is already taken. Try the next one
97+
dedup_idx += 1;
98+
}
99+
}
56100
}
57101

58102
pub fn display_cur_stack(&self, globals: &LinkerGlobals) -> impl Display {
@@ -109,7 +153,16 @@ impl Instantiator {
109153
let name = global_ref.display(globals).to_string();
110154

111155
let result = crate::debug::debug_context("instantiating", name, || {
112-
match start_instantiation(globals, linker_files, global_ref.clone()) {
156+
let name = global_ref.display(globals).to_string();
157+
let mangled_name = self.mangle_name(&name);
158+
159+
match start_instantiation(
160+
globals,
161+
linker_files,
162+
global_ref.clone(),
163+
name,
164+
mangled_name,
165+
) {
113166
Ok(mut context) => {
114167
loop {
115168
let submodules_to_instantiate = context.typecheck_step();
@@ -208,6 +261,7 @@ impl Executed {
208261
md: &'l Module,
209262
global_ref: Rc<ConcreteGlobalReference<ModuleUUID>>,
210263
name: String,
264+
mangled_name: String,
211265
) -> ModuleTypingContext<'l> {
212266
let errors = ErrorCollector::new_empty(md.link_info.span, linker_files);
213267
if let Err(err) = self.execution_status {
@@ -222,7 +276,7 @@ impl Executed {
222276
&errors,
223277
);
224278
ModuleTypingContext {
225-
mangled_name: mangle_name(&name),
279+
mangled_name,
226280
name,
227281
global_ref,
228282
clocks,
@@ -237,39 +291,16 @@ impl Executed {
237291
}
238292
}
239293

240-
/// Mangle the module name for use in code generation
241-
fn mangle_name(str: &str) -> String {
242-
let mut result = String::with_capacity(str.len());
243-
244-
let mut last_was_underscore = false;
245-
for c in str.chars() {
246-
if c.is_alphanumeric() {
247-
result.push(c);
248-
last_was_underscore = false;
249-
} else if c == '-' {
250-
result.push('N');
251-
last_was_underscore = false;
252-
} else {
253-
// Max 1 underscore at a time, as some tools don't like it (#128)
254-
if !last_was_underscore {
255-
result.push('_');
256-
}
257-
last_was_underscore = true;
258-
}
259-
}
260-
result.trim_matches('_').to_owned()
261-
}
262-
263294
#[allow(clippy::result_large_err)]
264295
fn start_instantiation<'l>(
265296
linker_globals: &'l LinkerGlobals,
266297
linker_files: &'l LinkerFiles,
267298
global_ref: Rc<ConcreteGlobalReference<ModuleUUID>>,
299+
name: String,
300+
mangled_name: String,
268301
) -> Result<ModuleTypingSuperContext<'l>, InstantiatedModule> {
269302
let md = &linker_globals.modules[global_ref.id];
270303

271-
let name = global_ref.display(linker_globals).to_string();
272-
273304
// Don't instantiate modules that already errored. Otherwise instantiator may crash
274305
if md.link_info.errors.did_error {
275306
let errors = ErrorCollector::new_empty(md.link_info.span, linker_files);
@@ -278,7 +309,7 @@ fn start_instantiation<'l>(
278309
errors.warn(md.link_info.name_span, msg);
279310
return Err(InstantiatedModule {
280311
global_ref,
281-
mangled_name: mangle_name(&name),
312+
mangled_name,
282313
name,
283314
errors: errors.into_storage(),
284315
clocks: Default::default(),
@@ -318,7 +349,7 @@ fn start_instantiation<'l>(
318349

319350
return Err(InstantiatedModule {
320351
global_ref,
321-
mangled_name: mangle_name(&name),
352+
mangled_name,
322353
name,
323354
errors: errors.into_storage(),
324355
clocks: Default::default(),
@@ -335,7 +366,14 @@ fn start_instantiation<'l>(
335366
debug!("Executing {name}");
336367
let exec = execute::execute(&md.link_info, linker_globals, &global_ref.template_args);
337368

338-
let typed = exec.into_module_typing_context(linker_globals, linker_files, md, global_ref, name);
369+
let typed = exec.into_module_typing_context(
370+
linker_globals,
371+
linker_files,
372+
md,
373+
global_ref,
374+
name,
375+
mangled_name,
376+
);
339377
let name = &typed.name;
340378

341379
if typed.errors.did_error() {

0 commit comments

Comments
 (0)