align gnu enum output with msvc enum output
This commit is contained in:
parent
c23ed3ef28
commit
95b031e7a8
3 changed files with 95 additions and 53 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue