Skip to content

Commit 11cb528

Browse files
authored
Rollup merge of rust-lang#147760 - Walnut356:gnu_enum_viz, r=Mark-Simulacrum
[Debugger Visualizers] Unify `*-gnu` and `*-msvc` enum output Followup patch to rust-lang#145218 Ports the msvc enum synthetic/summary logic to the gnu handlers so they have identical output. Also removes the "look-through-pointers" logic that caused rust-lang#147450 <img width="629" height="220" alt="image" src="https://github.com/user-attachments/assets/d6ae44d5-232f-412d-b291-64ac52850c74" /> I know we don't run the test suite in CI anymore, but it's still useful locally so I updated the relevant tests.
2 parents 518b428 + b32411e commit 11cb528

21 files changed

+140
-97
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

tests/debuginfo/basic-types-globals.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
// lldb-command:v I
1414
// lldb-check: ::I::[...] = -1
1515
// lldb-command:v --format=d C
16-
// lldb-check: ::C::[...] = 97
16+
// lldb-check: ::C::[...] = 97 U+0x00000061 U'a'
1717
// lldb-command:v --format=d I8
1818
// lldb-check: ::I8::[...] = 68
1919
// lldb-command:v I16

tests/debuginfo/borrowed-enum.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@
2323
// lldb-command:run
2424

2525
// lldb-command:v *the_a_ref
26-
// lldb-check:(borrowed_enum::ABC) *the_a_ref = { TheA = { x = 0 y = 8970181431921507452 } }
26+
// lldb-check:(borrowed_enum::ABC) *the_a_ref = TheA{x:0, y:8970181431921507452} { x = 0 y = 8970181431921507452 }
2727
// lldb-command:v *the_b_ref
28-
// lldb-check:(borrowed_enum::ABC) *the_b_ref = { TheB = { 0 = 0 1 = 286331153 2 = 286331153 } }
28+
// lldb-check:(borrowed_enum::ABC) *the_b_ref = TheB(0, 286331153, 286331153) { 0 = 0 1 = 286331153 2 = 286331153 }
2929
// lldb-command:v *univariant_ref
30-
// lldb-check:(borrowed_enum::Univariant) *univariant_ref = { TheOnlyCase = { 0 = 4820353753753434 } }
30+
// lldb-check:(borrowed_enum::Univariant) *univariant_ref = TheOnlyCase(4820353753753434) { 0 = 4820353753753434 }
3131

3232
#![allow(unused_variables)]
3333

tests/debuginfo/c-style-enum-in-composite.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
// lldb-check:[...] { 0 = 0 1 = OneHundred }
3636

3737
// lldb-command:v tuple_padding_at_end
38-
// lldb-check:[...] { 0 = { 0 = 1 1 = OneThousand } 1 = 2 }
38+
// lldb-check:[...] ((1, OneThousand), 2) { 0 = (1, OneThousand) { 0 = 1 1 = OneThousand } 1 = 2 }
3939

4040
// lldb-command:v tuple_different_enums
4141
// lldb-check:[...] { 0 = OneThousand 1 = MountainView 2 = OneMillion 3 = Vienna }

tests/debuginfo/coroutine-objects.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
// lldb-command:run
2929
// lldb-command:v b
30-
// lldb-check:(coroutine_objects::main::{coroutine_env#0}) b = { value = { _ref__a = 0x[...] } $discr$ = [...] }
30+
// lldb-check:(coroutine_objects::main::{coroutine_env#0}) b = 0{_ref__a:0x[...]} { _ref__a = 0x[...] }
3131

3232
// === CDB TESTS ===================================================================================
3333

tests/debuginfo/enum-thinlto.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
// lldb-command:run
1616

1717
// lldb-command:v *abc
18-
// lldb-check:(enum_thinlto::ABC) *abc = { value = { x = 0 y = 8970181431921507452 } $discr$ = 0 }
18+
// lldb-check:(enum_thinlto::ABC) *abc = TheA{x:0, y:8970181431921507452} { x = 0 y = 8970181431921507452 }
1919

2020
#![allow(unused_variables)]
2121

tests/debuginfo/generic-method-on-generic-struct.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858

5959
// STACK BY REF
6060
// lldb-command:v *self
61-
// lldb-check:[...] { x = { 0 = 8888 1 = -8888 } }
61+
// lldb-check:[...] { x = (8888, -8888) { 0 = 8888 1 = -8888 } }
6262
// lldb-command:v arg1
6363
// lldb-check:[...] -1
6464
// lldb-command:v arg2
@@ -67,7 +67,7 @@
6767

6868
// STACK BY VAL
6969
// lldb-command:v self
70-
// lldb-check:[...] { x = { 0 = 8888 1 = -8888 } }
70+
// lldb-check:[...] { x = (8888, -8888) { 0 = 8888 1 = -8888 } }
7171
// lldb-command:v arg1
7272
// lldb-check:[...] -3
7373
// lldb-command:v arg2

tests/debuginfo/issue-57822.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
// lldb-check:(issue_57822::main::{closure_env#1}) g = { f = { x = 1 } }
2525

2626
// lldb-command:v b
27-
// lldb-check:(issue_57822::main::{coroutine_env#3}) b = { value = { a = { value = { y = 2 } $discr$ = '\x02' } } $discr$ = '\x02' }
27+
// lldb-check:(issue_57822::main::{coroutine_env#3}) b = 2{a:2{y:2}} { a = 2{y:2} { y = 2 } }
2828

2929
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
3030

0 commit comments

Comments
 (0)