mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
InternPool: add lldb pretty printing for indices
This commit is contained in:
parent
a6fcf469fc
commit
a7c3ca3531
@ -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,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user