authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-08-17 19:00:21-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-09-03 12:59:38-04:00
log84c2fd3d781b8843dfd3565139282fddf60e4e97
treef27ecfebd78e4b0d66341502a1e8dc61e1f0bfe2
parentea682d27a14176ef5bc07c2538a4388f31bf8161

Dwarf2: implement more type debug info


3 files changed, 413 insertions(+), 130 deletions(-)

src/link/Coff.zig+22-14
...@@ -7756,22 +7756,30 @@ pub fn printNode(...@@ -7756,22 +7756,30 @@ pub fn printNode(
7756 }7756 }
7757 return;7757 return;
7758 }7758 }
7759 const file_loc = ni.fileLocation(&coff.mf, false);7759 const start_address: usize, const end_address: usize = file_loc: {
7760 if (file_loc.size == 0) return;7760 const file_loc = ni.fileLocation(&coff.mf, false);
7761 var address = file_loc.offset;7761 break :file_loc .{ @intCast(file_loc.offset), @intCast(file_loc.offset + file_loc.size) };
7762 };
7763 var address = start_address;
7762 const line_len = 0x10;7764 const line_len = 0x10;
7763 var line_it = std.mem.window(7765 while (true) : (address = @min(std.mem.alignForward(usize, address + 1, line_len), end_address)) {
7764 u8,
7765 coff.mf.memory_map.memory[@intCast(file_loc.offset)..][0..@intCast(file_loc.size)],
7766 line_len,
7767 line_len,
7768 );
7769 while (line_it.next()) |line_bytes| : (address += line_len) {
7770 try w.splatByteAll(' ', indent + 1);7766 try w.splatByteAll(' ', indent + 1);
7771 try w.print("{x:0>8} ", .{address});7767 try w.print("{x:0>8}", .{address});
7772 for (line_bytes) |byte| try w.print("{x:0>2} ", .{byte});7768 if (address == end_address) break try w.writeByte('\n');
7773 try w.splatByteAll(' ', 3 * (line_len - line_bytes.len) + 1);7769 try w.splatByteAll(' ', 2);
7774 for (line_bytes) |byte| try w.writeByte(if (std.ascii.isPrint(byte)) byte else '.');7770 const start_byte_address = std.mem.alignBackward(usize, address, line_len);
7771 const end_byte_address = start_byte_address + line_len;
7772 for (start_byte_address..end_byte_address) |byte_address|
7773 if (byte_address < start_address or byte_address >= end_address)
7774 try w.splatByteAll(' ', 3)
7775 else
7776 try w.print("{x:0>2} ", .{coff.mf.memory_map.memory[byte_address]});
7777 try w.writeByte(' ');
7778 for (start_byte_address..@min(end_address, end_byte_address)) |byte_address|
7779 try w.writeByte(if (byte_address < start_address or byte_address >= end_address) ' ' else char: {
7780 const byte = coff.mf.memory_map.memory[byte_address];
7781 break :char if (std.ascii.isPrint(byte)) byte else '.';
7782 });
7775 try w.writeByte('\n');7783 try w.writeByte('\n');
7776 }7784 }
7777}7785}
src/link/Dwarf2.zig+295-74
...@@ -635,8 +635,12 @@ pub const WipNav = struct {...@@ -635,8 +635,12 @@ pub const WipNav = struct {
635 const zcu = debug.pt.zcu;635 const zcu = debug.pt.zcu;
636 const ip = &zcu.intern_pool;636 const ip = &zcu.intern_pool;
637 const func = zcu.funcInfo(debug.wip_nav.func);637 const func = zcu.funcInfo(debug.wip_nav.func);
638 const func_type = ip.indexToKey(func.ty).func_type;
638 const inst_info = ip.getNav(func.owner_nav).srcInst(ip).resolveFull(ip).?;639 const inst_info = ip.getNav(func.owner_nav).srcInst(ip).resolveFull(ip).?;
639 const decl = zcu.fileByIndex(inst_info.file).zir.?.getDeclaration(inst_info.inst);640 const zf = zcu.fileByIndex(inst_info.file);
641 const mod = zf.mod.?;
642 const target = &mod.resolved_target.result;
643 const decl = zf.zir.?.getDeclaration(inst_info.inst);
640 const nav = ip.getNav(func.owner_nav);644 const nav = ip.getNav(func.owner_nav);
641 const diw = &debug.info_writer.interface;645 const diw = &debug.info_writer.interface;
642 try diw.writeUleb128(try dwarf.refAbbrevCode(.decl_func));646 try diw.writeUleb128(try dwarf.refAbbrevCode(.decl_func));
...@@ -645,10 +649,19 @@ pub const WipNav = struct {...@@ -645,10 +649,19 @@ pub const WipNav = struct {
645 try diw.writeUleb128(decl.src_column + 1);649 try diw.writeUleb128(decl.src_column + 1);
646 try diw.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private);650 try diw.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private);
647 try debug.strp(nav.name.toSlice(ip));651 try debug.strp(nav.name.toSlice(ip));
648 try debug.strp(nav.fqn.toSlice(ip));652 try debug.strp(switch (decl.linkage) {
653 .normal => nav.fqn,
654 .@"extern", .@"export" => nav.name,
655 }.toSlice(ip));
656 try debug.refType(.fromInterned(func_type.return_type));
649 try dwarf.symbolAddress(&debug.info_writer, debug.wip_nav.func_si, 0);657 try dwarf.symbolAddress(&debug.info_writer, debug.wip_nav.func_si, 0);
650 debug.info_func_length_offset = diw.end;658 debug.info_func_length_offset = diw.end;
651 try diw.writeInt(u32, undefined, dwarf.endian);659 try diw.writeInt(u32, undefined, dwarf.endian);
660 try diw.writeUleb128(
661 target_info.minFunctionAlignment(target).max(nav.resolved.?.@"align").toByteUnits().?,
662 );
663 try diw.writeByte(@intFromBool(decl.linkage != .normal));
664 try diw.writeByte(@intFromBool(Type.fromInterned(func_type.return_type).isNoReturn(zcu)));
652 }665 }
653666
654 pub fn startDebugLine(debug: *Debug) link.Error!void {667 pub fn startDebugLine(debug: *Debug) link.Error!void {
...@@ -1712,7 +1725,7 @@ pub fn genDebugInfoHeader(...@@ -1712,7 +1725,7 @@ pub fn genDebugInfoHeader(
1712 try dwarf.strp(&dwarf.debug_line_str, dih_nw, mod.root_src_path);1725 try dwarf.strp(&dwarf.debug_line_str, dih_nw, mod.root_src_path);
1713 try dwarf.sectionOffset(1726 try dwarf.sectionOffset(
1714 dih_nw,1727 dih_nw,
1715 dwarf.getUnit(comp.root_mod).get(dwarf).debug_info_header_ni.unwrap().?,1728 dwarf.getUnit(zcu.root_mod).get(dwarf).debug_info_header_ni.unwrap().?,
1716 compile_unit_offset,1729 compile_unit_offset,
1717 );1730 );
1718 try dwarf.sectionOffset(dih_nw, unit.debug_line_header_ni.unwrap().?, 0);1731 try dwarf.sectionOffset(dih_nw, unit.debug_line_header_ni.unwrap().?, 0);
...@@ -1726,11 +1739,14 @@ pub fn genDebugInfoHeader(...@@ -1726,11 +1739,14 @@ pub fn genDebugInfoHeader(
1726 try dihw.writeUleb128(try dwarf.refAbbrevCode(.module));1739 try dihw.writeUleb128(try dwarf.refAbbrevCode(.module));
1727 try dwarf.strp(&dwarf.debug_str, dih_nw, mod.fully_qualified_name);1740 try dwarf.strp(&dwarf.debug_str, dih_nw, mod.fully_qualified_name);
1728 try dihw.writeUleb128(0);1741 try dihw.writeUleb128(0);
1729 for ([_][]const u8{ "builtin", "root", "std" }, [_]*Module{1742 try dwarf.genModuleDependency(
1743 dih_nw,
1744 "builtin",
1730 zcu.builtin_modules.get(mod.getBuiltinOptions(comp.config).hash()).?,1745 zcu.builtin_modules.get(mod.getBuiltinOptions(comp.config).hash()).?,
1731 zcu.root_mod,1746 module_offset,
1732 zcu.std_mod,1747 );
1733 }) |name, dep| try dwarf.genModuleDependency(dih_nw, name, dep, module_offset);1748 try dwarf.genModuleDependency(dih_nw, "root", zcu.root_mod, module_offset);
1749 try dwarf.genModuleDependency(dih_nw, "std", zcu.std_mod, module_offset);
1734 for (mod.deps.keys(), mod.deps.values()) |name, dep|1750 for (mod.deps.keys(), mod.deps.values()) |name, dep|
1735 try dwarf.genModuleDependency(dih_nw, name, dep, module_offset);1751 try dwarf.genModuleDependency(dih_nw, name, dep, module_offset);
1736 for ([2]AbbrevCode{ .pad_1, .pad_n }) |pad| _ = try dwarf.refAbbrevCode(pad);1752 for ([2]AbbrevCode{ .pad_1, .pad_n }) |pad| _ = try dwarf.refAbbrevCode(pad);
...@@ -1739,18 +1755,17 @@ pub fn genDebugInfoHeader(...@@ -1739,18 +1755,17 @@ pub fn genDebugInfoHeader(
17391755
1740fn genModuleDependency(1756fn genModuleDependency(
1741 dwarf: *Dwarf,1757 dwarf: *Dwarf,
1742 nw: *MappedFile.Node.Writer,1758 di_nw: *MappedFile.Node.Writer,
1743 name: []const u8,1759 name: []const u8,
1744 dep: *Module,1760 dep: *Module,
1745 module_offset: usize,1761 module_offset: usize,
1746) link.EmitError!void {1762) link.EmitError!void {
1747 const dep_unit = dwarf.getUnit(dep).get(dwarf);1763 const dep_unit = dwarf.getUnit(dep).get(dwarf);
1748 if (!dep_unit.alive) return;1764 if (!dep_unit.alive) return;
1749 const diw = &nw.interface;1765 const diw = &di_nw.interface;
1750 try diw.writeUleb128(try dwarf.refAbbrevCode(.module_dependency));1766 try diw.writeUleb128(try dwarf.refAbbrevCode(.module_dependency));
1751 try diw.writeAll(name);1767 try dwarf.strp(&dwarf.debug_str, di_nw, name);
1752 try diw.writeByte(0);1768 try dwarf.sectionOffset(di_nw, dep_unit.debug_info_header_ni.unwrap().?, module_offset);
1753 try dwarf.sectionOffset(nw, dep_unit.debug_info_header_ni.unwrap().?, module_offset);
1754}1769}
17551770
1756pub fn genDebugInfoPadding(dwarf: *Dwarf, diw: *Writer, size: u64) Writer.Error!void {1771pub fn genDebugInfoPadding(dwarf: *Dwarf, diw: *Writer, size: u64) Writer.Error!void {
...@@ -1948,9 +1963,10 @@ pub fn updateComptimeNav(...@@ -1948,9 +1963,10 @@ pub fn updateComptimeNav(
1948 pt: Zcu.PerThread,1963 pt: Zcu.PerThread,
1949 nav_index: InternPool.Nav.Index,1964 nav_index: InternPool.Nav.Index,
1950) link.Error!void {1965) link.Error!void {
1951 const zcu = dwarf.lf.comp.zcu.?;1966 const zcu = pt.zcu;
1952 const ip = &zcu.intern_pool;1967 const ip = &zcu.intern_pool;
1953 const nav = ip.getNav(nav_index);1968 const nav = ip.getNav(nav_index);
1969 log.debug("updateComptimeNav({f})", .{nav.fqn.fmt(ip)});
1954 const inst_info = nav.srcInst(ip).resolveFull(ip).?;1970 const inst_info = nav.srcInst(ip).resolveFull(ip).?;
1955 const nav_val: Value = .fromInterned(nav.resolved.?.value);1971 const nav_val: Value = .fromInterned(nav.resolved.?.value);
1956 const file = zcu.fileByIndex(inst_info.file);1972 const file = zcu.fileByIndex(inst_info.file);
...@@ -1998,6 +2014,7 @@ pub fn updateComptimeNav(...@@ -1998,6 +2014,7 @@ pub fn updateComptimeNav(
1998 defer di_nw.deinit();2014 defer di_nw.deinit();
1999 const parent_cpi = try dwarf.getConst(pt, .fromInterned(zcu.fileRootType(inst_info.file)));2015 const parent_cpi = try dwarf.getConst(pt, .fromInterned(zcu.fileRootType(inst_info.file)));
2000 dwarf.genDeclFuncGeneric(2016 dwarf.genDeclFuncGeneric(
2017 pt,
2001 &di_nw,2018 &di_nw,
2002 zir,2019 zir,
2003 parent_cpi,2020 parent_cpi,
...@@ -2020,6 +2037,7 @@ pub fn updateComptimeNav(...@@ -2020,6 +2037,7 @@ pub fn updateComptimeNav(
2020}2037}
2021fn genDeclFuncGeneric(2038fn genDeclFuncGeneric(
2022 dwarf: *Dwarf,2039 dwarf: *Dwarf,
2040 pt: Zcu.PerThread,
2023 di_nw: *MappedFile.Node.Writer,2041 di_nw: *MappedFile.Node.Writer,
2024 zir: *const std.zig.Zir,2042 zir: *const std.zig.Zir,
2025 parent_cpi: link.ConstPool.Index,2043 parent_cpi: link.ConstPool.Index,
...@@ -2035,75 +2053,268 @@ fn genDeclFuncGeneric(...@@ -2035,75 +2053,268 @@ fn genDeclFuncGeneric(
2035 try diw.writeUleb128(decl.src_column + 1);2053 try diw.writeUleb128(decl.src_column + 1);
2036 try diw.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private);2054 try diw.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private);
2037 try dwarf.strp(&dwarf.debug_str, di_nw, name);2055 try dwarf.strp(&dwarf.debug_str, di_nw, name);
2038 for (param_body) |param_inst| switch (zir.getParamName(param_inst) orelse continue) {2056 var param_index: u32 = 0;
2039 .empty => {2057 for (param_body) |param_inst| {
2040 try diw.writeUleb128(try dwarf.refAbbrevCode(.unnamed_arg));2058 switch (zir.getParamName(param_inst) orelse break) {
2041 try diw.writeUleb128(0);2059 .empty => try diw.writeUleb128(try dwarf.refAbbrevCode(.unnamed_param)),
2042 },2060 else => |param_name| {
2043 else => |param_name| {2061 try diw.writeUleb128(try dwarf.refAbbrevCode(.param));
2044 try diw.writeUleb128(try dwarf.refAbbrevCode(.arg));2062 try dwarf.strp(&dwarf.debug_str, di_nw, zir.nullTerminatedString(param_name));
2045 try dwarf.strp(&dwarf.debug_str, di_nw, zir.nullTerminatedString(param_name));2063 },
2046 try diw.writeUleb128(0);2064 }
2047 },2065 try dwarf.sectionOffset(di_nw, Const.get(try dwarf.getConst(
2048 };2066 pt,
2067 .fromInterned(fn_ty.param_types.get(&pt.zcu.intern_pool)[param_index]),
2068 ), dwarf).debug_info_ni.unwrap().?, 0);
2069 param_index += 1;
2070 }
2049 if (fn_ty.is_var_args) try diw.writeUleb128(try dwarf.refAbbrevCode(.is_var_args));2071 if (fn_ty.is_var_args) try diw.writeUleb128(try dwarf.refAbbrevCode(.is_var_args));
2050 try diw.writeUleb128(@backingInt(AbbrevCode.null));2072 try diw.writeUleb128(@backingInt(AbbrevCode.null));
2051 try dwarf.genDebugInfoPadding(diw, diw.unusedCapacityLen());2073 try dwarf.genDebugInfoPadding(diw, diw.unusedCapacityLen());
2052}2074}
20532075
2054pub fn addConst(dwarf: *Dwarf, cpi: link.ConstPool.Index, val: InternPool.Index) link.Error!void {2076pub fn addConst(
2077 dwarf: *Dwarf,
2078 cpi: link.ConstPool.Index,
2079 val: InternPool.Index,
2080 addConstNode: *const fn (
2081 lf: *link.File,
2082 ui: Dwarf.Unit.Index,
2083 cpi: link.ConstPool.Index,
2084 ) link.Error!MappedFile.Node.Index,
2085) link.Error!void {
2055 const comp = dwarf.lf.comp;2086 const comp = dwarf.lf.comp;
2056 const zcu = comp.zcu.?;2087 const zcu = comp.zcu.?;
2057 const ip = &zcu.intern_pool;2088 const ip = &zcu.intern_pool;
2058 try dwarf.consts.ensureUnusedCapacity(comp.gpa, 1);
20592089
2060 assert(@backingInt(cpi) == dwarf.consts.items.len);2090 assert(@backingInt(cpi) == dwarf.consts.items.len);
2061 dwarf.consts.appendAssumeCapacity(.{2091 try dwarf.consts.append(comp.gpa, .{
2062 .debug_info_ni = switch (ip.indexToKey(val)) {2092 .debug_info_ni = debug_info_ni: switch (ip.indexToKey(val)) {
2063 else => .none,2093 else => try addConstNode(dwarf.lf, dwarf.getUnit(zcu.root_mod), cpi),
2064 .struct_type, .union_type, .enum_type, .opaque_type => |_, tag| debug_info_ni: {2094 .func => |func| {
2095 const fi = try dwarf.getFunc(func.owner_nav);
2096 break :debug_info_ni fi.get(dwarf).debug_info_ni.unwrap().?;
2097 },
2098 .@"extern" => |@"extern"| {
2099 const gi = try dwarf.getGlobal(@"extern".owner_nav);
2100 break :debug_info_ni gi.get(dwarf).debug_info_ni.unwrap().?;
2101 },
2102 .struct_type, .union_type, .enum_type, .opaque_type => |_, tag| {
2065 if (switch (tag) {2103 if (switch (tag) {
2104 else => unreachable,
2066 .struct_type => ip.loadStructType(val).name_nav,2105 .struct_type => ip.loadStructType(val).name_nav,
2067 .union_type => ip.loadUnionType(val).name_nav,2106 .union_type => ip.loadUnionType(val).name_nav,
2068 .enum_type => ip.loadEnumType(val).name_nav,2107 .enum_type => ip.loadEnumType(val).name_nav,
2069 .opaque_type => ip.loadOpaqueType(val).name_nav,2108 .opaque_type => ip.loadOpaqueType(val).name_nav,
2070 else => unreachable,
2071 }.unwrap()) |name_nav| {2109 }.unwrap()) |name_nav| {
2072 const name_gi = try dwarf.getGlobal(name_nav);2110 const name_gi = try dwarf.getGlobal(name_nav);
2073 break :debug_info_ni name_gi.get(dwarf).debug_info_ni.unwrap().?;2111 break :debug_info_ni name_gi.get(dwarf).debug_info_ni.unwrap().?;
2074 }2112 }
2075 const elf = dwarf.lf.cast(.elf2).?;2113 break :debug_info_ni try addConstNode(dwarf.lf, dwarf.getUnit(zcu.fileByIndex(
2076 try elf.nodes.ensureUnusedCapacity(comp.gpa, 1);2114 Type.fromInterned(val).typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip),
2077 try elf.dwarf_consts.ensureUnusedCapacity(comp.gpa, 1);2115 ).mod.?), cpi);
2078 const src_inst = Type.fromInterned(val).typeDeclInstAllowGeneratedTag(zcu).?;2116 },
2079 const unit = dwarf.getUnit(zcu.fileByIndex(src_inst.resolveFile(ip)).mod.?).get(dwarf);2117 }.toOptional(),
2080 const debug_info_ni = elf.addNodeAssumeCapacity(
2081 unit.debug_info_ni.unwrap().?.addFloatingChild(comp.gpa, &elf.mf, .{
2082 .enable_next_moved = true,
2083 }) catch |err| switch (err) {
2084 else => |e| return e,
2085 error.MappedFileIo => return comp.link_diags.fail("failed to write output file: {t}", .{
2086 elf.mf.io_err.?,
2087 }),
2088 },
2089 .{ .const_debug_info = cpi },
2090 );
2091 elf.dwarf_consts.putAssumeCapacity(cpi, .{
2092 .debug_info_first_target_reloc = .none,
2093 .debug_info_first_symbol_reloc = .none,
2094 .debug_info_first_node_reloc = .none,
2095 });
2096
2097 break :debug_info_ni debug_info_ni;
2098 }.toOptional(),
2099 },
2100 });2118 });
2101}2119}
21022120
2103pub fn updateConst(dwarf: *Dwarf, cpi: link.ConstPool.Index, val: InternPool.Index) void {2121pub fn updateConst(
2104 _ = dwarf;2122 dwarf: *Dwarf,
2105 _ = cpi;2123 pt: Zcu.PerThread,
2106 _ = val;2124 di_nw: *MappedFile.Node.Writer,
2125 val: InternPool.Index,
2126) link.Error!void {
2127 switch (val) {
2128 .generic_poison_type => log.debug("updateConst(anytype)", .{}),
2129 else => log.debug("updateConst({f})", .{Value.fromInterned(val).fmtValue(pt)}),
2130 }
2131 dwarf.updateConstInner(pt, di_nw, val) catch |err| switch (err) {
2132 else => |e| return e,
2133 error.WriteFailed => return dwarf.reportWriteError(di_nw),
2134 };
2135}
2136fn updateConstInner(
2137 dwarf: *Dwarf,
2138 pt: Zcu.PerThread,
2139 di_nw: *MappedFile.Node.Writer,
2140 val: InternPool.Index,
2141) link.EmitError!void {
2142 const zcu = pt.zcu;
2143 const ip = &zcu.intern_pool;
2144 const diw = &di_nw.interface;
2145 switch (ip.indexToKey(val)) {
2146 else => return,
2147 .struct_type => {
2148 const loaded_struct = ip.loadStructType(val);
2149 const ty: Type = .fromInterned(val);
2150 const file = loaded_struct.zir_index.resolveFile(ip);
2151 switch (loaded_struct.layout) {
2152 .auto, .@"extern" => {
2153 const struct_is_file: bool = if (loaded_struct.zir_index.resolve(ip)) |inst|
2154 inst == .main_struct_inst
2155 else
2156 false;
2157 if (loaded_struct.name_nav.unwrap()) |nav_index| {
2158 assert(!struct_is_file);
2159 const nav = ip.getNav(nav_index);
2160 const decl_inst = nav.srcInst(ip).resolve(ip).?;
2161 const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst);
2162 try diw.writeUleb128(try dwarf.refAbbrevCode(
2163 if (loaded_struct.field_types.len == 0) .decl_namespace_struct else .decl_struct,
2164 ));
2165 try dwarf.sectionOffset(di_nw, Const.get(
2166 try dwarf.getConst(pt, .fromInterned(zcu.fileRootType(file))),
2167 dwarf,
2168 ).debug_info_ni.unwrap().?, 0);
2169 try diw.writeInt(u32, decl.src_line + 1, dwarf.endian);
2170 try diw.writeUleb128(decl.src_column + 1);
2171 try diw.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private);
2172 try dwarf.strp(&dwarf.debug_str, di_nw, nav.name.toSlice(ip));
2173 } else {
2174 const zfi = loaded_struct.zir_index.resolveFile(ip);
2175 const ui = dwarf.getUnit(zcu.fileByIndex(zfi).mod.?);
2176 _, const fi = try ui.get(dwarf).getFile(zcu.gpa, ui, zfi);
2177 try diw.writeUleb128(try dwarf.refAbbrevCode(switch (loaded_struct.field_types.len) {
2178 0 => if (struct_is_file) .empty_file else .empty_struct_type,
2179 else => if (struct_is_file) .file else .struct_type,
2180 }));
2181 try diw.writeUleb128(@backingInt(fi));
2182 try dwarf.strp(&dwarf.debug_str, di_nw, loaded_struct.name.toSlice(ip));
2183 }
2184 if (loaded_struct.field_types.len == 0) {
2185 if (!struct_is_file) try diw.writeByte(@intFromBool(false));
2186 } else {
2187 try diw.writeUleb128(ty.abiSize(zcu));
2188 try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?);
2189 for (0..loaded_struct.field_types.len) |field_index| {
2190 const is_comptime = loaded_struct.field_is_comptime_bits.get(ip, field_index);
2191 // TODO: we currently don't emit information about default values for
2192 // non-`comptime` fields, because these default values are resolved at a
2193 // separate time in the compiler frontend. To emit this information, the
2194 // frontend needs to tell us when the default values are available: like
2195 // how `Zcu.PerThread.ensureTypeLayoutUpToDate` enqueues a link task to
2196 // indicate completion of the type's layout, a task should be enqueued
2197 // by `Zcu.PerThread.ensureStructDefaultsUpToDate`, and upon receiving
2198 // it we should patch the correct default field values in.
2199 const field_init: InternPool.Index = if (is_comptime) loaded_struct.field_defaults.getOrNone(ip, field_index) else .none;
2200 assert(!(is_comptime and field_init == .none));
2201 const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);
2202 const has_runtime_bits, const has_comptime_state = switch (field_init) {
2203 .none => .{ false, false },
2204 else => .{
2205 field_type.hasRuntimeBits(zcu),
2206 field_type.comptimeOnly(zcu),
2207 },
2208 };
2209 try diw.writeUleb128(try dwarf.refAbbrevCode(if (is_comptime)
2210 if (has_comptime_state)
2211 .field_comptime_comptime_state
2212 else if (has_runtime_bits)
2213 .field_comptime_runtime_bits
2214 else
2215 .field_comptime
2216 else if (field_init != .none)
2217 if (has_comptime_state)
2218 .field_default_comptime_state
2219 else if (has_runtime_bits)
2220 .field_default_runtime_bits
2221 else
2222 .field
2223 else
2224 .field));
2225 try dwarf.strp(
2226 &dwarf.debug_str,
2227 di_nw,
2228 loaded_struct.field_names.get(ip)[field_index].toSlice(ip),
2229 );
2230 try dwarf.sectionOffset(di_nw, Const.get(
2231 try dwarf.getConst(pt, field_type.toValue()),
2232 dwarf,
2233 ).debug_info_ni.unwrap().?, 0);
2234 if (!is_comptime) {
2235 try diw.writeUleb128(loaded_struct.field_offsets.get(ip)[field_index]);
2236 try diw.writeUleb128(loaded_struct.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse
2237 field_type.abiAlignment(zcu).toByteUnits().?);
2238 }
2239 if (has_comptime_state)
2240 try dwarf.sectionOffset(di_nw, Const.get(
2241 try dwarf.getConst(pt, .fromInterned(field_init)),
2242 dwarf,
2243 ).debug_info_ni.unwrap().?, 0)
2244 else if (has_runtime_bits)
2245 //try wip_nav.blockValue(.fromInterned(field_init));
2246 try diw.writeUleb128(0);
2247 }
2248 try diw.writeUleb128(@backingInt(AbbrevCode.null));
2249 }
2250 },
2251 .@"packed" => return,
2252 }
2253 },
2254 .simple_type => |simple_type| switch (simple_type) {
2255 .f16,
2256 .f32,
2257 .f64,
2258 .f80,
2259 .f128,
2260 .usize,
2261 .isize,
2262 .c_char,
2263 .c_short,
2264 .c_ushort,
2265 .c_int,
2266 .c_uint,
2267 .c_long,
2268 .c_ulong,
2269 .c_longlong,
2270 .c_ulonglong,
2271 .c_longdouble,
2272 .bool,
2273 => {
2274 const ty: Type = .fromInterned(val);
2275 try diw.writeUleb128(try dwarf.refAbbrevCode(.numeric_type));
2276 try dwarf.strp(&dwarf.debug_str, di_nw, @tagName(simple_type));
2277 try diw.writeByte(if (val == .bool_type)
2278 DW.ATE.boolean
2279 else if (ty.isRuntimeFloat())
2280 DW.ATE.float
2281 else if (ty.isSignedInt(zcu))
2282 DW.ATE.signed
2283 else if (ty.isUnsignedInt(zcu))
2284 DW.ATE.unsigned
2285 else
2286 unreachable);
2287 try diw.writeUleb128(ty.bitSize(zcu));
2288 try diw.writeUleb128(ty.abiSize(zcu));
2289 try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?);
2290 },
2291 .generic_poison => {
2292 try diw.writeUleb128(try dwarf.refAbbrevCode(.void_type));
2293 try dwarf.strp(&dwarf.debug_str, di_nw, "anytype");
2294 },
2295 .anyopaque,
2296 .void,
2297 .type,
2298 .comptime_int,
2299 .comptime_float,
2300 .noreturn,
2301 => {
2302 try diw.writeUleb128(try dwarf.refAbbrevCode(.void_type));
2303 try dwarf.strp(&dwarf.debug_str, di_nw, @tagName(simple_type));
2304 },
2305 inline .null, .undefined => |tag| {
2306 try diw.writeUleb128(try dwarf.refAbbrevCode(.void_type));
2307 try dwarf.strp(&dwarf.debug_str, di_nw, "@TypeOf(" ++ @tagName(tag) ++ ")");
2308 },
2309 .enum_literal => {
2310 try diw.writeUleb128(try dwarf.refAbbrevCode(.void_type));
2311 try dwarf.strp(&dwarf.debug_str, di_nw, "@EnumLiteral()");
2312 },
2313 .anyerror => return,
2314 .adhoc_inferred_error_set => unreachable,
2315 },
2316 }
2317 try dwarf.genDebugInfoPadding(diw, diw.unusedCapacityLen());
2107}2318}
21082319
2109pub fn updateConstIncomplete(2320pub fn updateConstIncomplete(
...@@ -2112,6 +2323,7 @@ pub fn updateConstIncomplete(...@@ -2112,6 +2323,7 @@ pub fn updateConstIncomplete(
2112 di_nw: *MappedFile.Node.Writer,2323 di_nw: *MappedFile.Node.Writer,
2113 val: InternPool.Index,2324 val: InternPool.Index,
2114) link.Error!void {2325) link.Error!void {
2326 log.debug("updateConstIncomplete({f})", .{Value.fromInterned(val).fmtValue(pt)});
2115 dwarf.updateConstIncompleteInner(pt, di_nw, val) catch |err| switch (err) {2327 dwarf.updateConstIncompleteInner(pt, di_nw, val) catch |err| switch (err) {
2116 else => |e| return e,2328 else => |e| return e,
2117 error.WriteFailed => return dwarf.reportWriteError(di_nw),2329 error.WriteFailed => return dwarf.reportWriteError(di_nw),
...@@ -2123,8 +2335,7 @@ fn updateConstIncompleteInner(...@@ -2123,8 +2335,7 @@ fn updateConstIncompleteInner(
2123 di_nw: *MappedFile.Node.Writer,2335 di_nw: *MappedFile.Node.Writer,
2124 val: InternPool.Index,2336 val: InternPool.Index,
2125) link.EmitError!void {2337) link.EmitError!void {
2126 const comp = dwarf.lf.comp;2338 const zcu = pt.zcu;
2127 const zcu = comp.zcu.?;
2128 const ip = &zcu.intern_pool;2339 const ip = &zcu.intern_pool;
2129 const diw = &di_nw.interface;2340 const diw = &di_nw.interface;
2130 done: {2341 done: {
...@@ -2133,8 +2344,8 @@ fn updateConstIncompleteInner(...@@ -2133,8 +2344,8 @@ fn updateConstIncompleteInner(
2133 const loaded_struct = ip.loadStructType(val);2344 const loaded_struct = ip.loadStructType(val);
2134 if (loaded_struct.zir_index.resolveFull(ip)) |src_inst| switch (src_inst.inst) {2345 if (loaded_struct.zir_index.resolveFull(ip)) |src_inst| switch (src_inst.inst) {
2135 .main_struct_inst => {2346 .main_struct_inst => {
2136 const ui = dwarf.getUnit(comp.zcu.?.fileByIndex(src_inst.file).mod.?);2347 const ui = dwarf.getUnit(zcu.fileByIndex(src_inst.file).mod.?);
2137 _, const fi = try ui.get(dwarf).getFile(comp.gpa, ui, src_inst.file);2348 _, const fi = try ui.get(dwarf).getFile(zcu.gpa, ui, src_inst.file);
2138 try diw.writeUleb128(try dwarf.refAbbrevCode(.empty_file));2349 try diw.writeUleb128(try dwarf.refAbbrevCode(.empty_file));
2139 try diw.writeUleb128(@backingInt(fi));2350 try diw.writeUleb128(@backingInt(fi));
2140 try dwarf.strp(&dwarf.debug_str, di_nw, loaded_struct.name.toSlice(ip));2351 try dwarf.strp(&dwarf.debug_str, di_nw, loaded_struct.name.toSlice(ip));
...@@ -2171,8 +2382,8 @@ fn updateConstIncompleteInner(...@@ -2171,8 +2382,8 @@ fn updateConstIncompleteInner(
2171 },2382 },
2172 else => |val_key| break :done switch (val_key.typeOf()) {2383 else => |val_key| break :done switch (val_key.typeOf()) {
2173 .type_type => {2384 .type_type => {
2174 const name = try comp.gpa.print("{f}", .{Type.fromInterned(val).fmt(pt)});2385 const name = try zcu.gpa.print("{f}", .{Type.fromInterned(val).fmt(pt)});
2175 defer comp.gpa.free(name);2386 defer zcu.gpa.free(name);
2176 try diw.writeUleb128(try dwarf.refAbbrevCode(.generated_empty_struct_type));2387 try diw.writeUleb128(try dwarf.refAbbrevCode(.generated_empty_struct_type));
2177 try dwarf.strp(&dwarf.debug_str, di_nw, name);2388 try dwarf.strp(&dwarf.debug_str, di_nw, name);
2178 try diw.writeByte(@intFromBool(true));2389 try diw.writeByte(@intFromBool(true));
...@@ -2203,7 +2414,7 @@ fn updateConstIncompleteInner(...@@ -2203,7 +2414,7 @@ fn updateConstIncompleteInner(
2203 try diw.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private);2414 try diw.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private);
2204 } else {2415 } else {
2205 const ui = dwarf.getUnit(zcu.fileByIndex(src_inst.file).mod.?);2416 const ui = dwarf.getUnit(zcu.fileByIndex(src_inst.file).mod.?);
2206 _, const fi = try ui.get(dwarf).getFile(comp.gpa, ui, src_inst.file);2417 _, const fi = try ui.get(dwarf).getFile(zcu.gpa, ui, src_inst.file);
2207 try diw.writeUleb128(try dwarf.refAbbrevCode(.empty_struct_type));2418 try diw.writeUleb128(try dwarf.refAbbrevCode(.empty_struct_type));
2208 try diw.writeUleb128(@backingInt(fi));2419 try diw.writeUleb128(@backingInt(fi));
2209 }2420 }
...@@ -2433,7 +2644,8 @@ pub const AbbrevCode = enum {...@@ -2433,7 +2644,8 @@ pub const AbbrevCode = enum {
2433 array_len,2644 array_len,
2434 nullary_func_type,2645 nullary_func_type,
2435 func_type,2646 func_type,
2436 func_type_param,2647 param,
2648 unnamed_param,
2437 is_var_args,2649 is_var_args,
2438 generated_empty_enum_type,2650 generated_empty_enum_type,
2439 generated_enum_type,2651 generated_enum_type,
...@@ -2651,12 +2863,12 @@ pub const AbbrevCode = enum {...@@ -2651,12 +2863,12 @@ pub const AbbrevCode = enum {
2651 .children = true,2863 .children = true,
2652 .attrs = decl_attrs ++ .{2864 .attrs = decl_attrs ++ .{
2653 .{ .linkage_name, .strp },2865 .{ .linkage_name, .strp },
2654 //.{ .type, .ref_addr },2866 .{ .type, .ref_addr },
2655 .{ .low_pc, .addr },2867 .{ .low_pc, .addr },
2656 .{ .high_pc, .data4 },2868 .{ .high_pc, .data4 },
2657 //.{ .alignment, .udata },2869 .{ .alignment, .udata },
2658 //.{ .external, .flag },2870 .{ .external, .flag },
2659 //.{ .noreturn, .flag },2871 .{ .noreturn, .flag },
2660 },2872 },
2661 },2873 },
2662 .decl_nullary_func_generic = .{2874 .decl_nullary_func_generic = .{
...@@ -2897,7 +3109,7 @@ pub const AbbrevCode = enum {...@@ -2897,7 +3109,7 @@ pub const AbbrevCode = enum {
2897 .module_dependency = .{3109 .module_dependency = .{
2898 .tag = .imported_module,3110 .tag = .imported_module,
2899 .attrs = &.{3111 .attrs = &.{
2900 .{ .name, .string },3112 .{ .name, .strp },
2901 .{ .import, .ref_addr },3113 .{ .import, .ref_addr },
2902 },3114 },
2903 },3115 },
...@@ -3148,7 +3360,14 @@ pub const AbbrevCode = enum {...@@ -3148,7 +3360,14 @@ pub const AbbrevCode = enum {
3148 .{ .type, .ref_addr },3360 .{ .type, .ref_addr },
3149 },3361 },
3150 },3362 },
3151 .func_type_param = .{3363 .param = .{
3364 .tag = .formal_parameter,
3365 .attrs = &.{
3366 .{ .name, .strp },
3367 .{ .type, .ref_addr },
3368 },
3369 },
3370 .unnamed_param = .{
3152 .tag = .formal_parameter,3371 .tag = .formal_parameter,
3153 .attrs = &.{3372 .attrs = &.{
3154 .{ .type, .ref_addr },3373 .{ .type, .ref_addr },
...@@ -3578,9 +3797,11 @@ const DW = std.dwarf;...@@ -3578,9 +3797,11 @@ const DW = std.dwarf;
3578const Dwarf = @This();3797const Dwarf = @This();
3579const InternPool = @import("../InternPool.zig");3798const InternPool = @import("../InternPool.zig");
3580const link = @import("../link.zig");3799const link = @import("../link.zig");
3800const log = std.log.scoped(.dwarf);
3581const MappedFile = @import("MappedFile.zig");3801const MappedFile = @import("MappedFile.zig");
3582const Module = @import("../Module.zig");3802const Module = @import("../Module.zig");
3583const std = @import("std");3803const std = @import("std");
3804const target_info = @import("../target.zig");
3584const Type = @import("../Type.zig");3805const Type = @import("../Type.zig");
3585const Value = @import("../Value.zig");3806const Value = @import("../Value.zig");
3586const Writer = std.Io.Writer;3807const Writer = std.Io.Writer;
src/link/Elf2.zig+96-42
...@@ -5954,15 +5954,11 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) Error!Node...@@ -5954,15 +5954,11 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) Error!Node
5954 .@"fn" => a: {5954 .@"fn" => a: {
5955 const mod = zcu.navFileScope(nav_index).mod.?;5955 const mod = zcu.navFileScope(nav_index).mod.?;
5956 const target = &mod.resolved_target.result;5956 const target = &mod.resolved_target.result;
5957 const min = target_util.minFunctionAlignment(target);
5958 break :a .fromIp(switch (nav.resolved.?.@"align") {5957 break :a .fromIp(switch (nav.resolved.?.@"align") {
5959 else => |a| a.maxStrict(min),5958 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),
5960 .none => switch (mod.optimize_mode) {5959 .none => switch (mod.optimize_mode) {
5961 .debug,5960 .debug, .safe, .fast => target_util.defaultFunctionAlignment(target),
5962 .safe,5961 .small => target_util.minFunctionAlignment(target),
5963 .fast,
5964 => target_util.defaultFunctionAlignment(target),
5965 .small => min,
5966 }.maxStrict(Type.fromInterned(nav.resolved.?.type).abiAlignment(zcu)),5962 }.maxStrict(Type.fromInterned(nav.resolved.?.type).abiAlignment(zcu)),
5967 });5963 });
5968 },5964 },
...@@ -8626,25 +8622,71 @@ pub fn updateContainerTypeInner(...@@ -8626,25 +8622,71 @@ pub fn updateContainerTypeInner(
8626pub fn addConst(8622pub fn addConst(
8627 elf: *Elf,8623 elf: *Elf,
8628 _: Zcu.PerThread,8624 _: Zcu.PerThread,
8629 index: link.ConstPool.Index,8625 cpi: link.ConstPool.Index,
8630 val: InternPool.Index,8626 val: InternPool.Index,
8631) link.Error!void {8627) link.Error!void {
8632 switch (elf.base.comp.config.debug_format) {8628 switch (elf.base.comp.config.debug_format) {
8633 .strip => {},8629 .strip => {},
8634 .dwarf => try elf.dwarf.addConst(index, val),8630 .dwarf => {
8631 const gpa = elf.base.comp.gpa;
8632 try elf.nodes.ensureUnusedCapacity(gpa, 1);
8633 try elf.dwarf_consts.ensureUnusedCapacity(gpa, 1);
8634 try elf.dwarf.addConst(cpi, val, &addConstNode);
8635 elf.dwarf_consts.putAssumeCapacity(cpi, .{
8636 .debug_info_first_target_reloc = .none,
8637 .debug_info_first_symbol_reloc = .none,
8638 .debug_info_first_node_reloc = .none,
8639 });
8640 },
8635 .code_view => unreachable,8641 .code_view => unreachable,
8636 }8642 }
8637}8643}
8644fn addConstNode(lf: *link.File, ui: Dwarf.Unit.Index, cpi: link.ConstPool.Index) link.Error!MappedFile.Node.Index {
8645 const elf = lf.cast(.elf2).?;
8646 const unit = ui.get(&elf.dwarf);
8647 return elf.addNodeAssumeCapacity(
8648 unit.debug_info_ni.unwrap().?.addFloatingChild(lf.comp.gpa, &elf.mf, .{
8649 .enable_next_moved = true,
8650 }) catch |err| switch (err) {
8651 else => |e| return e,
8652 error.MappedFileIo => return lf.comp.link_diags.fail("failed to write output file: {t}", .{
8653 elf.mf.io_err.?,
8654 }),
8655 },
8656 .{ .const_debug_info = cpi },
8657 );
8658}
86388659
8639pub fn updateConst(8660pub fn updateConst(
8640 elf: *Elf,8661 elf: *Elf,
8641 _: Zcu.PerThread,8662 pt: Zcu.PerThread,
8663 cpi: link.ConstPool.Index,
8664 val: InternPool.Index,
8665) link.Error!void {
8666 switch (val) {
8667 .anyerror_type => {}, // handled in `updateErrorData` instead
8668 else => try elf.updateConstInner(pt, cpi, val),
8669 }
8670}
8671fn updateConstInner(
8672 elf: *Elf,
8673 pt: Zcu.PerThread,
8642 cpi: link.ConstPool.Index,8674 cpi: link.ConstPool.Index,
8643 val: InternPool.Index,8675 val: InternPool.Index,
8644) link.Error!void {8676) link.Error!void {
8677 if (val == .anyerror_type) return; // handled in `updateErrorData` instead
8645 switch (elf.base.comp.config.debug_format) {8678 switch (elf.base.comp.config.debug_format) {
8646 .strip => {},8679 .strip => {},
8647 .dwarf => elf.dwarf.updateConst(cpi, val),8680 .dwarf => {
8681 const gpa = elf.base.comp.gpa;
8682 const debug_info_ni = Dwarf.Const.get(cpi, &elf.dwarf).debug_info_ni.unwrap().?;
8683 try debug_info_ni.moved(gpa, &elf.mf);
8684 var di_nw: MappedFile.Node.Writer = undefined;
8685 debug_info_ni.writer(gpa, &elf.mf, &di_nw);
8686 defer di_nw.deinit();
8687 elf.resetNodeRelocs(debug_info_ni);
8688 try elf.dwarf.updateConst(pt, &di_nw, val);
8689 },
8648 .code_view => unreachable,8690 .code_view => unreachable,
8649 }8691 }
8650}8692}
...@@ -8658,10 +8700,13 @@ pub fn updateConstIncomplete(...@@ -8658,10 +8700,13 @@ pub fn updateConstIncomplete(
8658 switch (elf.base.comp.config.debug_format) {8700 switch (elf.base.comp.config.debug_format) {
8659 .strip => {},8701 .strip => {},
8660 .dwarf => {8702 .dwarf => {
8703 const gpa = elf.base.comp.gpa;
8661 const debug_info_ni = Dwarf.Const.get(cpi, &elf.dwarf).debug_info_ni.unwrap().?;8704 const debug_info_ni = Dwarf.Const.get(cpi, &elf.dwarf).debug_info_ni.unwrap().?;
8705 try debug_info_ni.moved(gpa, &elf.mf);
8662 var di_nw: MappedFile.Node.Writer = undefined;8706 var di_nw: MappedFile.Node.Writer = undefined;
8663 debug_info_ni.writer(elf.base.comp.gpa, &elf.mf, &di_nw);8707 debug_info_ni.writer(gpa, &elf.mf, &di_nw);
8664 defer di_nw.deinit();8708 defer di_nw.deinit();
8709 elf.resetNodeRelocs(debug_info_ni);
8665 try elf.dwarf.updateConstIncomplete(pt, &di_nw, val);8710 try elf.dwarf.updateConstIncomplete(pt, &di_nw, val);
8666 },8711 },
8667 .code_view => unreachable,8712 .code_view => unreachable,
...@@ -8952,16 +8997,19 @@ pub fn lostTracking(...@@ -8952,16 +8997,19 @@ pub fn lostTracking(
8952}8997}
89538998
8954pub fn updateErrorData(elf: *Elf, pt: Zcu.PerThread) link.Error!void {8999pub fn updateErrorData(elf: *Elf, pt: Zcu.PerThread) link.Error!void {
8955 elf.genLazyInner(pt, .{9000 const comp = elf.base.comp;
9001 if (elf.lazy.getPtr(.const_data).map.getIndex(.anyerror_type)) |lmi| elf.genLazyInner(pt, .{
8956 .kind = .const_data,9002 .kind = .const_data,
8957 .index = @intCast(elf.lazy.getPtr(.const_data).map.getIndex(.anyerror_type) orelse return),9003 .index = @intCast(lmi),
8958 }) catch |err| switch (err) {9004 }) catch |err| switch (err) {
8959 else => |e| return e,9005 else => |e| return e,
8960 error.MappedFileIo => return elf.base.comp.link_diags.fail(9006 error.MappedFileIo => return comp.link_diags.fail(
8961 "failed to write output file: {t}",9007 "failed to write output file: {t}",
8962 .{elf.mf.io_err.?},9008 .{elf.mf.io_err.?},
8963 ),9009 ),
8964 };9010 };
9011 if (elf.dwarf.const_pool.getIfExists(.anyerror_type)) |cpi|
9012 try elf.updateConstInner(pt, cpi, .anyerror_type);
8965}9013}
89669014
8967pub fn flush(9015pub fn flush(
...@@ -9258,10 +9306,12 @@ fn idleProgNode(...@@ -9258,10 +9306,12 @@ fn idleProgNode(
9258 },9306 },
9259 ui.mod(&elf.dwarf).fully_qualified_name,9307 ui.mod(&elf.dwarf).fully_qualified_name,
9260 }) catch &name,9308 }) catch &name,
9261 .const_debug_info => |cpi| std.mem.print(&name, "debug info for {f}", .{9309 .const_debug_info => |cpi| switch (cpi.val(&elf.dwarf.const_pool)) {
9262 Value.fromInterned(cpi.val(&elf.dwarf.const_pool))9310 .generic_poison_type => "anytype",
9263 .fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }),9311 else => |val| std.mem.print(&name, "debug info for {f}", .{
9264 }) catch &name,9312 Value.fromInterned(val).fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }),
9313 }) catch &name,
9314 },
9265 .global_debug_info => |gi| {9315 .global_debug_info => |gi| {
9266 const ip = &elf.base.comp.zcu.?.intern_pool;9316 const ip = &elf.base.comp.zcu.?.intern_pool;
9267 break :name std.mem.print(&name, "debug info for {f}", .{9317 break :name std.mem.print(&name, "debug info for {f}", .{
...@@ -10790,12 +10840,12 @@ pub fn printNode(...@@ -10790,12 +10840,12 @@ pub fn printNode(
10790 .unit_debug_line_header,10840 .unit_debug_line_header,
10791 .unit_debug_rnglists,10841 .unit_debug_rnglists,
10792 => |ui| try w.print("({s})", .{ui.mod(&elf.dwarf).fully_qualified_name}),10842 => |ui| try w.print("({s})", .{ui.mod(&elf.dwarf).fully_qualified_name}),
10793 .const_debug_info => |cpi| try w.print("({f})", .{10843 .const_debug_info => |cpi| switch (cpi.val(&elf.dwarf.const_pool)) {
10794 Value.fromInterned(cpi.val(&elf.dwarf.const_pool)).fmtValue(.{10844 .generic_poison_type => try w.writeAll("(anytype)"),
10795 .zcu = elf.base.comp.zcu.?,10845 else => |val| try w.print("({f})", .{
10796 .tid = tid,10846 Value.fromInterned(val).fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }),
10797 }),10847 }),
10798 }),10848 },
10799 .global_debug_info => |gi| {10849 .global_debug_info => |gi| {
10800 const zcu = elf.base.comp.zcu.?;10850 const zcu = elf.base.comp.zcu.?;
10801 const ip = &zcu.intern_pool;10851 const ip = &zcu.intern_pool;
...@@ -10839,26 +10889,30 @@ pub fn printNode(...@@ -10839,26 +10889,30 @@ pub fn printNode(
10839 }10889 }
10840 return;10890 return;
10841 }10891 }
10842 const file_loc = ni.fileLocation(&elf.mf, false);10892 const start_address: usize, const end_address: usize = file_loc: {
10843 var address = file_loc.offset;10893 const file_loc = ni.fileLocation(&elf.mf, false);
10844 if (file_loc.size == 0) {10894 break :file_loc .{ @intCast(file_loc.offset), @intCast(file_loc.offset + file_loc.size) };
10845 try w.splatByteAll(' ', indent + 1);10895 };
10846 try w.print("{x:0>8}\n", .{address});10896 var address = start_address;
10847 return;
10848 }
10849 const line_len = 0x10;10897 const line_len = 0x10;
10850 var line_it = std.mem.window(10898 while (true) : (address = @min(std.mem.alignForward(usize, address + 1, line_len), end_address)) {
10851 u8,
10852 elf.mf.memory_map.memory[@intCast(file_loc.offset)..][0..@intCast(file_loc.size)],
10853 line_len,
10854 line_len,
10855 );
10856 while (line_it.next()) |line_bytes| : (address += line_len) {
10857 try w.splatByteAll(' ', indent + 1);10899 try w.splatByteAll(' ', indent + 1);
10858 try w.print("{x:0>8} ", .{address});10900 try w.print("{x:0>8}", .{address});
10859 for (line_bytes) |byte| try w.print("{x:0>2} ", .{byte});10901 if (address == end_address) break try w.writeByte('\n');
10860 try w.splatByteAll(' ', 3 * (line_len - line_bytes.len) + 1);10902 try w.splatByteAll(' ', 2);
10861 for (line_bytes) |byte| try w.writeByte(if (std.ascii.isPrint(byte)) byte else '.');10903 const start_byte_address = std.mem.alignBackward(usize, address, line_len);
10904 const end_byte_address = start_byte_address + line_len;
10905 for (start_byte_address..end_byte_address) |byte_address|
10906 if (byte_address < start_address or byte_address >= end_address)
10907 try w.splatByteAll(' ', 3)
10908 else
10909 try w.print("{x:0>2} ", .{elf.mf.memory_map.memory[byte_address]});
10910 try w.writeByte(' ');
10911 for (start_byte_address..@min(end_address, end_byte_address)) |byte_address|
10912 try w.writeByte(if (byte_address < start_address or byte_address >= end_address) ' ' else char: {
10913 const byte = elf.mf.memory_map.memory[byte_address];
10914 break :char if (std.ascii.isPrint(byte)) byte else '.';
10915 });
10862 try w.writeByte('\n');10916 try w.writeByte('\n');
10863 }10917 }
10864}10918}