From f34b19825133ff13ea6e9faa576aa253f4d1252c Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Thu, 5 Sep 2024 15:58:24 -0400 Subject: [PATCH] Dwarf: implement and test decls --- ci/x86_64-linux-debug.sh | 2 +- ci/x86_64-linux-release.sh | 2 +- src/link/Dwarf.zig | 761 +++++++++++++++++-------------------- test/src/Debugger.zig | 67 +++- 4 files changed, 412 insertions(+), 420 deletions(-) diff --git a/ci/x86_64-linux-debug.sh b/ci/x86_64-linux-debug.sh index 8e9929bc22..370100e68e 100755 --- a/ci/x86_64-linux-debug.sh +++ b/ci/x86_64-linux-debug.sh @@ -64,7 +64,7 @@ stage3-debug/bin/zig build \ stage3-debug/bin/zig build test docs \ --maxrss 21000000000 \ - -Dlldb=$HOME/deps/lldb-zig/Debug-befcd57a8/bin/lldb \ + -Dlldb=$HOME/deps/lldb-zig/Debug-4a44163df/bin/lldb \ -fqemu \ -fwasmtime \ -Dstatic-llvm \ diff --git a/ci/x86_64-linux-release.sh b/ci/x86_64-linux-release.sh index 346e942602..8ee7f79412 100755 --- a/ci/x86_64-linux-release.sh +++ b/ci/x86_64-linux-release.sh @@ -64,7 +64,7 @@ stage3-release/bin/zig build \ stage3-release/bin/zig build test docs \ --maxrss 21000000000 \ - -Dlldb=$HOME/deps/lldb-zig/Release-befcd57a8/bin/lldb \ + -Dlldb=$HOME/deps/lldb-zig/Release-4a44163df/bin/lldb \ -fqemu \ -fwasmtime \ -Dstatic-llvm \ diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 26aafd8092..2a9fd8f8f9 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -2509,6 +2509,19 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool return; } + const parent_type, const accessibility: u8 = if (nav.analysis_owner.unwrap()) |cau| parent: { + const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).namespace); + break :parent .{ + parent_namespace_ptr.owner_type, + if (parent_namespace_ptr.pub_decls.containsContext(nav_index, .{ .zcu = zcu })) + DW.ACCESS.public + else if (parent_namespace_ptr.priv_decls.containsContext(nav_index, .{ .zcu = zcu })) + DW.ACCESS.private + else + unreachable, + }; + } else .{ zcu.fileRootType(inst_info.file), DW.ACCESS.private }; + const tree = try file.getTree(dwarf.gpa); const loc = tree.tokenLocation(0, tree.nodes.items(.main_token)[decl_inst.data.declaration.src_node]); assert(loc.line == zcu.navSrcLine(nav_index)); @@ -2534,8 +2547,328 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool const nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index); errdefer _ = dwarf.navs.pop(); - switch (ip.indexToKey(nav_val.toIntern())) { - .func => |func| { + + const tag: enum { done, decl_alias } = switch (ip.indexToKey(nav_val.toIntern())) { + .int_type, + .ptr_type, + .array_type, + .vector_type, + .opt_type, + .anyframe_type, + .error_union_type, + .simple_type, + .anon_struct_type, + .func_type, + .error_set_type, + .inferred_error_set_type, + => .decl_alias, + .struct_type => tag: { + const loaded_struct = ip.loadStructType(nav_val.toIntern()); + if (loaded_struct.zir_index == .none) break :tag .decl_alias; + + const type_inst_info = loaded_struct.zir_index.unwrap().?.resolveFull(ip).?; + if (type_inst_info.file != inst_info.file) break :tag .decl_alias; + + const value_inst = value_inst: { + const decl_value_body = decl_extra.data.getBodies(@intCast(decl_extra.end), file.zir).value_body; + const break_inst = file.zir.instructions.get(@intFromEnum(decl_value_body[decl_value_body.len - 1])); + if (break_inst.tag != .break_inline) break :value_inst null; + assert(file.zir.extraData(Zir.Inst.Break, break_inst.data.@"break".payload_index).data.block_inst == inst_info.inst); + var value_inst = break_inst.data.@"break".operand.toIndex(); + while (value_inst) |value_inst_index| switch (file.zir.instructions.items(.tag)[@intFromEnum(value_inst_index)]) { + else => break, + .as_node => value_inst = file.zir.extraData( + Zir.Inst.As, + file.zir.instructions.items(.data)[@intFromEnum(value_inst_index)].pl_node.payload_index, + ).data.operand.toIndex(), + }; + break :value_inst value_inst; + }; + if (type_inst_info.inst != value_inst) break :tag .decl_alias; + + const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern()); + if (type_gop.found_existing) { + dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).clear(); + nav_gop.value_ptr.* = type_gop.value_ptr.*; + } else { + if (nav_gop.found_existing) + dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear() + else + nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit); + type_gop.value_ptr.* = nav_gop.value_ptr.*; + } + wip_nav.entry = nav_gop.value_ptr.*; + + const diw = wip_nav.debug_info.writer(dwarf.gpa); + + switch (loaded_struct.layout) { + .auto, .@"extern" => { + try wip_nav.abbrevCode(if (loaded_struct.field_types.len == 0) .decl_namespace_struct else .decl_struct); + try wip_nav.refType(Type.fromInterned(parent_type)); + assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); + try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian); + try uleb128(diw, loc.column + 1); + try diw.writeByte(accessibility); + try wip_nav.strp(nav.name.toSlice(ip)); + if (loaded_struct.field_types.len == 0) try diw.writeByte(@intFromBool(false)) else { + try uleb128(diw, nav_val.toType().abiSize(zcu)); + try uleb128(diw, nav_val.toType().abiAlignment(zcu).toByteUnits().?); + for (0..loaded_struct.field_types.len) |field_index| { + const is_comptime = loaded_struct.fieldIsComptime(ip, field_index); + try wip_nav.abbrevCode(if (is_comptime) .struct_field_comptime else .struct_field); + if (loaded_struct.fieldName(ip, field_index).unwrap()) |field_name| try wip_nav.strp(field_name.toSlice(ip)) else { + const field_name = try std.fmt.allocPrint(dwarf.gpa, "{d}", .{field_index}); + defer dwarf.gpa.free(field_name); + try wip_nav.strp(field_name); + } + const field_type = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); + try wip_nav.refType(field_type); + if (!is_comptime) { + try uleb128(diw, loaded_struct.offsets.get(ip)[field_index]); + try uleb128(diw, loaded_struct.fieldAlign(ip, field_index).toByteUnits() orelse + field_type.abiAlignment(zcu).toByteUnits().?); + } + } + try uleb128(diw, @intFromEnum(AbbrevCode.null)); + } + }, + .@"packed" => { + try wip_nav.abbrevCode(.decl_packed_struct); + try wip_nav.refType(Type.fromInterned(parent_type)); + assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); + try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian); + try uleb128(diw, loc.column + 1); + try diw.writeByte(accessibility); + try wip_nav.strp(nav.name.toSlice(ip)); + try wip_nav.refType(Type.fromInterned(loaded_struct.backingIntTypeUnordered(ip))); + var field_bit_offset: u16 = 0; + for (0..loaded_struct.field_types.len) |field_index| { + try wip_nav.abbrevCode(.packed_struct_field); + try wip_nav.strp(loaded_struct.fieldName(ip, field_index).unwrap().?.toSlice(ip)); + const field_type = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); + try wip_nav.refType(field_type); + try uleb128(diw, field_bit_offset); + field_bit_offset += @intCast(field_type.bitSize(zcu)); + } + try uleb128(diw, @intFromEnum(AbbrevCode.null)); + }, + } + break :tag .done; + }, + .enum_type => tag: { + const loaded_enum = ip.loadEnumType(nav_val.toIntern()); + if (loaded_enum.zir_index == .none) break :tag .decl_alias; + + const type_inst_info = loaded_enum.zir_index.unwrap().?.resolveFull(ip).?; + if (type_inst_info.file != inst_info.file) break :tag .decl_alias; + + const value_inst = value_inst: { + const decl_value_body = decl_extra.data.getBodies(@intCast(decl_extra.end), file.zir).value_body; + const break_inst = file.zir.instructions.get(@intFromEnum(decl_value_body[decl_value_body.len - 1])); + if (break_inst.tag != .break_inline) break :value_inst null; + assert(file.zir.extraData(Zir.Inst.Break, break_inst.data.@"break".payload_index).data.block_inst == inst_info.inst); + var value_inst = break_inst.data.@"break".operand.toIndex(); + while (value_inst) |value_inst_index| switch (file.zir.instructions.items(.tag)[@intFromEnum(value_inst_index)]) { + else => break, + .as_node => value_inst = file.zir.extraData( + Zir.Inst.As, + file.zir.instructions.items(.data)[@intFromEnum(value_inst_index)].pl_node.payload_index, + ).data.operand.toIndex(), + }; + break :value_inst value_inst; + }; + if (type_inst_info.inst != value_inst) break :tag .decl_alias; + + const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern()); + if (type_gop.found_existing) { + dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).clear(); + nav_gop.value_ptr.* = type_gop.value_ptr.*; + } else { + if (nav_gop.found_existing) + dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear() + else + nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit); + type_gop.value_ptr.* = nav_gop.value_ptr.*; + } + wip_nav.entry = nav_gop.value_ptr.*; + const diw = wip_nav.debug_info.writer(dwarf.gpa); + try wip_nav.abbrevCode(if (loaded_enum.names.len > 0) .decl_enum else .decl_empty_enum); + try wip_nav.refType(Type.fromInterned(parent_type)); + assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); + try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian); + try uleb128(diw, loc.column + 1); + try diw.writeByte(accessibility); + try wip_nav.strp(nav.name.toSlice(ip)); + try wip_nav.refType(Type.fromInterned(loaded_enum.tag_ty)); + for (0..loaded_enum.names.len) |field_index| { + try wip_nav.enumConstValue(loaded_enum, .{ + .sdata = .signed_enum_field, + .udata = .unsigned_enum_field, + .block = .big_enum_field, + }, field_index); + try wip_nav.strp(loaded_enum.names.get(ip)[field_index].toSlice(ip)); + } + if (loaded_enum.names.len > 0) try uleb128(diw, @intFromEnum(AbbrevCode.null)); + break :tag .done; + }, + .union_type => tag: { + const loaded_union = ip.loadUnionType(nav_val.toIntern()); + + const type_inst_info = loaded_union.zir_index.resolveFull(ip).?; + if (type_inst_info.file != inst_info.file) break :tag .decl_alias; + + const value_inst = value_inst: { + const decl_value_body = decl_extra.data.getBodies(@intCast(decl_extra.end), file.zir).value_body; + const break_inst = file.zir.instructions.get(@intFromEnum(decl_value_body[decl_value_body.len - 1])); + if (break_inst.tag != .break_inline) break :value_inst null; + assert(file.zir.extraData(Zir.Inst.Break, break_inst.data.@"break".payload_index).data.block_inst == inst_info.inst); + var value_inst = break_inst.data.@"break".operand.toIndex(); + while (value_inst) |value_inst_index| switch (file.zir.instructions.items(.tag)[@intFromEnum(value_inst_index)]) { + else => break, + .as_node => value_inst = file.zir.extraData( + Zir.Inst.As, + file.zir.instructions.items(.data)[@intFromEnum(value_inst_index)].pl_node.payload_index, + ).data.operand.toIndex(), + }; + break :value_inst value_inst; + }; + if (type_inst_info.inst != value_inst) break :tag .decl_alias; + + const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern()); + if (type_gop.found_existing) { + dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).clear(); + nav_gop.value_ptr.* = type_gop.value_ptr.*; + } else { + if (nav_gop.found_existing) + dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear() + else + nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit); + type_gop.value_ptr.* = nav_gop.value_ptr.*; + } + wip_nav.entry = nav_gop.value_ptr.*; + const diw = wip_nav.debug_info.writer(dwarf.gpa); + try wip_nav.abbrevCode(.decl_union); + try wip_nav.refType(Type.fromInterned(parent_type)); + assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); + try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian); + try uleb128(diw, loc.column + 1); + try diw.writeByte(accessibility); + try wip_nav.strp(nav.name.toSlice(ip)); + const union_layout = Type.getUnionLayout(loaded_union, zcu); + try uleb128(diw, union_layout.abi_size); + try uleb128(diw, union_layout.abi_align.toByteUnits().?); + const loaded_tag = loaded_union.loadTagType(ip); + if (loaded_union.hasTag(ip)) { + try wip_nav.abbrevCode(.tagged_union); + try wip_nav.infoSectionOffset( + .debug_info, + wip_nav.unit, + wip_nav.entry, + @intCast(wip_nav.debug_info.items.len + dwarf.sectionOffsetBytes()), + ); + { + try wip_nav.abbrevCode(.generated_field); + try wip_nav.strp("tag"); + try wip_nav.refType(Type.fromInterned(loaded_union.enum_tag_ty)); + try uleb128(diw, union_layout.tagOffset()); + + for (0..loaded_union.field_types.len) |field_index| { + try wip_nav.enumConstValue(loaded_tag, .{ + .sdata = .signed_tagged_union_field, + .udata = .unsigned_tagged_union_field, + .block = .big_tagged_union_field, + }, field_index); + { + try wip_nav.abbrevCode(.struct_field); + try wip_nav.strp(loaded_tag.names.get(ip)[field_index].toSlice(ip)); + const field_type = Type.fromInterned(loaded_union.field_types.get(ip)[field_index]); + try wip_nav.refType(field_type); + try uleb128(diw, union_layout.payloadOffset()); + try uleb128(diw, loaded_union.fieldAlign(ip, field_index).toByteUnits() orelse + if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?); + } + try uleb128(diw, @intFromEnum(AbbrevCode.null)); + } + } + try uleb128(diw, @intFromEnum(AbbrevCode.null)); + } else for (0..loaded_union.field_types.len) |field_index| { + try wip_nav.abbrevCode(.untagged_union_field); + try wip_nav.strp(loaded_tag.names.get(ip)[field_index].toSlice(ip)); + const field_type = Type.fromInterned(loaded_union.field_types.get(ip)[field_index]); + try wip_nav.refType(field_type); + try uleb128(diw, loaded_union.fieldAlign(ip, field_index).toByteUnits() orelse + field_type.abiAlignment(zcu).toByteUnits().?); + } + try uleb128(diw, @intFromEnum(AbbrevCode.null)); + break :tag .done; + }, + .opaque_type => tag: { + const loaded_opaque = ip.loadOpaqueType(nav_val.toIntern()); + + const type_inst_info = loaded_opaque.zir_index.resolveFull(ip).?; + if (type_inst_info.file != inst_info.file) break :tag .decl_alias; + + const value_inst = value_inst: { + const decl_value_body = decl_extra.data.getBodies(@intCast(decl_extra.end), file.zir).value_body; + const break_inst = file.zir.instructions.get(@intFromEnum(decl_value_body[decl_value_body.len - 1])); + if (break_inst.tag != .break_inline) break :value_inst null; + assert(file.zir.extraData(Zir.Inst.Break, break_inst.data.@"break".payload_index).data.block_inst == inst_info.inst); + var value_inst = break_inst.data.@"break".operand.toIndex(); + while (value_inst) |value_inst_index| switch (file.zir.instructions.items(.tag)[@intFromEnum(value_inst_index)]) { + else => break, + .as_node => value_inst = file.zir.extraData( + Zir.Inst.As, + file.zir.instructions.items(.data)[@intFromEnum(value_inst_index)].pl_node.payload_index, + ).data.operand.toIndex(), + }; + break :value_inst value_inst; + }; + if (type_inst_info.inst != value_inst) break :tag .decl_alias; + + const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern()); + if (type_gop.found_existing) { + dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).clear(); + nav_gop.value_ptr.* = type_gop.value_ptr.*; + } else { + if (nav_gop.found_existing) + dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear() + else + nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit); + type_gop.value_ptr.* = nav_gop.value_ptr.*; + } + wip_nav.entry = nav_gop.value_ptr.*; + const diw = wip_nav.debug_info.writer(dwarf.gpa); + try wip_nav.abbrevCode(.decl_namespace_struct); + try wip_nav.refType(Type.fromInterned(parent_type)); + assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); + try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian); + try uleb128(diw, loc.column + 1); + try diw.writeByte(accessibility); + try wip_nav.strp(nav.name.toSlice(ip)); + try diw.writeByte(@intFromBool(false)); + break :tag .done; + }, + .undef, + .simple_value, + .variable, + .@"extern", + .int, + .err, + .error_union, + .enum_literal, + .enum_tag, + .empty_enum_value, + .float, + .ptr, + .slice, + .opt, + .aggregate, + .un, + => { + _ = dwarf.navs.pop(); + return; + }, + .func => |func| tag: { if (nav_gop.found_existing) { const unit_ptr = dwarf.debug_info.section.getUnit(wip_nav.unit); const entry_ptr = unit_ptr.getEntry(nav_gop.value_ptr.*); @@ -2559,19 +2892,6 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool } else nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit); wip_nav.entry = nav_gop.value_ptr.*; - const parent_type, const accessibility: u8 = if (nav.analysis_owner.unwrap()) |cau| parent: { - const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).namespace); - break :parent .{ - parent_namespace_ptr.owner_type, - if (parent_namespace_ptr.pub_decls.containsContext(nav_index, .{ .zcu = zcu })) - DW.ACCESS.public - else if (parent_namespace_ptr.priv_decls.containsContext(nav_index, .{ .zcu = zcu })) - DW.ACCESS.private - else - unreachable, - }; - } else .{ zcu.fileRootType(inst_info.file), DW.ACCESS.private }; - const func_type = ip.indexToKey(func.ty).func_type; const diw = wip_nav.debug_info.writer(dwarf.gpa); try wip_nav.abbrevCode(if (func_type.param_types.len > 0 or func_type.is_var_args) @@ -2593,116 +2913,14 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool if (func_type.is_var_args) try wip_nav.abbrevCode(.is_var_args); try uleb128(diw, @intFromEnum(AbbrevCode.null)); } + break :tag .done; }, - .struct_type => done: { - const loaded_struct = ip.loadStructType(nav_val.toIntern()); - - const parent_type, const accessibility: u8 = if (nav.analysis_owner.unwrap()) |cau| parent: { - const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).namespace); - break :parent .{ - parent_namespace_ptr.owner_type, - if (parent_namespace_ptr.pub_decls.containsContext(nav_index, .{ .zcu = zcu })) - DW.ACCESS.public - else if (parent_namespace_ptr.priv_decls.containsContext(nav_index, .{ .zcu = zcu })) - DW.ACCESS.private - else - unreachable, - }; - } else .{ zcu.fileRootType(inst_info.file), DW.ACCESS.private }; - - decl_struct: { - if (loaded_struct.zir_index == .none) break :decl_struct; - - const type_inst_info = loaded_struct.zir_index.unwrap().?.resolveFull(ip).?; - if (type_inst_info.file != inst_info.file) break :decl_struct; - - const value_inst = value_inst: { - const decl_value_body = decl_extra.data.getBodies(@intCast(decl_extra.end), file.zir).value_body; - const break_inst = file.zir.instructions.get(@intFromEnum(decl_value_body[decl_value_body.len - 1])); - if (break_inst.tag != .break_inline) break :value_inst null; - assert(file.zir.extraData(Zir.Inst.Break, break_inst.data.@"break".payload_index).data.block_inst == inst_info.inst); - var value_inst = break_inst.data.@"break".operand.toIndex(); - while (value_inst) |value_inst_index| switch (file.zir.instructions.items(.tag)[@intFromEnum(value_inst_index)]) { - else => break, - .as_node => value_inst = file.zir.extraData( - Zir.Inst.As, - file.zir.instructions.items(.data)[@intFromEnum(value_inst_index)].pl_node.payload_index, - ).data.operand.toIndex(), - }; - break :value_inst value_inst; - }; - if (type_inst_info.inst != value_inst) break :decl_struct; - - const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern()); - if (type_gop.found_existing) { - dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).clear(); - nav_gop.value_ptr.* = type_gop.value_ptr.*; - } else { - if (nav_gop.found_existing) - dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear() - else - nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit); - type_gop.value_ptr.* = nav_gop.value_ptr.*; - } - wip_nav.entry = nav_gop.value_ptr.*; - - const diw = wip_nav.debug_info.writer(dwarf.gpa); - - switch (loaded_struct.layout) { - .auto, .@"extern" => { - try wip_nav.abbrevCode(if (loaded_struct.field_types.len == 0) .decl_namespace_struct else .decl_struct); - try wip_nav.refType(Type.fromInterned(parent_type)); - assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); - try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian); - try uleb128(diw, loc.column + 1); - try diw.writeByte(accessibility); - try wip_nav.strp(nav.name.toSlice(ip)); - if (loaded_struct.field_types.len == 0) try diw.writeByte(@intFromBool(false)) else { - try uleb128(diw, nav_val.toType().abiSize(zcu)); - try uleb128(diw, nav_val.toType().abiAlignment(zcu).toByteUnits().?); - for (0..loaded_struct.field_types.len) |field_index| { - const is_comptime = loaded_struct.fieldIsComptime(ip, field_index); - try wip_nav.abbrevCode(if (is_comptime) .struct_field_comptime else .struct_field); - if (loaded_struct.fieldName(ip, field_index).unwrap()) |field_name| try wip_nav.strp(field_name.toSlice(ip)) else { - const field_name = try std.fmt.allocPrint(dwarf.gpa, "{d}", .{field_index}); - defer dwarf.gpa.free(field_name); - try wip_nav.strp(field_name); - } - const field_type = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); - try wip_nav.refType(field_type); - if (!is_comptime) { - try uleb128(diw, loaded_struct.offsets.get(ip)[field_index]); - try uleb128(diw, loaded_struct.fieldAlign(ip, field_index).toByteUnits() orelse - field_type.abiAlignment(zcu).toByteUnits().?); - } - } - try uleb128(diw, @intFromEnum(AbbrevCode.null)); - } - }, - .@"packed" => { - try wip_nav.abbrevCode(.decl_packed_struct); - try wip_nav.refType(Type.fromInterned(parent_type)); - assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); - try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian); - try uleb128(diw, loc.column + 1); - try diw.writeByte(accessibility); - try wip_nav.strp(nav.name.toSlice(ip)); - try wip_nav.refType(Type.fromInterned(loaded_struct.backingIntTypeUnordered(ip))); - var field_bit_offset: u16 = 0; - for (0..loaded_struct.field_types.len) |field_index| { - try wip_nav.abbrevCode(.packed_struct_field); - try wip_nav.strp(loaded_struct.fieldName(ip, field_index).unwrap().?.toSlice(ip)); - const field_type = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); - try wip_nav.refType(field_type); - try uleb128(diw, field_bit_offset); - field_bit_offset += @intCast(field_type.bitSize(zcu)); - } - try uleb128(diw, @intFromEnum(AbbrevCode.null)); - }, - } - break :done; - } - + // memoization, not types + .memoized_call => unreachable, + }; + switch (tag) { + .done => {}, + .decl_alias => { if (nav_gop.found_existing) dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear() else @@ -2718,294 +2936,6 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool try wip_nav.strp(nav.name.toSlice(ip)); try wip_nav.refType(nav_val.toType()); }, - .enum_type => done: { - const loaded_enum = ip.loadEnumType(nav_val.toIntern()); - - const parent_type, const accessibility: u8 = if (nav.analysis_owner.unwrap()) |cau| parent: { - const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).namespace); - break :parent .{ - parent_namespace_ptr.owner_type, - if (parent_namespace_ptr.pub_decls.containsContext(nav_index, .{ .zcu = zcu })) - DW.ACCESS.public - else if (parent_namespace_ptr.priv_decls.containsContext(nav_index, .{ .zcu = zcu })) - DW.ACCESS.private - else - unreachable, - }; - } else .{ zcu.fileRootType(inst_info.file), DW.ACCESS.private }; - - decl_enum: { - if (loaded_enum.zir_index == .none) break :decl_enum; - - const type_inst_info = loaded_enum.zir_index.unwrap().?.resolveFull(ip).?; - if (type_inst_info.file != inst_info.file) break :decl_enum; - - const value_inst = value_inst: { - const decl_value_body = decl_extra.data.getBodies(@intCast(decl_extra.end), file.zir).value_body; - const break_inst = file.zir.instructions.get(@intFromEnum(decl_value_body[decl_value_body.len - 1])); - if (break_inst.tag != .break_inline) break :value_inst null; - assert(file.zir.extraData(Zir.Inst.Break, break_inst.data.@"break".payload_index).data.block_inst == inst_info.inst); - var value_inst = break_inst.data.@"break".operand.toIndex(); - while (value_inst) |value_inst_index| switch (file.zir.instructions.items(.tag)[@intFromEnum(value_inst_index)]) { - else => break, - .as_node => value_inst = file.zir.extraData( - Zir.Inst.As, - file.zir.instructions.items(.data)[@intFromEnum(value_inst_index)].pl_node.payload_index, - ).data.operand.toIndex(), - }; - break :value_inst value_inst; - }; - if (type_inst_info.inst != value_inst) break :decl_enum; - - const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern()); - if (type_gop.found_existing) { - dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).clear(); - nav_gop.value_ptr.* = type_gop.value_ptr.*; - } else { - if (nav_gop.found_existing) - dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear() - else - nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit); - type_gop.value_ptr.* = nav_gop.value_ptr.*; - } - wip_nav.entry = nav_gop.value_ptr.*; - const diw = wip_nav.debug_info.writer(dwarf.gpa); - try wip_nav.abbrevCode(if (loaded_enum.names.len > 0) .decl_enum else .decl_empty_enum); - try wip_nav.refType(Type.fromInterned(parent_type)); - assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); - try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian); - try uleb128(diw, loc.column + 1); - try diw.writeByte(accessibility); - try wip_nav.strp(nav.name.toSlice(ip)); - try wip_nav.refType(Type.fromInterned(loaded_enum.tag_ty)); - for (0..loaded_enum.names.len) |field_index| { - try wip_nav.enumConstValue(loaded_enum, .{ - .sdata = .signed_enum_field, - .udata = .unsigned_enum_field, - .block = .big_enum_field, - }, field_index); - try wip_nav.strp(loaded_enum.names.get(ip)[field_index].toSlice(ip)); - } - if (loaded_enum.names.len > 0) try uleb128(diw, @intFromEnum(AbbrevCode.null)); - break :done; - } - - if (nav_gop.found_existing) - dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear() - else - nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit); - wip_nav.entry = nav_gop.value_ptr.*; - const diw = wip_nav.debug_info.writer(dwarf.gpa); - try wip_nav.abbrevCode(.decl_alias); - try wip_nav.refType(Type.fromInterned(parent_type)); - assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); - try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian); - try uleb128(diw, loc.column + 1); - try diw.writeByte(accessibility); - try wip_nav.strp(nav.name.toSlice(ip)); - try wip_nav.refType(nav_val.toType()); - }, - .union_type => done: { - const loaded_union = ip.loadUnionType(nav_val.toIntern()); - - const parent_type, const accessibility: u8 = if (nav.analysis_owner.unwrap()) |cau| parent: { - const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).namespace); - break :parent .{ - parent_namespace_ptr.owner_type, - if (parent_namespace_ptr.pub_decls.containsContext(nav_index, .{ .zcu = zcu })) - DW.ACCESS.public - else if (parent_namespace_ptr.priv_decls.containsContext(nav_index, .{ .zcu = zcu })) - DW.ACCESS.private - else - unreachable, - }; - } else .{ zcu.fileRootType(inst_info.file), DW.ACCESS.private }; - - decl_union: { - const type_inst_info = loaded_union.zir_index.resolveFull(ip).?; - if (type_inst_info.file != inst_info.file) break :decl_union; - - const value_inst = value_inst: { - const decl_value_body = decl_extra.data.getBodies(@intCast(decl_extra.end), file.zir).value_body; - const break_inst = file.zir.instructions.get(@intFromEnum(decl_value_body[decl_value_body.len - 1])); - if (break_inst.tag != .break_inline) break :value_inst null; - assert(file.zir.extraData(Zir.Inst.Break, break_inst.data.@"break".payload_index).data.block_inst == inst_info.inst); - var value_inst = break_inst.data.@"break".operand.toIndex(); - while (value_inst) |value_inst_index| switch (file.zir.instructions.items(.tag)[@intFromEnum(value_inst_index)]) { - else => break, - .as_node => value_inst = file.zir.extraData( - Zir.Inst.As, - file.zir.instructions.items(.data)[@intFromEnum(value_inst_index)].pl_node.payload_index, - ).data.operand.toIndex(), - }; - break :value_inst value_inst; - }; - if (type_inst_info.inst != value_inst) break :decl_union; - - const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern()); - if (type_gop.found_existing) { - dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).clear(); - nav_gop.value_ptr.* = type_gop.value_ptr.*; - } else { - if (nav_gop.found_existing) - dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear() - else - nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit); - type_gop.value_ptr.* = nav_gop.value_ptr.*; - } - wip_nav.entry = nav_gop.value_ptr.*; - const diw = wip_nav.debug_info.writer(dwarf.gpa); - try wip_nav.abbrevCode(.decl_union); - try wip_nav.refType(Type.fromInterned(parent_type)); - assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); - try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian); - try uleb128(diw, loc.column + 1); - try diw.writeByte(accessibility); - try wip_nav.strp(nav.name.toSlice(ip)); - const union_layout = Type.getUnionLayout(loaded_union, zcu); - try uleb128(diw, union_layout.abi_size); - try uleb128(diw, union_layout.abi_align.toByteUnits().?); - const loaded_tag = loaded_union.loadTagType(ip); - if (loaded_union.hasTag(ip)) { - try wip_nav.abbrevCode(.tagged_union); - try wip_nav.infoSectionOffset( - .debug_info, - wip_nav.unit, - wip_nav.entry, - @intCast(wip_nav.debug_info.items.len + dwarf.sectionOffsetBytes()), - ); - { - try wip_nav.abbrevCode(.generated_field); - try wip_nav.strp("tag"); - try wip_nav.refType(Type.fromInterned(loaded_union.enum_tag_ty)); - try uleb128(diw, union_layout.tagOffset()); - - for (0..loaded_union.field_types.len) |field_index| { - try wip_nav.enumConstValue(loaded_tag, .{ - .sdata = .signed_tagged_union_field, - .udata = .unsigned_tagged_union_field, - .block = .big_tagged_union_field, - }, field_index); - { - try wip_nav.abbrevCode(.struct_field); - try wip_nav.strp(loaded_tag.names.get(ip)[field_index].toSlice(ip)); - const field_type = Type.fromInterned(loaded_union.field_types.get(ip)[field_index]); - try wip_nav.refType(field_type); - try uleb128(diw, union_layout.payloadOffset()); - try uleb128(diw, loaded_union.fieldAlign(ip, field_index).toByteUnits() orelse - if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?); - } - try uleb128(diw, @intFromEnum(AbbrevCode.null)); - } - } - try uleb128(diw, @intFromEnum(AbbrevCode.null)); - } else for (0..loaded_union.field_types.len) |field_index| { - try wip_nav.abbrevCode(.untagged_union_field); - try wip_nav.strp(loaded_tag.names.get(ip)[field_index].toSlice(ip)); - const field_type = Type.fromInterned(loaded_union.field_types.get(ip)[field_index]); - try wip_nav.refType(field_type); - try uleb128(diw, loaded_union.fieldAlign(ip, field_index).toByteUnits() orelse - field_type.abiAlignment(zcu).toByteUnits().?); - } - try uleb128(diw, @intFromEnum(AbbrevCode.null)); - break :done; - } - - if (nav_gop.found_existing) - dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear() - else - nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit); - wip_nav.entry = nav_gop.value_ptr.*; - const diw = wip_nav.debug_info.writer(dwarf.gpa); - try wip_nav.abbrevCode(.decl_alias); - try wip_nav.refType(Type.fromInterned(parent_type)); - assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); - try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian); - try uleb128(diw, loc.column + 1); - try diw.writeByte(accessibility); - try wip_nav.strp(nav.name.toSlice(ip)); - try wip_nav.refType(nav_val.toType()); - }, - .opaque_type => done: { - const loaded_opaque = ip.loadOpaqueType(nav_val.toIntern()); - - const parent_type, const accessibility: u8 = if (nav.analysis_owner.unwrap()) |cau| parent: { - const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).namespace); - break :parent .{ - parent_namespace_ptr.owner_type, - if (parent_namespace_ptr.pub_decls.containsContext(nav_index, .{ .zcu = zcu })) - DW.ACCESS.public - else if (parent_namespace_ptr.priv_decls.containsContext(nav_index, .{ .zcu = zcu })) - DW.ACCESS.private - else - unreachable, - }; - } else .{ zcu.fileRootType(inst_info.file), DW.ACCESS.private }; - - decl_opaque: { - const type_inst_info = loaded_opaque.zir_index.resolveFull(ip).?; - if (type_inst_info.file != inst_info.file) break :decl_opaque; - - const value_inst = value_inst: { - const decl_value_body = decl_extra.data.getBodies(@intCast(decl_extra.end), file.zir).value_body; - const break_inst = file.zir.instructions.get(@intFromEnum(decl_value_body[decl_value_body.len - 1])); - if (break_inst.tag != .break_inline) break :value_inst null; - assert(file.zir.extraData(Zir.Inst.Break, break_inst.data.@"break".payload_index).data.block_inst == inst_info.inst); - var value_inst = break_inst.data.@"break".operand.toIndex(); - while (value_inst) |value_inst_index| switch (file.zir.instructions.items(.tag)[@intFromEnum(value_inst_index)]) { - else => break, - .as_node => value_inst = file.zir.extraData( - Zir.Inst.As, - file.zir.instructions.items(.data)[@intFromEnum(value_inst_index)].pl_node.payload_index, - ).data.operand.toIndex(), - }; - break :value_inst value_inst; - }; - if (type_inst_info.inst != value_inst) break :decl_opaque; - - const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern()); - if (type_gop.found_existing) { - dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).clear(); - nav_gop.value_ptr.* = type_gop.value_ptr.*; - } else { - if (nav_gop.found_existing) - dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear() - else - nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit); - type_gop.value_ptr.* = nav_gop.value_ptr.*; - } - wip_nav.entry = nav_gop.value_ptr.*; - const diw = wip_nav.debug_info.writer(dwarf.gpa); - try wip_nav.abbrevCode(.decl_namespace_struct); - try wip_nav.refType(Type.fromInterned(parent_type)); - assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); - try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian); - try uleb128(diw, loc.column + 1); - try diw.writeByte(accessibility); - try wip_nav.strp(nav.name.toSlice(ip)); - try diw.writeByte(@intFromBool(false)); - break :done; - } - - if (nav_gop.found_existing) - dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear() - else - nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit); - wip_nav.entry = nav_gop.value_ptr.*; - const diw = wip_nav.debug_info.writer(dwarf.gpa); - try wip_nav.abbrevCode(.decl_alias); - try wip_nav.refType(Type.fromInterned(parent_type)); - assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); - try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian); - try uleb128(diw, loc.column + 1); - try diw.writeByte(accessibility); - try wip_nav.strp(nav.name.toSlice(ip)); - try wip_nav.refType(nav_val.toType()); - }, - else => { - _ = dwarf.navs.pop(); - return; - }, } try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items); try wip_nav.flush(); @@ -3734,12 +3664,15 @@ fn refAbbrevCode(dwarf: *Dwarf, abbrev_code: AbbrevCode) UpdateError!@typeInfo(A pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { const zcu = pt.zcu; const ip = &zcu.intern_pool; - if (dwarf.types.get(.anyerror_type)) |entry| { + + { + const type_gop = try dwarf.types.getOrPut(dwarf.gpa, .anyerror_type); + if (!type_gop.found_existing) type_gop.value_ptr.* = try dwarf.addCommonEntry(.main); var wip_nav: WipNav = .{ .dwarf = dwarf, .pt = pt, .unit = .main, - .entry = entry, + .entry = type_gop.value_ptr.*, .any_children = false, .func = .none, .func_sym_index = undefined, diff --git a/test/src/Debugger.zig b/test/src/Debugger.zig index afa4f6d803..ca1348d13f 100644 --- a/test/src/Debugger.zig +++ b/test/src/Debugger.zig @@ -411,10 +411,27 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void { }, \\breakpoint set --file enums.zig --source-pattern-regexp '_ = enums;' \\process launch + \\expression --show-types -- Enums \\frame variable --show-types enums \\breakpoint delete --force 1 , &.{ + \\(lldb) expression --show-types -- Enums + \\(type) Enums = struct { + \\ (type) Zero = enum {} + \\ (type) One = enum { + \\ (root.enums.Enums.One) first = .first + \\ } + \\ (type) Two = enum { + \\ (root.enums.Enums.Two) first = .first + \\ (root.enums.Enums.Two) second = .second + \\ } + \\ (type) Three = enum { + \\ (root.enums.Enums.Three) first = .first + \\ (root.enums.Enums.Three) second = .second + \\ (root.enums.Enums.Three) third = .third + \\ } + \\} \\(lldb) frame variable --show-types enums \\(root.enums.Enums) enums = { \\ (root.enums.Enums.Zero) zero = @enumFromInt(13) @@ -434,12 +451,17 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void { .path = "errors.zig", .source = \\const Errors = struct { - \\ one: error{One} = error.One, - \\ two: error{One,Two} = error.Two, - \\ three: error{One,Two,Three} = error.Three, + \\ const Zero = error{}; + \\ const One = Zero || error{One}; + \\ const Two = One || error{Two}; + \\ const Three = Two || error{Three}; + \\ + \\ one: One = error.One, + \\ two: Two = error.Two, + \\ three: Three = error.Three, \\ any: anyerror = error.Any, \\ any_void: anyerror!void = error.NotVoid, - \\ any_u32: error{One}!u32 = 42, + \\ any_u32: One!u32 = 42, \\}; \\fn testErrors(errors: Errors) void { \\ _ = errors; @@ -453,10 +475,27 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void { }, \\breakpoint set --file errors.zig --source-pattern-regexp '_ = errors;' \\process launch + \\expression --show-types -- Errors \\frame variable --show-types errors \\breakpoint delete --force 1 , &.{ + \\(lldb) expression --show-types -- Errors + \\(type) Errors = struct { + \\ (type) Zero = error {} + \\ (type) One = error { + \\ (error{One}) One = error.One + \\ } + \\ (type) Two = error { + \\ (error{One,Two}) One = error.One + \\ (error{One,Two}) Two = error.Two + \\ } + \\ (type) Three = error { + \\ (error{One,Two,Three}) One = error.One + \\ (error{One,Two,Three}) Two = error.Two + \\ (error{One,Two,Three}) Three = error.Three + \\ } + \\} \\(lldb) frame variable --show-types errors \\(root.errors.Errors) errors = { \\ (error{One}) one = error.One @@ -565,10 +604,30 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void { }, \\breakpoint set --file unions.zig --source-pattern-regexp '_ = unions;' \\process launch + \\expression --show-types -- Unions \\frame variable --show-types unions \\breakpoint delete --force 1 , &.{ + \\(lldb) expression --show-types -- Unions + \\(type) Unions = struct { + \\ (type) Untagged = union {} + \\ (type) SafetyTagged = union(enum) { + \\ (@typeInfo(unions.Unions.SafetyTagged).@"union".tag_type.?) void = .void + \\ (@typeInfo(unions.Unions.SafetyTagged).@"union".tag_type.?) en = .en + \\ (@typeInfo(unions.Unions.SafetyTagged).@"union".tag_type.?) eu = .eu + \\ } + \\ (type) Enum = enum { + \\ (root.unions.Unions.Enum) first = .first + \\ (root.unions.Unions.Enum) second = .second + \\ (root.unions.Unions.Enum) third = .third + \\ } + \\ (type) Tagged = union(enum) { + \\ (@typeInfo(unions.Unions.Tagged).@"union".tag_type.?) void = .void + \\ (@typeInfo(unions.Unions.Tagged).@"union".tag_type.?) en = .en + \\ (@typeInfo(unions.Unions.Tagged).@"union".tag_type.?) eu = .eu + \\ } + \\} \\(lldb) frame variable --show-types unions \\(root.unions.Unions) unions = { \\ (root.unions.Unions.Untagged) untagged = {