aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorRobin Voetter <robin@voetter.nl>2022-03-16 15:38:30 +0100
committerRobin Voetter <robin@voetter.nl>2022-03-16 15:50:03 +0100
commitfeb8981a95988434506bad9864498e2ff1ff9243 (patch)
treea22230a1a1c91ac5c6101bd89e9ab2e30a01a327 /tools
parente18c29af5bf873ed3165ab9abb57b2246f37c406 (diff)
downloadzig-feb8981a95988434506bad9864498e2ff1ff9243.tar.gz
zig-feb8981a95988434506bad9864498e2ff1ff9243.zip
gdb: add slice, multi array list, and array hash map printers
Diffstat (limited to 'tools')
-rw-r--r--tools/zig-gdb.py142
1 files changed, 127 insertions, 15 deletions
diff --git a/tools/zig-gdb.py b/tools/zig-gdb.py
index 3a656d9b22..b6ba4a7baf 100644
--- a/tools/zig-gdb.py
+++ b/tools/zig-gdb.py
@@ -32,6 +32,27 @@ class BufPrinter:
def display_hint(self):
return 'string'
+class SlicePrinter:
+ def __init__(self, val):
+ self.val = val
+
+ def children(self):
+ for i in range(self.val['len']):
+ yield ('[%d]' % i, (self.val['ptr'] + i).dereference())
+
+ def display_hint(self):
+ return 'array'
+
+class SliceStringPrinter:
+ def __init__(self, val):
+ self.val = val
+
+ def to_string(self):
+ return self.val['ptr'].string(length=self.val['len'])
+
+ def display_hint(self):
+ return 'string'
+
# Handles both ArrayList and ArrayListUnmanaged.
class ArrayListPrinter:
def __init__(self, val):
@@ -39,52 +60,143 @@ class ArrayListPrinter:
def to_string(self):
type = self.val.type.name[len('std.array_list.'):]
- type = re.sub(r'ArrayListAligned(Unmanaged)?\((.*),null\)$', r'ArrayList\1(\2)', type)
+ type = re.sub(r'^ArrayListAligned(Unmanaged)?\((.*),null\)$', r'ArrayList\1(\2)', type)
return '%s of length %s, capacity %s' % (type, self.val['items']['len'], self.val['capacity'])
def children(self):
- for i in range(int(self.val['items']['len'])):
+ for i in range(self.val['items']['len']):
item = self.val['items']['ptr'] + i
yield ('[%d]' % i, item.dereference())
def display_hint(self):
return 'array'
-# Handles both HashMap and HashMapUnmanaged
+class MultiArrayListPrinter:
+ def __init__(self, val):
+ self.val = val
+
+ def child_type(self):
+ (helper_fn, _) = gdb.lookup_symbol('%s.gdbHelper' % self.val.type.name)
+ return helper_fn.type.fields()[1].type.target()
+
+ def to_string(self):
+ type = self.val.type.name[len('std.multi_array_list.'):]
+ return '%s of length %s, capacity %s' % (type, self.val['len'], self.val['capacity'])
+
+ def slice(self):
+ fields = self.child_type().fields()
+ base = self.val['bytes']
+ cap = self.val['capacity']
+ len = self.val['len']
+
+ if len == 0:
+ return
+
+ fields = sorted(fields, key=lambda field: field.type.alignof, reverse=True)
+
+ for field in fields:
+ ptr = base.cast(field.type.pointer()).dereference().cast(field.type.array(len - 1))
+ base += field.type.sizeof * cap
+ yield (field.name, ptr)
+
+ def children(self):
+ for i, (name, ptr) in enumerate(self.slice()):
+ yield ('[%d]' % i, name)
+ yield ('[%d]' % i, ptr)
+
+ def display_hint(self):
+ return 'map'
+
+# Handles both HashMap and HashMapUnmanaged.
class HashMapPrinter:
def __init__(self, val):
self.type = val.type
is_managed = re.search(r'^std\.hash_map\.HashMap\(', self.type.name)
self.val = val['unmanaged'] if is_managed else val
+ def header_ptr_type(self):
+ (helper_fn, _) = gdb.lookup_symbol('%s.gdbHelper' % self.val.type.name)
+ return helper_fn.type.fields()[1].type
+
def header(self):
- (header_fn, _) = gdb.lookup_symbol('%s.header' % self.val.type.name)
- header_ptr_type = header_fn.type.target()
- return (self.val['metadata'].cast(header_ptr_type) - 1).dereference()
+ if self.val['metadata'] == 0:
+ return None
+ return (self.val['metadata'].cast(self.header_ptr_type()) - 1).dereference()
def to_string(self):
type = self.type.name[len('std.hash_map.'):]
type = re.sub(r'^HashMap(Unmanaged)?\((.*),std.hash_map.AutoContext\(.*$', r'AutoHashMap\1(\2)', type)
- return '%s of length %s, capacity %s' % (type, self.val['size'], self.header()['capacity'])
+ hdr = self.header()
+ if hdr is not None:
+ cap = hdr['capacity']
+ else:
+ cap = 0
+ return '%s of length %s, capacity %s' % (type, self.val['size'], cap)
def children(self):
hdr = self.header()
- for i in range(int(hdr['capacity'])):
+ if hdr is None:
+ return
+ is_map = self.display_hint() == 'map'
+ for i in range(hdr['capacity']):
metadata = self.val['metadata'] + i
if metadata.dereference()['used'] == 1:
yield ('[%d]' % i, (hdr['keys'] + i).dereference())
- yield ('[%d]' % i, (hdr['values'] + i).dereference())
+ if is_map:
+ yield ('[%d]' % i, (hdr['values'] + i).dereference())
def display_hint(self):
- return 'map'
+ for field in self.header_ptr_type().target().fields():
+ if field.name == 'values':
+ return 'map'
+ return 'array'
+
+# Handles both ArrayHashMap and ArrayHashMapUnmanaged.
+class ArrayHashMapPrinter:
+ def __init__(self, val):
+ self.type = val.type
+ is_managed = re.search(r'^std\.array_hash_map\.ArrayHashMap\(', self.type.name)
+ self.val = val['unmanaged'] if is_managed else val
+
+ def to_string(self):
+ type = self.type.name[len('std.array_hash_map.'):]
+ type = re.sub(r'^ArrayHashMap(Unmanaged)?\((.*),std.array_hash_map.AutoContext\(.*$', r'AutoArrayHashMap\1(\2)', type)
+ return '%s of length %s' % (type, self.val['entries']['len'])
+
+ def children(self):
+ entries = MultiArrayListPrinter(self.val['entries'])
+ len = self.val['entries']['len']
+ fields = {}
+ for name, ptr in entries.slice():
+ fields[str(name)] = ptr
+
+ for i in range(len):
+ if 'key' in fields:
+ yield ('[%d]' % i, fields['key'][i])
+ else:
+ yield ('[%d]' % i, '{}')
+ if 'value' in fields:
+ yield ('[%d]' % i, fields['value'][i])
+
+ def display_hint(self):
+ for name, ptr in MultiArrayListPrinter(self.val['entries']).slice():
+ if name == 'value':
+ return 'map'
+ return 'array'
+
+pp1 = gdb.printing.RegexpCollectionPrettyPrinter('Zig stage1 compiler')
+pp1.add_printer('Buf', '^Buf$', BufPrinter)
+pp1.add_printer('ZigList<char>', '^ZigList<char>$', BufPrinter)
+pp1.add_printer('ZigList', '^ZigList<.*>$', ZigListPrinter)
+gdb.printing.register_pretty_printer(gdb.current_objfile(), pp1)
-pp = gdb.printing.RegexpCollectionPrettyPrinter('Zig stage1 compiler')
-pp.add_printer('Buf', '^Buf$', BufPrinter)
-pp.add_printer('ZigList<char>', '^ZigList<char>$', BufPrinter)
-pp.add_printer('ZigList', '^ZigList<.*>$', ZigListPrinter)
-gdb.printing.register_pretty_printer(gdb.current_objfile(), pp)
+pplang = gdb.printing.RegexpCollectionPrettyPrinter('Zig language')
+pplang.add_printer('Slice', '^\[\]u8', SliceStringPrinter)
+pplang.add_printer('Slice', '^\[\]', SlicePrinter)
ppstd = gdb.printing.RegexpCollectionPrettyPrinter('Zig standard library')
ppstd.add_printer('ArrayList', r'^std\.array_list\.ArrayListAligned(Unmanaged)?\(.*\)$', ArrayListPrinter)
+ppstd.add_printer('MultiArrayList', r'^std\.multi_array_list\.MultiArrayList\(.*\)$', MultiArrayListPrinter)
ppstd.add_printer('HashMap', r'^std\.hash_map\.HashMap(Unmanaged)?\(.*\)$', HashMapPrinter)
+ppstd.add_printer('ArrayHashMap', r'^std\.array_hash_map\.ArrayHashMap(Unmanaged)?\(.*\)$', ArrayHashMapPrinter)
gdb.printing.register_pretty_printer(gdb.current_objfile(), ppstd)