Skip to content

Commit c14628b

Browse files
committed
refactor: replace get_qualified_type with _resolve_type for improved type resolution
1 parent 69b4fc7 commit c14628b

File tree

1 file changed

+42
-31
lines changed

1 file changed

+42
-31
lines changed

src/dwarf2cpp/visitor.py

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import copy
2-
import functools
32
import logging
43
import posixpath
54
import struct
@@ -38,23 +37,6 @@
3837
logger = logging.getLogger("dwarf2cpp")
3938

4039

41-
@functools.cache
42-
def get_qualified_type(die: DWARFDie, split=False) -> str | tuple[str, str]:
43-
printer = DWARFTypePrinter()
44-
if not split:
45-
printer.append_qualified_name(die)
46-
ty = str(printer).strip()
47-
return ty
48-
else:
49-
inner = printer.append_qualified_name_before(die)
50-
before = str(printer).strip()
51-
52-
printer = DWARFTypePrinter()
53-
printer.append_unqualified_name_after(die, inner)
54-
after = str(printer).strip()
55-
return before, after
56-
57-
5840
def float_to_str(value: float) -> str:
5941
s = f"{value:.7f}".rstrip("0")
6042
if s[-1] == ".":
@@ -82,6 +64,7 @@ def __init__(self, context: DWARFContext, base_dir: str):
8264
self._param_names: dict[str, list[str]] = {}
8365
self._functions: dict[str, list[Function]] = defaultdict(list)
8466
self._templates: dict[str | int, dict[int, list[Template]]] = defaultdict(lambda: defaultdict(list))
67+
self._types = {}
8568

8669
@property
8770
def files(self) -> Generator[tuple[str, dict[int, list[Object]]], None, None]:
@@ -149,6 +132,12 @@ def visit(self, die: DWARFDie) -> None:
149132
func(die)
150133

151134
def visit_compile_unit(self, die: DWARFDie):
135+
self._handle_unit(die)
136+
137+
def visit_type_unit(self, die: DWARFDie):
138+
self._handle_unit(die)
139+
140+
def _handle_unit(self, die: DWARFDie):
152141
"""Visit a compile unit"""
153142
for child in die.children:
154143
if child.tag == "DW_TAG_namespace":
@@ -281,7 +270,7 @@ def visit_typedef(self, die: DWARFDie) -> None:
281270
value.is_implicit = True
282271
typedef.value = value
283272
else:
284-
typedef.value = get_qualified_type(type_die)
273+
typedef.value = self._resolve_type(type_die)
285274

