Skip to content

Commit c322690

Browse files
committed
align gnu enum output with msvc enum output
1 parent 4b94758 commit c322690

File tree

3 files changed

+96
-54
lines changed

3 files changed

+96
-54
lines changed

src/etc/lldb_commands

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# Forces test-compliant formatting to all other types
22
type synthetic add -l lldb_lookup.synthetic_lookup -x ".*" --category Rust
3-
type summary add -F _ -e -x -h "^.*$" --category Rust
43
# Std String
54
type synthetic add -l lldb_lookup.StdStringSyntheticProvider -x "^(alloc::([a-z_]+::)+)String$" --category Rust
65
type summary add -F lldb_lookup.StdStringSummaryProvider -e -x -h "^(alloc::([a-z_]+::)+)String$" --category Rust
@@ -66,6 +65,7 @@ type summary add -F lldb_lookup.summary_lookup -e -x -h "^(std::([a-z_]+::)+)Pa
6665
type synthetic add -l lldb_lookup.synthetic_lookup -x "^&(mut )?(std::([a-z_]+::)+)Path$" --category Rust
6766
type summary add -F lldb_lookup.summary_lookup -e -x -h "^&(mut )?(std::([a-z_]+::)+)Path$" --category Rust
6867
# Enum
68+
# type summary add -F lldb_lookup.ClangEncodedEnumSummaryProvider -e -h "lldb_lookup.is_sum_type_enum" --recognizer-function --category Rust
6969
## MSVC
7070
type synthetic add -l lldb_lookup.MSVCEnumSyntheticProvider -x "^enum2\$<.+>$" --category Rust
7171
type summary add -F lldb_lookup.MSVCEnumSummaryProvider -e -x -h "^enum2\$<.+>$" --category Rust
@@ -74,6 +74,7 @@ type synthetic add -l lldb_lookup.synthetic_lookup -x "^enum2\$<.+>::.*$" --cate
7474
type summary add -F lldb_lookup.summary_lookup -e -x -h "^enum2\$<.+>::.*$" --category Rust
7575
# Tuple
7676
type synthetic add -l lldb_lookup.synthetic_lookup -x "^\(.*\)$" --category Rust
77+
type summary add -F lldb_lookup.TupleSummaryProvider -e -x -h "^\(.*\)$" --category Rust
7778
## MSVC
7879
type synthetic add -l lldb_lookup.MSVCTupleSyntheticProvider -x "^tuple\$<.+>$" --category Rust
7980
type summary add -F lldb_lookup.TupleSummaryProvider -e -x -h "^tuple\$<.+>$" --category Rust

src/etc/lldb_lookup.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@ def is_hashbrown_hashmap(hash_map: lldb.SBValue) -> bool:
1010

1111

1212
def classify_rust_type(type: lldb.SBType) -> str:
13-
if type.IsPointerType():
14-
type = type.GetPointeeType()
15-
1613
type_class = type.GetTypeClass()
1714
if type_class == lldb.eTypeClassStruct:
1815
return classify_struct(type.name, type.fields)
@@ -88,6 +85,26 @@ def synthetic_lookup(valobj: lldb.SBValue, _dict: LLDBOpaque) -> object:
8885
if rust_type == RustType.SINGLETON_ENUM:
8986
return synthetic_lookup(valobj.GetChildAtIndex(0), _dict)
9087
if rust_type == RustType.ENUM:
88+
# this little trick lets us treat `synthetic_lookup` as a "recognizer function" for the enum
89+
# summary providers, reducing the number of lookups we have to do. This is a huge time save
90+
# because there's no way (via type name) to recognize sum-type enums on `*-gnu` targets. The
91+
# alternative would be to shove every single type through `summary_lookup`, which is
92+
# incredibly wasteful. Once these scripts are updated for LLDB 19.0 and we can use
93+
# `--recognizer-function`, this hack will only be needed for backwards compatibility.
94+
summary: lldb.SBTypeSummary = valobj.GetTypeSummary()
95+
if (
96+
summary.summary_data is None
97+
or summary.summary_data.strip()
98+
!= "lldb_lookup.ClangEncodedEnumSummaryProvider(valobj,internal_dict)"
99+
):
100+
rust_category: lldb.SBTypeCategory = lldb.debugger.GetCategory("Rust")
101+
rust_category.AddTypeSummary(
102+
lldb.SBTypeNameSpecifier(valobj.GetTypeName()),
103+
lldb.SBTypeSummary().CreateWithFunctionName(
104+
"lldb_lookup.ClangEncodedEnumSummaryProvider"
105+
),
106+
)
107+
91108
return ClangEncodedEnumProvider(valobj, _dict)
92109
if rust_type == RustType.STD_VEC:
93110
return StdVecSyntheticProvider(valobj, _dict)

