diff --git a/src/InternPool.zig b/src/InternPool.zig index ecc7b7a383..c15e1afead 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -56,6 +56,7 @@ string_table: std.HashMapUnmanaged( std.hash_map.default_max_load_percentage, ) = .{}, +const builtin = @import("builtin"); const std = @import("std"); const Allocator = std.mem.Allocator; const assert = std.debug.assert; @@ -1057,6 +1058,131 @@ pub const Index = enum(u32) { return std.hash.uint32(@enumToInt(a)); } }; + + /// This function is used in the debugger pretty formatters in tools/ to fetch the + /// Tag to encoding mapping to facilitate fancy debug printing for this type. + fn dbHelper(self: *Index, tag_to_encoding_map: *struct { + const DataIsIndex = struct { data: Index }; + const DataIsExtraIndexOfEnumExplicit = struct { + const @"data.fields_len" = opaque {}; + data: *EnumExplicit, + @"trailing.names.len": *@"data.fields_len", + @"trailing.values.len": *@"data.fields_len", + trailing: struct { + names: []NullTerminatedString, + values: []Index, + }, + }; + const DataIsExtraIndexOfTypeStructAnon = struct { + const @"data.fields_len" = opaque {}; + data: *TypeStructAnon, + @"trailing.types.len": *@"data.fields_len", + @"trailing.values.len": *@"data.fields_len", + @"trailing.names.len": *@"data.fields_len", + trailing: struct { + types: []Index, + values: []Index, + names: []NullTerminatedString, + }, + }; + + type_int_signed: struct { data: u32 }, + type_int_unsigned: struct { data: u32 }, + type_array_big: struct { data: *Array }, + type_array_small: struct { data: *Vector }, + type_vector: struct { data: *Vector }, + type_pointer: struct { data: *Pointer }, + type_slice: DataIsIndex, + type_optional: DataIsIndex, + type_anyframe: DataIsIndex, + type_error_union: struct { data: *Key.ErrorUnionType }, + type_error_set: struct { + const @"data.names_len" = opaque {}; + data: *ErrorSet, + @"trailing.names.len": *@"data.names_len", + trailing: struct { names: []NullTerminatedString }, + }, + type_inferred_error_set: struct { data: Module.Fn.InferredErrorSet.Index }, + type_enum_auto: struct { + const @"data.fields_len" = opaque {}; + data: *EnumAuto, + @"trailing.names.len": *@"data.fields_len", + trailing: struct { names: []NullTerminatedString }, + }, + type_enum_explicit: DataIsExtraIndexOfEnumExplicit, + type_enum_nonexhaustive: DataIsExtraIndexOfEnumExplicit, + simple_type: struct { data: SimpleType }, + type_opaque: struct { data: *Key.OpaqueType }, + type_struct: struct { data: Module.Struct.OptionalIndex }, + type_struct_ns: struct { data: Module.Namespace.Index }, + type_struct_anon: DataIsExtraIndexOfTypeStructAnon, + type_tuple_anon: DataIsExtraIndexOfTypeStructAnon, + type_union_tagged: struct { data: Module.Union.Index }, + type_union_untagged: struct { data: Module.Union.Index }, + type_union_safety: struct { data: Module.Union.Index }, + type_function: struct { + const @"data.params_len" = opaque {}; + data: *TypeFunction, + @"trailing.param_types.len": *@"data.params_len", + trailing: struct { param_types: []Index }, + }, + + undef: DataIsIndex, + simple_value: struct { data: SimpleValue }, + ptr_var: struct { data: *PtrVar }, + ptr_mut_decl: struct { data: *PtrMutDecl }, + ptr_decl: struct { data: *PtrDecl }, + ptr_int: struct { data: *PtrInt }, + ptr_eu_payload: DataIsIndex, + ptr_opt_payload: DataIsIndex, + ptr_comptime_field: struct { data: *PtrComptimeField }, + ptr_elem: struct { data: *PtrBaseIndex }, + ptr_field: struct { data: *PtrBaseIndex }, + ptr_slice: struct { data: *PtrSlice }, + opt_payload: DataIsIndex, + opt_null: DataIsIndex, + int_u8: struct { data: u8 }, + int_u16: struct { data: u16 }, + int_u32: struct { data: u32 }, + int_i32: struct { data: i32 }, + int_usize: struct { data: u32 }, + int_comptime_int_u32: struct { data: u32 }, + int_comptime_int_i32: struct { data: i32 }, + int_small: struct { data: *IntSmall }, + int_positive: struct { data: u32 }, + int_negative: struct { data: u32 }, + enum_tag: struct { data: *Key.EnumTag }, + float_f16: struct { data: f16 }, + float_f32: struct { data: f32 }, + float_f64: struct { data: *Float64 }, + float_f80: struct { data: *Float80 }, + float_f128: struct { data: *Float128 }, + float_c_longdouble_f80: struct { data: *Float80 }, + float_c_longdouble_f128: struct { data: *Float128 }, + float_comptime_float: struct { data: *Float128 }, + extern_func: struct { data: void }, + func: struct { data: void }, + only_possible_value: DataIsIndex, + union_value: struct { data: *Key.Union }, + aggregate: struct { data: *Aggregate }, + repeated: struct { data: *Repeated }, + }) void { + _ = self; + @setEvalBranchQuota(10_000); + inline for (@typeInfo(Tag).Enum.fields) |tag| { + inline for (@typeInfo(@typeInfo(@TypeOf(tag_to_encoding_map)).Pointer.child).Struct.fields) |entry| { + if (comptime std.mem.eql(u8, tag.name, entry.name)) break; + } else { + @compileError(@typeName(Tag) ++ "." ++ tag.name ++ " missing dbHelper tag_to_encoding_map entry"); + } + } + } + + comptime { + if (builtin.mode == .Debug) { + _ = dbHelper; + } + } }; pub const static_keys = [_]Key{ @@ -1776,7 +1902,7 @@ pub const PtrVar = struct { is_const: bool, is_threadlocal: bool, is_weak_linkage: bool, - unused: u29 = undefined, + _: u29 = 0, }; }; diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 26d03c9be0..1eb6afd994 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -4693,8 +4693,8 @@ pub const FuncGen = struct { } fn resolveValue(self: *FuncGen, tv: TypedValue) !*llvm.Value { - const llvm_val = try self.dg.lowerValue(tv); const mod = self.dg.module; + const llvm_val = try self.dg.lowerValue(tv); if (!isByRef(tv.ty, mod)) return llvm_val; // We have an LLVM value but we need to create a global constant and @@ -4972,8 +4972,8 @@ pub const FuncGen = struct { const pl_op = self.air.instructions.items(.data)[inst].pl_op; const extra = self.air.extraData(Air.Call, pl_op.payload); const args = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]); - const callee_ty = self.typeOf(pl_op.operand); const mod = self.dg.module; + const callee_ty = self.typeOf(pl_op.operand); const zig_fn_ty = switch (callee_ty.zigTypeTag(mod)) { .Fn => callee_ty, .Pointer => callee_ty.childType(mod), diff --git a/tools/lldb_pretty_printers.py b/tools/lldb_pretty_printers.py index e0b84e1b41..6cccf77ee0 100644 --- a/tools/lldb_pretty_printers.py +++ b/tools/lldb_pretty_printers.py @@ -115,7 +115,7 @@ class zig_Slice_SynthProvider: try: return int(name.removeprefix('[').removesuffix(']')) except: return -1 def get_child_at_index(self, index): - if index < 0 or index >= self.len: return None + if index not in range(self.len): return None try: return self.ptr.CreateChildAtOffset('[%d]' % index, index * self.elem_size, self.elem_type) except: return None @@ -176,7 +176,7 @@ class zig_TaggedUnion_SynthProvider: def get_child_index(self, name): try: return ('tag', 'payload').index(name) except: return -1 - def get_child_at_index(self, index): return (self.tag, self.payload)[index] if index >= 0 and index < 2 else None + def get_child_at_index(self, index): return (self.tag, self.payload)[index] if index in range(2) else None # Define Zig Standard Library @@ -196,7 +196,7 @@ class std_SegmentedList_SynthProvider: except: return -1 def get_child_at_index(self, index): try: - if index < 0 or index >= self.len: return None + if index not in range(self.len): return None prealloc_item_count = len(self.prealloc_segment) if index < prealloc_item_count: return self.prealloc_segment.child[index] prealloc_exp = prealloc_item_count.bit_length() - 1 @@ -231,7 +231,7 @@ class std_MultiArrayList_SynthProvider: except: return -1 def get_child_at_index(self, index): try: - if index < 0 or index >= self.len: return None + if index not in range(self.len): return None offset = 0 data = lldb.SBData() for field in self.entry_type.fields: @@ -266,7 +266,7 @@ class std_MultiArrayList_Slice_SynthProvider: except: return -1 def get_child_at_index(self, index): try: - if index < 0 or index >= self.len: return None + if index not in range(self.len): return None data = lldb.SBData() for field in self.entry_type.fields: field_type = field.type.GetPointeeType() @@ -328,7 +328,7 @@ class std_Entry_SynthProvider: def has_children(self): return self.num_children() != 0 def num_children(self): return len(self.children) def get_child_index(self, name): return self.indices.get(name) - def get_child_at_index(self, index): return self.children[index].deref if index >= 0 and index < len(self.children) else None + def get_child_at_index(self, index): return self.children[index].deref if index in range(len(self.children)) else None # Define Zig Stage2 Compiler @@ -345,7 +345,7 @@ class TagAndPayload_SynthProvider: def get_child_index(self, name): try: return ('tag', 'payload').index(name) except: return -1 - def get_child_at_index(self, index): return (self.tag, self.payload)[index] if index >= 0 and index < 2 else None + def get_child_at_index(self, index): return (self.tag, self.payload)[index] if index in range(2) else None def Inst_Ref_SummaryProvider(value, _=None): members = value.type.enum_members @@ -392,7 +392,7 @@ class TagOrPayloadPtr_SynthProvider: def get_child_index(self, name): try: return ('tag', 'payload').index(name) except: return -1 - def get_child_at_index(self, index): return (self.tag, self.payload)[index] if index >= 0 and index < 2 else None + def get_child_at_index(self, index): return (self.tag, self.payload)[index] if index in range(2) else None def Module_Decl_name(decl): error = lldb.SBError() @@ -407,6 +407,71 @@ def Module_Decl_RenderFullyQualifiedName(decl): return '.'.join((Module_Namespac def OwnerDecl_RenderFullyQualifiedName(payload): return Module_Decl_RenderFullyQualifiedName(payload.GetChildMemberWithName('owner_decl').GetChildMemberWithName('decl')) +def InternPool_Find(thread): + for frame in thread: + ip = frame.FindVariable('ip') or frame.FindVariable('intern_pool') + if ip: return ip + mod = frame.FindVariable('mod') or frame.FindVariable('module') + if mod: + ip = mod.GetChildMemberWithName('intern_pool') + if ip: return ip + +class InternPool_Index_SynthProvider: + def __init__(self, value, _=None): self.value = value + def update(self): + try: + index_type = self.value.type + for helper in self.value.target.FindFunctions('%s.dbHelper' % index_type.name, lldb.eFunctionNameTypeFull): + ptr_self_type, ptr_tag_to_encoding_map_type = helper.function.type.GetFunctionArgumentTypes() + if ptr_self_type.GetPointeeType() == index_type: break + else: return + tag_to_encoding_map = {field.name: field.type for field in ptr_tag_to_encoding_map_type.GetPointeeType().fields} + + ip = InternPool_Find(self.value.thread) + if not ip: return + self.item = ip.GetChildMemberWithName('items').GetChildAtIndex(self.value.unsigned) + extra = ip.GetChildMemberWithName('extra').GetChildMemberWithName('items') + self.tag = self.item.GetChildMemberWithName('tag').Clone('tag') + self.data = None + self.trailing = None + data = self.item.GetChildMemberWithName('data') + encoding_type = tag_to_encoding_map[self.tag.value] + dynamic_values = {} + for encoding_field in encoding_type.fields: + if encoding_field.name == 'data': + if encoding_field.type.IsPointerType(): + data_type = encoding_field.type.GetPointeeType() + extra_index = data.unsigned + self.data = extra.GetChildAtIndex(extra_index).Cast(data_type).Clone('data') + extra_index += data_type.num_fields + else: + self.data = data.Cast(encoding_field.type).Clone('data') + elif encoding_field.name == 'trailing': + trailing_data = lldb.SBData() + for trailing_field in encoding_field.type.fields: + if trailing_field.type.IsAggregateType(): + trailing_data.Append(extra.GetChildAtIndex(extra_index).address_of.data) + len = dynamic_values['trailing.%s.len' % trailing_field.name].unsigned + trailing_data.Append(lldb.SBData.CreateDataFromInt(len, trailing_data.GetAddressByteSize())) + extra_index += len + else: + pass + self.trailing = self.data.CreateValueFromData('trailing', trailing_data, encoding_field.type) + else: + path = encoding_field.type.GetPointeeType().name.removeprefix('%s::' % encoding_type.name).removeprefix('%s.' % encoding_type.name).partition('__')[0].split('.') + if path[0] == 'data': + dynamic_value = self.data + for name in path[1:]: + dynamic_value = dynamic_value.GetChildMemberWithName(name) + dynamic_values[encoding_field.name] = dynamic_value + except: pass + def has_children(self): return True + def num_children(self): return 2 + (self.trailing is not None) + def get_child_index(self, name): + try: return ('tag', 'data', 'trailing').index(name) + except: return -1 + def get_child_at_index(self, index): return (self.tag, self.data, self.trailing)[index] if index in range(3) else None + def type_Type_pointer(payload): pointee_type = payload.GetChildMemberWithName('pointee_type') sentinel = payload.GetChildMemberWithName('sentinel').GetChildMemberWithName('child') @@ -616,8 +681,5 @@ def __lldb_init_module(debugger, _=None): add(debugger, category='zig.stage2', regex=True, type=MultiArrayList_Entry('Air\\.Inst'), identifier='TagAndPayload', synth=True, inline_children=True, summary=True) add(debugger, category='zig.stage2', regex=True, type='^Air\\.Inst\\.Data\\.Data__struct_[1-9][0-9]*$', inline_children=True, summary=True) add(debugger, category='zig.stage2', type='Module.Decl::Module.Decl.Index', synth=True) - add(debugger, category='zig.stage2', type='type.Type', identifier='TagOrPayloadPtr', synth=True) - add(debugger, category='zig.stage2', type='type.Type', summary=True) - add(debugger, category='zig.stage2', type='value.Value', identifier='TagOrPayloadPtr', synth=True) - add(debugger, category='zig.stage2', type='value.Value', summary=True) + add(debugger, category='zig.stage2', type='InternPool.Index', synth=True) add(debugger, category='zig.stage2', type='arch.x86_64.CodeGen.MCValue', identifier='zig_TaggedUnion', synth=True, inline_children=True, summary=True)