diff --git a/ci/x86_64-linux-debug.sh b/ci/x86_64-linux-debug.sh index f849e9fca03c..9c53c329e268 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-bfeada333/bin/lldb \ + -Dlldb=$HOME/deps/lldb-zig/Debug-e0a42bb34/bin/lldb \ -fqemu \ -fwasmtime \ -Dstatic-llvm \ diff --git a/ci/x86_64-linux-release.sh b/ci/x86_64-linux-release.sh index 4ab6b4810c7f..f51942250400 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-bfeada333/bin/lldb \ + -Dlldb=$HOME/deps/lldb-zig/Release-e0a42bb34/bin/lldb \ -fqemu \ -fwasmtime \ -Dstatic-llvm \ diff --git a/src/Compilation.zig b/src/Compilation.zig index 4a32b3c45726..fc2e25febf0a 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -348,6 +348,7 @@ const Job = union(enum) { /// Corresponds to the task in `link.Task`. /// Only needed for backends that haven't yet been updated to not race against Sema. codegen_type: InternPool.Index, + update_line_number: InternPool.TrackedInst.Index, /// The `AnalUnit`, which is *not* a `func`, must be semantically analyzed. /// This may be its first time being analyzed, or it may be outdated. /// If the unit is a function, a `codegen_func` job will then be queued. @@ -3718,6 +3719,9 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre .codegen_type => |ty| { comp.dispatchCodegenTask(tid, .{ .codegen_type = ty }); }, + .update_line_number => |ti| { + comp.dispatchCodegenTask(tid, .{ .update_line_number = ti }); + }, .analyze_func => |func| { const named_frame = tracy.namedFrame("analyze_func"); defer named_frame.end(); diff --git a/src/InternPool.zig b/src/InternPool.zig index c34e21a4d345..7264f0b8936f 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -168,6 +168,8 @@ pub const TrackedInst = extern struct { _ => @enumFromInt(@intFromEnum(opt)), }; } + + const debug_state = InternPool.debug_state; }; pub const Unwrapped = struct { @@ -187,6 +189,8 @@ pub const TrackedInst = extern struct { .index = @intFromEnum(tracked_inst_index) & ip.getIndexMask(u32), }; } + + const debug_state = InternPool.debug_state; }; }; @@ -508,7 +512,7 @@ pub const Nav = struct { /// The fully-qualified name of this `Nav`. fqn: NullTerminatedString, /// This field is populated iff this `Nav` is resolved by semantic analysis. - /// If this is `null`, then `status == .resolved` always. + /// If this is `null`, then `status == .fully_resolved` always. analysis: ?struct { namespace: NamespaceIndex, zir_index: TrackedInst.Index, @@ -6631,6 +6635,8 @@ pub fn activate(ip: *const InternPool) void { _ = OptionalString.debug_state; _ = NullTerminatedString.debug_state; _ = OptionalNullTerminatedString.debug_state; + _ = TrackedInst.Index.debug_state; + _ = TrackedInst.Index.Optional.debug_state; _ = Nav.Index.debug_state; _ = Nav.Index.Optional.debug_state; std.debug.assert(debug_state.intern_pool == null); diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index 854e27ae9bba..9619986e6ca8 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -379,6 +379,7 @@ fn cleanupUpdatedFiles(gpa: Allocator, updated_files: *std.AutoArrayHashMapUnman pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { assert(pt.tid == .main); const zcu = pt.zcu; + const comp = zcu.comp; const ip = &zcu.intern_pool; const gpa = zcu.gpa; @@ -435,8 +436,19 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { const old_zir = file.prev_zir.?.*; const new_zir = file.zir; - const old_tag = old_zir.instructions.items(.tag); - const old_data = old_zir.instructions.items(.data); + const old_tag = old_zir.instructions.items(.tag)[@intFromEnum(old_inst)]; + const old_data = old_zir.instructions.items(.data)[@intFromEnum(old_inst)]; + + switch (old_tag) { + .declaration => { + const old_line = old_zir.getDeclaration(old_inst).src_line; + const new_line = new_zir.getDeclaration(new_inst).src_line; + if (old_line != new_line) { + try comp.queueJob(.{ .update_line_number = tracked_inst_index }); + } + }, + else => {}, + } if (old_zir.getAssociatedSrcHash(old_inst)) |old_hash| hash_changed: { if (new_zir.getAssociatedSrcHash(new_inst)) |new_hash| { @@ -455,8 +467,8 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { } // If this is a `struct_decl` etc, we must invalidate any outdated namespace dependencies. - const has_namespace = switch (old_tag[@intFromEnum(old_inst)]) { - .extended => switch (old_data[@intFromEnum(old_inst)].extended.opcode) { + const has_namespace = switch (old_tag) { + .extended => switch (old_data.extended.opcode) { .struct_decl, .union_decl, .opaque_decl, .enum_decl => true, else => false, }, @@ -2517,8 +2529,6 @@ const ScanDeclIter = struct { ); try comp.queueJob(.{ .analyze_comptime_unit = unit }); } - - // TODO: we used to do line number updates here, but this is an inappropriate place for this logic to live. } }; @@ -3152,6 +3162,15 @@ pub fn linkerUpdateContainerType(pt: Zcu.PerThread, ty: InternPool.Index) !void } } +pub fn linkerUpdateLineNumber(pt: Zcu.PerThread, ti: InternPool.TrackedInst.Index) !void { + if (pt.zcu.comp.bin_file) |lf| { + lf.updateLineNumber(pt, ti) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + else => |e| log.err("update line number failed: {s}", .{@errorName(e)}), + }; + } +} + pub fn reportRetryableAstGenError( pt: Zcu.PerThread, src: Zcu.AstGenSrc, diff --git a/src/link.zig b/src/link.zig index 58c5cf35af09..fd1ef7ce334a 100644 --- a/src/link.zig +++ b/src/link.zig @@ -727,16 +727,22 @@ pub const File = struct { } } - pub fn updateNavLineNumber( - base: *File, - pt: Zcu.PerThread, - nav_index: InternPool.Nav.Index, - ) UpdateNavError!void { + /// On an incremental update, fixup the line number of all `Nav`s at the given `TrackedInst`, because + /// its line number has changed. The ZIR instruction `ti_id` has tag `.declaration`. + pub fn updateLineNumber(base: *File, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) UpdateNavError!void { + { + const ti = ti_id.resolveFull(&pt.zcu.intern_pool).?; + const file = pt.zcu.fileByIndex(ti.file); + assert(file.zir_loaded); + const inst = file.zir.instructions.get(@intFromEnum(ti.inst)); + assert(inst.tag == .declaration); + } + switch (base.tag) { .spirv, .nvptx => {}, inline else => |tag| { dev.check(tag.devFeature()); - return @as(*tag.Type(), @fieldParentPtr("base", base)).updateNavineNumber(pt, nav_index); + return @as(*tag.Type(), @fieldParentPtr("base", base)).updateLineNumber(pt, ti_id); }, } } @@ -1407,6 +1413,8 @@ pub const Task = union(enum) { codegen_func: CodegenFunc, codegen_type: InternPool.Index, + update_line_number: InternPool.TrackedInst.Index, + pub const CodegenFunc = struct { /// This will either be a non-generic `func_decl` or a `func_instance`. func: InternPool.Index, @@ -1558,6 +1566,13 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void { error.OutOfMemory => diags.setAllocFailure(), }; }, + .update_line_number => |ti| { + const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid)); + defer pt.deactivate(); + pt.linkerUpdateLineNumber(ti) catch |err| switch (err) { + error.OutOfMemory => diags.setAllocFailure(), + }; + }, } } diff --git a/src/link/C.zig b/src/link/C.zig index d84f29eb4b5b..88b0839b85d2 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -379,12 +379,12 @@ pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) ! gop.value_ptr.fwd_decl = try self.addString(object.dg.fwd_decl.items); } -pub fn updateNavLineNumber(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void { +pub fn updateLineNumber(self: *C, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void { // The C backend does not have the ability to fix line numbers without re-generating // the entire Decl. _ = self; _ = pt; - _ = nav_index; + _ = ti_id; } pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) !void { diff --git a/src/link/Coff.zig b/src/link/Coff.zig index f13863cfb9b1..6ce992404557 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -2484,11 +2484,11 @@ pub fn getGlobalSymbol(coff: *Coff, name: []const u8, lib_name_name: ?[]const u8 return global_index; } -pub fn updateDeclLineNumber(coff: *Coff, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) !void { +pub fn updateLineNumber(coff: *Coff, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void { _ = coff; _ = pt; - _ = decl_index; - log.debug("TODO implement updateDeclLineNumber", .{}); + _ = ti_id; + log.debug("TODO implement updateLineNumber", .{}); } /// TODO: note if we need to rewrite base relocations by dirtying any of the entries in the global table diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 5af6f804107b..2e67cf86d648 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -8,6 +8,7 @@ mods: std.AutoArrayHashMapUnmanaged(*Module, ModInfo), types: std.AutoArrayHashMapUnmanaged(InternPool.Index, Entry.Index), values: std.AutoArrayHashMapUnmanaged(InternPool.Index, Entry.Index), navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, Entry.Index), +decls: std.AutoArrayHashMapUnmanaged(InternPool.TrackedInst.Index, Entry.Index), debug_abbrev: DebugAbbrev, debug_aranges: DebugAranges, @@ -51,9 +52,7 @@ pub const AddressSize = enum(u8) { const ModInfo = struct { root_dir_path: Entry.Index, dirs: std.AutoArrayHashMapUnmanaged(Unit.Index, void), - files: Files, - - const Files = std.AutoArrayHashMapUnmanaged(Zcu.File.Index, void); + files: std.AutoArrayHashMapUnmanaged(Zcu.File.Index, void), fn deinit(mod_info: *ModInfo, gpa: std.mem.Allocator) void { mod_info.dirs.deinit(gpa); @@ -137,6 +136,20 @@ const DebugInfo = struct { return AbbrevCode.decl_bytes + dwarf.sectionOffsetBytes(); } + fn declAbbrevCode(debug_info: *DebugInfo, unit: Unit.Index, entry: Entry.Index) !AbbrevCode { + const dwarf: *Dwarf = @fieldParentPtr("debug_info", debug_info); + const unit_ptr = debug_info.section.getUnit(unit); + const entry_ptr = unit_ptr.getEntry(entry); + if (entry_ptr.len < AbbrevCode.decl_bytes) return .null; + var abbrev_code_buf: [AbbrevCode.decl_bytes]u8 = undefined; + if (try dwarf.getFile().?.preadAll( + &abbrev_code_buf, + debug_info.section.off(dwarf) + unit_ptr.off + unit_ptr.header_len + entry_ptr.off, + ) != abbrev_code_buf.len) return error.InputOutput; + var abbrev_code_fbs = std.io.fixedBufferStream(&abbrev_code_buf); + return @enumFromInt(std.leb.readUleb128(@typeInfo(AbbrevCode).@"enum".tag_type, abbrev_code_fbs.reader()) catch unreachable); + } + const trailer_bytes = 1 + 1; }; @@ -206,8 +219,8 @@ const StringSection = struct { const unit: Unit.Index = @enumFromInt(0); const init: StringSection = .{ - .contents = .{}, - .map = .{}, + .contents = .empty, + .map = .empty, .section = Section.init, }; @@ -219,9 +232,9 @@ const StringSection = struct { fn addString(str_sec: *StringSection, dwarf: *Dwarf, str: []const u8) UpdateError!Entry.Index { const gop = try str_sec.map.getOrPutAdapted(dwarf.gpa, str, Adapter{ .str_sec = str_sec }); - errdefer _ = str_sec.map.pop(); const entry: Entry.Index = @enumFromInt(gop.index); if (!gop.found_existing) { + errdefer _ = str_sec.map.pop(); const unit_ptr = str_sec.section.getUnit(unit); assert(try str_sec.section.getUnit(unit).addEntry(dwarf.gpa) == entry); errdefer _ = unit_ptr.entries.pop(); @@ -284,7 +297,7 @@ pub const Section = struct { .index = std.math.maxInt(u32), .first = .none, .last = .none, - .units = .{}, + .units = .empty, .len = 0, }; @@ -319,13 +332,14 @@ pub const Section = struct { .next = .none, .first = .none, .last = .none, + .free = .none, .header_len = aligned_header_len, .trailer_len = aligned_trailer_len, .off = 0, .len = aligned_header_len + aligned_trailer_len, - .entries = .{}, - .cross_unit_relocs = .{}, - .cross_section_relocs = .{}, + .entries = .empty, + .cross_unit_relocs = .empty, + .cross_section_relocs = .empty, }; if (sec.last.unwrap()) |last_unit| { const last_unit_ptr = sec.getUnit(last_unit); @@ -385,6 +399,28 @@ pub const Section = struct { try unit_ptr.getEntry(entry).replace(unit_ptr, sec, dwarf, contents); } + fn freeEntry(sec: *Section, unit: Unit.Index, entry: Entry.Index, dwarf: *Dwarf) UpdateError!void { + const unit_ptr = sec.getUnit(unit); + const entry_ptr = unit_ptr.getEntry(entry); + if (entry_ptr.len > 0) { + if (entry_ptr.next.unwrap()) |next_entry| unit_ptr.getEntry(next_entry).prev = entry_ptr.prev; + if (entry_ptr.prev.unwrap()) |prev_entry| { + const prev_entry_ptr = unit_ptr.getEntry(prev_entry); + prev_entry_ptr.next = entry_ptr.next; + try prev_entry_ptr.pad(unit_ptr, sec, dwarf); + } else { + unit_ptr.trim(); + sec.trim(dwarf); + } + } else assert(entry_ptr.prev == .none and entry_ptr.next == .none); + entry_ptr.prev = .none; + entry_ptr.next = unit_ptr.free; + entry_ptr.off = 0; + entry_ptr.len = 0; + entry_ptr.clear(); + unit_ptr.free = entry.toOptional(); + } + fn resize(sec: *Section, dwarf: *Dwarf, len: u64) UpdateError!void { if (len <= sec.len) return; if (dwarf.bin_file.cast(.elf)) |elf_file| { @@ -449,6 +485,7 @@ const Unit = struct { next: Index.Optional, first: Entry.Index.Optional, last: Entry.Index.Optional, + free: Entry.Index.Optional, /// offset within containing section off: u32, header_len: u32, @@ -491,6 +528,12 @@ const Unit = struct { } fn addEntry(unit: *Unit, gpa: std.mem.Allocator) std.mem.Allocator.Error!Entry.Index { + if (unit.free.unwrap()) |entry| { + const entry_ptr = unit.getEntry(entry); + unit.free = entry_ptr.next; + entry_ptr.next = .none; + return entry; + } const entry: Entry.Index = @enumFromInt(unit.entries.items.len); const entry_ptr = try unit.entries.addOne(gpa); entry_ptr.* = .{ @@ -498,10 +541,10 @@ const Unit = struct { .next = .none, .off = 0, .len = 0, - .cross_entry_relocs = .{}, - .cross_unit_relocs = .{}, - .cross_section_relocs = .{}, - .external_relocs = .{}, + .cross_entry_relocs = .empty, + .cross_unit_relocs = .empty, + .cross_section_relocs = .empty, + .external_relocs = .empty, }; return entry; } @@ -1583,7 +1626,7 @@ pub const WipNav = struct { const dlw = wip_nav.debug_line.writer(dwarf.gpa); if (dwarf.incremental()) { const new_nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, new_func_info.owner_nav); - errdefer _ = dwarf.navs.pop(); + errdefer _ = if (!new_nav_gop.found_existing) dwarf.navs.pop(); if (!new_nav_gop.found_existing) new_nav_gop.value_ptr.* = try dwarf.addCommonEntry(new_unit); try dlw.writeByte(DW.LNS.extended_op); @@ -1603,10 +1646,8 @@ pub const WipNav = struct { const old_file = zcu.navFileScopeIndex(old_func_info.owner_nav); if (old_file != new_file) { const mod_info = dwarf.getModInfo(wip_nav.unit); - const mod_gop = try mod_info.dirs.getOrPut(dwarf.gpa, new_unit); - errdefer _ = if (!mod_gop.found_existing) mod_info.dirs.pop(); + try mod_info.dirs.put(dwarf.gpa, new_unit, {}); const file_gop = try mod_info.files.getOrPut(dwarf.gpa, new_file); - errdefer _ = if (!file_gop.found_existing) mod_info.files.pop(); try dlw.writeByte(DW.LNS.set_file); try uleb128(dlw, file_gop.index); @@ -1934,6 +1975,90 @@ pub const WipNav = struct { std.math.big.int.Mutable.init(&big_int_space.limbs, field_index).toConst()); } + fn declCommon( + wip_nav: *WipNav, + abbrev_code: struct { + decl: AbbrevCode, + generic_decl: AbbrevCode, + instance: AbbrevCode, + }, + nav: *const InternPool.Nav, + file: Zcu.File.Index, + decl: *const std.zig.Zir.Inst.Declaration.Unwrapped, + ) UpdateError!void { + const zcu = wip_nav.pt.zcu; + const ip = &zcu.intern_pool; + const dwarf = wip_nav.dwarf; + const diw = wip_nav.debug_info.writer(dwarf.gpa); + + const orig_entry = wip_nav.entry; + defer wip_nav.entry = orig_entry; + const parent_type, const is_generic_decl = if (nav.analysis) |analysis| parent_info: { + const parent_type: Type = .fromInterned(zcu.namespacePtr(analysis.namespace).owner_type); + const decl_gop = try dwarf.decls.getOrPut(dwarf.gpa, analysis.zir_index); + errdefer _ = if (!decl_gop.found_existing) dwarf.decls.pop(); + const was_generic_decl = decl_gop.found_existing and + switch (try dwarf.debug_info.declAbbrevCode(wip_nav.unit, decl_gop.value_ptr.*)) { + else => unreachable, + .decl_alias, + .decl_enum, + .decl_empty_enum, + .decl_namespace_struct, + .decl_struct, + .decl_packed_struct, + .decl_union, + .decl_var, + .decl_const, + .decl_const_runtime_bits, + .decl_const_comptime_state, + .decl_const_runtime_bits_comptime_state, + .decl_func, + .decl_empty_func, + .decl_func_generic, + .decl_empty_func_generic, + => false, + .generic_decl_alias, + .generic_decl_enum, + .generic_decl_struct, + .generic_decl_union, + .generic_decl_var, + .generic_decl_const, + .generic_decl_func, + => true, + }; + if (parent_type.getCaptures(zcu).len == 0) { + if (was_generic_decl) try dwarf.freeCommonEntry(wip_nav.unit, decl_gop.value_ptr.*); + decl_gop.value_ptr.* = orig_entry; + break :parent_info .{ parent_type, false }; + } else { + if (was_generic_decl) + dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(decl_gop.value_ptr.*).clear() + else + decl_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit); + wip_nav.entry = decl_gop.value_ptr.*; + break :parent_info .{ parent_type, true }; + } + } else .{ null, false }; + + try wip_nav.abbrevCode(if (is_generic_decl) abbrev_code.generic_decl else abbrev_code.decl); + try wip_nav.refType((if (is_generic_decl) null else parent_type) orelse + .fromInterned(zcu.fileRootType(file))); + assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); + try diw.writeInt(u32, decl.src_line + 1, dwarf.endian); + try uleb128(diw, decl.src_column + 1); + try diw.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); + try wip_nav.strp(nav.name.toSlice(ip)); + + if (!is_generic_decl) return; + const generic_decl_entry = wip_nav.entry; + try dwarf.debug_info.section.replaceEntry(wip_nav.unit, generic_decl_entry, dwarf, wip_nav.debug_info.items); + wip_nav.debug_info.clearRetainingCapacity(); + wip_nav.entry = orig_entry; + try wip_nav.abbrevCode(abbrev_code.instance); + try wip_nav.refType(parent_type.?); + try wip_nav.infoSectionOffset(.debug_info, wip_nav.unit, generic_decl_entry, 0); + } + fn updateLazy(wip_nav: *WipNav, src_loc: Zcu.LazySrcLoc) UpdateError!void { const ip = &wip_nav.pt.zcu.intern_pool; while (wip_nav.pending_lazy.popOrNull()) |val| switch (ip.typeOf(val)) { @@ -1966,10 +2091,11 @@ pub fn init(lf: *link.File, format: DW.Format) Dwarf { }, .endian = target.cpu.arch.endian(), - .mods = .{}, - .types = .{}, - .values = .{}, - .navs = .{}, + .mods = .empty, + .types = .empty, + .values = .empty, + .navs = .empty, + .decls = .empty, .debug_abbrev = .{ .section = Section.init }, .debug_aranges = .{ .section = Section.init }, @@ -2142,6 +2268,7 @@ pub fn deinit(dwarf: *Dwarf) void { dwarf.types.deinit(gpa); dwarf.values.deinit(gpa); dwarf.navs.deinit(gpa); + dwarf.decls.deinit(gpa); dwarf.debug_abbrev.section.deinit(gpa); dwarf.debug_aranges.section.deinit(gpa); dwarf.debug_frame.section.deinit(gpa); @@ -2161,8 +2288,8 @@ fn getUnit(dwarf: *Dwarf, mod: *Module) UpdateError!Unit.Index { errdefer _ = dwarf.mods.pop(); mod_gop.value_ptr.* = .{ .root_dir_path = undefined, - .dirs = .{}, - .files = .{}, + .dirs = .empty, + .files = .empty, }; errdefer mod_gop.value_ptr.dirs.deinit(dwarf.gpa); try mod_gop.value_ptr.dirs.putNoClobber(dwarf.gpa, unit, {}); @@ -2219,14 +2346,28 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In const ip = &zcu.intern_pool; const nav = ip.getNav(nav_index); - log.debug("initWipNav({})", .{nav.fqn.fmt(ip)}); - const inst_info = nav.srcInst(ip).resolveFull(ip).?; const file = zcu.fileByIndex(inst_info.file); + assert(file.zir_loaded); + const decl = file.zir.getDeclaration(inst_info.inst); + log.debug("initWipNav({s}:{d}:{d} %{d} = {})", .{ + file.sub_file_path, + decl.src_line + 1, + decl.src_column + 1, + @intFromEnum(inst_info.inst), + nav.fqn.fmt(ip), + }); + + const nav_val = zcu.navValue(nav_index); + const nav_key = ip.indexToKey(nav_val.toIntern()); + switch (nav_key) { + .@"extern" => return null, + else => {}, + } const unit = try dwarf.getUnit(file.mod); const nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index); - errdefer _ = dwarf.navs.pop(); + errdefer _ = if (!nav_gop.found_existing) dwarf.navs.pop(); if (nav_gop.found_existing) { for ([_]*Section{ &dwarf.debug_aranges.section, @@ -2236,7 +2377,6 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In &dwarf.debug_rnglists.section, }) |sec| sec.getUnit(unit).getEntry(nav_gop.value_ptr.*).clear(); } else nav_gop.value_ptr.* = try dwarf.addCommonEntry(unit); - const nav_val = zcu.navValue(nav_index); var wip_nav: WipNav = .{ .dwarf = dwarf, .pt = pt, @@ -2248,91 +2388,52 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In .func_high_pc = undefined, .blocks = undefined, .cfi = undefined, - .debug_frame = .{}, - .debug_info = .{}, - .debug_line = .{}, - .debug_loclists = .{}, - .pending_lazy = .{}, + .debug_frame = .empty, + .debug_info = .empty, + .debug_line = .empty, + .debug_loclists = .empty, + .pending_lazy = .empty, }; errdefer wip_nav.deinit(); - switch (ip.indexToKey(nav_val.toIntern())) { + switch (nav_key) { else => { - assert(file.zir_loaded); - const decl = file.zir.getDeclaration(inst_info.inst); - - const parent_type, const accessibility: u8 = if (nav.analysis) |a| parent: { - const parent_namespace_ptr = ip.namespacePtr(a.namespace); - break :parent .{ - parent_namespace_ptr.owner_type, - if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private, - }; - } else .{ zcu.fileRootType(inst_info.file), DW.ACCESS.private }; - const diw = wip_nav.debug_info.writer(dwarf.gpa); - try wip_nav.abbrevCode(.decl_var); - try wip_nav.refType(.fromInterned(parent_type)); - assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); - try diw.writeInt(u32, @intCast(decl.src_line + 1), dwarf.endian); - try uleb128(diw, decl.src_column + 1); - try diw.writeByte(accessibility); - try wip_nav.strp(nav.name.toSlice(ip)); + try wip_nav.declCommon(.{ + .decl = .decl_var, + .generic_decl = .generic_decl_var, + .instance = .instance_var, + }, &nav, inst_info.file, &decl); try wip_nav.strp(nav.fqn.toSlice(ip)); - const nav_ty = nav_val.typeOf(zcu); - const nav_ty_reloc_index = try wip_nav.refForward(); - try wip_nav.infoExprloc(.{ .addr = .{ .sym = sym_index } }); - try uleb128(diw, nav.status.fully_resolved.alignment.toByteUnits() orelse - nav_ty.abiAlignment(zcu).toByteUnits().?); - try diw.writeByte(@intFromBool(false)); - wip_nav.finishForward(nav_ty_reloc_index); - try wip_nav.abbrevCode(.is_const); - try wip_nav.refType(nav_ty); - }, - .variable => |variable| { - assert(file.zir_loaded); - const decl = file.zir.getDeclaration(inst_info.inst); - - const parent_type, const accessibility: u8 = if (nav.analysis) |a| parent: { - const parent_namespace_ptr = ip.namespacePtr(a.namespace); - break :parent .{ - parent_namespace_ptr.owner_type, - if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private, - }; - } else .{ zcu.fileRootType(inst_info.file), DW.ACCESS.private }; - - const diw = wip_nav.debug_info.writer(dwarf.gpa); - try wip_nav.abbrevCode(.decl_var); - try wip_nav.refType(.fromInterned(parent_type)); - assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); - try diw.writeInt(u32, @intCast(decl.src_line + 1), dwarf.endian); - try uleb128(diw, decl.src_column + 1); - try diw.writeByte(accessibility); - try wip_nav.strp(nav.name.toSlice(ip)); - try wip_nav.strp(nav.fqn.toSlice(ip)); - const ty: Type = .fromInterned(variable.ty); - try wip_nav.refType(ty); + const ty: Type = nav_val.typeOf(zcu); const addr: Loc = .{ .addr = .{ .sym = sym_index } }; - try wip_nav.infoExprloc(if (variable.is_threadlocal) .{ .form_tls_address = &addr } else addr); - try uleb128(diw, nav.status.fully_resolved.alignment.toByteUnits() orelse - ty.abiAlignment(zcu).toByteUnits().?); - try diw.writeByte(@intFromBool(false)); + const loc: Loc = if (decl.is_threadlocal) .{ .form_tls_address = &addr } else addr; + switch (decl.kind) { + .unnamed_test, .@"test", .decltest, .@"comptime", .@"usingnamespace" => unreachable, + .@"const" => { + const const_ty_reloc_index = try wip_nav.refForward(); + try wip_nav.infoExprloc(loc); + try uleb128(diw, nav.status.fully_resolved.alignment.toByteUnits() orelse + ty.abiAlignment(zcu).toByteUnits().?); + try diw.writeByte(@intFromBool(decl.linkage != .normal)); + wip_nav.finishForward(const_ty_reloc_index); + try wip_nav.abbrevCode(.is_const); + try wip_nav.refType(ty); + }, + .@"var" => { + try wip_nav.refType(ty); + try wip_nav.infoExprloc(loc); + try uleb128(diw, nav.status.fully_resolved.alignment.toByteUnits() orelse + ty.abiAlignment(zcu).toByteUnits().?); + try diw.writeByte(@intFromBool(decl.linkage != .normal)); + }, + } }, .func => |func| { - assert(file.zir_loaded); - const decl = file.zir.getDeclaration(inst_info.inst); - - const parent_type, const accessibility: u8 = if (nav.analysis) |a| parent: { - const parent_namespace_ptr = ip.namespacePtr(a.namespace); - break :parent .{ - parent_namespace_ptr.owner_type, - if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private, - }; - } else .{ zcu.fileRootType(inst_info.file), DW.ACCESS.private }; - const func_type = ip.indexToKey(func.ty).func_type; wip_nav.func = nav_val.toIntern(); wip_nav.func_sym_index = sym_index; - wip_nav.blocks = .{}; + wip_nav.blocks = .empty; if (dwarf.debug_frame.header.format != .none) wip_nav.cfi = .{ .loc = 0, .cfa = dwarf.debug_frame.header.initial_instructions[0].def_cfa, @@ -2375,13 +2476,11 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In } const diw = wip_nav.debug_info.writer(dwarf.gpa); - try wip_nav.abbrevCode(.decl_func); - try wip_nav.refType(.fromInterned(parent_type)); - assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); - try diw.writeInt(u32, @intCast(decl.src_line + 1), dwarf.endian); - try uleb128(diw, decl.src_column + 1); - try diw.writeByte(accessibility); - try wip_nav.strp(nav.name.toSlice(ip)); + try wip_nav.declCommon(.{ + .decl = .decl_func, + .generic_decl = .generic_decl_func, + .instance = .instance_func, + }, &nav, inst_info.file, &decl); try wip_nav.strp(nav.fqn.toSlice(ip)); try wip_nav.refType(.fromInterned(func_type.return_type)); try wip_nav.infoAddrSym(sym_index, 0); @@ -2392,7 +2491,7 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In .none => target_info.defaultFunctionAlignment(target), else => |a| a.maxStrict(target_info.minFunctionAlignment(target)), }.toByteUnits().?); - try diw.writeByte(@intFromBool(false)); + try diw.writeByte(@intFromBool(decl.linkage != .normal)); try diw.writeByte(@intFromBool(func_type.return_type == .noreturn_type)); const dlw = wip_nav.debug_line.writer(dwarf.gpa); @@ -2435,97 +2534,110 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In return wip_nav; } -pub fn finishWipNav( +pub fn finishWipNavFunc( dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, - sym: struct { index: u32, addr: u64, size: u64 }, + code_size: u64, wip_nav: *WipNav, ) UpdateError!void { const zcu = pt.zcu; const ip = &zcu.intern_pool; const nav = ip.getNav(nav_index); - log.debug("finishWipNav({})", .{nav.fqn.fmt(ip)}); + assert(wip_nav.func != .none); + log.debug("finishWipNavFunc({})", .{nav.fqn.fmt(ip)}); - if (wip_nav.func != .none) { - { - const external_relocs = &dwarf.debug_aranges.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs; - try external_relocs.append(dwarf.gpa, .{ .target_sym = sym.index }); - var entry: [8 + 8]u8 = undefined; - @memset(entry[0..@intFromEnum(dwarf.address_size)], 0); - dwarf.writeInt(entry[@intFromEnum(dwarf.address_size)..][0..@intFromEnum(dwarf.address_size)], sym.size); - try dwarf.debug_aranges.section.replaceEntry( - wip_nav.unit, - wip_nav.entry, - dwarf, - entry[0 .. @intFromEnum(dwarf.address_size) * 2], - ); - } - switch (dwarf.debug_frame.header.format) { - .none => {}, - .debug_frame, .eh_frame => |format| { - try wip_nav.debug_frame.appendNTimes( - dwarf.gpa, - DW.CFA.nop, - @intCast(dwarf.debug_frame.section.alignment.forward(wip_nav.debug_frame.items.len) - wip_nav.debug_frame.items.len), - ); - const contents = wip_nav.debug_frame.items; - try dwarf.debug_frame.section.resizeEntry(wip_nav.unit, wip_nav.entry, dwarf, @intCast(contents.len)); - const unit = dwarf.debug_frame.section.getUnit(wip_nav.unit); - const entry = unit.getEntry(wip_nav.entry); - const unit_len = (if (entry.next.unwrap()) |next_entry| - unit.getEntry(next_entry).off - entry.off - else - entry.len) - dwarf.unitLengthBytes(); - dwarf.writeInt(contents[dwarf.unitLengthBytes() - dwarf.sectionOffsetBytes() ..][0..dwarf.sectionOffsetBytes()], unit_len); - switch (format) { - .none => unreachable, - .debug_frame => dwarf.writeInt(contents[dwarf.unitLengthBytes() + dwarf.sectionOffsetBytes() + - @intFromEnum(dwarf.address_size) ..][0..@intFromEnum(dwarf.address_size)], sym.size), - .eh_frame => { - std.mem.writeInt( - u32, - contents[dwarf.unitLengthBytes()..][0..4], - unit.header_len + entry.off + dwarf.unitLengthBytes(), - dwarf.endian, - ); - std.mem.writeInt(u32, contents[dwarf.unitLengthBytes() + 4 + 4 ..][0..4], @intCast(sym.size), dwarf.endian); - }, - } - try entry.replace(unit, &dwarf.debug_frame.section, dwarf, contents); - }, - } - { - std.mem.writeInt(u32, wip_nav.debug_info.items[wip_nav.func_high_pc..][0..4], @intCast(sym.size), dwarf.endian); - if (wip_nav.any_children) { - const diw = wip_nav.debug_info.writer(dwarf.gpa); - try uleb128(diw, @intFromEnum(AbbrevCode.null)); - } else std.leb.writeUnsignedFixed( - AbbrevCode.decl_bytes, - wip_nav.debug_info.items[0..AbbrevCode.decl_bytes], - try dwarf.refAbbrevCode(.decl_empty_func), + { + const external_relocs = &dwarf.debug_aranges.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs; + try external_relocs.append(dwarf.gpa, .{ .target_sym = wip_nav.func_sym_index }); + var entry: [8 + 8]u8 = undefined; + @memset(entry[0..@intFromEnum(dwarf.address_size)], 0); + dwarf.writeInt(entry[@intFromEnum(dwarf.address_size)..][0..@intFromEnum(dwarf.address_size)], code_size); + try dwarf.debug_aranges.section.replaceEntry( + wip_nav.unit, + wip_nav.entry, + dwarf, + entry[0 .. @intFromEnum(dwarf.address_size) * 2], + ); + } + switch (dwarf.debug_frame.header.format) { + .none => {}, + .debug_frame, .eh_frame => |format| { + try wip_nav.debug_frame.appendNTimes( + dwarf.gpa, + DW.CFA.nop, + @intCast(dwarf.debug_frame.section.alignment.forward(wip_nav.debug_frame.items.len) - wip_nav.debug_frame.items.len), ); - } - { - try dwarf.debug_rnglists.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs.appendSlice(dwarf.gpa, &.{ - .{ - .source_off = 1, - .target_sym = sym.index, - }, - .{ - .source_off = 1 + @intFromEnum(dwarf.address_size), - .target_sym = sym.index, - .target_off = sym.size, + const contents = wip_nav.debug_frame.items; + try dwarf.debug_frame.section.resizeEntry(wip_nav.unit, wip_nav.entry, dwarf, @intCast(contents.len)); + const unit = dwarf.debug_frame.section.getUnit(wip_nav.unit); + const entry = unit.getEntry(wip_nav.entry); + const unit_len = (if (entry.next.unwrap()) |next_entry| + unit.getEntry(next_entry).off - entry.off + else + entry.len) - dwarf.unitLengthBytes(); + dwarf.writeInt(contents[dwarf.unitLengthBytes() - dwarf.sectionOffsetBytes() ..][0..dwarf.sectionOffsetBytes()], unit_len); + switch (format) { + .none => unreachable, + .debug_frame => dwarf.writeInt(contents[dwarf.unitLengthBytes() + dwarf.sectionOffsetBytes() + + @intFromEnum(dwarf.address_size) ..][0..@intFromEnum(dwarf.address_size)], code_size), + .eh_frame => { + std.mem.writeInt( + u32, + contents[dwarf.unitLengthBytes()..][0..4], + unit.header_len + entry.off + dwarf.unitLengthBytes(), + dwarf.endian, + ); + std.mem.writeInt(u32, contents[dwarf.unitLengthBytes() + 4 + 4 ..][0..4], @intCast(code_size), dwarf.endian); }, - }); - try dwarf.debug_rnglists.section.replaceEntry( - wip_nav.unit, - wip_nav.entry, - dwarf, - ([1]u8{DW.RLE.start_end} ++ [1]u8{0} ** (8 + 8))[0 .. 1 + @intFromEnum(dwarf.address_size) + @intFromEnum(dwarf.address_size)], - ); - } + } + try entry.replace(unit, &dwarf.debug_frame.section, dwarf, contents); + }, + } + { + std.mem.writeInt(u32, wip_nav.debug_info.items[wip_nav.func_high_pc..][0..4], @intCast(code_size), dwarf.endian); + if (wip_nav.any_children) { + const diw = wip_nav.debug_info.writer(dwarf.gpa); + try uleb128(diw, @intFromEnum(AbbrevCode.null)); + } else std.leb.writeUnsignedFixed( + AbbrevCode.decl_bytes, + wip_nav.debug_info.items[0..AbbrevCode.decl_bytes], + try dwarf.refAbbrevCode(.decl_empty_func), + ); } + { + try dwarf.debug_rnglists.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs.appendSlice(dwarf.gpa, &.{ + .{ + .source_off = 1, + .target_sym = wip_nav.func_sym_index, + }, + .{ + .source_off = 1 + @intFromEnum(dwarf.address_size), + .target_sym = wip_nav.func_sym_index, + .target_off = code_size, + }, + }); + try dwarf.debug_rnglists.section.replaceEntry( + wip_nav.unit, + wip_nav.entry, + dwarf, + ([1]u8{DW.RLE.start_end} ++ [1]u8{0} ** (8 + 8))[0 .. 1 + @intFromEnum(dwarf.address_size) + @intFromEnum(dwarf.address_size)], + ); + } + + try dwarf.finishWipNav(pt, nav_index, wip_nav); +} + +pub fn finishWipNav( + dwarf: *Dwarf, + pt: Zcu.PerThread, + nav_index: InternPool.Nav.Index, + wip_nav: *WipNav, +) UpdateError!void { + const zcu = pt.zcu; + const ip = &zcu.intern_pool; + const nav = ip.getNav(nav_index); + log.debug("finishWipNav({})", .{nav.fqn.fmt(ip)}); try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items); if (wip_nav.debug_line.items.len > 0) { @@ -2547,12 +2659,17 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool const nav_val = zcu.navValue(nav_index); const nav = ip.getNav(nav_index); - log.debug("updateComptimeNav({})", .{nav.fqn.fmt(ip)}); - const inst_info = nav.srcInst(ip).resolveFull(ip).?; const file = zcu.fileByIndex(inst_info.file); assert(file.zir_loaded); const decl = file.zir.getDeclaration(inst_info.inst); + log.debug("updateComptimeNav({s}:{d}:{d} %{d} = {})", .{ + file.sub_file_path, + decl.src_line + 1, + decl.src_column + 1, + @intFromEnum(inst_info.inst), + nav.fqn.fmt(ip), + }); const is_test = switch (decl.kind) { .unnamed_test, .@"test", .decltest => true, @@ -2563,14 +2680,6 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool return; } - const parent_type, const accessibility: u8 = if (nav.analysis) |a| parent: { - const parent_namespace_ptr = ip.namespacePtr(a.namespace); - break :parent .{ - parent_namespace_ptr.owner_type, - if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private, - }; - } else .{ zcu.fileRootType(inst_info.file), DW.ACCESS.private }; - var wip_nav: WipNav = .{ .dwarf = dwarf, .pt = pt, @@ -2582,16 +2691,16 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool .func_high_pc = undefined, .blocks = undefined, .cfi = undefined, - .debug_frame = .{}, - .debug_info = .{}, - .debug_line = .{}, - .debug_loclists = .{}, - .pending_lazy = .{}, + .debug_frame = .empty, + .debug_info = .empty, + .debug_line = .empty, + .debug_loclists = .empty, + .pending_lazy = .empty, }; defer wip_nav.deinit(); const nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index); - errdefer _ = dwarf.navs.pop(); + errdefer _ = if (!nav_gop.found_existing) dwarf.navs.pop(); const tag: enum { done, decl_alias, decl_var, decl_const } = switch (ip.indexToKey(nav_val.toIntern())) { .int_type, @@ -2609,9 +2718,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool => .decl_alias, .struct_type => tag: { const loaded_struct = ip.loadStructType(nav_val.toIntern()); - - const type_inst_info = loaded_struct.zir_index.resolveFull(ip).?; - if (type_inst_info.file != inst_info.file) break :tag .decl_alias; + if (loaded_struct.zir_index.resolveFile(ip) != inst_info.file) break :tag .decl_alias; const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern()); if (type_gop.found_existing) { @@ -2630,13 +2737,15 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool 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(.fromInterned(parent_type)); - assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); - try diw.writeInt(u32, @intCast(decl.src_line + 1), dwarf.endian); - try uleb128(diw, decl.src_column + 1); - try diw.writeByte(accessibility); - try wip_nav.strp(nav.name.toSlice(ip)); + try wip_nav.declCommon(if (loaded_struct.field_types.len == 0) .{ + .decl = .decl_namespace_struct, + .generic_decl = .generic_decl_struct, + .instance = .instance_namespace_struct, + } else .{ + .decl = .decl_struct, + .generic_decl = .generic_decl_struct, + .instance = .instance_struct, + }, &nav, inst_info.file, &decl); 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().?); @@ -2688,13 +2797,11 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool } }, .@"packed" => { - try wip_nav.abbrevCode(.decl_packed_struct); - try wip_nav.refType(.fromInterned(parent_type)); - assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); - try diw.writeInt(u32, @intCast(decl.src_line + 1), dwarf.endian); - try uleb128(diw, decl.src_column + 1); - try diw.writeByte(accessibility); - try wip_nav.strp(nav.name.toSlice(ip)); + try wip_nav.declCommon(.{ + .decl = .decl_packed_struct, + .generic_decl = .generic_decl_struct, + .instance = .instance_packed_struct, + }, &nav, inst_info.file, &decl); try wip_nav.refType(.fromInterned(loaded_struct.backingIntTypeUnordered(ip))); var field_bit_offset: u16 = 0; for (0..loaded_struct.field_types.len) |field_index| { @@ -2712,10 +2819,8 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool }, .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 type_zir_index = loaded_enum.zir_index.unwrap() orelse break :tag .decl_alias; + if (type_zir_index.resolveFile(ip) != inst_info.file) break :tag .decl_alias; const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern()); if (type_gop.found_existing) { @@ -2730,13 +2835,15 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool } 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(.fromInterned(parent_type)); - assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); - try diw.writeInt(u32, @intCast(decl.src_line + 1), dwarf.endian); - try uleb128(diw, decl.src_column + 1); - try diw.writeByte(accessibility); - try wip_nav.strp(nav.name.toSlice(ip)); + try wip_nav.declCommon(if (loaded_enum.names.len > 0) .{ + .decl = .decl_enum, + .generic_decl = .generic_decl_enum, + .instance = .instance_enum, + } else .{ + .decl = .decl_empty_enum, + .generic_decl = .generic_decl_enum, + .instance = .instance_empty_enum, + }, &nav, inst_info.file, &decl); try wip_nav.refType(.fromInterned(loaded_enum.tag_ty)); for (0..loaded_enum.names.len) |field_index| { try wip_nav.enumConstValue(loaded_enum, .{ @@ -2751,9 +2858,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool }, .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; + if (loaded_union.zir_index.resolveFile(ip) != inst_info.file) break :tag .decl_alias; const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern()); if (type_gop.found_existing) { @@ -2768,13 +2873,11 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool } 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(.fromInterned(parent_type)); - assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); - try diw.writeInt(u32, @intCast(decl.src_line + 1), dwarf.endian); - try uleb128(diw, decl.src_column + 1); - try diw.writeByte(accessibility); - try wip_nav.strp(nav.name.toSlice(ip)); + try wip_nav.declCommon(.{ + .decl = .decl_union, + .generic_decl = .generic_decl_union, + .instance = .instance_union, + }, &nav, inst_info.file, &decl); const union_layout = Type.getUnionLayout(loaded_union, zcu); try uleb128(diw, union_layout.abi_size); try uleb128(diw, union_layout.abi_align.toByteUnits().?); @@ -2825,9 +2928,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool }, .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; + if (loaded_opaque.zir_index.resolveFile(ip) != inst_info.file) break :tag .decl_alias; const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern()); if (type_gop.found_existing) { @@ -2842,19 +2943,16 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool } 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(.fromInterned(parent_type)); - assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); - try diw.writeInt(u32, @intCast(decl.src_line + 1), dwarf.endian); - try uleb128(diw, decl.src_column + 1); - try diw.writeByte(accessibility); - try wip_nav.strp(nav.name.toSlice(ip)); - try diw.writeByte(@intFromBool(false)); + try wip_nav.declCommon(.{ + .decl = .decl_namespace_struct, + .generic_decl = .generic_decl_struct, + .instance = .instance_namespace_struct, + }, &nav, inst_info.file, &decl); + try diw.writeByte(@intFromBool(true)); break :tag .done; }, .undef, .simple_value, - .@"extern", .int, .err, .error_union, @@ -2869,42 +2967,31 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool .un, => .decl_const, .variable => .decl_var, + .@"extern" => unreachable, .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.*); - if (entry_ptr.len >= AbbrevCode.decl_bytes) { - var abbrev_code_buf: [AbbrevCode.decl_bytes]u8 = undefined; - if (try dwarf.getFile().?.preadAll( - &abbrev_code_buf, - dwarf.debug_info.section.off(dwarf) + unit_ptr.off + unit_ptr.header_len + entry_ptr.off, - ) != abbrev_code_buf.len) return error.InputOutput; - var abbrev_code_fbs = std.io.fixedBufferStream(&abbrev_code_buf); - const abbrev_code: AbbrevCode = @enumFromInt( - std.leb.readUleb128(@typeInfo(AbbrevCode).@"enum".tag_type, abbrev_code_fbs.reader()) catch unreachable, - ); - switch (abbrev_code) { - else => unreachable, - .decl_func, .decl_empty_func => return, - .decl_func_generic, .decl_empty_func_generic => {}, - } - } - entry_ptr.clear(); + if (nav_gop.found_existing) switch (try dwarf.debug_info.declAbbrevCode(wip_nav.unit, nav_gop.value_ptr.*)) { + .null => {}, + else => unreachable, + .decl_func, .decl_empty_func, .instance_func, .instance_empty_func => return, + .decl_func_generic, + .decl_empty_func_generic, + .instance_func_generic, + .instance_empty_func_generic, + => 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 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) - .decl_func_generic - else - .decl_empty_func_generic); - try wip_nav.refType(.fromInterned(parent_type)); - assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); - try diw.writeInt(u32, @intCast(decl.src_line + 1), dwarf.endian); - try uleb128(diw, decl.src_column + 1); - try diw.writeByte(accessibility); - try wip_nav.strp(nav.name.toSlice(ip)); + try wip_nav.declCommon(if (func_type.param_types.len > 0 or func_type.is_var_args) .{ + .decl = .decl_func_generic, + .generic_decl = .generic_decl_func, + .instance = .instance_func_generic, + } else .{ + .decl = .decl_empty_func_generic, + .generic_decl = .generic_decl_func, + .instance = .instance_empty_func_generic, + }, &nav, inst_info.file, &decl); try wip_nav.refType(.fromInterned(func_type.return_type)); if (func_type.param_types.len > 0 or func_type.is_var_args) { for (0..func_type.param_types.len) |param_index| { @@ -2929,57 +3016,55 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool switch (tag) { .done => {}, .decl_alias => { - const diw = wip_nav.debug_info.writer(dwarf.gpa); - try wip_nav.abbrevCode(.decl_alias); - try wip_nav.refType(.fromInterned(parent_type)); - assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); - try diw.writeInt(u32, @intCast(decl.src_line + 1), dwarf.endian); - try uleb128(diw, decl.src_column + 1); - try diw.writeByte(accessibility); - try wip_nav.strp(nav.name.toSlice(ip)); + try wip_nav.declCommon(.{ + .decl = .decl_alias, + .generic_decl = .generic_decl_alias, + .instance = .instance_alias, + }, &nav, inst_info.file, &decl); try wip_nav.refType(nav_val.toType()); }, .decl_var => { const diw = wip_nav.debug_info.writer(dwarf.gpa); - try wip_nav.abbrevCode(.decl_var); - try wip_nav.refType(.fromInterned(parent_type)); - assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); - try diw.writeInt(u32, @intCast(decl.src_line + 1), dwarf.endian); - try uleb128(diw, decl.src_column + 1); - try diw.writeByte(accessibility); - try wip_nav.strp(nav.name.toSlice(ip)); + try wip_nav.declCommon(.{ + .decl = .decl_var, + .generic_decl = .generic_decl_var, + .instance = .instance_var, + }, &nav, inst_info.file, &decl); try wip_nav.strp(nav.fqn.toSlice(ip)); const nav_ty = nav_val.typeOf(zcu); try wip_nav.refType(nav_ty); try wip_nav.blockValue(nav_src_loc, nav_val); try uleb128(diw, nav.status.fully_resolved.alignment.toByteUnits() orelse nav_ty.abiAlignment(zcu).toByteUnits().?); - try diw.writeByte(@intFromBool(false)); + try diw.writeByte(@intFromBool(decl.linkage != .normal)); }, .decl_const => { const diw = wip_nav.debug_info.writer(dwarf.gpa); const nav_ty = nav_val.typeOf(zcu); const has_runtime_bits = nav_ty.hasRuntimeBits(zcu); const has_comptime_state = nav_ty.comptimeOnly(zcu) and try nav_ty.onePossibleValue(pt) == null; - try wip_nav.abbrevCode(if (has_runtime_bits and has_comptime_state) - .decl_const_runtime_bits_comptime_state - else if (has_comptime_state) - .decl_const_comptime_state - else if (has_runtime_bits) - .decl_const_runtime_bits - else - .decl_const); - try wip_nav.refType(.fromInterned(parent_type)); - assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); - try diw.writeInt(u32, @intCast(decl.src_line + 1), dwarf.endian); - try uleb128(diw, decl.src_column + 1); - try diw.writeByte(accessibility); - try wip_nav.strp(nav.name.toSlice(ip)); + try wip_nav.declCommon(if (has_runtime_bits and has_comptime_state) .{ + .decl = .decl_const_runtime_bits_comptime_state, + .generic_decl = .generic_decl_const, + .instance = .instance_const_runtime_bits_comptime_state, + } else if (has_comptime_state) .{ + .decl = .decl_const_comptime_state, + .generic_decl = .generic_decl_const, + .instance = .instance_const_comptime_state, + } else if (has_runtime_bits) .{ + .decl = .decl_const_runtime_bits, + .generic_decl = .generic_decl_const, + .instance = .instance_const_runtime_bits, + } else .{ + .decl = .decl_const, + .generic_decl = .generic_decl_const, + .instance = .instance_const, + }, &nav, inst_info.file, &decl); try wip_nav.strp(nav.fqn.toSlice(ip)); const nav_ty_reloc_index = try wip_nav.refForward(); try uleb128(diw, nav.status.fully_resolved.alignment.toByteUnits() orelse nav_ty.abiAlignment(zcu).toByteUnits().?); - try diw.writeByte(@intFromBool(false)); + try diw.writeByte(@intFromBool(decl.linkage != .normal)); if (has_runtime_bits) try wip_nav.blockValue(nav_src_loc, nav_val); if (has_comptime_state) try wip_nav.refValue(nav_val); wip_nav.finishForward(nav_ty_reloc_index); @@ -3017,15 +3102,15 @@ fn updateLazyType( .func_high_pc = undefined, .blocks = undefined, .cfi = undefined, - .debug_frame = .{}, - .debug_info = .{}, - .debug_line = .{}, - .debug_loclists = .{}, + .debug_frame = .empty, + .debug_info = .empty, + .debug_line = .empty, + .debug_loclists = .empty, .pending_lazy = pending_lazy.*, }; defer { pending_lazy.* = wip_nav.pending_lazy; - wip_nav.pending_lazy = .{}; + wip_nav.pending_lazy = .empty; wip_nav.deinit(); } const diw = wip_nav.debug_info.writer(dwarf.gpa); @@ -3076,7 +3161,7 @@ fn updateLazyType( } }, .Slice => { - try wip_nav.abbrevCode(.struct_type); + try wip_nav.abbrevCode(.generated_struct_type); try wip_nav.strp(name); try uleb128(diw, ty.abiSize(zcu)); try uleb128(diw, ty.abiAlignment(zcu).toByteUnits().?); @@ -3115,7 +3200,7 @@ fn updateLazyType( }, .opt_type => |opt_child_type_index| { const opt_child_type: Type = .fromInterned(opt_child_type_index); - try wip_nav.abbrevCode(.union_type); + try wip_nav.abbrevCode(.generated_union_type); try wip_nav.strp(name); try uleb128(diw, ty.abiSize(zcu)); try uleb128(diw, ty.abiAlignment(zcu).toByteUnits().?); @@ -3199,7 +3284,7 @@ fn updateLazyType( }, }; - try wip_nav.abbrevCode(.union_type); + try wip_nav.abbrevCode(.generated_union_type); try wip_nav.strp(name); if (error_union_type.error_set_type != .generic_poison_type and error_union_type.payload_type != .generic_poison_type) @@ -3308,11 +3393,11 @@ fn updateLazyType( .opaque_type, => unreachable, .tuple_type => |tuple_type| if (tuple_type.types.len == 0) { - try wip_nav.abbrevCode(.namespace_struct_type); + try wip_nav.abbrevCode(.generated_empty_struct_type); try wip_nav.strp(name); try diw.writeByte(@intFromBool(false)); } else { - try wip_nav.abbrevCode(.struct_type); + try wip_nav.abbrevCode(.generated_struct_type); try wip_nav.strp(name); try uleb128(diw, ty.abiSize(zcu)); try uleb128(diw, ty.abiAlignment(zcu).toByteUnits().?); @@ -3357,7 +3442,7 @@ fn updateLazyType( }, .enum_type => { const loaded_enum = ip.loadEnumType(type_index); - try wip_nav.abbrevCode(if (loaded_enum.names.len > 0) .enum_type else .empty_enum_type); + try wip_nav.abbrevCode(if (loaded_enum.names.len > 0) .generated_enum_type else .generated_empty_enum_type); try wip_nav.strp(name); try wip_nav.refType(.fromInterned(loaded_enum.tag_ty)); for (0..loaded_enum.names.len) |field_index| { @@ -3449,7 +3534,7 @@ fn updateLazyType( if (!is_nullary) try uleb128(diw, @intFromEnum(AbbrevCode.null)); }, .error_set_type => |error_set_type| { - try wip_nav.abbrevCode(if (error_set_type.names.len > 0) .enum_type else .empty_enum_type); + try wip_nav.abbrevCode(if (error_set_type.names.len > 0) .generated_enum_type else .generated_empty_enum_type); try wip_nav.strp(name); try wip_nav.refType(.fromInterned(try pt.intern(.{ .int_type = .{ .signedness = .unsigned, @@ -3518,15 +3603,15 @@ fn updateLazyValue( .func_high_pc = undefined, .blocks = undefined, .cfi = undefined, - .debug_frame = .{}, - .debug_info = .{}, - .debug_line = .{}, - .debug_loclists = .{}, + .debug_frame = .empty, + .debug_info = .empty, + .debug_line = .empty, + .debug_loclists = .empty, .pending_lazy = pending_lazy.*, }; defer { pending_lazy.* = wip_nav.pending_lazy; - wip_nav.pending_lazy = .{}; + wip_nav.pending_lazy = .empty; wip_nav.deinit(); } const diw = wip_nav.debug_info.writer(dwarf.gpa); @@ -3870,12 +3955,13 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP const ip = &zcu.intern_pool; const ty: Type = .fromInterned(type_index); const ty_src_loc = ty.srcLoc(zcu); - log.debug("updateContainerType({}({d}))", .{ ty.fmt(pt), @intFromEnum(type_index) }); + log.debug("updateContainerType({})", .{ty.fmt(pt)}); const inst_info = ty.typeDeclInst(zcu).?.resolveFull(ip).?; const file = zcu.fileByIndex(inst_info.file); + const unit = try dwarf.getUnit(file.mod); + const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, inst_info.file); if (inst_info.inst == .main_struct_inst) { - const unit = try dwarf.getUnit(file.mod); const type_gop = try dwarf.types.getOrPut(dwarf.gpa, type_index); if (!type_gop.found_existing) type_gop.value_ptr.* = try dwarf.addCommonEntry(unit); var wip_nav: WipNav = .{ @@ -3889,19 +3975,18 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP .func_high_pc = undefined, .blocks = undefined, .cfi = undefined, - .debug_frame = .{}, - .debug_info = .{}, - .debug_line = .{}, - .debug_loclists = .{}, - .pending_lazy = .{}, + .debug_frame = .empty, + .debug_info = .empty, + .debug_line = .empty, + .debug_loclists = .empty, + .pending_lazy = .empty, }; defer wip_nav.deinit(); const loaded_struct = ip.loadStructType(type_index); const diw = wip_nav.debug_info.writer(dwarf.gpa); - try wip_nav.abbrevCode(if (loaded_struct.field_types.len == 0) .namespace_file else .file); - const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, inst_info.file); + try wip_nav.abbrevCode(if (loaded_struct.field_types.len == 0) .empty_file else .file); try uleb128(diw, file_gop.index); try wip_nav.strp(loaded_struct.name.toSlice(ip)); if (loaded_struct.field_types.len > 0) { @@ -3978,7 +4063,6 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP if (name_strat == .parent) return; } - const unit = try dwarf.getUnit(file.mod); const type_gop = try dwarf.types.getOrPut(dwarf.gpa, type_index); if (!type_gop.found_existing) type_gop.value_ptr.* = try dwarf.addCommonEntry(unit); var wip_nav: WipNav = .{ @@ -3992,11 +4076,11 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP .func_high_pc = undefined, .blocks = undefined, .cfi = undefined, - .debug_frame = .{}, - .debug_info = .{}, - .debug_line = .{}, - .debug_loclists = .{}, - .pending_lazy = .{}, + .debug_frame = .empty, + .debug_info = .empty, + .debug_line = .empty, + .debug_loclists = .empty, + .pending_lazy = .empty, }; defer wip_nav.deinit(); const diw = wip_nav.debug_info.writer(dwarf.gpa); @@ -4008,7 +4092,8 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP const loaded_struct = ip.loadStructType(type_index); switch (loaded_struct.layout) { .auto, .@"extern" => { - try wip_nav.abbrevCode(if (loaded_struct.field_types.len == 0) .namespace_struct_type else .struct_type); + try wip_nav.abbrevCode(if (loaded_struct.field_types.len == 0) .empty_struct_type else .struct_type); + try uleb128(diw, file_gop.index); try wip_nav.strp(name); if (loaded_struct.field_types.len == 0) try diw.writeByte(@intFromBool(false)) else { try uleb128(diw, ty.abiSize(zcu)); @@ -4062,6 +4147,7 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP }, .@"packed" => { try wip_nav.abbrevCode(if (loaded_struct.field_types.len > 0) .packed_struct_type else .empty_packed_struct_type); + try uleb128(diw, file_gop.index); try wip_nav.strp(name); try wip_nav.refType(.fromInterned(loaded_struct.backingIntTypeUnordered(ip))); var field_bit_offset: u16 = 0; @@ -4080,6 +4166,7 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP .enum_type => { const loaded_enum = ip.loadEnumType(type_index); try wip_nav.abbrevCode(if (loaded_enum.names.len > 0) .enum_type else .empty_enum_type); + try uleb128(diw, file_gop.index); try wip_nav.strp(name); try wip_nav.refType(.fromInterned(loaded_enum.tag_ty)); for (0..loaded_enum.names.len) |field_index| { @@ -4095,6 +4182,7 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP .union_type => { const loaded_union = ip.loadUnionType(type_index); try wip_nav.abbrevCode(if (loaded_union.field_types.len > 0) .union_type else .empty_union_type); + try uleb128(diw, file_gop.index); try wip_nav.strp(name); const union_layout = Type.getUnionLayout(loaded_union, zcu); try uleb128(diw, union_layout.abi_size); @@ -4144,7 +4232,8 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP if (loaded_union.field_types.len > 0) try uleb128(diw, @intFromEnum(AbbrevCode.null)); }, .opaque_type => { - try wip_nav.abbrevCode(.namespace_struct_type); + try wip_nav.abbrevCode(.empty_struct_type); + try uleb128(diw, file_gop.index); try wip_nav.strp(name); try diw.writeByte(@intFromBool(true)); }, @@ -4156,21 +4245,28 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP } } -pub fn updateNavLineNumber(dwarf: *Dwarf, zcu: *Zcu, nav_index: InternPool.Nav.Index) UpdateError!void { +pub fn updateLineNumber(dwarf: *Dwarf, zcu: *Zcu, zir_index: InternPool.TrackedInst.Index) UpdateError!void { const ip = &zcu.intern_pool; - const zir_index = ip.getCau(ip.getNav(nav_index).analysis_owner.unwrap() orelse return).zir_index; const inst_info = zir_index.resolveFull(ip).?; assert(inst_info.inst != .main_struct_inst); const file = zcu.fileByIndex(inst_info.file); + assert(file.zir_loaded); + const decl = file.zir.getDeclaration(inst_info.inst); + log.debug("updateLineNumber({s}:{d}:{d} %{d} = {s})", .{ + file.sub_file_path, + decl.src_line + 1, + decl.src_column + 1, + @intFromEnum(inst_info.inst), + file.zir.nullTerminatedString(decl.name), + }); - const line = file.zir.getDeclaration(inst_info.inst).src_line; var line_buf: [4]u8 = undefined; - std.mem.writeInt(u32, &line_buf, line, dwarf.endian); + std.mem.writeInt(u32, &line_buf, decl.src_line + 1, dwarf.endian); - const unit = dwarf.debug_line.section.getUnit(dwarf.mods.get(file.mod).?); - const entry = unit.getEntry(dwarf.navs.get(nav_index).?); - try dwarf.getFile().?.pwriteAll(&line, dwarf.debug_line.section.off + unit.off + unit.header_len + entry.off + DebugInfo.declEntryLineOff(dwarf)); + const unit = dwarf.debug_info.section.getUnit(dwarf.getUnitIfExists(file.mod) orelse return); + const entry = unit.getEntry(dwarf.decls.get(zir_index) orelse return); + try dwarf.getFile().?.pwriteAll(&line_buf, dwarf.debug_info.section.off(dwarf) + unit.off + unit.header_len + entry.off + DebugInfo.declEntryLineOff(dwarf)); } pub fn freeNav(dwarf: *Dwarf, nav_index: InternPool.Nav.Index) void { @@ -4213,16 +4309,16 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { .func_high_pc = undefined, .blocks = undefined, .cfi = undefined, - .debug_frame = .{}, - .debug_info = .{}, - .debug_line = .{}, - .debug_loclists = .{}, - .pending_lazy = .{}, + .debug_frame = .empty, + .debug_info = .empty, + .debug_line = .empty, + .debug_loclists = .empty, + .pending_lazy = .empty, }; defer wip_nav.deinit(); const diw = wip_nav.debug_info.writer(dwarf.gpa); const global_error_set_names = ip.global_error_set.getNamesFromMainThread(); - try wip_nav.abbrevCode(if (global_error_set_names.len > 0) .enum_type else .empty_enum_type); + try wip_nav.abbrevCode(if (global_error_set_names.len > 0) .generated_enum_type else .generated_empty_enum_type); try wip_nav.strp("anyerror"); try wip_nav.refType(.fromInterned(try pt.intern(.{ .int_type = .{ .signedness = .unsigned, @@ -4611,7 +4707,7 @@ const AbbrevCode = enum { // padding codes must be one byte uleb128 values to function pad_1, pad_n, - // decl codes are assumed to all have the same uleb128 length + // (generic) decl codes are assumed to all have the same uleb128 length decl_alias, decl_enum, decl_empty_enum, @@ -4628,11 +4724,34 @@ const AbbrevCode = enum { decl_empty_func, decl_func_generic, decl_empty_func_generic, + generic_decl_alias, + generic_decl_enum, + generic_decl_struct, + generic_decl_union, + generic_decl_var, + generic_decl_const, + generic_decl_func, // the rest are unrestricted + instance_alias, + instance_enum, + instance_empty_enum, + instance_namespace_struct, + instance_struct, + instance_packed_struct, + instance_union, + instance_var, + instance_const, + instance_const_runtime_bits, + instance_const_comptime_state, + instance_const_runtime_bits_comptime_state, + instance_func, + instance_empty_func, + instance_func_generic, + instance_empty_func_generic, compile_unit, module, - namespace_file, file, + empty_file, signed_enum_field, unsigned_enum_field, big_enum_field, @@ -4665,10 +4784,15 @@ const AbbrevCode = enum { func_type, func_type_param, is_var_args, + generated_enum_type, + generated_empty_enum_type, + generated_struct_type, + generated_empty_struct_type, + generated_union_type, enum_type, empty_enum_type, - namespace_struct_type, struct_type, + empty_struct_type, packed_struct_type, empty_packed_struct_type, union_type, @@ -4694,7 +4818,7 @@ const AbbrevCode = enum { comptime_value_elem_runtime_bits, comptime_value_elem_comptime_state, - const decl_bytes = uleb128Bytes(@intFromEnum(AbbrevCode.decl_empty_func_generic)); + const decl_bytes = uleb128Bytes(@intFromEnum(AbbrevCode.generic_decl_func)); const Attr = struct { DeclValEnum(DW.AT), @@ -4707,6 +4831,10 @@ const AbbrevCode = enum { .{ .accessibility, .data1 }, .{ .name, .strp }, }; + const instance_abbrev_common_attrs = &[_]Attr{ + .{ .ZIG_parent, .ref_addr }, + .{ .abstract_origin, .ref_addr }, + }; const abbrevs = std.EnumArray(AbbrevCode, struct { tag: DeclValEnum(DW.TAG), children: bool = false, @@ -4857,6 +4985,184 @@ const AbbrevCode = enum { .{ .type, .ref_addr }, }, }, + .generic_decl_alias = .{ + .tag = .imported_declaration, + .attrs = decl_abbrev_common_attrs ++ .{ + .{ .declaration, .flag_present }, + }, + }, + .generic_decl_enum = .{ + .tag = .enumeration_type, + .attrs = decl_abbrev_common_attrs ++ .{ + .{ .declaration, .flag_present }, + }, + }, + .generic_decl_struct = .{ + .tag = .structure_type, + .attrs = decl_abbrev_common_attrs ++ .{ + .{ .declaration, .flag_present }, + }, + }, + .generic_decl_union = .{ + .tag = .union_type, + .attrs = decl_abbrev_common_attrs ++ .{ + .{ .declaration, .flag_present }, + }, + }, + .generic_decl_var = .{ + .tag = .variable, + .attrs = decl_abbrev_common_attrs ++ .{ + .{ .declaration, .flag_present }, + }, + }, + .generic_decl_const = .{ + .tag = .constant, + .attrs = decl_abbrev_common_attrs ++ .{ + .{ .declaration, .flag_present }, + }, + }, + .generic_decl_func = .{ + .tag = .subprogram, + .attrs = decl_abbrev_common_attrs ++ .{ + .{ .declaration, .flag_present }, + }, + }, + .instance_alias = .{ + .tag = .imported_declaration, + .attrs = instance_abbrev_common_attrs ++ .{ + .{ .import, .ref_addr }, + }, + }, + .instance_enum = .{ + .tag = .enumeration_type, + .children = true, + .attrs = instance_abbrev_common_attrs ++ .{ + .{ .type, .ref_addr }, + }, + }, + .instance_empty_enum = .{ + .tag = .enumeration_type, + .attrs = instance_abbrev_common_attrs ++ .{ + .{ .type, .ref_addr }, + }, + }, + .instance_namespace_struct = .{ + .tag = .structure_type, + .attrs = instance_abbrev_common_attrs ++ .{ + .{ .declaration, .flag }, + }, + }, + .instance_struct = .{ + .tag = .structure_type, + .children = true, + .attrs = instance_abbrev_common_attrs ++ .{ + .{ .byte_size, .udata }, + .{ .alignment, .udata }, + }, + }, + .instance_packed_struct = .{ + .tag = .structure_type, + .children = true, + .attrs = instance_abbrev_common_attrs ++ .{ + .{ .type, .ref_addr }, + }, + }, + .instance_union = .{ + .tag = .union_type, + .children = true, + .attrs = instance_abbrev_common_attrs ++ .{ + .{ .byte_size, .udata }, + .{ .alignment, .udata }, + }, + }, + .instance_var = .{ + .tag = .variable, + .attrs = instance_abbrev_common_attrs ++ .{ + .{ .linkage_name, .strp }, + .{ .type, .ref_addr }, + .{ .location, .exprloc }, + .{ .alignment, .udata }, + .{ .external, .flag }, + }, + }, + .instance_const = .{ + .tag = .constant, + .attrs = instance_abbrev_common_attrs ++ .{ + .{ .linkage_name, .strp }, + .{ .type, .ref_addr }, + .{ .alignment, .udata }, + .{ .external, .flag }, + }, + }, + .instance_const_runtime_bits = .{ + .tag = .constant, + .attrs = instance_abbrev_common_attrs ++ .{ + .{ .linkage_name, .strp }, + .{ .type, .ref_addr }, + .{ .alignment, .udata }, + .{ .external, .flag }, + .{ .const_value, .block }, + }, + }, + .instance_const_comptime_state = .{ + .tag = .constant, + .attrs = instance_abbrev_common_attrs ++ .{ + .{ .linkage_name, .strp }, + .{ .type, .ref_addr }, + .{ .alignment, .udata }, + .{ .external, .flag }, + .{ .ZIG_comptime_value, .ref_addr }, + }, + }, + .instance_const_runtime_bits_comptime_state = .{ + .tag = .constant, + .attrs = instance_abbrev_common_attrs ++ .{ + .{ .linkage_name, .strp }, + .{ .type, .ref_addr }, + .{ .alignment, .udata }, + .{ .external, .flag }, + .{ .const_value, .block }, + .{ .ZIG_comptime_value, .ref_addr }, + }, + }, + .instance_func = .{ + .tag = .subprogram, + .children = true, + .attrs = instance_abbrev_common_attrs ++ .{ + .{ .linkage_name, .strp }, + .{ .type, .ref_addr }, + .{ .low_pc, .addr }, + .{ .high_pc, .data4 }, + .{ .alignment, .udata }, + .{ .external, .flag }, + .{ .noreturn, .flag }, + }, + }, + .instance_empty_func = .{ + .tag = .subprogram, + .attrs = instance_abbrev_common_attrs ++ .{ + .{ .linkage_name, .strp }, + .{ .type, .ref_addr }, + .{ .low_pc, .addr }, + .{ .high_pc, .data4 }, + .{ .alignment, .udata }, + .{ .external, .flag }, + .{ .noreturn, .flag }, + }, + }, + .instance_func_generic = .{ + .tag = .subprogram, + .children = true, + .attrs = instance_abbrev_common_attrs ++ .{ + .{ .type, .ref_addr }, + }, + }, + .instance_empty_func_generic = .{ + .tag = .subprogram, + .attrs = instance_abbrev_common_attrs ++ .{ + .{ .type, .ref_addr }, + }, + }, .compile_unit = .{ .tag = .compile_unit, .children = true, @@ -4879,21 +5185,21 @@ const AbbrevCode = enum { .{ .ranges, .rnglistx }, }, }, - .namespace_file = .{ + .file = .{ .tag = .structure_type, + .children = true, .attrs = &.{ .{ .decl_file, .udata }, .{ .name, .strp }, + .{ .byte_size, .udata }, + .{ .alignment, .udata }, }, }, - .file = .{ + .empty_file = .{ .tag = .structure_type, - .children = true, .attrs = &.{ .{ .decl_file, .udata }, .{ .name, .strp }, - .{ .byte_size, .udata }, - .{ .alignment, .udata }, }, }, .signed_enum_field = .{ @@ -5143,7 +5449,7 @@ const AbbrevCode = enum { .is_var_args = .{ .tag = .unspecified_parameters, }, - .enum_type = .{ + .generated_enum_type = .{ .tag = .enumeration_type, .children = true, .attrs = &.{ @@ -5151,33 +5457,78 @@ const AbbrevCode = enum { .{ .type, .ref_addr }, }, }, - .empty_enum_type = .{ + .generated_empty_enum_type = .{ .tag = .enumeration_type, .attrs = &.{ .{ .name, .strp }, .{ .type, .ref_addr }, }, }, - .namespace_struct_type = .{ + .generated_struct_type = .{ + .tag = .structure_type, + .children = true, + .attrs = &.{ + .{ .name, .strp }, + .{ .byte_size, .udata }, + .{ .alignment, .udata }, + }, + }, + .generated_empty_struct_type = .{ .tag = .structure_type, .attrs = &.{ .{ .name, .strp }, .{ .declaration, .flag }, }, }, + .generated_union_type = .{ + .tag = .union_type, + .children = true, + .attrs = &.{ + .{ .name, .strp }, + .{ .byte_size, .udata }, + .{ .alignment, .udata }, + }, + }, + .enum_type = .{ + .tag = .enumeration_type, + .children = true, + .attrs = &.{ + .{ .decl_file, .udata }, + .{ .name, .strp }, + .{ .type, .ref_addr }, + }, + }, + .empty_enum_type = .{ + .tag = .enumeration_type, + .attrs = &.{ + .{ .decl_file, .udata }, + .{ .name, .strp }, + .{ .type, .ref_addr }, + }, + }, .struct_type = .{ .tag = .structure_type, .children = true, .attrs = &.{ + .{ .decl_file, .udata }, .{ .name, .strp }, .{ .byte_size, .udata }, .{ .alignment, .udata }, }, }, + .empty_struct_type = .{ + .tag = .structure_type, + .attrs = &.{ + .{ .decl_file, .udata }, + .{ .name, .strp }, + .{ .declaration, .flag }, + }, + }, .packed_struct_type = .{ .tag = .structure_type, .children = true, .attrs = &.{ + .{ .decl_file, .udata }, .{ .name, .strp }, .{ .type, .ref_addr }, }, @@ -5185,6 +5536,7 @@ const AbbrevCode = enum { .empty_packed_struct_type = .{ .tag = .structure_type, .attrs = &.{ + .{ .decl_file, .udata }, .{ .name, .strp }, .{ .type, .ref_addr }, }, @@ -5193,6 +5545,7 @@ const AbbrevCode = enum { .tag = .union_type, .children = true, .attrs = &.{ + .{ .decl_file, .udata }, .{ .name, .strp }, .{ .byte_size, .udata }, .{ .alignment, .udata }, @@ -5201,6 +5554,7 @@ const AbbrevCode = enum { .empty_union_type = .{ .tag = .union_type, .attrs = &.{ + .{ .decl_file, .udata }, .{ .name, .strp }, .{ .byte_size, .udata }, .{ .alignment, .udata }, @@ -5373,6 +5727,15 @@ fn addCommonEntry(dwarf: *Dwarf, unit: Unit.Index) UpdateError!Entry.Index { return entry; } +fn freeCommonEntry(dwarf: *Dwarf, unit: Unit.Index, entry: Entry.Index) UpdateError!void { + try dwarf.debug_aranges.section.freeEntry(unit, entry, dwarf); + try dwarf.debug_frame.section.freeEntry(unit, entry, dwarf); + try dwarf.debug_info.section.freeEntry(unit, entry, dwarf); + try dwarf.debug_line.section.freeEntry(unit, entry, dwarf); + try dwarf.debug_loclists.section.freeEntry(unit, entry, dwarf); + try dwarf.debug_rnglists.section.freeEntry(unit, entry, dwarf); +} + fn writeInt(dwarf: *Dwarf, buf: []u8, int: u64) void { switch (buf.len) { inline 0...8 => |len| std.mem.writeInt(@Type(.{ .int = .{ diff --git a/src/link/Elf.zig b/src/link/Elf.zig index ca7a46c4bb85..4e6bab756cff 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -2372,9 +2372,9 @@ pub fn updateExports( return self.zigObjectPtr().?.updateExports(self, pt, exported, export_indices); } -pub fn updateNavLineNumber(self: *Elf, pt: Zcu.PerThread, nav: InternPool.Nav.Index) !void { +pub fn updateLineNumber(self: *Elf, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void { if (self.llvm_object) |_| return; - return self.zigObjectPtr().?.updateNavLineNumber(pt, nav); + return self.zigObjectPtr().?.updateLineNumber(pt, ti_id); } pub fn deleteExport( diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index 5a2a7a8009b7..73ea6288643c 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -1463,19 +1463,7 @@ pub fn updateFunc( break :blk .{ atom_ptr.value, atom_ptr.alignment }; }; - if (debug_wip_nav) |*wip_nav| { - const sym = self.symbol(sym_index); - try self.dwarf.?.finishWipNav( - pt, - func.owner_nav, - .{ - .index = sym_index, - .addr = @intCast(sym.address(.{}, elf_file)), - .size = self.atom(sym.ref.index).?.size, - }, - wip_nav, - ); - } + if (debug_wip_nav) |*wip_nav| try self.dwarf.?.finishWipNavFunc(pt, func.owner_nav, code.len, wip_nav); // Exports will be updated by `Zcu.processExports` after the update. @@ -1546,13 +1534,21 @@ pub fn updateNav( .func => .none, .variable => |variable| variable.init, .@"extern" => |@"extern"| { - if (ip.isFunctionType(@"extern".ty)) return; const sym_index = try self.getGlobalSymbol( elf_file, nav.name.toSlice(ip), @"extern".lib_name.toSlice(ip), ); - self.symbol(sym_index).flags.is_extern_ptr = true; + if (!ip.isFunctionType(@"extern".ty)) { + const sym = self.symbol(sym_index); + sym.flags.is_extern_ptr = true; + if (@"extern".is_threadlocal) sym.flags.is_tls = true; + } + if (self.dwarf) |*dwarf| dwarf: { + var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, sym_index) orelse break :dwarf; + defer debug_wip_nav.deinit(); + try dwarf.finishWipNav(pt, nav_index, &debug_wip_nav); + } return; }, else => nav.status.fully_resolved.val, @@ -1596,19 +1592,7 @@ pub fn updateNav( else try self.updateNavCode(elf_file, pt, nav_index, sym_index, shndx, code, elf.STT_OBJECT); - if (debug_wip_nav) |*wip_nav| { - const sym = self.symbol(sym_index); - try self.dwarf.?.finishWipNav( - pt, - nav_index, - .{ - .index = sym_index, - .addr = @intCast(sym.address(.{}, elf_file)), - .size = sym.atom(elf_file).?.size, - }, - wip_nav, - ); - } + if (debug_wip_nav) |*wip_nav| try self.dwarf.?.finishWipNav(pt, nav_index, wip_nav); } else if (self.dwarf) |*dwarf| try dwarf.updateComptimeNav(pt, nav_index); // Exports will be updated by `Zcu.processExports` after the update. @@ -1863,22 +1847,9 @@ pub fn updateExports( } } -/// Must be called only after a successful call to `updateNav`. -pub fn updateNavLineNumber( - self: *ZigObject, - pt: Zcu.PerThread, - nav_index: InternPool.Nav.Index, -) !void { - const tracy = trace(@src()); - defer tracy.end(); - - const ip = &pt.zcu.intern_pool; - const nav = ip.getNav(nav_index); - - log.debug("updateNavLineNumber {}({d})", .{ nav.fqn.fmt(ip), nav_index }); - +pub fn updateLineNumber(self: *ZigObject, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void { if (self.dwarf) |*dwarf| { - try dwarf.updateNavLineNumber(pt.zcu, nav_index); + try dwarf.updateLineNumber(pt.zcu, ti_id); } } diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 8bec62420b95..3a3710aed88b 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -3014,9 +3014,9 @@ pub fn updateNav(self: *MachO, pt: Zcu.PerThread, nav: InternPool.Nav.Index) !vo return self.getZigObject().?.updateNav(self, pt, nav); } -pub fn updateNavLineNumber(self: *MachO, pt: Zcu.PerThread, nav: InternPool.NavIndex) !void { +pub fn updateLineNumber(self: *MachO, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void { if (self.llvm_object) |_| return; - return self.getZigObject().?.updateNavLineNumber(pt, nav); + return self.getZigObject().?.updateLineNumber(pt, ti_id); } pub fn updateExports( diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig index 511cb6839de7..fb5a1255caf1 100644 --- a/src/link/MachO/ZigObject.zig +++ b/src/link/MachO/ZigObject.zig @@ -780,8 +780,8 @@ pub fn updateFunc( var code_buffer = std.ArrayList(u8).init(gpa); defer code_buffer.deinit(); - var dwarf_wip_nav = if (self.dwarf) |*dwarf| try dwarf.initWipNav(pt, func.owner_nav, sym_index) else null; - defer if (dwarf_wip_nav) |*wip_nav| wip_nav.deinit(); + var debug_wip_nav = if (self.dwarf) |*dwarf| try dwarf.initWipNav(pt, func.owner_nav, sym_index) else null; + defer if (debug_wip_nav) |*wip_nav| wip_nav.deinit(); const res = try codegen.generateFunction( &macho_file.base, @@ -791,7 +791,7 @@ pub fn updateFunc( air, liveness, &code_buffer, - if (dwarf_wip_nav) |*wip_nav| .{ .dwarf = wip_nav } else .none, + if (debug_wip_nav) |*wip_nav| .{ .dwarf = wip_nav } else .none, ); const code = switch (res) { @@ -813,19 +813,7 @@ pub fn updateFunc( break :blk .{ atom.value, atom.alignment }; }; - if (dwarf_wip_nav) |*wip_nav| { - const sym = self.symbols.items[sym_index]; - try self.dwarf.?.finishWipNav( - pt, - func.owner_nav, - .{ - .index = sym_index, - .addr = sym.getAddress(.{}, macho_file), - .size = sym.getAtom(macho_file).?.size, - }, - wip_nav, - ); - } + if (debug_wip_nav) |*wip_nav| try self.dwarf.?.finishWipNavFunc(pt, func.owner_nav, code.len, wip_nav); // Exports will be updated by `Zcu.processExports` after the update. if (old_rva != new_rva and old_rva > 0) { @@ -883,13 +871,20 @@ pub fn updateNav( .func => .none, .variable => |variable| variable.init, .@"extern" => |@"extern"| { - if (ip.isFunctionType(@"extern".ty)) return; // Extern variable gets a __got entry only const name = @"extern".name.toSlice(ip); const lib_name = @"extern".lib_name.toSlice(ip); - const index = try self.getGlobalSymbol(macho_file, name, lib_name); - const sym = &self.symbols.items[index]; - sym.flags.is_extern_ptr = true; + const sym_index = try self.getGlobalSymbol(macho_file, name, lib_name); + if (!ip.isFunctionType(@"extern".ty)) { + const sym = &self.symbols.items[sym_index]; + sym.flags.is_extern_ptr = true; + if (@"extern".is_threadlocal) sym.flags.tlv = true; + } + if (self.dwarf) |*dwarf| dwarf: { + var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, sym_index) orelse break :dwarf; + defer debug_wip_nav.deinit(); + try dwarf.finishWipNav(pt, nav_index, &debug_wip_nav); + } return; }, else => nav.status.fully_resolved.val, @@ -927,19 +922,7 @@ pub fn updateNav( else try self.updateNavCode(macho_file, pt, nav_index, sym_index, sect_index, code); - if (debug_wip_nav) |*wip_nav| { - const sym = self.symbols.items[sym_index]; - try self.dwarf.?.finishWipNav( - pt, - nav_index, - .{ - .index = sym_index, - .addr = sym.getAddress(.{}, macho_file), - .size = sym.getAtom(macho_file).?.size, - }, - wip_nav, - ); - } + if (debug_wip_nav) |*wip_nav| try self.dwarf.?.finishWipNav(pt, nav_index, wip_nav); } else if (self.dwarf) |*dwarf| try dwarf.updateComptimeNav(pt, nav_index); // Exports will be updated by `Zcu.processExports` after the update. @@ -1432,14 +1415,9 @@ fn updateLazySymbol( try macho_file.base.file.?.pwriteAll(code, file_offset); } -/// Must be called only after a successful call to `updateNav`. -pub fn updateNavLineNumber( - self: *ZigObject, - pt: Zcu.PerThread, - nav_index: InternPool.Nav.Index, -) !void { +pub fn updateLineNumber(self: *ZigObject, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void { if (self.dwarf) |*dwarf| { - try dwarf.updateNavLineNumber(pt.zcu, nav_index); + try dwarf.updateLineNumber(pt.zcu, ti_id); } } diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig index 8e27e20ec775..31aac2486ef7 100644 --- a/src/link/Plan9.zig +++ b/src/link/Plan9.zig @@ -1354,11 +1354,10 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { } } -/// Must be called only after a successful call to `updateDecl`. -pub fn updateDeclLineNumber(self: *Plan9, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) !void { +pub fn updateLineNumber(self: *Plan9, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void { _ = self; _ = pt; - _ = decl_index; + _ = ti_id; } pub fn getNavVAddr( diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 7d00aa5a64ff..ec13a75f2c5f 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -1574,9 +1574,9 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav: InternPool.Nav.Index) !voi try wasm.zig_object.?.updateNav(wasm, pt, nav); } -pub fn updateNavLineNumber(wasm: *Wasm, pt: Zcu.PerThread, nav: InternPool.Nav.Index) !void { +pub fn updateLineNumber(wasm: *Wasm, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void { if (wasm.llvm_object) |_| return; - try wasm.zig_object.?.updateNavLineNumber(pt, nav); + try wasm.zig_object.?.updateLineNumber(pt, ti_id); } /// From a given symbol location, returns its `wasm.GlobalType`. diff --git a/src/link/Wasm/ZigObject.zig b/src/link/Wasm/ZigObject.zig index 09d764773018..f2bce777ed70 100644 --- a/src/link/Wasm/ZigObject.zig +++ b/src/link/Wasm/ZigObject.zig @@ -1074,15 +1074,9 @@ pub fn createDebugSectionForIndex(zig_object: *ZigObject, wasm: *Wasm, index: *? return atom_index; } -pub fn updateDeclLineNumber( - zig_object: *ZigObject, - pt: Zcu.PerThread, - decl_index: InternPool.DeclIndex, -) !void { +pub fn updateLineNumber(zig_object: *ZigObject, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void { if (zig_object.dwarf) |*dw| { - const decl = pt.zcu.declPtr(decl_index); - log.debug("updateDeclLineNumber {}{*}", .{ decl.fqn.fmt(&pt.zcu.intern_pool), decl }); - try dw.updateDeclLineNumber(pt.zcu, decl_index); + try dw.updateLineNumber(pt.zcu, ti_id); } } diff --git a/test/incremental/change_generic_line_number b/test/incremental/change_generic_line_number new file mode 100644 index 000000000000..e59723306dcb --- /dev/null +++ b/test/incremental/change_generic_line_number @@ -0,0 +1,32 @@ +#target=x86_64-linux-selfhosted +#update=initial version +#file=main.zig +const std = @import("std"); +fn Printer(message: []const u8) type { + return struct { + fn print() !void { + try std.io.getStdOut().writeAll(message); + } + }; +} +pub fn main() !void { + try Printer("foo\n").print(); + try Printer("bar\n").print(); +} +#expect_stdout="foo\nbar\n" +#update=change line number +#file=main.zig +const std = @import("std"); + +fn Printer(message: []const u8) type { + return struct { + fn print() !void { + try std.io.getStdOut().writeAll(message); + } + }; +} +pub fn main() !void { + try Printer("foo\n").print(); + try Printer("bar\n").print(); +} +#expect_stdout="foo\nbar\n" diff --git a/test/incremental/change_line_number b/test/incremental/change_line_number new file mode 100644 index 000000000000..c272bcb5dfa5 --- /dev/null +++ b/test/incremental/change_line_number @@ -0,0 +1,16 @@ +#target=x86_64-linux-selfhosted +#update=initial version +#file=main.zig +const std = @import("std"); +pub fn main() !void { + try std.io.getStdOut().writeAll("foo\n"); +} +#expect_stdout="foo\n" +#update=change line number +#file=main.zig +const std = @import("std"); + +pub fn main() !void { + try std.io.getStdOut().writeAll("foo\n"); +} +#expect_stdout="foo\n" diff --git a/tools/incr-check.zig b/tools/incr-check.zig index b5329f134e43..144e05ccc417 100644 --- a/tools/incr-check.zig +++ b/tools/incr-check.zig @@ -2,7 +2,7 @@ const std = @import("std"); const Allocator = std.mem.Allocator; const Cache = std.Build.Cache; -const usage = "usage: incr-check [--zig-lib-dir lib] [--debug-zcu] [--debug-link] [--preserve-tmp] [--zig-cc-binary /path/to/zig]"; +const usage = "usage: incr-check [--zig-lib-dir lib] [--debug-zcu] [--debug-dwarf] [--debug-link] [--preserve-tmp] [--zig-cc-binary /path/to/zig]"; pub fn main() !void { const fatal = std.process.fatal; @@ -16,6 +16,7 @@ pub fn main() !void { var opt_lib_dir: ?[]const u8 = null; var opt_cc_zig: ?[]const u8 = null; var debug_zcu = false; + var debug_dwarf = false; var debug_link = false; var preserve_tmp = false; @@ -27,6 +28,8 @@ pub fn main() !void { opt_lib_dir = arg_it.next() orelse fatal("expected arg after '--zig-lib-dir'\n{s}", .{usage}); } else if (std.mem.eql(u8, arg, "--debug-zcu")) { debug_zcu = true; + } else if (std.mem.eql(u8, arg, "--debug-dwarf")) { + debug_dwarf = true; } else if (std.mem.eql(u8, arg, "--debug-link")) { debug_link = true; } else if (std.mem.eql(u8, arg, "--preserve-tmp")) { @@ -85,7 +88,7 @@ pub fn main() !void { const host = try std.zig.system.resolveTargetQuery(.{}); - const debug_log_verbose = debug_zcu or debug_link; + const debug_log_verbose = debug_zcu or debug_dwarf or debug_link; for (case.targets) |target| { const target_prog_node = node: { @@ -125,6 +128,9 @@ pub fn main() !void { if (debug_zcu) { try child_args.appendSlice(arena, &.{ "--debug-log", "zcu" }); } + if (debug_dwarf) { + try child_args.appendSlice(arena, &.{ "--debug-log", "dwarf" }); + } if (debug_link) { try child_args.appendSlice(arena, &.{ "--debug-log", "link", "--debug-log", "link_state", "--debug-log", "link_relocs" }); } diff --git a/tools/lldb_pretty_printers.py b/tools/lldb_pretty_printers.py index b862cf0ab99e..fd7e9fa08a36 100644 --- a/tools/lldb_pretty_printers.py +++ b/tools/lldb_pretty_printers.py @@ -25,7 +25,7 @@ def create_struct(parent, name, struct_type, inits): case lldb.eByteOrderBig: byte_order = 'big' field_bytes = field_init.to_bytes(field_size, byte_order, signed=field.type.GetTypeFlags() & lldb.eTypeIsSigned != 0) - elif isinstance(field_init_type, lldb.SBValue): + elif isinstance(field_init, lldb.SBValue): field_bytes = field_init.data.uint8 else: return match struct_data.byte_order: @@ -731,7 +731,7 @@ def root_InternPool_Index_SummaryProvider(value, _=None): if not unwrapped: return '' # .none tag = unwrapped.GetChildMemberWithName('tag') tag_value = tag.value - summary = tag.CreateValueFromType(tag.type).GetChildMemberWithName('encodings').GetChildMemberWithName(tag_value.removeprefix('.')).GetChildMemberWithName('summary') + summary = tag.CreateValueFromType(tag.type).GetChildMemberWithName('encodings').GetChildMemberWithName(tag_value.removeprefix('.').removeprefix('@"').removesuffix('"').replace(r'\"', '"')).GetChildMemberWithName('summary') if not summary: return tag_value return re.sub( expr_path_re, @@ -767,7 +767,7 @@ def update(self): shared = ip.GetChildMemberWithName('locals').GetSyntheticValue().child[self.value.GetChildMemberWithName('tid').unsigned].GetChildMemberWithName('shared') item = shared.GetChildMemberWithName('items').GetChildMemberWithName('view').child[index.unsigned] self.tag, item_data = item.GetChildMemberWithName('tag'), item.GetChildMemberWithName('data') - encoding = self.tag.CreateValueFromType(self.tag.type).GetChildMemberWithName('encodings').GetChildMemberWithName(self.tag.value.removeprefix('.')) + encoding = self.tag.CreateValueFromType(self.tag.type).GetChildMemberWithName('encodings').GetChildMemberWithName(self.tag.value.removeprefix('.').removeprefix('@"').removesuffix('"').replace(r'\"', '"')) encoding_index, encoding_data, encoding_payload, encoding_trailing, encoding_config = encoding.GetChildMemberWithName('index'), encoding.GetChildMemberWithName('data'), encoding.GetChildMemberWithName('payload'), encoding.GetChildMemberWithName('trailing'), encoding.GetChildMemberWithName('config') if encoding_index: index_type = encoding_index.GetValueAsType() @@ -869,6 +869,7 @@ def get_child_at_index(self, index): def root_InternPool_String_SummaryProvider(value, _=None): wrapped = value.unsigned + if wrapped == (1 << 32) - 1: return '' ip = value.CreateValueFromType(value.type).GetChildMemberWithName('debug_state').GetChildMemberWithName('intern_pool').GetNonSyntheticValue().GetChildMemberWithName('?') tid_shift_32 = ip.GetChildMemberWithName('tid_shift_32').unsigned locals_value = ip.GetChildMemberWithName('locals').GetSyntheticValue() @@ -880,24 +881,24 @@ def root_InternPool_String_SummaryProvider(value, _=None): string.format = lldb.eFormatCString return string.value -class root_InternPool_Cau_Index_SynthProvider: +class root_InternPool_TrackedInst_Index_SynthProvider: def __init__(self, value, _=None): self.value = value def update(self): - self.cau = None + self.tracked_inst = None wrapped = self.value.unsigned if wrapped == (1 << 32) - 1: return ip = self.value.CreateValueFromType(self.value.type).GetChildMemberWithName('debug_state').GetChildMemberWithName('intern_pool').GetNonSyntheticValue().GetChildMemberWithName('?') - tid_shift_31 = ip.GetChildMemberWithName('tid_shift_31').unsigned + tid_shift_32 = ip.GetChildMemberWithName('tid_shift_32').unsigned locals_value = ip.GetChildMemberWithName('locals').GetSyntheticValue() - local_value = locals_value.child[wrapped >> tid_shift_31] + local_value = locals_value.child[wrapped >> tid_shift_32] if local_value is None: wrapped = 0 local_value = locals_value.child[0] - self.cau = local_value.GetChildMemberWithName('shared').GetChildMemberWithName('caus').GetChildMemberWithName('view').GetChildMemberWithName('0').child[wrapped & (1 << tid_shift_31) - 1] - def has_children(self): return self.cau.GetNumChildren(1) > 0 - def num_children(self): return self.cau.GetNumChildren() - def get_child_index(self, name): return self.cau.GetIndexOfChildWithName(name) - def get_child_at_index(self, index): return self.cau.GetChildAtIndex(index) + self.tracked_inst = local_value.GetChildMemberWithName('shared').GetChildMemberWithName('tracked_insts').GetChildMemberWithName('view').GetChildMemberWithName('0').child[wrapped & (1 << tid_shift_32) - 1] + def has_children(self): return False if self.tracked_inst is None else self.tracked_inst.GetNumChildren(1) > 0 + def num_children(self): return 0 if self.tracked_inst is None else self.tracked_inst.GetNumChildren() + def get_child_index(self, name): return -1 if self.tracked_inst is None else self.tracked_inst.GetIndexOfChildWithName(name) + def get_child_at_index(self, index): return None if self.tracked_inst is None else self.tracked_inst.GetChildAtIndex(index) class root_InternPool_Nav_Index_SynthProvider: def __init__(self, value, _=None): self.value = value @@ -913,10 +914,10 @@ def update(self): wrapped = 0 local_value = locals_value.child[0] self.nav = local_value.GetChildMemberWithName('shared').GetChildMemberWithName('navs').GetChildMemberWithName('view').child[wrapped & (1 << tid_shift_32) - 1] - def has_children(self): return self.nav.GetNumChildren(1) > 0 - def num_children(self): return self.nav.GetNumChildren() - def get_child_index(self, name): return self.nav.GetIndexOfChildWithName(name) - def get_child_at_index(self, index): return self.nav.GetChildAtIndex(index) + def has_children(self): return False if self.nav is None else self.nav.GetNumChildren(1) > 0 + def num_children(self): return 0 if self.nav is None else self.nav.GetNumChildren() + def get_child_index(self, name): return -1 if self.nav is None else self.nav.GetIndexOfChildWithName(name) + def get_child_at_index(self, index): return None if self.nav is None else self.nav.GetChildAtIndex(index) # Initialize @@ -973,5 +974,5 @@ def __lldb_init_module(debugger, _=None): add(debugger, category='zig', type='root.InternPool.Index', synth=True, summary=True) add(debugger, category='zig', type='root.InternPool.Index.Unwrapped', synth=True) add(debugger, category='zig', regex=True, type=r'^root\.InternPool\.(Optional)?(NullTerminated)?String$', identifier='root_InternPool_String', summary=True) - add(debugger, category='zig', regex=True, type=r'^root\.InternPool\.Cau\.Index(\.Optional)?$', identifier='root_InternPool_Cau_Index', synth=True) + add(debugger, category='zig', regex=True, type=r'^root\.InternPool\.TrackedInst\.Index(\.Optional)?$', identifier='root_InternPool_TrackedInst_Index', synth=True) add(debugger, category='zig', regex=True, type=r'^root\.InternPool\.Nav\.Index(\.Optional)?$', identifier='root_InternPool_Nav_Index', synth=True)