align gnu enum output with msvc enum output

This commit is contained in:
Walnut 2025-10-15 20:23:11 -05:00
parent c23ed3ef28
commit 95b031e7a8
3 changed files with 95 additions and 53 deletions

View file

@ -1,6 +1,5 @@
# Forces test-compliant formatting to all other types
type synthetic add -l lldb_lookup.synthetic_lookup -x ".*" --category Rust
type summary add -F _ -e -x -h "^.*$" --category Rust
# Std String
type synthetic add -l lldb_lookup.StdStringSyntheticProvider -x "^(alloc::([a-z_]+::)+)String$" --category Rust
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
type synthetic add -l lldb_lookup.synthetic_lookup -x "^&(mut )?(std::([a-z_]+::)+)Path$" --category Rust
type summary add -F lldb_lookup.summary_lookup -e -x -h "^&(mut )?(std::([a-z_]+::)+)Path$" --category Rust
# Enum
# type summary add -F lldb_lookup.ClangEncodedEnumSummaryProvider -e -h "lldb_lookup.is_sum_type_enum" --recognizer-function --category Rust
## MSVC
type synthetic add -l lldb_lookup.MSVCEnumSyntheticProvider -x "^enum2\$<.+>$" --category Rust
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
type summary add -F lldb_lookup.summary_lookup -e -x -h "^enum2\$<.+>::.*$" --category Rust
# Tuple
type synthetic add -l lldb_lookup.synthetic_lookup -x "^\(.*\)$" --category Rust
type summary add -F lldb_lookup.TupleSummaryProvider -e -x -h "^\(.*\)$" --category Rust
## MSVC
type synthetic add -l lldb_lookup.MSVCTupleSyntheticProvider -x "^tuple\$<.+>$" --category Rust
type summary add -F lldb_lookup.TupleSummaryProvider -e -x -h "^tuple\$<.+>$" --category Rust

View file

@ -10,9 +10,6 @@ def is_hashbrown_hashmap(hash_map: lldb.SBValue) -> bool:
def classify_rust_type(type: lldb.SBType) -> str:
if type.IsPointerType():
type = type.GetPointeeType()
type_class = type.GetTypeClass()
if type_class == lldb.eTypeClassStruct:
return classify_struct(type.name, type.fields)
@ -88,6 +85,26 @@ def synthetic_lookup(valobj: lldb.SBValue, _dict: LLDBOpaque) -> object:
if rust_type == RustType.SINGLETON_ENUM:
return synthetic_lookup(valobj.GetChildAtIndex(0), _dict)
if rust_type == RustType.ENUM:
# this little trick lets us treat `synthetic_lookup` as a "recognizer function" for the enum
# summary providers, reducing the number of lookups we have to do. This is a huge time save
# because there's no way (via type name) to recognize sum-type enums on `*-gnu` targets. The
# alternative would be to shove every single type through `summary_lookup`, which is
# incredibly wasteful. Once these scripts are updated for LLDB 19.0 and we can use
# `--recognizer-function`, this hack will only be needed for backwards compatibility.
summary: lldb.SBTypeSummary = valobj.GetTypeSummary()
if (
summary.summary_data is None
or summary.summary_data.strip()
!= "lldb_lookup.ClangEncodedEnumSummaryProvider(valobj,internal_dict)"
):
rust_category: lldb.SBTypeCategory = lldb.debugger.GetCategory("Rust")
rust_category.AddTypeSummary(
lldb.SBTypeNameSpecifier(valobj.GetTypeName()),
lldb.SBTypeSummary().CreateWithFunctionName(
"lldb_lookup.ClangEncodedEnumSummaryProvider"
),
)
return ClangEncodedEnumProvider(valobj, _dict)
if rust_type == RustType.STD_VEC:
return StdVecSyntheticProvider(valobj, _dict)

View file