src/etc/lldb_providers.py

Lines changed: 74 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from __future__ import annotations
2-
import re
32
import sys
4-
from typing import List, TYPE_CHECKING
3+
from typing import Generator, List, TYPE_CHECKING
54

65
from lldb import (
76
SBData,
@@ -12,6 +11,8 @@
1211
eFormatChar,
1312
)
1413

14+
from rust_types import is_tuple_fields
15+
1516
if TYPE_CHECKING:
1617
from lldb import SBValue, SBType, SBTypeStaticField
1718

@@ -133,7 +134,7 @@ def has_children(self) -> bool:
133134
return False
134135

135136

136-
def get_template_args(type_name: str) -> list[str]:
137+
def get_template_args(type_name: str) -> List[str]:
137138
"""
138139
Takes a type name `T<A, tuple$<B, C>, D>` and returns a list of its generic args
139140
`["A", "tuple$<B, C>", "D"]`.
@@ -163,6 +164,34 @@ def get_template_args(type_name: str) -> list[str]:
163164
return params
164165

165166

167+
def StructSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
168+
# structs need the field name before the field value
169+
output = (
170+
f"{valobj.GetChildAtIndex(i).GetName()}:{child}"
171+
for i, child in enumerate(aggregate_field_summary(valobj, _dict))
172+
)
173+
174+
return "{" + ", ".join(output) + "}"
175+
176+
177+
def TupleSummaryProvider(valobj: SBValue, _dict: LLDBOpaque):
178+
return "(" + ", ".join(aggregate_field_summary(valobj, _dict)) + ")"
179+
180+
181+
def aggregate_field_summary(valobj: SBValue, _dict) -> Generator[str, None, None]:
182+
for i in range(0, valobj.GetNumChildren()):
183+
child: SBValue = valobj.GetChildAtIndex(i)
184+
summary = child.summary
185+
if summary is None:
186+
summary = child.value
187+
if summary is None:
188+
if is_tuple_fields(child):
189+
summary = TupleSummaryProvider(child, _dict)
190+
else:
191+
summary = StructSummaryProvider(child, _dict)
192+
yield summary
193+
194+
166195
def SizeSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
167196
return "size=" + str(valobj.GetNumChildren())
168197

@@ -411,49 +440,55 @@ def get_type_name(self):
411440
return "&str"
412441

413442

414-
def _getVariantName(variant) -> str:
443+
def _getVariantName(variant: SBValue) -> str:
415444
"""
416445
Since the enum variant's type name is in the form `TheEnumName::TheVariantName$Variant`,
417446
we can extract `TheVariantName` from it for display purpose.
418447
"""
419448
s = variant.GetType().GetName()
420-
match = re.search(r"::([^:]+)\$Variant$", s)
421-
return match.group(1) if match else ""
449+
if not s.endswith("$Variant"):
450+
return ""
451+
452+
# trim off path and "$Variant"
453+
# len("$Variant") == 8
454+
return s.rsplit("::", 1)[1][:-8]
422455

423456

424457
class ClangEncodedEnumProvider:
425458
"""Pretty-printer for 'clang-encoded' enums support implemented in LLDB"""
426459

460+
valobj: SBValue
461+
variant: SBValue
462+
value: SBValue
463+
427464
DISCRIMINANT_MEMBER_NAME = "$discr$"
428465
VALUE_MEMBER_NAME = "value"
429466

467+
__slots__ = ("valobj", "variant", "value")
468+
430469
def __init__(self, valobj: SBValue, _dict: LLDBOpaque):
431470
self.valobj = valobj
432471
self.update()
433472

434473
def has_children(self) -> bool:
435-
return True
474+
return self.value.MightHaveChildren()
436475

437476
def num_children(self) -> int:
438-
return 1
477+
return self.value.GetNumChildren()
439478

440-
def get_child_index(self, _name: str) -> int:
441-
return -1
479+
def get_child_index(self, name: str) -> int:
480+
return self.value.GetIndexOfChildWithName(name)
442481

443482
def get_child_at_index(self, index: int) -> SBValue:
444-
if index == 0:
445-
value = self.variant.GetChildMemberWithName(
446-
ClangEncodedEnumProvider.VALUE_MEMBER_NAME
447-
)
448-
return value.CreateChildAtOffset(
449-
_getVariantName(self.variant), 0, value.GetType()
450-
)
451-
return None
483+
return self.value.GetChildAtIndex(index)
452484

453485
def update(self):
454486
all_variants = self.valobj.GetChildAtIndex(0)
455487
index = self._getCurrentVariantIndex(all_variants)
456488
self.variant = all_variants.GetChildAtIndex(index)
489+
self.value = self.variant.GetChildMemberWithName(
490+
ClangEncodedEnumProvider.VALUE_MEMBER_NAME
491+
).GetSyntheticValue()
457492

458493
def _getCurrentVariantIndex(self, all_variants: SBValue) -> int:
459494
default_index = 0
@@ -471,6 +506,23 @@ def _getCurrentVariantIndex(self, all_variants: SBValue) -> int:
471506
return default_index
472507

473508

509+
def ClangEncodedEnumSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
510+
enum_synth = ClangEncodedEnumProvider(valobj.GetNonSyntheticValue(), _dict)
511+
variant = enum_synth.variant
512+
name = _getVariantName(variant)
513+
514+
if valobj.GetNumChildren() == 0:
515+
return name
516+
517+
child_name: str = valobj.GetChildAtIndex(0).name
518+
if child_name == "0" or child_name == "__0":
519+
# enum variant is a tuple struct
520+
return name + TupleSummaryProvider(valobj, _dict)
521+
else:
522+
# enum variant is a regular struct
523+
return name + StructSummaryProvider(valobj, _dict)
524+
525+
474526
class MSVCEnumSyntheticProvider:
475527
"""
476528
Synthetic provider for sum-type enums on MSVC. For a detailed explanation of the internals,
@@ -479,12 +531,14 @@ class MSVCEnumSyntheticProvider:
479531
https://github.com/rust-lang/rust/blob/master/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
480532
"""
481533

534+
valobj: SBValue
535+
variant: SBValue
536+
value: SBValue
537+
482538
__slots__ = ["valobj", "variant", "value"]
483539

484540
def __init__(self, valobj: SBValue, _dict: LLDBOpaque):
485541
self.valobj = valobj
486-
self.variant: SBValue
487-
self.value: SBValue
488542
self.update()
489543

490544
def update(self):
@@ -652,21 +706,6 @@ def get_type_name(self) -> str:
652706
return name
653707

654708

655-
def StructSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
656-
output = []
657-
for i in range(valobj.GetNumChildren()):
658-
child: SBValue = valobj.GetChildAtIndex(i)
659-
summary = child.summary
660-
if summary is None:
661-
summary = child.value
662-
if summary is None:
663-
summary = StructSummaryProvider(child, _dict)
664-
summary = child.GetName() + ":" + summary
665-
output.append(summary)
666-
667-
return "{" + ", ".join(output) + "}"
668-
669-
670709
def MSVCEnumSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
671710
enum_synth = MSVCEnumSyntheticProvider(valobj.GetNonSyntheticValue(), _dict)
672711
variant_names: SBType = valobj.target.FindFirstType(
@@ -783,21 +822,6 @@ def get_type_name(self) -> str:
783822
return "(" + name + ")"
784823

785824

786-
def TupleSummaryProvider(valobj: SBValue, _dict: LLDBOpaque):
787-
output: List[str] = []
788-
789-
for i in range(0, valobj.GetNumChildren()):
790-
child: SBValue = valobj.GetChildAtIndex(i)
791-
summary = child.summary
792-
if summary is None:
793-
summary = child.value
794-
if summary is None:
795-
summary = "{...}"
796-
output.append(summary)
797-
798-
return "(" + ", ".join(output) + ")"
799-
800-
801825
class StdVecSyntheticProvider:
802826
"""Pretty-printer for alloc::vec::Vec<T>
803827

0 commit comments

Comments
 (0)