Files
swift-mirror/utils/lldb/lldbSwiftDataFormatters.py
Dave Lee 3ac427f94e [utils] Update Demangle::Node data formatter (#82739)
Updates the lldb data formatter for `Demangle::Node` to reflect the
current `PayloadKind` enum values (which were changed in
https://github.com/swiftlang/swift/pull/72884).
2025-07-04 21:36:37 -07:00

182 lines
6.7 KiB
Python

"""
LLDB Formatters for LLVM data types for use in the swift project.
Load into LLDB with 'command script import /path/to/lldbSwiftDataFormatters.py'
"""
import sys
from enum import Enum
def __lldb_init_module(debugger, internal_dict):
category = 'swift-compiler-internals'
debugger.HandleCommand(f'type category define -e {category} -l c++')
tName = 'lldbSwiftDataFormatters.SmallBitVectorSummaryProvider'
debugger.HandleCommand('type summary add -w llvm '
f'-F {tName} -x "^llvm::SmallBitVector$"')
debugger.HandleCommand(f'type summary add --expand --skip-references -w {category} '
'-F lldbSwiftDataFormatters.DemangleNodeSummaryProvider '
'-x "^swift::Demangle::Node$"')
debugger.HandleCommand(f'type synthetic add --skip-references -w {category} '
'-l lldbSwiftDataFormatters.DemangleNodeSynthProvider '
'-x "^swift::Demangle::Node$"')
debugger.HandleCommand(f'type summary add -w {category} '
'-s "${var.Pointer%S}" '
'swift::Identifier')
def SmallBitVectorSummaryProvider(valobj, internal_dict):
underlyingValue = valobj.GetChildMemberWithName('X').GetValueAsUnsigned()
numBaseBits = 32
is64Bit = sys.maxsize > 2**32
if is64Bit:
numBaseBits = 64
smallNumRawBits = numBaseBits - 1
smallNumSizeBits = None
if numBaseBits == 32:
smallNumSizeBits = 5
elif numBaseBits == 64:
smallNumSizeBits = 6
else:
smallNumSizeBits = smallNumRawBits
smallNumDataBits = smallNumRawBits - smallNumSizeBits
# If our underlying value is not small, print we can not dump large values.
isSmallMask = 1
if (underlyingValue & isSmallMask) == 0:
return '<can not read large SmallBitVector>'
smallRawBits = underlyingValue >> 1
smallSize = smallRawBits >> smallNumDataBits
bits = smallRawBits & ((1 << (smallSize + 1)) - 1)
res = "["
for i in reversed(range(0, smallSize)):
if bool(bits & (1 << i)):
res += '1'
else:
res += '0'
res += "]"
return res
class DemangleNodePayloadKind(Enum):
NONE = 0
ONE_CHILD = 1
TWO_CHILDREN = 2
TEXT = 3
INDEX = 4
MANY_CHILDREN = 5
class DemangleNodeSynthProvider:
""" Provider for swift::Demangle::Node """
def __init__(self, valobj, internal_dict):
self.valobj = valobj
self.update() # initialize this provider
def num_children(self):
if self.payload_kind in [DemangleNodePayloadKind.TEXT,
DemangleNodePayloadKind.INDEX,
DemangleNodePayloadKind.ONE_CHILD]:
return 2
if self.payload_kind is DemangleNodePayloadKind.TWO_CHILDREN:
return 3
if self.payload_kind is DemangleNodePayloadKind.MANY_CHILDREN:
return self.payload.GetChildMemberWithName('Children'). \
GetChildMemberWithName('Number').GetValueAsUnsigned() + 1
return 1
def get_child_index(self, name):
if name == 'NodeKind':
return 0
if self.payload_kind is DemangleNodePayloadKind.TEXT and name == 'Text':
return 1
if self.payload_kind is DemangleNodePayloadKind.INDEX and name == 'Index':
return 1
if self.payload_kind is DemangleNodePayloadKind.NONE:
return None
try:
return int(name.lstrip('[').rstrip(']')) + 1
except ValueError:
return None
def get_child_at_index(self, index):
if index == 0:
return self.valobj.GetChildMemberWithName('NodeKind')
index -= 1
if self.payload_kind is DemangleNodePayloadKind.TEXT and index == 0:
return self.payload.GetChildMemberWithName('Text')
if self.payload_kind is DemangleNodePayloadKind.INDEX and index == 0:
return self.payload.GetChildMemberWithName('Index')
if self.payload_kind is DemangleNodePayloadKind.ONE_CHILD \
and index == 0:
return self.payload \
.GetChildMemberWithName('InlineChildren') \
.GetChildAtIndex(0)
if self.payload_kind is DemangleNodePayloadKind.TWO_CHILDREN \
and 0 <= index <= 1:
return self.payload \
.GetChildMemberWithName('InlineChildren') \
.GetChildAtIndex(index)
if self.payload_kind is DemangleNodePayloadKind.MANY_CHILDREN \
and index >= 0:
node_vector = self.payload.GetChildMemberWithName('Children')
length = node_vector.GetChildMemberWithName('Number')
if index >= length.GetValueAsUnsigned():
return None
nodes_ptr = node_vector.GetChildMemberWithName('Nodes')
offset = self.node_ptr_size * index
return nodes_ptr.CreateChildAtOffset('[' + str(index) + ']',
offset, self.node_ptr_type)
return None
def update(self):
self.payload_kind = DemangleNodePayloadKind(
self.valobj.GetChildMemberWithName('NodePayloadKind').GetValueAsUnsigned()
)
valobj_type = self.valobj.GetType()
if valobj_type.IsPointerType():
self.node_ptr_type = valobj_type
else:
self.node_ptr_type = valobj_type.GetPointerType()
self.node_ptr_size = self.node_ptr_type.GetByteSize()
self.payload = self.valobj.GetChildAtIndex(0)
def DemangleNodeSummaryProvider(valobj, internal_dict):
valobj = valobj.GetNonSyntheticValue()
result = valobj.GetChildMemberWithName('NodeKind').GetValue()
result += ', '
payload_kind = DemangleNodePayloadKind(
valobj.GetChildMemberWithName('NodePayloadKind').GetValueAsUnsigned()
)
if payload_kind is DemangleNodePayloadKind.NONE:
result += '0 children'
if payload_kind is DemangleNodePayloadKind.TEXT:
result += 'Text='
result += valobj \
.GetChildAtIndex(0) \
.GetChildMemberWithName('Text') \
.GetSummary()
if payload_kind is DemangleNodePayloadKind.INDEX:
result += 'Index='
index = valobj \
.GetChildAtIndex(0) \
.GetChildMemberWithName('Index') \
.GetValueAsUnsigned()
result += str(index)
if payload_kind is DemangleNodePayloadKind.ONE_CHILD:
result += '1 child'
if payload_kind in [DemangleNodePayloadKind.TWO_CHILDREN,
DemangleNodePayloadKind.MANY_CHILDREN]:
num_children = \
DemangleNodeSynthProvider(valobj, internal_dict).num_children() - 1
result += str(num_children)
result += ' children'
return result