-
Notifications
You must be signed in to change notification settings - Fork 12.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[lldb] Add basic support to Rust enums in TypeSystemClang
LLDB doesn't yet have a TypeSystemRust implemented however it is used to debug Rust applications. Most of the types map well enough to Clang types and there are python formatters implemented to display those types reasonably well in a debugger. However, Rust enums are completely ignored by LLDB as Clang never emits DW_TAG_variant_part inside DW_TAG_structure_type This diff adds a parser for DW_TAG_variant_part (Rust-only) that creates a matching valid Clang declaration to the Rust enum. As long as there is enough information and all fields have correct offsets synthetic/summary providers can be implemented to display it correctly when debugging Rust code Differential Revision: https://reviews.llvm.org/D149213
- Loading branch information
1 parent
52c62d4
commit e84751a
Showing
6 changed files
with
3,775 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
"""Helper library to traverse data emitted for Rust enums """ | ||
from lldbsuite.test.lldbtest import * | ||
|
||
DISCRIMINANT_MEMBER_NAME = "$discr$" | ||
VALUE_MEMBER_NAME = "value" | ||
|
||
class RustEnumValue: | ||
|
||
def __init__(self, value: lldb.SBValue): | ||
self.value = value | ||
|
||
def getAllVariantTypes(self): | ||
result = [] | ||
for i in range(self._inner().GetNumChildren()): | ||
result.append(self.getVariantByIndex(i).GetDisplayTypeName()) | ||
return result | ||
|
||
def _inner(self) -> lldb.SBValue: | ||
return self.value.GetChildAtIndex(0) | ||
|
||
def getVariantByIndex(self, index): | ||
return self._inner().GetChildAtIndex(index).GetChildMemberWithName(VALUE_MEMBER_NAME) | ||
|
||
@staticmethod | ||
def _getDiscriminantValueAsUnsigned(discr_sbvalue: lldb.SBValue): | ||
byte_size = discr_sbvalue.GetType().GetByteSize() | ||
error = lldb.SBError() | ||
|
||
# when discriminant is u16 Clang emits 'unsigned char' | ||
# and LLDB seems to treat it as character type disalowing to call GetValueAsUnsigned | ||
if byte_size == 1: | ||
return discr_sbvalue.GetData().GetUnsignedInt8(error, 0) | ||
elif byte_size == 2: | ||
return discr_sbvalue.GetData().GetUnsignedInt16(error, 0) | ||
elif byte_size == 4: | ||
return discr_sbvalue.GetData().GetUnsignedInt32(error, 0) | ||
elif byte_size == 8: | ||
return discr_sbvalue.GetData().GetUnsignedInt64(error, 0) | ||
else: | ||
return discr_sbvalue.GetValueAsUnsigned() | ||
|
||
def getCurrentVariantIndex(self): | ||
default_index = 0 | ||
for i in range(self._inner().GetNumChildren()): | ||
variant: lldb.SBValue = self._inner().GetChildAtIndex(i); | ||
discr = variant.GetChildMemberWithName(DISCRIMINANT_MEMBER_NAME) | ||
if discr.IsValid(): | ||
discr_unsigned_value = RustEnumValue._getDiscriminantValueAsUnsigned(discr) | ||
if variant.GetName() == f"$variant${discr_unsigned_value}": | ||
return discr_unsigned_value | ||
else: | ||
default_index = i | ||
return default_index | ||
|
||
def getFields(self): | ||
result = [] | ||
for i in range(self._inner().GetNumChildren()): | ||
type: lldb.SBType = self._inner().GetType() | ||
result.append(type.GetFieldAtIndex(i).GetName()) | ||
return result | ||
|
||
def getCurrentValue(self) -> lldb.SBValue: | ||
return self.getVariantByIndex(self.getCurrentVariantIndex()) |
Oops, something went wrong.