authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-09-01 12:58:19-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-09-03 12:59:38-04:00
logdd01fe96d36a7cf898f04a55b820174d76588a32
tree7d6e9b5bb22df174c00b883a4d5570c13cd8f53c
parent3939c4f5b56a6f3440d98e1c5f6dbf4a1e6ccdce

Dwarf2: track function resolution for deterministic ies debug info

Avoid calling `funcIesResolvedUnordered` before the frontend is guaranteed to have set it.

2 files changed, 24 insertions(+), 5 deletions(-)

src/link/Dwarf2.zig+18-5
...@@ -120,10 +120,13 @@ pub const Global = struct {...@@ -120,10 +120,13 @@ pub const Global = struct {
120};120};
121121
122pub const Func = struct {122pub const Func = struct {
123 state: State,
123 fde_ni: MappedFile.Node.Index.Optional,124 fde_ni: MappedFile.Node.Index.Optional,
124 debug_info_ni: MappedFile.Node.Index.Optional,125 debug_info_ni: MappedFile.Node.Index.Optional,
125 debug_line_ni: MappedFile.Node.Index.Optional,126 debug_line_ni: MappedFile.Node.Index.Optional,
126127
128 pub const State = enum { unresolved, resolved };
129
127 pub const Index = enum(u32) {130 pub const Index = enum(u32) {
128 _,131 _,
129132
...@@ -1419,6 +1422,7 @@ pub fn getFunc(dwarf: *Dwarf, nav: InternPool.Nav.Index) link.Error!Func.Index {...@@ -1419,6 +1422,7 @@ pub fn getFunc(dwarf: *Dwarf, nav: InternPool.Nav.Index) link.Error!Func.Index {
1419 const gpa = comp.gpa;1422 const gpa = comp.gpa;
1420 const func_gop = try dwarf.funcs.getOrPut(gpa, nav);1423 const func_gop = try dwarf.funcs.getOrPut(gpa, nav);
1421 if (!func_gop.found_existing) func_gop.value_ptr.* = .{1424 if (!func_gop.found_existing) func_gop.value_ptr.* = .{
1425 .state = .unresolved,
1422 .fde_ni = .none,1426 .fde_ni = .none,
1423 .debug_info_ni = .none,1427 .debug_info_ni = .none,
1424 .debug_line_ni = .none,1428 .debug_line_ni = .none,
...@@ -1975,7 +1979,10 @@ pub fn updateComptimeNav(...@@ -1975,7 +1979,10 @@ pub fn updateComptimeNav(
1975 .func => |func| if (func.owner_nav == nav_index and func.generic_owner == .none) {1979 .func => |func| if (func.owner_nav == nav_index and func.generic_owner == .none) {
1976 const fi = try dwarf.getFunc(func.owner_nav);1980 const fi = try dwarf.getFunc(func.owner_nav);
1977 const f = fi.get(dwarf);1981 const f = fi.get(dwarf);
1978 if (f.fde_ni != .none or f.debug_line_ni != .none) return;1982 switch (f.state) {
1983 .unresolved => {},
1984 .resolved => return,
1985 }
1979 const elf = dwarf.lf.cast(.elf2).?;1986 const elf = dwarf.lf.cast(.elf2).?;
1980 const debug_info_ni = f.debug_info_ni.unwrap().?;1987 const debug_info_ni = f.debug_info_ni.unwrap().?;
1981 var di_nw: MappedFile.Node.Writer = undefined;1988 var di_nw: MappedFile.Node.Writer = undefined;
...@@ -2837,7 +2844,14 @@ fn updateConstInner(...@@ -2837,7 +2844,14 @@ fn updateConstInner(
2837 defer zcu.gpa.free(name);2844 defer zcu.gpa.free(name);
2838 try diw.writeUleb128(try dwarf.refAbbrevCode(.inferred_error_set_type));2845 try diw.writeUleb128(try dwarf.refAbbrevCode(.inferred_error_set_type));
2839 try dwarf.strp(&dwarf.debug_str, di_nw, name);2846 try dwarf.strp(&dwarf.debug_str, di_nw, name);
2840 try dwarf.refType(pt, di_nw, switch (ip.funcIesResolvedUnordered(func)) {2847 try dwarf.refType(pt, di_nw, switch (ies: {
2848 const fi = dwarf.getFuncIfExists(ip.indexToKey(func).func.owner_nav) orelse
2849 break :ies .none;
2850 break :ies switch (fi.get(dwarf).state) {
2851 .unresolved => .none,
2852 .resolved => ip.funcIesResolvedUnordered(func),
2853 };
2854 }) {
2841 .none => .anyerror,2855 .none => .anyerror,
2842 else => |ies| .fromInterned(ies),2856 else => |ies| .fromInterned(ies),
2843 });2857 });
...@@ -3563,10 +3577,9 @@ fn exprLoc(dwarf: *Dwarf, nw: *MappedFile.Node.Writer, loc: Loc) link.EmitError!...@@ -3563,10 +3577,9 @@ fn exprLoc(dwarf: *Dwarf, nw: *MappedFile.Node.Writer, loc: Loc) link.EmitError!
35633577
3564fn strp(dwarf: *Dwarf, s: *Str, nw: *MappedFile.Node.Writer, str: []const u8) link.EmitError!void {3578fn strp(dwarf: *Dwarf, s: *Str, nw: *MappedFile.Node.Writer, str: []const u8) link.EmitError!void {
3565 const comp = dwarf.lf.comp;3579 const comp = dwarf.lf.comp;
3566 const mf = &dwarf.lf.cast(.elf2).?.mf;3580 try dwarf.secOffset(nw, s.ni.unwrap().?, s.get(comp.gpa, nw.mf, str) catch |err| switch (err) {
3567 try dwarf.secOffset(nw, s.ni.unwrap().?, s.get(comp.gpa, mf, str) catch |err| switch (err) {
3568 error.MappedFileIo => return comp.link_diags.fail("failed to write output file: {t}", .{3581 error.MappedFileIo => return comp.link_diags.fail("failed to write output file: {t}", .{
3569 mf.io_err.?,3582 nw.mf.io_err.?,
3570 }),3583 }),
3571 else => |e| return e,3584 else => |e| return e,
3572 });3585 });
src/link/Elf2.zig+6
...@@ -8926,6 +8926,7 @@ fn updateFuncInner(...@@ -8926,6 +8926,7 @@ fn updateFuncInner(
8926 debug.pt = pt;8926 debug.pt = pt;
8927 debug.any_children = false;8927 debug.any_children = false;
8928 debug.blocks = .empty;8928 debug.blocks = .empty;
8929 dwarf_func.state = .resolved;
89298930
8930 const debug_info_ni = dwarf_func.debug_info_ni.unwrap().?;8931 const debug_info_ni = dwarf_func.debug_info_ni.unwrap().?;
8931 try dwarf.decls.put(zcu.comp.gpa, src_inst, .{8932 try dwarf.decls.put(zcu.comp.gpa, src_inst, .{
...@@ -9020,6 +9021,11 @@ fn updateFuncInner(...@@ -9020,6 +9021,11 @@ fn updateFuncInner(
9020 );9021 );
9021 }9022 }
9022 debug.wip_nav.finishDebugFrameFde(func_length);9023 debug.wip_nav.finishDebugFrameFde(func_length);
9024 if (func.analysisUnordered(ip).inferred_error_set) {
9025 const ies = ip.getIfExists(.{ .inferred_error_set_type = func_index }).?;
9026 if (elf.dwarf.const_pool.getIfExists(ies)) |cpi|
9027 try elf.updateConstInner(pt, cpi, ies);
9028 }
9023 },9029 },
9024 .none => {},9030 .none => {},
9025 }9031 }