@ -1,7 +1,6 @@
from __future__ import annotations
import re
import sys
from typing import List, TYPE_CHECKING, Generator
from typing import Generator, List, TYPE_CHECKING
from lldb import (
SBData,
@ -12,6 +11,8 @@ from lldb import (
eFormatChar,
)
from rust_types import is_tuple_fields
if TYPE_CHECKING:
from lldb import SBValue, SBType, SBTypeStaticField, SBTarget
@ -206,6 +207,34 @@ def resolve_msvc_template_arg(arg_name: str, target: SBTarget) -> SBType:
return result
def StructSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
# structs need the field name before the field value
output = (
f"{valobj.GetChildAtIndex(i).GetName()}:{child}"
for i, child in enumerate(aggregate_field_summary(valobj, _dict))
)
return "{" + ", ".join(output) + "}"
def TupleSummaryProvider(valobj: SBValue, _dict: LLDBOpaque):
return "(" + ", ".join(aggregate_field_summary(valobj, _dict)) + ")"
def aggregate_field_summary(valobj: SBValue, _dict) -> Generator[str, None, None]:
for i in range(0, valobj.GetNumChildren()):
child: SBValue = valobj.GetChildAtIndex(i)
summary = child.summary
if summary is None:
summary = child.value
if summary is None:
if is_tuple_fields(child):
summary = TupleSummaryProvider(child, _dict)
else:
summary = StructSummaryProvider(child, _dict)
yield summary
def SizeSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
return "size=" + str(valobj.GetNumChildren())
@ -454,49 +483,55 @@ class MSVCStrSyntheticProvider:
return "&str"
def _getVariantName(variant) -> str:
def _getVariantName(variant: SBValue) -> str:
"""
Since the enum variant's type name is in the form `TheEnumName::TheVariantName$Variant`,
we can extract `TheVariantName` from it for display purpose.
"""
s = variant.GetType().GetName()
match = re.search(r"::([^:]+)\$Variant$", s)
return match.group(1) if match else ""
if not s.endswith("$Variant"):
return ""
# trim off path and "$Variant"
# len("$Variant") == 8
return s.rsplit("::", 1)[1][:-8]
class ClangEncodedEnumProvider:
"""Pretty-printer for 'clang-encoded' enums support implemented in LLDB"""
valobj: SBValue
variant: SBValue
value: SBValue
DISCRIMINANT_MEMBER_NAME = "$discr$"
VALUE_MEMBER_NAME = "value"
__slots__ = ("valobj", "variant", "value")
def __init__(self, valobj: SBValue, _dict: LLDBOpaque):
self.valobj = valobj
self.update()
def has_children(self) -> bool:
return True
return self.value.MightHaveChildren()
def num_children(self) -> int:
return 1
return self.value.GetNumChildren()
def get_child_index(self, _name: str) -> int:
return -1
def get_child_index(self, name: str) -> int:
return self.value.GetIndexOfChildWithName(name)
def get_child_at_index(self, index: int) -> SBValue:
if index == 0:
value = self.variant.GetChildMemberWithName(
ClangEncodedEnumProvider.VALUE_MEMBER_NAME
)
return value.CreateChildAtOffset(
_getVariantName(self.variant), 0, value.GetType()
)
return None
return self.value.GetChildAtIndex(index)
def update(self):
all_variants = self.valobj.GetChildAtIndex(0)
index = self._getCurrentVariantIndex(all_variants)
self.variant = all_variants.GetChildAtIndex(index)
self.value = self.variant.GetChildMemberWithName(
ClangEncodedEnumProvider.VALUE_MEMBER_NAME
).GetSyntheticValue()
def _getCurrentVariantIndex(self, all_variants: SBValue) -> int:
default_index = 0
@ -514,6 +549,23 @@ class ClangEncodedEnumProvider:
return default_index
def ClangEncodedEnumSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
enum_synth = ClangEncodedEnumProvider(valobj.GetNonSyntheticValue(), _dict)
variant = enum_synth.variant
name = _getVariantName(variant)
if valobj.GetNumChildren() == 0:
return name
child_name: str = valobj.GetChildAtIndex(0).name
if child_name == "0" or child_name == "__0":
# enum variant is a tuple struct
return name + TupleSummaryProvider(valobj, _dict)
else:
# enum variant is a regular struct
return name + StructSummaryProvider(valobj, _dict)
class MSVCEnumSyntheticProvider:
"""
Synthetic provider for sum-type enums on MSVC. For a detailed explanation of the internals,
@ -522,12 +574,14 @@ class MSVCEnumSyntheticProvider:
https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
"""
valobj: SBValue
variant: SBValue
value: SBValue
__slots__ = ["valobj", "variant", "value"]
def __init__(self, valobj: SBValue, _dict: LLDBOpaque):
self.valobj = valobj
self.variant: SBValue
self.value: SBValue
self.update()
def update(self):
@ -695,21 +749,6 @@ class MSVCEnumSyntheticProvider:
return name
def StructSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
output = []
for i in range(valobj.GetNumChildren()):
child: SBValue = valobj.GetChildAtIndex(i)
summary = child.summary
if summary is None:
summary = child.value
if summary is None:
summary = StructSummaryProvider(child, _dict)
summary = child.GetName() + ":" + summary
output.append(summary)
return "{" + ", ".join(output) + "}"
def MSVCEnumSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
enum_synth = MSVCEnumSyntheticProvider(valobj.GetNonSyntheticValue(), _dict)
variant_names: SBType = valobj.target.FindFirstType(
@ -826,21 +865,6 @@ class MSVCTupleSyntheticProvider:
return "(" + name + ")"
def TupleSummaryProvider(valobj: SBValue, _dict: LLDBOpaque):
output: List[str] = []
for i in range(0, valobj.GetNumChildren()):
child: SBValue = valobj.GetChildAtIndex(i)
summary = child.summary
if summary is None:
summary = child.value
if summary is None:
summary = "{...}"
output.append(summary)
return "(" + ", ".join(output) + ")"
class StdVecSyntheticProvider:
"""Pretty-printer for alloc::vec::Vec<T>