Commit eaa227449c

Jacob Young <jacobly0@users.noreply.github.com>
2024-08-20 04:16:20
Dwarf: fix issues with inline call sites
1 parent 62f7276
src/arch/x86_64/CodeGen.zig
@@ -12033,6 +12033,10 @@ fn genLocalDebugInfo(
                     .disp = sym_off.off,
                 } },
             }),
+            .lea_direct, .lea_got, .lea_tlv => |sym| try self.asmAirMemory(.dbg_local, inst, .{
+                .base = .{ .reloc = .{ .atom_index = undefined, .sym_index = sym } },
+                .mod = .{ .rm = .{ .size = .qword } },
+            }),
         },
     }
 }
src/link/Elf/ZigObject.zig
@@ -1122,9 +1122,9 @@ pub fn updateNav(
 
     log.debug("updateNav {}({d})", .{ nav.fqn.fmt(ip), nav_index });
 
-    const nav_val = zcu.navValue(nav_index);
-    const nav_init = switch (ip.indexToKey(nav_val.toIntern())) {
-        .variable => |variable| Value.fromInterned(variable.init),
+    const nav_init = switch (ip.indexToKey(nav.status.resolved.val)) {
+        .func => .none,
+        .variable => |variable| variable.init,
         .@"extern" => |@"extern"| {
             if (ip.isFunctionType(@"extern".ty)) return;
             const sym_index = try self.getGlobalSymbol(
@@ -1135,10 +1135,10 @@ pub fn updateNav(
             self.symbol(sym_index).flags.is_extern_ptr = true;
             return;
         },
-        else => nav_val,
+        else => nav.status.resolved.val,
     };
 
-    if (nav_init.typeOf(zcu).isFnOrHasRuntimeBits(pt)) {
+    if (nav_init != .none and Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(pt)) {
         const sym_index = try self.getOrCreateMetadataForNav(elf_file, nav_index);
         self.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file);
 
@@ -1153,7 +1153,7 @@ pub fn updateNav(
             &elf_file.base,
             pt,
             zcu.navSrcLoc(nav_index),
-            nav_init,
+            Value.fromInterned(nav_init),
             &code_buffer,
             if (debug_wip_nav) |*wip_nav| .{ .dwarf = wip_nav } else .none,
             .{ .parent_atom_index = sym_index },
src/link/MachO/ZigObject.zig
@@ -869,10 +869,11 @@ pub fn updateNav(
 
     const zcu = pt.zcu;
     const ip = &zcu.intern_pool;
+    const nav = ip.getNav(nav_index);
 
-    const nav_val = zcu.navValue(nav_index);
-    const nav_init = switch (ip.indexToKey(nav_val.toIntern())) {
-        .variable => |variable| Value.fromInterned(variable.init),
+    const nav_init = switch (ip.indexToKey(nav.status.resolved.val)) {
+        .func => .none,
+        .variable => |variable| variable.init,
         .@"extern" => |@"extern"| {
             if (ip.isFunctionType(@"extern".ty)) return;
             // Extern variable gets a __got entry only
@@ -883,10 +884,10 @@ pub fn updateNav(
             sym.flags.is_extern_ptr = true;
             return;
         },
-        else => nav_val,
+        else => nav.status.resolved.val,
     };
 
-    if (nav_init.typeOf(zcu).isFnOrHasRuntimeBits(pt)) {
+    if (nav_init != .none and Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(pt)) {
         const sym_index = try self.getOrCreateMetadataForNav(macho_file, nav_index);
         self.symbols.items[sym_index].getAtom(macho_file).?.freeRelocs(macho_file);
 
@@ -900,7 +901,7 @@ pub fn updateNav(
             &macho_file.base,
             pt,
             zcu.navSrcLoc(nav_index),
-            nav_init,
+            Value.fromInterned(nav_init),
             &code_buffer,
             if (debug_wip_nav) |*wip_nav| .{ .dwarf = wip_nav } else .none,
             .{ .parent_atom_index = sym_index },
src/link/Wasm/ZigObject.zig
@@ -259,7 +259,7 @@ pub fn updateNav(
         else => .{ false, .none, nav_val },
     };
 
-    if (nav_init.typeOf(zcu).isFnOrHasRuntimeBits(pt)) {
+    if (nav_init.typeOf(zcu).hasRuntimeBits(pt)) {
         const gpa = wasm_file.base.comp.gpa;
         const atom_index = try zig_object.getOrCreateAtomForNav(wasm_file, pt, nav_index);
         const atom = wasm_file.getAtomPtr(atom_index);
src/link/C.zig
@@ -317,8 +317,18 @@ pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !
     defer tracy.end();
 
     const gpa = self.base.comp.gpa;
-
     const zcu = pt.zcu;
+    const ip = &zcu.intern_pool;
+
+    const nav = ip.getNav(nav_index);
+    const nav_init = switch (ip.indexToKey(nav.status.resolved.val)) {
+        .func => return,
+        .@"extern" => .none,
+        .variable => |variable| variable.init,
+        else => nav.status.resolved.val,
+    };
+    if (nav_init != .none and !Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(pt)) return;
+
     const gop = try self.navs.getOrPut(gpa, nav_index);
     errdefer _ = self.navs.pop();
     if (!gop.found_existing) gop.value_ptr.* = .{};
src/link/Coff.zig
@@ -1207,6 +1207,7 @@ pub fn updateNav(
 
     const nav_val = zcu.navValue(nav_index);
     const nav_init = switch (ip.indexToKey(nav_val.toIntern())) {
+        .func => return,
         .variable => |variable| Value.fromInterned(variable.init),
         .@"extern" => |@"extern"| {
             if (ip.isFunctionType(@"extern".ty)) return;
@@ -1220,7 +1221,7 @@ pub fn updateNav(
         else => nav_val,
     };
 
-    if (nav_init.typeOf(zcu).isFnOrHasRuntimeBits(pt)) {
+    if (nav_init.typeOf(zcu).hasRuntimeBits(pt)) {
         const atom_index = try self.getOrCreateAtomForNav(nav_index);
         Atom.freeRelocations(self, atom_index);
         const atom = self.getAtom(atom_index);
src/link/Dwarf.zig
@@ -21,8 +21,9 @@ pub const UpdateError =
     std.fs.File.OpenError ||
     std.fs.File.SetEndPosError ||
     std.fs.File.CopyRangeError ||
+    std.fs.File.PReadError ||
     std.fs.File.PWriteError ||
-    error{ Overflow, Underflow, UnexpectedEndOfFile };
+    error{ EndOfStream, Overflow, Underflow, UnexpectedEndOfFile };
 
 pub const FlushError =
     UpdateError ||
@@ -253,10 +254,8 @@ const Section = struct {
             .trailer_len = trailer_len,
             .len = header_len + trailer_len,
             .entries = .{},
-            .cross_entry_relocs = .{},
             .cross_unit_relocs = .{},
             .cross_section_relocs = .{},
-            .external_relocs = .{},
         };
         if (sec.last.unwrap()) |last_unit| {
             const last_unit_ptr = sec.getUnit(last_unit);
@@ -358,10 +357,8 @@ const Unit = struct {
     /// data length in bytes
     len: u32,
     entries: std.ArrayListUnmanaged(Entry),
-    cross_entry_relocs: std.ArrayListUnmanaged(CrossEntryReloc),
     cross_unit_relocs: std.ArrayListUnmanaged(CrossUnitReloc),
     cross_section_relocs: std.ArrayListUnmanaged(CrossSectionReloc),
-    external_relocs: std.ArrayListUnmanaged(ExternalReloc),
 
     const Index = enum(u32) {
         main,
@@ -381,12 +378,16 @@ const Unit = struct {
         }
     };
 
+    fn clear(unit: *Unit) void {
+        unit.cross_unit_relocs.clearRetainingCapacity();
+        unit.cross_section_relocs.clearRetainingCapacity();
+    }
+
     fn deinit(unit: *Unit, gpa: std.mem.Allocator) void {
+        for (unit.entries.items) |*entry| entry.deinit(gpa);
         unit.entries.deinit(gpa);
-        unit.cross_entry_relocs.deinit(gpa);
         unit.cross_unit_relocs.deinit(gpa);
         unit.cross_section_relocs.deinit(gpa);
-        unit.external_relocs.deinit(gpa);
         unit.* = undefined;
     }
 
@@ -398,6 +399,10 @@ const Unit = struct {
             .next = .none,
             .off = 0,
             .len = 0,
+            .cross_entry_relocs = .{},
+            .cross_unit_relocs = .{},
+            .cross_section_relocs = .{},
+            .external_relocs = .{},
         };
         if (unit.last.unwrap()) |last_entry| {
             const last_entry_ptr = unit.getEntry(last_entry);
@@ -451,6 +456,14 @@ const Unit = struct {
         unit_ptr.len = len;
     }
 
+    fn trim(unit: *Unit) void {
+        const len = unit.getEntry(unit.first.unwrap() orelse return).off;
+        if (len == 0) return;
+        for (unit.entries.items) |*entry| entry.off -= len;
+        unit.off += len;
+        unit.len -= len;
+    }
+
     fn move(unit: *Unit, sec: *Section, dwarf: *Dwarf, new_off: u32) UpdateError!void {
         if (unit.off == new_off) return;
         if (try dwarf.getFile().?.copyRangeAll(
@@ -463,6 +476,7 @@ const Unit = struct {
     }
 
     fn resizeHeader(unit: *Unit, sec: *Section, dwarf: *Dwarf, len: u32) UpdateError!void {
+        unit.trim();
         if (unit.header_len == len) return;
         const available_len = if (unit.prev.unwrap()) |prev_unit| prev_excess: {
             const prev_unit_ptr = sec.getUnit(prev_unit);
@@ -535,23 +549,11 @@ const Unit = struct {
     }
 
     fn resolveRelocs(unit: *Unit, sec: *Section, dwarf: *Dwarf) RelocError!void {
-        for (unit.cross_entry_relocs.items) |reloc| {
-            try dwarf.resolveReloc(
-                sec.off + unit.off + (if (reloc.source_entry.unwrap()) |source_entry|
-                    unit.header_len + unit.getEntry(source_entry).off
-                else
-                    0) + reloc.source_off,
-                unit.off + unit.header_len + unit.getEntry(reloc.target_entry).assertNonEmpty(unit, sec, dwarf).off + reloc.target_off,
-                dwarf.sectionOffsetBytes(),
-            );
-        }
+        const unit_off = sec.off + unit.off;
         for (unit.cross_unit_relocs.items) |reloc| {
             const target_unit = sec.getUnit(reloc.target_unit);
             try dwarf.resolveReloc(
-                sec.off + unit.off + (if (reloc.source_entry.unwrap()) |source_entry|
-                    unit.header_len + unit.getEntry(source_entry).off
-                else
-                    0) + reloc.source_off,
+                unit_off + reloc.source_off,
                 target_unit.off + (if (reloc.target_entry.unwrap()) |target_entry|
                     target_unit.header_len + target_unit.getEntry(target_entry).assertNonEmpty(unit, sec, dwarf).off
                 else
@@ -565,10 +567,7 @@ const Unit = struct {
             };
             const target_unit = target_sec.getUnit(reloc.target_unit);
             try dwarf.resolveReloc(
-                sec.off + unit.off + (if (reloc.source_entry.unwrap()) |source_entry|
-                    unit.header_len + unit.getEntry(source_entry).off
-                else
-                    0) + reloc.source_off,
+                unit_off + reloc.source_off,
                 target_unit.off + (if (reloc.target_entry.unwrap()) |target_entry|
                     target_unit.header_len + target_unit.getEntry(target_entry).assertNonEmpty(unit, sec, dwarf).off
                 else
@@ -576,57 +575,8 @@ const Unit = struct {
                 dwarf.sectionOffsetBytes(),
             );
         }
-        if (dwarf.bin_file.cast(.elf)) |elf_file| {
-            const zo = elf_file.zigObjectPtr().?;
-            for (unit.external_relocs.items) |reloc| {
-                const symbol = zo.symbol(reloc.target_sym);
-                try dwarf.resolveReloc(
-                    sec.off + unit.off + unit.header_len + unit.getEntry(reloc.source_entry).off + reloc.source_off,
-                    @bitCast(symbol.address(.{}, elf_file) + @as(i64, @intCast(reloc.target_off)) -
-                        if (symbol.flags.is_tls) elf_file.dtpAddress() else 0),
-                    @intFromEnum(dwarf.address_size),
-                );
-            }
-        } else if (dwarf.bin_file.cast(.macho)) |macho_file| {
-            const zo = macho_file.getZigObject().?;
-            for (unit.external_relocs.items) |reloc| {
-                const ref = zo.getSymbolRef(reloc.target_sym, macho_file);
-                try dwarf.resolveReloc(
-                    sec.off + unit.off + unit.header_len + unit.getEntry(reloc.source_entry).off + reloc.source_off,
-                    ref.getSymbol(macho_file).?.getAddress(.{}, macho_file),
-                    @intFromEnum(dwarf.address_size),
-                );
-            }
-        }
+        for (unit.entries.items) |*entry| try entry.resolveRelocs(unit, sec, dwarf);
     }
-
-    const CrossEntryReloc = struct {
-        source_entry: Entry.Index.Optional = .none,
-        source_off: u32 = 0,
-        target_entry: Entry.Index,
-        target_off: u32 = 0,
-    };
-    const CrossUnitReloc = struct {
-        source_entry: Entry.Index.Optional = .none,
-        source_off: u32 = 0,
-        target_unit: Unit.Index,
-        target_entry: Entry.Index.Optional = .none,
-        target_off: u32 = 0,
-    };
-    const CrossSectionReloc = struct {
-        source_entry: Entry.Index.Optional = .none,
-        source_off: u32 = 0,
-        target_sec: Section.Index,
-        target_unit: Unit.Index,
-        target_entry: Entry.Index.Optional = .none,
-        target_off: u32 = 0,
-    };
-    const ExternalReloc = struct {
-        source_entry: Entry.Index,
-        source_off: u32 = 0,
-        target_sym: u32,
-        target_off: u64 = 0,
-    };
 };
 
 /// An indivisible entry within a `Unit` containing section-specific data.
@@ -637,6 +587,25 @@ const Entry = struct {
     off: u32,
     /// data length in bytes
     len: u32,
+    cross_entry_relocs: std.ArrayListUnmanaged(CrossEntryReloc),
+    cross_unit_relocs: std.ArrayListUnmanaged(CrossUnitReloc),
+    cross_section_relocs: std.ArrayListUnmanaged(CrossSectionReloc),
+    external_relocs: std.ArrayListUnmanaged(ExternalReloc),
+
+    fn clear(entry: *Entry) void {
+        entry.cross_entry_relocs.clearRetainingCapacity();
+        entry.cross_unit_relocs.clearRetainingCapacity();
+        entry.cross_section_relocs.clearRetainingCapacity();
+        entry.external_relocs.clearRetainingCapacity();
+    }
+
+    fn deinit(entry: *Entry, gpa: std.mem.Allocator) void {
+        entry.cross_entry_relocs.deinit(gpa);
+        entry.cross_unit_relocs.deinit(gpa);
+        entry.cross_section_relocs.deinit(gpa);
+        entry.external_relocs.deinit(gpa);
+        entry.* = undefined;
+    }
 
     const Index = enum(u32) {
         _,
@@ -803,6 +772,88 @@ const Entry = struct {
         }
         @panic("missing dwarf relocation target");
     }
+
+    fn resolveRelocs(entry: *Entry, unit: *Unit, sec: *Section, dwarf: *Dwarf) RelocError!void {
+        const entry_off = sec.off + unit.off + unit.header_len + entry.off;
+        for (entry.cross_entry_relocs.items) |reloc| {
+            try dwarf.resolveReloc(
+                entry_off + reloc.source_off,
+                unit.off + unit.header_len + unit.getEntry(reloc.target_entry).assertNonEmpty(unit, sec, dwarf).off + reloc.target_off,
+                dwarf.sectionOffsetBytes(),
+            );
+        }
+        for (entry.cross_unit_relocs.items) |reloc| {
+            const target_unit = sec.getUnit(reloc.target_unit);
+            try dwarf.resolveReloc(
+                entry_off + reloc.source_off,
+                target_unit.off + (if (reloc.target_entry.unwrap()) |target_entry|
+                    target_unit.header_len + target_unit.getEntry(target_entry).assertNonEmpty(unit, sec, dwarf).off
+                else
+                    0) + reloc.target_off,
+                dwarf.sectionOffsetBytes(),
+            );
+        }
+        for (entry.cross_section_relocs.items) |reloc| {
+            const target_sec = switch (reloc.target_sec) {
+                inline else => |target_sec| &@field(dwarf, @tagName(target_sec)).section,
+            };
+            const target_unit = target_sec.getUnit(reloc.target_unit);
+            try dwarf.resolveReloc(
+                entry_off + reloc.source_off,
+                target_unit.off + (if (reloc.target_entry.unwrap()) |target_entry|
+                    target_unit.header_len + target_unit.getEntry(target_entry).assertNonEmpty(unit, sec, dwarf).off
+                else
+                    0) + reloc.target_off,
+                dwarf.sectionOffsetBytes(),
+            );
+        }
+        if (dwarf.bin_file.cast(.elf)) |elf_file| {
+            const zo = elf_file.zigObjectPtr().?;
+            for (entry.external_relocs.items) |reloc| {
+                const symbol = zo.symbol(reloc.target_sym);
+                try dwarf.resolveReloc(
+                    entry_off + reloc.source_off,
+                    @bitCast(symbol.address(.{}, elf_file) + @as(i64, @intCast(reloc.target_off)) -
+                        if (symbol.flags.is_tls) elf_file.dtpAddress() else 0),
+                    @intFromEnum(dwarf.address_size),
+                );
+            }
+        } else if (dwarf.bin_file.cast(.macho)) |macho_file| {
+            const zo = macho_file.getZigObject().?;
+            for (entry.external_relocs.items) |reloc| {
+                const ref = zo.getSymbolRef(reloc.target_sym, macho_file);
+                try dwarf.resolveReloc(
+                    entry_off + reloc.source_off,
+                    ref.getSymbol(macho_file).?.getAddress(.{}, macho_file),
+                    @intFromEnum(dwarf.address_size),
+                );
+            }
+        }
+    }
+};
+
+const CrossEntryReloc = struct {
+    source_off: u32 = 0,
+    target_entry: Entry.Index,
+    target_off: u32 = 0,
+};
+const CrossUnitReloc = struct {
+    source_off: u32 = 0,
+    target_unit: Unit.Index,
+    target_entry: Entry.Index.Optional = .none,
+    target_off: u32 = 0,
+};
+const CrossSectionReloc = struct {
+    source_off: u32 = 0,
+    target_sec: Section.Index,
+    target_unit: Unit.Index,
+    target_entry: Entry.Index.Optional = .none,
+    target_off: u32 = 0,
+};
+const ExternalReloc = struct {
+    source_off: u32 = 0,
+    target_sym: u32,
+    target_off: u64 = 0,
 };
 
 pub const Loc = union(enum) {
@@ -1087,14 +1138,13 @@ pub const WipNav = struct {
         const diw = wip_nav.debug_info.writer(dwarf.gpa);
         try wip_nav.inlined_funcs_high_reloc.ensureUnusedCapacity(dwarf.gpa, 1);
 
-        const external_relocs = &dwarf.debug_info.section.getUnit(wip_nav.unit).external_relocs;
-        try external_relocs.ensureUnusedCapacity(dwarf.gpa, 2);
         try uleb128(diw, @intFromEnum(AbbrevCode.inlined_func));
         try wip_nav.refNav(zcu.funcInfo(func).owner_nav);
         try uleb128(diw, zcu.navSrcLine(zcu.funcInfo(wip_nav.func).owner_nav) + line + 1);
-        try uleb128(diw, column);
+        try uleb128(diw, column + 1);
+        const external_relocs = &dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs;
+        try external_relocs.ensureUnusedCapacity(dwarf.gpa, 2);
         external_relocs.appendAssumeCapacity(.{
-            .source_entry = wip_nav.entry,
             .source_off = @intCast(wip_nav.debug_info.items.len),
             .target_sym = wip_nav.func_sym_index,
             .target_off = code_off,
@@ -1102,7 +1152,6 @@ pub const WipNav = struct {
         try diw.writeByteNTimes(0, @intFromEnum(dwarf.address_size));
         wip_nav.inlined_funcs_high_reloc.appendAssumeCapacity(@intCast(external_relocs.items.len));
         external_relocs.appendAssumeCapacity(.{
-            .source_entry = wip_nav.entry,
             .source_off = @intCast(wip_nav.debug_info.items.len),
             .target_sym = wip_nav.func_sym_index,
             .target_off = undefined,
@@ -1112,7 +1161,7 @@ pub const WipNav = struct {
     }
 
     pub fn leaveInlineFunc(wip_nav: *WipNav, func: InternPool.Index, code_off: u64) UpdateError!void {
-        const external_relocs = &wip_nav.dwarf.debug_info.section.getUnit(wip_nav.unit).external_relocs;
+        const external_relocs = &wip_nav.dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs;
         external_relocs.items[wip_nav.inlined_funcs_high_reloc.pop()].target_off = code_off;
         try uleb128(wip_nav.debug_info.writer(wip_nav.dwarf.gpa), @intFromEnum(AbbrevCode.null));
         try wip_nav.setInlineFunc(func);
@@ -1137,8 +1186,7 @@ pub const WipNav = struct {
             try dlw.writeByte(DW.LNS.extended_op);
             try uleb128(dlw, 1 + dwarf.sectionOffsetBytes());
             try dlw.writeByte(DW.LNE.ZIG_set_decl);
-            try dwarf.debug_line.section.getUnit(wip_nav.unit).cross_section_relocs.append(dwarf.gpa, .{
-                .source_entry = wip_nav.entry.toOptional(),
+            try dwarf.debug_line.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_section_relocs.append(dwarf.gpa, .{
                 .source_off = @intCast(wip_nav.debug_line.items.len),
                 .target_sec = .debug_info,
                 .target_unit = new_unit,
@@ -1174,9 +1222,9 @@ pub const WipNav = struct {
     fn infoSectionOffset(wip_nav: *WipNav, sec: Section.Index, unit: Unit.Index, entry: Entry.Index, off: u32) UpdateError!void {
         const dwarf = wip_nav.dwarf;
         const gpa = dwarf.gpa;
+        const entry_ptr = dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry);
         if (sec != .debug_info) {
-            try dwarf.debug_info.section.getUnit(wip_nav.unit).cross_section_relocs.append(gpa, .{
-                .source_entry = wip_nav.entry.toOptional(),
+            try entry_ptr.cross_section_relocs.append(gpa, .{
                 .source_off = @intCast(wip_nav.debug_info.items.len),
                 .target_sec = sec,
                 .target_unit = unit,
@@ -1184,16 +1232,14 @@ pub const WipNav = struct {
                 .target_off = off,
             });
         } else if (unit != wip_nav.unit) {
-            try dwarf.debug_info.section.getUnit(wip_nav.unit).cross_unit_relocs.append(gpa, .{
-                .source_entry = wip_nav.entry.toOptional(),
+            try entry_ptr.cross_unit_relocs.append(gpa, .{
                 .source_off = @intCast(wip_nav.debug_info.items.len),
                 .target_unit = unit,
                 .target_entry = entry.toOptional(),
                 .target_off = off,
             });
         } else {
-            try dwarf.debug_info.section.getUnit(wip_nav.unit).cross_entry_relocs.append(gpa, .{
-                .source_entry = wip_nav.entry.toOptional(),
+            try entry_ptr.cross_entry_relocs.append(gpa, .{
                 .source_off = @intCast(wip_nav.debug_info.items.len),
                 .target_entry = entry,
                 .target_off = off,
@@ -1208,8 +1254,7 @@ pub const WipNav = struct {
 
     fn addrSym(wip_nav: *WipNav, sym_index: u32) UpdateError!void {
         const dwarf = wip_nav.dwarf;
-        try dwarf.debug_info.section.getUnit(wip_nav.unit).external_relocs.append(dwarf.gpa, .{
-            .source_entry = wip_nav.entry,
+        try dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs.append(dwarf.gpa, .{
             .source_off = @intCast(wip_nav.debug_info.items.len),
             .target_sym = sym_index,
         });
@@ -1269,10 +1314,9 @@ pub const WipNav = struct {
 
     fn refForward(wip_nav: *WipNav) std.mem.Allocator.Error!u32 {
         const dwarf = wip_nav.dwarf;
-        const cross_entry_relocs = &dwarf.debug_info.section.getUnit(wip_nav.unit).cross_entry_relocs;
+        const cross_entry_relocs = &dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_entry_relocs;
         const reloc_index: u32 = @intCast(cross_entry_relocs.items.len);
         try cross_entry_relocs.append(dwarf.gpa, .{
-            .source_entry = wip_nav.entry.toOptional(),
             .source_off = @intCast(wip_nav.debug_info.items.len),
             .target_entry = undefined,
             .target_off = undefined,
@@ -1282,7 +1326,7 @@ pub const WipNav = struct {
     }
 
     fn finishForward(wip_nav: *WipNav, reloc_index: u32) void {
-        const reloc = &wip_nav.dwarf.debug_info.section.getUnit(wip_nav.unit).cross_entry_relocs.items[reloc_index];
+        const reloc = &wip_nav.dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_entry_relocs.items[reloc_index];
         reloc.target_entry = wip_nav.entry;
         reloc.target_off = @intCast(wip_nav.debug_info.items.len);
     }
@@ -1595,7 +1639,15 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
     const unit = try dwarf.getUnit(file.mod);
     const nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index);
     errdefer _ = dwarf.navs.pop();
-    if (!nav_gop.found_existing) nav_gop.value_ptr.* = try dwarf.addCommonEntry(unit);
+    if (nav_gop.found_existing) {
+        for ([_]*Section{
+            &dwarf.debug_aranges.section,
+            &dwarf.debug_info.section,
+            &dwarf.debug_line.section,
+            &dwarf.debug_loclists.section,
+            &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,
@@ -1759,17 +1811,15 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
             try wip_nav.strp(nav.name.toSlice(ip));
             try wip_nav.strp(nav.fqn.toSlice(ip));
             try wip_nav.refType(Type.fromInterned(func_type.return_type));
-            const external_relocs = &dwarf.debug_info.section.getUnit(unit).external_relocs;
+            const external_relocs = &dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs;
             try external_relocs.ensureUnusedCapacity(dwarf.gpa, 2);
             external_relocs.appendAssumeCapacity(.{
-                .source_entry = wip_nav.entry,
                 .source_off = @intCast(wip_nav.debug_info.items.len),
                 .target_sym = sym_index,
             });
             try diw.writeByteNTimes(0, @intFromEnum(dwarf.address_size));
             wip_nav.func_high_reloc = @intCast(external_relocs.items.len);
             external_relocs.appendAssumeCapacity(.{
-                .source_entry = wip_nav.entry,
                 .source_off = @intCast(wip_nav.debug_info.items.len),
                 .target_sym = sym_index,
                 .target_off = undefined,
@@ -1785,8 +1835,7 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
             if (dwarf.incremental()) {
                 try uleb128(dlw, 1 + dwarf.sectionOffsetBytes());
                 try dlw.writeByte(DW.LNE.ZIG_set_decl);
-                try dwarf.debug_line.section.getUnit(wip_nav.unit).cross_section_relocs.append(dwarf.gpa, .{
-                    .source_entry = wip_nav.entry.toOptional(),
+                try dwarf.debug_line.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_section_relocs.append(dwarf.gpa, .{
                     .source_off = @intCast(wip_nav.debug_line.items.len),
                     .target_sec = .debug_info,
                     .target_unit = wip_nav.unit,
@@ -1801,8 +1850,7 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
             } else {
                 try uleb128(dlw, 1 + @intFromEnum(dwarf.address_size));
                 try dlw.writeByte(DW.LNE.set_address);
-                try dwarf.debug_line.section.getUnit(wip_nav.unit).external_relocs.append(dwarf.gpa, .{
-                    .source_entry = wip_nav.entry,
+                try dwarf.debug_line.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs.append(dwarf.gpa, .{
                     .source_off = @intCast(wip_nav.debug_line.items.len),
                     .target_sym = sym_index,
                 });
@@ -1835,7 +1883,7 @@ pub fn finishWipNav(
     log.debug("finishWipNav({})", .{nav.fqn.fmt(ip)});
 
     if (wip_nav.func != .none) {
-        const external_relocs = &dwarf.debug_info.section.getUnit(wip_nav.unit).external_relocs;
+        const external_relocs = &dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs;
         external_relocs.items[wip_nav.func_high_reloc].target_off = sym.size;
         if (wip_nav.any_children) {
             const diw = wip_nav.debug_info.writer(dwarf.gpa);
@@ -1847,8 +1895,7 @@ pub fn finishWipNav(
         );
 
         var aranges_entry = [1]u8{0} ** (8 + 8);
-        try dwarf.debug_aranges.section.getUnit(wip_nav.unit).external_relocs.append(dwarf.gpa, .{
-            .source_entry = wip_nav.entry,
+        try dwarf.debug_aranges.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs.append(dwarf.gpa, .{
             .target_sym = sym.index,
         });
         dwarf.writeInt(aranges_entry[0..@intFromEnum(dwarf.address_size)], 0);
@@ -1862,14 +1909,12 @@ pub fn finishWipNav(
             aranges_entry[0 .. @intFromEnum(dwarf.address_size) * 2],
         );
 
-        try dwarf.debug_rnglists.section.getUnit(wip_nav.unit).external_relocs.appendSlice(dwarf.gpa, &.{
+        try dwarf.debug_rnglists.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs.appendSlice(dwarf.gpa, &.{
             .{
-                .source_entry = wip_nav.entry,
                 .source_off = 1,
                 .target_sym = sym.index,
             },
             .{
-                .source_entry = wip_nav.entry,
                 .source_off = 1 + @intFromEnum(dwarf.address_size),
                 .target_sym = sym.index,
                 .target_off = sym.size,
@@ -1935,6 +1980,29 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
     errdefer _ = dwarf.navs.pop();
     switch (ip.indexToKey(nav_val.toIntern())) {
         .func => |func| {
+            if (nav_gop.found_existing) {
+                const unit_ptr = dwarf.debug_info.section.getUnit(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 + 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(
+                        try std.leb.readUleb128(@typeInfo(AbbrevCode).Enum.tag_type, abbrev_code_fbs.reader()),
+                    );
+                    switch (abbrev_code) {
+                        else => unreachable,
+                        .decl_func, .decl_func_empty => return,
+                        .decl_func_generic, .decl_func_generic_empty => {},
+                    }
+                }
+                entry_ptr.clear();
+            } else nav_gop.value_ptr.* = try dwarf.addCommonEntry(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 .{
@@ -1948,12 +2016,9 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
                 };
             } else .{ zcu.fileRootType(inst_info.file), DW.ACCESS.private };
 
-            if (!nav_gop.found_existing) nav_gop.value_ptr.* = try dwarf.addCommonEntry(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 uleb128(diw, @intFromEnum(@as(AbbrevCode, if (func_type.param_types.len > 0 and func_type.is_var_args) .decl_func_generic else .decl_func_generic_empty)));
+            try uleb128(diw, @intFromEnum(@as(AbbrevCode, if (func_type.param_types.len > 0 or func_type.is_var_args) .decl_func_generic else .decl_func_generic_empty)));
             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);
@@ -1961,12 +2026,14 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
             try diw.writeByte(accessibility);
             try wip_nav.strp(nav.name.toSlice(ip));
             try wip_nav.refType(Type.fromInterned(func_type.return_type));
-            for (0..func_type.param_types.len) |param_index| {
-                try uleb128(diw, @intFromEnum(AbbrevCode.func_type_param));
-                try wip_nav.refType(Type.fromInterned(func_type.param_types.get(ip)[param_index]));
+            if (func_type.param_types.len > 0 or func_type.is_var_args) {
+                for (0..func_type.param_types.len) |param_index| {
+                    try uleb128(diw, @intFromEnum(AbbrevCode.func_type_param));
+                    try wip_nav.refType(Type.fromInterned(func_type.param_types.get(ip)[param_index]));
+                }
+                if (func_type.is_var_args) try uleb128(diw, @intFromEnum(AbbrevCode.is_var_args));
+                try uleb128(diw, @intFromEnum(AbbrevCode.null));
             }
-            if (func_type.is_var_args) try uleb128(diw, @intFromEnum(AbbrevCode.is_var_args));
-            try uleb128(diw, @intFromEnum(AbbrevCode.null));
         },
         .struct_type => done: {
             const loaded_struct = ip.loadStructType(nav_val.toIntern());
@@ -2535,13 +2602,25 @@ fn updateType(
         .error_union_type => |error_union_type| {
             const error_union_error_set_type = Type.fromInterned(error_union_type.error_set_type);
             const error_union_payload_type = Type.fromInterned(error_union_type.payload_type);
-            const error_union_error_set_offset = codegen.errUnionErrorOffset(error_union_payload_type, pt);
-            const error_union_payload_offset = codegen.errUnionPayloadOffset(error_union_payload_type, pt);
+            const error_union_error_set_offset, const error_union_payload_offset = switch (error_union_type.payload_type) {
+                .generic_poison_type => .{ 0, 0 },
+                else => .{
+                    codegen.errUnionErrorOffset(error_union_payload_type, pt),
+                    codegen.errUnionPayloadOffset(error_union_payload_type, pt),
+                },
+            };
 
             try uleb128(diw, @intFromEnum(AbbrevCode.union_type));
             try wip_nav.strp(name);
-            try uleb128(diw, ty.abiSize(pt));
-            try uleb128(diw, ty.abiAlignment(pt).toByteUnits().?);
+            if (error_union_type.error_set_type != .generic_poison_type and
+                error_union_type.payload_type != .generic_poison_type)
+            {
+                try uleb128(diw, ty.abiSize(pt));
+                try uleb128(diw, ty.abiAlignment(pt).toByteUnits().?);
+            } else {
+                try uleb128(diw, 0);
+                try uleb128(diw, 1);
+            }
             {
                 try uleb128(diw, @intFromEnum(AbbrevCode.tagged_union));
                 try wip_nav.infoSectionOffset(
@@ -2723,10 +2802,16 @@ fn updateType(
             }
             if (error_set_type.names.len > 0) try uleb128(diw, @intFromEnum(AbbrevCode.null));
         },
-        .inferred_error_set_type => |func| {
-            try uleb128(diw, @intFromEnum(AbbrevCode.inferred_error_set_type));
-            try wip_nav.strp(name);
-            try wip_nav.refType(Type.fromInterned(ip.funcIesResolvedUnordered(func)));
+        .inferred_error_set_type => |func| switch (ip.funcIesResolvedUnordered(func)) {
+            .none => {
+                try uleb128(diw, @intFromEnum(AbbrevCode.void_type));
+                try wip_nav.strp(name);
+            },
+            else => |ies| {
+                try uleb128(diw, @intFromEnum(AbbrevCode.inferred_error_set_type));
+                try wip_nav.strp(name);
+                try wip_nav.refType(Type.fromInterned(ies));
+            },
         },
 
         // values, not types
@@ -3072,7 +3157,8 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
     if (dwarf.debug_aranges.section.dirty) {
         for (dwarf.debug_aranges.section.units.items, 0..) |*unit_ptr, unit_index| {
             const unit: Unit.Index = @enumFromInt(unit_index);
-            try unit_ptr.cross_section_relocs.ensureUnusedCapacity(dwarf.gpa, 1);
+            unit_ptr.clear();
+            try unit_ptr.cross_section_relocs.ensureTotalCapacity(dwarf.gpa, 1);
             header.clearRetainingCapacity();
             try header.ensureTotalCapacity(unit_ptr.header_len);
             const unit_len = (if (unit_ptr.next.unwrap()) |next_unit|
@@ -3103,8 +3189,9 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
     if (dwarf.debug_info.section.dirty) {
         for (dwarf.mods.keys(), dwarf.mods.values(), dwarf.debug_info.section.units.items, 0..) |mod, mod_info, *unit_ptr, unit_index| {
             const unit: Unit.Index = @enumFromInt(unit_index);
-            try unit_ptr.cross_unit_relocs.ensureUnusedCapacity(dwarf.gpa, 1);
-            try unit_ptr.cross_section_relocs.ensureUnusedCapacity(dwarf.gpa, 7);
+            unit_ptr.clear();
+            try unit_ptr.cross_unit_relocs.ensureTotalCapacity(dwarf.gpa, 1);
+            try unit_ptr.cross_section_relocs.ensureTotalCapacity(dwarf.gpa, 7);
             header.clearRetainingCapacity();
             try header.ensureTotalCapacity(unit_ptr.header_len);
             const unit_len = (if (unit_ptr.next.unwrap()) |next_unit|
@@ -3195,7 +3282,8 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
         for (dwarf.mods.values(), dwarf.debug_line.section.units.items) |mod_info, *unit|
             try unit.resizeHeader(&dwarf.debug_line.section, dwarf, DebugLine.headerBytes(dwarf, @intCast(mod_info.dirs.count()), @intCast(mod_info.files.count())));
         for (dwarf.mods.values(), dwarf.debug_line.section.units.items) |mod_info, *unit| {
-            try unit.cross_section_relocs.ensureUnusedCapacity(dwarf.gpa, 2 * (1 + mod_info.files.count()));
+            unit.clear();
+            try unit.cross_section_relocs.ensureTotalCapacity(dwarf.gpa, 2 * (1 + mod_info.files.count()));
             header.clearRetainingCapacity();
             try header.ensureTotalCapacity(unit.header_len);
             const unit_len = (if (unit.next.unwrap()) |next_unit|
src/link/Plan9.zig
@@ -448,6 +448,7 @@ pub fn updateNav(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde
     const nav = ip.getNav(nav_index);
     const nav_val = zcu.navValue(nav_index);
     const nav_init = switch (ip.indexToKey(nav_val.toIntern())) {
+        .func => return,
         .variable => |variable| Value.fromInterned(variable.init),
         .@"extern" => {
             log.debug("found extern decl: {}", .{nav.name.fmt(ip)});
@@ -456,7 +457,7 @@ pub fn updateNav(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde
         else => nav_val,
     };
 
-    if (nav_init.typeOf(zcu).isFnOrHasRuntimeBits(pt)) {
+    if (nav_init.typeOf(zcu).hasRuntimeBits(pt)) {
         const atom_idx = try self.seeNav(pt, nav_index);
 
         var code_buffer = std.ArrayList(u8).init(gpa);
src/Zcu/PerThread.zig
@@ -1240,14 +1240,11 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {
         };
     }
 
-    const nav_already_populated, const queue_linker_work = switch (ip.indexToKey(decl_val.toIntern())) {
-        .func => |f| status: {
-            const func_type = ip.indexToKey(f.ty).func_type;
-            break :status .{ f.owner_nav == nav_index, func_type.is_generic or func_type.cc == .Inline };
-        },
-        .variable => |v| .{ false, v.owner_nav == nav_index },
-        .@"extern" => .{ false, false },
-        else => .{ false, true },
+    const nav_already_populated, const queue_linker_work, const resolve_type = switch (ip.indexToKey(decl_val.toIntern())) {
+        .func => |f| .{ f.owner_nav == nav_index, true, false },
+        .variable => |v| .{ false, v.owner_nav == nav_index, true },
+        .@"extern" => .{ false, false, false },
+        else => .{ false, true, true },
     };
 
     if (nav_already_populated) {
@@ -1320,14 +1317,16 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {
     queue_codegen: {
         if (!queue_linker_work) break :queue_codegen;
 
-        // Needed for codegen_nav which will call updateDecl and then the
-        // codegen backend wants full access to the Decl Type.
-        // We also need this for the `isFnOrHasRuntimeBits` check below.
-        // TODO: we could make the language more lenient by deferring this work
-        // to the `codegen_nav` job.
-        try decl_ty.resolveFully(pt);
+        if (resolve_type) {
+            // Needed for codegen_nav which will call updateDecl and then the
+            // codegen backend wants full access to the Decl Type.
+            // We also need this for the `isFnOrHasRuntimeBits` check below.
+            // TODO: we could make the language more lenient by deferring this work
+            // to the `codegen_nav` job.
+            try decl_ty.resolveFully(pt);
+        }
 
-        if (!decl_ty.isFnOrHasRuntimeBits(pt)) {
+        if (!resolve_type or !decl_ty.hasRuntimeBits(pt)) {
             if (zcu.comp.config.use_llvm) break :queue_codegen;
             if (file.mod.strip) break :queue_codegen;
         }
test/src/Debugger.zig
@@ -587,7 +587,7 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {
         },
     );
     db.addLldbTest(
-        "cross_module_call",
+        "inline_call",
         target,
         &.{
             .{
@@ -595,8 +595,18 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {
                 .source =
                 \\const module = @import("module");
                 \\pub fn main() void {
-                \\    module.foo(123);
-                \\    module.bar(456);
+                \\    fa(12);
+                \\    fb(34);
+                \\    module.fc(56);
+                \\    module.fd(78);
+                \\}
+                \\fn fa(pa: u32) void {
+                \\    const la = ~pa;
+                \\    _ = la;
+                \\}
+                \\inline fn fb(pb: u32) void {
+                \\    const lb = ~pb;
+                \\    _ = lb;
                 \\}
                 \\
                 ,
@@ -605,34 +615,84 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {
                 .import = "module",
                 .path = "module.zig",
                 .source =
-                \\pub fn foo(x: u32) void {
-                \\    _ = x;
+                \\pub fn fc(pc: u32) void {
+                \\    const lc = ~pc;
+                \\    _ = lc;
                 \\}
-                \\pub inline fn bar(y: u32) void {
-                \\    _ = y;
+                \\pub inline fn fd(pd: u32) void {
+                \\    const ld = ~pd;
+                \\    _ = ld;
                 \\}
                 \\
                 ,
             },
         },
-        \\breakpoint set --file module.zig --source-pattern-regexp '_ = x;'
+        \\settings set frame-format 'frame #${frame.index}:{ ${module.file.basename}{\`${function.name-with-args}{${frame.no-debug}${function.pc-offset}}}}{ at ${line.file.basename}:${line.number}{:${line.column}}}{${function.is-optimized} [opt]}{${frame.is-artificial} [artificial]}\n'
+        \\
+        \\breakpoint set --file main.zig --source-pattern-regexp '_ = la;'
         \\process launch
-        \\source info
+        \\frame variable pa la
+        \\thread backtrace --count 2
         \\breakpoint delete --force 1
         \\
-        \\breakpoint set --file module.zig --line 5
+        \\breakpoint set --file main.zig --source-pattern-regexp '_ = lb;'
         \\process continue
-        \\source info
+        \\frame variable pb lb
+        \\thread backtrace --count 2
         \\breakpoint delete --force 2
+        \\
+        \\breakpoint set --file module.zig --source-pattern-regexp '_ = lc;'
+        \\process continue
+        \\frame variable pc lc
+        \\thread backtrace --count 2
+        \\breakpoint delete --force 3
+        \\
+        \\breakpoint set --file module.zig --line 7
+        \\process continue
+        \\frame variable pd ld
+        \\thread backtrace --count 2
+        \\breakpoint delete --force 4
     ,
         &.{
-            \\/module.zig:2:5
+            \\(lldb) frame variable pa la
+            \\(u32) pa = 12
+            \\(u32) la = 4294967283
+            \\(lldb) thread backtrace --count 2
+            \\* thread #1, name = 'inline_call', stop reason = breakpoint 1.1
+            \\  * frame #0: inline_call`main.fa(pa=12) at main.zig:10:5
+            \\    frame #1: inline_call`main.main at main.zig:3:7
             \\(lldb) breakpoint delete --force 1
             \\1 breakpoints deleted; 0 breakpoint locations disabled.
             ,
-            \\/module.zig:5:5
+            \\(lldb) frame variable pb lb
+            \\(u32) pb = 34
+            \\(u32) lb = 4294967261
+            \\(lldb) thread backtrace --count 2
+            \\* thread #1, name = 'inline_call', stop reason = breakpoint 2.1
+            \\  * frame #0: inline_call`main.main [inlined] fb(pb=34) at main.zig:14:5
+            \\    frame #1: inline_call`main.main at main.zig:4:7
             \\(lldb) breakpoint delete --force 2
             \\1 breakpoints deleted; 0 breakpoint locations disabled.
+            ,
+            \\(lldb) frame variable pc lc
+            \\(u32) pc = 56
+            \\(u32) lc = 4294967239
+            \\(lldb) thread backtrace --count 2
+            \\* thread #1, name = 'inline_call', stop reason = breakpoint 3.1
+            \\  * frame #0: inline_call`module.fc(pc=56) at module.zig:3:5
+            \\    frame #1: inline_call`main.main at main.zig:5:14
+            \\(lldb) breakpoint delete --force 3
+            \\1 breakpoints deleted; 0 breakpoint locations disabled.
+            ,
+            \\(lldb) frame variable pd ld
+            \\(u32) pd = 78
+            \\(u32) ld = 4294967217
+            \\(lldb) thread backtrace --count 2
+            \\* thread #1, name = 'inline_call', stop reason = breakpoint 4.1
+            \\  * frame #0: inline_call`main.main [inlined] fd(pd=78) at module.zig:7:5
+            \\    frame #1: inline_call`main.main at main.zig:6:14
+            \\(lldb) breakpoint delete --force 4
+            \\1 breakpoints deleted; 0 breakpoint locations disabled.
         },
     );
 }