authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-10-16 23:33:13-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-10-17 07:55:28-04:00
log1e963053d0ff67361b587b046a917375e963d5e9
treec5a318eef4ee88c6539919335f35e6955f1b7f0d
parentc010767311904177681280c6427eb360200df28f

tools: add lldb stage2 pretty printers

* Fix untagged struct names in debug info for llvm. * Factor out common stage2 pretty printer data. * Add lldb version of stage2 pretty printers.

6 files changed, 169 insertions(+), 108 deletions(-)

src/codegen/llvm.zig+1-1
...@@ -2153,7 +2153,7 @@ pub const Object = struct {...@@ -2153,7 +2153,7 @@ pub const Object = struct {
2153 ));2153 ));
2154 }2154 }
21552155
2156 const union_name = if (layout.tag_size == 0) "AnonUnion" else name.ptr;2156 const union_name = if (layout.tag_size == 0) name.ptr else "AnonUnion";
21572157
2158 const union_di_ty = dib.createUnionType(2158 const union_di_ty = dib.createUnionType(
2159 compile_unit_scope,2159 compile_unit_scope,
src/type.zig+1-1
...@@ -6062,7 +6062,7 @@ pub const Type = extern union {...@@ -6062,7 +6062,7 @@ pub const Type = extern union {
6062 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;6062 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
60636063
6064 pub fn Type(comptime t: Tag) type {6064 pub fn Type(comptime t: Tag) type {
6065 // Keep in sync with tools/zig-gdb.py6065 // Keep in sync with tools/stage2_pretty_printers_common.py
6066 return switch (t) {6066 return switch (t) {
6067 .u1,6067 .u1,
6068 .u8,6068 .u8,
src/value.zig+1-1
...@@ -22,7 +22,7 @@ pub const Value = extern union {...@@ -22,7 +22,7 @@ pub const Value = extern union {
22 tag_if_small_enough: Tag,22 tag_if_small_enough: Tag,
23 ptr_otherwise: *Payload,23 ptr_otherwise: *Payload,
2424
25 // Keep in sync with tools/zig-gdb.py25 // Keep in sync with tools/stage2_pretty_printers_common.py
26 pub const Tag = enum(usize) {26 pub const Tag = enum(usize) {
27 // The first section of this enum are tags that require no payload.27 // The first section of this enum are tags that require no payload.
28 u1_type,28 u1_type,
tools/stage2_gdb_pretty_printers.py+9-105
...@@ -2,56 +2,9 @@...@@ -2,56 +2,9 @@
2# put "source /path/to/stage2_gdb_pretty_printers.py" in ~/.gdbinit to load it automatically.2# put "source /path/to/stage2_gdb_pretty_printers.py" in ~/.gdbinit to load it automatically.
3import re3import re
4import gdb.printing4import gdb.printing
5import stage2_pretty_printers_common as common
56
6class TypePrinter:7class TypePrinter:
7 no_payload_count = 4096
8
9 # Keep in sync with src/type.zig
10 # Types which have no payload do not need to be entered here.
11 payload_type_names = {
12 'array_u8': 'Type.Payload.Len',
13 'array_u8_sentinel_0': 'Type.Payload.Len',
14
15 'single_const_pointer': 'Type.Payload.ElemType',
16 'single_mut_pointer': 'Type.Payload.ElemType',
17 'many_const_pointer': 'Type.Payload.ElemType',
18 'many_mut_pointer': 'Type.Payload.ElemType',
19 'c_const_pointer': 'Type.Payload.ElemType',
20 'c_mut_pointer': 'Type.Payload.ElemType',
21 'const_slice': 'Type.Payload.ElemType',
22 'mut_slice': 'Type.Payload.ElemType',
23 'optional': 'Type.Payload.ElemType',
24 'optional_single_mut_pointer': 'Type.Payload.ElemType',
25 'optional_single_const_pointer': 'Type.Payload.ElemType',
26 'anyframe_T': 'Type.Payload.ElemType',
27
28 'int_signed': 'Type.Payload.Bits',
29 'int_unsigned': 'Type.Payload.Bits',
30
31 'error_set': 'Type.Payload.ErrorSet',
32 'error_set_inferred': 'Type.Payload.ErrorSetInferred',
33 'error_set_merged': 'Type.Payload.ErrorSetMerged',
34
35 'array': 'Type.Payload.Array',
36 'vector': 'Type.Payload.Array',
37
38 'array_sentinel': 'Type.Payload.ArraySentinel',
39 'pointer': 'Type.Payload.Pointer',
40 'function': 'Type.Payload.Function',
41 'error_union': 'Type.Payload.ErrorUnion',
42 'error_set_single': 'Type.Payload.Name',
43 'opaque': 'Type.Payload.Opaque',
44 'struct': 'Type.Payload.Struct',
45 'union': 'Type.Payload.Union',
46 'union_tagged': 'Type.Payload.Union',
47 'enum_full, .enum_nonexhaustive': 'Type.Payload.EnumFull',
48 'enum_simple': 'Type.Payload.EnumSimple',
49 'enum_numbered': 'Type.Payload.EnumNumbered',
50 'empty_struct': 'Type.Payload.ContainerScope',
51 'tuple': 'Type.Payload.Tuple',
52 'anon_struct': 'Type.Payload.AnonStruct',
53 }
54
55 def __init__(self, val):8 def __init__(self, val):
56 self.val = val9 self.val = val
5710
...@@ -59,7 +12,7 @@ class TypePrinter:...@@ -59,7 +12,7 @@ class TypePrinter:
59 tag_if_small_enough = self.val['tag_if_small_enough']12 tag_if_small_enough = self.val['tag_if_small_enough']
60 tag_type = tag_if_small_enough.type13 tag_type = tag_if_small_enough.type
6114
62 if tag_if_small_enough < TypePrinter.no_payload_count:15 if tag_if_small_enough < common.Type.no_payload_count:
63 return tag_if_small_enough16 return tag_if_small_enough
64 else:17 else:
65 return self.val['ptr_otherwise'].dereference()['tag']18 return self.val['ptr_otherwise'].dereference()['tag']
...@@ -69,7 +22,7 @@ class TypePrinter:...@@ -69,7 +22,7 @@ class TypePrinter:
69 if tag is None:22 if tag is None:
70 return None23 return None
7124
72 type_name = TypePrinter.payload_type_names.get(str(tag))25 type_name = common.Type.payload_type_names.get(str(tag))
73 if type_name is None:26 if type_name is None:
74 return None27 return None
75 return gdb.lookup_type('struct type.%s' % type_name)28 return gdb.lookup_type('struct type.%s' % type_name)
...@@ -78,12 +31,12 @@ class TypePrinter:...@@ -78,12 +31,12 @@ class TypePrinter:
78 tag = self.tag()31 tag = self.tag()
79 if tag is None:32 if tag is None:
80 return '(invalid type)'33 return '(invalid type)'
81 if self.val['tag_if_small_enough'] < TypePrinter.no_payload_count:34 if self.val['tag_if_small_enough'] < common.Type.no_payload_count:
82 return '.%s' % str(tag)35 return '.%s' % str(tag)
83 return None36 return None
8437
85 def children(self):38 def children(self):
86 if self.val['tag_if_small_enough'] < TypePrinter.no_payload_count:39 if self.val['tag_if_small_enough'] < common.Type.no_payload_count:
87 return40 return
8841
89 yield ('tag', '.%s' % str(self.tag()))42 yield ('tag', '.%s' % str(self.tag()))
...@@ -93,55 +46,6 @@ class TypePrinter:...@@ -93,55 +46,6 @@ class TypePrinter:
93 yield ('payload', self.val['ptr_otherwise'].cast(payload_type.pointer()).dereference()['data'])46 yield ('payload', self.val['ptr_otherwise'].cast(payload_type.pointer()).dereference()['data'])
9447
95class ValuePrinter:48class ValuePrinter:
96 no_payload_count = 4096
97
98 # Keep in sync with src/value.zig
99 # Values which have no payload do not need to be entered here.
100 payload_type_names = {
101 'big_int_positive': 'Value.Payload.BigInt',
102 'big_int_negative': 'Value.Payload.BigInt',
103
104 'extern_fn': 'Value.Payload.ExternFn',
105
106 'decl_ref': 'Value.Payload.Decl',
107
108 'repeated': 'Value.Payload.SubValue',
109 'eu_payload': 'Value.Payload.SubValue',
110 'opt_payload': 'Value.Payload.SubValue',
111 'empty_array_sentinel': 'Value.Payload.SubValue',
112
113 'eu_payload_ptr': 'Value.Payload.PayloadPtr',
114 'opt_payload_ptr': 'Value.Payload.PayloadPtr',
115
116 'bytes': 'Value.Payload.Bytes',
117 'enum_literal': 'Value.Payload.Bytes',
118
119 'slice': 'Value.Payload.Slice',
120
121 'enum_field_index': 'Value.Payload.U32',
122
123 'ty': 'Value.Payload.Ty',
124 'int_type': 'Value.Payload.IntType',
125 'int_u64': 'Value.Payload.U64',
126 'int_i64': 'Value.Payload.I64',
127 'function': 'Value.Payload.Function',
128 'variable': 'Value.Payload.Variable',
129 'decl_ref_mut': 'Value.Payload.DeclRefMut',
130 'elem_ptr': 'Value.Payload.ElemPtr',
131 'field_ptr': 'Value.Payload.FieldPtr',
132 'float_16': 'Value.Payload.Float_16',
133 'float_32': 'Value.Payload.Float_32',
134 'float_64': 'Value.Payload.Float_64',
135 'float_80': 'Value.Payload.Float_80',
136 'float_128': 'Value.Payload.Float_128',
137 'error': 'Value.Payload.Error',
138 'inferred_alloc': 'Value.Payload.InferredAlloc',
139 'inferred_alloc_comptime': 'Value.Payload.InferredAllocComptime',
140 'aggregate': 'Value.Payload.Aggregate',
141 'union': 'Value.Payload.Union',
142 'bound_fn': 'Value.Payload.BoundFn',
143 }
144
145 def __init__(self, val):49 def __init__(self, val):
146 self.val = val50 self.val = val
14751
...@@ -149,7 +53,7 @@ class ValuePrinter:...@@ -149,7 +53,7 @@ class ValuePrinter:
149 tag_if_small_enough = self.val['tag_if_small_enough']53 tag_if_small_enough = self.val['tag_if_small_enough']
150 tag_type = tag_if_small_enough.type54 tag_type = tag_if_small_enough.type
15155
152 if tag_if_small_enough < ValuePrinter.no_payload_count:56 if tag_if_small_enough < common.Value.no_payload_count:
153 return tag_if_small_enough57 return tag_if_small_enough
154 else:58 else:
155 return self.val['ptr_otherwise'].dereference()['tag']59 return self.val['ptr_otherwise'].dereference()['tag']
...@@ -159,7 +63,7 @@ class ValuePrinter:...@@ -159,7 +63,7 @@ class ValuePrinter:
159 if tag is None:63 if tag is None:
160 return None64 return None
16165
162 type_name = ValuePrinter.payload_type_names.get(str(tag))66 type_name = Comman.Value.payload_type_names.get(str(tag))
163 if type_name is None:67 if type_name is None:
164 return None68 return None
165 return gdb.lookup_type('struct value.%s' % type_name)69 return gdb.lookup_type('struct value.%s' % type_name)
...@@ -168,12 +72,12 @@ class ValuePrinter:...@@ -168,12 +72,12 @@ class ValuePrinter:
168 tag = self.tag()72 tag = self.tag()
169 if tag is None:73 if tag is None:
170 return '(invalid value)'74 return '(invalid value)'
171 if self.val['tag_if_small_enough'] < ValuePrinter.no_payload_count:75 if self.val['tag_if_small_enough'] < common.Value.no_payload_count:
172 return '.%s' % str(tag)76 return '.%s' % str(tag)
173 return None77 return None
17478
175 def children(self):79 def children(self):
176 if self.val['tag_if_small_enough'] < ValuePrinter.no_payload_count:80 if self.val['tag_if_small_enough'] < common.Value.no_payload_count:
177 return81 return
17882
179 yield ('tag', '.%s' % str(self.tag()))83 yield ('tag', '.%s' % str(self.tag()))
tools/stage2_lldb_pretty_printers.py created+59
...@@ -0,0 +1,59 @@
1# pretty printing for stage 2.
2# put "command script /path/to/stage2_lldb_pretty_printers.py" and "type category enable stage2" in ~/.lldbinit to load it automatically.
3import lldb
4import stage2_pretty_printers_common as common
5
6category = 'stage2'
7module = category + '_lldb_pretty_printers'
8
9class type_Type_SynthProvider:
10 def __init__(self, type, _=None):
11 self.type = type
12
13 def update(self):
14 self.tag = self.type.GetChildMemberWithName('tag_if_small_enough').Clone('tag')
15 self.payload = None
16 if self.tag.GetValueAsUnsigned() >= common.Type.no_payload_count:
17 ptr_otherwise = self.type.GetChildMemberWithName('ptr_otherwise')
18 self.tag = ptr_otherwise.Dereference().GetChildMemberWithName('tag')
19 payload_type = self.type.target.FindFirstType('type.' + common.Type.payload_type_names[self.tag.GetValue()])
20 self.payload = ptr_otherwise.Cast(payload_type.GetPointerType()).Dereference().GetChildMemberWithName('data').Clone('payload')
21
22 def num_children(self):
23 return 1 + (self.payload is not None)
24
25 def get_child_index(self, name):
26 return ['tag', 'payload'].index(name)
27
28 def get_child_at_index(self, index):
29 return [self.tag, self.payload][index]
30
31class value_Value_SynthProvider:
32 def __init__(self, value, _=None):
33 self.value = value
34
35 def update(self):
36 self.tag = self.value.GetChildMemberWithName('tag_if_small_enough').Clone('tag')
37 self.payload = None
38 if self.tag.GetValueAsUnsigned() >= common.Value.no_payload_count:
39 ptr_otherwise = self.value.GetChildMemberWithName('ptr_otherwise')
40 self.tag = ptr_otherwise.Dereference().GetChildMemberWithName('tag')
41 payload_type = self.value.target.FindFirstType('value.' + common.Value.payload_type_names[self.tag.GetValue()])
42 self.payload = ptr_otherwise.Cast(payload_type.GetPointerType()).Dereference().GetChildMemberWithName('data').Clone('payload')
43
44 def num_children(self):
45 return 1 + (self.payload is not None)
46
47 def get_child_index(self, name):
48 return ['tag', 'payload'].index(name)
49
50 def get_child_at_index(self, index):
51 return [self.tag, self.payload][index]
52
53def add(debugger, type, summary=False, synth=False):
54 if summary: debugger.HandleCommand('type summary add --python-function ' + module + '.' + type.replace('.', '_') + '_SummaryProvider "' + type + '" --category ' + category)
55 if synth: debugger.HandleCommand('type synthetic add --python-class ' + module + '.' + type.replace('.', '_') + '_SynthProvider "' + type + '" --category ' + category)
56
57def __lldb_init_module(debugger, _=None):
58 add(debugger, 'type.Type', synth=True)
59 add(debugger, 'value.Value', synth=True)
tools/stage2_pretty_printers_common.py created+98
...@@ -0,0 +1,98 @@
1class Type:
2 no_payload_count = 4096
3
4 # Keep in sync with src/type.zig
5 # Types which have no payload do not need to be entered here.
6 payload_type_names = {
7 'array_u8': 'Type.Payload.Len',
8 'array_u8_sentinel_0': 'Type.Payload.Len',
9
10 'single_const_pointer': 'Type.Payload.ElemType',
11 'single_mut_pointer': 'Type.Payload.ElemType',
12 'many_const_pointer': 'Type.Payload.ElemType',
13 'many_mut_pointer': 'Type.Payload.ElemType',
14 'c_const_pointer': 'Type.Payload.ElemType',
15 'c_mut_pointer': 'Type.Payload.ElemType',
16 'const_slice': 'Type.Payload.ElemType',
17 'mut_slice': 'Type.Payload.ElemType',
18 'optional': 'Type.Payload.ElemType',
19 'optional_single_mut_pointer': 'Type.Payload.ElemType',
20 'optional_single_const_pointer': 'Type.Payload.ElemType',
21 'anyframe_T': 'Type.Payload.ElemType',
22
23 'int_signed': 'Type.Payload.Bits',
24 'int_unsigned': 'Type.Payload.Bits',
25
26 'error_set': 'Type.Payload.ErrorSet',
27 'error_set_inferred': 'Type.Payload.ErrorSetInferred',
28 'error_set_merged': 'Type.Payload.ErrorSetMerged',
29
30 'array': 'Type.Payload.Array',
31 'vector': 'Type.Payload.Array',
32
33 'array_sentinel': 'Type.Payload.ArraySentinel',
34 'pointer': 'Type.Payload.Pointer',
35 'function': 'Type.Payload.Function',
36 'error_union': 'Type.Payload.ErrorUnion',
37 'error_set_single': 'Type.Payload.Name',
38 'opaque': 'Type.Payload.Opaque',
39 'struct': 'Type.Payload.Struct',
40 'union': 'Type.Payload.Union',
41 'union_tagged': 'Type.Payload.Union',
42 'enum_full, .enum_nonexhaustive': 'Type.Payload.EnumFull',
43 'enum_simple': 'Type.Payload.EnumSimple',
44 'enum_numbered': 'Type.Payload.EnumNumbered',
45 'empty_struct': 'Type.Payload.ContainerScope',
46 'tuple': 'Type.Payload.Tuple',
47 'anon_struct': 'Type.Payload.AnonStruct',
48 }
49
50class Value:
51 no_payload_count = 4096
52
53 # Keep in sync with src/value.zig
54 # Values which have no payload do not need to be entered here.
55 payload_type_names = {
56 'big_int_positive': 'Value.Payload.BigInt',
57 'big_int_negative': 'Value.Payload.BigInt',
58
59 'extern_fn': 'Value.Payload.ExternFn',
60
61 'decl_ref': 'Value.Payload.Decl',
62
63 'repeated': 'Value.Payload.SubValue',
64 'eu_payload': 'Value.Payload.SubValue',
65 'opt_payload': 'Value.Payload.SubValue',
66 'empty_array_sentinel': 'Value.Payload.SubValue',
67
68 'eu_payload_ptr': 'Value.Payload.PayloadPtr',
69 'opt_payload_ptr': 'Value.Payload.PayloadPtr',
70
71 'bytes': 'Value.Payload.Bytes',
72 'enum_literal': 'Value.Payload.Bytes',
73
74 'slice': 'Value.Payload.Slice',
75
76 'enum_field_index': 'Value.Payload.U32',
77
78 'ty': 'Value.Payload.Ty',
79 'int_type': 'Value.Payload.IntType',
80 'int_u64': 'Value.Payload.U64',
81 'int_i64': 'Value.Payload.I64',
82 'function': 'Value.Payload.Function',
83 'variable': 'Value.Payload.Variable',
84 'decl_ref_mut': 'Value.Payload.DeclRefMut',
85 'elem_ptr': 'Value.Payload.ElemPtr',
86 'field_ptr': 'Value.Payload.FieldPtr',
87 'float_16': 'Value.Payload.Float_16',
88 'float_32': 'Value.Payload.Float_32',
89 'float_64': 'Value.Payload.Float_64',
90 'float_80': 'Value.Payload.Float_80',
91 'float_128': 'Value.Payload.Float_128',
92 'error': 'Value.Payload.Error',
93 'inferred_alloc': 'Value.Payload.InferredAlloc',
94 'inferred_alloc_comptime': 'Value.Payload.InferredAllocComptime',
95 'aggregate': 'Value.Payload.Aggregate',
96 'union': 'Value.Payload.Union',
97 'bound_fn': 'Value.Payload.BoundFn',
98 }