Commit e18c29af5b

Robin Voetter <robin@voetter.nl>
2022-03-16 12:40:08
gdb: add arraylist and hashmap printer
1 parent d4a0d5f
Changed files (1)
tools/zig-gdb.py
@@ -1,7 +1,8 @@
-# pretty printing for stage1
+# pretty printing for stage1, stage2 and the standard library
 # put "source /path/to/zig-gdb.py" in ~/.gdbinit to load it automatically
 
 import gdb.printing
+import re
 
 class ZigListPrinter:
     def __init__(self, val):
@@ -31,9 +32,59 @@ class BufPrinter:
     def display_hint(self):
         return 'string'
 
+# Handles both ArrayList and ArrayListUnmanaged.
+class ArrayListPrinter:
+    def __init__(self, val):
+        self.val = val
+
+    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)
+        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'])):
+            item = self.val['items']['ptr'] + i
+            yield ('[%d]' % i, item.dereference())
+
+    def display_hint(self):
+        return 'array'
+
+# 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(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()
+
+    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'])
+
+    def children(self):
+        hdr = self.header()
+        for i in range(int(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())
+
+    def display_hint(self):
+        return 'map'
+
 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)
+
+ppstd = gdb.printing.RegexpCollectionPrettyPrinter('Zig standard library')
+ppstd.add_printer('ArrayList', r'^std\.array_list\.ArrayListAligned(Unmanaged)?\(.*\)$', ArrayListPrinter)
+ppstd.add_printer('HashMap', r'^std\.hash_map\.HashMap(Unmanaged)?\(.*\)$', HashMapPrinter)
+gdb.printing.register_pretty_printer(gdb.current_objfile(), ppstd)