Skip to content

Commit 95b031e

Browse files
committed
align gnu enum output with msvc enum output
1 parent c23ed3e commit 95b031e

File tree

3 files changed

+95
-53
lines changed

3 files changed

+95
-53
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: 73 additions & 49 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, Generator
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, SBTarget
1718

@@ -206,6 +207,34 @@ def resolve_msvc_template_arg(arg_name: str, target: SBTarget) -> SBType:
206207
return result
207208

208209

210+
def StructSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
211+
# structs need the field name before the field value
212+
output = (
213+
f"{valobj.GetChildAtIndex(i).GetName()}:{child}"
214+
for i, child in enumerate(aggregate_field_summary(valobj, _dict))
215+
)
216+
217+
return "{" + ", ".join(output) + "}"
218+
219+
220+
def TupleSummaryProvider(valobj: SBValue, _dict: LLDBOpaque):
221+
return "(" + ", ".join(aggregate_field_summary(valobj, _dict)) + ")"
222+
223+
224+
def aggregate_field_summary(valobj: SBValue, _dict) -> Generator[str, None, None]:
225+
for i in range(0, valobj.GetNumChildren()):
226+
child: SBValue = valobj.GetChildAtIndex(i)
227+
summary = child.summary
228+
if summary is None:
229+
summary = child.value
230+
if summary is None:
231+
if is_tuple_fields(child):
232+
summary = TupleSummaryProvider(child, _dict)
233+
else:
234+
summary = StructSummaryProvider(child, _dict)
235+
yield summary
236+
237+
209238
def SizeSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
210239
return "size=" + str(valobj.GetNumChildren())
211240

@@ -454,49 +483,55 @@ def get_type_name(self):
454483
return "&str"
455484

456485

457-
def _getVariantName(variant) -> str:
486+
def _getVariantName(variant: SBValue) -> str:
458487
"""
459488
Since the enum variant's type name is in the form `TheEnumName::TheVariantName$Variant`,
460489
we can extract `TheVariantName` from it for display purpose.
461490
"""
462491
s = variant.GetType().GetName()
463-
match = re.search(r"::([^:]+)\$Variant$", s)
464-
return match.group(1) if match else ""
492+
if not s.endswith("$Variant"):
493+
return ""
494+
495+
# trim off path and "$Variant"
496+
# len("$Variant") == 8
497+
return s.rsplit("::", 1)[1][:-8]
465498

466499

467500
class ClangEncodedEnumProvider:
468501
"""Pretty-printer for 'clang-encoded' enums support implemented in LLDB"""
469502

503+
valobj: SBValue
504+
variant: SBValue
505+
value: SBValue
506+
470507
DISCRIMINANT_MEMBER_NAME = "$discr$"
471508
VALUE_MEMBER_NAME = "value"
472509

510+
__slots__ = ("valobj", "variant", "value")
511+
473512
def __init__(self, valobj: SBValue, _dict: LLDBOpaque):
474513
self.valobj = valobj
475514
self.update()
476515

477516
def has_children(self) -> bool:
478-
return True
517+
return self.value.MightHaveChildren()
479518

480519
def num_children(self) -> int:
481-
return 1
520+
return self.value.GetNumChildren()
482521

483-
def get_child_index(self, _name: str) -> int:
484-
return -1
522+
def get_child_index(self, name: str) -> int:
523+
return self.value.GetIndexOfChildWithName(name)
485524

486525
def get_child_at_index(self, index: int) -> SBValue:
487-
if index == 0:
488-
value = self.variant.GetChildMemberWithName(
489-
ClangEncodedEnumProvider.VALUE_MEMBER_NAME
490-
)
491-
return value.CreateChildAtOffset(
492-
_getVariantName(self.variant), 0, value.GetType()
493-
)
494-
return None
526+
return self.value.GetChildAtIndex(index)
495527

496528
def update(self):
497529
all_variants = self.valobj.GetChildAtIndex(0)
498530
index = self._getCurrentVariantIndex(all_variants)
499531
self.variant = all_variants.GetChildAtIndex(index)
532+
self.value = self.variant.GetChildMemberWithName(
533+
ClangEncodedEnumProvider.VALUE_MEMBER_NAME
534+
).GetSyntheticValue()
500535

501536
def _getCurrentVariantIndex(self, all_variants: SBValue) -> int:
502537
default_index = 0
@@ -514,6 +549,23 @@ def _getCurrentVariantIndex(self, all_variants: SBValue) -> int:
514549
return default_index
515550

516551

552+
def ClangEncodedEnumSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
553+
enum_synth = ClangEncodedEnumProvider(valobj.GetNonSyntheticValue(), _dict)
554+
variant = enum_synth.variant
555+
name = _getVariantName(variant)
556+
557+
if valobj.GetNumChildren() == 0:
558+
return name
559+
560+
child_name: str = valobj.GetChildAtIndex(0).name
561+
if child_name == "0" or child_name == "__0":
562+
# enum variant is a tuple struct
563+
return name + TupleSummaryProvider(valobj, _dict)
564+
else:
565+
# enum variant is a regular struct
566+
return name + StructSummaryProvider(valobj, _dict)
567+
568+
517569
class MSVCEnumSyntheticProvider:
518570
"""
519571
Synthetic provider for sum-type enums on MSVC. For a detailed explanation of the internals,
@@ -522,12 +574,14 @@ class MSVCEnumSyntheticProvider:
522574
https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
523575
"""
524576

577+
valobj: SBValue
578+
variant: SBValue
579+
value: SBValue
580+
525581
__slots__ = ["valobj", "variant", "value"]
526582

527583
def __init__(self, valobj: SBValue, _dict: LLDBOpaque):
528584
self.valobj = valobj
529-
self.variant: SBValue
530-
self.value: SBValue
531585
self.update()
532586

533587
def update(self):
@@ -695,21 +749,6 @@ def get_type_name(self) -> str:
695749
return name
696750

697751

698-
def StructSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
699-
output = []
700-
for i in range(valobj.GetNumChildren()):
701-
child: SBValue = valobj.GetChildAtIndex(i)
702-
summary = child.summary
703-
if summary is None:
704-
summary = child.value
705-
if summary is None:
706-
summary = StructSummaryProvider(child, _dict)
707-
summary = child.GetName() + ":" + summary
708-
output.append(summary)
709-
710-
return "{" + ", ".join(output) + "}"
711-
712-
713752
def MSVCEnumSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
714753
enum_synth = MSVCEnumSyntheticProvider(valobj.GetNonSyntheticValue(), _dict)
715754
variant_names: SBType = valobj.target.FindFirstType(
@@ -826,21 +865,6 @@ def get_type_name(self) -> str:
826865
return "(" + name + ")"
827866

828867

829-
def TupleSummaryProvider(valobj: SBValue, _dict: LLDBOpaque):
830-
output: List[str] = []
831-
832-
for i in range(0, valobj.GetNumChildren()):
833-
child: SBValue = valobj.GetChildAtIndex(i)
834-
summary = child.summary
835-
if summary is None:
836-
summary = child.value
837-
if summary is None:
838-
summary = "{...}"
839-
output.append(summary)
840-
841-
return "(" + ", ".join(output) + ")"
842-
843-
844868
class StdVecSyntheticProvider:
845869
"""Pretty-printer for alloc::vec::Vec<T>
846870

0 commit comments

Comments
 (0)