authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-10-16 18:36:25-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-10-21 10:04:01-07:00
log77576c960388f0ad6712f1e15b97ca689892d708
tree24a197cf1c1def6d297f7605aa75f1089281f702
parentbaed9626d075628887b7d5400fb03efcb9910050

lldb/pretty_printers.py: support new `MultiArrayList.pointer_stability`

Also fix unwrapped printing of reified union types.

2 files changed, 103 insertions(+), 51 deletions(-)

lib/lldb/pretty_printers.py+100-51
......@@ -13,34 +13,73 @@ page_size = 1 << 12
1313
1414def log2_int(i): return i.bit_length() - 1
1515
16def create_struct(parent, name, struct_type, inits):
17 struct_bytes, struct_data = bytearray(struct_type.size), lldb.SBData()
18 for field in struct_type.fields:
19 field_size = field.type.size
20 field_init = inits[field.name]
21 if isinstance(field_init, int):
22 match struct_data.byte_order:
23 case lldb.eByteOrderLittle:
24 byte_order = 'little'
25 case lldb.eByteOrderBig:
26 byte_order = 'big'
27 field_bytes = field_init.to_bytes(field_size, byte_order, signed=field.type.GetTypeFlags() & lldb.eTypeIsSigned != 0)
28 elif isinstance(field_init, lldb.SBValue):
29 field_bytes = field_init.data.uint8
30 else: return
31 match struct_data.byte_order:
16class ValueInit:
17 def __init__(self, value: lldb.SBValue): self.value = value
18 def toBytes(self, parent: lldb.SBValue, value_type: lldb.SBType) -> bytes:
19 return self.value.data.uint8
20 def create(self, parent: lldb.SBValue, name: str, value_type: lldb.SBType) -> lldb.SBValue:
21 return self.value.Clone(name)
22
23class FromBytes(ValueInit):
24 def __init__(self, value_bytes: bytes): self.value_bytes = value_bytes
25 def toBytes(self, parent: lldb.SBValue, value_type: lldb.SBType) -> bytes: return self.value_bytes
26 def create(self, parent: lldb.SBValue, name: str, value_type: lldb.SBType) -> lldb.SBValue:
27 data = lldb.SBData()
28 error = lldb.SBError()
29 value_bytes = self.toBytes(parent, value_type);
30 target = parent.target
31 data.SetData(error, value_bytes, target.byte_order, target.addr_size)
32 return parent.CreateValueFromData(name, data, value_type)
33
34class IntLiteral(FromBytes):
35 def __init__(self, int_value: int): self.int_value = int_value
36 def toBytes(self, parent: lldb.SBValue, int_type: lldb.SBType) -> bytes:
37 int_flags = int_type.GetTypeFlags()
38 assert int_flags & lldb.eTypeIsInteger != 0
39 int_is_signed = int_flags & lldb.eTypeIsSigned != 0
40 match parent.target.byte_order:
3241 case lldb.eByteOrderLittle:
33 field_bytes = field_bytes[:field_size]
34 field_start = field.byte_offset
35 struct_bytes[field_start:field_start + len(field_bytes)] = field_bytes
42 byte_order = 'little'
3643 case lldb.eByteOrderBig:
37 field_bytes = field_bytes[-field_size:]
38 field_end = field.byte_offset + field_size
39 struct_bytes[field_end - len(field_bytes):field_end] = field_bytes
40 struct_data.SetData(lldb.SBError(), struct_bytes, struct_data.byte_order, struct_data.GetAddressByteSize())
41 return parent.CreateValueFromData(name, struct_data, struct_type)
42
43# Define Zig Language
44 byte_order = 'big'
45 return self.int_value.to_bytes(int_type.size, byte_order, signed=int_is_signed)
46
47class FromBackingInt(FromBytes):
48 def __init__(self, field_value: int): self.field_value = field_value
49 def fieldValue(self, enum_type: lldb.SBType) -> int: return self.field_value
50 def toBytes(self, parent: lldb.SBValue, enum_type: lldb.SBType) -> bytes:
51 assert enum_type.type == lldb.eTypeClassEnumeration
52 backing_int = IntLiteral(self.fieldValue(enum_type));
53 return backing_int.toBytes(parent, enum_type.GetEnumerationIntegerType())
54
55class EnumField(FromBackingInt):
56 def __init__(self, field_index: int): self.field_index = field_index
57 def fieldIndex(self, enum_type: lldb.SBType) -> int: return self.field_index
58 def fieldValue(self, enum_type: lldb.SBType) -> int:
59 enum_is_signed = enum_type.GetEnumerationIntegerType().GetTypeFlags() & lldb.eTypeIsSigned != 0
60 field = enum_type.enum_members[self.fieldIndex(enum_type)]
61 return field.signed if enum_is_signed else field.unsigned
62
63class EnumLiteral(EnumField):
64 def __init__(self, field_name: str): self.field_name = field_name
65 def fieldName(self, enum_type: lldb.SBType) -> str: return self.field_name
66 def fieldIndex(self, enum_type: lldb.SBType) -> int:
67 field_name = self.fieldName(enum_type)
68 return next(field_index for field_index, field in enumerate(enum_type.enum_members)
69 if field.name == field_name)
70
71class StructInit(FromBytes):
72 def __init__(self, field_inits: dict[str, ValueInit]): self.field_inits = field_inits
73 def toBytes(self, parent: lldb.SBValue, struct_type: lldb.SBType) -> bytes:
74 assert struct_type.type == lldb.eTypeClassStruct
75 struct_bytes = bytearray(struct_type.size)
76 for field in struct_type.fields:
77 field_bytes = self.field_inits[field.name].toBytes(parent, field.type)
78 assert len(field_bytes) == field.type.size
79 struct_bytes[field.byte_offset:field.byte_offset + len(field_bytes)] = field_bytes
80 return bytes(struct_bytes)
81
82# Define Zig Language (for programs compiled with the llvm backend)
4483
4584zig_keywords = {
4685 'addrspace',
......@@ -204,7 +243,7 @@ class zig_TaggedUnion_SynthProvider:
204243 except: return -1
205244 def get_child_at_index(self, index): return (self.tag, self.payload)[index] if index in range(2) else None
206245
207# Define Zig Standard Library
246# Define Zig Standard Library (for programs compiled with the llvm backend)
208247
209248class std_MultiArrayList_SynthProvider:
210249 def __init__(self, value, _=None): self.value = value
......@@ -331,7 +370,7 @@ class std_Entry_SynthProvider:
331370 def get_child_index(self, name): return self.indices.get(name)
332371 def get_child_at_index(self, index): return self.children[index].deref if index in range(len(self.children)) else None
333372
334# Define Zig Compiler
373# Define Zig Compiler (compiled with the llvm backend)
335374
336375class TagAndPayload_SynthProvider:
337376 def __init__(self, value, _=None): self.value = value
......@@ -435,8 +474,9 @@ class InternPool_Index_SynthProvider:
435474 def __init__(self, value, _=None): self.value = value
436475 def update(self):
437476 try:
477 target = self.value.target
438478 index_type = self.value.type
439 for helper in self.value.target.FindFunctions('%s.dbHelper' % index_type.name, lldb.eFunctionNameTypeFull):
479 for helper in target.FindFunctions('%s.dbHelper' % index_type.name, lldb.eFunctionNameTypeFull):
440480 ptr_self_type, ptr_tag_to_encoding_map_type = helper.function.type.GetFunctionArgumentTypes()
441481 if ptr_self_type.GetPointeeType() == index_type: break
442482 else: return
......@@ -465,7 +505,7 @@ class InternPool_Index_SynthProvider:
465505 for trailing_field in encoding_field.type.fields:
466506 trailing_data.Append(extra.GetChildAtIndex(extra_index).address_of.data)
467507 trailing_len = dynamic_values['trailing.%s.len' % trailing_field.name].unsigned
468 trailing_data.Append(lldb.SBData.CreateDataFromInt(trailing_len, trailing_data.GetAddressByteSize()))
508 trailing_data.Append(lldb.SBData.CreateDataFromInt(trailing_len, target.addr_size, target=target))
469509 extra_index += trailing_len
470510 self.trailing = self.data.CreateValueFromData('trailing', trailing_data, encoding_field.type)
471511 else:
......@@ -685,8 +725,18 @@ value_tag_handlers = {
685725class root_InternPool_Local_List_SynthProvider:
686726 def __init__(self, value, _=None): self.value = value
687727 def update(self):
688 capacity = self.value.EvaluateExpression('@as(*@This().Header, @alignCast(@ptrCast(@this().bytes - @This().bytes_offset))).capacity')
689 self.view = create_struct(self.value, '.view', self.value.type.FindDirectNestedType('View'), { 'bytes': self.value.GetChildMemberWithName('bytes'), 'len': capacity, 'capacity': capacity }).GetNonSyntheticValue()
728 capacity = IntLiteral(self.value.EvaluateExpression(
729 '@as(*@This().Header, @alignCast(@ptrCast(@this().bytes - @This().bytes_offset))).capacity',
730 ).unsigned)
731 View = self.value.type.FindDirectNestedType('View')
732 self.view = StructInit({
733 'bytes': ValueInit(self.value.GetChildMemberWithName('bytes')),
734 'len': capacity,
735 'capacity': capacity,
736 'pointer_stability': StructInit({
737 'state': EnumField(0),
738 }),
739 }).create(self.value, '.view', View).GetNonSyntheticValue()
690740 def has_children(self): return True
691741 def num_children(self): return 1
692742 def get_child_index(self, name):
......@@ -719,7 +769,10 @@ class root_InternPool_Index_SynthProvider:
719769 unwrapped_type = self.value.type.FindDirectNestedType('Unwrapped')
720770 ip = self.value.CreateValueFromType(unwrapped_type).GetChildMemberWithName('debug_state').GetChildMemberWithName('intern_pool').GetNonSyntheticValue().GetChildMemberWithName('?')
721771 tid_shift_30 = ip.GetChildMemberWithName('tid_shift_30').unsigned
722 self.unwrapped = create_struct(self.value, '.unwrapped', unwrapped_type, { 'tid': wrapped >> tid_shift_30, 'index': wrapped & (1 << tid_shift_30) - 1 })
772 self.unwrapped = StructInit({
773 'tid': FromBackingInt(wrapped >> tid_shift_30),
774 'index': IntLiteral(wrapped & (1 << tid_shift_30) - 1),
775 }).create(self.value, '.unwrapped', unwrapped_type)
723776 def has_children(self): return True
724777 def num_children(self): return 0
725778 def get_child_index(self, name):
......@@ -732,6 +785,7 @@ class root_InternPool_Index_SynthProvider:
732785class root_InternPool_Index_Unwrapped_SynthProvider:
733786 def __init__(self, value, _=None): self.value = value
734787 def update(self):
788 target = self.value.target
735789 self.tag, self.index, self.data, self.payload, self.trailing = None, None, None, None, None
736790 index = self.value.GetChildMemberWithName('index')
737791 ip = self.value.CreateValueFromType(self.value.type).GetChildMemberWithName('debug_state').GetChildMemberWithName('intern_pool').GetNonSyntheticValue().GetChildMemberWithName('?')
......@@ -742,36 +796,34 @@ class root_InternPool_Index_Unwrapped_SynthProvider:
742796 encoding_index, encoding_data, encoding_payload, encoding_trailing, encoding_config = encoding.GetChildMemberWithName('index'), encoding.GetChildMemberWithName('data'), encoding.GetChildMemberWithName('payload'), encoding.GetChildMemberWithName('trailing'), encoding.GetChildMemberWithName('config')
743797 if encoding_index:
744798 index_type = encoding_index.GetValueAsType()
745 index_bytes, index_data = index.data.uint8, lldb.SBData()
746 match index_data.byte_order:
799 index_bytes = index.data.uint8
800 match target.byte_order:
747801 case lldb.eByteOrderLittle:
748802 index_bytes = bytes(index_bytes[:index_type.size])
749803 case lldb.eByteOrderBig:
750804 index_bytes = bytes(index_bytes[-index_type.size:])
751 index_data.SetData(lldb.SBError(), index_bytes, index_data.byte_order, index_data.GetAddressByteSize())
752 self.index = self.value.CreateValueFromData('.index', index_data, index_type)
805 self.index = FromBytes(index_bytes).create(self.value, '.index', index_type)
753806 elif encoding_data:
754807 data_type = encoding_data.GetValueAsType()
755 data_bytes, data_data = item_data.data.uint8, lldb.SBData()
756 match data_data.byte_order:
808 data_bytes = item_data.data.uint8
809 match target.byte_order:
757810 case lldb.eByteOrderLittle:
758811 data_bytes = bytes(data_bytes[:data_type.size])
759812 case lldb.eByteOrderBig:
760813 data_bytes = bytes(data_bytes[-data_type.size:])
761 data_data.SetData(lldb.SBError(), data_bytes, data_data.byte_order, data_data.GetAddressByteSize())
762 self.data = self.value.CreateValueFromData('.data', data_data, data_type)
814 self.data = FromBytes(data_bytes).create(self.value, '.data', data_type)
763815 elif encoding_payload:
764816 extra = shared.GetChildMemberWithName('extra').GetChildMemberWithName('view').GetChildMemberWithName('0')
765817 extra_index = item_data.unsigned
766818 payload_type = encoding_payload.GetValueAsType()
767819 payload_fields = dict()
768820 for payload_field in payload_type.fields:
769 payload_fields[payload_field.name] = extra.child[extra_index]
821 payload_fields[payload_field.name] = ValueInit(extra.child[extra_index])
770822 extra_index += 1
771 self.payload = create_struct(self.value, '.payload', payload_type, payload_fields)
823 self.payload = StructInit(payload_fields).create(self.value, '.payload', payload_type)
772824 if encoding_trailing and encoding_config:
773825 trailing_type = encoding_trailing.GetValueAsType()
774 trailing_bytes, trailing_data = bytearray(trailing_type.size), lldb.SBData()
826 trailing_bytes = bytearray(trailing_type.size)
775827 def eval_config(config_name):
776828 expr = encoding_config.GetChildMemberWithName(config_name).value.removeprefix('.').removeprefix('@"').removesuffix('"').replace(r'\"', '"')
777829 if 'payload.' in expr:
......@@ -780,13 +832,11 @@ class root_InternPool_Index_Unwrapped_SynthProvider:
780832 field_type, field_byte_offset = trailing_type, 0
781833 expr_parts = expr.split('.')
782834 for expr_part in expr_parts[1:]:
783 field = next(filter(lambda field: field.name == expr_part, field_type.fields))
835 field = next(field for field in field_type.fields if field.name == expr_part)
784836 field_type = field.type
785837 field_byte_offset += field.byte_offset
786 field_data = lldb.SBData()
787838 field_bytes = trailing_bytes[field_byte_offset:field_byte_offset + field_type.size]
788 field_data.SetData(lldb.SBError(), field_bytes, field_data.byte_order, field_data.GetAddressByteSize())
789 return self.value.CreateValueFromData('.%s' % expr_parts[-1], field_data, field_type)
839 return FromBytes(field_bytes).create(self.value, '.%s' % expr_parts[-1], field_type)
790840 else:
791841 return self.value.frame.EvaluateExpression(expr)
792842 for trailing_field in trailing_type.fields:
......@@ -812,7 +862,7 @@ class root_InternPool_Index_Unwrapped_SynthProvider:
812862 trailing_bytes[ptr_field_byte_offset:ptr_field_byte_offset + ptr_field.type.size] = extra.child[extra_index].address_of.data.uint8
813863 len_field_value = eval_config('%s.len' % trailing_field_name)
814864 len_field_size = len_field.type.size
815 match trailing_data.byte_order:
865 match target.byte_order:
816866 case lldb.eByteOrderLittle:
817867 len_field_bytes = len_field_value.data.uint8[:len_field_size]
818868 trailing_bytes[len_field_byte_offset:len_field_byte_offset + len(len_field_bytes)] = len_field_bytes
......@@ -827,8 +877,7 @@ class root_InternPool_Index_Unwrapped_SynthProvider:
827877 trailing_bytes[trailing_field_byte_offset + offset:trailing_field_byte_offset + offset + 4] = extra.child[extra_index].data.uint8
828878 extra_index += 1
829879 break
830 trailing_data.SetData(lldb.SBError(), trailing_bytes, trailing_data.byte_order, trailing_data.GetAddressByteSize())
831 self.trailing = self.value.CreateValueFromData('.trailing', trailing_data, trailing_type)
880 self.trailing = FromBytes(trailing_bytes).create(self.value, '.trailing', trailing_type)
832881 def has_children(self): return True
833882 def num_children(self): return 1 + ((self.index or self.data or self.payload) is not None) + (self.trailing is not None)
834883 def get_child_index(self, name):
src/InternPool.zig+3
......@@ -5255,6 +5255,7 @@ pub const Tag = enum(u8) {
52555255 type_hash: ?u64,
52565256 captures_len: ?u32,
52575257 captures: ?[]CaptureValue,
5258 reified_field_name: ?[]NullTerminatedString,
52585259 field_types: []Index,
52595260 field_aligns: ?[]Alignment,
52605261 },
......@@ -5263,6 +5264,8 @@ pub const Tag = enum(u8) {
52635264 .@"trailing.captures_len.?" = .@"payload.flags.any_captures == .true",
52645265 .@"trailing.captures.?" = .@"payload.flags.any_captures == .true",
52655266 .@"trailing.captures.?.len" = .@"trailing.captures_len.?",
5267 .@"trailing.reified_field_name.?" = .@"payload.flags.any_captures == .reified",
5268 .@"trailing.reified_field_name.?.len" = .@"payload.fields_len",
52665269 .@"trailing.field_types.len" = .@"payload.fields_len",
52675270 .@"trailing.field_aligns.?" = .@"payload.flags.any_field_aligns",
52685271 .@"trailing.field_aligns.?.len" = .@"(payload.fields_len + 3) & ~@as(u32, 3)",