about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/etc/lldb_lookup.py3
-rw-r--r--src/etc/lldb_providers.py52
-rw-r--r--src/etc/rust_types.py7
3 files changed, 60 insertions, 2 deletions
diff --git a/src/etc/lldb_lookup.py b/src/etc/lldb_lookup.py
index a93b42e1cc4..db3afb00369 100644
--- a/src/etc/lldb_lookup.py
+++ b/src/etc/lldb_lookup.py
@@ -86,7 +86,8 @@ def synthetic_lookup(valobj, dict):
         return synthetic_lookup(valobj.GetChildAtIndex(discriminant), dict)
     if rust_type == RustType.SINGLETON_ENUM:
         return synthetic_lookup(valobj.GetChildAtIndex(0), dict)
-
+    if rust_type == RustType.ENUM:
+        return ClangEncodedEnumProvider(valobj, dict)
     if rust_type == RustType.STD_VEC:
         return StdVecSyntheticProvider(valobj, dict)
     if rust_type == RustType.STD_VEC_DEQUE:
diff --git a/src/etc/lldb_providers.py b/src/etc/lldb_providers.py
index 1c43977a501..a87fd6078b8 100644
--- a/src/etc/lldb_providers.py
+++ b/src/etc/lldb_providers.py
@@ -247,6 +247,58 @@ class StructSyntheticProvider:
         # type: () -> bool
         return True
 
+class ClangEncodedEnumProvider:
+    """Pretty-printer for 'clang-encoded' enums support implemented in LLDB"""
+    DISCRIMINANT_MEMBER_NAME = "$discr$"
+    VALUE_MEMBER_NAME = "value"
+
+    def __init__(self, valobj, dict):
+        self.valobj = valobj
+        self.update()
+
+    def has_children(self):
+       return True
+
+    def num_children(self):
+        if self.is_default:
+            return 1
+        return 2
+
+    def get_child_index(self, name):
+        if name == ClangEncodedEnumProvider.VALUE_MEMBER_NAME:
+            return 0
+        if name == ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME:
+            return 1
+        return -1
+
+    def get_child_at_index(self, index):
+        if index == 0:
+            return self.variant.GetChildMemberWithName(ClangEncodedEnumProvider.VALUE_MEMBER_NAME)
+        if index == 1:
+            return self.variant.GetChildMemberWithName(
+                ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME)
+
+
+    def update(self):
+        all_variants = self.valobj.GetChildAtIndex(0)
+        index = self._getCurrentVariantIndex(all_variants)
+        self.variant = all_variants.GetChildAtIndex(index)
+        self.is_default = self.variant.GetIndexOfChildWithName(
+            ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME) == -1
+
+    def _getCurrentVariantIndex(self, all_variants):
+        default_index = 0
+        for i in range(all_variants.GetNumChildren()):
+            variant = all_variants.GetChildAtIndex(i)
+            discr = variant.GetChildMemberWithName(
+                ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME)
+            if discr.IsValid():
+                discr_unsigned_value = discr.GetValueAsUnsigned()
+                if variant.GetName() == f"$variant${discr_unsigned_value}":
+                    return i
+            else:
+                default_index = i
+        return default_index
 
 class TupleSyntheticProvider:
     """Pretty-printer for tuples and tuple enum variants"""
diff --git a/src/etc/rust_types.py b/src/etc/rust_types.py
index c0415a3cdcf..190fbc13a17 100644
--- a/src/etc/rust_types.py
+++ b/src/etc/rust_types.py
@@ -60,6 +60,7 @@ TUPLE_ITEM_REGEX = re.compile(r"__\d+$")
 
 ENCODED_ENUM_PREFIX = "RUST$ENCODED$ENUM$"
 ENUM_DISR_FIELD_NAME = "<<variant>>"
+ENUM_LLDB_ENCODED_VARIANTS = "$variants$"
 
 STD_TYPE_TO_REGEX = {
     RustType.STD_STRING: STD_STRING_REGEX,
@@ -96,7 +97,11 @@ def classify_struct(name, fields):
         if regex.match(name):
             return ty
 
-    if fields[0].name == ENUM_DISR_FIELD_NAME:
+    # <<variant>> is emitted by GDB while LLDB(18.1+) emits "$variants$"
+    if (
+        fields[0].name == ENUM_DISR_FIELD_NAME
+        or fields[0].name == ENUM_LLDB_ENCODED_VARIANTS
+    ):
         return RustType.ENUM
 
     if is_tuple_fields(fields):