authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2022-03-16 18:13:10+01:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2022-03-16 18:13:10+01:00
log4ff7553d6b918e4eef643d10bd8f41492355f39c
treebfc47888a58259ea17fd1f0306c64875f563bbbe
parent0bd84e03b98a75806c47cb7f514a15de7e4d2b6e

gdb: restructure pretty printers into different files


5 files changed, 370 insertions(+), 391 deletions(-)

tools/stage1_gdb_pretty_printers.py created+37
...@@ -0,0 +1,37 @@
1# pretty printing for stage1.
2# put "source /path/to/stage1_gdb_pretty_printers.py" in ~/.gdbinit to load it automatically.
3import gdb.printing
4
5class ZigListPrinter:
6 def __init__(self, val):
7 self.val = val
8
9 def to_string(self):
10 return '%s of length %d, capacity %d' % (self.val.type.name, int(self.val['length']), int(self.val['capacity']))
11
12 def children(self):
13 def it(ziglist):
14 for i in range(int(ziglist.val['length'])):
15 item = ziglist.val['items'] + i
16 yield ('[%d]' % i, item.dereference())
17 return it(self)
18
19 def display_hint(self):
20 return 'array'
21
22# handle both Buf and ZigList<char> because Buf* doesn't work otherwise (gdb bug?)
23class BufPrinter:
24 def __init__(self, val):
25 self.val = val['list'] if val.type.name == 'Buf' else val
26
27 def to_string(self):
28 return self.val['items'].string(length=int(self.val['length']))
29
30 def display_hint(self):
31 return 'string'
32
33pp = gdb.printing.RegexpCollectionPrettyPrinter('Zig stage1 compiler')
34pp.add_printer('Buf', '^Buf$', BufPrinter)
35pp.add_printer('ZigList<char>', '^ZigList<char>$', BufPrinter)
36pp.add_printer('ZigList', '^ZigList<.*>$', ZigListPrinter)
37gdb.printing.register_pretty_printer(gdb.current_objfile(), pp)
tools/stage2_gdb_pretty_printers.py created+189
...@@ -0,0 +1,189 @@
1# pretty printing for stage 2.
2# put "source /path/to/stage2_gdb_pretty_printers.py" in ~/.gdbinit to load it automatically.
3import re
4import gdb.printing
5
6class 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.Len',
13 'array_u8_sentinel_0': 'Len',
14
15 'single_const_pointer': 'ElemType',
16 'single_mut_pointer': 'ElemType',
17 'many_const_pointer': 'ElemType',
18 'many_mut_pointer': 'ElemType',
19 'c_const_pointer': 'ElemType',
20 'c_mut_pointer': 'ElemType',
21 'const_slice': 'ElemType',
22 'mut_slice': 'ElemType',
23 'optional': 'ElemType',
24 'optional_single_mut_pointer': 'ElemType',
25 'optional_single_const_pointer': 'ElemType',
26 'anyframe_T': 'ElemType',
27
28 'int_signed': 'Bits',
29 'int_unsigned': 'Bits',
30
31 'error_set': 'ErrorSet',
32 'error_set_inferred': 'ErrorSetInferred',
33 'error_set_merged': 'ErrorSetMerged',
34
35 'array': 'Array',
36 'vector': 'Array',
37
38 'array_sentinel': 'ArraySentinel',
39 'pointer': 'Pointer',
40 'function': 'Function',
41 'error_union': 'ErrorUnion',
42 'error_set_single': 'Name',
43 'opaque': 'Opaque',
44 'struct': 'Struct',
45 'union': 'Union',
46 'union_tagged': 'Union',
47 'enum_full, .enum_nonexhaustive': 'EnumFull',
48 'enum_simple': 'EnumSimple',
49 'enum_numbered': 'EnumNumbered',
50 'empty_struct': 'ContainerScope',
51 'tuple': 'Tuple',
52 'anon_struct': 'AnonStruct',
53 }
54
55 def __init__(self, val):
56 self.val = val
57
58 def tag(self):
59 tag_if_small_enough = self.val['tag_if_small_enough']
60 tag_type = tag_if_small_enough.type
61
62 if tag_if_small_enough < TypePrinter.no_payload_count:
63 return tag_if_small_enough
64 else:
65 return self.val['ptr_otherwise'].dereference()['tag']
66
67 def payload_type(self):
68 tag = self.tag()
69 if tag is None:
70 return None
71
72 type_name = TypePrinter.payload_type_names.get(str(tag))
73 if type_name is None:
74 return None
75 return gdb.lookup_type('struct type.%s' % type_name)
76
77 def to_string(self):
78 tag = self.tag()
79 if tag is None:
80 return '(invalid type)'
81 if self.val['tag_if_small_enough'] < TypePrinter.no_payload_count:
82 return '.%s' % str(tag)
83 return None
84
85 def children(self):
86 if self.val['tag_if_small_enough'] < TypePrinter.no_payload_count:
87 return
88
89 yield ('tag', '.%s' % str(self.tag()))
90
91 payload_type = self.payload_type()
92 if payload_type is not None:
93 yield ('payload', self.val['ptr_otherwise'].cast(payload_type.pointer()).dereference()['data'])
94
95class 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': 'BigInt',
102 'big_int_negative': 'BigInt',
103
104 'extern_fn': 'ExternFn',
105
106 'decl_ref': 'Decl',
107
108 'repeated': 'SubValue',
109 'eu_payload': 'SubValue',
110 'opt_payload': 'SubValue',
111 'empty_array_sentinel': 'SubValue',
112
113 'eu_payload_ptr': 'PayloadPtr',
114 'opt_payload_ptr': 'PayloadPtr',
115
116 'bytes': 'Bytes',
117 'enum_literal': 'Bytes',
118
119 'slice': 'Slice',
120
121 'enum_field_index': 'U32',
122
123 'ty': 'Ty',
124 'int_type': 'IntType',
125 'int_u64': 'U64',
126 'int_i64': 'I64',
127 'function': 'Function',
128 'variable': 'Variable',
129 'decl_ref_mut': 'DeclRefMut',
130 'elem_ptr': 'ElemPtr',
131 'field_ptr': 'FieldPtr',
132 'float_16': 'Float_16',
133 'float_32': 'Float_32',
134 'float_64': 'Float_64',
135 'float_80': 'Float_80',
136 'float_128': 'Float_128',
137 'error': 'Error',
138 'inferred_alloc': 'InferredAlloc',
139 'inferred_alloc_comptime': 'InferredAllocComptime',
140 'aggregate': 'Aggregate',
141 'union': 'Union',
142 'bound_fn': 'BoundFn',
143 }
144
145 def __init__(self, val):
146 self.val = val
147
148 def tag(self):
149 tag_if_small_enough = self.val['tag_if_small_enough']
150 tag_type = tag_if_small_enough.type
151
152 if tag_if_small_enough < ValuePrinter.no_payload_count:
153 return tag_if_small_enough
154 else:
155 return self.val['ptr_otherwise'].dereference()['tag']
156
157 def payload_type(self):
158 tag = self.tag()
159 if tag is None:
160 return None
161
162 type_name = ValuePrinter.payload_type_names.get(str(tag))
163 if type_name is None:
164 return None
165 return gdb.lookup_type('struct value.%s' % type_name)
166
167 def to_string(self):
168 tag = self.tag()
169 if tag is None:
170 return '(invalid value)'
171 if self.val['tag_if_small_enough'] < ValuePrinter.no_payload_count:
172 return '.%s' % str(tag)
173 return None
174
175 def children(self):
176 if self.val['tag_if_small_enough'] < ValuePrinter.no_payload_count:
177 return
178
179 yield ('tag', '.%s' % str(self.tag()))
180
181 payload_type = self.payload_type()
182 if payload_type is not None:
183 yield ('payload', self.val['ptr_otherwise'].cast(payload_type.pointer()).dereference()['data'])
184
185pp = gdb.printing.RegexpCollectionPrettyPrinter('Zig stage2 compiler')
186pp.add_printer('Type', r'^type\.Type$', TypePrinter)
187pp.add_printer('Value', r'^value\.Value$', ValuePrinter)
188gdb.printing.register_pretty_printer(gdb.current_objfile(), pp)
189
tools/std_gdb_pretty_printers.py created+142
...@@ -0,0 +1,142 @@
1# pretty printing for the standard library.
2# put "source /path/to/stage2_gdb_pretty_printers.py" in ~/.gdbinit to load it automatically.
3import re
4import gdb.printing
5
6# Handles both ArrayList and ArrayListUnmanaged.
7class ArrayListPrinter:
8 def __init__(self, val):
9 self.val = val
10
11 def to_string(self):
12 type = self.val.type.name[len('std.array_list.'):]
13 type = re.sub(r'^ArrayListAligned(Unmanaged)?\((.*),null\)$', r'ArrayList\1(\2)', type)
14 return '%s of length %s, capacity %s' % (type, self.val['items']['len'], self.val['capacity'])
15
16 def children(self):
17 for i in range(self.val['items']['len']):
18 item = self.val['items']['ptr'] + i
19 yield ('[%d]' % i, item.dereference())
20
21 def display_hint(self):
22 return 'array'
23
24class MultiArrayListPrinter:
25 def __init__(self, val):
26 self.val = val
27
28 def child_type(self):
29 (helper_fn, _) = gdb.lookup_symbol('%s.gdbHelper' % self.val.type.name)
30 return helper_fn.type.fields()[1].type.target()
31
32 def to_string(self):
33 type = self.val.type.name[len('std.multi_array_list.'):]
34 return '%s of length %s, capacity %s' % (type, self.val['len'], self.val['capacity'])
35
36 def slice(self):
37 fields = self.child_type().fields()
38 base = self.val['bytes']
39 cap = self.val['capacity']
40 len = self.val['len']
41
42 if len == 0:
43 return
44
45 fields = sorted(fields, key=lambda field: field.type.alignof, reverse=True)
46
47 for field in fields:
48 ptr = base.cast(field.type.pointer()).dereference().cast(field.type.array(len - 1))
49 base += field.type.sizeof * cap
50 yield (field.name, ptr)
51
52 def children(self):
53 for i, (name, ptr) in enumerate(self.slice()):
54 yield ('[%d]' % i, name)
55 yield ('[%d]' % i, ptr)
56
57 def display_hint(self):
58 return 'map'
59
60# Handles both HashMap and HashMapUnmanaged.
61class HashMapPrinter:
62 def __init__(self, val):
63 self.type = val.type
64 is_managed = re.search(r'^std\.hash_map\.HashMap\(', self.type.name)
65 self.val = val['unmanaged'] if is_managed else val
66
67 def header_ptr_type(self):
68 (helper_fn, _) = gdb.lookup_symbol('%s.gdbHelper' % self.val.type.name)
69 return helper_fn.type.fields()[1].type
70
71 def header(self):
72 if self.val['metadata'] == 0:
73 return None
74 return (self.val['metadata'].cast(self.header_ptr_type()) - 1).dereference()
75
76 def to_string(self):
77 type = self.type.name[len('std.hash_map.'):]
78 type = re.sub(r'^HashMap(Unmanaged)?\((.*),std.hash_map.AutoContext\(.*$', r'AutoHashMap\1(\2)', type)
79 hdr = self.header()
80 if hdr is not None:
81 cap = hdr['capacity']
82 else:
83 cap = 0
84 return '%s of length %s, capacity %s' % (type, self.val['size'], cap)
85
86 def children(self):
87 hdr = self.header()
88 if hdr is None:
89 return
90 is_map = self.display_hint() == 'map'
91 for i in range(hdr['capacity']):
92 metadata = self.val['metadata'] + i
93 if metadata.dereference()['used'] == 1:
94 yield ('[%d]' % i, (hdr['keys'] + i).dereference())
95 if is_map:
96 yield ('[%d]' % i, (hdr['values'] + i).dereference())
97
98 def display_hint(self):
99 for field in self.header_ptr_type().target().fields():
100 if field.name == 'values':
101 return 'map'
102 return 'array'
103
104# Handles both ArrayHashMap and ArrayHashMapUnmanaged.
105class ArrayHashMapPrinter:
106 def __init__(self, val):
107 self.type = val.type
108 is_managed = re.search(r'^std\.array_hash_map\.ArrayHashMap\(', self.type.name)
109 self.val = val['unmanaged'] if is_managed else val
110
111 def to_string(self):
112 type = self.type.name[len('std.array_hash_map.'):]
113 type = re.sub(r'^ArrayHashMap(Unmanaged)?\((.*),std.array_hash_map.AutoContext\(.*$', r'AutoArrayHashMap\1(\2)', type)
114 return '%s of length %s' % (type, self.val['entries']['len'])
115
116 def children(self):
117 entries = MultiArrayListPrinter(self.val['entries'])
118 len = self.val['entries']['len']
119 fields = {}
120 for name, ptr in entries.slice():
121 fields[str(name)] = ptr
122
123 for i in range(len):
124 if 'key' in fields:
125 yield ('[%d]' % i, fields['key'][i])
126 else:
127 yield ('[%d]' % i, '{}')
128 if 'value' in fields:
129 yield ('[%d]' % i, fields['value'][i])
130
131 def display_hint(self):
132 for name, ptr in MultiArrayListPrinter(self.val['entries']).slice():
133 if name == 'value':
134 return 'map'
135 return 'array'
136
137pp = gdb.printing.RegexpCollectionPrettyPrinter('Zig standard library')
138pp.add_printer('ArrayList', r'^std\.array_list\.ArrayListAligned(Unmanaged)?\(.*\)$', ArrayListPrinter)
139pp.add_printer('MultiArrayList', r'^std\.multi_array_list\.MultiArrayList\(.*\)$', MultiArrayListPrinter)
140pp.add_printer('HashMap', r'^std\.hash_map\.HashMap(Unmanaged)?\(.*\)$', HashMapPrinter)
141pp.add_printer('ArrayHashMap', r'^std\.array_hash_map\.ArrayHashMap(Unmanaged)?\(.*\)$', ArrayHashMapPrinter)
142gdb.printing.register_pretty_printer(gdb.current_objfile(), pp)
tools/zig-gdb.py deleted-389
...@@ -1,389 +0,0 @@
1# pretty printing for stage1, stage2 and the standard library
2# put "source /path/to/zig-gdb.py" in ~/.gdbinit to load it automatically
3
4import re
5import gdb.printing
6import gdb.types
7
8class ZigListPrinter:
9 def __init__(self, val):
10 self.val = val
11
12 def to_string(self):
13 return '%s of length %d, capacity %d' % (self.val.type.name, int(self.val['length']), int(self.val['capacity']))
14
15 def children(self):
16 def it(ziglist):
17 for i in range(int(ziglist.val['length'])):
18 item = ziglist.val['items'] + i
19 yield ('[%d]' % i, item.dereference())
20 return it(self)
21
22 def display_hint(self):
23 return 'array'
24
25# handle both Buf and ZigList<char> because Buf* doesn't work otherwise (gdb bug?)
26class BufPrinter:
27 def __init__(self, val):
28 self.val = val['list'] if val.type.name == 'Buf' else val
29
30 def to_string(self):
31 return self.val['items'].string(length=int(self.val['length']))
32
33 def display_hint(self):
34 return 'string'
35
36class SlicePrinter:
37 def __init__(self, val):
38 self.val = val
39
40 def children(self):
41 for i in range(self.val['len']):
42 yield ('[%d]' % i, (self.val['ptr'] + i).dereference())
43
44 def display_hint(self):
45 return 'array'
46
47class SliceStringPrinter:
48 def __init__(self, val):
49 self.val = val
50
51 def to_string(self):
52 return self.val['ptr'].string(length=self.val['len'])
53
54 def display_hint(self):
55 return 'string'
56
57# Handles both ArrayList and ArrayListUnmanaged.
58class ArrayListPrinter:
59 def __init__(self, val):
60 self.val = val
61
62 def to_string(self):
63 type = self.val.type.name[len('std.array_list.'):]
64 type = re.sub(r'^ArrayListAligned(Unmanaged)?\((.*),null\)$', r'ArrayList\1(\2)', type)
65 return '%s of length %s, capacity %s' % (type, self.val['items']['len'], self.val['capacity'])
66
67 def children(self):
68 for i in range(self.val['items']['len']):
69 item = self.val['items']['ptr'] + i
70 yield ('[%d]' % i, item.dereference())
71
72 def display_hint(self):
73 return 'array'
74
75class MultiArrayListPrinter:
76 def __init__(self, val):
77 self.val = val
78
79 def child_type(self):
80 (helper_fn, _) = gdb.lookup_symbol('%s.gdbHelper' % self.val.type.name)
81 return helper_fn.type.fields()[1].type.target()
82
83 def to_string(self):
84 type = self.val.type.name[len('std.multi_array_list.'):]
85 return '%s of length %s, capacity %s' % (type, self.val['len'], self.val['capacity'])
86
87 def slice(self):
88 fields = self.child_type().fields()
89 base = self.val['bytes']
90 cap = self.val['capacity']
91 len = self.val['len']
92
93 if len == 0:
94 return
95
96 fields = sorted(fields, key=lambda field: field.type.alignof, reverse=True)
97
98 for field in fields:
99 ptr = base.cast(field.type.pointer()).dereference().cast(field.type.array(len - 1))
100 base += field.type.sizeof * cap
101 yield (field.name, ptr)
102
103 def children(self):
104 for i, (name, ptr) in enumerate(self.slice()):
105 yield ('[%d]' % i, name)
106 yield ('[%d]' % i, ptr)
107
108 def display_hint(self):
109 return 'map'
110
111# Handles both HashMap and HashMapUnmanaged.
112class HashMapPrinter:
113 def __init__(self, val):
114 self.type = val.type
115 is_managed = re.search(r'^std\.hash_map\.HashMap\(', self.type.name)
116 self.val = val['unmanaged'] if is_managed else val
117
118 def header_ptr_type(self):
119 (helper_fn, _) = gdb.lookup_symbol('%s.gdbHelper' % self.val.type.name)
120 return helper_fn.type.fields()[1].type
121
122 def header(self):
123 if self.val['metadata'] == 0:
124 return None
125 return (self.val['metadata'].cast(self.header_ptr_type()) - 1).dereference()
126
127 def to_string(self):
128 type = self.type.name[len('std.hash_map.'):]
129 type = re.sub(r'^HashMap(Unmanaged)?\((.*),std.hash_map.AutoContext\(.*$', r'AutoHashMap\1(\2)', type)
130 hdr = self.header()
131 if hdr is not None:
132 cap = hdr['capacity']
133 else:
134 cap = 0
135 return '%s of length %s, capacity %s' % (type, self.val['size'], cap)
136
137 def children(self):
138 hdr = self.header()
139 if hdr is None:
140 return
141 is_map = self.display_hint() == 'map'
142 for i in range(hdr['capacity']):
143 metadata = self.val['metadata'] + i
144 if metadata.dereference()['used'] == 1:
145 yield ('[%d]' % i, (hdr['keys'] + i).dereference())
146 if is_map:
147 yield ('[%d]' % i, (hdr['values'] + i).dereference())
148
149 def display_hint(self):
150 for field in self.header_ptr_type().target().fields():
151 if field.name == 'values':
152 return 'map'
153 return 'array'
154
155# Handles both ArrayHashMap and ArrayHashMapUnmanaged.
156class ArrayHashMapPrinter:
157 def __init__(self, val):
158 self.type = val.type
159 is_managed = re.search(r'^std\.array_hash_map\.ArrayHashMap\(', self.type.name)
160 self.val = val['unmanaged'] if is_managed else val
161
162 def to_string(self):
163 type = self.type.name[len('std.array_hash_map.'):]
164 type = re.sub(r'^ArrayHashMap(Unmanaged)?\((.*),std.array_hash_map.AutoContext\(.*$', r'AutoArrayHashMap\1(\2)', type)
165 return '%s of length %s' % (type, self.val['entries']['len'])
166
167 def children(self):
168 entries = MultiArrayListPrinter(self.val['entries'])
169 len = self.val['entries']['len']
170 fields = {}
171 for name, ptr in entries.slice():
172 fields[str(name)] = ptr
173
174 for i in range(len):
175 if 'key' in fields:
176 yield ('[%d]' % i, fields['key'][i])
177 else:
178 yield ('[%d]' % i, '{}')
179 if 'value' in fields:
180 yield ('[%d]' % i, fields['value'][i])
181
182 def display_hint(self):
183 for name, ptr in MultiArrayListPrinter(self.val['entries']).slice():
184 if name == 'value':
185 return 'map'
186 return 'array'
187
188class TypePrinter:
189 no_payload_count = 4096
190
191 # Keep in sync with src/type.zig
192 # Types which have no payload do not need to be entered here.
193 payload_type_names = {
194 'array_u8': 'type.Len',
195 'array_u8_sentinel_0': 'Len',
196
197 'single_const_pointer': 'ElemType',
198 'single_mut_pointer': 'ElemType',
199 'many_const_pointer': 'ElemType',
200 'many_mut_pointer': 'ElemType',
201 'c_const_pointer': 'ElemType',
202 'c_mut_pointer': 'ElemType',
203 'const_slice': 'ElemType',
204 'mut_slice': 'ElemType',
205 'optional': 'ElemType',
206 'optional_single_mut_pointer': 'ElemType',
207 'optional_single_const_pointer': 'ElemType',
208 'anyframe_T': 'ElemType',
209
210 'int_signed': 'Bits',
211 'int_unsigned': 'Bits',
212
213 'error_set': 'ErrorSet',
214 'error_set_inferred': 'ErrorSetInferred',
215 'error_set_merged': 'ErrorSetMerged',
216
217 'array': 'Array',
218 'vector': 'Array',
219
220 'array_sentinel': 'ArraySentinel',
221 'pointer': 'Pointer',
222 'function': 'Function',
223 'error_union': 'ErrorUnion',
224 'error_set_single': 'Name',
225 'opaque': 'Opaque',
226 'struct': 'Struct',
227 'union': 'Union',
228 'union_tagged': 'Union',
229 'enum_full, .enum_nonexhaustive': 'EnumFull',
230 'enum_simple': 'EnumSimple',
231 'enum_numbered': 'EnumNumbered',
232 'empty_struct': 'ContainerScope',
233 'tuple': 'Tuple',
234 'anon_struct': 'AnonStruct',
235 }
236
237 def __init__(self, val):
238 self.val = val
239
240 def tag(self):
241 tag_if_small_enough = self.val['tag_if_small_enough']
242 tag_type = tag_if_small_enough.type
243
244 if tag_if_small_enough < TypePrinter.no_payload_count:
245 return tag_if_small_enough
246 else:
247 return self.val['ptr_otherwise'].dereference()['tag']
248
249 def payload_type(self):
250 tag = self.tag()
251 if tag is None:
252 return None
253
254 type_name = TypePrinter.payload_type_names.get(str(tag))
255 if type_name is None:
256 return None
257 return gdb.lookup_type('struct type.%s' % type_name)
258
259 def to_string(self):
260 tag = self.tag()
261 if tag is None:
262 return '(invalid type)'
263 if self.val['tag_if_small_enough'] < TypePrinter.no_payload_count:
264 return '.%s' % str(tag)
265 return None
266
267 def children(self):
268 if self.val['tag_if_small_enough'] < TypePrinter.no_payload_count:
269 return
270
271 yield ('tag', '.%s' % str(self.tag()))
272
273 payload_type = self.payload_type()
274 if payload_type is not None:
275 yield ('payload', self.val['ptr_otherwise'].cast(payload_type.pointer()).dereference()['data'])
276
277class ValuePrinter:
278 no_payload_count = 4096
279
280 # Keep in sync with src/value.zig
281 # Values which have no payload do not need to be entered here.
282 payload_type_names = {
283 'big_int_positive': 'BigInt',
284 'big_int_negative': 'BigInt',
285
286 'extern_fn': 'ExternFn',
287
288 'decl_ref': 'Decl',
289
290 'repeated': 'SubValue',
291 'eu_payload': 'SubValue',
292 'opt_payload': 'SubValue',
293 'empty_array_sentinel': 'SubValue',
294
295 'eu_payload_ptr': 'PayloadPtr',
296 'opt_payload_ptr': 'PayloadPtr',
297
298 'bytes': 'Bytes',
299 'enum_literal': 'Bytes',
300
301 'slice': 'Slice',
302
303 'enum_field_index': 'U32',
304
305 'ty': 'Ty',
306 'int_type': 'IntType',
307 'int_u64': 'U64',
308 'int_i64': 'I64',
309 'function': 'Function',
310 'variable': 'Variable',
311 'decl_ref_mut': 'DeclRefMut',
312 'elem_ptr': 'ElemPtr',
313 'field_ptr': 'FieldPtr',
314 'float_16': 'Float_16',
315 'float_32': 'Float_32',
316 'float_64': 'Float_64',
317 'float_80': 'Float_80',
318 'float_128': 'Float_128',
319 'error': 'Error',
320 'inferred_alloc': 'InferredAlloc',
321 'inferred_alloc_comptime': 'InferredAllocComptime',
322 'aggregate': 'Aggregate',
323 'union': 'Union',
324 'bound_fn': 'BoundFn',
325 }
326
327 def __init__(self, val):
328 self.val = val
329
330 def tag(self):
331 tag_if_small_enough = self.val['tag_if_small_enough']
332 tag_type = tag_if_small_enough.type
333
334 if tag_if_small_enough < ValuePrinter.no_payload_count:
335 return tag_if_small_enough
336 else:
337 return self.val['ptr_otherwise'].dereference()['tag']
338
339 def payload_type(self):
340 tag = self.tag()
341 if tag is None:
342 return None
343
344 type_name = ValuePrinter.payload_type_names.get(str(tag))
345 if type_name is None:
346 return None
347 return gdb.lookup_type('struct value.%s' % type_name)
348
349 def to_string(self):
350 tag = self.tag()
351 if tag is None:
352 return '(invalid value)'
353 if self.val['tag_if_small_enough'] < ValuePrinter.no_payload_count:
354 return '.%s' % str(tag)
355 return None
356
357 def children(self):
358 if self.val['tag_if_small_enough'] < ValuePrinter.no_payload_count:
359 return
360
361 yield ('tag', '.%s' % str(self.tag()))
362
363 payload_type = self.payload_type()
364 if payload_type is not None:
365 yield ('payload', self.val['ptr_otherwise'].cast(payload_type.pointer()).dereference()['data'])
366
367pp1 = gdb.printing.RegexpCollectionPrettyPrinter('Zig stage1 compiler')
368pp1.add_printer('Buf', '^Buf$', BufPrinter)
369pp1.add_printer('ZigList<char>', '^ZigList<char>$', BufPrinter)
370pp1.add_printer('ZigList', '^ZigList<.*>$', ZigListPrinter)
371gdb.printing.register_pretty_printer(gdb.current_objfile(), pp1)
372
373pplang = gdb.printing.RegexpCollectionPrettyPrinter('Zig language')
374pplang.add_printer('Slice', '^\[\]u8', SliceStringPrinter)
375pplang.add_printer('Slice', '^\[\]', SlicePrinter)
376gdb.printing.register_pretty_printer(gdb.current_objfile(), pplang)
377
378ppstd = gdb.printing.RegexpCollectionPrettyPrinter('Zig standard library')
379ppstd.add_printer('ArrayList', r'^std\.array_list\.ArrayListAligned(Unmanaged)?\(.*\)$', ArrayListPrinter)
380ppstd.add_printer('MultiArrayList', r'^std\.multi_array_list\.MultiArrayList\(.*\)$', MultiArrayListPrinter)
381ppstd.add_printer('HashMap', r'^std\.hash_map\.HashMap(Unmanaged)?\(.*\)$', HashMapPrinter)
382ppstd.add_printer('ArrayHashMap', r'^std\.array_hash_map\.ArrayHashMap(Unmanaged)?\(.*\)$', ArrayHashMapPrinter)
383gdb.printing.register_pretty_printer(gdb.current_objfile(), ppstd)
384
385pp2 = gdb.printing.RegexpCollectionPrettyPrinter('Zig stage2 compiler')
386pp2.add_printer('Type', r'^type\.Type$', TypePrinter)
387pp2.add_printer('Value', r'^value\.Value$', ValuePrinter)
388gdb.printing.register_pretty_printer(gdb.current_objfile(), pp2)
389
tools/zig_gdb_pretty_printers.py+2-2
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1# gdb pretty printers for Zig language constructs1# pretty printing for the language.
22# put "source /path/to/zig_gdb_pretty_printers.py" in ~/.gdbinit to load it automatically.
3import gdb.printing3import gdb.printing
44
5class ZigPrettyPrinter(gdb.printing.PrettyPrinter):5class ZigPrettyPrinter(gdb.printing.PrettyPrinter):