11import copy
2- import functools
32import logging
43import posixpath
54import struct
3837logger = 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-
5840def 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