Skip to content

Commit 2eacf6e

Browse files
committed
feat: support split-qualified types
1 parent 7e397ee commit 2eacf6e

5 files changed

Lines changed: 54 additions & 58 deletions

File tree

src/dwarf2cpp/_dwarf.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,12 @@ class PyDWARFTypePrinter {
100100
auto appendUnqualifiedName(llvm::DWARFDie die) {
101101
printer.appendUnqualifiedName(die);
102102
}
103+
auto appendUnqualifiedNameBefore(llvm::DWARFDie die) {
104+
return printer.appendUnqualifiedNameBefore(die);
105+
}
106+
auto appendUnqualifiedNameAfter(llvm::DWARFDie die, llvm::DWARFDie inner) {
107+
printer.appendUnqualifiedNameAfter(die, inner);
108+
}
103109
auto appendScopes(llvm::DWARFDie die) { printer.appendScopes(die); }
104110

105111
private:
@@ -286,6 +292,10 @@ PYBIND11_MODULE(_dwarf, m) {
286292
.def("append_qualified_name", &PyDWARFTypePrinter::appendQualifiedName)
287293
.def("append_unqualified_name",
288294
&PyDWARFTypePrinter::appendUnqualifiedName)
295+
.def("append_unqualified_name_before",
296+
&PyDWARFTypePrinter::appendUnqualifiedNameBefore)
297+
.def("append_unqualified_name_after",
298+
&PyDWARFTypePrinter::appendUnqualifiedNameAfter)
289299
.def("append_scopes", &PyDWARFTypePrinter::appendScopes)
290300
.def("__str__", &PyDWARFTypePrinter::string);
291301
}

src/dwarf2cpp/filters.py

Lines changed: 10 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import functools
2-
import re
32

43
from .models import Namespace
54

@@ -31,43 +30,17 @@ def do_ns_actions(prev: list[Namespace], curr: list[Namespace]):
3130

3231

3332
@functools.cache
34-
def do_insert_name(tp: str, name: str):
35-
"""Insert `name` into the C++ declarator described by `tp`."""
36-
t = tp.strip()
33+
def do_insert_name(tp: str | tuple[str, str], name: str):
34+
if isinstance(tp, tuple):
35+
if not name:
36+
return "".join(tp)
3737

38-
if not name:
39-
return t
40-
41-
# Arrays: BASE [N][M]...
42-
m = re.match(r"^(?P<base>.+?)(?P<arrays>(?:\s*\[[^\]]*\]\s*)+)$", t)
43-
if m:
44-
base = m.group("base").strip()
45-
arrays = m.group("arrays").strip()
46-
return f"{base} {name}{arrays}"
38+
if tp[0].endswith("*") and not tp[1].startswith("["):
39+
return f"{tp[0]}{name}{tp[1]}"
4740

48-
# Plain C-style function pointer: RET (*)(ARGS)
49-
m = re.match(r"^(?P<ret>.+?)\s*\(\s*\*\s*\)\s*\((?P<args>.*)\)$", t)
50-
if m:
51-
ret = m.group("ret").strip()
52-
args = m.group("args").strip()
53-
return f"{ret} (*{name})({args})"
41+
return f"{tp[0]} {name}{tp[1]}"
5442

55-
# Member function pointer: RET (Class::*)(ARGS) [const/volatile]* [&|&&]?
56-
m = re.match(
57-
r"^(?P<ret>.+?)\s*\(\s*(?P<cls>.+?::\*)\s*\)\s*"
58-
r"\((?P<args>[^)]*)\)\s*"
59-
r"(?P<cv>(?:const|volatile)(?:\s+(?:const|volatile))*)?\s*"
60-
r"(?P<ref>&{1,2})?\s*$",
61-
t,
62-
)
63-
if m:
64-
ret = m.group("ret").strip()
65-
cls = m.group("cls").strip()
66-
args = m.group("args").strip()
67-
cv = (m.group("cv") or "").strip()
68-
ref = (m.group("ref") or "").strip()
69-
tail = " ".join(x for x in (cv, ref) if x)
70-
return f"{ret} ({cls}{name})({args}){(' ' + tail) if tail else ''}"
43+
if not name:
44+
return tp
7145

72-
# Fallback: just a normal "type name"
73-
return f"{t} {name}"
46+
return f"{tp} {name}"

src/dwarf2cpp/models.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class ImportedDeclaration(Object):
4646
class Attribute(Object):
4747
kind: ClassVar[str] = "attribute"
4848
# attributes
49-
type: str | None = None
49+
type: str | tuple[str, str] | None = None
5050
default_value: int | float | None = None
5151
alignment: int | None = None
5252
bit_size: int | None = None
@@ -62,7 +62,7 @@ class ParameterKind(enum.StrEnum):
6262
@dataclass
6363
class Parameter:
6464
name: str
65-
type: str | None = None
65+
type: str | tuple[str, str] | None = None
6666
kind: ParameterKind | None = None
6767

6868

src/dwarf2cpp/templates/attribute.jinja

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{{- "static " if obj.is_static -}}
22
{{- "alignas({}) ".format(obj.alignment) if obj.alignment -}}
3-
{%- if obj.type is string -%}
3+
{%- if obj.type is string or obj.type is sequence -%}
44
{{ obj.type | insert_name(obj.name) }}
55
{%- else -%}
66
{%- with obj = obj.type -%}

src/dwarf2cpp/visitor.py

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,26 @@ def scoped_tags(tag: str) -> bool:
4646

4747

4848
@functools.cache
49-
def get_qualified_type(die: DWARFDie):
49+
def get_qualified_type(die: DWARFDie, split=False) -> str | tuple[str, str]:
5050
printer = DWARFTypePrinter()
5151
if scoped_tags(die.tag):
5252
printer.append_scopes(die.parent)
5353

54-
printer.append_unqualified_name(die)
55-
return str(printer)
54+
if not split:
55+
printer.append_unqualified_name(die)
56+
return str(printer).strip()
57+
58+
inner = printer.append_unqualified_name_before(die)
59+
before = str(printer).strip()
60+
61+
printer = DWARFTypePrinter()
62+
printer.append_unqualified_name_after(die, inner)
63+
after = str(printer).strip()
64+
65+
if not after:
66+
return before
67+
68+
return before, after
5669

5770

5871
def float_to_str(value: float) -> str:
@@ -92,11 +105,11 @@ def files(self) -> Generator[tuple[str, dict[int, list[Object]]]]:
92105
List of files
93106
"""
94107
for i, cu in (
95-
pbar := tqdm(
96-
enumerate(self.context.compile_units),
97-
total=self.context.num_compile_units,
98-
bar_format="[{n_fmt}/{total_fmt}] {desc}",
99-
)
108+
pbar := tqdm(
109+
enumerate(self.context.compile_units),
110+
total=self.context.num_compile_units,
111+
bar_format="[{n_fmt}/{total_fmt}] {desc}",
112+
)
100113
):
101114
cu_die = cu.unit_die
102115
name = cu_die.short_name
@@ -475,18 +488,18 @@ def visit_subprogram(self, die: DWARFDie) -> None:
475488

476489
parameter = Parameter(
477490
name=child.short_name,
478-
type=get_qualified_type(child.find("DW_AT_type").as_referenced_die()),
491+
type=get_qualified_type(child.find("DW_AT_type").as_referenced_die(), split=True),
479492
kind=ParameterKind.POSITIONAL,
480493
)
481494
function.parameters.append(parameter)
482495
case "DW_TAG_unspecified_parameters":
483496
parameter = Parameter(name="", type="", kind=ParameterKind.VARIADIC)
484497
function.parameters.append(parameter)
485498
case (
486-
"DW_TAG_template_type_parameter"
487-
| "DW_TAG_template_value_parameter"
488-
| "DW_TAG_GNU_template_parameter_pack"
489-
| "DW_TAG_GNU_template_template_param"
499+
"DW_TAG_template_type_parameter"
500+
| "DW_TAG_template_value_parameter"
501+
| "DW_TAG_GNU_template_parameter_pack"
502+
| "DW_TAG_GNU_template_template_param"
490503
):
491504
# TODO: handle template params
492505
pass
@@ -609,7 +622,7 @@ def _handle_attribute(self, die: DWARFDie) -> None:
609622
value.is_implicit = True
610623
variable.type = value
611624
else:
612-
variable.type = get_qualified_type(ty)
625+
variable.type = get_qualified_type(ty, split=True)
613626

614627
assert variable.type, "Expected type"
615628

@@ -730,10 +743,10 @@ def _handle_struct(self, die: DWARFDie, struct: Struct) -> None:
730743

731744
match child.tag:
732745
case (
733-
"DW_TAG_template_type_parameter"
734-
| "DW_TAG_template_value_parameter"
735-
| "DW_TAG_GNU_template_parameter_pack"
736-
| "DW_TAG_GNU_template_template_param"
746+
"DW_TAG_template_type_parameter"
747+
| "DW_TAG_template_value_parameter"
748+
| "DW_TAG_GNU_template_parameter_pack"
749+
| "DW_TAG_GNU_template_template_param"
737750
):
738751
# TODO: handle template params
739752
pass

0 commit comments

Comments
 (0)