Skip to content

Commit 003a439

Browse files
committed
refactor: improve template handling and registration logic
1 parent 8e8a7ab commit 003a439

File tree

1 file changed

+51
-10
lines changed

1 file changed

+51
-10
lines changed

src/dwarf2cpp/visitor.py

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ def __init__(self, context: DWARFContext, base_dir: str):
9595
self._cache = {}
9696
self._param_names: dict[str, list[str]] = {}
9797
self._functions: dict[str, list[Function]] = defaultdict(list)
98+
self._templates: dict[str | int, dict[int, list[Template]]] = defaultdict(lambda: defaultdict(list))
9899

99100
@property
100101
def files(self) -> Generator[tuple[str, dict[int, list[Object]]]]:
@@ -106,11 +107,11 @@ def files(self) -> Generator[tuple[str, dict[int, list[Object]]]]:
106107
List of files
107108
"""
108109
for i, cu in (
109-
pbar := tqdm(
110-
enumerate(self.context.compile_units),
111-
total=self.context.num_compile_units,
112-
bar_format="[{n_fmt}/{total_fmt}] {desc}",
113-
)
110+
pbar := tqdm(
111+
enumerate(self.context.compile_units),
112+
total=self.context.num_compile_units,
113+
bar_format="[{n_fmt}/{total_fmt}] {desc}",
114+
)
114115
):
115116
cu_die = cu.unit_die
116117
name = cu_die.short_name
@@ -191,7 +192,9 @@ def visit_compile_unit(self, die: DWARFDie):
191192
self.visit(child)
192193
if child.offset in self._cache:
193194
if template := self._cache[child.offset].template:
194-
self._add(decl_file, decl_line, template)
195+
if template := self._register_template(decl_file, decl_line, template):
196+
self._add(decl_file, decl_line, template)
197+
195198
self._add(decl_file, decl_line, self._cache[child.offset])
196199

197200
elif child.tag in {
@@ -265,7 +268,7 @@ def visit_namespace(self, die: DWARFDie) -> None:
265268
member.parent = namespace
266269
if template := member.template:
267270
template.parent = namespace
268-
if template not in self._files[decl_file][decl_line]:
271+
if template := self._register_template(decl_file, decl_line, template):
269272
self._add(decl_file, decl_line, template)
270273

271274
self._add(decl_file, decl_line, member)
@@ -604,11 +607,33 @@ def visit_imported_declaration(self, die: DWARFDie) -> None:
604607
self._cache[die.offset] = imported_decl
605608

606609
def visit_template_type_parameter(self, die: DWARFDie) -> None:
607-
self._cache[die.offset] = TemplateParameter(die.short_name, TemplateParameterKind.TYPE)
610+
param = TemplateParameter(die.short_name, TemplateParameterKind.TYPE)
611+
612+
# A template type parameter entry has a DW_AT_type attribute
613+
# describing the actual type by which the formal is replaced.
614+
if ty := die.find("DW_AT_type"):
615+
param.arg = get_qualified_type(ty.as_referenced_die())
616+
else:
617+
param.arg = "void"
618+
619+
for attribute in die.attributes:
620+
if attribute.name in {"DW_AT_name", "DW_AT_type"}:
621+
continue
622+
623+
match attribute.name:
624+
case "DW_AT_default_value":
625+
param.default = param.arg
626+
case _:
627+
raise ValueError(f"Unhandled attribute {attribute.name}")
628+
629+
for child in die.children:
630+
raise ValueError(f"Unhandled child tag {child.tag}")
631+
632+
self._cache[die.offset] = param
608633

609634
def visit_template_value_parameter(self, die: DWARFDie) -> None:
610635
ty = get_qualified_type(die.find("DW_AT_type").as_referenced_die())
611-
self._cache[die.offset] = TemplateParameter(die.short_name, TemplateParameterKind.CONSTANT, value_type=ty)
636+
self._cache[die.offset] = TemplateParameter(die.short_name, TemplateParameterKind.CONSTANT, type=ty)
612637

613638
def visit_GNU_template_parameter_pack(self, die: DWARFDie) -> None:
614639
self._cache[die.offset] = TemplateParameter(die.short_name, TemplateParameterKind.PACK)
@@ -630,6 +655,22 @@ def _add(self, filepath: str, lineno: int, obj: Object) -> None:
630655

631656
lines.append(obj)
632657

658+
def _register_template(self, key: str | int, lineno: int, template: Template) -> Template | None:
659+
templates = self._templates[key][lineno]
660+
661+
# make a copy for template declaration
662+
template = copy.copy(template)
663+
for parameter in template.parameters:
664+
parameter.arg = None # declaration must not have type replacement
665+
666+
# try to merge with existing templates
667+
for t in templates:
668+
if t.merge(template):
669+
return None
670+
671+
templates.append(template)
672+
return template
673+
633674
def _handle_attribute(self, die: DWARFDie) -> None:
634675
if not die.decl_file or not die.decl_line or not die.short_name:
635676
return
@@ -788,7 +829,7 @@ def _handle_struct(self, die: DWARFDie, struct: Struct) -> None:
788829
if template.access is None:
789830
template.access = access
790831

791-
if template not in lines:
832+
if template := self._register_template(die.offset, child.decl_line, template):
792833
lines.append(template)
793834

794835
lines.append(member)

0 commit comments

Comments
 (0)