Skip to content

Commit 7ab9299

Browse files
add a build option to shorten mangled name
(refs: veryl-lang#1608)
1 parent da47b3f commit 7ab9299

File tree

10 files changed

+163
-40
lines changed

10 files changed

+163
-40
lines changed

crates/analyzer/src/reference_table.rs

-1
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,6 @@ impl ReferenceTable {
277277

278278
let table = symbol.found.generic_table(&path.arguments);
279279
let map = vec![GenericMap {
280-
name: "".to_string(),
281280
id: None,
282281
map: table,
283282
}];

crates/analyzer/src/symbol.rs

+42-12
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ impl DocComment {
5353

5454
#[derive(Clone, Debug, Default)]
5555
pub struct GenericMap {
56-
pub name: String,
5756
pub id: Option<SymbolId>,
5857
pub map: HashMap<StrId, GenericSymbolPath>,
5958
}
@@ -62,6 +61,46 @@ impl GenericMap {
6261
pub fn generic(&self) -> bool {
6362
!self.map.is_empty()
6463
}
64+
65+
pub fn name(&self, include_namspace_prefix: bool, shoten_name: bool) -> String {
66+
let symbol = symbol_table::get(self.id.unwrap()).unwrap();
67+
if let SymbolKind::GenericInstance(x) = symbol.kind {
68+
let base = symbol_table::get(x.base).unwrap();
69+
if shoten_name {
70+
format!(
71+
"{}__{}__{}",
72+
self.get_name_prefix(&base, include_namspace_prefix),
73+
base.token,
74+
x.index
75+
)
76+
} else {
77+
format!(
78+
"{}{}",
79+
self.get_name_prefix(&base, include_namspace_prefix),
80+
symbol.token
81+
)
82+
}
83+
} else {
84+
format!(
85+
"{}{}",
86+
self.get_name_prefix(&symbol, include_namspace_prefix),
87+
symbol.token
88+
)
89+
}
90+
}
91+
92+
fn get_name_prefix(&self, symbol: &Symbol, include_namspace_prefix: bool) -> String {
93+
if include_namspace_prefix
94+
&& matches!(
95+
symbol.kind,
96+
SymbolKind::Module(_) | SymbolKind::Interface(_) | SymbolKind::Package(_)
97+
)
98+
{
99+
format!("{}_", symbol.namespace)
100+
} else {
101+
"".to_string()
102+
}
103+
}
65104
}
66105

67106
#[derive(Debug, Clone)]
@@ -277,15 +316,6 @@ impl Symbol {
277316
pub fn generic_maps(&self) -> Vec<GenericMap> {
278317
let mut ret = Vec::new();
279318

280-
let prefix = if matches!(
281-
self.kind,
282-
SymbolKind::Module(_) | SymbolKind::Interface(_) | SymbolKind::Package(_)
283-
) {
284-
format!("{}_", self.namespace)
285-
} else {
286-
"".to_string()
287-
};
288-
289319
let generic_instances = if matches!(self.kind, SymbolKind::GenericInstance(_)) {
290320
&vec![self.id]
291321
} else {
@@ -298,9 +328,8 @@ impl Symbol {
298328
} else {
299329
HashMap::default()
300330
};
301-
let name = format!("{}{}", prefix, symbol.token.text);
331+
302332
ret.push(GenericMap {
303-
name,
304333
id: Some(symbol.id),
305334
map,
306335
});
@@ -2074,6 +2103,7 @@ pub struct GenericParameterProperty {
20742103
pub struct GenericInstanceProperty {
20752104
pub base: SymbolId,
20762105
pub arguments: Vec<GenericSymbolPath>,
2106+
pub index: usize,
20772107
}
20782108

20792109
#[derive(Debug, Clone)]

crates/analyzer/src/symbol_path.rs

+1
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ impl GenericSymbol {
294294
let property = GenericInstanceProperty {
295295
base: base.id,
296296
arguments: self.arguments.clone(),
297+
index: base.generic_instances.len(),
297298
};
298299
let kind = SymbolKind::GenericInstance(property);
299300
let token = &self.base;

crates/emitter/src/emitter.rs

+59-23
Original file line numberDiff line numberDiff line change
@@ -1763,16 +1763,17 @@ impl Emitter {
17631763
}
17641764
}
17651765

1766-
fn get_generic_declaration_name(&self, generic_name: &str) -> String {
1766+
fn get_generic_declaration_name(&self, generic_map: &GenericMap) -> String {
1767+
let name = generic_map.name(true, self.build_opt.shorten_mangled_name);
17671768
let ret = if self.build_opt.omit_project_prefix {
17681769
let project_name = format!("{}_", self.project_name.unwrap());
1769-
if let Some(x) = generic_name.strip_prefix(&project_name) {
1770+
if let Some(x) = name.strip_prefix(&project_name) {
17701771
x
17711772
} else {
1772-
generic_name
1773+
&name
17731774
}
17741775
} else {
1775-
generic_name
1776+
&name
17761777
};
17771778

17781779
ret.replace("$std_", "__std_")
@@ -4159,7 +4160,8 @@ impl VerylWalker for Emitter {
41594160
self.str("}");
41604161
self.space(1);
41614162
if map.generic() {
4162-
self.str(&map.name.clone());
4163+
let name = map.name(true, self.build_opt.shorten_mangled_name);
4164+
self.token(&arg.identifier.identifier_token.replace(&name));
41634165
} else {
41644166
self.identifier(&arg.identifier);
41654167
}
@@ -4795,7 +4797,8 @@ impl VerylWalker for Emitter {
47954797
}
47964798
self.space(1);
47974799
if map.generic() {
4798-
self.str(&map.name.clone());
4800+
let name = map.name(true, self.build_opt.shorten_mangled_name);
4801+
self.token(&arg.identifier.identifier_token.replace(&name));
47994802
} else {
48004803
self.identifier(&arg.identifier);
48014804
}
@@ -4873,7 +4876,7 @@ impl VerylWalker for Emitter {
48734876
self.module(&arg.module);
48744877
self.space(1);
48754878
if map.generic() {
4876-
let name = self.get_generic_declaration_name(&map.name);
4879+
let name = self.get_generic_declaration_name(map);
48774880
self.token(&arg.identifier.identifier_token.replace(&name));
48784881
} else {
48794882
let context: SymbolContext = self.into();
@@ -4956,7 +4959,7 @@ impl VerylWalker for Emitter {
49564959
self.interface(&arg.interface);
49574960
self.space(1);
49584961
if map.generic() {
4959-
let name = self.get_generic_declaration_name(&map.name);
4962+
let name = self.get_generic_declaration_name(map);
49604963
self.token(&arg.identifier.identifier_token.replace(&name));
49614964
} else {
49624965
let context: SymbolContext = self.into();
@@ -5157,7 +5160,7 @@ impl VerylWalker for Emitter {
51575160
self.package(&arg.package);
51585161
self.space(1);
51595162
if map.generic() {
5160-
let name = self.get_generic_declaration_name(&map.name);
5163+
let name = self.get_generic_declaration_name(map);
51615164
self.token(&arg.identifier.identifier_token.replace(&name));
51625165
} else {
51635166
let context: SymbolContext = self.into();
@@ -5398,21 +5401,30 @@ fn namespace_string(namespace: &Namespace, context: &SymbolContext) -> String {
53985401
} else {
53995402
let symbol_path = SymbolPath::new(&[*path]);
54005403
if let Ok(ref symbol) = symbol_table::resolve((&symbol_path, &resolve_namespace)) {
5401-
let separator = match symbol.found.kind {
5402-
SymbolKind::Package(_) => "::",
5403-
SymbolKind::GenericInstance(ref x) => {
5404-
let symbol = symbol_table::get(x.base).unwrap();
5405-
match symbol.kind {
5406-
SymbolKind::Interface(_) => ".",
5407-
_ => "::",
5408-
}
5404+
let text = if let SymbolKind::GenericInstance(ref x) = symbol.found.kind {
5405+
let base = symbol_table::get(x.base).unwrap();
5406+
let separator =
5407+
namespace_separator(&base, context.in_direction_modport, in_sv_namespace);
5408+
if context.build_opt.shorten_mangled_name {
5409+
let name = symbol
5410+
.found
5411+
.generic_maps()
5412+
.first()
5413+
.map(|x| x.name(false, true))
5414+
.unwrap();
5415+
format!("{}{}", name, separator)
5416+
} else {
5417+
format!("{}{}", path, separator)
54095418
}
5410-
SymbolKind::Interface(_) => ".",
5411-
SymbolKind::SystemVerilog if context.in_direction_modport => ".",
5412-
_ if in_sv_namespace => "::",
5413-
_ => "_",
5419+
} else {
5420+
let separator = namespace_separator(
5421+
&symbol.found,
5422+
context.in_direction_modport,
5423+
in_sv_namespace,
5424+
);
5425+
format!("{}{}", path, separator)
54145426
};
5415-
ret.push_str(&format!("{}{}", path, separator));
5427+
ret.push_str(&text);
54165428
} else {
54175429
return format!("{}", namespace);
54185430
}
@@ -5424,6 +5436,21 @@ fn namespace_string(namespace: &Namespace, context: &SymbolContext) -> String {
54245436
ret.replace("$std_", "__std_")
54255437
}
54265438

5439+
fn namespace_separator(
5440+
symbol: &Symbol,
5441+
in_direction_modport: bool,
5442+
in_sv_namespace: bool,
5443+
) -> String {
5444+
let separator = match symbol.kind {
5445+
SymbolKind::Package(_) => "::",
5446+
SymbolKind::Interface(_) => ".",
5447+
SymbolKind::SystemVerilog if in_direction_modport => ".",
5448+
_ if in_sv_namespace => "::",
5449+
_ => "_",
5450+
};
5451+
separator.to_string()
5452+
}
5453+
54275454
pub fn symbol_string(token: &VerylToken, symbol: &Symbol, context: &SymbolContext) -> String {
54285455
let mut ret = String::new();
54295456
let namespace = namespace_table::get(token.token.id).unwrap();
@@ -5486,7 +5513,16 @@ pub fn symbol_string(token: &VerylToken, symbol: &Symbol, context: &SymbolContex
54865513
if !visible | top_level {
54875514
ret.push_str(&namespace_string(&symbol.namespace, context));
54885515
}
5489-
ret.push_str(&token_text);
5516+
if context.build_opt.shorten_mangled_name {
5517+
let name = symbol
5518+
.generic_maps()
5519+
.first()
5520+
.map(|x| x.name(true, true))
5521+
.unwrap();
5522+
ret.push_str(&name);
5523+
} else {
5524+
ret.push_str(&token_text);
5525+
}
54905526
}
54915527
SymbolKind::GenericParameter(_)
54925528
| SymbolKind::ProtoModule(_)

crates/emitter/src/tests.rs

+55
Original file line numberDiff line numberDiff line change
@@ -1468,3 +1468,58 @@ endmodule
14681468
println!("ret\n{}\nexp\n{}", ret, expect);
14691469
assert_eq!(ret, expect);
14701470
}
1471+
1472+
#[test]
1473+
fn shorten_mangled_name() {
1474+
let code = r#"
1475+
package PkgA::<
1476+
A: u32,
1477+
B: u32,
1478+
C: u32,
1479+
D: u32,
1480+
> {
1481+
const V: u32 = A + B + C + D;
1482+
}
1483+
module ModuleA {
1484+
function FuncA::<V: u32>() -> u32 {
1485+
return V;
1486+
}
1487+
let _a: u32 = FuncA::<PkgA::<0, 1, 2, 3>::V>();
1488+
let _b: u32 = FuncA::<PkgA::<0, 1, 2, 3>::V>();
1489+
let _c: u32 = FuncA::<PkgA::<4, 5, 6, 7>::V>();
1490+
}
1491+
"#;
1492+
1493+
let expect = r#"package prj___PkgA__0;
1494+
localparam int unsigned V = 0 + 1 + 2 + 3;
1495+
endpackage
1496+
package prj___PkgA__1;
1497+
localparam int unsigned V = 4 + 5 + 6 + 7;
1498+
endpackage
1499+
module prj_ModuleA;
1500+
function automatic int unsigned __FuncA__0() ;
1501+
return prj___PkgA__0::V;
1502+
endfunction
1503+
function automatic int unsigned __FuncA__1() ;
1504+
return prj___PkgA__1::V;
1505+
endfunction
1506+
int unsigned _a; always_comb _a = __FuncA__0();
1507+
int unsigned _b; always_comb _b = __FuncA__0();
1508+
int unsigned _c; always_comb _c = __FuncA__1();
1509+
endmodule
1510+
//# sourceMappingURL=test.sv.map
1511+
"#;
1512+
1513+
let mut metadata: Metadata =
1514+
toml::from_str(&Metadata::create_default_toml("prj").unwrap()).unwrap();
1515+
metadata.build.shorten_mangled_name = true;
1516+
1517+
let ret = if cfg!(windows) {
1518+
emit(&metadata, code).replace("\r\n", "\n")
1519+
} else {
1520+
emit(&metadata, code)
1521+
};
1522+
1523+
println!("ret\n{}\nexp\n{}", ret, expect);
1524+
assert_eq!(ret, expect);
1525+
}

crates/metadata/src/build.rs

+2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ pub struct Build {
4242
pub instance_total_limit: usize,
4343
#[serde(default)]
4444
pub flatten_array_interface: bool,
45+
#[serde(default)]
46+
pub shorten_mangled_name: bool,
4547
}
4648

4749
fn default_source() -> PathBuf {

testcases/map/54_generic_function.sv.map

+1-1
Original file line numberDiff line numberDiff line change

0 commit comments

Comments
 (0)