authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-08-12 22:46:34-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-09-03 12:59:38-04:00
log3dd202df0101e9ac9380a1aa5a813555241e8c3d
treeac3e5b0637fc3c5eb5e24412161b33b08839c325
parentfd9f45c358837b0091b795fad1c75f4efc8f4fc4

Dwarf2: implement enough debug info for incremental line info to work


6 files changed, 379 insertions(+), 141 deletions(-)

src/Compilation.zig+8-1
......@@ -3710,8 +3710,15 @@ pub fn saveState(comp: *Compilation) !void {
37103710
37113711 // linker state
37123712 switch (lf.tag) {
3713 .elf => {},
3714 .elf2 => {
3715 const elf = lf.cast(.elf2).?;
3716 try bufs.ensureUnusedCapacity(3);
3717 addBuf(&bufs, @ptrCast(elf.mf.nodes.items));
3718 addBuf(&bufs, @ptrCast(&elf.mf.free_ni));
3719 addBuf(&bufs, @ptrCast(elf.mf.large.items));
3720 },
37133721 .wasm => {
3714 dev.check(link.File.Tag.wasm.devFeature());
37153722 const wasm = lf.cast(.wasm).?;
37163723 const is_obj = comp.config.output_mode == .Obj;
37173724 try bufs.ensureUnusedCapacity(85);
src/codegen/llvm.zig+2-2
......@@ -1431,7 +1431,7 @@ pub const Object = struct {
14311431
14321432 pub fn getDebugType(o: *Object, pt: Zcu.PerThread, ty: Type) Allocator.Error!Builder.Metadata {
14331433 assert(!o.builder.strip);
1434 const index = try o.type_pool.get(pt, .{ .llvm = o }, ty.toIntern());
1434 const index = o.type_pool.get(pt, .{ .llvm = o }, ty.toIntern()) catch |err| return @errorCast(err);
14351435 return o.debug_types.items[@backingInt(index)];
14361436 }
14371437
......@@ -4108,7 +4108,7 @@ pub const Object = struct {
41084108 }
41094109
41104110 pub fn lazyAbiAlignment(o: *Object, pt: Zcu.PerThread, ty: Type) Allocator.Error!Builder.Alignment.Lazy {
4111 const index = try o.type_pool.get(pt, .{ .llvm = o }, ty.toIntern());
4111 const index = o.type_pool.get(pt, .{ .llvm = o }, ty.toIntern()) catch |err| return @errorCast(err);
41124112 return o.lazy_abi_aligns.items[@backingInt(index)];
41134113 }
41144114
src/link/C.zig+3-3
......@@ -209,7 +209,7 @@ pub fn addConst(
209209 pt: Zcu.PerThread,
210210 pool_index: link.ConstPool.Index,
211211 val: InternPool.Index,
212) Allocator.Error!void {
212) link.Error!void {
213213 const zcu = pt.zcu;
214214 const gpa = zcu.comp.gpa;
215215 assert(zcu.intern_pool.typeOf(val) == .type_type);
......@@ -310,7 +310,7 @@ pub fn updateConst(
310310 pt: Zcu.PerThread,
311311 index: link.ConstPool.Index,
312312 val: InternPool.Index,
313) Allocator.Error!void {
313) link.Error!void {
314314 const zcu = pt.zcu;
315315 const gpa = zcu.comp.gpa;
316316
......@@ -1344,7 +1344,7 @@ fn addCTypeDependencies(
13441344 c: *C,
13451345 pt: Zcu.PerThread,
13461346 deps: *const codegen.CType.Dependencies,
1347) Allocator.Error!CTypeDependencies {
1347) link.Error!CTypeDependencies {
13481348 const gpa = pt.zcu.comp.gpa;
13491349
13501350 try c.bigint_types.ensureUnusedCapacity(gpa, deps.bigint.count());
src/link/ConstPool.zig+2-2
......@@ -59,7 +59,7 @@ pub const User = union(enum) {
5959 pt: Zcu.PerThread,
6060 index: Index,
6161 val: InternPool.Index,
62 ) Allocator.Error!void {
62 ) link.Error!void {
6363 switch (user) {
6464 inline else => |impl| return impl.addConst(pt, index, val),
6565 }
......@@ -144,7 +144,7 @@ pub fn updateContainerType(
144144
145145/// After this is called, there may be a constant for which debug information (complete or not) has
146146/// not yet been emitted, so the user must call `flushPending` at some point after this call.
147pub fn get(pool: *ConstPool, pt: Zcu.PerThread, user: User, val: InternPool.Index) Allocator.Error!ConstPool.Index {
147pub fn get(pool: *ConstPool, pt: Zcu.PerThread, user: User, val: InternPool.Index) link.Error!ConstPool.Index {
148148 const zcu = pt.zcu;
149149 const ip = &zcu.intern_pool;
150150 const gpa = zcu.comp.gpa;
src/link/Dwarf2.zig+260-61
......@@ -6,7 +6,7 @@ const_pool: link.ConstPool,
66
77units: std.array_hash_map.Auto(*Module, Unit),
88/// Indices are `link.ConstPool.Index`.
9values: std.ArrayList(Value),
9consts: std.ArrayList(Const),
1010globals: std.array_hash_map.Auto(InternPool.Nav.Index, Global),
1111funcs: std.array_hash_map.Auto(InternPool.Nav.Index, Func),
1212decls: std.array_hash_map.Auto(InternPool.TrackedInst.Index, MappedFile.Node.Index),
......@@ -92,20 +92,12 @@ pub const Unit = struct {
9292 }
9393};
9494
95pub const Value = struct {
96 debug_info_ni: MappedFile.Node.Index,
97
98 pub const Index = enum(u32) {
99 _,
100
101 pub fn cpi(vi: Value.Index, dwarf: *Dwarf) link.ConstPool.Index {
102 return dwarf.values[@backingInt(vi)];
103 }
95pub const Const = struct {
96 debug_info_ni: MappedFile.Node.Index.Optional,
10497
105 pub fn get(vi: Value.Index, dwarf: *Dwarf) *Global {
106 return &dwarf.values[@backingInt(vi)];
107 }
108 };
98 pub fn get(cpi: link.ConstPool.Index, dwarf: *Dwarf) *Const {
99 return &dwarf.consts.items[@backingInt(cpi)];
100 }
109101};
110102
111103pub const Global = struct {
......@@ -626,14 +618,14 @@ pub const WipNav = struct {
626618 return debug.wip_nav.genDebugFrame(loc, cfa);
627619 }
628620
629 pub fn startDebugInfo(debug: *Debug) link.Error!void {
621 pub fn startFuncDebugInfo(debug: *Debug) link.Error!void {
630622 assert(debug.wip_nav.func != .none);
631 debug.startDebugInfoInner() catch |err| switch (err) {
623 debug.startFuncDebugInfoInner() catch |err| switch (err) {
632624 error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.info_writer),
633625 else => |e| return e,
634626 };
635627 }
636 fn startDebugInfoInner(debug: *Debug) link.EmitError!void {
628 fn startFuncDebugInfoInner(debug: *Debug) link.EmitError!void {
637629 const dwarf = debug.wip_nav.dwarf;
638630 const zcu = debug.pt.zcu;
639631 const ip = &zcu.intern_pool;
......@@ -644,6 +636,7 @@ pub const WipNav = struct {
644636 const nav = ip.getNav(func.owner_nav);
645637 const diw = &debug.info_writer.interface;
646638 try diw.writeUleb128(try dwarf.refAbbrevCode(.decl_func));
639 try debug.refType(.fromInterned(zcu.fileRootType(inst_info.file)));
647640 try diw.writeInt(u32, decl.src_line + 1, dwarf.endian);
648641 try diw.writeUleb128(decl.src_column + 1);
649642 try diw.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private);
......@@ -730,7 +723,7 @@ pub const WipNav = struct {
730723 debug: *Debug,
731724 tag: LocalVarTag,
732725 opt_name: ?[]const u8,
733 ty: ZigType,
726 ty: Type,
734727 loc: Loc,
735728 ) link.Error!void {
736729 return debug.genLocalVarDebugInfoInner(tag, opt_name, ty, loc) catch |err| switch (err) {
......@@ -742,7 +735,7 @@ pub const WipNav = struct {
742735 debug: *Debug,
743736 tag: LocalVarTag,
744737 opt_name: ?[]const u8,
745 ty: ZigType,
738 ty: Type,
746739 loc: Loc,
747740 ) link.EmitError!void {
748741 assert(debug.wip_nav.func != .none);
......@@ -761,7 +754,7 @@ pub const WipNav = struct {
761754 debug: *Debug,
762755 tag: LocalConstTag,
763756 opt_name: ?[]const u8,
764 val: ZigValue,
757 val: Value,
765758 ) link.Error!void {
766759 return debug.genLocalConstDebugInfoInner(tag, opt_name, val) catch |err| switch (err) {
767760 error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.info_writer),
......@@ -772,7 +765,7 @@ pub const WipNav = struct {
772765 debug: *Debug,
773766 tag: LocalConstTag,
774767 opt_name: ?[]const u8,
775 val: ZigValue,
768 val: Value,
776769 ) link.EmitError!void {
777770 assert(debug.wip_nav.func != .none);
778771 const zcu = debug.pt.zcu;
......@@ -1059,11 +1052,11 @@ pub const WipNav = struct {
10591052
10601053 const old_owner_nav = zcu.funcInfo(debug.wip_nav.func).owner_nav;
10611054 const old_inst_info = ip.getNav(old_owner_nav).srcInst(ip).resolveFull(ip).?;
1062 const old_file = zcu.fileByIndex(old_inst_info.file);
1055 const old_zf = zcu.fileByIndex(old_inst_info.file);
10631056 const new_inst_info = ip.getNav(new_owner_nav).srcInst(ip).resolveFull(ip).?;
1064 const new_file = zcu.fileByIndex(new_inst_info.file);
1057 const new_zf = zcu.fileByIndex(new_inst_info.file);
10651058 if (old_inst_info.file != new_inst_info.file) {
1066 const new_ui = dwarf.getUnit(new_file.mod.?);
1059 const new_ui = dwarf.getUnit(new_zf.mod.?);
10671060 _, const new_fi =
10681061 try debug.wip_nav.unit.get(dwarf).getFile(zcu.gpa, new_ui, new_inst_info.file);
10691062
......@@ -1071,8 +1064,8 @@ pub const WipNav = struct {
10711064 try dlw.writeUleb128(@backingInt(new_fi));
10721065 }
10731066
1074 const old_src_line: i33 = old_file.zir.?.getDeclaration(old_inst_info.inst).src_line;
1075 const new_src_line: i33 = new_file.zir.?.getDeclaration(new_inst_info.inst).src_line;
1067 const old_src_line: i33 = old_zf.zir.?.getDeclaration(old_inst_info.inst).src_line;
1068 const new_src_line: i33 = new_zf.zir.?.getDeclaration(new_inst_info.inst).src_line;
10761069 if (new_src_line != old_src_line) {
10771070 try dlw.writeByte(DW.LNS.advance_line);
10781071 try dlw.writeSleb128(new_src_line - old_src_line);
......@@ -1137,27 +1130,21 @@ pub const WipNav = struct {
11371130 );
11381131 }
11391132
1140 fn refType(debug: *Debug, ty: ZigType) link.EmitError!void {
1133 fn refType(debug: *Debug, ty: Type) link.EmitError!void {
11411134 return debug.refValue(ty.toValue());
11421135 }
11431136
1144 fn refValue(debug: *Debug, value: ZigValue) link.EmitError!void {
1145 try debug.wip_nav.dwarf.sectionOffset(&debug.info_writer, try debug.getValueNode(value), 0);
1146 }
1147
1148 fn getValueNode(debug: *Debug, value: ZigValue) link.Error!MappedFile.Node.Index {
1149 const zcu = debug.pt.zcu;
1150 if (value.typeOf(zcu).toIntern() != .type_type) {
1151 assert(value.typeOf(zcu).comptimeOnly(zcu));
1152 }
1137 fn refValue(debug: *Debug, val: Value) link.EmitError!void {
11531138 const dwarf = debug.wip_nav.dwarf;
1154 const index = try dwarf.const_pool.get(debug.pt, .{
1155 .elf2 = dwarf.lf.cast(.elf2).?,
1156 }, value.toIntern());
1157 return dwarf.values.items[@backingInt(index)].debug_info_ni;
1139 const cpi = try dwarf.getConst(debug.pt, val);
1140 try dwarf.sectionOffset(
1141 &debug.info_writer,
1142 Const.get(cpi, dwarf).debug_info_ni.unwrap().?,
1143 0,
1144 );
11581145 }
11591146
1160 fn blockValue(debug: *Debug, val: ZigValue) link.EmitError!void {
1147 fn blockValue(debug: *Debug, val: Value) link.EmitError!void {
11611148 const ty = val.typeOf(debug.pt.zcu);
11621149 const diw = &debug.info_writer.interface;
11631150 const size = ty.abiSize(debug.pt.zcu);
......@@ -1355,7 +1342,7 @@ pub fn init(lf: *link.File, format: DW.Format) Dwarf {
13551342 .const_pool = .empty,
13561343
13571344 .units = .empty,
1358 .values = .empty,
1345 .consts = .empty,
13591346 .globals = .empty,
13601347 .funcs = .empty,
13611348 .decls = .empty,
......@@ -1429,9 +1416,10 @@ pub fn deinit(dwarf: *Dwarf) void {
14291416 dwarf.const_pool.deinit(gpa);
14301417 for (dwarf.units.values()) |*unit| unit.deinit(gpa);
14311418 dwarf.units.deinit(gpa);
1432 dwarf.values.deinit(gpa);
1419 dwarf.consts.deinit(gpa);
14331420 dwarf.globals.deinit(gpa);
14341421 dwarf.funcs.deinit(gpa);
1422 dwarf.decls.deinit(gpa);
14351423 dwarf.debug_line_str.map.deinit(gpa);
14361424 dwarf.debug_str.map.deinit(gpa);
14371425 dwarf.* = undefined;
......@@ -1471,6 +1459,13 @@ pub fn getUnit(dwarf: *Dwarf, mod: *Module) Unit.Index {
14711459 return @fromBackingInt(@intCast(dwarf.units.getIndex(mod).?));
14721460}
14731461
1462pub fn getConst(dwarf: *Dwarf, pt: Zcu.PerThread, val: Value) link.Error!link.ConstPool.Index {
1463 const zcu = pt.zcu;
1464 const ty = val.typeOf(zcu);
1465 if (ty.toIntern() != .type_type) assert(ty.comptimeOnly(zcu));
1466 return dwarf.const_pool.get(pt, .{ .elf2 = dwarf.lf.cast(.elf2).? }, val.toIntern());
1467}
1468
14741469pub fn getGlobal(dwarf: *Dwarf, nav: InternPool.Nav.Index) link.Error!Global.Index {
14751470 const comp = dwarf.lf.comp;
14761471 const gpa = comp.gpa;
......@@ -1483,10 +1478,9 @@ pub fn getGlobal(dwarf: *Dwarf, nav: InternPool.Nav.Index) link.Error!Global.Ind
14831478 const elf = dwarf.lf.cast(.elf2).?;
14841479 try elf.nodes.ensureUnusedCapacity(gpa, 1);
14851480 try elf.dwarf_globals.ensureUnusedCapacity(gpa, 1);
1486 const unit = dwarf.getUnit(comp.zcu.?.zcu.navFileScope(nav).mod.?).get(dwarf);
1487 assert(unit.debug_info_ni != .none);
1488 global_gop.value_ptr.debug_info_ni = elf.addNodeAssumeCapacity(
1489 elf.mf.addLastChildNode(gpa, unit.debug_info_ni, .{
1481 const unit = dwarf.getUnit(comp.zcu.?.navFileScope(nav).mod.?).get(dwarf);
1482 global_gop.value_ptr.debug_info_ni = .wrap(elf.addNodeAssumeCapacity(
1483 unit.debug_info_ni.unwrap().?.addFloatingChild(gpa, &elf.mf, .{
14901484 .enable_next_moved = true,
14911485 }) catch |err| switch (err) {
14921486 else => |e| return e,
......@@ -1495,7 +1489,7 @@ pub fn getGlobal(dwarf: *Dwarf, nav: InternPool.Nav.Index) link.Error!Global.Ind
14951489 }),
14961490 },
14971491 .{ .global_debug_info = gi },
1498 );
1492 ));
14991493 elf.dwarf_globals.addOneAssumeCapacity().* = .{
15001494 .debug_info_first_target_reloc = .none,
15011495 .debug_info_first_node_reloc = .none,
......@@ -1773,7 +1767,6 @@ pub fn genDebugInfoPadding(dwarf: *Dwarf, diw: *Writer, size: u64) Writer.Error!
17731767
17741768pub fn genDebugLineHeader(
17751769 dwarf: *Dwarf,
1776 mod: *Module,
17771770 unit: *Unit,
17781771 dlh_nw: *MappedFile.Node.Writer,
17791772 zcu: *Zcu,
......@@ -1817,7 +1810,7 @@ pub fn genDebugLineHeader(
18171810 try dlhw.writeByte(1);
18181811 try dlhw.writeUleb128(DW.LNCT.path);
18191812 try dlhw.writeUleb128(DW.FORM.line_strp);
1820 const dir_count = 1;
1813 const dir_count = unit.dirs.count();
18211814 const directory_index_form: DeclValEnum(DW.FORM) = if (dir_count <= 1 << 8)
18221815 .data1
18231816 else if (dir_count <= 1 << 16)
......@@ -1825,8 +1818,8 @@ pub fn genDebugLineHeader(
18251818 else
18261819 .udata;
18271820 try dlhw.writeUleb128(dir_count);
1828 {
1829 const root_dir_path = try mod.root.toAbsolute(&zcu.comp.dirs, comp.gpa);
1821 for (unit.dirs.keys()) |ui| {
1822 const root_dir_path = try ui.mod(dwarf).root.toAbsolute(&zcu.comp.dirs, comp.gpa);
18301823 defer comp.gpa.free(root_dir_path);
18311824 try dwarf.strp(&dwarf.debug_line_str, dlh_nw, root_dir_path);
18321825 }
......@@ -1845,11 +1838,12 @@ pub fn genDebugLineHeader(
18451838 for (unit.files.keys()) |zfi| {
18461839 const zf = zcu.fileByIndex(zfi);
18471840 try dwarf.strp(&dwarf.debug_line_str, dlh_nw, zf.sub_file_path);
1841 const di = unit.dirs.getIndex(dwarf.getUnit(zf.mod.?)).?;
18481842 switch (directory_index_form) {
18491843 else => unreachable,
1850 .data1 => try dlhw.writeByte(0),
1851 .data2 => try dlhw.writeInt(u16, 0, dwarf.endian),
1852 .udata => try dlhw.writeUleb128(0),
1844 .data1 => try dlhw.writeByte(@intCast(di)),
1845 .data2 => try dlhw.writeInt(u16, @intCast(di), dwarf.endian),
1846 .udata => try dlhw.writeUleb128(di),
18531847 }
18541848 try dlhw.writeInt(i64, @truncate(zf.stat.mtime.nanoseconds), dwarf.endian);
18551849 try dlhw.writeInt(u64, zf.stat.size, dwarf.endian);
......@@ -1938,6 +1932,209 @@ pub fn genDebugRnglists(
19381932 try drw.writeByte(DW.RLE.end_of_list);
19391933}
19401934
1935pub fn updateComptimeNav(
1936 dwarf: *Dwarf,
1937 pt: Zcu.PerThread,
1938 nav_index: InternPool.Nav.Index,
1939) link.Error!void {
1940 const zcu = dwarf.lf.comp.zcu.?;
1941 const ip = &zcu.intern_pool;
1942 const nav = ip.getNav(nav_index);
1943 const inst_info = nav.srcInst(ip).resolveFull(ip).?;
1944 const nav_val: Value = .fromInterned(nav.resolved.?.value);
1945 const file = zcu.fileByIndex(inst_info.file);
1946 const zir = &file.zir.?;
1947 const decl = zir.getDeclaration(inst_info.inst);
1948 switch (decl.kind) {
1949 .unnamed_test, .@"test", .decltest => return,
1950 .@"comptime", .@"const", .@"var" => {},
1951 }
1952 emit: switch (ip.indexToKey(nav_val.toIntern())) {
1953 .struct_type => {
1954 const loaded_struct = ip.loadStructType(nav_val.toIntern());
1955 if (nav_index.toOptional() == loaded_struct.name_nav) {
1956 _ = try dwarf.const_pool.get(pt, .{ .elf2 = dwarf.lf.cast(.elf2).? }, nav_val.toIntern());
1957 break :emit;
1958 }
1959 },
1960 .enum_type => {
1961 const loaded_enum = ip.loadEnumType(nav_val.toIntern());
1962 if (nav_index.toOptional() == loaded_enum.name_nav) {
1963 _ = try dwarf.const_pool.get(pt, .{ .elf2 = dwarf.lf.cast(.elf2).? }, nav_val.toIntern());
1964 break :emit;
1965 }
1966 },
1967 .union_type => {
1968 const loaded_union = ip.loadUnionType(nav_val.toIntern());
1969 if (nav_index.toOptional() == loaded_union.name_nav) {
1970 _ = try dwarf.const_pool.get(pt, .{ .elf2 = dwarf.lf.cast(.elf2).? }, nav_val.toIntern());
1971 break :emit;
1972 }
1973 },
1974 .opaque_type => {
1975 const loaded_opaque = ip.loadOpaqueType(nav_val.toIntern());
1976 if (nav_index.toOptional() == loaded_opaque.name_nav) {
1977 _ = try dwarf.const_pool.get(pt, .{ .elf2 = dwarf.lf.cast(.elf2).? }, nav_val.toIntern());
1978 break :emit;
1979 }
1980 },
1981 .func => |func| if (func.owner_nav == nav_index and func.generic_owner == .none) {
1982 const fi = try dwarf.getFunc(func.owner_nav);
1983 const f = fi.get(dwarf);
1984 if (f.fde_ni != .none or f.debug_line_ni != .none) return;
1985 var di_nw: MappedFile.Node.Writer = undefined;
1986 f.debug_info_ni.unwrap().?.writer(zcu.gpa, &dwarf.lf.cast(.elf2).?.mf, &di_nw);
1987 defer di_nw.deinit();
1988 const parent_cpi = try dwarf.getConst(pt, .fromInterned(zcu.fileRootType(inst_info.file)));
1989 dwarf.genDeclFuncGeneric(
1990 &di_nw,
1991 zir,
1992 parent_cpi,
1993 &decl,
1994 &ip.indexToKey(func.ty).func_type,
1995 nav.name.toSlice(ip),
1996 zir.getParamBody(func.zir_body_inst.resolve(ip).?),
1997 ) catch |err| switch (err) {
1998 else => |e| return e,
1999 error.WriteFailed => return dwarf.reportWriteError(&di_nw),
2000 };
2001 } else return,
2002
2003 else => return,
2004
2005 // memoization, not values
2006 .memoized_call => unreachable,
2007 }
2008 try dwarf.const_pool.flushPending(pt, .{ .elf2 = dwarf.lf.cast(.elf2).? });
2009}
2010fn genDeclFuncGeneric(
2011 dwarf: *Dwarf,
2012 di_nw: *MappedFile.Node.Writer,
2013 zir: *const std.zig.Zir,
2014 parent_cpi: link.ConstPool.Index,
2015 decl: *const std.zig.Zir.Inst.Declaration.Unwrapped,
2016 fn_ty: *const InternPool.Key.FuncType,
2017 name: []const u8,
2018 param_body: []const std.zig.Zir.Inst.Index,
2019) link.EmitError!void {
2020 const diw = &di_nw.interface;
2021 try diw.writeUleb128(try dwarf.refAbbrevCode(.decl_func_generic));
2022 try dwarf.sectionOffset(di_nw, Const.get(parent_cpi, dwarf).debug_info_ni.unwrap().?, 0);
2023 try diw.writeInt(u32, decl.src_line + 1, dwarf.endian);
2024 try diw.writeUleb128(decl.src_column + 1);
2025 try diw.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private);
2026 try dwarf.strp(&dwarf.debug_str, di_nw, name);
2027 for (param_body) |param_inst| switch (zir.getParamName(param_inst) orelse continue) {
2028 .empty => {
2029 try diw.writeUleb128(try dwarf.refAbbrevCode(.unnamed_arg));
2030 try diw.writeUleb128(0);
2031 },
2032 else => |param_name| {
2033 try diw.writeUleb128(try dwarf.refAbbrevCode(.arg));
2034 try dwarf.strp(&dwarf.debug_str, di_nw, zir.nullTerminatedString(param_name));
2035 try diw.writeUleb128(0);
2036 },
2037 };
2038 if (fn_ty.is_var_args) try diw.writeUleb128(try dwarf.refAbbrevCode(.is_var_args));
2039 try diw.writeUleb128(@backingInt(AbbrevCode.null));
2040 try dwarf.genDebugInfoPadding(diw, diw.unusedCapacityLen());
2041}
2042
2043pub fn addConst(dwarf: *Dwarf, cpi: link.ConstPool.Index, val: InternPool.Index) link.Error!void {
2044 const comp = dwarf.lf.comp;
2045 const zcu = comp.zcu.?;
2046 const ip = &zcu.intern_pool;
2047 try dwarf.consts.ensureUnusedCapacity(comp.gpa, 1);
2048
2049 assert(@backingInt(cpi) == dwarf.consts.items.len);
2050 dwarf.consts.appendAssumeCapacity(.{
2051 .debug_info_ni = switch (ip.indexToKey(val)) {
2052 else => .none,
2053 .struct_type, .union_type, .enum_type, .opaque_type => |_, tag| debug_info_ni: {
2054 if (switch (tag) {
2055 .struct_type => ip.loadStructType(val).name_nav,
2056 .union_type => ip.loadUnionType(val).name_nav,
2057 .enum_type => ip.loadEnumType(val).name_nav,
2058 .opaque_type => ip.loadOpaqueType(val).name_nav,
2059 else => unreachable,
2060 }.unwrap()) |name_nav| {
2061 const name_gi = try dwarf.getGlobal(name_nav);
2062 break :debug_info_ni name_gi.get(dwarf).debug_info_ni.unwrap().?;
2063 }
2064 const elf = dwarf.lf.cast(.elf2).?;
2065 try elf.nodes.ensureUnusedCapacity(comp.gpa, 1);
2066 try elf.dwarf_consts.ensureUnusedCapacity(comp.gpa, 1);
2067 const src_inst = Type.fromInterned(val).typeDeclInstAllowGeneratedTag(zcu).?;
2068 const unit = dwarf.getUnit(zcu.fileByIndex(src_inst.resolveFile(ip)).mod.?).get(dwarf);
2069 const debug_info_ni = elf.addNodeAssumeCapacity(
2070 unit.debug_info_ni.unwrap().?.addFloatingChild(comp.gpa, &elf.mf, .{
2071 .enable_next_moved = true,
2072 }) catch |err| switch (err) {
2073 else => |e| return e,
2074 error.MappedFileIo => return comp.link_diags.fail("failed to write output file: {t}", .{
2075 elf.mf.io_err.?,
2076 }),
2077 },
2078 .{ .const_debug_info = cpi },
2079 );
2080 elf.dwarf_consts.putAssumeCapacity(cpi, .{
2081 .debug_info_first_target_reloc = .none,
2082 .debug_info_first_symbol_reloc = .none,
2083 .debug_info_first_node_reloc = .none,
2084 });
2085
2086 break :debug_info_ni debug_info_ni;
2087 }.toOptional(),
2088 },
2089 });
2090}
2091
2092pub fn updateConst(dwarf: *Dwarf, cpi: link.ConstPool.Index, val: InternPool.Index) void {
2093 _ = dwarf;
2094 _ = cpi;
2095 _ = val;
2096}
2097
2098pub fn updateConstIncomplete(
2099 dwarf: *Dwarf,
2100 di_nw: *MappedFile.Node.Writer,
2101 val: InternPool.Index,
2102) link.Error!void {
2103 dwarf.updateConstIncompleteInner(di_nw, val) catch |err| switch (err) {
2104 else => |e| return e,
2105 error.WriteFailed => return dwarf.reportWriteError(di_nw),
2106 };
2107}
2108fn updateConstIncompleteInner(
2109 dwarf: *Dwarf,
2110 di_nw: *MappedFile.Node.Writer,
2111 val: InternPool.Index,
2112) link.EmitError!void {
2113 const comp = dwarf.lf.comp;
2114 const zcu = comp.zcu.?;
2115 const ip = &zcu.intern_pool;
2116 const diw = &di_nw.interface;
2117 emit: switch (ip.indexToKey(val)) {
2118 .struct_type => {
2119 const loaded_struct = ip.loadStructType(val);
2120 if (loaded_struct.zir_index.resolveFull(ip)) |src_inst| switch (src_inst.inst) {
2121 .main_struct_inst => {
2122 const ui = dwarf.getUnit(comp.zcu.?.fileByIndex(src_inst.file).mod.?);
2123 _, const fi = try ui.get(dwarf).getFile(comp.gpa, ui, src_inst.file);
2124 try diw.writeUleb128(try dwarf.refAbbrevCode(.empty_file));
2125 try diw.writeUleb128(@backingInt(fi));
2126 try dwarf.strp(&dwarf.debug_str, di_nw, loaded_struct.name.toSlice(ip));
2127 break :emit;
2128 },
2129 else => return,
2130 };
2131 return;
2132 },
2133 else => return,
2134 }
2135 try dwarf.genDebugInfoPadding(diw, diw.unusedCapacityLen());
2136}
2137
19412138pub fn updateLineNumber(
19422139 dwarf: *Dwarf,
19432140 mf: *MappedFile,
......@@ -2221,7 +2418,7 @@ pub const AbbrevCode = enum {
22212418 DeclValEnum(DW.FORM),
22222419 };
22232420 const decl_attrs = &[_]Attr{
2224 //.{ .ZIG_parent, .ref_addr },
2421 .{ .ZIG_parent, .ref_addr },
22252422 .{ .decl_line, .data4 },
22262423 .{ .decl_column, .udata },
22272424 .{ .accessibility, .data1 },
......@@ -2233,7 +2430,7 @@ pub const AbbrevCode = enum {
22332430 };
22342431
22352432 const decl_instance_attrs = &[_]Attr{
2236 //.{ .ZIG_parent, .ref_addr },
2433 .{ .ZIG_parent, .ref_addr },
22372434 .{ .specification, .ref_addr },
22382435 };
22392436
......@@ -2387,14 +2584,16 @@ pub const AbbrevCode = enum {
23872584 .decl_nullary_func_generic = .{
23882585 .tag = .subprogram,
23892586 .attrs = decl_attrs ++ .{
2390 .{ .type, .ref_addr },
2587 //.{ .type, .ref_addr },
2588 //.{ .noreturn, .flag },
23912589 },
23922590 },
23932591 .decl_func_generic = .{
23942592 .tag = .subprogram,
23952593 .children = true,
23962594 .attrs = decl_attrs ++ .{
2397 .{ .type, .ref_addr },
2595 //.{ .type, .ref_addr },
2596 //.{ .noreturn, .flag },
23982597 },
23992598 },
24002599 .decl_extern_nullary_func = .{
......@@ -3304,7 +3503,7 @@ const link = @import("../link.zig");
33043503const MappedFile = @import("MappedFile.zig");
33053504const Module = @import("../Module.zig");
33063505const std = @import("std");
3307const ZigType = @import("../Type.zig");
3308const ZigValue = @import("../Value.zig");
3506const Type = @import("../Type.zig");
3507const Value = @import("../Value.zig");
33093508const Writer = std.Io.Writer;
33103509const Zcu = @import("../Zcu.zig");
src/link/Elf2.zig+104-72
......@@ -224,7 +224,7 @@ dwarf_units: std.ArrayList(struct {
224224 debug_rnglists_first_target_reloc: NodeReloc.Index,
225225 debug_rnglists_symbol_relocs: std.array_hash_map.Auto(SymbolReloc.Index, void),
226226}),
227dwarf_values: std.ArrayList(struct {
227dwarf_consts: std.array_hash_map.Auto(link.ConstPool.Index, struct {
228228 debug_info_first_target_reloc: NodeReloc.Index,
229229 debug_info_first_symbol_reloc: SymbolReloc.Index,
230230 debug_info_first_node_reloc: NodeReloc.Index,
......@@ -318,7 +318,7 @@ const Node = union(enum) {
318318 unit_debug_line_header: Dwarf.Unit.Index,
319319 unit_debug_rnglists: Dwarf.Unit.Index,
320320
321 value_debug_info: link.ConstPool.Index,
321 const_debug_info: link.ConstPool.Index,
322322 global_debug_info: Dwarf.Global.Index,
323323 func_frame_fde: Dwarf.Func.Index,
324324 func_debug_info: Dwarf.Func.Index,
......@@ -1142,7 +1142,8 @@ const SymbolReloc = struct {
11421142 /// * An input section
11431143 /// * A section
11441144 /// * A NAV, UAV, or lazy code/data
1145 node: MappedFile.Node.Index,
1145 /// * `.none`, if this relocation was deleted (in which case it should be ignored)
1146 node: MappedFile.Node.Index.Optional,
11461147 /// The offset of the relocation inside of `node`.
11471148 offset: u64,
11481149 /// A symbol used to compute the relocated value. Precise meaning depends on `@"type"`.
......@@ -1182,7 +1183,7 @@ const SymbolReloc = struct {
11821183 /// because relocations in the GOTPLT are handled specially, without `SymbolReloc` entries.
11831184 fn relaSection(sr: *const SymbolReloc, elf: *Elf) Section.Index {
11841185 const shndx = switch (elf.ehdrType()) {
1185 .REL => elf.getNodeShndx(sr.node).get(elf).rela.shndx,
1186 .REL => elf.getNodeShndx(sr.node.unwrap().?).get(elf).rela.shndx,
11861187 .EXEC, .DYN => elf.shndx.rela_dyn,
11871188 };
11881189 assert(shndx != .UNDEF);
......@@ -1619,7 +1620,8 @@ const SymbolReloc = struct {
16191620
16201621 fn apply(reloc: *SymbolReloc, elf: *Elf) void {
16211622 assert(elf.ehdrType() != .REL);
1622 if (reloc.node.hasMoved(&elf.mf) or reloc.target.hasMoved(elf)) {
1623 const node = reloc.node.unwrap() orelse return; // deleted
1624 if (node.hasMoved(&elf.mf) or reloc.target.hasMoved(elf)) {
16231625 // There's no point applying the relocation now, because it will be re-applied by
16241626 // `flushMoved` at some point anyway.
16251627 return;
......@@ -1644,8 +1646,9 @@ const SymbolReloc = struct {
16441646 }
16451647 }
16461648 fn applyInner(reloc: *const SymbolReloc, elf: *Elf) error{ RelocationOverflow, RelocationMisaligned }!void {
1647 const dest_vaddr = elf.getNodeVAddr(reloc.node) + reloc.offset;
1648 const dest_slice = reloc.node.slice(&elf.mf)[@intCast(reloc.offset)..];
1649 const node = reloc.node.unwrap().?;
1650 const dest_vaddr = elf.getNodeVAddr(node) + reloc.offset;
1651 const dest_slice = node.slice(&elf.mf)[@intCast(reloc.offset)..];
16491652
16501653 const addend: u64 = @bitCast(reloc.addend);
16511654 const target_val: u64 = type: switch (reloc.type.target) {
......@@ -1737,6 +1740,7 @@ const SymbolReloc = struct {
17371740 }
17381741
17391742 reloc.* = undefined;
1743 reloc.node = .none;
17401744 }
17411745
17421746 /// If `reloc.rela_index` is populated, reset it to `.none` and delete the relocation, updating
......@@ -1746,7 +1750,7 @@ const SymbolReloc = struct {
17461750 reloc.relaSection(elf).relaDeleteOne(elf, rela_index);
17471751 switch (elf.ehdrType()) {
17481752 .REL => {},
1749 .EXEC, .DYN => switch (elf.nodeWantsDsoRelocation(reloc.node)) {
1753 .EXEC, .DYN => switch (elf.nodeWantsDsoRelocation(reloc.node.unwrap().?)) {
17501754 .no => unreachable, // there *was* a dynamic relocation!
17511755 .yes => {},
17521756 .yes_textrel => elf.textrel_count -= 1,
......@@ -1760,7 +1764,7 @@ const SymbolReloc = struct {
17601764/// This represents a symbol reloc against the section symbol containing the node
17611765/// with a variable addend that changes when the target node moves.
17621766const NodeReloc = struct {
1763 node: MappedFile.Node.Index,
1767 node: MappedFile.Node.Index.Optional,
17641768 offset: u64,
17651769 target: MappedFile.Node.Index,
17661770 addend: i64,
......@@ -1786,7 +1790,7 @@ const NodeReloc = struct {
17861790 assert(elf.ehdrType() == .REL);
17871791 // The node has moved, so the offset of the relocation within the section might have
17881792 // changed, so update the `offset` field of the `ElfN.Rela` entry.
1789 elf.getNodeShndx(reloc.node).get(elf).rela.shndx.relaSetOffset(elf, rela_index, node_vaddr + reloc.offset);
1793 elf.getNodeShndx(reloc.node.unwrap().?).get(elf).rela.shndx.relaSetOffset(elf, rela_index, node_vaddr + reloc.offset);
17901794 } else {
17911795 assert(elf.ehdrType() != .REL);
17921796 reloc.apply(elf);
......@@ -1797,7 +1801,7 @@ const NodeReloc = struct {
17971801 if (reloc.rela_index.unwrap()) |rela_index| {
17981802 assert(elf.ehdrType() == .REL);
17991803 // The target has moved, so the `addend` field of the `ElfN.Rela` entry needs to be updated.
1800 elf.getNodeShndx(reloc.node).get(elf).rela.shndx.relaSetAddend(elf, rela_index, target_section_offset +% @as(u64, @bitCast(reloc.addend)));
1804 elf.getNodeShndx(reloc.node.unwrap().?).get(elf).rela.shndx.relaSetAddend(elf, rela_index, target_section_offset +% @as(u64, @bitCast(reloc.addend)));
18011805 } else {
18021806 assert(elf.ehdrType() != .REL);
18031807 reloc.apply(elf);
......@@ -1805,12 +1809,13 @@ const NodeReloc = struct {
18051809 }
18061810
18071811 fn apply(reloc: *NodeReloc, elf: *Elf) void {
1812 const node = reloc.node.unwrap() orelse return; // deleted
18081813 if (reloc.rela_index.unwrap()) |rela_index| {
18091814 assert(elf.ehdrType() == .REL);
18101815 _ = rela_index;
18111816 } else {
18121817 assert(elf.ehdrType() != .REL);
1813 if (reloc.node.hasMoved(&elf.mf) or reloc.target.hasMoved(&elf.mf)) {
1818 if (node.hasMoved(&elf.mf) or reloc.target.hasMoved(&elf.mf)) {
18141819 // There's no point applying the relocation now, because it will be re-applied by
18151820 // `flushMoved` at some point anyway.
18161821 return;
......@@ -1842,7 +1847,7 @@ const NodeReloc = struct {
18421847 }, .cast = .unsigned, .shift = .@"0" };
18431848 const addend: u64 = @bitCast(reloc.addend);
18441849 const target_val = elf.getNodeVAddr(reloc.target) +% addend;
1845 const dest_slice = reloc.node.slice(&elf.mf)[@intCast(reloc.offset)..];
1850 const dest_slice = reloc.node.unwrap().?.slice(&elf.mf)[@intCast(reloc.offset)..];
18461851 try simple.write(target_val, dest_slice, elf.targetEndian());
18471852 }
18481853
......@@ -1858,7 +1863,7 @@ const NodeReloc = struct {
18581863 .unit_debug_info_header => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_info_header_first_target_reloc,
18591864 .unit_debug_line_header => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_line_header_first_target_reloc,
18601865 .unit_debug_rnglists => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_rnglists_first_target_reloc,
1861 .value_debug_info => |vi| &elf.dwarf_values.items[@backingInt(vi)].debug_info_first_target_reloc,
1866 .const_debug_info => |cpi| &elf.dwarf_consts.getPtr(cpi).?.debug_info_first_target_reloc,
18621867 .global_debug_info => |gi| &elf.dwarf_globals.items[@backingInt(gi)].debug_info_first_target_reloc,
18631868 .func_debug_info => |fi| &elf.dwarf_funcs.items[@backingInt(fi)].debug_info_first_target_reloc,
18641869 };
......@@ -1877,13 +1882,14 @@ const NodeReloc = struct {
18771882 }
18781883
18791884 reloc.* = undefined;
1885 reloc.node = .none;
18801886 }
18811887
18821888 /// If `reloc.rela_index` is populated, reset it to `.none` and delete the relocation.
18831889 fn deleteOutputRel(reloc: *NodeReloc, elf: *Elf) void {
18841890 const rela_index = reloc.rela_index.unwrap() orelse return;
18851891 assert(elf.ehdrType() == .REL);
1886 elf.getNodeShndx(reloc.node).get(elf).rela.shndx.relaDeleteOne(elf, rela_index);
1892 elf.getNodeShndx(reloc.node.unwrap().?).get(elf).rela.shndx.relaDeleteOne(elf, rela_index);
18871893 reloc.rela_index = .none;
18881894 }
18891895};
......@@ -3175,7 +3181,8 @@ const Symbol = struct {
31753181 .abs, .pltabs => {},
31763182 }
31773183 if (!reloc.type.action.simple.dest.isAddr(elf)) continue;
3178 switch (elf.nodeWantsDsoRelocation(reloc.node)) {
3184 const node = reloc.node.unwrap().?;
3185 switch (elf.nodeWantsDsoRelocation(node)) {
31793186 .no => continue,
31803187 .yes_textrel => elf.textrel_count += 1,
31813188 .yes => {},
......@@ -3183,7 +3190,7 @@ const Symbol = struct {
31833190 // There is capacity for a relocation because we just deleted one earlier.
31843191 reloc.rela_index = elf.shndx.rela_dyn.relaAddOneAssumeCapacity(elf, .{
31853192 .type = .relative(elf),
3186 .offset = elf.getNodeVAddr(reloc.node) + reloc.offset,
3193 .offset = elf.getNodeVAddr(node) + reloc.offset,
31873194 .raw_sym_index = 0,
31883195 .addend = 0,
31893196 }).toOptional();
......@@ -3310,7 +3317,7 @@ pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId {
33103317 .unit_debug_line,
33113318 .unit_debug_line_header,
33123319 .unit_debug_rnglists,
3313 .value_debug_info,
3320 .const_debug_info,
33143321 .global_debug_info,
33153322 .func_frame_fde,
33163323 .func_debug_info,
......@@ -3823,7 +3830,7 @@ fn create(
38233830 .first_target_reloc = .none,
38243831 }),
38253832 .dwarf_units = .empty,
3826 .dwarf_values = .empty,
3833 .dwarf_consts = .empty,
38273834 .dwarf_globals = .empty,
38283835 .dwarf_funcs = .empty,
38293836
......@@ -3878,7 +3885,7 @@ pub fn deinit(elf: *Elf) void {
38783885 elf.dwarf.deinit();
38793886 for (elf.dwarf_units.items) |*dwarf_unit| dwarf_unit.debug_rnglists_symbol_relocs.deinit(gpa);
38803887 elf.dwarf_units.deinit(gpa);
3881 elf.dwarf_values.deinit(gpa);
3888 elf.dwarf_consts.deinit(gpa);
38823889 elf.dwarf_globals.deinit(gpa);
38833890 elf.dwarf_funcs.deinit(gpa);
38843891
......@@ -5176,7 +5183,7 @@ fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index {
51765183 .unit_frame_cie,
51775184 .unit_debug_info_header,
51785185 .unit_debug_line_header,
5179 .value_debug_info,
5186 .const_debug_info,
51805187 .global_debug_info,
51815188 .func_frame_fde,
51825189 .func_debug_info,
......@@ -5213,7 +5220,7 @@ fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
52135220 .unit_debug_line,
52145221 .unit_debug_line_header,
52155222 .unit_debug_rnglists,
5216 .value_debug_info,
5223 .const_debug_info,
52175224 .global_debug_info,
52185225 .func_frame_fde,
52195226 .func_debug_info,
......@@ -5252,7 +5259,7 @@ fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
52525259 .unit_debug_info_header,
52535260 .unit_debug_line_header,
52545261 .unit_debug_rnglists,
5255 .value_debug_info,
5262 .const_debug_info,
52565263 .global_debug_info,
52575264 .func_frame_fde,
52585265 .func_debug_info,
......@@ -5287,7 +5294,7 @@ fn computeNodeSectionOffset(elf: *Elf, ni: MappedFile.Node.Index) u64 {
52875294 .unit_debug_info_header,
52885295 .unit_debug_line_header,
52895296 .unit_debug_rnglists,
5290 .value_debug_info,
5297 .const_debug_info,
52915298 .global_debug_info,
52925299 .func_frame_fde,
52935300 .func_debug_info,
......@@ -5356,9 +5363,9 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {
53565363 .first_node_reloc = &elf.dwarf_units.items[@backingInt(ui)].debug_line_header_first_node_reloc,
53575364 },
53585365 .unit_debug_rnglists => unreachable, // unsupported
5359 .value_debug_info => |vi| .{
5360 .first_symbol_reloc = &elf.dwarf_values.items[@backingInt(vi)].debug_info_first_symbol_reloc,
5361 .first_node_reloc = &elf.dwarf_values.items[@backingInt(vi)].debug_info_first_node_reloc,
5366 .const_debug_info => |cpi| .{
5367 .first_symbol_reloc = &elf.dwarf_consts.getPtr(cpi).?.debug_info_first_symbol_reloc,
5368 .first_node_reloc = &elf.dwarf_consts.getPtr(cpi).?.debug_info_first_node_reloc,
53625369 },
53635370 .global_debug_info => |gi| .{
53645371 .first_symbol_reloc = &elf.dwarf_globals.items[@backingInt(gi)].debug_info_first_symbol_reloc,
......@@ -5387,8 +5394,11 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {
53875394 if (opts.first_symbol_reloc) |ptr| {
53885395 if (ptr.* != .none) {
53895396 for (elf.symbol_relocs.items[@backingInt(ptr.*)..], @backingInt(ptr.*)..) |*reloc, index| {
5390 if (reloc.node.toOptional() == opts.skip_symbol_relocs) continue;
5391 if (reloc.node != ni) break;
5397 if (reloc.node != ni.toOptional()) {
5398 if (reloc.node == .none) continue;
5399 if (reloc.node == opts.skip_symbol_relocs) continue;
5400 break;
5401 }
53925402 reloc.delete(elf, @fromBackingInt(@intCast(index)));
53935403 }
53945404 }
......@@ -5398,8 +5408,11 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {
53985408 if (opts.first_node_reloc) |ptr| {
53995409 if (ptr.* != .none) {
54005410 for (elf.node_relocs.items[@backingInt(ptr.*)..]) |*reloc| {
5401 if (reloc.node.toOptional() == opts.skip_node_relocs) continue;
5402 if (reloc.node != ni) break;
5411 if (reloc.node != ni.toOptional()) {
5412 if (reloc.node == .none) continue;
5413 if (reloc.node == opts.skip_node_relocs) continue;
5414 break;
5415 }
54035416 reloc.delete(elf);
54045417 }
54055418 }
......@@ -5409,7 +5422,10 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {
54095422 if (opts.first_got_reloc) |ptr| {
54105423 if (ptr.* != .none) {
54115424 for (elf.got_relocs.items[@backingInt(ptr.*)..]) |*reloc| {
5412 if (reloc.node != ni.toOptional()) break;
5425 if (reloc.node != ni.toOptional()) {
5426 if (reloc.node == .none) continue;
5427 break;
5428 }
54135429 reloc.delete(elf);
54145430 }
54155431 }
......@@ -5433,23 +5449,32 @@ fn flushMovedNodeRelocs(
54335449) void {
54345450 if (opts.first_symbol_reloc != .none) {
54355451 for (elf.symbol_relocs.items[@backingInt(opts.first_symbol_reloc)..]) |*reloc| {
5436 if (reloc.node.toOptional() == opts.skip_symbol_relocs) continue;
5437 if (reloc.node != node) break;
5452 if (reloc.node != node.toOptional()) {
5453 if (reloc.node == .none) continue;
5454 if (reloc.node == opts.skip_symbol_relocs) continue;
5455 break;
5456 }
54385457 reloc.flushMovedNode(elf, node_vaddr);
54395458 }
54405459 }
54415460
54425461 if (opts.first_node_reloc != .none) {
54435462 for (elf.node_relocs.items[@backingInt(opts.first_node_reloc)..]) |*reloc| {
5444 if (reloc.node.toOptional() == opts.skip_node_relocs) continue;
5445 if (reloc.node != node) break;
5463 if (reloc.node != node.toOptional()) {
5464 if (reloc.node == .none) continue;
5465 if (reloc.node == opts.skip_node_relocs) continue;
5466 break;
5467 }
54465468 reloc.flushMovedNode(elf, node_vaddr);
54475469 }
54485470 }
54495471
54505472 if (opts.first_got_reloc != .none) {
54515473 for (elf.got_relocs.items[@backingInt(opts.first_got_reloc)..]) |*reloc| {
5452 if (reloc.node != node.toOptional()) break;
5474 if (reloc.node != node.toOptional()) {
5475 if (reloc.node == .none) continue;
5476 break;
5477 }
54535478 reloc.apply(elf);
54545479 }
54555480 }
......@@ -7277,7 +7302,7 @@ fn zcuFilesReadyInner(elf: *Elf, zcu: *Zcu) Error!void {
72777302
72787303fn flushFiles(elf: *Elf) Error!void {
72797304 const gpa = elf.base.comp.gpa;
7280 if (elf.shndx.debug_line != .UNDEF) for (elf.dwarf.units.keys(), elf.dwarf.units.values()) |mod, *unit| {
7305 if (elf.shndx.debug_line != .UNDEF) for (elf.dwarf.units.values()) |*unit| {
72817306 if (!unit.cleanDebugLineHeaderChanged()) continue;
72827307 const debug_line_header_ni = unit.debug_line_header_ni.unwrap().?;
72837308 try debug_line_header_ni.parent(&elf.mf).unwrap().?.nextMoved(gpa, &elf.mf);
......@@ -7287,7 +7312,7 @@ fn flushFiles(elf: *Elf) Error!void {
72877312 debug_line_header_ni.writer(gpa, &elf.mf, &dlh_nw);
72887313 defer dlh_nw.deinit();
72897314 elf.resetNodeRelocs(debug_line_header_ni);
7290 elf.dwarf.genDebugLineHeader(mod, unit, &dlh_nw, elf.base.comp.zcu.?) catch |err| switch (err) {
7315 elf.dwarf.genDebugLineHeader(unit, &dlh_nw, elf.base.comp.zcu.?) catch |err| switch (err) {
72917316 else => |e| return e,
72927317 error.WriteFailed => return dlh_nw.err.?,
72937318 };
......@@ -7629,7 +7654,7 @@ fn addRelocAssumeCapacity(
76297654 first_target_reloc.* = ri;
76307655 if (next != .none) next.get(elf).prev = ri;
76317656 elf.symbol_relocs.appendAssumeCapacity(.{
7632 .node = node,
7657 .node = node.toOptional(),
76337658 .offset = offset,
76347659 .type = undefined,
76357660 .target = target,
......@@ -8067,7 +8092,7 @@ fn addSymbolRelocAssumeCapacity(
80678092 first_target_reloc.* = ri;
80688093 if (next != .none) next.get(elf).prev = ri;
80698094 elf.symbol_relocs.appendAssumeCapacity(.{
8070 .node = node,
8095 .node = node.toOptional(),
80718096 .offset = offset,
80728097 .target = target,
80738098 .addend = addend,
......@@ -8101,7 +8126,7 @@ fn addNodeRelocAssumeCapacity(
81018126 .unit_debug_info_header => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_info_header_first_target_reloc,
81028127 .unit_debug_line_header => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_line_header_first_target_reloc,
81038128 .unit_debug_rnglists => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_rnglists_first_target_reloc,
8104 .value_debug_info => |vi| &elf.dwarf_values.items[@backingInt(vi)].debug_info_first_target_reloc,
8129 .const_debug_info => |cpi| &elf.dwarf_consts.getPtr(cpi).?.debug_info_first_target_reloc,
81058130 .global_debug_info => |gi| &elf.dwarf_globals.items[@backingInt(gi)].debug_info_first_target_reloc,
81068131 .func_debug_info => |fi| &elf.dwarf_funcs.items[@backingInt(fi)].debug_info_first_target_reloc,
81078132 };
......@@ -8151,7 +8176,7 @@ fn addNodeRelocAssumeCapacity(
81518176 .addend = 0,
81528177 });
81538178 elf.node_relocs.appendAssumeCapacity(.{
8154 .node = node,
8179 .node = node.toOptional(),
81558180 .offset = offset,
81568181 .type = undefined,
81578182 .target = target,
......@@ -8164,7 +8189,7 @@ fn addNodeRelocAssumeCapacity(
81648189 },
81658190 .DYN, .EXEC => {
81668191 elf.node_relocs.appendAssumeCapacity(.{
8167 .node = node,
8192 .node = node.toOptional(),
81688193 .offset = offset,
81698194 .target = target,
81708195 .addend = addend,
......@@ -8209,7 +8234,7 @@ fn addGotRelocAssumeCapacity(
82098234 .unit_debug_line,
82108235 .unit_debug_line_header,
82118236 .unit_debug_rnglists,
8212 .value_debug_info,
8237 .const_debug_info,
82138238 .global_debug_info,
82148239 .func_frame_fde,
82158240 .func_debug_info,
......@@ -8502,7 +8527,8 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)
85028527
85038528 const nav = ip.getNav(nav_index);
85048529 if (ip.indexToKey(nav.resolved.?.value) == .@"extern") return;
8505 if (!Type.fromInterned(nav.resolved.?.type).hasRuntimeBits(zcu)) return;
8530 if (!Type.fromInterned(nav.resolved.?.type).hasRuntimeBits(zcu))
8531 return elf.dwarf.updateComptimeNav(pt, nav_index);
85068532
85078533 const nmi = try elf.navMapIndex(zcu, nav_index);
85088534 const ni = nmi.symbol(elf).index().ptr(elf).node.unwrap().?;
......@@ -8546,11 +8572,11 @@ pub fn updateContainerType(
85468572
85478573pub fn addConst(
85488574 elf: *Elf,
8549 pt: Zcu.PerThread,
8575 _: Zcu.PerThread,
85508576 index: link.ConstPool.Index,
85518577 val: InternPool.Index,
8552) std.mem.Allocator.Error!void {
8553 if (false) try elf.dwarf.addConst(pt, index, val);
8578) link.Error!void {
8579 try elf.dwarf.addConst(index, val);
85548580}
85558581
85568582pub fn updateConst(
......@@ -8570,7 +8596,7 @@ fn updateConstInner(
85708596) link.Error!void {
85718597 var lazy_it = elf.lazy.iterator();
85728598 while (lazy_it.next()) |lazy| if (lazy.value.getIndex(cpi)) |li| {
8573 const lazy_ty: Type = .fromInterned(cpi.val(&elf.dwarf.const_pool));
8599 const lazy_ty: Type = .fromInterned(val);
85748600 var prog_name_buf: [std.Progress.Node.max_name_len]u8 = undefined;
85758601 const prog_name: []const u8 = switch (lazy_ty.zigTypeTag(pt.zcu)) {
85768602 .@"enum" => std.mem.print(&prog_name_buf, "@tagName({f})", .{lazy_ty.fmt(pt)}) catch &prog_name_buf,
......@@ -8590,16 +8616,20 @@ fn updateConstInner(
85908616 ),
85918617 };
85928618 };
8593 if (false) try elf.dwarf.updateConst(pt, cpi, val);
8619 elf.dwarf.updateConst(cpi, val);
85948620}
85958621
85968622pub fn updateConstIncomplete(
85978623 elf: *Elf,
8598 pt: Zcu.PerThread,
8624 _: Zcu.PerThread,
85998625 cpi: link.ConstPool.Index,
86008626 val: InternPool.Index,
86018627) link.Error!void {
8602 if (false) try elf.dwarf.updateConstIncomplete(pt, cpi, val);
8628 const debug_info_ni = Dwarf.Const.get(cpi, &elf.dwarf).debug_info_ni.unwrap().?;
8629 var di_nw: MappedFile.Node.Writer = undefined;
8630 debug_info_ni.writer(elf.base.comp.gpa, &elf.mf, &di_nw);
8631 defer di_nw.deinit();
8632 try elf.dwarf.updateConstIncomplete(&di_nw, val);
86038633}
86048634
86058635pub fn updateFunc(
......@@ -8770,7 +8800,7 @@ fn updateFuncInner(
87708800 elf.resetNodeRelocs(dwarf_func.debug_line_ni.unwrap().?);
87718801 try debug.startDebugLine();
87728802 elf.resetNodeRelocs(dwarf_func.debug_info_ni.unwrap().?);
8773 try debug.startDebugInfo();
8803 try debug.startFuncDebugInfo();
87748804 },
87758805 .none => {},
87768806 }
......@@ -9187,7 +9217,7 @@ fn idleProgNode(
91879217 },
91889218 ui.mod(&elf.dwarf).fully_qualified_name,
91899219 }) catch &name,
9190 .value_debug_info => |cpi| std.mem.print(&name, "debug info for {f}", .{
9220 .const_debug_info => |cpi| std.mem.print(&name, "debug info for {f}", .{
91919221 Value.fromInterned(cpi.val(&elf.dwarf.const_pool))
91929222 .fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }),
91939223 }) catch &name,
......@@ -9648,14 +9678,14 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
96489678 const node_vaddr = elf.computeNodeVAddr(ni);
96499679 for (dwarf_unit.debug_rnglists_symbol_relocs.keys()) |symbol_ri| {
96509680 const symbol_reloc = symbol_ri.get(elf);
9651 assert(symbol_reloc.node == ni);
9681 assert(symbol_reloc.node.unwrap().? == ni);
96529682 symbol_reloc.flushMovedNode(elf, node_vaddr);
96539683 }
96549684 },
9655 .value_debug_info => |vi| {
9656 const dwarf_value = &elf.dwarf_values.items[@backingInt(vi)];
9685 .const_debug_info => |cpi| {
9686 const dwarf_const = &elf.dwarf_consts.get(cpi).?;
96579687 const target_section_offset = elf.computeNodeSectionOffset(ni);
9658 var target_ri = dwarf_value.debug_info_first_target_reloc;
9688 var target_ri = dwarf_const.debug_info_first_target_reloc;
96599689 while (target_ri != .none) {
96609690 const target_reloc = target_ri.get(elf);
96619691 assert(target_reloc.target == ni);
......@@ -9663,12 +9693,12 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
96639693 target_ri = target_reloc.next;
96649694 }
96659695 elf.flushMovedNodeRelocs(ni, elf.computeNodeVAddr(ni), .{
9666 .first_symbol_reloc = dwarf_value.debug_info_first_symbol_reloc,
9667 .first_node_reloc = dwarf_value.debug_info_first_node_reloc,
9696 .first_symbol_reloc = dwarf_const.debug_info_first_symbol_reloc,
9697 .first_node_reloc = dwarf_const.debug_info_first_node_reloc,
96689698 });
96699699 },
9670 .global_debug_info => |vi| {
9671 const dwarf_global = &elf.dwarf_globals.items[@backingInt(vi)];
9700 .global_debug_info => |gi| {
9701 const dwarf_global = &elf.dwarf_globals.items[@backingInt(gi)];
96729702 const target_section_offset = elf.computeNodeSectionOffset(ni);
96739703 var target_ri = dwarf_global.debug_info_first_target_reloc;
96749704 while (target_ri != .none) {
......@@ -9972,7 +10002,7 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo
997210002 .unit_debug_line,
997310003 .unit_debug_line_header,
997410004 .unit_debug_rnglists,
9975 .value_debug_info,
10005 .const_debug_info,
997610006 .global_debug_info,
997710007 .func_frame_fde,
997810008 .func_debug_info,
......@@ -10036,7 +10066,7 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!
1003610066 .unit_debug_info_header,
1003710067 .unit_debug_line_header,
1003810068 .unit_debug_rnglists,
10039 .value_debug_info,
10069 .const_debug_info,
1004010070 .global_debug_info,
1004110071 .func_frame_fde,
1004210072 .func_debug_info,
......@@ -10089,7 +10119,7 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!
1008910119 },
1009010120 .unit_debug_info_header,
1009110121 .unit_debug_line_header,
10092 .value_debug_info,
10122 .const_debug_info,
1009310123 .global_debug_info,
1009410124 .func_debug_info,
1009510125 .func_debug_line,
......@@ -10105,7 +10135,7 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!
1010510135 switch (tag) {
1010610136 else => unreachable,
1010710137 .unit_debug_info_header,
10108 .value_debug_info,
10138 .const_debug_info,
1010910139 .global_debug_info,
1011010140 .func_debug_info,
1011110141 => for (0..2) |_| fw.writeUleb128(@backingInt(Dwarf.AbbrevCode.null)) catch unreachable,
......@@ -10119,7 +10149,7 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!
1011910149 elf.dwarf.updateUnitLength(fw.buffer, fw.buffer.len);
1012010150 switch (tag) {
1012110151 else => unreachable,
10122 .unit_debug_info_header, .value_debug_info, .global_debug_info, .func_debug_info => {
10152 .unit_debug_info_header, .const_debug_info, .global_debug_info, .func_debug_info => {
1012310153 comptime assert(Dwarf.uleb128Size(@backingInt(Dwarf.AbbrevCode.null)) == 1);
1012410154 @memset(fw.unusedCapacitySlice(), @backingInt(Dwarf.AbbrevCode.null));
1012510155 },
......@@ -10143,7 +10173,7 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!
1014310173 @memset(fw.buffer, std.dwarf.CFA.nop);
1014410174 },
1014510175 .unit_debug_info_header,
10146 .value_debug_info,
10176 .const_debug_info,
1014710177 .global_debug_info,
1014810178 .func_debug_info,
1014910179 => elf.dwarf.genDebugInfoPadding(&fw, fw.buffer.len) catch unreachable,
......@@ -10693,9 +10723,11 @@ pub fn printNode(
1069310723 .unit_debug_line_header,
1069410724 .unit_debug_rnglists,
1069510725 => |ui| try w.print("({s})", .{ui.mod(&elf.dwarf).fully_qualified_name}),
10696 .value_debug_info => |cpi| try w.print("({f})", .{
10697 Value.fromInterned(cpi.val(&elf.dwarf.const_pool))
10698 .fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }),
10726 .const_debug_info => |cpi| try w.print("({f})", .{
10727 Value.fromInterned(cpi.val(&elf.dwarf.const_pool)).fmtValue(.{
10728 .zcu = elf.base.comp.zcu.?,
10729 .tid = tid,
10730 }),
1069910731 }),
1070010732 .global_debug_info => |gi| {
1070110733 const zcu = elf.base.comp.zcu.?;