286275
for attribute in die.attributes:
287276
if attribute.name in {
@@ -324,7 +313,7 @@ def visit_enumeration_type(self, die: DWARFDie) -> None:
324313

325314
match attribute.name:
326315
case "DW_AT_type":
327-
enum.base = get_qualified_type(attribute.value.as_referenced_die().resolve_type_unit_reference())
316+
enum.base = self._resolve_type(attribute.value.as_referenced_die())
328317
case "DW_AT_enum_class":
329318
enum.is_class = True
330319
case _:
@@ -416,7 +405,7 @@ def visit_subprogram(self, die: DWARFDie) -> None:
416405
name = die.short_name
417406
returns = "void"
418407
if ret := die.find("DW_AT_type"):
419-
returns = get_qualified_type(ret.as_referenced_die().resolve_type_unit_reference())
408+
returns = self._resolve_type(ret.as_referenced_die())
420409

421410
function = Function(name=name, returns=returns)
422411

@@ -505,9 +494,7 @@ def visit_subprogram(self, die: DWARFDie) -> None:
505494

506495
parameter = Parameter(
507496
name=child.short_name,
508-
type=get_qualified_type(
509-
child.find("DW_AT_type").as_referenced_die().resolve_type_unit_reference(), split=True
510-
),
497+
type=self._resolve_type(child.find("DW_AT_type").as_referenced_die(), split=True),
511498
kind=ParameterKind.POSITIONAL,
512499
)
513500
function.parameters.append(parameter)
@@ -585,7 +572,7 @@ def visit_imported_declaration(self, die: DWARFDie) -> None:
585572
if import_die.tag == "DW_TAG_namespace":
586573
imported_decl = ImportedDeclaration(name=die.short_name, import_=import_)
587574
else:
588-
imported_decl = ImportedDeclaration(name="", import_=get_qualified_type(import_die))
575+
imported_decl = ImportedDeclaration(name="", import_=self._resolve_type(import_die))
589576

590577
assert imported_decl.import_ is not None, "Expected valid import."
591578

@@ -608,7 +595,7 @@ def visit_template_type_parameter(self, die: DWARFDie) -> None:
608595
# A template type parameter entry has a DW_AT_type attribute
609596
# describing the actual type by which the formal is replaced.
610597
if ty := die.find("DW_AT_type"):
611-
param.type = get_qualified_type(ty.as_referenced_die().resolve_type_unit_reference())
598+
param.type = self._resolve_type(ty.as_referenced_die())
612599
else:
613600
param.type = "void"
614601

@@ -629,7 +616,7 @@ def visit_template_type_parameter(self, die: DWARFDie) -> None:
629616

630617
def visit_template_value_parameter(self, die: DWARFDie) -> None:
631618
param = TemplateParameter(TemplateParameterKind.CONSTANT, name=die.short_name)
632-
param.type = get_qualified_type(die.find("DW_AT_type").as_referenced_die().resolve_type_unit_reference())
619+
param.type = self._resolve_type(die.find("DW_AT_type").as_referenced_die())
633620

634621
if value := die.find("DW_AT_const_value"):
635622
param.value = value.as_constant()
@@ -759,7 +746,7 @@ def _handle_attribute(self, die: DWARFDie) -> None:
759746
value.is_implicit = True
760747
variable.type = value
761748
else:
762-
variable.type = get_qualified_type(ty, split=True)
749+
variable.type = self._resolve_type(ty, split=True)
763750

764751
for attribute in die.attributes:
765752
if attribute.name in {
@@ -922,9 +909,7 @@ def _handle_struct(self, die: DWARFDie, struct: Struct) -> None:
922909
match child.tag:
923910
case "DW_TAG_inheritance":
924911
inherit_access = None
925-
base = get_qualified_type(
926-
child.find("DW_AT_type").as_referenced_die().resolve_type_unit_reference()
927-
)
912+
base = self._resolve_type(child.find("DW_AT_type").as_referenced_die())
928913
for attribute in child.attributes:
929914
if attribute.name in {
930915
"DW_AT_type",
@@ -966,3 +951,29 @@ def _get(self, die: DWARFDie):
966951
def _set(self, die: DWARFDie, obj) -> None:
967952
assert die.offset not in self._objects[die.unit.is_type_unit]
968953
self._objects[die.unit.is_type_unit][die.offset] = obj
954+
955+
def _resolve_type(self, die: DWARFDie, split=False) -> str | tuple[str, str]:
956+
die = die.resolve_type_unit_reference()
957+
if die.unit.is_type_unit:
958+
# TODO: visit type unit
959+
pass
960+
961+
key = (die.unit.is_type_unit, die.offset, split)
962+
if key in self._types:
963+
return self._types[key]
964+
965+
printer = DWARFTypePrinter()
966+
if not split:
967+
printer.append_qualified_name(die)
968+
ty = str(printer).strip()
969+
self._types[key] = ty
970+
else:
971+
inner = printer.append_qualified_name_before(die)
972+
before = str(printer).strip()
973+
974+
printer = DWARFTypePrinter()
975+
printer.append_unqualified_name_after(die, inner)
976+
after = str(printer).strip()
977+
self._types[key] = (before, after)
978+
979+
return self._types[key]

0 commit comments

Comments
 (0)