From 0bd84e03b98a75806c47cb7f514a15de7e4d2b6e Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Wed, 16 Mar 2022 17:57:31 +0100 Subject: [PATCH] gdb: add printer for selfhosted Value --- src/value.zig | 1 + tools/zig-gdb.py | 95 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 94 insertions(+), 2 deletions(-) diff --git a/src/value.zig b/src/value.zig index 24cec0396e..d63452ee56 100644 --- a/src/value.zig +++ b/src/value.zig @@ -20,6 +20,7 @@ pub const Value = extern union { tag_if_small_enough: Tag, ptr_otherwise: *Payload, + // Keep in sync with tools/zig-gdb.py pub const Tag = enum(usize) { // The first section of this enum are tags that require no payload. u1_type, diff --git a/tools/zig-gdb.py b/tools/zig-gdb.py index ff1b20bb74..001211267c 100644 --- a/tools/zig-gdb.py +++ b/tools/zig-gdb.py @@ -259,7 +259,7 @@ class TypePrinter: def to_string(self): tag = self.tag() if tag is None: - return 'Type.(invalid type)' + return '(invalid type)' if self.val['tag_if_small_enough'] < TypePrinter.no_payload_count: return '.%s' % str(tag) return None @@ -274,6 +274,96 @@ class TypePrinter: if payload_type is not None: yield ('payload', self.val['ptr_otherwise'].cast(payload_type.pointer()).dereference()['data']) +class ValuePrinter: + no_payload_count = 4096 + + # Keep in sync with src/value.zig + # Values which have no payload do not need to be entered here. + payload_type_names = { + 'big_int_positive': 'BigInt', + 'big_int_negative': 'BigInt', + + 'extern_fn': 'ExternFn', + + 'decl_ref': 'Decl', + + 'repeated': 'SubValue', + 'eu_payload': 'SubValue', + 'opt_payload': 'SubValue', + 'empty_array_sentinel': 'SubValue', + + 'eu_payload_ptr': 'PayloadPtr', + 'opt_payload_ptr': 'PayloadPtr', + + 'bytes': 'Bytes', + 'enum_literal': 'Bytes', + + 'slice': 'Slice', + + 'enum_field_index': 'U32', + + 'ty': 'Ty', + 'int_type': 'IntType', + 'int_u64': 'U64', + 'int_i64': 'I64', + 'function': 'Function', + 'variable': 'Variable', + 'decl_ref_mut': 'DeclRefMut', + 'elem_ptr': 'ElemPtr', + 'field_ptr': 'FieldPtr', + 'float_16': 'Float_16', + 'float_32': 'Float_32', + 'float_64': 'Float_64', + 'float_80': 'Float_80', + 'float_128': 'Float_128', + 'error': 'Error', + 'inferred_alloc': 'InferredAlloc', + 'inferred_alloc_comptime': 'InferredAllocComptime', + 'aggregate': 'Aggregate', + 'union': 'Union', + 'bound_fn': 'BoundFn', + } + + def __init__(self, val): + self.val = val + + def tag(self): + tag_if_small_enough = self.val['tag_if_small_enough'] + tag_type = tag_if_small_enough.type + + if tag_if_small_enough < ValuePrinter.no_payload_count: + return tag_if_small_enough + else: + return self.val['ptr_otherwise'].dereference()['tag'] + + def payload_type(self): + tag = self.tag() + if tag is None: + return None + + type_name = ValuePrinter.payload_type_names.get(str(tag)) + if type_name is None: + return None + return gdb.lookup_type('struct value.%s' % type_name) + + def to_string(self): + tag = self.tag() + if tag is None: + return '(invalid value)' + if self.val['tag_if_small_enough'] < ValuePrinter.no_payload_count: + return '.%s' % str(tag) + return None + + def children(self): + if self.val['tag_if_small_enough'] < ValuePrinter.no_payload_count: + return + + yield ('tag', '.%s' % str(self.tag())) + + payload_type = self.payload_type() + if payload_type is not None: + yield ('payload', self.val['ptr_otherwise'].cast(payload_type.pointer()).dereference()['data']) + pp1 = gdb.printing.RegexpCollectionPrettyPrinter('Zig stage1 compiler') pp1.add_printer('Buf', '^Buf$', BufPrinter) pp1.add_printer('ZigList', '^ZigList$', BufPrinter) @@ -293,6 +383,7 @@ ppstd.add_printer('ArrayHashMap', r'^std\.array_hash_map\.ArrayHashMap(Unmanaged gdb.printing.register_pretty_printer(gdb.current_objfile(), ppstd) pp2 = gdb.printing.RegexpCollectionPrettyPrinter('Zig stage2 compiler') -ppstd.add_printer('Type', r'^type\.Type$', TypePrinter) +pp2.add_printer('Type', r'^type\.Type$', TypePrinter) +pp2.add_printer('Value', r'^value\.Value$', ValuePrinter) gdb.printing.register_pretty_printer(gdb.current_objfile(), pp2)