diff --git a/src/Zcu.zig b/src/Zcu.zig index 0e812d3faa42a1f0bb189f86f856e61149d5484d..d6f9da974052860224583dd47cd3b6e44c90d056 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -2754,7 +2754,7 @@ pub const LazySrcLoc = struct { if (zir_inst == .main_struct_inst) return .{ file, .root }; // Otherwise, make sure ZIR is loaded. - const zir = file.zir.?; + const zir = &file.zir.?; const inst = zir.instructions.get(@backingInt(zir_inst)); const base_node: Ast.Node.Index = switch (inst.tag) { @@ -3045,7 +3045,7 @@ pub fn saveZirCache( gpa: Allocator, cache_file_writer: *Io.File.Writer, stat: Io.File.Stat, - zir: Zir, + zir: *const Zir, ) (Io.File.Writer.Error || Allocator.Error)!void { const safety_buffer = if (data_has_safety_tag) try gpa.alloc([8]u8, zir.instructions.len) @@ -3085,7 +3085,7 @@ pub fn saveZirCache( }; } -pub fn saveZoirCache(cache_file_writer: *Io.File.Writer, stat: Io.File.Stat, zoir: Zoir) Io.File.Writer.Error!void { +pub fn saveZoirCache(cache_file_writer: *Io.File.Writer, stat: Io.File.Stat, zoir: *const Zoir) Io.File.Writer.Error!void { const header: Zoir.Header = .{ .nodes_len = @intCast(zoir.nodes.len), .extra_len = @intCast(zoir.extra.len), @@ -3399,8 +3399,8 @@ pub fn flushRetryableFailures(zcu: *Zcu) !void { pub fn mapOldZirToNew( gpa: Allocator, - old_zir: Zir, - new_zir: Zir, + old_zir: *const Zir, + new_zir: *const Zir, inst_map: *std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index), ) Allocator.Error!void { // Contain ZIR indexes of namespace declaration instructions, e.g. struct_decl, union_decl, etc. diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index 06bbdf9d3ddae622fe4aeffe118b06c8c03b942e..bfcf8dca46a25500bda95171d37dfa4a27710fed 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -389,17 +389,18 @@ fn workerUpdateFile( // Discover all imports in the file. Imports of modules we ignore for now since we don't // know which module we're in, but imports of file paths might need us to queue up other // AstGen jobs. - const imports_index = file.zir.?.extra[@backingInt(Zir.ExtraIndex.imports)]; + const zir = &file.zir.?; + const imports_index = zir.extra[@backingInt(Zir.ExtraIndex.imports)]; if (imports_index != 0) { - const extra = file.zir.?.extraData(Zir.Inst.Imports, imports_index); + const extra = zir.extraData(Zir.Inst.Imports, imports_index); var import_i: u32 = 0; var extra_index = extra.end; while (import_i < extra.data.imports_len) : (import_i += 1) { - const item = file.zir.?.extraData(Zir.Inst.Imports.Item, extra_index); + const item = zir.extraData(Zir.Inst.Imports.Item, extra_index); extra_index = item.end; - const import_path = file.zir.?.nullTerminatedString(item.data.name); + const import_path = zir.nullTerminatedString(item.data.name); if (active.pt.discoverImport(file.path, import_path)) |res| switch (res) { .module, .existing_file => {}, @@ -652,7 +653,7 @@ pub fn updateFile( switch (file.getMode()) { .zig => { file.zir = try AstGen.generate(gpa, file.tree.?); - Zcu.saveZirCache(gpa, &cache_file_writer, stat, file.zir.?) catch |err| switch (err) { + Zcu.saveZirCache(gpa, &cache_file_writer, stat, &file.zir.?) catch |err| switch (err) { error.OutOfMemory => |e| return e, else => log.warn("unable to write cached ZIR code for {f} to {f}{s}: {t}", .{ file.path.fmt(comp), cache_directory, &hex_digest, err, @@ -661,7 +662,7 @@ pub fn updateFile( }, .zon => { file.zoir = try ZonGen.generate(gpa, file.tree.?, .{}); - Zcu.saveZoirCache(&cache_file_writer, stat, file.zoir.?) catch |err| { + Zcu.saveZoirCache(&cache_file_writer, stat, &file.zoir.?) catch |err| { log.warn("unable to write cached ZOIR code for {f} to {f}{s}: {t}", .{ file.path.fmt(comp), cache_directory, &hex_digest, err, }); @@ -694,12 +695,13 @@ pub fn updateFile( switch (file.getMode()) { .zig => { - if (file.zir.?.hasCompileErrors()) { + const zir = &file.zir.?; + if (zir.hasCompileErrors()) { comp.mutex.lockUncancelable(io); defer comp.mutex.unlock(io); try zcu.failed_files.putNoClobber(gpa, file_index, null); } - if (file.zir.?.loweringFailed()) { + if (zir.loweringFailed()) { file.status = .astgen_failure; } else { file.status = .success; @@ -829,14 +831,14 @@ fn updateZirRefs(pt: Zcu.PerThread) (Io.Cancelable || Allocator.Error)!void { }, } const old_zir = file.prev_zir orelse continue; - const new_zir = file.zir.?; + const new_zir = &file.zir.?; const gop = try updated_files.getOrPut(gpa, file_index); assert(!gop.found_existing); gop.value_ptr.* = .{ .file = file, .inst_map = .{}, }; - try Zcu.mapOldZirToNew(gpa, old_zir.*, new_zir, &gop.value_ptr.inst_map); + try Zcu.mapOldZirToNew(gpa, old_zir, new_zir, &gop.value_ptr.inst_map); } if (updated_files.count() == 0) @@ -870,7 +872,7 @@ fn updateZirRefs(pt: Zcu.PerThread) (Io.Cancelable || Allocator.Error)!void { const old_tag = old_zir.instructions.items(.tag)[@backingInt(old_inst)]; const old_data = old_zir.instructions.items(.data)[@backingInt(old_inst)]; - const new_zir = file.zir.?; + const new_zir = &file.zir.?; const new_data = new_zir.instructions.items(.data)[@backingInt(new_inst)]; debug_update_line_number: { @@ -2640,7 +2642,7 @@ fn computeAliveFiles(pt: Zcu.PerThread) Allocator.Error!bool { if (file.status != .success) continue; // ZIR not valid if there was a file failure - const zir = file.zir.?; + const zir = &file.zir.?; const imports_index = zir.extra[@backingInt(Zir.ExtraIndex.imports)]; if (imports_index == 0) continue; // this Zig file has no imports const extra = zir.extraData(Zir.Inst.Imports, imports_index); @@ -2655,7 +2657,13 @@ fn computeAliveFiles(pt: Zcu.PerThread) Allocator.Error!bool { // We've not necessarily generated builtin modules yet, so `doImport` could fail. Instead, // create the module here. Then, since we know that `builtin.zig` doesn't have an error and // has no imports other than 'std', we can just continue onto the next import. - try pt.updateBuiltinModule(file.mod.?.getBuiltinOptions(comp.config)); + const res = try pt.updateBuiltinModule(file.mod.?.getBuiltinOptions(comp.config)); + const gop = zcu.alive_files.getOrPutAssumeCapacity(res.file); + if (!gop.found_existing) gop.value_ptr.* = .{ .import = .{ + .importer = file_idx, + .tok = item.data.token, + .module = res.module_root, + } }; continue; } @@ -2754,14 +2762,20 @@ fn computeAliveFiles(pt: Zcu.PerThread) Allocator.Error!bool { /// up-to-date, setting a misc failure if updating it fails. /// Asserts that the imported `builtin.zig` has no ZIR errors, and that it has only one /// import, which is 'std'. -pub fn updateBuiltinModule(pt: Zcu.PerThread, opts: Builtin) Allocator.Error!void { +fn updateBuiltinModule(pt: Zcu.PerThread, opts: Builtin) Allocator.Error!struct { + file: Zcu.File.Index, + module_root: *Module, +} { const zcu = pt.zcu; const comp = zcu.comp; const gpa = comp.gpa; const io = comp.io; const gop = try zcu.builtin_modules.getOrPut(gpa, opts.hash()); - if (gop.found_existing) return; // the `File` is up-to-date + if (gop.found_existing) return .{ // the `File` is up-to-date + .file = zcu.module_roots.get(gop.value_ptr.*).?.unwrap().?, + .module_root = gop.value_ptr.*, + }; errdefer _ = zcu.builtin_modules.pop(); const mod: *Module = try .createBuiltin(comp.arena, opts, comp.dirs); @@ -2809,15 +2823,16 @@ pub fn updateBuiltinModule(pt: Zcu.PerThread, opts: Builtin) Allocator.Error!voi try opts.populateFile(gpa, file); assert(file.status == .success); - assert(!file.zir.?.hasCompileErrors()); + const zir = &file.zir.?; + assert(!zir.hasCompileErrors()); { // Check that it has only one import, which is 'std'. - const imports_idx = file.zir.?.extra[@backingInt(Zir.ExtraIndex.imports)]; + const imports_idx = zir.extra[@backingInt(Zir.ExtraIndex.imports)]; assert(imports_idx != 0); // there is an import - const extra = file.zir.?.extraData(Zir.Inst.Imports, imports_idx); + const extra = zir.extraData(Zir.Inst.Imports, imports_idx); assert(extra.data.imports_len == 1); // there is exactly one import - const item = file.zir.?.extraData(Zir.Inst.Imports.Item, extra.end); - const import_path = file.zir.?.nullTerminatedString(item.data.name); + const item = zir.extraData(Zir.Inst.Imports.Item, extra.end); + const import_path = zir.nullTerminatedString(item.data.name); assert(mem.eql(u8, import_path, "std")); // the single import is of 'std' } @@ -2826,6 +2841,10 @@ pub fn updateBuiltinModule(pt: Zcu.PerThread, opts: Builtin) Allocator.Error!voi "unable to write '{f}': {s}", .{ file.path.fmt(comp), @errorName(err) }, ); + return .{ + .file = file_index, + .module_root = mod, + }; } pub fn embedFile( @@ -3137,7 +3156,7 @@ const ScanDeclIter = struct { const gpa = comp.gpa; const io = comp.io; const file = namespace.fileScope(zcu); - const zir = file.zir.?; + const zir = &file.zir.?; const ip = &zcu.intern_pool; const decl = zir.getDeclaration(decl_inst); @@ -3572,11 +3591,11 @@ fn lockAndClearFileCompileError(pt: Zcu.PerThread, file_index: Zcu.File.Index, f .astgen_failure => true, .success => switch (file.getMode()) { .zig => has_error: { - const zir = file.zir orelse break :has_error false; + const zir = &(file.zir orelse break :has_error false); break :has_error zir.hasCompileErrors(); }, .zon => has_error: { - const zoir = file.zoir orelse break :has_error false; + const zoir = &(file.zoir orelse break :has_error false); break :has_error zoir.hasCompileErrors(); }, }, diff --git a/src/codegen/x86_64/Emit.zig b/src/codegen/x86_64/Emit.zig index 7196aca6ef02eee3b07bcdf58d84822ee550877d..0955a8d91b10ad9687fb522e76db3a03778258f0 100644 --- a/src/codegen/x86_64/Emit.zig +++ b/src/codegen/x86_64/Emit.zig @@ -552,9 +552,9 @@ pub fn emitMir(emit: *Emit) Error!void { .pseudo_dbg_var_m, => switch (emit.debug_output) { inline .dwarf, .dwarf2 => |dwarf, tag| { - const DwarfLoc = switch (tag) { - .dwarf => link.File.Dwarf.Loc, - .dwarf2 => link.File.Dwarf2.Loc, + const DwarfLoc, const addr_loc = switch (tag) { + .dwarf => .{ link.File.Dwarf.Loc, "addr_reloc" }, + .dwarf2 => .{ link.File.Dwarf2.Loc, "addrx_sym" }, .eh_frame, .none => comptime unreachable, }; var loc_buf: [2]DwarfLoc = undefined; @@ -597,16 +597,21 @@ pub fn emitMir(emit: *Emit) Error!void { .none => .{ .constu = 0 }, .reg => |reg| .{ .breg = reg.dwarfNum() }, .frame, .table, .rip_inst => unreachable, - .nav => |nav| .{ .addr_reloc = try codegen.genNavRef( - emit.bin_file, - emit.pt, - nav, - ) }, - .uav => |uav| .{ .addr_reloc = try emit.bin_file.lowerUav( - emit.pt, - uav.val, - Type.fromInterned(uav.orig_ty).ptrAlignment(emit.pt.zcu), - ) }, + .nav => |nav| @unionInit( + DwarfLoc, + addr_loc, + try codegen.genNavRef(emit.bin_file, emit.pt, nav), + ), + .uav => |uav| @unionInit( + DwarfLoc, + addr_loc, + try emit.bin_file.lowerUav( + emit.pt, + uav.val, + Type.fromInterned(uav.orig_ty) + .ptrAlignment(emit.pt.zcu), + ), + ), .lazy_sym, .extern_func => unreachable, }; break :base &loc_buf[0]; diff --git a/src/codegen/x86_64/Mir.zig b/src/codegen/x86_64/Mir.zig index 763378dd4bb41acafb46c7302286f12aa8dde08b..eb56298da4647617101a8339a89112ec6884e649 100644 --- a/src/codegen/x86_64/Mir.zig +++ b/src/codegen/x86_64/Mir.zig @@ -2009,7 +2009,7 @@ pub fn emit( .column = func.lbrace_column, .is_stmt = switch (debug_output) { .dwarf => |dwarf| dwarf.dwarf.debug_line.header.default_is_stmt, - .dwarf2 => |dwarf| dwarf.wip_nav.dwarf.debug_line.header.default_is_stmt, + .dwarf2 => |dwarf| dwarf.wip_func.dwarf.debug_line.header.default_is_stmt, .eh_frame, .none => undefined, }, }, diff --git a/src/link.zig b/src/link.zig index 056251dcd9431a90d35720769f71ff08f9db21ec..babee6e563e072fd863c3622be6107fdac6a35fd 100644 --- a/src/link.zig +++ b/src/link.zig @@ -755,8 +755,8 @@ pub const File = struct { pub const DebugInfoOutput = union(enum) { dwarf: *Dwarf.WipNav, - eh_frame: *Dwarf2.WipNav, - dwarf2: *Dwarf2.WipNav.Debug, + eh_frame: *Dwarf2.WipFunc, + dwarf2: *Dwarf2.WipFunc.Debug, none, }; pub const UpdateDebugInfoError = Dwarf.UpdateError; diff --git a/src/link/Dwarf2.zig b/src/link/Dwarf2.zig index 20ab9a14877402921eb62c09c2b0f2a68dbcc541..d03bbd284a87b7ff75738c874551c20c4e27617f 100644 --- a/src/link/Dwarf2.zig +++ b/src/link/Dwarf2.zig @@ -10,9 +10,10 @@ consts: std.ArrayList(Const), globals: std.array_hash_map.Auto(InternPool.Nav.Index, Global), funcs: std.array_hash_map.Auto(InternPool.Nav.Index, Func), decls: std.array_hash_map.Auto(InternPool.TrackedInst.Index, Decl), -pending_decl: struct { di: Decl.Index, instance_val: InternPool.Index }, +pending_decl: struct { di: Decl.Index, instance: Decl.Instance }, debug_abbrev: Abbrev, +debug_addr: Addr, frame: Frame, debug_info: Info, debug_line: Line, @@ -81,6 +82,7 @@ pub const Unit = struct { ui: Unit.Index, zfi: Zcu.File.Index, ) std.mem.Allocator.Error!struct { DirIndex, FileIndex } { + assert(unit.alive); try unit.dirs.ensureUnusedCapacity(gpa, 1); try unit.files.ensureUnusedCapacity(gpa, 1); const dir_gop = unit.dirs.getOrPutAssumeCapacity(ui); @@ -154,6 +156,12 @@ pub const Decl = struct { return &dwarf.decls.values()[@backingInt(di)]; } }; + + const Instance = union(enum) { + none, + @"const": InternPool.Index, + global: InternPool.Nav.Index, + }; }; pub const Frame = struct { @@ -175,6 +183,29 @@ pub const Abbrev = struct { set: std.enums.EnumSet(AbbrevCode), }; +pub const Addr = struct { + ni: link.MappedFile.Node.Index.Optional, + pending_index: usize, + map: std.array_hash_map.Auto(link.File.SymbolId, void), + + fn get(a: *Addr, gpa: std.mem.Allocator, si: link.File.SymbolId) std.mem.Allocator.Error!usize { + const gop = try a.map.getOrPut(gpa, si); + return gop.index; + } + + fn tableOffset(dwarf: *Dwarf) usize { + return dwarf.unitLengthSize() + 2 + 1 + 1; + } + + pub fn size(a: *Addr, dwarf: *Dwarf) usize { + return tableOffset(dwarf) + @backingInt(dwarf.address_size) * a.pending_index; + } + + pub fn anyPending(a: *Addr) bool { + return a.map.count() - a.pending_index > 0; + } +}; + pub const Info = struct {}; pub const Line = struct { @@ -192,8 +223,8 @@ pub const Line = struct { pub const Str = struct { ni: link.MappedFile.Node.Index.Optional, - offset: usize, - map: std.HashMapUnmanaged(usize, void, Context, std.hash_map.default_max_load_percentage), + end: usize, + map: std.array_hash_map.Custom(usize, void, Context, true), fn get( s: *Str, @@ -210,21 +241,21 @@ pub const Str = struct { .{ .slice = slice }, ); if (!gop.found_existing) { - gop.key_ptr.* = s.offset; - try ni.ensureMinimumSize(gpa, mf, s.offset + str.len + 1); + gop.key_ptr.* = s.end; + try ni.ensureMinimumSize(gpa, mf, s.end + str.len + 1); const slice_mut = ni.slice(mf); - @memcpy(slice_mut[s.offset..][0..str.len], str); - s.offset += str.len; - slice_mut[s.offset] = 0; - s.offset += 1; + @memcpy(slice_mut[s.end..][0..str.len], str); + s.end += str.len; + slice_mut[s.end] = 0; + s.end += 1; } return gop.key_ptr.*; } const Context = struct { slice: []const u8, - pub fn hash(context: Context, offset: usize) u64 { - return std.hash.Wyhash.hash(0, std.mem.sliceTo(context.slice[offset..], 0)); + pub fn hash(context: Context, offset: usize) u32 { + return @truncate(std.hash.Wyhash.hash(0, std.mem.sliceTo(context.slice[offset..], 0))); } pub fn eql(_: Context, lhs_offset: usize, rhs_offset: usize) bool { return lhs_offset == rhs_offset; @@ -233,10 +264,10 @@ pub const Str = struct { const Adapter = struct { slice: []const u8, - pub fn hash(_: Adapter, key: []const u8) u64 { - return std.hash.Wyhash.hash(0, key); + pub fn hash(_: Adapter, key: []const u8) u32 { + return @truncate(std.hash.Wyhash.hash(0, key)); } - pub fn eql(adapter: Adapter, key: []const u8, rhs_offset: usize) bool { + pub fn eql(adapter: Adapter, key: []const u8, rhs_offset: usize, _: usize) bool { return std.mem.startsWith(u8, adapter.slice[rhs_offset..], key) and adapter.slice[rhs_offset + key.len] == 0; } @@ -244,21 +275,60 @@ pub const Str = struct { }; pub const Rnglists = struct { - fn offsetsTableOffset(dwarf: *Dwarf) usize { + fn tableOffset(dwarf: *Dwarf) usize { return dwarf.unitLengthSize() + 2 + 1 + 1 + 4; } + + pub fn size(dwarf: *Dwarf, ui: Unit.Index) usize { + return ui.get(dwarf).debug_rnglists_end + 1; + } }; pub const StrOffsets = struct { ni: link.MappedFile.Node.Index.Optional, - offset: usize, + pending_index: usize, + map: std.array_hash_map.Auto(usize, void), + + fn get( + so: *StrOffsets, + dwarf: *Dwarf, + s: *Str, + mf: *link.MappedFile, + str: []const u8, + ) link.Error!usize { + const comp = dwarf.lf.comp; + try so.map.ensureUnusedCapacity(comp.gpa, 1); + const offset = s.get(comp.gpa, mf, str) catch |err| switch (err) { + else => |e| return e, + error.MappedFileIo => return comp.link_diags.fail("failed to write output file: {t}", .{ + mf.io_err.?, + }), + }; + const gop = so.map.getOrPutAssumeCapacity(offset); + return gop.index; + } + + fn tableOffset(dwarf: *Dwarf) usize { + return dwarf.unitLengthSize() + 2 + 2; + } + + pub fn size(so: *StrOffsets, dwarf: *Dwarf) usize { + return tableOffset(dwarf) + dwarf.secOffsetSize() * so.pending_index; + } + + pub fn anyPending(so: *StrOffsets) bool { + return so.map.count() - so.pending_index > 0; + } }; -pub const SharedSection = enum { debug_abbrev, debug_line_str, debug_str, debug_str_offsets }; +pub const SharedSection = enum { debug_abbrev, debug_line_str, debug_str }; pub const Loc = union(enum) { empty, - addr_reloc: link.File.SymbolId, + addr_sym: struct { + si: link.File.SymbolId, + offset: usize = 0, + }, deref: *const Loc, constu: u64, consts: i64, @@ -277,6 +347,8 @@ pub const Loc = union(enum) { node: link.MappedFile.Node.Index, offset: i65 = 0, }, + addrx_sym: link.File.SymbolId, + constx_sym: link.File.SymbolId, wasm_ext: union(enum) { local: u32, global: u32, @@ -319,11 +391,11 @@ pub const Loc = union(enum) { }; switch (loc) { .empty => {}, - .addr_reloc => |si| { + .addr_sym => |sym| { try w.writeByte(DW.OP.addr); switch (writer) { .io => try dwarf.addrPlaceholder(w), - .mf => |nw| try dwarf.addrSym(nw, si, 0), + .mf => |nw| try dwarf.addrSym(nw, sym.si, sym.offset), } }, .deref => |addr| { @@ -442,6 +514,14 @@ pub const Loc = union(enum) { } try w.writeSleb128(implicit_pointer.offset); }, + .addrx_sym => |si| { + try w.writeByte(DW.OP.addrx); + try dwarf.addrxSym(w, si); + }, + .constx_sym => |si| { + try w.writeByte(DW.OP.constx); + try dwarf.addrxSym(w, si); + }, .wasm_ext => |wasm_ext| { try w.writeByte(DW.OP.WASM_location); switch (wasm_ext) { @@ -490,33 +570,33 @@ pub const Cfa = union(enum) { const RegOff = struct { reg: u32, off: i64 }; const RegExpr = struct { reg: u32, expr: Loc }; - fn write(cfa: Cfa, wip_nav: *WipNav) link.EmitError!void { - const df_nw = &wip_nav.fde_writer; + fn write(cfa: Cfa, wip_func: *WipFunc) link.EmitError!void { + const df_nw = &wip_func.fde_writer; const df_w = &df_nw.interface; switch (cfa) { .nop => try df_w.writeByte(DW.CFA.nop), .advance_loc => |loc| { const delta = - @divExact(loc - wip_nav.cfi.loc, wip_nav.dwarf.frame.header.code_alignment_factor); + @divExact(loc - wip_func.cfi.loc, wip_func.dwarf.frame.header.code_alignment_factor); if (delta == 0) {} else if (std.math.cast(u6, delta)) |small_delta| try df_w.writeByte(@as(u8, DW.CFA.advance_loc) + small_delta) else if (std.math.cast(u8, delta)) |ubyte_delta| try df_w.writeAll(&.{ DW.CFA.advance_loc1, ubyte_delta }) else if (std.math.cast(u16, delta)) |uhalf_delta| { try df_w.writeByte(DW.CFA.advance_loc2); - try df_w.writeInt(u16, uhalf_delta, wip_nav.dwarf.endian); + try df_w.writeInt(u16, uhalf_delta, wip_func.dwarf.endian); } else if (std.math.cast(u32, delta)) |uword_delta| { try df_w.writeByte(DW.CFA.advance_loc4); - try df_w.writeInt(u32, uword_delta, wip_nav.dwarf.endian); + try df_w.writeInt(u32, uword_delta, wip_func.dwarf.endian); } - wip_nav.cfi.loc = loc; + wip_func.cfi.loc = loc; }, .offset, .rel_offset => |reg_off| { const factored_off = @divExact(reg_off.off - switch (cfa) { else => unreachable, .offset => 0, - .rel_offset => wip_nav.cfi.cfa.off, - }, wip_nav.dwarf.frame.header.data_alignment_factor); + .rel_offset => wip_func.cfi.cfa.off, + }, wip_func.dwarf.frame.header.data_alignment_factor); if (std.math.cast(u63, factored_off)) |unsigned_off| { if (std.math.cast(u6, reg_off.reg)) |small_reg| { try df_w.writeByte(@as(u8, DW.CFA.offset) + small_reg); @@ -558,21 +638,21 @@ pub const Cfa = union(enum) { const reg_off: RegOff = switch (cfa) { else => unreachable, .def_cfa => |reg_off| reg_off, - .def_cfa_register => |reg| .{ .reg = reg, .off = wip_nav.cfi.cfa.off }, - .def_cfa_offset => |off| .{ .reg = wip_nav.cfi.cfa.reg, .off = off }, + .def_cfa_register => |reg| .{ .reg = reg, .off = wip_func.cfi.cfa.off }, + .def_cfa_offset => |off| .{ .reg = wip_func.cfi.cfa.reg, .off = off }, .adjust_cfa_offset => |off| .{ - .reg = wip_nav.cfi.cfa.reg, - .off = wip_nav.cfi.cfa.off + off, + .reg = wip_func.cfi.cfa.reg, + .off = wip_func.cfi.cfa.off + off, }, }; - const changed_reg = reg_off.reg != wip_nav.cfi.cfa.reg; + const changed_reg = reg_off.reg != wip_func.cfi.cfa.reg; const unsigned_off = std.math.cast(u63, reg_off.off); - if (reg_off.off == wip_nav.cfi.cfa.off) { + if (reg_off.off == wip_func.cfi.cfa.off) { if (changed_reg) { try df_w.writeByte(DW.CFA.def_cfa_register); try df_w.writeUleb128(reg_off.reg); } - } else if (switch (wip_nav.dwarf.frame.header.data_alignment_factor) { + } else if (switch (wip_func.dwarf.frame.header.data_alignment_factor) { 0 => unreachable, 1 => unsigned_off != null, else => |data_alignment_factor| @rem(reg_off.off, data_alignment_factor) != 0, @@ -584,23 +664,23 @@ pub const Cfa = union(enum) { try df_w.writeByte(if (changed_reg) DW.CFA.def_cfa_sf else DW.CFA.def_cfa_offset_sf); if (changed_reg) try df_w.writeUleb128(reg_off.reg); try df_w.writeSleb128( - @divExact(reg_off.off, wip_nav.dwarf.frame.header.data_alignment_factor), + @divExact(reg_off.off, wip_func.dwarf.frame.header.data_alignment_factor), ); } - wip_nav.cfi.cfa = reg_off; + wip_func.cfi.cfa = reg_off; }, .def_cfa_expression => |expr| { try df_w.writeByte(DW.CFA.def_cfa_expression); - try wip_nav.dwarf.exprLoc(df_nw, expr); + try wip_func.dwarf.exprLoc(df_nw, expr); }, .expression => |reg_expr| { try df_w.writeByte(DW.CFA.expression); try df_w.writeUleb128(reg_expr.reg); - try wip_nav.dwarf.exprLoc(df_nw, reg_expr.expr); + try wip_func.dwarf.exprLoc(df_nw, reg_expr.expr); }, .val_offset => |reg_off| { const factored_off = - @divExact(reg_off.off, wip_nav.dwarf.frame.header.data_alignment_factor); + @divExact(reg_off.off, wip_func.dwarf.frame.header.data_alignment_factor); if (std.math.cast(u63, factored_off)) |unsigned_off| { try df_w.writeByte(DW.CFA.val_offset); try df_w.writeUleb128(reg_off.reg); @@ -614,14 +694,14 @@ pub const Cfa = union(enum) { .val_expression => |reg_expr| { try df_w.writeByte(DW.CFA.val_expression); try df_w.writeUleb128(reg_expr.reg); - try wip_nav.dwarf.exprLoc(df_nw, reg_expr.expr); + try wip_func.dwarf.exprLoc(df_nw, reg_expr.expr); }, .escape => |bytes| try df_w.writeAll(bytes), } } }; -pub const WipNav = struct { +pub const WipFunc = struct { dwarf: *Dwarf, unit: Unit.Index, func: InternPool.Index, @@ -635,44 +715,50 @@ pub const WipNav = struct { frame_func_length: struct { offset: usize, size: AddressSize }, pub const Debug = struct { - wip_nav: WipNav, + wip_func: WipFunc, pt: Zcu.PerThread, - any_children: bool, + is_empty: bool, + empty_abbrev_code: AbbrevCode, blocks: std.ArrayList(struct { - abbrev_code: u32, - low_pc_off: usize, - high_pc: u32, + abbrev_code_offset: usize, + low_pc: usize, + high_pc_offset: usize, }), info_writer: link.MappedFile.Node.Writer, info_func_length_offset: usize, line_writer: link.MappedFile.Node.Writer, + pub fn init(debug: *Debug, pt: Zcu.PerThread) void { + debug.pt = pt; + debug.is_empty = true; + debug.blocks = .empty; + } + pub fn deinit(debug: *Debug) void { const gpa = debug.pt.zcu.gpa; debug.line_writer.deinit(); debug.info_writer.deinit(); debug.blocks.deinit(gpa); - debug.wip_nav.deinit(); + debug.wip_func.deinit(); debug.* = undefined; } pub fn genDebugFrame(debug: *Debug, loc: u32, cfa: Cfa) link.Error!void { - return debug.wip_nav.genDebugFrame(loc, cfa); + return debug.wip_func.genDebugFrame(loc, cfa); } - pub fn startFuncDebugInfo(debug: *Debug) link.Error!void { - assert(debug.wip_nav.func != .none); - debug.startFuncDebugInfoInner() catch |err| switch (err) { - error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.info_writer), + pub fn startDebugInfo(debug: *Debug) link.Error!void { + debug.startDebugInfoInner() catch |err| switch (err) { else => |e| return e, + error.WriteFailed => return debug.wip_func.dwarf.reportWriteError(&debug.info_writer), }; } - fn startFuncDebugInfoInner(debug: *Debug) link.EmitError!void { - const dwarf = debug.wip_nav.dwarf; + fn startDebugInfoInner(debug: *Debug) link.EmitError!void { + const dwarf = debug.wip_func.dwarf; const pt = debug.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; - const func = zcu.funcInfo(debug.wip_nav.func); + const func = zcu.funcInfo(debug.wip_func.func); const nav = ip.getNav(func.owner_nav); const func_type = ip.indexToKey(func.ty).func_type; const inst_info = nav.srcInst(ip).resolveFull(ip).?; @@ -681,42 +767,52 @@ pub const WipNav = struct { const decl = zf.zir.?.getDeclaration(inst_info.inst); const di_nw = &debug.info_writer; const di_w = &di_nw.interface; - try dwarf.abbrevCode(di_nw, .decl_func); - try dwarf.refType(pt, di_nw, .fromInterned(ip.namespacePtr(switch (func.generic_owner) { - .none => nav, + const parent_ty: Type = .fromInterned(ip.namespacePtr(switch (func.generic_owner) { else => |generic_owner| ip.getNav(zcu.funcInfo(generic_owner).owner_nav), - }.analysis.?.namespace).owner_type)); - try di_w.writeInt(u32, decl.src_line + 1, dwarf.endian); - try di_w.writeUleb128(decl.src_column + 1); - try di_w.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); - try dwarf.strp(&dwarf.debug_str, di_nw, nav.name.toSlice(ip)); - try dwarf.strp(&dwarf.debug_str, di_nw, switch (decl.linkage) { + .none => nav, + }.analysis.?.namespace).owner_type); + if (func.generic_owner != .none or parent_ty.getCaptures(zcu).len > 0) { + debug.empty_abbrev_code = .decl_instance_empty_func; + try dwarf.abbrevCode(di_nw, .decl_instance_func); + try dwarf.refType(pt, di_nw, parent_ty); + try dwarf.secOffset(di_nw, try dwarf.getConstDecl(pt, debug.wip_func.func), 0); + } else { + debug.empty_abbrev_code = .decl_empty_func; + try dwarf.abbrevCode(di_nw, .decl_func); + try dwarf.refType(pt, di_nw, parent_ty); + try di_w.writeInt(u32, decl.src_line + 1, dwarf.endian); + try di_w.writeUleb128(decl.src_column + 1); + try di_w.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); + try dwarf.strx(di_nw, nav.name.toSlice(ip)); + } + try dwarf.strx(di_nw, switch (decl.linkage) { .normal => nav.fqn, .@"extern", .@"export" => nav.name, }.toSlice(ip)); try dwarf.refType(pt, di_nw, .fromInterned(func_type.return_type)); - try dwarf.addrSym(di_nw, debug.wip_nav.func_si, 0); + try dwarf.addrxSym(di_w, debug.wip_func.func_si); debug.info_func_length_offset = di_w.end; try di_w.writeInt(u32, undefined, dwarf.endian); try di_w.writeUleb128( target_info.minFunctionAlignment(target).max(nav.resolved.?.@"align").toByteUnits().?, ); - try di_w.writeByte(@intFromBool(decl.linkage != .normal)); - try di_w.writeByte(@intFromBool(Type.fromInterned(func_type.return_type).isNoReturn(zcu))); + try di_w.writeAll(&.{ + @intFromBool(decl.linkage != .normal), + @intFromBool(Type.fromInterned(func_type.return_type).isNoReturn(zcu)), + }); } pub fn startDebugLine(debug: *Debug) link.Error!void { - assert(debug.wip_nav.func != .none); debug.startDebugLineInner() catch |err| switch (err) { - error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.line_writer), else => |e| return e, + error.WriteFailed => return debug.wip_func.dwarf.reportWriteError(&debug.line_writer), }; } fn startDebugLineInner(debug: *Debug) link.EmitError!void { - const dwarf = debug.wip_nav.dwarf; + const dwarf = debug.wip_func.dwarf; const zcu = debug.pt.zcu; const ip = &zcu.intern_pool; - const func = zcu.funcInfo(debug.wip_nav.func); + const func = zcu.funcInfo(debug.wip_func.func); const inst_info = ip.getNav(func.owner_nav).srcInst(ip).resolveFull(ip).?; const zf = zcu.fileByIndex(inst_info.file); const decl = zf.zir.?.getDeclaration(inst_info.inst); @@ -735,10 +831,10 @@ pub const WipNav = struct { } else { try dl_w.writeUleb128(1 + @backingInt(dwarf.address_size)); try dl_w.writeByte(DW.LNE.set_address); - try dwarf.addrSym(dl_nw, debug.wip_nav.func_si, 0); + try dwarf.addrSym(dl_nw, debug.wip_func.func_si, 0); - const unit = dwarf.getUnit(zf.mod.?); - _, const fi = try unit.get(dwarf).getFile(zcu.gpa, unit, inst_info.file); + const ui = dwarf.getUnit(zf.mod.?); + _, const fi = try ui.get(dwarf).getFile(zcu.gpa, ui, inst_info.file); try dl_w.writeByte(DW.LNS.set_file); try dl_w.writeUleb128(@backingInt(fi)); @@ -749,28 +845,32 @@ pub const WipNav = struct { } } - pub fn finishFunc(debug: *Debug, func_length: u64) link.Error!void { - assert(debug.wip_nav.func != .none); + pub fn finish(debug: *Debug, func_length: u64) link.Error!void { const di_nw = &debug.info_writer; debug.finishDebugInfo(func_length) catch |err| switch (err) { - error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(di_nw), else => |e| return e, + error.WriteFailed => return debug.wip_func.dwarf.reportWriteError(di_nw), }; debug.finishDebugLine() catch |err| switch (err) { - error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(di_nw), else => |e| return e, + error.WriteFailed => return debug.wip_func.dwarf.reportWriteError(di_nw), }; } fn finishDebugInfo(debug: *Debug, func_length: u64) link.EmitError!void { - const dwarf = debug.wip_nav.dwarf; - const di_w = &debug.info_writer.interface; + const dwarf = debug.wip_func.dwarf; + const di_nw = &debug.info_writer; + const di_w = &di_nw.interface; std.mem.writeInt( u32, di_w.buffered()[debug.info_func_length_offset..][0..4], @intCast(func_length), dwarf.endian, ); - try di_w.writeUleb128(@backingInt(AbbrevCode.null)); + if (debug.is_empty) std.leb.writeUnsignedFixed( + AbbrevCode.decl_size, + di_w.buffered()[0..AbbrevCode.decl_size], + @intCast(try dwarf.refAbbrevCode(di_nw.mf, debug.empty_abbrev_code)), + ) else try di_w.writeUleb128(@backingInt(AbbrevCode.null)); try dwarf.genDebugInfoPadding(di_w, di_w.unusedCapacityLen()); } fn finishDebugLine(debug: *Debug) link.EmitError!void { @@ -787,8 +887,8 @@ pub const WipNav = struct { loc: Loc, ) link.Error!void { return debug.genLocalVarDebugInfoInner(tag, opt_name, ty, loc) catch |err| switch (err) { - error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.info_writer), else => |e| e, + error.WriteFailed => return debug.wip_func.dwarf.reportWriteError(&debug.info_writer), }; } fn genLocalVarDebugInfoInner( @@ -798,17 +898,16 @@ pub const WipNav = struct { ty: Type, loc: Loc, ) link.EmitError!void { - assert(debug.wip_nav.func != .none); - const dwarf = debug.wip_nav.dwarf; + const dwarf = debug.wip_func.dwarf; const di_nw = &debug.info_writer; try dwarf.abbrevCode(di_nw, switch (tag) { .arg => if (opt_name) |_| .arg else .unnamed_arg, .local_var => if (opt_name) |_| .local_var else unreachable, }); - if (opt_name) |name| try dwarf.strp(&dwarf.debug_str, di_nw, name); + if (opt_name) |name| try dwarf.strx(di_nw, name); try dwarf.refType(debug.pt, di_nw, ty); try dwarf.exprLoc(di_nw, loc); - debug.any_children = true; + debug.is_empty = false; } pub const LocalConstTag = enum { comptime_arg, local_const }; @@ -819,8 +918,8 @@ pub const WipNav = struct { val: Value, ) link.Error!void { return debug.genLocalConstDebugInfoInner(tag, opt_name, val) catch |err| switch (err) { - error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.info_writer), else => |e| e, + error.WriteFailed => return debug.wip_func.dwarf.reportWriteError(&debug.info_writer), }; } fn genLocalConstDebugInfoInner( @@ -829,8 +928,7 @@ pub const WipNav = struct { opt_name: ?[]const u8, val: Value, ) link.EmitError!void { - assert(debug.wip_nav.func != .none); - const dwarf = debug.wip_nav.dwarf; + const dwarf = debug.wip_func.dwarf; const pt = debug.pt; const zcu = debug.pt.zcu; const ty = val.typeOf(zcu); @@ -858,23 +956,22 @@ pub const WipNav = struct { .fully_comptime => .local_const_fully_comptime, } else unreachable, }); - if (opt_name) |name| try dwarf.strp(&dwarf.debug_str, di_nw, name); + if (opt_name) |name| try dwarf.strx(di_nw, name); try dwarf.refType(pt, di_nw, ty); if (ty_class.hasRuntimeBits()) try dwarf.blockConst(pt, di_nw, val); if (ty_class.comptimeOnly()) try dwarf.refConst(pt, di_nw, val); - debug.any_children = true; + debug.is_empty = false; } pub fn genVarArgsDebugInfo(debug: *Debug) link.Error!void { return debug.genVarArgsDebugInfoInner() catch |err| switch (err) { - error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.info_writer), else => |e| e, + error.WriteFailed => return debug.wip_func.dwarf.reportWriteError(&debug.info_writer), }; } fn genVarArgsDebugInfoInner(debug: *Debug) link.EmitError!void { - assert(debug.wip_nav.func != .none); - try debug.wip_nav.dwarf.abbrevCode(&debug.info_writer, .is_var_args); - debug.any_children = true; + try debug.wip_func.dwarf.abbrevCode(&debug.info_writer, .is_var_args); + debug.is_empty = false; } pub fn advanceLineAndPc( @@ -884,7 +981,7 @@ pub const WipNav = struct { end: bool, ) link.Error!void { return debug.advanceLineAndPcInner(delta_line, delta_pc, end) catch |err| switch (err) { - error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.line_writer), + error.WriteFailed => return debug.wip_func.dwarf.reportWriteError(&debug.line_writer), }; } fn advanceLineAndPcInner( @@ -895,7 +992,7 @@ pub const WipNav = struct { ) std.Io.Writer.Error!void { const dl_w = &debug.line_writer.interface; - const header = debug.wip_nav.dwarf.debug_line.header; + const header = debug.wip_func.dwarf.debug_line.header; assert(header.maximum_operations_per_instruction == 1); const delta_op: u64 = 0; @@ -939,7 +1036,7 @@ pub const WipNav = struct { pub fn setColumn(debug: *Debug, column: u32) link.Error!void { return debug.setColumnInner(column) catch |err| switch (err) { - error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.line_writer), + error.WriteFailed => return debug.wip_func.dwarf.reportWriteError(&debug.line_writer), }; } fn setColumnInner(debug: *Debug, column: u32) std.Io.Writer.Error!void { @@ -950,7 +1047,7 @@ pub const WipNav = struct { pub fn negateStmt(debug: *Debug) link.Error!void { return debug.negateStmtInner() catch |err| switch (err) { - error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.line_writer), + error.WriteFailed => return debug.wip_func.dwarf.reportWriteError(&debug.line_writer), }; } fn negateStmtInner(debug: *Debug) std.Io.Writer.Error!void { @@ -959,7 +1056,7 @@ pub const WipNav = struct { pub fn setPrologueEnd(debug: *Debug) link.Error!void { return debug.setPrologueEndInner() catch |err| switch (err) { - error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.line_writer), + error.WriteFailed => return debug.wip_func.dwarf.reportWriteError(&debug.line_writer), }; } fn setPrologueEndInner(debug: *Debug) std.Io.Writer.Error!void { @@ -968,151 +1065,155 @@ pub const WipNav = struct { pub fn setEpilogueBegin(debug: *Debug) link.Error!void { return debug.setEpilogueBeginInner() catch |err| switch (err) { - error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.line_writer), + error.WriteFailed => return debug.wip_func.dwarf.reportWriteError(&debug.line_writer), }; } fn setEpilogueBeginInner(debug: *Debug) std.Io.Writer.Error!void { try debug.line_writer.interface.writeByte(DW.LNS.set_epilogue_begin); } - pub fn enterBlock(debug: *Debug, code_off: usize) link.Error!void { - return debug.enterBlockInner(code_off) catch |err| switch (err) { - error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.info_writer), + pub fn enterBlock(debug: *Debug, code_offset: usize) link.Error!void { + return debug.enterBlockInner(code_offset) catch |err| switch (err) { else => |e| e, + error.WriteFailed => return debug.wip_func.dwarf.reportWriteError(&debug.info_writer), }; } - fn enterBlockInner(debug: *Debug, code_off: usize) link.EmitError!void { - const dwarf = debug.wip_nav.dwarf; + fn enterBlockInner(debug: *Debug, code_offset: usize) link.EmitError!void { + const dwarf = debug.wip_func.dwarf; const block = try debug.blocks.addOne(dwarf.lf.comp.gpa); const di_nw = &debug.info_writer; const di_w = &di_nw.interface; - block.abbrev_code = @intCast(di_w.end); + block.abbrev_code_offset = di_w.end; try dwarf.abbrevCode(di_nw, .block); - block.low_pc_off = code_off; - try dwarf.addrSym(di_nw, debug.wip_nav.func_si, code_off); - block.high_pc = @intCast(di_w.end); + block.low_pc = code_offset; + try dwarf.addrSym(di_nw, debug.wip_func.func_si, code_offset); + block.high_pc_offset = di_w.end; try di_w.writeInt(u32, 0, dwarf.endian); - debug.any_children = false; + debug.is_empty = true; } - pub fn leaveBlock(debug: *Debug, code_off: usize) link.Error!void { - return debug.leaveBlockInner(code_off) catch |err| switch (err) { - error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.info_writer), + pub fn leaveBlock(debug: *Debug, code_offset: usize) link.Error!void { + return debug.leaveBlockInner(code_offset) catch |err| switch (err) { else => |e| e, + error.WriteFailed => return debug.wip_func.dwarf.reportWriteError(&debug.info_writer), }; } - fn leaveBlockInner(debug: *Debug, code_off: usize) link.EmitError!void { - const dwarf = debug.wip_nav.dwarf; + fn leaveBlockInner(debug: *Debug, code_offset: usize) link.EmitError!void { + const dwarf = debug.wip_func.dwarf; + const block = debug.blocks.pop().?; + + const di_nw = &debug.info_writer; + const di_w = &di_nw.interface; const block_size = comptime uleb128Size(@backingInt(AbbrevCode.block)); - const block = debug.blocks.pop().?; - - const di_nw = &debug.info_writer; - const di_w = &di_nw.interface; - if (debug.any_children) - try di_w.writeUleb128(@backingInt(AbbrevCode.null)) - else - std.leb.writeUnsignedFixed( - block_size, - di_w.buffered()[block.abbrev_code..][0..block_size], - @intCast(try dwarf.refAbbrevCode(di_nw.mf, .empty_block)), - ); + if (debug.is_empty) std.leb.writeUnsignedFixed( + block_size, + di_w.buffered()[block.abbrev_code_offset..][0..block_size], + @intCast(try dwarf.refAbbrevCode(di_nw.mf, .empty_block)), + ) else try di_w.writeUleb128(@backingInt(AbbrevCode.null)); std.mem.writeInt( u32, - di_nw.interface.buffered()[block.high_pc..][0..4], - @intCast(code_off - block.low_pc_off), + di_nw.interface.buffered()[block.high_pc_offset..][0..4], + @intCast(code_offset - block.low_pc), dwarf.endian, ); - debug.any_children = true; + debug.is_empty = false; } pub fn enterInlineFunc( debug: *Debug, func: InternPool.Index, - code_off: usize, + code_offset: usize, line: u32, column: u32, ) link.Error!void { - return debug.enterInlineFuncInner(func, code_off, line, column) catch |err| switch (err) { - error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.info_writer), + return debug.enterInlineFuncInner( + func, + code_offset, + line, + column, + ) catch |err| switch (err) { else => |e| e, + error.WriteFailed => return debug.wip_func.dwarf.reportWriteError(&debug.info_writer), }; } fn enterInlineFuncInner( debug: *Debug, func: InternPool.Index, - code_off: usize, + code_offset: usize, line: u32, column: u32, ) link.EmitError!void { - const dwarf = debug.wip_nav.dwarf; - const zcu = debug.pt.zcu; + const dwarf = debug.wip_func.dwarf; + const pt = debug.pt; + const zcu = pt.zcu; const block = try debug.blocks.addOne(zcu.gpa); const di_nw = &debug.info_writer; const di_w = &di_nw.interface; - block.abbrev_code = @intCast(di_w.end); + block.abbrev_code_offset = di_w.end; try dwarf.abbrevCode(di_nw, .inlined_func); - try debug.refFunc(func); + try dwarf.refConst(pt, di_nw, .fromInterned(func)); try di_w.writeUleb128((if (zcu.comp.config.incremental) 0 else - zcu.navSrcLine(zcu.funcInfo(debug.wip_nav.func).owner_nav) + 1) + line); + zcu.navSrcLine(zcu.funcInfo(debug.wip_func.func).owner_nav) + 1) + line); try di_w.writeUleb128(column + 1); - block.low_pc_off = code_off; - try dwarf.addrSym(di_nw, debug.wip_nav.func_si, code_off); - block.high_pc = @intCast(di_w.end); + block.low_pc = code_offset; + try dwarf.addrSym(di_nw, debug.wip_func.func_si, code_offset); + block.high_pc_offset = di_w.end; try di_w.writeInt(u32, 0, dwarf.endian); try debug.setInlineFunc(func); - debug.any_children = false; + debug.is_empty = true; } - pub fn leaveInlineFunc(debug: *Debug, func: InternPool.Index, code_off: usize) link.Error!void { - return debug.leaveInlineFuncInner(func, code_off) catch |err| switch (err) { - error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.info_writer), + pub fn leaveInlineFunc( + debug: *Debug, + func: InternPool.Index, + code_offset: usize, + ) link.Error!void { + return debug.leaveInlineFuncInner(func, code_offset) catch |err| switch (err) { else => |e| e, + error.WriteFailed => return debug.wip_func.dwarf.reportWriteError(&debug.info_writer), }; } fn leaveInlineFuncInner( debug: *Debug, func: InternPool.Index, - code_off: usize, + code_offset: usize, ) link.EmitError!void { - const dwarf = debug.wip_nav.dwarf; + const dwarf = debug.wip_func.dwarf; + const block = debug.blocks.pop().?; + + const di_nw = &debug.info_writer; + const di_w = &di_nw.interface; const inlined_func_size = comptime uleb128Size(@backingInt(AbbrevCode.inlined_func)); - const block = debug.blocks.pop().?; - - const di_nw = &debug.info_writer; - const di_w = &di_nw.interface; - if (debug.any_children) - try di_w.writeUleb128(@backingInt(AbbrevCode.null)) - else - std.leb.writeUnsignedFixed( - inlined_func_size, - di_w.buffered()[block.abbrev_code..][0..inlined_func_size], - @intCast(try dwarf.refAbbrevCode(di_nw.mf, .empty_inlined_func)), - ); + if (debug.is_empty) std.leb.writeUnsignedFixed( + inlined_func_size, + di_w.buffered()[block.abbrev_code_offset..][0..inlined_func_size], + @intCast(try dwarf.refAbbrevCode(di_nw.mf, .empty_inlined_func)), + ) else try di_w.writeUleb128(@backingInt(AbbrevCode.null)); std.mem.writeInt( u32, - di_w.buffered()[block.high_pc..][0..4], - @intCast(code_off - block.low_pc_off), + di_w.buffered()[block.high_pc_offset..][0..4], + @intCast(code_offset - block.low_pc), dwarf.endian, ); try debug.setInlineFunc(func); - debug.any_children = true; + debug.is_empty = false; } pub fn setInlineFunc(debug: *Debug, func: InternPool.Index) link.Error!void { return debug.setInlineFuncInner(func) catch |err| switch (err) { - error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.line_writer), else => |e| e, + error.WriteFailed => return debug.wip_func.dwarf.reportWriteError(&debug.line_writer), }; } fn setInlineFuncInner(debug: *Debug, func: InternPool.Index) link.EmitError!void { const zcu = debug.pt.zcu; const ip = &zcu.intern_pool; - const dwarf = debug.wip_nav.dwarf; - if (debug.wip_nav.func == func) return; + const dwarf = debug.wip_func.dwarf; + if (debug.wip_func.func == func) return; const dl_nw = &debug.line_writer; const dl_w = &dl_nw.interface; @@ -1126,7 +1227,7 @@ pub const WipNav = struct { return; } - const old_owner_nav = zcu.funcInfo(debug.wip_nav.func).owner_nav; + const old_owner_nav = zcu.funcInfo(debug.wip_func.func).owner_nav; const old_inst_info = ip.getNav(old_owner_nav).srcInst(ip).resolveFull(ip).?; const old_zf = zcu.fileByIndex(old_inst_info.file); const new_inst_info = ip.getNav(new_owner_nav).srcInst(ip).resolveFull(ip).?; @@ -1134,7 +1235,7 @@ pub const WipNav = struct { if (old_inst_info.file != new_inst_info.file) { const new_ui = dwarf.getUnit(new_zf.mod.?); _, const new_fi = - try debug.wip_nav.unit.get(dwarf).getFile(zcu.gpa, new_ui, new_inst_info.file); + try debug.wip_func.unit.get(dwarf).getFile(zcu.gpa, new_ui, new_inst_info.file); try dl_w.writeByte(DW.LNS.set_file); try dl_w.writeUleb128(@backingInt(new_fi)); @@ -1147,38 +1248,27 @@ pub const WipNav = struct { try dl_w.writeSleb128(new_src_line - old_src_line); } - debug.wip_nav.func = func; - } - - fn refFunc(debug: *Debug, func: InternPool.Index) link.EmitError!void { - const dwarf = debug.wip_nav.dwarf; - const fi = try dwarf.getFunc(debug.pt.zcu.funcInfo(func).owner_nav); - try debug.wip_nav.dwarf.secOffset( - &debug.info_writer, - fi.get(dwarf).debug_info_ni.unwrap().?, - 0, - ); + debug.wip_func.func = func; } }; - pub fn deinit(wip_nav: *WipNav) void { - wip_nav.fde_writer.deinit(); - wip_nav.* = undefined; + pub fn deinit(wip_func: *WipFunc) void { + wip_func.fde_writer.deinit(); + wip_func.* = undefined; } - pub fn genDebugFrameHeader(wip_nav: *WipNav) link.Error!void { - wip_nav.genDebugFrameHeaderInner() catch |err| switch (err) { - error.WriteFailed => return wip_nav.dwarf.reportWriteError(&wip_nav.fde_writer), + pub fn genDebugFrameHeader(wip_func: *WipFunc) link.Error!void { + wip_func.genDebugFrameHeaderInner() catch |err| switch (err) { else => |e| return e, + error.WriteFailed => return wip_func.dwarf.reportWriteError(&wip_func.fde_writer), }; } - fn genDebugFrameHeaderInner(wip_nav: *WipNav) link.EmitError!void { - assert(wip_nav.func != .none); - const dwarf = wip_nav.dwarf; - const df_nw = &wip_nav.fde_writer; + fn genDebugFrameHeaderInner(wip_func: *WipFunc) link.EmitError!void { + const dwarf = wip_func.dwarf; + const df_nw = &wip_func.fde_writer; const df_w = &df_nw.interface; try dwarf.genUnitLength(df_w); - switch (wip_nav.frame_format) { + switch (wip_func.frame_format) { .eh_frame => { try df_w.writeInt(u32, undefined, dwarf.endian); { @@ -1187,51 +1277,50 @@ pub const WipNav = struct { if (dwarf.lf.cast(.elf2)) |elf| try elf.addReloc( @bitCast(df_nw.ni), offset, - wip_nav.func_si, + wip_func.func_si, 0, .rel32(elf), ) else unreachable; } - wip_nav.frame_func_length = .{ .offset = df_w.end, .size = .@"32" }; + wip_func.frame_func_length = .{ .offset = df_w.end, .size = .@"32" }; try df_w.writeInt(u32, undefined, dwarf.endian); try df_w.writeUleb128(0); }, .debug_frame => { - try dwarf.secOffset(df_nw, wip_nav.unit.get(dwarf).cie_ni.unwrap().?, 0); - try dwarf.addrSym(df_nw, wip_nav.func_si, 0); - wip_nav.frame_func_length = .{ .offset = df_w.end, .size = dwarf.address_size }; + try dwarf.secOffset(df_nw, wip_func.unit.get(dwarf).cie_ni.unwrap().?, 0); + try dwarf.addrSym(df_nw, wip_func.func_si, 0); + wip_func.frame_func_length = .{ .offset = df_w.end, .size = dwarf.address_size }; try dwarf.addrPlaceholder(df_w); }, } } - pub fn genDebugFrame(wip_nav: *WipNav, loc: u32, cfa: Cfa) link.Error!void { - return wip_nav.genDebugFrameInner(loc, cfa) catch |err| switch (err) { - error.WriteFailed => return wip_nav.dwarf.reportWriteError(&wip_nav.fde_writer), + pub fn genDebugFrame(wip_func: *WipFunc, loc: u32, cfa: Cfa) link.Error!void { + return wip_func.genDebugFrameInner(loc, cfa) catch |err| switch (err) { else => |e| return e, + error.WriteFailed => return wip_func.dwarf.reportWriteError(&wip_func.fde_writer), }; } - fn genDebugFrameInner(wip_nav: *WipNav, loc: u32, cfa: Cfa) link.EmitError!void { - assert(wip_nav.func != .none); + fn genDebugFrameInner(wip_func: *WipFunc, loc: u32, cfa: Cfa) link.EmitError!void { const loc_cfa: Cfa = .{ .advance_loc = loc }; - try loc_cfa.write(wip_nav); - try cfa.write(wip_nav); + try loc_cfa.write(wip_func); + try cfa.write(wip_func); } - pub fn finishDebugFrameFde(wip_nav: *WipNav, func_length: u64) void { - const dwarf = wip_nav.dwarf; - const df_w = &wip_nav.fde_writer.interface; - switch (wip_nav.frame_func_length.size) { + pub fn finishDebugFrameFde(wip_func: *WipFunc, func_length: u64) void { + const dwarf = wip_func.dwarf; + const df_w = &wip_func.fde_writer.interface; + switch (wip_func.frame_func_length.size) { _ => unreachable, .@"32" => std.mem.writeInt( u32, - df_w.buffered()[wip_nav.frame_func_length.offset..][0..4], + df_w.buffered()[wip_func.frame_func_length.offset..][0..4], @intCast(func_length), dwarf.endian, ), .@"64" => std.mem.writeInt( u64, - df_w.buffered()[wip_nav.frame_func_length.offset..][0..8], + df_w.buffered()[wip_func.frame_func_length.offset..][0..8], func_length, dwarf.endian, ), @@ -1258,13 +1347,18 @@ pub fn init(lf: *link.File, format: DW.Format) Dwarf { .globals = .empty, .funcs = .empty, .decls = .empty, - .pending_decl = .{ .di = undefined, .instance_val = .none }, + .pending_decl = .{ .di = undefined, .instance = .none }, .debug_abbrev = .{ .ni = .none, .end = 0, .set = .empty, }, + .debug_addr = .{ + .ni = .none, + .pending_index = 0, + .map = .empty, + }, .frame = .{ .header = if (target.cpu.arch == .x86_64 and target.ofmt == .elf) header: { dev.checkAny(&.{ .llvm_backend, .x86_64_backend }); @@ -1308,18 +1402,19 @@ pub fn init(lf: *link.File, format: DW.Format) Dwarf { }, .debug_line_str = .{ .ni = .none, - .offset = 0, + .end = 0, .map = .empty, }, .debug_rnglists = .{}, .debug_str = .{ .ni = .none, - .offset = 0, + .end = 0, .map = .empty, }, .debug_str_offsets = .{ .ni = .none, - .offset = 0, + .pending_index = 0, + .map = .empty, }, }; } @@ -1333,8 +1428,10 @@ pub fn deinit(dwarf: *Dwarf) void { dwarf.globals.deinit(gpa); dwarf.funcs.deinit(gpa); dwarf.decls.deinit(gpa); + dwarf.debug_addr.map.deinit(gpa); dwarf.debug_line_str.map.deinit(gpa); dwarf.debug_str.map.deinit(gpa); + dwarf.debug_str_offsets.map.deinit(gpa); dwarf.* = undefined; } @@ -1389,8 +1486,7 @@ pub fn getConst(dwarf: *Dwarf, pt: Zcu.PerThread, val: Value) link.Error!link.Co pub fn getGlobal(dwarf: *Dwarf, nav: InternPool.Nav.Index) link.Error!Global.Index { const comp = dwarf.lf.comp; - const gpa = comp.gpa; - const global_gop = try dwarf.globals.getOrPut(gpa, nav); + const global_gop = try dwarf.globals.getOrPut(comp.gpa, nav); if (!global_gop.found_existing) global_gop.value_ptr.* = .{ .debug_info_ni = .none, }; @@ -1398,25 +1494,26 @@ pub fn getGlobal(dwarf: *Dwarf, nav: InternPool.Nav.Index) link.Error!Global.Ind if (global_gop.value_ptr.debug_info_ni != .none) return gi; const mod = comp.zcu.?.navFileScope(nav).mod.?; assert(!mod.strip); - const elf = dwarf.lf.cast(.elf2).?; - try elf.nodes.ensureUnusedCapacity(gpa, 1); - try elf.dwarf_globals.append(gpa, .{ - .debug_info_first_target_reloc = .none, - .debug_info_first_node_reloc = .none, - .debug_info_first_symbol_reloc = .none, - }); - const unit = dwarf.getUnit(mod).get(dwarf); - global_gop.value_ptr.debug_info_ni = .wrap(elf.addNodeAssumeCapacity( - unit.debug_info_ni.unwrap().?.addFloatingChild(gpa, &elf.mf, .{ - .enable_next_moved = true, - }) catch |err| switch (err) { - else => |e| return e, - error.MappedFileIo => return comp.link_diags.fail("failed to write output file: {t}", .{ - elf.mf.io_err.?, - }), - }, - .{ .global_debug_info = gi }, - )); + if (dwarf.lf.cast(.elf2)) |elf| { + try elf.nodes.ensureUnusedCapacity(comp.gpa, 1); + try elf.dwarf_globals.append(comp.gpa, .{ + .debug_info_first_target_reloc = .none, + .debug_info_first_node_reloc = .none, + .debug_info_first_symbol_reloc = .none, + }); + const unit = dwarf.getUnit(mod).get(dwarf); + global_gop.value_ptr.debug_info_ni = .wrap(elf.addNodeAssumeCapacity( + unit.debug_info_ni.unwrap().?.addFloatingChild(comp.gpa, &elf.mf, .{ + .enable_next_moved = true, + }) catch |err| switch (err) { + else => |e| return e, + error.MappedFileIo => return comp.link_diags.fail("failed to write output file: {t}", .{ + elf.mf.io_err.?, + }), + }, + .{ .global_debug_info = gi }, + )); + } else unreachable; return gi; } pub fn getGlobalIfExists(dwarf: *Dwarf, nav: InternPool.Nav.Index) ?Global.Index { @@ -1436,118 +1533,150 @@ pub fn getFunc(dwarf: *Dwarf, nav: InternPool.Nav.Index) link.Error!Func.Index { const fi: Func.Index = @fromBackingInt(@intCast(func_gop.index)); if (func_gop.value_ptr.debug_info_ni != .none) return fi; const mod = comp.zcu.?.navFileScope(nav).mod.?; - const elf = dwarf.lf.cast(.elf2).?; - try elf.nodes.ensureUnusedCapacity(gpa, 1); - try elf.dwarf_funcs.append(gpa, .{ - .frame_fde_first_symbol_reloc = .none, - .frame_fde_first_node_reloc = .none, - .debug_info_first_target_reloc = .none, - .debug_info_first_symbol_reloc = .none, - .debug_info_first_node_reloc = .none, - .debug_line_first_symbol_reloc = .none, - .debug_line_first_node_reloc = .none, - }); - if (mod.strip) return fi; - const unit = dwarf.getUnit(mod).get(dwarf); - func_gop.value_ptr.debug_info_ni = .wrap(elf.addNodeAssumeCapacity( - unit.debug_info_ni.unwrap().?.addFloatingChild(gpa, &elf.mf, .{ - .enable_next_moved = true, - }) catch |err| switch (err) { - else => |e| return e, - error.MappedFileIo => return comp.link_diags.fail("failed to write output file: {t}", .{ - elf.mf.io_err.?, - }), - }, - .{ .func_debug_info = fi }, - )); + if (dwarf.lf.cast(.elf2)) |elf| { + try elf.nodes.ensureUnusedCapacity(gpa, 1); + try elf.dwarf_funcs.append(gpa, .{ + .frame_fde_first_symbol_reloc = .none, + .frame_fde_first_node_reloc = .none, + .debug_info_first_target_reloc = .none, + .debug_info_first_symbol_reloc = .none, + .debug_info_first_node_reloc = .none, + .debug_line_first_symbol_reloc = .none, + .debug_line_first_node_reloc = .none, + }); + if (mod.strip) return fi; + const unit = dwarf.getUnit(mod).get(dwarf); + func_gop.value_ptr.debug_info_ni = .wrap(elf.addNodeAssumeCapacity( + unit.debug_info_ni.unwrap().?.addFloatingChild(gpa, &elf.mf, .{ + .enable_next_moved = true, + }) catch |err| switch (err) { + else => |e| return e, + error.MappedFileIo => return comp.link_diags.fail("failed to write output file: {t}", .{ + elf.mf.io_err.?, + }), + }, + .{ .func_debug_info = fi }, + )); + } else unreachable; return fi; } pub fn getFuncIfExists(dwarf: *Dwarf, nav: InternPool.Nav.Index) ?Func.Index { return @fromBackingInt(@intCast(dwarf.funcs.getIndex(nav) orelse return null)); } -fn getDeclInst(dwarf: *Dwarf, val: InternPool.Index) ?InternPool.TrackedInst.Index { - const ip = &dwarf.lf.comp.zcu.?.intern_pool; - switch (ip.indexToKey(val)) { +fn getConstDeclInst(dwarf: *Dwarf, @"const": InternPool.Index) union(enum) { + @"const": InternPool.Index, + src_inst: InternPool.TrackedInst.Index, +} { + const zcu = dwarf.lf.comp.zcu.?; + const ip = &zcu.intern_pool; + switch (ip.indexToKey(@"const")) { else => unreachable, .struct_type, .union_type, .enum_type, .opaque_type => |container, tag| switch (container) { .declared => |declared| switch (declared.captures.owned.len) { - 0 => return null, - else => switch (tag) { + 0 => return .{ .@"const" = @"const" }, + else => return .{ .src_inst = src_inst: switch (tag) { else => unreachable, .struct_type => { - const loaded_struct = ip.loadStructType(val); - return ip.getNav(loaded_struct.name_nav.unwrap() orelse - return loaded_struct.zir_index).srcInst(ip); + const loaded_struct = ip.loadStructType(@"const"); + break :src_inst ip.getNav(loaded_struct.name_nav.unwrap() orelse + break :src_inst loaded_struct.zir_index).srcInst(ip); }, .union_type => { - const loaded_union = ip.loadUnionType(val); - return ip.getNav(loaded_union.name_nav.unwrap() orelse - return loaded_union.zir_index).srcInst(ip); + const loaded_union = ip.loadUnionType(@"const"); + break :src_inst ip.getNav(loaded_union.name_nav.unwrap() orelse + break :src_inst loaded_union.zir_index).srcInst(ip); }, .enum_type => { - const loaded_enum = ip.loadEnumType(val); - return ip.getNav(loaded_enum.name_nav.unwrap() orelse - return loaded_enum.zir_index.unwrap().?).srcInst(ip); + const loaded_enum = ip.loadEnumType(@"const"); + break :src_inst ip.getNav(loaded_enum.name_nav.unwrap() orelse + break :src_inst loaded_enum.zir_index.unwrap().?).srcInst(ip); }, .opaque_type => { - const loaded_opaque = ip.loadOpaqueType(val); - return ip.getNav(loaded_opaque.name_nav.unwrap() orelse - return loaded_opaque.zir_index).srcInst(ip); + const loaded_opaque = ip.loadOpaqueType(@"const"); + break :src_inst ip.getNav(loaded_opaque.name_nav.unwrap() orelse + break :src_inst loaded_opaque.zir_index).srcInst(ip); }, - }, + } }, }, .reified => |reified| { assert(reified.zir_index.resolve(ip).? != .main_struct_inst); - return reified.zir_index; + return .{ .src_inst = reified.zir_index }; }, .generated_union_tag => unreachable, }, - .func => |func| return ip.getNav(switch (func.generic_owner) { - .none => func.owner_nav, - else => |generic_owner| ip.indexToKey(generic_owner).func.owner_nav, - }).srcInst(ip), + .func => |func| switch (func.generic_owner) { + else => |generic_owner| return .{ .@"const" = generic_owner }, + .none => { + const owner_nav = ip.getNav(func.owner_nav); + return switch (Type.fromInterned( + ip.namespacePtr(owner_nav.analysis.?.namespace).owner_type, + ).getCaptures(zcu).len) { + 0 => .{ .@"const" = @"const" }, + else => .{ .src_inst = owner_nav.srcInst(ip) }, + }; + }, + }, } } -pub fn getDecl( +pub fn getConstDecl( dwarf: *Dwarf, pt: Zcu.PerThread, - instance_val: InternPool.Index, + instance_const: InternPool.Index, +) link.Error!link.MappedFile.Node.Index { + switch (dwarf.getConstDeclInst(instance_const)) { + .@"const" => |@"const"| { + const cpi = try dwarf.getConst(pt, .fromInterned(@"const")); + return Const.get(cpi, dwarf).debug_info_ni.unwrap().?; + }, + .src_inst => |src_inst| return dwarf.getDecl(pt, src_inst, .{ .@"const" = instance_const }), + } +} +pub fn getGlobalDecl( + dwarf: *Dwarf, + pt: Zcu.PerThread, + instance_global: InternPool.Nav.Index, +) link.Error!link.MappedFile.Node.Index { + const ip = &pt.zcu.intern_pool; + return dwarf.getDecl(pt, ip.getNav(instance_global).srcInst(ip), .{ .global = instance_global }); +} +fn getDecl( + dwarf: *Dwarf, + pt: Zcu.PerThread, + inst: InternPool.TrackedInst.Index, + instance: Decl.Instance, ) link.Error!link.MappedFile.Node.Index { - assert(dwarf.pending_decl.instance_val == .none); const comp = dwarf.lf.comp; const gpa = comp.gpa; const zcu = pt.zcu; const ip = &zcu.intern_pool; - const inst = dwarf.getDeclInst(instance_val) orelse { - const cpi = try dwarf.getConst(pt, .fromInterned(instance_val)); - return Const.get(cpi, dwarf).debug_info_ni.unwrap().?; - }; const decl_gop = try dwarf.decls.getOrPut(gpa, inst); if (!decl_gop.found_existing) decl_gop.value_ptr.* = .{ .debug_info_ni = .none, }; const di: Decl.Index = @fromBackingInt(@intCast(decl_gop.index)); if (decl_gop.value_ptr.debug_info_ni.unwrap()) |debug_info_ni| return debug_info_ni; - dwarf.pending_decl = .{ .di = di, .instance_val = instance_val }; - const elf = dwarf.lf.cast(.elf2).?; - try elf.nodes.ensureUnusedCapacity(gpa, 1); - try elf.dwarf_decls.putNoClobber(gpa, di, .{ - .debug_info_first_target_reloc = .none, - .debug_info_first_node_reloc = .none, - }); - const unit = dwarf.getUnit(zcu.fileByIndex(di.srcInst(dwarf).resolveFile(ip)).mod.?).get(dwarf); - const debug_info_ni = elf.addNodeAssumeCapacity( - unit.debug_info_ni.unwrap().?.addFloatingChild(gpa, &elf.mf, .{ - .enable_next_moved = true, - }) catch |err| switch (err) { - else => |e| return e, - error.MappedFileIo => return comp.link_diags.fail("failed to write output file: {t}", .{ - elf.mf.io_err.?, - }), - }, - .{ .decl_debug_info = di }, - ); + dwarf.pending_decl = .{ .di = di, .instance = instance }; + const debug_info_ni = if (dwarf.lf.cast(.elf2)) |elf| debug_info_ni: { + try elf.nodes.ensureUnusedCapacity(gpa, 1); + try elf.dwarf_decls.putNoClobber(gpa, di, .{ + .debug_info_first_target_reloc = .none, + .debug_info_first_node_reloc = .none, + }); + const unit = dwarf.getUnit(zcu.fileByIndex(di.srcInst(dwarf).resolveFile(ip)).mod.?).get(dwarf); + const debug_info_ni = elf.addNodeAssumeCapacity( + unit.debug_info_ni.unwrap().?.addFloatingChild(gpa, &elf.mf, .{ + .enable_next_moved = true, + }) catch |err| switch (err) { + else => |e| return e, + error.MappedFileIo => return comp.link_diags.fail("failed to write output file: {t}", .{ + elf.mf.io_err.?, + }), + }, + .{ .decl_debug_info = di }, + ); + break :debug_info_ni debug_info_ni; + } else unreachable; decl_gop.value_ptr.debug_info_ni = .wrap(debug_info_ni); return debug_info_ni; } @@ -1561,7 +1690,7 @@ pub fn unitLengthSize(dwarf: *Dwarf) usize { .@"64" => 4 + 8, }; } -pub fn genUnitLength(dwarf: *Dwarf, w: *std.Io.Writer) std.Io.Writer.Error!void { +fn genUnitLength(dwarf: *Dwarf, w: *std.Io.Writer) std.Io.Writer.Error!void { switch (dwarf.format) { .@"32" => try w.writeInt(u32, undefined, dwarf.endian), .@"64" => { @@ -1582,6 +1711,24 @@ pub fn genUnitPadding(dwarf: *Dwarf, w: *std.Io.Writer) std.Io.Writer.Error!void try w.writeInt(u16, 0, dwarf.endian); } +pub fn genDebugAddrHeader(dwarf: *Dwarf, dah_w: *std.Io.Writer) std.Io.Writer.Error!void { + try dwarf.genUnitLength(dah_w); + try dah_w.writeInt(u16, 5, dwarf.endian); + try dah_w.writeAll(&.{ @backingInt(dwarf.address_size), 0 }); + assert(dah_w.end == Addr.tableOffset(dwarf)); +} + +pub fn genPendingDebugAddr(dwarf: *Dwarf, da_nw: *link.MappedFile.Node.Writer) link.Error!void { + da_nw.interface.end = dwarf.debug_addr.size(dwarf); + for (dwarf.debug_addr.map.keys()[dwarf.debug_addr.pending_index..]) |si| { + dwarf.addrSym(da_nw, si, 0) catch |err| switch (err) { + else => |e| return e, + error.WriteFailed => return dwarf.reportWriteError(da_nw), + }; + dwarf.debug_addr.pending_index += 1; + } +} + pub const EhFrameHdr = extern struct { version: u8, eh_frame_ptr_enc: std.dwarf.EH.PE, @@ -1637,11 +1784,7 @@ pub fn genDebugFrameCie( const Register = @import("../codegen/x86_64/bits.zig").Register; switch (format) { .eh_frame => try df_w.writeAll("zR\x00"), - .debug_frame => { - try df_w.writeAll("\x00"); - try df_w.writeByte(@backingInt(dwarf.address_size)); - try df_w.writeByte(0); - }, + .debug_frame => try df_w.writeAll("\x00" ++ .{ @backingInt(dwarf.address_size), 0 }), } try df_w.writeUleb128(dwarf.frame.header.code_alignment_factor); try df_w.writeSleb128(dwarf.frame.header.data_alignment_factor); @@ -1688,28 +1831,29 @@ pub fn genDebugInfoHeader( if (!unit.alive) return dwarf.genUnitPadding(dih_w); try dwarf.genUnitLength(dih_w); try dih_w.writeInt(u16, 5, dwarf.endian); - try dih_w.writeByte(DW.UT.compile); - try dih_w.writeByte(@backingInt(dwarf.address_size)); + try dih_w.writeAll(&.{ DW.UT.compile, @backingInt(dwarf.address_size) }); try dwarf.secOffset(dih_nw, dwarf.debug_abbrev.ni.unwrap().?, 0); const compile_unit_offset = dih_w.end; try dwarf.abbrevCode(dih_nw, .compile_unit); try dih_w.writeByte(DW.LANG.Zig); - try dwarf.strp(&dwarf.debug_str, dih_nw, "zig " ++ @import("build_options").version); - const root_dir_path = try mod.root.toAbsolute(&comp.dirs, comp.gpa); - defer comp.gpa.free(root_dir_path); - try dwarf.strp(&dwarf.debug_line_str, dih_nw, root_dir_path); - try dwarf.strp(&dwarf.debug_line_str, dih_nw, mod.root_src_path); try dwarf.secOffset( dih_nw, dwarf.getUnit(zcu.root_mod).get(dwarf).debug_info_header_ni.unwrap().?, compile_unit_offset, ); try dwarf.secOffset(dih_nw, unit.debug_line_header_ni.unwrap().?, 0); - try dwarf.secOffset(dih_nw, unit.debug_rnglists_ni.unwrap().?, Rnglists.offsetsTableOffset(dwarf)); + try dwarf.secOffset(dih_nw, dwarf.debug_addr.ni.unwrap().?, Addr.tableOffset(dwarf)); + try dwarf.secOffset(dih_nw, unit.debug_rnglists_ni.unwrap().?, Rnglists.tableOffset(dwarf)); + try dwarf.secOffset(dih_nw, dwarf.debug_str_offsets.ni.unwrap().?, StrOffsets.tableOffset(dwarf)); + try dwarf.strx1(dih_nw, "zig " ++ @import("build_options").version); + const root_dir_path = try mod.root.toAbsolute(&comp.dirs, comp.gpa); + defer comp.gpa.free(root_dir_path); + try dwarf.strp(&dwarf.debug_line_str, dih_nw, root_dir_path); + try dwarf.strp(&dwarf.debug_line_str, dih_nw, mod.root_src_path); try dih_w.writeUleb128(0); const module_offset = dih_w.end; try dwarf.abbrevCode(dih_nw, .module); - try dwarf.strp(&dwarf.debug_str, dih_nw, mod.fully_qualified_name); + try dwarf.strx(dih_nw, mod.fully_qualified_name); try dih_w.writeUleb128(0); try dwarf.genModuleDependency( dih_nw, @@ -1735,7 +1879,7 @@ fn genModuleDependency( const dep_unit = dwarf.getUnit(dep).get(dwarf); if (!dep_unit.alive) return; try dwarf.abbrevCode(di_nw, .module_dependency); - try dwarf.strp(&dwarf.debug_str, di_nw, name); + try dwarf.strx(di_nw, name); try dwarf.secOffset(di_nw, dep_unit.debug_info_header_ni.unwrap().?, module_offset); } @@ -1779,8 +1923,7 @@ pub fn genDebugLineHeader( const dlh_w = &dlh_nw.interface; try dwarf.genUnitLength(dlh_w); try dlh_w.writeInt(u16, 5, dwarf.endian); - try dlh_w.writeByte(@backingInt(dwarf.address_size)); - try dlh_w.writeByte(0); + try dlh_w.writeAll(&.{ @backingInt(dwarf.address_size), 0 }); const header_length_offset = dlh_w.end; switch (dwarf.format) { .@"32" => try dlh_w.writeInt(u32, undefined, dwarf.endian), @@ -1852,11 +1995,7 @@ pub fn genDebugLineHeader( } try dlh_w.writeInt(i64, @truncate(zf.stat.mtime.nanoseconds), dwarf.endian); try dlh_w.writeInt(u64, zf.stat.size, dwarf.endian); - try dwarf.strp( - &dwarf.debug_line_str, - dlh_nw, - if (zf.is_builtin) zf.source.? else "", - ); + try dwarf.strp(&dwarf.debug_line_str, dlh_nw, if (zf.is_builtin) zf.source.? else ""); } switch (dwarf.format) { .@"32" => std.mem.writeInt( @@ -1915,10 +2054,9 @@ pub fn genDebugRnglistsHeader( const drh_w = &drh_nw.interface; try dwarf.genUnitLength(drh_w); try drh_w.writeInt(u16, 5, dwarf.endian); - try drh_w.writeByte(@backingInt(dwarf.address_size)); - try drh_w.writeByte(0); + try drh_w.writeAll(&.{ @backingInt(dwarf.address_size), 0 }); try drh_w.writeInt(u32, 1, dwarf.endian); - assert(drh_w.end == Rnglists.offsetsTableOffset(dwarf)); + assert(drh_w.end == Rnglists.tableOffset(dwarf)); switch (dwarf.format) { .@"32" => try drh_w.writeInt(u32, 4, dwarf.endian), .@"64" => try drh_w.writeInt(u64, 8, dwarf.endian), @@ -1927,7 +2065,7 @@ pub fn genDebugRnglistsHeader( try drh_w.writeByte(DW.RLE.end_of_list); } -pub fn genDebugRnglists( +pub fn genDebugRnglistsRange( dwarf: *Dwarf, unit: *Unit, dr_nw: *link.MappedFile.Node.Writer, @@ -1936,74 +2074,396 @@ pub fn genDebugRnglists( ) link.EmitError!void { const dr_w = &dr_nw.interface; dr_w.end = unit.debug_rnglists_end; - try dr_w.writeByte(DW.RLE.start_length); - try dwarf.addrSym(dr_nw, func_si, 0); + try dr_w.writeByte(DW.RLE.startx_length); + try dwarf.addrxSym(dr_w, func_si); try dr_w.writeUleb128(func_length); unit.debug_rnglists_end = dr_w.end; try dr_w.writeByte(DW.RLE.end_of_list); } -pub fn updateComptimeNav( +pub fn genDebugStrOffsetsHeader(dwarf: *Dwarf, dsoh_w: *std.Io.Writer) std.Io.Writer.Error!void { + try dwarf.genUnitLength(dsoh_w); + try dsoh_w.writeInt(u16, 5, dwarf.endian); + try dsoh_w.writeInt(u16, 0, dwarf.endian); + assert(dsoh_w.end == StrOffsets.tableOffset(dwarf)); +} + +pub fn genPendingDebugStrOffsets(dwarf: *Dwarf, dso_nw: *link.MappedFile.Node.Writer) link.Error!void { + const debug_str_ni = dwarf.debug_str.ni.unwrap().?; + dso_nw.interface.end = dwarf.debug_str_offsets.size(dwarf); + for (dwarf.debug_str_offsets.map.keys()[dwarf.debug_str_offsets.pending_index..]) |offset| { + dwarf.secOffset(dso_nw, debug_str_ni, offset) catch |err| switch (err) { + else => |e| return e, + error.WriteFailed => return dwarf.reportWriteError(dso_nw), + }; + dwarf.debug_str_offsets.pending_index += 1; + } +} + +pub fn updateExtern( dwarf: *Dwarf, pt: Zcu.PerThread, - nav_index: InternPool.Nav.Index, + di_nw: *link.MappedFile.Node.Writer, + arch: std.Target.Cpu.Arch, + si: link.File.SymbolId, + global: InternPool.Nav.Index, +) link.Error!void { + dwarf.updateExternInner(pt, di_nw, arch, si, global) catch |err| switch (err) { + else => |e| return e, + error.WriteFailed => return dwarf.reportWriteError(di_nw), + }; +} +fn updateExternInner( + dwarf: *Dwarf, + pt: Zcu.PerThread, + di_nw: *link.MappedFile.Node.Writer, + arch: std.Target.Cpu.Arch, + si: link.File.SymbolId, + global: InternPool.Nav.Index, +) link.EmitError!void { + const zcu = pt.zcu; + const ip = &zcu.intern_pool; + const nav = ip.getNav(global); + log.debug("updateExtern({f})", .{nav.fqn.fmt(ip)}); + const nav_align, const nav_const, const nav_threadlocal, const nav_extern = nav_resolved: { + const nav_resolved = nav.resolved.?; + break :nav_resolved .{ + nav_resolved.@"align", + nav_resolved.@"const", + nav_resolved.@"threadlocal", + ip.indexToKey(nav_resolved.value).@"extern", + }; + }; + const inst_info = nav.srcInst(ip).resolveFull(ip).?; + const decl = switch (nav_extern.source) { + .builtin => undefined, + .syntax => zcu.fileByIndex(inst_info.file).zir.?.getDeclaration(inst_info.inst), + }; + const maybe_func_type = switch (ip.indexToKey(nav_extern.ty)) { + .func_type => |func_type| func_type, + else => null, + }; + const is_empty = if (maybe_func_type) |func_type| func_type.param_types.len == 0 and + !func_type.is_var_args else undefined; + const di_w = &di_nw.interface; + switch (nav_extern.source) { + .builtin => { + try dwarf.abbrevCode(di_nw, if (maybe_func_type) |_| + if (is_empty) .builtin_extern_empty_func else .builtin_extern_func + else + .builtin_extern_var); + try dwarf.refType(pt, di_nw, .fromInterned(zcu.fileRootType(inst_info.file))); + }, + .syntax => if (maybe_func_type) |_| { + try dwarf.abbrevCode( + di_nw, + if (is_empty) .decl_extern_empty_func else .decl_extern_func, + ); + try dwarf.refType(pt, di_nw, .fromInterned(zcu.fileRootType(inst_info.file))); + try di_w.writeInt(u32, decl.src_line + 1, dwarf.endian); + try di_w.writeUleb128(decl.src_column + 1); + try di_w.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); + try dwarf.strx(di_nw, nav.name.toSlice(ip)); + } else { + try dwarf.abbrevCode(di_nw, .decl_var); + try dwarf.refType(pt, di_nw, .fromInterned(zcu.fileRootType(inst_info.file))); + try di_w.writeInt(u32, decl.src_line + 1, dwarf.endian); + try di_w.writeUleb128(decl.src_column + 1); + try di_w.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); + try dwarf.strx(di_nw, nav.name.toSlice(ip)); + }, + } + try dwarf.strx(di_nw, nav_extern.name.toSlice(ip)); + if (maybe_func_type) |func_type| { + try dwarf.refType(pt, di_nw, .fromInterned(func_type.return_type)); + try dwarf.addrSym(di_nw, si, 0); + try di_w.writeByte(@intFromBool(Type.fromInterned(func_type.return_type).isNoReturn(zcu))); + for (func_type.param_types.get(ip)) |param_type| { + try dwarf.abbrevCode(di_nw, .extern_param); + try dwarf.refType(pt, di_nw, .fromInterned(param_type)); + } + if (func_type.is_var_args) try dwarf.abbrevCode(di_nw, .is_var_args); + if (!is_empty) try di_w.writeUleb128(@backingInt(AbbrevCode.null)); + } else { + const addr: Loc = .{ .addr_sym = .{ .si = si } }; + const loc: Loc = if (nav_threadlocal) switch (arch) { + .x86_64 => .{ .form_tls_address = &addr }, + else => unreachable, + } else addr; + const type_offset = di_w.end; + if (nav_const) + try dwarf.secOffsetPlaceholder(di_w) + else + try dwarf.refType(pt, di_nw, .fromInterned(nav_extern.ty)); + try dwarf.exprLoc(di_nw, loc); + try di_w.writeUleb128(nav_align.toByteUnits() orelse + Type.fromInterned(nav_extern.ty).abiAlignment(zcu).toByteUnits().?); + switch (nav_extern.source) { + .builtin => {}, + .syntax => try di_w.writeByte(@intFromBool(decl.linkage != .normal)), + } + if (nav_const) { + try dwarf.secOffsetFinish(di_nw, type_offset, di_nw.ni, di_w.end); + try dwarf.abbrevCode(di_nw, .is_const); + try dwarf.refType(pt, di_nw, .fromInterned(nav_extern.ty)); + } + } + try dwarf.genDebugInfoPadding(di_w, di_w.unusedCapacityLen()); +} + +pub fn updateGlobal( + dwarf: *Dwarf, + pt: Zcu.PerThread, + di_nw: *link.MappedFile.Node.Writer, + arch: std.Target.Cpu.Arch, + si: link.File.SymbolId, + global: InternPool.Nav.Index, +) link.Error!void { + const ip = &pt.zcu.intern_pool; + log.debug("updateGlobal({f})", .{ip.getNav(global).fqn.fmt(ip)}); + dwarf.updateGlobalInner(pt, di_nw, arch, si, global) catch |err| switch (err) { + else => |e| return e, + error.WriteFailed => return dwarf.reportWriteError(di_nw), + }; +} +fn updateGlobalInner( + dwarf: *Dwarf, + pt: Zcu.PerThread, + di_nw: *link.MappedFile.Node.Writer, + arch: std.Target.Cpu.Arch, + si: link.File.SymbolId, + global: InternPool.Nav.Index, +) link.EmitError!void { + const zcu = pt.zcu; + const ip = &zcu.intern_pool; + const nav = ip.getNav(global); + const nav_ty: Type, const nav_align, const nav_const, const nav_threadlocal = nav_resolved: { + const nav_resolved = nav.resolved.?; + break :nav_resolved .{ + .fromInterned(nav_resolved.type), + nav_resolved.@"align", + nav_resolved.@"const", + nav_resolved.@"threadlocal", + }; + }; + const inst_info = nav.srcInst(ip).resolveFull(ip).?; + const decl = zcu.fileByIndex(inst_info.file).zir.?.getDeclaration(inst_info.inst); + switch (decl.kind) { + .unnamed_test, .@"test", .decltest, .@"comptime" => unreachable, + .@"const" => assert(nav_const), + .@"var" => assert(!nav_const), + } + const parent_ty: Type = .fromInterned(ip.namespacePtr(nav.analysis.?.namespace).owner_type); + const di_w = &di_nw.interface; + if (parent_ty.getCaptures(zcu).len > 0) { + try dwarf.abbrevCode(di_nw, .decl_instance_var); + try dwarf.refType(pt, di_nw, parent_ty); + try dwarf.secOffset(di_nw, try dwarf.getGlobalDecl(pt, global), 0); + } else { + const parent_ni = try dwarf.getConstDecl(pt, parent_ty.toIntern()); + try dwarf.abbrevCode(di_nw, .decl_var); + try dwarf.secOffset(di_nw, parent_ni, 0); + try di_w.writeInt(u32, decl.src_line + 1, dwarf.endian); + try di_w.writeUleb128(decl.src_column + 1); + try di_w.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); + try dwarf.strx(di_nw, nav.name.toSlice(ip)); + } + try dwarf.strx(di_nw, switch (decl.linkage) { + .normal => nav.fqn, + .@"extern" => unreachable, + .@"export" => nav.name, + }.toSlice(ip)); + const addr: Loc = .{ .addr_sym = .{ .si = si } }; + const loc: Loc = if (nav_threadlocal) switch (arch) { + .x86_64 => .{ .form_tls_address = &addr }, + else => unreachable, + } else addr; + const type_offset = di_w.end; + if (nav_const) try dwarf.secOffsetPlaceholder(di_w) else try dwarf.refType(pt, di_nw, nav_ty); + try dwarf.exprLoc(di_nw, loc); + try di_w.writeUleb128(nav_align.toByteUnits() orelse nav_ty.abiAlignment(zcu).toByteUnits().?); + try di_w.writeByte(@intFromBool(decl.linkage != .normal)); + if (nav_const) { + try dwarf.secOffsetFinish(di_nw, type_offset, di_nw.ni, di_w.end); + try dwarf.abbrevCode(di_nw, .is_const); + try dwarf.refType(pt, di_nw, nav_ty); + } + try dwarf.genDebugInfoPadding(di_w, di_w.unusedCapacityLen()); +} + +pub fn updateComptimeGlobal( + dwarf: *Dwarf, + pt: Zcu.PerThread, + global: InternPool.Nav.Index, ) link.Error!void { const zcu = pt.zcu; const ip = &zcu.intern_pool; - const nav = ip.getNav(nav_index); - log.debug("updateComptimeNav({f})", .{nav.fqn.fmt(ip)}); + const nav = ip.getNav(global); + log.debug("updateComptimeGlobal({f})", .{nav.fqn.fmt(ip)}); const inst_info = nav.srcInst(ip).resolveFull(ip).?; const nav_val: Value = .fromInterned(nav.resolved.?.value); - const zf = zcu.fileByIndex(inst_info.file); - const decl = zf.zir.?.getDeclaration(inst_info.inst); + const decl = zcu.fileByIndex(inst_info.file).zir.?.getDeclaration(inst_info.inst); switch (decl.kind) { .unnamed_test, .@"test", .decltest => return, .@"comptime", .@"const", .@"var" => {}, } - done: switch (ip.indexToKey(nav_val.toIntern())) { + switch (ip.indexToKey(nav_val.toIntern())) { + .int_type, + .ptr_type, + .array_type, + .vector_type, + .opt_type, + .error_union_type, + .anyframe_type, + .simple_type, + .tuple_type, + .func_type, + .error_set_type, + .inferred_error_set_type, + .spirv_type, + .undef, + .simple_value, + .int, + .err, + .error_union, + .enum_literal, + .enum_tag, + .float, + .ptr, + .slice, + .opt, + .aggregate, + .un, + .bitpack, + => try dwarf.genComptimeGlobal(pt, global, &decl), .struct_type => { const loaded_struct = ip.loadStructType(nav_val.toIntern()); - if (nav_index.toOptional() == loaded_struct.name_nav) { + if (loaded_struct.name_nav == global.toOptional()) { _ = try dwarf.const_pool.get(pt, dwarf.constPoolUser(), nav_val.toIntern()); - break :done; - } - return; + } else try dwarf.genComptimeGlobal(pt, global, &decl); }, .enum_type => { const loaded_enum = ip.loadEnumType(nav_val.toIntern()); - if (nav_index.toOptional() == loaded_enum.name_nav) { + if (loaded_enum.name_nav == global.toOptional()) { _ = try dwarf.const_pool.get(pt, dwarf.constPoolUser(), nav_val.toIntern()); - break :done; - } - return; + } else try dwarf.genComptimeGlobal(pt, global, &decl); }, .union_type => { const loaded_union = ip.loadUnionType(nav_val.toIntern()); - if (nav_index.toOptional() == loaded_union.name_nav) { + if (loaded_union.name_nav == global.toOptional()) { _ = try dwarf.const_pool.get(pt, dwarf.constPoolUser(), nav_val.toIntern()); - break :done; - } - return; + } else try dwarf.genComptimeGlobal(pt, global, &decl); }, .opaque_type => { const loaded_opaque = ip.loadOpaqueType(nav_val.toIntern()); - if (nav_index.toOptional() == loaded_opaque.name_nav) { + if (loaded_opaque.name_nav == global.toOptional()) { _ = try dwarf.const_pool.get(pt, dwarf.constPoolUser(), nav_val.toIntern()); - break :done; - } - return; + } else try dwarf.genComptimeGlobal(pt, global, &decl); }, - .func => |func| if (func.owner_nav == nav_index and func.generic_owner == .none) { + .@"extern" => unreachable, + .func => |func| if (func.owner_nav == global) { _ = try dwarf.const_pool.get(pt, dwarf.constPoolUser(), nav_val.toIntern()); - break :done; - } else return, - - else => return, - - // memoization, not values - .memoized_call => unreachable, + } else try dwarf.genComptimeGlobal(pt, global, &decl), + .memoized_call => unreachable, // not a value } - try dwarf.const_pool.flushPending(pt, dwarf.constPoolUser()); +} +fn genComptimeGlobal( + dwarf: *Dwarf, + pt: Zcu.PerThread, + global: InternPool.Nav.Index, + decl: *const std.zig.Zir.Inst.Declaration.Unwrapped, +) link.Error!void { + const gpa = pt.zcu.gpa; + const gi = try dwarf.getGlobal(global); + const debug_info_ni = gi.get(dwarf).debug_info_ni.unwrap().?; + var di_nw: link.MappedFile.Node.Writer = undefined; + if (dwarf.lf.cast(.elf2)) |elf| { + try debug_info_ni.moved(gpa, &elf.mf); + debug_info_ni.writer(gpa, &elf.mf, &di_nw); + elf.resetNodeRelocs(debug_info_ni); + } else unreachable; + defer di_nw.deinit(); + dwarf.genComptimeGlobalInner(pt, &di_nw, global, decl) catch |err| switch (err) { + else => |e| return e, + error.WriteFailed => return dwarf.reportWriteError(&di_nw), + }; +} +fn genComptimeGlobalInner( + dwarf: *Dwarf, + pt: Zcu.PerThread, + di_nw: *link.MappedFile.Node.Writer, + global: InternPool.Nav.Index, + decl: *const std.zig.Zir.Inst.Declaration.Unwrapped, +) link.EmitError!void { + const zcu = pt.zcu; + const ip = &zcu.intern_pool; + const nav = ip.getNav(global); + const nav_ty: Type, const nav_align, const nav_const, const nav_val: Value = nav_resolved: { + const nav_resolved = nav.resolved.?; + break :nav_resolved .{ + .fromInterned(nav_resolved.type), + nav_resolved.@"align", + nav_resolved.@"const", + .fromInterned(nav_resolved.value), + }; + }; + const nav_class = nav_ty.classify(zcu); + const parent_ty: Type = .fromInterned(ip.namespacePtr(nav.analysis.?.namespace).owner_type); + const di_w = &di_nw.interface; + if (parent_ty.getCaptures(zcu).len > 0) { + try dwarf.abbrevCode(di_nw, switch (nav_ty.toIntern()) { + .type_type => .decl_instance_type, + else => switch (nav_class) { + .no_possible_value, .one_possible_value => .decl_instance_const, + .runtime => .decl_instance_const_fully_runtime, + .partially_comptime => .decl_instance_const_partially_comptime, + .fully_comptime => .decl_instance_const_fully_comptime, + }, + }); + try dwarf.refType(pt, di_nw, parent_ty); + try dwarf.secOffset(di_nw, try dwarf.getGlobalDecl(pt, global), 0); + } else { + const parent_ni = try dwarf.getConstDecl(pt, parent_ty.toIntern()); + try dwarf.abbrevCode(di_nw, switch (nav_ty.toIntern()) { + .type_type => .decl_type, + else => switch (nav_class) { + .no_possible_value, .one_possible_value => .decl_const, + .runtime => .decl_const_fully_runtime, + .partially_comptime => .decl_const_partially_comptime, + .fully_comptime => .decl_const_fully_comptime, + }, + }); + try dwarf.secOffset(di_nw, parent_ni, 0); + try di_w.writeInt(u32, decl.src_line + 1, dwarf.endian); + try di_w.writeUleb128(decl.src_column + 1); + try di_w.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); + try dwarf.strx(di_nw, nav.name.toSlice(ip)); + } + switch (nav_ty.toIntern()) { + .type_type => try dwarf.refConst(pt, di_nw, nav_val), + else => { + try dwarf.strx(di_nw, switch (decl.linkage) { + .normal => nav.fqn, + .@"extern", .@"export" => nav.name, + }.toSlice(ip)); + const type_offset = di_w.end; + if (nav_const) + try dwarf.secOffsetPlaceholder(di_w) + else + try dwarf.refType(pt, di_nw, nav_ty); + try di_w.writeUleb128(nav_align.toByteUnits() orelse + nav_ty.abiAlignment(zcu).toByteUnits().?); + try di_w.writeByte(@intFromBool(decl.linkage != .normal)); + if (nav_class.hasRuntimeBits()) try dwarf.blockConst(pt, di_nw, nav_val); + if (nav_class.comptimeOnly()) try dwarf.refConst(pt, di_nw, nav_val); + if (nav_const) { + try dwarf.secOffsetFinish(di_nw, type_offset, di_nw.ni, di_w.end); + try dwarf.abbrevCode(di_nw, .is_const); + try dwarf.refType(pt, di_nw, nav_ty); + } + }, + } + try dwarf.genDebugInfoPadding(di_w, di_w.unusedCapacityLen()); } pub fn addConst( @@ -2041,9 +2501,11 @@ pub fn addConst( const name_gi = try dwarf.getGlobal(name_nav); break :debug_info_ni name_gi.get(dwarf).debug_info_ni.unwrap().?; } - break :debug_info_ni try addConstNode(dwarf.lf, dwarf.getUnit(zcu.fileByIndex( + const mod = zcu.fileByIndex( Type.fromInterned(val).typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip), - ).mod.?), cpi); + ).mod.?; + assert(!mod.strip); + break :debug_info_ni try addConstNode(dwarf.lf, dwarf.getUnit(mod), cpi); }, }.toOptional(), }); @@ -2068,17 +2530,17 @@ fn updateConstInner( dwarf: *Dwarf, pt: Zcu.PerThread, di_nw: *link.MappedFile.Node.Writer, - val: InternPool.Index, + @"const": InternPool.Index, ) link.EmitError!void { const zcu = pt.zcu; const ip = &zcu.intern_pool; const di_w = &di_nw.interface; - switch (ip.indexToKey(val)) { + switch (ip.indexToKey(@"const")) { .int_type => |int_type| { - const ty: Type = .fromInterned(val); + const ty: Type = .fromInterned(@"const"); try dwarf.abbrevCode(di_nw, .numeric_type); var name_buf: [std.fmt.count("i{d}", .{std.math.maxInt(u16)})]u8 = undefined; - try dwarf.strp(&dwarf.debug_str, di_nw, std.mem.print(&name_buf, "{f}", .{ + try dwarf.strx(di_nw, std.mem.print(&name_buf, "{f}", .{ ty.fmt(pt), }) catch unreachable); try di_w.writeByte(switch (int_type.signedness) { @@ -2091,56 +2553,54 @@ fn updateConstInner( }, .ptr_type => |ptr_type| switch (ptr_type.flags.size) { .one, .many, .c => { - const name = try zcu.gpa.print("{f}", .{Type.fromInterned(val).fmt(pt)}); + const name = try zcu.gpa.print("{f}", .{Type.fromInterned(@"const").fmt(pt)}); defer zcu.gpa.free(name); try dwarf.abbrevCode(di_nw, switch (ptr_type.sentinel) { - .none => switch (ptr_type.flags.alignment) { - .none => .ptr_type, - else => .ptr_aligned_type, - }, - else => switch (ptr_type.flags.alignment) { - .none => .ptr_sentinel_type, - else => .ptr_aligned_sentinel_type, - }, + .none => .ptr_type, + else => .ptr_sentinel_type, }); - try dwarf.strp(&dwarf.debug_str, di_nw, name); + try dwarf.strx(di_nw, name); switch (ptr_type.sentinel) { .none => {}, else => |sentinel| try dwarf.blockConst(pt, di_nw, .fromInterned(sentinel)), } - if (ptr_type.flags.alignment.toByteUnits()) |a| try di_w.writeUleb128(a); try di_w.writeByte(@backingInt(ptr_type.flags.address_space)); - if (ptr_type.flags.is_const or ptr_type.flags.is_volatile) try dwarf.secOffset( - di_nw, - di_nw.ni, - di_w.end + dwarf.secOffsetSize(), - ); + if (ptr_type.flags.alignment.toByteUnits()) |a| { + const type_offset = di_w.end; + try dwarf.secOffsetPlaceholder(di_w); + try dwarf.secOffsetFinish(di_nw, type_offset, di_nw.ni, di_w.end); + try dwarf.abbrevCode(di_nw, .is_aligned); + try di_w.writeUleb128(a); + } if (ptr_type.flags.is_const) { + const type_offset = di_w.end; + try dwarf.secOffsetPlaceholder(di_w); + try dwarf.secOffsetFinish(di_nw, type_offset, di_nw.ni, di_w.end); try dwarf.abbrevCode(di_nw, .is_const); - if (ptr_type.flags.is_volatile) try dwarf.secOffset( - di_nw, - di_nw.ni, - di_w.end + dwarf.secOffsetSize(), - ); } - if (ptr_type.flags.is_volatile) try dwarf.abbrevCode(di_nw, .is_volatile); + if (ptr_type.flags.is_volatile) { + const type_offset = di_w.end; + try dwarf.secOffsetPlaceholder(di_w); + try dwarf.secOffsetFinish(di_nw, type_offset, di_nw.ni, di_w.end); + try dwarf.abbrevCode(di_nw, .is_volatile); + } try dwarf.refType(pt, di_nw, .fromInterned(ptr_type.child)); }, .slice => { - const ty: Type = .fromInterned(val); + const ty: Type = .fromInterned(@"const"); const name = try zcu.gpa.print("{f}", .{ty.fmt(pt)}); defer zcu.gpa.free(name); try dwarf.abbrevCode(di_nw, .generated_struct_type); - try dwarf.strp(&dwarf.debug_str, di_nw, name); + try dwarf.strx(di_nw, name); try di_w.writeUleb128(ty.abiSize(zcu)); try di_w.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?); try dwarf.abbrevCode(di_nw, .generated_field); - try dwarf.strp(&dwarf.debug_str, di_nw, "ptr"); + try dwarf.strx(di_nw, "ptr"); const ptr_field_ty = ty.slicePtrFieldType(zcu); try dwarf.refType(pt, di_nw, ptr_field_ty); try di_w.writeUleb128(0); try dwarf.abbrevCode(di_nw, .generated_field); - try dwarf.strp(&dwarf.debug_str, di_nw, "len"); + try dwarf.strx(di_nw, "len"); const len_field_ty: Type = .usize; try dwarf.refType(pt, di_nw, len_field_ty); try di_w.writeUleb128(len_field_ty.abiAlignment(zcu).forward(ptr_field_ty.abiSize(zcu))); @@ -2148,13 +2608,13 @@ fn updateConstInner( }, }, .array_type => |array_type| { - const name = try zcu.gpa.print("{f}", .{Type.fromInterned(val).fmt(pt)}); + const name = try zcu.gpa.print("{f}", .{Type.fromInterned(@"const").fmt(pt)}); defer zcu.gpa.free(name); try dwarf.abbrevCode( di_nw, if (array_type.sentinel == .none) .array_type else .array_sentinel_type, ); - try dwarf.strp(&dwarf.debug_str, di_nw, name); + try dwarf.strx(di_nw, name); if (array_type.sentinel != .none) try dwarf.blockConst(pt, di_nw, .fromInterned(array_type.sentinel)); try dwarf.refType(pt, di_nw, .fromInterned(array_type.child)); @@ -2164,10 +2624,10 @@ fn updateConstInner( try di_w.writeUleb128(@backingInt(AbbrevCode.null)); }, .vector_type => |vector_type| { - const name = try zcu.gpa.print("{f}", .{Type.fromInterned(val).fmt(pt)}); + const name = try zcu.gpa.print("{f}", .{Type.fromInterned(@"const").fmt(pt)}); defer zcu.gpa.free(name); try dwarf.abbrevCode(di_nw, .vector_type); - try dwarf.strp(&dwarf.debug_str, di_nw, name); + try dwarf.strx(di_nw, name); try dwarf.refType(pt, di_nw, .fromInterned(vector_type.child)); try dwarf.abbrevCode(di_nw, .array_len); try dwarf.refType(pt, di_nw, .usize); @@ -2175,28 +2635,30 @@ fn updateConstInner( try di_w.writeUleb128(@backingInt(AbbrevCode.null)); }, .opt_type => |opt_child_type_index| { - const opt_ty: Type = .fromInterned(val); + const opt_ty: Type = .fromInterned(@"const"); const opt_child_ty: Type = .fromInterned(opt_child_type_index); const opt_repr = optRepr(opt_child_ty, zcu); const name = try zcu.gpa.print("{f}", .{opt_ty.fmt(pt)}); defer zcu.gpa.free(name); try dwarf.abbrevCode(di_nw, .generated_union_type); - try dwarf.strp(&dwarf.debug_str, di_nw, name); + try dwarf.strx(di_nw, name); try di_w.writeUleb128(opt_ty.abiSize(zcu)); try di_w.writeUleb128(opt_ty.abiAlignment(zcu).toByteUnits().?); switch (opt_repr) { .opv_null => { try dwarf.abbrevCode(di_nw, .generated_field); - try dwarf.strp(&dwarf.debug_str, di_nw, "null"); + try dwarf.strx(di_nw, "null"); try dwarf.refType(pt, di_nw, .null); try di_w.writeUleb128(0); }, .unpacked, .error_set, .pointer => { try dwarf.abbrevCode(di_nw, .tagged_union); - try dwarf.secOffset(di_nw, di_nw.ni, di_w.end + dwarf.secOffsetSize()); + const discr_offset = di_w.end; + try dwarf.secOffsetPlaceholder(di_w); { + try dwarf.secOffsetFinish(di_nw, discr_offset, di_nw.ni, di_w.end); try dwarf.abbrevCode(di_nw, .generated_field); - try dwarf.strp(&dwarf.debug_str, di_nw, "has_value"); + try dwarf.strx(di_nw, "has_value"); switch (opt_repr) { .opv_null => unreachable, .unpacked => { @@ -2207,7 +2669,10 @@ fn updateConstInner( 0); }, .error_set => { - try dwarf.refType(pt, di_nw, try pt.intType(.unsigned, zcu.errorSetBits())); + try dwarf.refType(pt, di_nw, try pt.intType( + .unsigned, + zcu.errorSetBits(), + )); try di_w.writeUleb128(0); }, .pointer => { @@ -2221,7 +2686,7 @@ fn updateConstInner( try di_w.writeByte(0); { try dwarf.abbrevCode(di_nw, .generated_field); - try dwarf.strp(&dwarf.debug_str, di_nw, "null"); + try dwarf.strx(di_nw, "null"); try dwarf.refType(pt, di_nw, .null); try di_w.writeUleb128(0); } @@ -2230,7 +2695,7 @@ fn updateConstInner( try dwarf.abbrevCode(di_nw, .tagged_union_default_field); { try dwarf.abbrevCode(di_nw, .generated_field); - try dwarf.strp(&dwarf.debug_str, di_nw, "?"); + try dwarf.strx(di_nw, "?"); try dwarf.refType(pt, di_nw, opt_child_ty); try di_w.writeUleb128(0); } @@ -2243,7 +2708,7 @@ fn updateConstInner( }, .anyframe_type => unreachable, .error_union_type => |error_union_type| { - const eu_ty: Type = .fromInterned(val); + const eu_ty: Type = .fromInterned(@"const"); const eu_error_set_ty: Type = .fromInterned(error_union_type.error_set_type); const eu_payload_ty: Type = .fromInterned(error_union_type.payload_type); const eu_error_set_offset, const eu_payload_offset = switch (error_union_type.payload_type) { @@ -2257,7 +2722,7 @@ fn updateConstInner( defer zcu.gpa.free(name); try dwarf.abbrevCode(di_nw, .generated_union_type); - try dwarf.strp(&dwarf.debug_str, di_nw, name); + try dwarf.strx(di_nw, name); if (error_union_type.error_set_type != .generic_poison_type and error_union_type.payload_type != .generic_poison_type) { @@ -2269,10 +2734,12 @@ fn updateConstInner( } { try dwarf.abbrevCode(di_nw, .tagged_union); - try dwarf.secOffset(di_nw, di_nw.ni, di_w.end + dwarf.secOffsetSize()); + const discr_offset = di_w.end; + try dwarf.secOffsetPlaceholder(di_w); { + try dwarf.secOffsetFinish(di_nw, discr_offset, di_nw.ni, di_w.end); try dwarf.abbrevCode(di_nw, .generated_field); - try dwarf.strp(&dwarf.debug_str, di_nw, "is_error"); + try dwarf.strx(di_nw, "is_error"); try dwarf.refType(pt, di_nw, try pt.intType(.unsigned, zcu.errorSetBits())); try di_w.writeUleb128(eu_error_set_offset); @@ -2281,7 +2748,7 @@ fn updateConstInner( try di_w.writeUleb128(0); { try dwarf.abbrevCode(di_nw, .generated_field); - try dwarf.strp(&dwarf.debug_str, di_nw, "value"); + try dwarf.strx(di_nw, "value"); try dwarf.refType(pt, di_nw, eu_payload_ty); try di_w.writeUleb128(eu_payload_offset); } @@ -2290,7 +2757,7 @@ fn updateConstInner( try dwarf.abbrevCode(di_nw, .tagged_union_default_field); { try dwarf.abbrevCode(di_nw, .generated_field); - try dwarf.strp(&dwarf.debug_str, di_nw, "error"); + try dwarf.strx(di_nw, "error"); try dwarf.refType(pt, di_nw, eu_error_set_ty); try di_w.writeUleb128(eu_error_set_offset); } @@ -2320,10 +2787,10 @@ fn updateConstInner( .c_longdouble, .bool, => { - const ty: Type = .fromInterned(val); + const ty: Type = .fromInterned(@"const"); try dwarf.abbrevCode(di_nw, .numeric_type); - try dwarf.strp(&dwarf.debug_str, di_nw, @tagName(simple_type)); - try di_w.writeByte(if (val == .bool_type) + try dwarf.strx(di_nw, @tagName(simple_type)); + try di_w.writeByte(if (@"const" == .bool_type) DW.ATE.boolean else if (ty.isRuntimeFloat()) DW.ATE.float @@ -2339,7 +2806,7 @@ fn updateConstInner( }, .generic_poison => { try dwarf.abbrevCode(di_nw, .void_type); - try dwarf.strp(&dwarf.debug_str, di_nw, "anytype"); + try dwarf.strx(di_nw, "anytype"); }, .anyopaque, .void, @@ -2351,10 +2818,10 @@ fn updateConstInner( .undefined, .enum_literal, => { - const ty: Type = .fromInterned(val); + const ty: Type = .fromInterned(@"const"); try dwarf.abbrevCode(di_nw, .void_type); var name_buf: ["@TypeOf(undefined)".len]u8 = undefined; - try dwarf.strp(&dwarf.debug_str, di_nw, std.mem.print(&name_buf, "{f}", .{ + try dwarf.strx(di_nw, std.mem.print(&name_buf, "{f}", .{ ty.fmt(pt), }) catch unreachable); }, @@ -2364,29 +2831,29 @@ fn updateConstInner( .generated_enum_type else .generated_empty_enum_type); - try dwarf.strp(&dwarf.debug_str, di_nw, "anyerror"); + try dwarf.strx(di_nw, "anyerror"); try dwarf.refType(pt, di_nw, try pt.intType(.unsigned, zcu.errorSetBits())); - for (global_error_set_names, 1..) |name, value| { + for (global_error_set_names, 1..) |err_name, err_value| { try dwarf.abbrevCode(di_nw, .enum_field); try di_w.writeUleb128(DW.FORM.udata); - try di_w.writeUleb128(value); - try dwarf.strp(&dwarf.debug_str, di_nw, name.toSlice(ip)); + try di_w.writeUleb128(err_value); + try dwarf.strx(di_nw, err_name.toSlice(ip)); } if (global_error_set_names.len > 0) try di_w.writeUleb128(@backingInt(AbbrevCode.null)); }, .adhoc_inferred_error_set => unreachable, }, .tuple_type => |tuple_type| { - const ty: Type = .fromInterned(val); + const ty: Type = .fromInterned(@"const"); const name = try zcu.gpa.print("{f}", .{ty.fmt(pt)}); defer zcu.gpa.free(name); if (tuple_type.types.len == 0) { try dwarf.abbrevCode(di_nw, .generated_empty_struct_type); - try dwarf.strp(&dwarf.debug_str, di_nw, name); + try dwarf.strx(di_nw, name); try di_w.writeByte(@intFromBool(false)); } else { try dwarf.abbrevCode(di_nw, .generated_struct_type); - try dwarf.strp(&dwarf.debug_str, di_nw, name); + try dwarf.strx(di_nw, name); try di_w.writeUleb128(ty.abiSize(zcu)); try di_w.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?); var field_byte_offset: u64 = 0; @@ -2407,7 +2874,7 @@ fn updateConstInner( }, }); var field_name_buf: [std.fmt.count("{d}", .{std.math.maxInt(u32)})]u8 = undefined; - try dwarf.strp(&dwarf.debug_str, di_nw, std.mem.print(&field_name_buf, "{d}", .{ + try dwarf.strx(di_nw, std.mem.print(&field_name_buf, "{d}", .{ field_index, }) catch unreachable); try dwarf.refType(pt, di_nw, field_ty); @@ -2427,72 +2894,81 @@ fn updateConstInner( } }, .struct_type => { - const loaded_struct = ip.loadStructType(val); - const zfi = loaded_struct.zir_index.resolveFile(ip); - const zf = zcu.fileByIndex(zfi); - const src_inst = loaded_struct.zir_index.resolve(ip); - if (src_inst == .main_struct_inst) { + const loaded_struct = ip.loadStructType(@"const"); + const src_inst = loaded_struct.zir_index.resolveFull(ip).?; + const zf = zcu.fileByIndex(src_inst.file); + const is_empty = loaded_struct.captures.len == 0 and loaded_struct.field_types.len == 0; + if (src_inst.inst == .main_struct_inst) { assert(loaded_struct.captures.len == 0); const ui = dwarf.getUnit(zf.mod.?); - _, const fi = try ui.get(dwarf).getFile(zcu.gpa, ui, zfi); + _, const fi = try ui.get(dwarf).getFile(zcu.gpa, ui, src_inst.file); try dwarf.abbrevCode(di_nw, switch (loaded_struct.layout) { - .auto => if (loaded_struct.field_types.len > 0) .file else .empty_file, + .auto => if (is_empty) .empty_file else .file, .@"extern", .@"packed" => unreachable, }); try di_w.writeUleb128(@backingInt(fi)); - try dwarf.strp(&dwarf.debug_str, di_nw, loaded_struct.name.toSlice(ip)); + try dwarf.strx(di_nw, loaded_struct.name.toSlice(ip)); } else if (loaded_struct.captures.len > 0 or loaded_struct.is_reified) { - try dwarf.abbrevCode(di_nw, if (loaded_struct.captures.len > 0 or - loaded_struct.field_types.len > 0) switch (loaded_struct.layout) { - .auto, .@"extern" => .decl_instance_struct, - .@"packed" => .decl_instance_packed_struct, - } else switch (loaded_struct.layout) { - .auto, .@"extern" => .decl_instance_empty_struct, - .@"packed" => .decl_instance_empty_packed_struct, + try dwarf.abbrevCode(di_nw, switch (loaded_struct.name_nav) { + else => if (is_empty) switch (loaded_struct.layout) { + .auto, .@"extern" => .decl_instance_empty_struct, + .@"packed" => .decl_instance_empty_packed_struct, + } else switch (loaded_struct.layout) { + .auto, .@"extern" => .decl_instance_struct, + .@"packed" => .decl_instance_packed_struct, + }, + .none => if (is_empty) switch (loaded_struct.layout) { + .auto, .@"extern" => .type_decl_instance_empty_struct, + .@"packed" => .type_decl_instance_empty_packed_struct, + } else switch (loaded_struct.layout) { + .auto, .@"extern" => .type_decl_instance_struct, + .@"packed" => .type_decl_instance_packed_struct, + }, }); - try dwarf.secOffset(di_nw, try dwarf.getDecl(pt, val), 0); + try dwarf.refType(pt, di_nw, .fromInterned(ip.namespacePtr( + ip.namespacePtr(loaded_struct.namespace).parent.unwrap().?, + ).owner_type)); + try dwarf.secOffset(di_nw, try dwarf.getConstDecl(pt, @"const"), 0); + if (loaded_struct.name_nav == .none) + try dwarf.strx(di_nw, loaded_struct.name.toSlice(ip)); } else if (loaded_struct.name_nav.unwrap()) |name_ni| { const name_nav = ip.getNav(name_ni); const decl = zf.zir.?.getDeclaration(name_nav.srcInst(ip).resolve(ip).?); - const parent_ni = try dwarf.getDecl(pt, ip.namespacePtr( + const parent_ni = try dwarf.getConstDecl(pt, ip.namespacePtr( name_nav.analysis.?.namespace, ).owner_type); - try dwarf.abbrevCode(di_nw, if (loaded_struct.field_types.len > 0) - switch (loaded_struct.layout) { - .auto, .@"extern" => .decl_struct, - .@"packed" => .decl_packed_struct, - } - else switch (loaded_struct.layout) { + try dwarf.abbrevCode(di_nw, if (is_empty) switch (loaded_struct.layout) { .auto, .@"extern" => .decl_empty_struct, .@"packed" => .decl_empty_packed_struct, + } else switch (loaded_struct.layout) { + .auto, .@"extern" => .decl_struct, + .@"packed" => .decl_packed_struct, }); try dwarf.secOffset(di_nw, parent_ni, 0); try di_w.writeInt(u32, decl.src_line + 1, dwarf.endian); try di_w.writeUleb128(decl.src_column + 1); try di_w.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); - try dwarf.strp(&dwarf.debug_str, di_nw, name_nav.name.toSlice(ip)); + try dwarf.strx(di_nw, name_nav.name.toSlice(ip)); } else { - const decl = zf.zir.?.getStructDecl(src_inst.?); - const parent_ni = try dwarf.getDecl(pt, ip.namespacePtr( + const decl = zf.zir.?.getStructDecl(src_inst.inst); + const parent_ni = try dwarf.getConstDecl(pt, ip.namespacePtr( ip.namespacePtr(loaded_struct.namespace).parent.unwrap().?, ).owner_type); - try dwarf.abbrevCode(di_nw, if (loaded_struct.field_types.len > 0) - switch (loaded_struct.layout) { - .auto, .@"extern" => .type_decl_struct, - .@"packed" => .type_decl_packed_struct, - } - else switch (loaded_struct.layout) { + try dwarf.abbrevCode(di_nw, if (is_empty) switch (loaded_struct.layout) { .auto, .@"extern" => .type_decl_empty_struct, .@"packed" => .type_decl_empty_packed_struct, + } else switch (loaded_struct.layout) { + .auto, .@"extern" => .type_decl_struct, + .@"packed" => .type_decl_packed_struct, }); try dwarf.secOffset(di_nw, parent_ni, 0); try di_w.writeInt(u32, decl.src_line + 1, dwarf.endian); try di_w.writeUleb128(decl.src_column + 1); - try dwarf.strp(&dwarf.debug_str, di_nw, loaded_struct.name.toSlice(ip)); + try dwarf.strx(di_nw, loaded_struct.name.toSlice(ip)); } switch (loaded_struct.layout) { .auto, .@"extern" => { - const ty: Type = .fromInterned(val); + const ty: Type = .fromInterned(@"const"); try di_w.writeUleb128(ty.abiSize(zcu)); try di_w.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?); try dwarf.genCaptures(pt, di_nw, loaded_struct.captures); @@ -2528,8 +3004,7 @@ fn updateConstInner( .partially_comptime => .field_default_partially_comptime, .fully_comptime => .field_default_fully_comptime, }); - try dwarf.strp( - &dwarf.debug_str, + try dwarf.strx( di_nw, loaded_struct.field_names.get(ip)[field_index].toSlice(ip), ); @@ -2553,8 +3028,7 @@ fn updateConstInner( var field_bit_offset: u16 = 0; for (0..loaded_struct.field_types.len) |field_index| { try dwarf.abbrevCode(di_nw, .packed_field); - try dwarf.strp( - &dwarf.debug_str, + try dwarf.strx( di_nw, loaded_struct.field_names.get(ip)[field_index].toSlice(ip), ); @@ -2566,62 +3040,71 @@ fn updateConstInner( } }, } - if (loaded_struct.captures.len > 0 or loaded_struct.field_types.len > 0) - try di_w.writeUleb128(@backingInt(AbbrevCode.null)); + if (!is_empty) try di_w.writeUleb128(@backingInt(AbbrevCode.null)); }, .union_type => { - const loaded_union = ip.loadUnionType(val); + const loaded_union = ip.loadUnionType(@"const"); const loaded_tag = ip.loadEnumType(loaded_union.enum_tag_type); const zfi = loaded_union.zir_index.resolveFile(ip); const zf = zcu.fileByIndex(zfi); + const is_empty = loaded_union.captures.len == 0 and loaded_union.field_types.len == 0; if (loaded_union.captures.len > 0 or loaded_union.is_reified) { - try dwarf.abbrevCode(di_nw, if (loaded_union.captures.len > 0 or - loaded_union.field_types.len > 0) switch (loaded_union.layout) { - .auto, .@"extern" => .decl_instance_union, - .@"packed" => .decl_instance_packed_union, - } else switch (loaded_union.layout) { - .auto, .@"extern" => .decl_instance_empty_union, - .@"packed" => .decl_instance_empty_packed_union, + try dwarf.abbrevCode(di_nw, switch (loaded_union.name_nav) { + else => if (is_empty) switch (loaded_union.layout) { + .auto, .@"extern" => .decl_instance_empty_union, + .@"packed" => .decl_instance_empty_packed_union, + } else switch (loaded_union.layout) { + .auto, .@"extern" => .decl_instance_union, + .@"packed" => .decl_instance_packed_union, + }, + .none => if (is_empty) switch (loaded_union.layout) { + .auto, .@"extern" => .type_decl_instance_empty_union, + .@"packed" => .type_decl_instance_empty_packed_union, + } else switch (loaded_union.layout) { + .auto, .@"extern" => .type_decl_instance_union, + .@"packed" => .type_decl_instance_packed_union, + }, }); - try dwarf.secOffset(di_nw, try dwarf.getDecl(pt, val), 0); + try dwarf.refType(pt, di_nw, .fromInterned(ip.namespacePtr( + ip.namespacePtr(loaded_union.namespace).parent.unwrap().?, + ).owner_type)); + try dwarf.secOffset(di_nw, try dwarf.getConstDecl(pt, @"const"), 0); + if (loaded_union.name_nav == .none) + try dwarf.strx(di_nw, loaded_union.name.toSlice(ip)); } else if (loaded_union.name_nav.unwrap()) |name_ni| { const name_nav = ip.getNav(name_ni); const decl = zf.zir.?.getDeclaration(name_nav.srcInst(ip).resolve(ip).?); - const parent_ni = try dwarf.getDecl(pt, ip.namespacePtr( + const parent_ni = try dwarf.getConstDecl(pt, ip.namespacePtr( name_nav.analysis.?.namespace, ).owner_type); - try dwarf.abbrevCode(di_nw, if (loaded_union.field_types.len > 0) - switch (loaded_union.layout) { - .auto, .@"extern" => .decl_union, - .@"packed" => .decl_packed_union, - } - else switch (loaded_union.layout) { + try dwarf.abbrevCode(di_nw, if (is_empty) switch (loaded_union.layout) { .auto, .@"extern" => .decl_empty_union, .@"packed" => .decl_empty_packed_union, + } else switch (loaded_union.layout) { + .auto, .@"extern" => .decl_union, + .@"packed" => .decl_packed_union, }); try dwarf.secOffset(di_nw, parent_ni, 0); try di_w.writeInt(u32, decl.src_line + 1, dwarf.endian); try di_w.writeUleb128(decl.src_column + 1); try di_w.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); - try dwarf.strp(&dwarf.debug_str, di_nw, name_nav.name.toSlice(ip)); + try dwarf.strx(di_nw, name_nav.name.toSlice(ip)); } else { const decl = zf.zir.?.getUnionDecl(loaded_union.zir_index.resolve(ip).?); - const parent_ni = try dwarf.getDecl(pt, ip.namespacePtr( + const parent_ni = try dwarf.getConstDecl(pt, ip.namespacePtr( ip.namespacePtr(loaded_union.namespace).parent.unwrap().?, ).owner_type); - try dwarf.abbrevCode(di_nw, if (loaded_union.field_types.len > 0) - switch (loaded_union.layout) { - .auto, .@"extern" => .type_decl_union, - .@"packed" => .type_decl_packed_union, - } - else switch (loaded_union.layout) { + try dwarf.abbrevCode(di_nw, if (is_empty) switch (loaded_union.layout) { .auto, .@"extern" => .type_decl_empty_union, .@"packed" => .type_decl_empty_packed_union, + } else switch (loaded_union.layout) { + .auto, .@"extern" => .type_decl_union, + .@"packed" => .type_decl_packed_union, }); try dwarf.secOffset(di_nw, parent_ni, 0); try di_w.writeInt(u32, decl.src_line + 1, dwarf.endian); try di_w.writeUleb128(decl.src_column + 1); - try dwarf.strp(&dwarf.debug_str, di_nw, loaded_union.name.toSlice(ip)); + try dwarf.strx(di_nw, loaded_union.name.toSlice(ip)); } switch (loaded_union.layout) { .auto, .@"extern" => { @@ -2631,10 +3114,12 @@ fn updateConstInner( try dwarf.genCaptures(pt, di_nw, loaded_union.captures); if (loaded_union.has_runtime_tag) { try dwarf.abbrevCode(di_nw, .tagged_union); - try dwarf.secOffset(di_nw, di_nw.ni, di_w.end + dwarf.secOffsetSize()); + const discr_offset = di_w.end; + try dwarf.secOffsetPlaceholder(di_w); { + try dwarf.secOffsetFinish(di_nw, discr_offset, di_nw.ni, di_w.end); try dwarf.abbrevCode(di_nw, .generated_field); - try dwarf.strp(&dwarf.debug_str, di_nw, "tag"); + try dwarf.strx(di_nw, "tag"); try dwarf.refType(pt, di_nw, .fromInterned(loaded_union.enum_tag_type)); try di_w.writeUleb128(union_layout.tagOffset()); @@ -2643,8 +3128,7 @@ fn updateConstInner( try dwarf.enumConstValue(di_w, loaded_tag, field_index); { try dwarf.abbrevCode(di_nw, .field); - try dwarf.strp( - &dwarf.debug_str, + try dwarf.strx( di_nw, loaded_tag.field_names.get(ip)[field_index].toSlice(ip), ); @@ -2666,8 +3150,7 @@ fn updateConstInner( try di_w.writeUleb128(@backingInt(AbbrevCode.null)); } else for (0..loaded_union.field_types.len) |field_index| { try dwarf.abbrevCode(di_nw, .field); - try dwarf.strp( - &dwarf.debug_str, + try dwarf.strx( di_nw, loaded_tag.field_names.get(ip)[field_index].toSlice(ip), ); @@ -2688,8 +3171,7 @@ fn updateConstInner( try dwarf.refType(pt, di_nw, .fromInterned(loaded_union.packed_backing_int_type)); for (0..loaded_union.field_types.len) |field_index| { try dwarf.abbrevCode(di_nw, .packed_field); - try dwarf.strp( - &dwarf.debug_str, + try dwarf.strx( di_nw, loaded_tag.field_names.get(ip)[field_index].toSlice(ip), ); @@ -2700,83 +3182,86 @@ fn updateConstInner( } }, } - if (loaded_union.captures.len > 0 or loaded_union.field_types.len > 0) - try di_w.writeUleb128(@backingInt(AbbrevCode.null)); + if (!is_empty) try di_w.writeUleb128(@backingInt(AbbrevCode.null)); }, .enum_type => { - const loaded_enum = ip.loadEnumType(val); + const loaded_enum = ip.loadEnumType(@"const"); + const is_empty = loaded_enum.captures.len == 0 and loaded_enum.field_names.len == 0; switch (loaded_enum.owner_union) { .none => { const zfi = loaded_enum.zir_index.unwrap().?.resolveFile(ip); const zf = zcu.fileByIndex(zfi); + const zir = &zf.zir.?; if (loaded_enum.captures.len > 0 or loaded_enum.is_reified) { - try dwarf.abbrevCode(di_nw, if (loaded_enum.captures.len > 0 or - loaded_enum.field_names.len > 0) - .decl_instance_enum - else - .decl_instance_empty_enum); - try dwarf.secOffset(di_nw, try dwarf.getDecl(pt, val), 0); + try dwarf.abbrevCode(di_nw, switch (loaded_enum.name_nav) { + else => if (is_empty) .decl_instance_empty_enum else .decl_instance_enum, + .none => if (is_empty) + .type_decl_instance_empty_enum + else + .type_decl_instance_enum, + }); + try dwarf.refType(pt, di_nw, .fromInterned(ip.namespacePtr( + ip.namespacePtr(loaded_enum.namespace).parent.unwrap().?, + ).owner_type)); + try dwarf.secOffset(di_nw, try dwarf.getConstDecl(pt, @"const"), 0); + if (loaded_enum.name_nav == .none) + try dwarf.strx(di_nw, loaded_enum.name.toSlice(ip)); } else if (loaded_enum.name_nav.unwrap()) |name_ni| { const name_nav = ip.getNav(name_ni); - const decl = zf.zir.?.getDeclaration(name_nav.srcInst(ip).resolve(ip).?); - const parent_ni = try dwarf.getDecl(pt, ip.namespacePtr( + const decl = zir.getDeclaration(name_nav.srcInst(ip).resolve(ip).?); + const parent_ni = try dwarf.getConstDecl(pt, ip.namespacePtr( name_nav.analysis.?.namespace, ).owner_type); try dwarf.abbrevCode( di_nw, - if (loaded_enum.field_names.len > 0) .decl_enum else .decl_empty_enum, + if (is_empty) .decl_empty_enum else .decl_enum, ); try dwarf.secOffset(di_nw, parent_ni, 0); try di_w.writeInt(u32, decl.src_line + 1, dwarf.endian); try di_w.writeUleb128(decl.src_column + 1); try di_w.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); - try dwarf.strp(&dwarf.debug_str, di_nw, name_nav.name.toSlice(ip)); + try dwarf.strx(di_nw, name_nav.name.toSlice(ip)); } else { - const decl = - zf.zir.?.getEnumDecl(loaded_enum.zir_index.unwrap().?.resolve(ip).?); - const parent_ni = try dwarf.getDecl(pt, ip.namespacePtr( + const decl = zir.getEnumDecl(loaded_enum.zir_index.unwrap().?.resolve(ip).?); + const parent_ni = try dwarf.getConstDecl(pt, ip.namespacePtr( ip.namespacePtr(loaded_enum.namespace).parent.unwrap().?, ).owner_type); - try dwarf.abbrevCode(di_nw, if (loaded_enum.field_names.len > 0) - .type_decl_enum - else - .type_decl_empty_enum); + try dwarf.abbrevCode( + di_nw, + if (is_empty) .type_decl_empty_enum else .type_decl_enum, + ); try dwarf.secOffset(di_nw, parent_ni, 0); try di_w.writeInt(u32, decl.src_line + 1, dwarf.endian); try di_w.writeUleb128(decl.src_column + 1); - try dwarf.strp(&dwarf.debug_str, di_nw, loaded_enum.name.toSlice(ip)); + try dwarf.strx(di_nw, loaded_enum.name.toSlice(ip)); } }, else => { - try dwarf.abbrevCode(di_nw, if (loaded_enum.field_names.len > 0) - .generated_enum_type - else - .generated_empty_enum_type); - try dwarf.strp(&dwarf.debug_str, di_nw, loaded_enum.fqn.toSlice(ip)); + try dwarf.abbrevCode( + di_nw, + if (is_empty) .generated_empty_enum_type else .generated_enum_type, + ); + try dwarf.strx(di_nw, loaded_enum.fqn.toSlice(ip)); }, } try dwarf.refType(pt, di_nw, .fromInterned(loaded_enum.int_tag_type)); + try dwarf.genCaptures(pt, di_nw, loaded_enum.captures); for (0..loaded_enum.field_names.len) |field_index| { try dwarf.abbrevCode(di_nw, .enum_field); try dwarf.enumConstValue(di_w, loaded_enum, field_index); - try dwarf.strp( - &dwarf.debug_str, - di_nw, - loaded_enum.field_names.get(ip)[field_index].toSlice(ip), - ); + try dwarf.strx(di_nw, loaded_enum.field_names.get(ip)[field_index].toSlice(ip)); } - if (loaded_enum.captures.len > 0 or loaded_enum.field_names.len > 0) - try di_w.writeUleb128(@backingInt(AbbrevCode.null)); + if (!is_empty) try di_w.writeUleb128(@backingInt(AbbrevCode.null)); }, // no defined size, so lowered the same as incomplete struct types - .opaque_type => return dwarf.updateConstIncompleteInner(pt, di_nw, val), + .opaque_type => return dwarf.updateConstIncompleteInner(pt, di_nw, @"const"), .spirv_type => unreachable, .func_type => |func_type| { - const is_nullary = func_type.param_types.len == 0 and !func_type.is_var_args; - const name = try zcu.gpa.print("{f}", .{Type.fromInterned(val).fmt(pt)}); + const is_empty = func_type.param_types.len == 0 and !func_type.is_var_args; + const name = try zcu.gpa.print("{f}", .{Type.fromInterned(@"const").fmt(pt)}); defer zcu.gpa.free(name); - try dwarf.abbrevCode(di_nw, if (is_nullary) .nullary_func_type else .func_type); - try dwarf.strp(&dwarf.debug_str, di_nw, name); + try dwarf.abbrevCode(di_nw, if (is_empty) .empty_func_type else .func_type); + try dwarf.strx(di_nw, name); const cc: DW.CC = cc: { if (zcu.getTarget().cCallingConvention()) |cc| { if (@as(std.lang.CallingConvention.Tag, cc) == func_type.cc) { @@ -2848,40 +3333,38 @@ fn updateConstInner( }; try di_w.writeByte(@backingInt(cc)); try dwarf.refType(pt, di_nw, .fromInterned(func_type.return_type)); - if (!is_nullary) { - for (0..func_type.param_types.len) |param_index| { - try dwarf.abbrevCode(di_nw, .unnamed_param); - try dwarf.refType(pt, di_nw, .fromInterned( - func_type.param_types.get(ip)[param_index], - )); - } - if (func_type.is_var_args) try dwarf.abbrevCode(di_nw, .is_var_args); - try di_w.writeUleb128(@backingInt(AbbrevCode.null)); + for (0..func_type.param_types.len) |param_index| { + try dwarf.abbrevCode(di_nw, .unnamed_param); + try dwarf.refType(pt, di_nw, .fromInterned( + func_type.param_types.get(ip)[param_index], + )); } + if (func_type.is_var_args) try dwarf.abbrevCode(di_nw, .is_var_args); + if (!is_empty) try di_w.writeUleb128(@backingInt(AbbrevCode.null)); }, .error_set_type => |error_set_type| { - const name = try zcu.gpa.print("{f}", .{Type.fromInterned(val).fmt(pt)}); + const name = try zcu.gpa.print("{f}", .{Type.fromInterned(@"const").fmt(pt)}); defer zcu.gpa.free(name); try dwarf.abbrevCode( di_nw, if (error_set_type.names.len > 0) .generated_enum_type else .generated_empty_enum_type, ); - try dwarf.strp(&dwarf.debug_str, di_nw, name); + try dwarf.strx(di_nw, name); try dwarf.refType(pt, di_nw, try pt.intType(.unsigned, zcu.errorSetBits())); for (0..error_set_type.names.len) |field_index| { const field_name = error_set_type.names.get(ip)[field_index]; try dwarf.abbrevCode(di_nw, .enum_field); try di_w.writeUleb128(DW.FORM.udata); try di_w.writeUleb128(ip.getErrorValueIfExists(field_name).?); - try dwarf.strp(&dwarf.debug_str, di_nw, field_name.toSlice(ip)); + try dwarf.strx(di_nw, field_name.toSlice(ip)); } if (error_set_type.names.len > 0) try di_w.writeUleb128(@backingInt(AbbrevCode.null)); }, .inferred_error_set_type => |func| { - const name = try zcu.gpa.print("{f}", .{Type.fromInterned(val).fmt(pt)}); + const name = try zcu.gpa.print("{f}", .{Type.fromInterned(@"const").fmt(pt)}); defer zcu.gpa.free(name); try dwarf.abbrevCode(di_nw, .inferred_error_set_type); - try dwarf.strp(&dwarf.debug_str, di_nw, name); + try dwarf.strx(di_nw, name); try dwarf.refType(pt, di_nw, switch (ies: { const fi = dwarf.getFuncIfExists(ip.indexToKey(func).func.owner_nav) orelse break :ies .none; @@ -2895,38 +3378,468 @@ fn updateConstInner( }); }, - else => return, + .undef => |ty| { + try dwarf.abbrevCode(di_nw, .undefined_comptime_value); + try dwarf.refType(pt, di_nw, .fromInterned(ty)); + }, + .simple_value => |simple_value| switch (simple_value) { + .void => unreachable, // opv state + .true, .false => unreachable, // runtime bits + .@"unreachable" => unreachable, // not a value + .null => { + // TODO: proper representation for this + try dwarf.abbrevCode(di_nw, .undefined_comptime_value); + try dwarf.refType(pt, di_nw, .null); + }, + }, + .@"extern" => unreachable, .func => |func| { - const fn_ty = ip.indexToKey(func.ty).func_type; + const func_type = ip.indexToKey(func.ty).func_type; const nav = ip.getNav(func.owner_nav); const inst_info = nav.srcInst(ip).resolveFull(ip).?; - const zf = zcu.fileByIndex(inst_info.file); - const decl = zf.zir.?.getDeclaration(inst_info.inst); + const zir = &zcu.fileByIndex(inst_info.file).zir.?; + const decl = zir.getDeclaration(inst_info.inst); + const is_empty = func_type.param_types.len == 0 and !func_type.is_var_args; const parent_ty: Type = .fromInterned(ip.namespacePtr(nav.analysis.?.namespace).owner_type); - try dwarf.abbrevCode(di_nw, .decl_func_generic); - try dwarf.refType(pt, di_nw, parent_ty); - try di_w.writeInt(u32, decl.src_line + 1, dwarf.endian); - try di_w.writeUleb128(decl.src_column + 1); - try di_w.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); - try dwarf.strp(&dwarf.debug_str, di_nw, nav.name.toSlice(ip)); - try dwarf.refType(pt, di_nw, .fromInterned(fn_ty.return_type)); - var param_index: u32 = 0; - for (zf.zir.?.getParamBody(func.zir_body_inst.resolve(ip).?)) |param_inst| { - switch (zf.zir.?.getParamName(param_inst) orelse break) { + if (func.generic_owner != .none or parent_ty.getCaptures(zcu).len > 0) { + try dwarf.abbrevCode( + di_nw, + if (is_empty) .decl_instance_empty_func_generic else .decl_instance_func_generic, + ); + try dwarf.refType(pt, di_nw, parent_ty); + try dwarf.secOffset(di_nw, try dwarf.getConstDecl(pt, @"const"), 0); + } else { + try dwarf.abbrevCode( + di_nw, + if (is_empty) .decl_empty_func_generic else .decl_func_generic, + ); + try dwarf.refType(pt, di_nw, parent_ty); + try di_w.writeInt(u32, decl.src_line + 1, dwarf.endian); + try di_w.writeUleb128(decl.src_column + 1); + try di_w.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); + try dwarf.strx(di_nw, nav.name.toSlice(ip)); + } + try dwarf.refType(pt, di_nw, .fromInterned(func_type.return_type)); + for ( + zir.getParamBody(func.zir_body_inst.resolve(ip).?)[0..func_type.param_types.len], + func_type.param_types.get(&zcu.intern_pool), + ) |param_inst, param_ty| { + switch (zir.getParamName(param_inst).?) { .empty => try dwarf.abbrevCode(di_nw, .unnamed_param), else => |param_name| { try dwarf.abbrevCode(di_nw, .param); - try dwarf.strp(&dwarf.debug_str, di_nw, zf.zir.?.nullTerminatedString( - param_name, - )); + try dwarf.strx(di_nw, zir.nullTerminatedString(param_name)); }, } - try dwarf.refType(pt, di_nw, .fromInterned( - fn_ty.param_types.get(&zcu.intern_pool)[param_index], - )); - param_index += 1; + try dwarf.refType(pt, di_nw, .fromInterned(param_ty)); + } + if (func_type.is_var_args) try dwarf.abbrevCode(di_nw, .is_var_args); + if (!is_empty) try di_w.writeUleb128(@backingInt(AbbrevCode.null)); + }, + .int => |int| { + var big_int_space: Value.BigIntSpace = undefined; + try dwarf.abbrevCode(di_nw, .comptime_value); + try dwarf.refType(pt, di_nw, .fromInterned(int.ty)); + try dwarf.bigIntConstValue( + di_w, + .fromInterned(int.ty), + Value.fromInterned(@"const").toBigInt(&big_int_space, zcu), + ); + }, + .bitpack => |bitpack| { + var big_int_space: Value.BigIntSpace = undefined; + const backing_int_val: Value = .fromInterned(bitpack.backing_int_val); + try dwarf.abbrevCode(di_nw, .comptime_value); + try dwarf.refType(pt, di_nw, .fromInterned(bitpack.ty)); + try dwarf.bigIntConstValue( + di_w, + backing_int_val.typeOf(zcu), + backing_int_val.toBigInt(&big_int_space, zcu), + ); + }, + .err => |err| { + try dwarf.abbrevCode(di_nw, .comptime_value); + try dwarf.refType(pt, di_nw, .fromInterned(err.ty)); + try di_w.writeUleb128(DW.FORM.udata); + try di_w.writeUleb128(try pt.getErrorValue(err.name)); + }, + .error_union => |error_union| { + try dwarf.abbrevCode(di_nw, .aggregate_undefined_comptime_value); + try dwarf.refType(pt, di_nw, .fromInterned(error_union.ty)); + var err_buf: [4]u8 = undefined; + const err_bytes = err_buf[0..@divCeil(zcu.errorSetBits(), 8)]; + const err_val = switch (error_union.val) { + .err_name => |err_name| try pt.getErrorValue(err_name), + .payload => 0, + }; + switch (err_bytes.len) { + else => unreachable, + inline 0...4 => |len| std.mem.writeInt( + @Int(.unsigned, 8 * len), + err_bytes[0..len], + @intCast(err_val), + dwarf.endian, + ), + } + { + try dwarf.abbrevCode(di_nw, .comptime_value_field_runtime); + try dwarf.strx(di_nw, "is_error"); + try di_w.writeUleb128(err_bytes.len); + try di_w.writeAll(err_bytes); + } + payload_field: switch (error_union.val) { + .err_name => {}, + .payload => |payload_val| { + const payload_ty: Type = .fromInterned(ip.typeOf(payload_val)); + const payload_class = payload_ty.classify(zcu); + try dwarf.abbrevCode(di_nw, if (payload_class.comptimeOnly()) + .comptime_value_field_comptime + else if (payload_class.hasRuntimeBits()) + .comptime_value_field_runtime + else + break :payload_field); + try dwarf.strx(di_nw, "value"); + if (payload_class.comptimeOnly()) + try dwarf.refConst(pt, di_nw, .fromInterned(payload_val)) + else if (payload_class.hasRuntimeBits()) + try dwarf.blockConst(pt, di_nw, .fromInterned(payload_val)) + else + unreachable; + }, + } + { + try dwarf.abbrevCode(di_nw, .comptime_value_field_runtime); + try dwarf.strx(di_nw, "error"); + try di_w.writeUleb128(err_bytes.len); + try di_w.writeAll(err_bytes); + } + try di_w.writeUleb128(@backingInt(AbbrevCode.null)); + }, + .enum_literal => |enum_literal| { + try dwarf.abbrevCode(di_nw, .comptime_value); + try dwarf.refType(pt, di_nw, .enum_literal); + try di_w.writeUleb128(DW.FORM.strx); + try dwarf.strx(di_nw, enum_literal.toSlice(ip)); + }, + .enum_tag => |enum_tag| { + var big_int_space: Value.BigIntSpace = undefined; + const int = ip.indexToKey(enum_tag.int).int; + try dwarf.abbrevCode(di_nw, .comptime_value); + try dwarf.refType(pt, di_nw, .fromInterned(enum_tag.ty)); + try dwarf.bigIntConstValue( + di_w, + .fromInterned(int.ty), + Value.fromInterned(@"const").toBigInt(&big_int_space, zcu), + ); + }, + .float => |float| { + try dwarf.abbrevCode(di_nw, .comptime_value); + try dwarf.refType(pt, di_nw, .fromInterned(float.ty)); + switch (float.storage) { + .f16 => |f16_val| { + try di_w.writeUleb128(DW.FORM.data2); + try di_w.writeInt(u16, @bitCast(f16_val), dwarf.endian); + }, + .f32 => |f32_val| { + try di_w.writeUleb128(DW.FORM.data4); + try di_w.writeInt(u32, @bitCast(f32_val), dwarf.endian); + }, + .f64 => |f64_val| { + try di_w.writeUleb128(DW.FORM.data8); + try di_w.writeInt(u64, @bitCast(f64_val), dwarf.endian); + }, + .f80 => |f80_val| { + try di_w.writeUleb128(DW.FORM.block); + try di_w.writeUleb128(@divExact(80, 8)); + try di_w.writeInt(u80, @bitCast(f80_val), dwarf.endian); + }, + .f128 => |f128_val| { + try di_w.writeUleb128(DW.FORM.data16); + try di_w.writeInt(u128, @bitCast(f128_val), dwarf.endian); + }, + } + }, + .ptr => |ptr| { + const Access = union(enum) { + index: u64, + field: InternPool.NullTerminatedString, + synthetic_field: []const u8, + tuple_index: u32, + }; + var zero_bit_accesses: std.ArrayList(Access) = .empty; + defer zero_bit_accesses.deinit(zcu.gpa); + location: { + var base_addr = ptr.base_addr; + var byte_offset = ptr.byte_offset; + const base_ni = while (true) { + const base_ptr, const access: Access = base_ptr_access: switch (base_addr) { + .nav => |ni| break (try dwarf.getGlobal(ni)).get(dwarf).debug_info_ni, + .comptime_alloc, .comptime_field => unreachable, + .uav => |uav| { + const uav_ty: Type = .fromInterned(ip.typeOf(uav.val)); + if (uav_ty.classify(zcu) == .one_possible_value) { + try dwarf.abbrevCode(di_nw, if (zero_bit_accesses.items.len > 0) + .aggregate_comptime_value + else + .comptime_value); + try dwarf.refType(pt, di_nw, .fromInterned(ptr.ty)); + try di_w.writeUleb128(DW.FORM.udata); + try di_w.writeUleb128(ip.indexToKey(uav.orig_ty) + .ptr_type.flags.alignment.toByteUnits() orelse + uav_ty.abiAlignment(zcu).toByteUnits().?); + break :location; + } else break Const.get(try dwarf.getConst(pt, .fromInterned( + uav.val, + )), dwarf).debug_info_ni; + }, + .int => { + try dwarf.abbrevCode(di_nw, if (zero_bit_accesses.items.len > 0) + .aggregate_comptime_value + else + .comptime_value); + try dwarf.refType(pt, di_nw, .fromInterned(ptr.ty)); + try di_w.writeUleb128(DW.FORM.udata); + try di_w.writeUleb128(byte_offset); + break :location; + }, + .eu_payload => |eu_ptr| { + const base_ptr = ip.indexToKey(eu_ptr).ptr; + byte_offset += codegen.errUnionPayloadOffset(.fromInterned(ip.indexToKey( + ip.indexToKey(base_ptr.ty).ptr_type.child, + ).error_union_type.payload_type), zcu); + break :base_ptr_access .{ base_ptr, .{ .synthetic_field = "value" } }; + }, + .opt_payload => |opt_ptr| .{ ip.indexToKey(opt_ptr).ptr, .{ + .synthetic_field = "?", + } }, + .field => |field| { + const base_ptr = ip.indexToKey(field.base).ptr; + const agg_ty: Type = + .fromInterned(ip.indexToKey(base_ptr.ty).ptr_type.child); + break :base_ptr_access .{ + base_ptr, + if (agg_ty.isSlice(zcu)) .{ .synthetic_field = switch (field.index) { + Value.slice_ptr_index => "ptr", + Value.slice_len_index => "len", + else => unreachable, + } } else if (agg_ty.structFieldName( + @intCast(field.index), + zcu, + ).unwrap()) |field_name| + .{ .field = field_name } + else + .{ .tuple_index = @intCast(field.index) }, + }; + }, + .arr_elem => |arr_elem| .{ + ip.indexToKey(arr_elem.base).ptr, + .{ .index = arr_elem.index }, + }, + }; + base_addr = base_ptr.base_addr; + byte_offset += base_ptr.byte_offset; + if (Type.fromInterned( + ip.indexToKey(base_ptr.ty).ptr_type.child, + ).hasRuntimeBits(zcu)) + assert(access != .index) + else + try zero_bit_accesses.append(zcu.gpa, access); + }; + try dwarf.abbrevCode(di_nw, if (zero_bit_accesses.items.len > 0) + .aggregate_location_comptime_value + else + .location_comptime_value); + try dwarf.refType(pt, di_nw, .fromInterned(ptr.ty)); + try dwarf.exprLoc(di_nw, .{ .implicit_pointer = .{ + .node = base_ni.unwrap().?, + .offset = byte_offset, + } }); + } + if (zero_bit_accesses.items.len > 0) { + for (zero_bit_accesses.items) |access| switch (access) { + .index => |index| { + try dwarf.abbrevCode(di_nw, .array_index); + try di_w.writeUleb128(index); + }, + .field => |field| { + try dwarf.abbrevCode(di_nw, .access); + try dwarf.strx(di_nw, field.toSlice(ip)); + }, + .synthetic_field => |field| { + try dwarf.abbrevCode(di_nw, .access); + try dwarf.strx(di_nw, field); + }, + .tuple_index => |index| { + try dwarf.abbrevCode(di_nw, .access); + var field_name_buf: [std.fmt.count("{d}", .{std.math.maxInt(u32)})]u8 = + undefined; + const field_name = std.mem.print(&field_name_buf, "{d}", .{index}) catch + unreachable; + try dwarf.strx(di_nw, field_name); + }, + }; + try di_w.writeUleb128(@backingInt(AbbrevCode.null)); + } + }, + .slice => |slice| { + try dwarf.abbrevCode(di_nw, .aggregate_undefined_comptime_value); + try dwarf.refType(pt, di_nw, .fromInterned(slice.ty)); + { + try dwarf.abbrevCode(di_nw, .comptime_value_field_comptime); + try dwarf.strx(di_nw, "ptr"); + try dwarf.refConst(pt, di_nw, .fromInterned(slice.ptr)); + } + { + try dwarf.abbrevCode(di_nw, .comptime_value_field_runtime); + try dwarf.strx(di_nw, "len"); + try dwarf.blockConst(pt, di_nw, .fromInterned(slice.len)); + } + try di_w.writeUleb128(@backingInt(AbbrevCode.null)); + }, + .opt => |opt| { + const opt_child_ty: Type = .fromInterned(ip.indexToKey(opt.ty).opt_type); + try dwarf.abbrevCode(di_nw, .aggregate_undefined_comptime_value); + try dwarf.refType(pt, di_nw, .fromInterned(opt.ty)); + { + try dwarf.abbrevCode(di_nw, .comptime_value_field_runtime); + try dwarf.strx(di_nw, "has_value"); + switch (optRepr(opt_child_ty, zcu)) { + .opv_null => try di_w.writeUleb128(0), + .unpacked => try dwarf.blockConst(pt, di_nw, .makeBool(opt.val != .none)), + .error_set, .pointer => try dwarf.blockConst(pt, di_nw, .fromInterned(@"const")), + } + } + if (opt.val != .none) child_field: { + const opt_child_class = opt_child_ty.classify(zcu); + try dwarf.abbrevCode(di_nw, if (opt_child_class.comptimeOnly()) + .comptime_value_field_comptime + else if (opt_child_class.hasRuntimeBits()) + .comptime_value_field_runtime + else + break :child_field); + try dwarf.strx(di_nw, "?"); + if (opt_child_class.comptimeOnly()) + try dwarf.refConst(pt, di_nw, .fromInterned(opt.val)) + else if (opt_child_class.hasRuntimeBits()) + try dwarf.blockConst(pt, di_nw, .fromInterned(opt.val)) + else + unreachable; + } + try di_w.writeUleb128(@backingInt(AbbrevCode.null)); + }, + .aggregate => |aggregate| { + try dwarf.abbrevCode(di_nw, .aggregate_undefined_comptime_value); + try dwarf.refType(pt, di_nw, .fromInterned(aggregate.ty)); + switch (ip.indexToKey(aggregate.ty)) { + .struct_type => { + const loaded_struct = ip.loadStructType(aggregate.ty); + assert(loaded_struct.layout == .auto); + for (0..loaded_struct.field_types.len) |field_index| { + if (loaded_struct.field_is_comptime_bits.get(ip, field_index)) continue; + const field_ty: Type = + .fromInterned(loaded_struct.field_types.get(ip)[field_index]); + const field_class = field_ty.classify(zcu); + try dwarf.abbrevCode(di_nw, if (field_class.comptimeOnly()) + .comptime_value_field_comptime + else if (field_class.hasRuntimeBits()) + .comptime_value_field_runtime + else + continue); + try dwarf.strx( + di_nw, + loaded_struct.field_names.get(ip)[field_index].toSlice(ip), + ); + const field_value: Value = .fromInterned(switch (aggregate.storage) { + .bytes => unreachable, + .elems => |elems| elems[field_index], + .repeated_elem => |repeated_elem| repeated_elem, + }); + if (field_class.comptimeOnly()) + try dwarf.refConst(pt, di_nw, field_value) + else if (field_class.hasRuntimeBits()) + try dwarf.blockConst(pt, di_nw, field_value) + else + unreachable; + } + }, + .tuple_type => |tuple_type| for (0..tuple_type.types.len) |field_index| { + if (tuple_type.values.get(ip)[field_index] != .none) continue; + const field_ty: Type = .fromInterned(tuple_type.types.get(ip)[field_index]); + const field_class = field_ty.classify(zcu); + try dwarf.abbrevCode(di_nw, if (field_class.comptimeOnly()) + .comptime_value_field_comptime + else if (field_class.hasRuntimeBits()) + .comptime_value_field_runtime + else + continue); + { + var field_name_buf: [std.fmt.count("{d}", .{std.math.maxInt(u32)})]u8 = + undefined; + const field_name = std.mem.print(&field_name_buf, "{d}", .{field_index}) catch + unreachable; + try dwarf.strx(di_nw, field_name); + } + const field_value: Value = .fromInterned(switch (aggregate.storage) { + .bytes => unreachable, + .elems => |elems| elems[field_index], + .repeated_elem => |repeated_elem| repeated_elem, + }); + if (field_class.comptimeOnly()) + try dwarf.refConst(pt, di_nw, field_value) + else if (field_class.hasRuntimeBits()) + try dwarf.blockConst(pt, di_nw, field_value) + else + unreachable; + }, + inline .array_type, .vector_type => |sequence_type| { + const child_ty: Type = .fromInterned(sequence_type.child); + const child_class = child_ty.classify(zcu); + for (switch (aggregate.storage) { + .bytes => unreachable, + .elems => |elems| elems, + .repeated_elem => |*repeated_elem| repeated_elem[0..1], + }) |elem| { + try dwarf.abbrevCode(di_nw, if (child_class.comptimeOnly()) + .comptime_value_elem_comptime + else if (child_class.hasRuntimeBits()) + .comptime_value_elem_runtime + else + break); + if (child_class.comptimeOnly()) + try dwarf.refConst(pt, di_nw, .fromInterned(elem)) + else if (child_class.hasRuntimeBits()) + try dwarf.blockConst(pt, di_nw, .fromInterned(elem)) + else + unreachable; + } + }, + else => unreachable, + } + try di_w.writeUleb128(@backingInt(AbbrevCode.null)); + }, + .un => |un| { + try dwarf.abbrevCode(di_nw, .aggregate_undefined_comptime_value); + try dwarf.refType(pt, di_nw, .fromInterned(un.ty)); + { + const loaded_union = ip.loadUnionType(un.ty); + assert(loaded_union.layout == .auto); + const field_index = zcu.unionTagFieldIndex(loaded_union, Value.fromInterned(un.tag)).?; + const field_ty: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); + const field_class = field_ty.classify(zcu); + const field_name = + ip.loadEnumType(loaded_union.enum_tag_type).field_names.get(ip)[field_index]; + try dwarf.abbrevCode(di_nw, if (field_class.comptimeOnly()) + .comptime_value_field_comptime + else if (field_class.hasRuntimeBits()) + .comptime_value_field_runtime + else + .access); + try dwarf.strx(di_nw, field_name.toSlice(ip)); + if (field_class.comptimeOnly()) + try dwarf.refConst(pt, di_nw, .fromInterned(un.val)) + else if (field_class.hasRuntimeBits()) + try dwarf.blockConst(pt, di_nw, .fromInterned(un.val)); } - if (fn_ty.is_var_args) try dwarf.abbrevCode(di_nw, .is_var_args); try di_w.writeUleb128(@backingInt(AbbrevCode.null)); }, @@ -2935,11 +3848,11 @@ fn updateConstInner( try dwarf.genDebugInfoPadding(di_w, di_w.unusedCapacityLen()); } -fn optRepr(opt_child_type: Type, zcu: *const Zcu) enum { unpacked, opv_null, error_set, pointer } { - if (opt_child_type.isNoReturn(zcu)) return .opv_null; - return switch (opt_child_type.toIntern()) { +fn optRepr(opt_child_ty: Type, zcu: *const Zcu) enum { unpacked, opv_null, error_set, pointer } { + if (opt_child_ty.isNoReturn(zcu)) return .opv_null; + return switch (opt_child_ty.toIntern()) { .anyerror_type => .error_set, - else => switch (zcu.intern_pool.indexToKey(opt_child_type.toIntern())) { + else => switch (zcu.intern_pool.indexToKey(opt_child_ty.toIntern())) { else => .unpacked, .error_set_type, .inferred_error_set_type => .error_set, .ptr_type => |ptr_type| if (ptr_type.flags.is_allowzero) .unpacked else .pointer, @@ -2983,21 +3896,21 @@ fn updateConstIncompleteInner( _, const fi = try ui.get(dwarf).getFile(zcu.gpa, ui, src_inst.file); try dwarf.abbrevCode(di_nw, .empty_file); try di_w.writeUleb128(@backingInt(fi)); - try dwarf.strp(&dwarf.debug_str, di_nw, loaded_struct.name.toSlice(ip)); + try dwarf.strx(di_nw, loaded_struct.name.toSlice(ip)); try di_w.writeByte(@intFromBool(true)); break :done; }, else => { - const data = - zf.zir.?.instructions.items(.data)[@backingInt(src_inst.inst)].extended; + const zir = &zf.zir.?; + const data = zir.instructions.items(.data)[@backingInt(src_inst.inst)].extended; const src_line, const src_column = src_loc: switch (data.opcode) { else => unreachable, .struct_decl => { - const decl = zf.zir.?.getStructDecl(src_inst.inst); + const decl = zir.getStructDecl(src_inst.inst); break :src_loc .{ decl.src_line, decl.src_column }; }, .reify_struct => { - const decl = zf.zir.?.extraData( + const decl = zir.extraData( std.zig.Zir.Inst.ReifyStruct, data.operand, ).data; @@ -3025,15 +3938,16 @@ fn updateConstIncompleteInner( break :done; }; const zf = zcu.fileByIndex(src_inst.file); - const data = zf.zir.?.instructions.items(.data)[@backingInt(src_inst.inst)].extended; + const zir = &zf.zir.?; + const data = zir.instructions.items(.data)[@backingInt(src_inst.inst)].extended; const src_line, const src_column = src_loc: switch (data.opcode) { else => unreachable, .union_decl => { - const decl = zf.zir.?.getUnionDecl(src_inst.inst); + const decl = zir.getUnionDecl(src_inst.inst); break :src_loc .{ decl.src_line, decl.src_column }; }, .reify_union => { - const decl = zf.zir.?.extraData(std.zig.Zir.Inst.ReifyUnion, data.operand).data; + const decl = zir.extraData(std.zig.Zir.Inst.ReifyUnion, data.operand).data; break :src_loc .{ decl.src_line, decl.src_column }; }, }; @@ -3053,7 +3967,7 @@ fn updateConstIncompleteInner( const loaded_enum = ip.loadEnumType(val); const zir_index = loaded_enum.zir_index.unwrap() orelse { try dwarf.abbrevCode(di_nw, .generated_empty_struct_type); - try dwarf.strp(&dwarf.debug_str, di_nw, loaded_enum.name.toSlice(ip)); + try dwarf.strx(di_nw, loaded_enum.name.toSlice(ip)); try di_w.writeByte(@intFromBool(true)); break :done; }; @@ -3062,15 +3976,16 @@ fn updateConstIncompleteInner( break :done; }; const zf = zcu.fileByIndex(src_inst.file); - const data = zf.zir.?.instructions.items(.data)[@backingInt(src_inst.inst)].extended; + const zir = &zf.zir.?; + const data = zir.instructions.items(.data)[@backingInt(src_inst.inst)].extended; const src_line, const src_column = src_loc: switch (data.opcode) { else => unreachable, .enum_decl => { - const decl = zf.zir.?.getEnumDecl(src_inst.inst); + const decl = zir.getEnumDecl(src_inst.inst); break :src_loc .{ decl.src_line, decl.src_column }; }, .reify_enum => { - const decl = zf.zir.?.extraData(std.zig.Zir.Inst.ReifyEnum, data.operand).data; + const decl = zir.extraData(std.zig.Zir.Inst.ReifyEnum, data.operand).data; break :src_loc .{ decl.src_line, decl.src_column }; }, }; @@ -3112,7 +4027,7 @@ fn updateConstIncompleteInner( const name = try zcu.gpa.print("{f}", .{Type.fromInterned(val).fmt(pt)}); defer zcu.gpa.free(name); try dwarf.abbrevCode(di_nw, .generated_empty_struct_type); - try dwarf.strp(&dwarf.debug_str, di_nw, name); + try dwarf.strx(di_nw, name); try di_w.writeByte(@intFromBool(true)); }, else => |ty| { @@ -3131,13 +4046,15 @@ fn updateConstIncompleteInner( .@"union" => .decl_instance_empty_incomplete_union, .@"enum" => .decl_instance_empty_incomplete_enum, }); - try dwarf.secOffset(di_nw, try dwarf.getDecl(pt, val), 0); + try dwarf.refType(pt, di_nw, .fromInterned(ip.namespacePtr( + ip.namespacePtr(namespace).parent.unwrap().?, + ).owner_type)); + try dwarf.secOffset(di_nw, try dwarf.getConstDecl(pt, val), 0); } else if (maybe_name_nav.unwrap()) |name_ni| { const name_nav = ip.getNav(name_ni); const decl = zf.zir.?.getDeclaration(name_nav.srcInst(ip).resolve(ip).?); - const parent_ni = try dwarf.getDecl(pt, ip.namespacePtr( - name_nav.analysis.?.namespace, - ).owner_type); + const parent_ni = + try dwarf.getConstDecl(pt, ip.namespacePtr(name_nav.analysis.?.namespace).owner_type); try dwarf.abbrevCode(di_nw, if (captures.len > 0) switch (kind) { .@"struct" => .decl_incomplete_struct, .@"union" => .decl_incomplete_union, @@ -3151,9 +4068,9 @@ fn updateConstIncompleteInner( try di_w.writeInt(u32, decl.src_line + 1, dwarf.endian); try di_w.writeUleb128(decl.src_column + 1); try di_w.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); - try dwarf.strp(&dwarf.debug_str, di_nw, name_nav.name.toSlice(ip)); + try dwarf.strx(di_nw, name_nav.name.toSlice(ip)); } else { - const parent_ni = try dwarf.getDecl(pt, ip.namespacePtr( + const parent_ni = try dwarf.getConstDecl(pt, ip.namespacePtr( ip.namespacePtr(namespace).parent.unwrap().?, ).owner_type); try dwarf.abbrevCode(di_nw, if (captures.len > 0) switch (kind) { @@ -3168,7 +4085,7 @@ fn updateConstIncompleteInner( try dwarf.secOffset(di_nw, parent_ni, 0); try di_w.writeInt(u32, src_line + 1, dwarf.endian); try di_w.writeUleb128(src_column + 1); - try dwarf.strp(&dwarf.debug_str, di_nw, name.toSlice(ip)); + try dwarf.strx(di_nw, name.toSlice(ip)); } try dwarf.genCaptures(pt, di_nw, captures); if (captures.len > 0) try di_w.writeByte(@backingInt(AbbrevCode.null)); @@ -3224,10 +4141,16 @@ pub fn genDecl( dwarf: *Dwarf, pt: Zcu.PerThread, di_nw: *link.MappedFile.Node.Writer, - instance_val: InternPool.Index, + instance: Decl.Instance, ) link.Error!void { - log.debug("genDecl({f})", .{Value.fromInterned(instance_val).fmtValue(pt)}); - dwarf.genDeclInner(pt, di_nw, instance_val) catch |err| switch (err) { + switch (instance) { + .none => unreachable, + .@"const" => |@"const"| log.debug("genDecl({f})", .{Value.fromInterned(@"const").fmtValue(pt)}), + .global => |global| log.debug("genDecl({f})", .{ + pt.zcu.intern_pool.getNav(global).fqn.fmt(&pt.zcu.intern_pool), + }), + } + dwarf.genDeclInner(pt, di_nw, instance) catch |err| switch (err) { else => |e| return e, error.WriteFailed => return dwarf.reportWriteError(di_nw), }; @@ -3236,216 +4159,255 @@ fn genDeclInner( dwarf: *Dwarf, pt: Zcu.PerThread, di_nw: *link.MappedFile.Node.Writer, - instance_val: InternPool.Index, + instance: Decl.Instance, ) link.EmitError!void { const zcu = pt.zcu; const ip = &zcu.intern_pool; const di_w = &di_nw.interface; - done: { - const kind: enum { @"struct", @"union", @"enum" }, const zf, const src_line, const src_column, const capture_names, const captures, const name, const maybe_name_nav, const namespace = container: switch (ip.indexToKey(instance_val)) { - else => unreachable, - .struct_type => { - const loaded_struct = ip.loadStructType(instance_val); - const src_inst = loaded_struct.zir_index.resolveFull(ip) orelse { - try dwarf.lostTracking(di_nw); - break :done; - }; - const zf = zcu.fileByIndex(src_inst.file); - const inst = zf.zir.?.instructions.get(@backingInt(src_inst.inst)); - const src_line, const src_column, const capture_names = decl: switch (inst.tag) { - else => unreachable, - .struct_init, .struct_init_ref => { - const decl = zf.zir.?.extraData( - std.zig.Zir.Inst.StructInit, - inst.data.pl_node.payload_index, - ).data; - break :decl .{ decl.src_line, decl.src_column, &.{} }; - }, - .struct_init_anon => { - const decl = zf.zir.?.extraData( - std.zig.Zir.Inst.StructInitAnon, - inst.data.pl_node.payload_index, - ).data; - break :decl .{ decl.src_line, decl.src_column, &.{} }; - }, - .extended => switch (inst.data.extended.opcode) { + done: switch (instance) { + .none => unreachable, + .@"const" => |@"const"| { + const kind: enum { @"struct", @"union", @"enum" }, const zf, const src_line, const src_column, const capture_names, const captures, const maybe_name_nav, const namespace = container: switch (ip.indexToKey(instance.@"const")) { + else => unreachable, + .struct_type => { + const loaded_struct = ip.loadStructType(@"const"); + const src_inst = loaded_struct.zir_index.resolveFull(ip) orelse { + try dwarf.lostTracking(di_nw); + break :done; + }; + const zf = zcu.fileByIndex(src_inst.file); + const zir = &zf.zir.?; + const inst = zir.instructions.get(@backingInt(src_inst.inst)); + const src_line, const src_column, const capture_names = decl: switch (inst.tag) { else => unreachable, - .struct_decl => { - const decl = zf.zir.?.getStructDecl(src_inst.inst); - break :decl .{ decl.src_line, decl.src_column, decl.capture_names }; - }, - .reify_struct => { - const decl = zf.zir.?.extraData( - std.zig.Zir.Inst.ReifyStruct, - inst.data.extended.operand, + .struct_init, .struct_init_ref => { + const decl = zir.extraData( + std.zig.Zir.Inst.StructInit, + inst.data.pl_node.payload_index, ).data; break :decl .{ decl.src_line, decl.src_column, &.{} }; }, - }, - }; - break :container .{ - .@"struct", - zf, - src_line, - src_column, - capture_names, - loaded_struct.captures, - loaded_struct.name, - loaded_struct.name_nav, - loaded_struct.namespace, - }; - }, - .union_type => { - const loaded_union = ip.loadUnionType(instance_val); - const src_inst = loaded_union.zir_index.resolveFull(ip) orelse { - try dwarf.lostTracking(di_nw); - break :done; - }; - const zf = zcu.fileByIndex(src_inst.file); - const inst = zf.zir.?.instructions.get(@backingInt(src_inst.inst)); - const src_line, const src_column, const capture_names = decl: switch (inst.tag) { - else => unreachable, - .extended => switch (inst.data.extended.opcode) { - else => unreachable, - .union_decl => { - const decl = zf.zir.?.getUnionDecl(src_inst.inst); - break :decl .{ decl.src_line, decl.src_column, decl.capture_names }; - }, - .reify_union => { - const decl = zf.zir.?.extraData( - std.zig.Zir.Inst.ReifyUnion, - inst.data.extended.operand, + .struct_init_anon => { + const decl = zir.extraData( + std.zig.Zir.Inst.StructInitAnon, + inst.data.pl_node.payload_index, ).data; break :decl .{ decl.src_line, decl.src_column, &.{} }; }, - }, - }; - break :container .{ - .@"union", - zf, - src_line, - src_column, - capture_names, - loaded_union.captures, - loaded_union.name, - loaded_union.name_nav, - loaded_union.namespace, - }; - }, - .enum_type => { - const loaded_enum = ip.loadEnumType(instance_val); - const src_inst = loaded_enum.zir_index.unwrap().?.resolveFull(ip) orelse { - try dwarf.lostTracking(di_nw); - break :done; - }; - const zf = zcu.fileByIndex(src_inst.file); - const inst = zf.zir.?.instructions.get(@backingInt(src_inst.inst)); - const src_line, const src_column, const capture_names = decl: switch (inst.tag) { - else => unreachable, - .extended => switch (inst.data.extended.opcode) { + .extended => switch (inst.data.extended.opcode) { + else => unreachable, + .struct_decl => { + const decl = zir.getStructDecl(src_inst.inst); + break :decl .{ decl.src_line, decl.src_column, decl.capture_names }; + }, + .reify_struct => { + const decl = zir.extraData( + std.zig.Zir.Inst.ReifyStruct, + inst.data.extended.operand, + ).data; + break :decl .{ decl.src_line, decl.src_column, &.{} }; + }, + }, + }; + break :container .{ + .@"struct", + zf, + src_line, + src_column, + capture_names, + loaded_struct.captures, + loaded_struct.name_nav, + loaded_struct.namespace, + }; + }, + .union_type => { + const loaded_union = ip.loadUnionType(@"const"); + const src_inst = loaded_union.zir_index.resolveFull(ip) orelse { + try dwarf.lostTracking(di_nw); + break :done; + }; + const zf = zcu.fileByIndex(src_inst.file); + const zir = &zf.zir.?; + const inst = zir.instructions.get(@backingInt(src_inst.inst)); + const src_line, const src_column, const capture_names = decl: switch (inst.tag) { else => unreachable, - .enum_decl => { - const decl = zf.zir.?.getEnumDecl(src_inst.inst); - break :decl .{ decl.src_line, decl.src_column, decl.capture_names }; + .extended => switch (inst.data.extended.opcode) { + else => unreachable, + .union_decl => { + const decl = zir.getUnionDecl(src_inst.inst); + break :decl .{ decl.src_line, decl.src_column, decl.capture_names }; + }, + .reify_union => { + const decl = zir.extraData( + std.zig.Zir.Inst.ReifyUnion, + inst.data.extended.operand, + ).data; + break :decl .{ decl.src_line, decl.src_column, &.{} }; + }, }, - .reify_enum => { - const decl = zf.zir.?.extraData( - std.zig.Zir.Inst.ReifyEnum, - inst.data.extended.operand, - ).data; - break :decl .{ decl.src_line, decl.src_column, &.{} }; + }; + break :container .{ + .@"union", + zf, + src_line, + src_column, + capture_names, + loaded_union.captures, + loaded_union.name_nav, + loaded_union.namespace, + }; + }, + .enum_type => { + const loaded_enum = ip.loadEnumType(@"const"); + const src_inst = loaded_enum.zir_index.unwrap().?.resolveFull(ip) orelse { + try dwarf.lostTracking(di_nw); + break :done; + }; + const zf = zcu.fileByIndex(src_inst.file); + const zir = &zf.zir.?; + const inst = zir.instructions.get(@backingInt(src_inst.inst)); + const src_line, const src_column, const capture_names = decl: switch (inst.tag) { + else => unreachable, + .extended => switch (inst.data.extended.opcode) { + else => unreachable, + .enum_decl => { + const decl = zir.getEnumDecl(src_inst.inst); + break :decl .{ decl.src_line, decl.src_column, decl.capture_names }; + }, + .reify_enum => { + const decl = zir.extraData( + std.zig.Zir.Inst.ReifyEnum, + inst.data.extended.operand, + ).data; + break :decl .{ decl.src_line, decl.src_column, &.{} }; + }, }, - }, - }; - break :container .{ - .@"enum", - zf, - src_line, - src_column, - capture_names, - loaded_enum.captures, - loaded_enum.name, - loaded_enum.name_nav, - loaded_enum.namespace, - }; - }, - .opaque_type => { - const loaded_opaque = ip.loadOpaqueType(instance_val); - const src_inst = loaded_opaque.zir_index.resolveFull(ip) orelse { - try dwarf.lostTracking(di_nw); + }; + break :container .{ + .@"enum", + zf, + src_line, + src_column, + capture_names, + loaded_enum.captures, + loaded_enum.name_nav, + loaded_enum.namespace, + }; + }, + .opaque_type => { + const loaded_opaque = ip.loadOpaqueType(@"const"); + const src_inst = loaded_opaque.zir_index.resolveFull(ip) orelse { + try dwarf.lostTracking(di_nw); + break :done; + }; + const zf = zcu.fileByIndex(src_inst.file); + const decl = zf.zir.?.getOpaqueDecl(src_inst.inst); + break :container .{ + .@"struct", + zf, + decl.src_line, + decl.src_column, + decl.capture_names, + loaded_opaque.captures, + loaded_opaque.name_nav, + loaded_opaque.namespace, + }; + }, + .func => |func| { + const owner_nav = ip.getNav(switch (func.generic_owner) { + else => |generic_owner| zcu.funcInfo(generic_owner).owner_nav, + .none => func.owner_nav, + }); + const inst_info = owner_nav.srcInst(ip).resolveFull(ip).?; + const decl = zcu.fileByIndex(inst_info.file).zir.?.getDeclaration(inst_info.inst); + const parent_ni = try dwarf.getConstDecl(pt, ip.namespacePtr( + owner_nav.analysis.?.namespace, + ).owner_type); + try dwarf.abbrevCode(di_nw, .decl_specification_func); + try dwarf.secOffset(di_nw, parent_ni, 0); + try di_w.writeInt(u32, decl.src_line + 1, dwarf.endian); + try di_w.writeUleb128(decl.src_column + 1); + try di_w.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); + try dwarf.strx(di_nw, owner_nav.name.toSlice(ip)); break :done; - }; - const zf = zcu.fileByIndex(src_inst.file); - const decl = zf.zir.?.getOpaqueDecl(src_inst.inst); - break :container .{ - .@"struct", - zf, - decl.src_line, - decl.src_column, - decl.capture_names, - loaded_opaque.captures, - loaded_opaque.name, - loaded_opaque.name_nav, - loaded_opaque.namespace, - }; - }, - }; - if (maybe_name_nav.unwrap()) |name_ni| { - const name_nav = ip.getNav(name_ni); - const decl = zf.zir.?.getDeclaration(name_nav.srcInst(ip).resolve(ip).?); - const parent_ni = try dwarf.getDecl(pt, ip.namespacePtr( - name_nav.analysis.?.namespace, + }, + }; + const zir = &zf.zir.?; + if (maybe_name_nav.unwrap()) |name_ni| { + const name_nav = ip.getNav(name_ni); + const decl = zir.getDeclaration(name_nav.srcInst(ip).resolve(ip).?); + const parent_ni = try dwarf.getConstDecl(pt, ip.namespacePtr( + name_nav.analysis.?.namespace, + ).owner_type); + try dwarf.abbrevCode(di_nw, if (captures.len > 0) switch (kind) { + .@"struct" => .decl_specification_struct, + .@"union" => .decl_specification_union, + .@"enum" => .decl_specification_enum, + } else switch (kind) { + .@"struct" => .decl_specification_empty_struct, + .@"union" => .decl_specification_empty_union, + .@"enum" => .decl_specification_empty_enum, + }); + try dwarf.secOffset(di_nw, parent_ni, 0); + try di_w.writeInt(u32, decl.src_line + 1, dwarf.endian); + try di_w.writeUleb128(decl.src_column + 1); + try di_w.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); + try dwarf.strx(di_nw, name_nav.name.toSlice(ip)); + } else { + const parent_ni = try dwarf.getConstDecl(pt, ip.namespacePtr( + ip.namespacePtr(namespace).parent.unwrap().?, + ).owner_type); + try dwarf.abbrevCode(di_nw, if (captures.len > 0) switch (kind) { + .@"struct" => .type_decl_specification_struct, + .@"union" => .type_decl_specification_union, + .@"enum" => .type_decl_specification_enum, + } else switch (kind) { + .@"struct" => .type_decl_specification_empty_struct, + .@"union" => .type_decl_specification_empty_union, + .@"enum" => .type_decl_specification_empty_enum, + }); + try dwarf.secOffset(di_nw, parent_ni, 0); + try di_w.writeInt(u32, src_line + 1, dwarf.endian); + try di_w.writeUleb128(src_column + 1); + } + for (capture_names, captures.get(ip)) |capture_name, capture| { + try dwarf.abbrevCode(di_nw, .capture_specification); + switch (capture.unwrap()) { + .@"comptime", + .runtime, + .nav_val, + => try dwarf.strx(di_nw, zir.nullTerminatedString(capture_name)), + .nav_ref => { + const capture_name_slice = + try zcu.gpa.print("&{s}", .{zir.nullTerminatedString(capture_name)}); + defer zcu.gpa.free(capture_name_slice); + try dwarf.strx(di_nw, capture_name_slice); + }, + } + } + if (captures.len > 0) try di_w.writeUleb128(@backingInt(AbbrevCode.null)); + }, + .global => |global| { + const nav = ip.getNav(global); + const nav_const, const nav_ty = nav_resolved: { + const nav_resolved = nav.resolved.?; + break :nav_resolved .{ nav_resolved.@"const", nav_resolved.type }; + }; + const src_inst = nav.srcInst(ip).resolveFull(ip).?; + const decl = zcu.fileByIndex(src_inst.file).zir.?.getDeclaration(src_inst.inst); + const parent_ni = try dwarf.getConstDecl(pt, ip.namespacePtr( + nav.analysis.?.namespace, ).owner_type); - try dwarf.abbrevCode(di_nw, if (captures.len > 0) switch (kind) { - .@"struct" => .decl_specification_struct, - .@"union" => .decl_specification_union, - .@"enum" => .decl_specification_enum, - } else switch (kind) { - .@"struct" => .decl_specification_empty_struct, - .@"union" => .decl_specification_empty_union, - .@"enum" => .decl_specification_empty_enum, + try dwarf.abbrevCode(di_nw, switch (nav_ty) { + .type_type => .decl_specification_type, + else => if (nav_const) .decl_specification_const else .decl_specification_var, }); try dwarf.secOffset(di_nw, parent_ni, 0); try di_w.writeInt(u32, decl.src_line + 1, dwarf.endian); try di_w.writeUleb128(decl.src_column + 1); try di_w.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); - try dwarf.strp(&dwarf.debug_str, di_nw, name.toSlice(ip)); - } else { - const parent_ni = try dwarf.getDecl(pt, ip.namespacePtr( - ip.namespacePtr(namespace).parent.unwrap().?, - ).owner_type); - try dwarf.abbrevCode(di_nw, if (captures.len > 0) switch (kind) { - .@"struct" => .type_decl_specification_struct, - .@"union" => .type_decl_specification_union, - .@"enum" => .type_decl_specification_enum, - } else switch (kind) { - .@"struct" => .type_decl_specification_empty_struct, - .@"union" => .type_decl_specification_empty_union, - .@"enum" => .type_decl_specification_empty_enum, - }); - try dwarf.secOffset(di_nw, parent_ni, 0); - try di_w.writeInt(u32, src_line + 1, dwarf.endian); - try di_w.writeUleb128(src_column + 1); - try dwarf.strp(&dwarf.debug_str, di_nw, name.toSlice(ip)); - } - for (capture_names, captures.get(ip)) |capture_name, capture| { - try dwarf.abbrevCode(di_nw, .capture_specification); - switch (capture.unwrap()) { - .@"comptime", .runtime, .nav_val => try dwarf.strp( - &dwarf.debug_str, - di_nw, - zf.zir.?.nullTerminatedString(capture_name), - ), - .nav_ref => { - const capture_name_slice = try zcu.gpa.print("&{s}", .{ - zf.zir.?.nullTerminatedString(capture_name), - }); - defer zcu.gpa.free(capture_name_slice); - try dwarf.strp(&dwarf.debug_str, di_nw, capture_name_slice); - }, - } - } - if (captures.len > 0) try di_w.writeUleb128(@backingInt(AbbrevCode.null)); + try dwarf.strx(di_nw, nav.name.toSlice(ip)); + }, } try dwarf.genDebugInfoPadding(di_w, di_w.unusedCapacityLen()); } @@ -3458,9 +4420,12 @@ pub fn updateLineNumber( ) void { const di = dwarf.getDeclIfExists(inst) orelse return; const decl_ni = di.get(dwarf).debug_info_ni.unwrap().?; + comptime assert(AbbrevCode.common_decl_attrs[0][1] == .ref_addr); + comptime assert(AbbrevCode.common_decl_attrs[1][0] == .decl_line); + comptime assert(AbbrevCode.common_decl_attrs[1][1] == .data4); std.mem.writeInt( u32, - decl_ni.slice(mf)[AbbrevCode.decl_size..][0..4], + decl_ni.slice(mf)[AbbrevCode.decl_size + dwarf.secOffsetSize() ..][0..4], line + 1, dwarf.endian, ); @@ -3486,8 +4451,11 @@ fn refAbbrevCode( @branchHint(.likely); return backing_int; } + const gpa = dwarf.lf.comp.gpa; + const debug_abbrev_ni = dwarf.debug_abbrev.ni.unwrap().?; + try debug_abbrev_ni.moved(gpa, mf); var da_nw: link.MappedFile.Node.Writer = undefined; - dwarf.debug_abbrev.ni.unwrap().?.writer(dwarf.lf.comp.gpa, mf, &da_nw); + debug_abbrev_ni.writer(gpa, mf, &da_nw); defer da_nw.deinit(); dwarf.genDebugAbbrev(&da_nw, abbrev_code) catch |err| switch (err) { else => |e| return e, @@ -3526,15 +4494,12 @@ fn genDebugAbbrev( dwarf.debug_abbrev.end = da_w.end; } -pub fn secOffsetSize(dwarf: *Dwarf) usize { +fn secOffsetSize(dwarf: *Dwarf) usize { return switch (dwarf.format) { .@"32" => 4, .@"64" => 8, }; } -fn secOffsetPlaceholder(dwarf: *Dwarf, w: *std.Io.Writer) std.Io.Writer.Error!void { - @memset(try w.writableSlice(dwarf.secOffsetSize()), undefined); -} fn secOffset( dwarf: *Dwarf, nw: *link.MappedFile.Node.Writer, @@ -3543,6 +4508,18 @@ fn secOffset( ) link.EmitError!void { const offset = nw.interface.end; try dwarf.secOffsetPlaceholder(&nw.interface); + try dwarf.secOffsetFinish(nw, offset, target_ni, addend); +} +fn secOffsetPlaceholder(dwarf: *Dwarf, w: *std.Io.Writer) std.Io.Writer.Error!void { + @memset(try w.writableSlice(dwarf.secOffsetSize()), undefined); +} +fn secOffsetFinish( + dwarf: *Dwarf, + nw: *link.MappedFile.Node.Writer, + offset: usize, + target_ni: link.MappedFile.Node.Index, + addend: usize, +) link.Error!void { if (dwarf.lf.cast(.elf2)) |elf| try elf.addNodeReloc( nw.ni, offset, @@ -3574,6 +4551,21 @@ fn addrSym( .absAddr(elf), ) else unreachable; } +fn addrxSym(dwarf: *Dwarf, w: *std.Io.Writer, si: link.File.SymbolId) link.EmitError!void { + try w.writeUleb128(try dwarf.debug_addr.get(dwarf.lf.comp.gpa, si)); +} +fn addrx1Sym(dwarf: *Dwarf, w: *std.Io.Writer, si: link.File.SymbolId) link.EmitError!void { + try w.writeByte(@intCast(try dwarf.debug_addr.get(dwarf.lf.comp.gpa, si))); +} +fn addrx2Sym(dwarf: *Dwarf, w: *std.Io.Writer, si: link.File.SymbolId) link.EmitError!void { + try w.writeInt(u16, @intCast(try dwarf.debug_addr.get(dwarf.lf.comp.gpa, si)), dwarf.endian); +} +fn addrx3Sym(dwarf: *Dwarf, w: *std.Io.Writer, si: link.File.SymbolId) link.EmitError!void { + try w.writeInt(u24, @intCast(try dwarf.debug_addr.get(dwarf.lf.comp.gpa, si)), dwarf.endian); +} +fn addrx4Sym(dwarf: *Dwarf, w: *std.Io.Writer, si: link.File.SymbolId) link.EmitError!void { + try w.writeInt(u32, @intCast(try dwarf.debug_addr.get(dwarf.lf.comp.gpa, si)), dwarf.endian); +} fn blockConst( dwarf: *Dwarf, @@ -3585,13 +4577,9 @@ fn blockConst( const size = ty.abiSize(pt.zcu); try nw.interface.writeUleb128(size); const start = nw.interface.end; - if (size > 0) try codegen.generateSymbol( - dwarf.lf, - pt, - val, - &nw.interface, - .{ .atom_index = @bitCast(nw.ni) }, - ); + if (size > 0) try codegen.generateSymbol(dwarf.lf, pt, val, &nw.interface, .{ + .atom_index = @bitCast(nw.ni), + }); assert(start + size == nw.interface.end); } @@ -3691,13 +4679,37 @@ fn exprLoc(dwarf: *Dwarf, nw: *link.MappedFile.Node.Writer, loc: Loc) link.EmitE fn strp(dwarf: *Dwarf, s: *Str, nw: *link.MappedFile.Node.Writer, str: []const u8) link.EmitError!void { const comp = dwarf.lf.comp; try dwarf.secOffset(nw, s.ni.unwrap().?, s.get(comp.gpa, nw.mf, str) catch |err| switch (err) { + else => |e| return e, error.MappedFileIo => return comp.link_diags.fail("failed to write output file: {t}", .{ nw.mf.io_err.?, }), - else => |e| return e, }); } +fn strx(dwarf: *Dwarf, nw: *link.MappedFile.Node.Writer, str: []const u8) link.EmitError!void { + try nw.interface.writeUleb128(try dwarf.debug_str_offsets.get(dwarf, &dwarf.debug_str, nw.mf, str)); +} +fn strx1(dwarf: *Dwarf, nw: *link.MappedFile.Node.Writer, str: []const u8) link.EmitError!void { + try nw.interface.writeByte(@intCast( + try dwarf.debug_str_offsets.get(dwarf, &dwarf.debug_str, nw.mf, str), + )); +} +fn strx2(dwarf: *Dwarf, nw: *link.MappedFile.Node.Writer, str: []const u8) link.EmitError!void { + try nw.interface.writeInt(u16, @intCast( + try dwarf.debug_str_offsets.get(dwarf, &dwarf.debug_str, nw.mf, str), + ), dwarf.endian); +} +fn strx3(dwarf: *Dwarf, nw: *link.MappedFile.Node.Writer, str: []const u8) link.EmitError!void { + try nw.interface.writeInt(u24, @intCast( + try dwarf.debug_str_offsets.get(dwarf, &dwarf.debug_str, nw.mf, str), + ), dwarf.endian); +} +fn strx4(dwarf: *Dwarf, nw: *link.MappedFile.Node.Writer, str: []const u8) link.EmitError!void { + try nw.interface.writeInt(u32, @intCast( + try dwarf.debug_str_offsets.get(dwarf, &dwarf.debug_str, nw.mf, str), + ), dwarf.endian); +} + fn reportWriteError(dwarf: *Dwarf, nw: *const link.MappedFile.Node.Writer) link.Error { switch (nw.err.?) { else => |e| return e, @@ -3744,7 +4756,6 @@ pub const AbbrevCode = enum { pad_n, // decl, specification, and instance codes are assumed to all have the same uleb128 size decl_lost, - decl_alias, decl_empty_incomplete_enum, decl_incomplete_enum, decl_empty_enum, @@ -3777,16 +4788,17 @@ pub const AbbrevCode = enum { decl_packed_union, type_decl_empty_packed_union, type_decl_packed_union, - decl_var, + decl_type, decl_const, - decl_const_runtime_bits, - decl_const_comptime_state, - decl_const_runtime_bits_comptime_state, - decl_nullary_func, + decl_const_fully_runtime, + decl_const_partially_comptime, + decl_const_fully_comptime, + decl_var, + decl_empty_func, decl_func, - decl_nullary_func_generic, + decl_empty_func_generic, decl_func_generic, - decl_extern_nullary_func, + decl_extern_empty_func, decl_extern_func, decl_specification_empty_struct, decl_specification_struct, @@ -3800,40 +4812,48 @@ pub const AbbrevCode = enum { decl_specification_union, type_decl_specification_empty_union, type_decl_specification_union, + decl_specification_type, + decl_specification_const, + decl_specification_var, decl_specification_func, - decl_instance_alias, decl_instance_empty_incomplete_enum, decl_instance_incomplete_enum, decl_instance_empty_enum, decl_instance_enum, + type_decl_instance_empty_enum, + type_decl_instance_enum, decl_instance_empty_incomplete_struct, decl_instance_incomplete_struct, decl_instance_empty_struct, decl_instance_struct, + type_decl_instance_empty_struct, + type_decl_instance_struct, decl_instance_empty_packed_struct, decl_instance_packed_struct, + type_decl_instance_empty_packed_struct, + type_decl_instance_packed_struct, decl_instance_empty_incomplete_union, decl_instance_incomplete_union, decl_instance_empty_union, decl_instance_union, + type_decl_instance_empty_union, + type_decl_instance_union, decl_instance_empty_packed_union, decl_instance_packed_union, - decl_instance_var, + type_decl_instance_empty_packed_union, + type_decl_instance_packed_union, + decl_instance_type, decl_instance_const, - decl_instance_const_runtime_bits, - decl_instance_const_comptime_state, - decl_instance_const_runtime_bits_comptime_state, - decl_instance_nullary_func, + decl_instance_const_fully_runtime, + decl_instance_const_partially_comptime, + decl_instance_const_fully_comptime, + decl_instance_var, + decl_instance_empty_func, decl_instance_func, - decl_instance_nullary_func_generic, + decl_instance_empty_func_generic, decl_instance_func_generic, - decl_instance_extern_nullary_func, - decl_instance_extern_func, // the rest are unrestricted other than empty variants must not be longer // than the non-empty variant, and so should appear first - compile_unit, - module, - module_dependency, empty_file, file, access, @@ -3856,8 +4876,7 @@ pub const AbbrevCode = enum { inferred_error_set_type, ptr_type, ptr_sentinel_type, - ptr_aligned_type, - ptr_aligned_sentinel_type, + is_aligned, is_const, is_volatile, array_type, @@ -3865,7 +4884,7 @@ pub const AbbrevCode = enum { vector_type, array_index, array_len, - nullary_func_type, + empty_func_type, func_type, param, unnamed_param, @@ -3882,7 +4901,7 @@ pub const AbbrevCode = enum { comptime_capture_fully_comptime, runtime_capture, nav_capture, - builtin_extern_nullary_func, + builtin_extern_empty_func, builtin_extern_func, builtin_extern_var, empty_block, @@ -3911,44 +4930,51 @@ pub const AbbrevCode = enum { aggregate_undefined_comptime_value, aggregate_comptime_value, aggregate_location_comptime_value, - comptime_value_field_runtime_bits, - comptime_value_field_comptime_state, - comptime_value_elem_runtime_bits, - comptime_value_elem_comptime_state, + comptime_value_field_runtime, + comptime_value_field_comptime, + comptime_value_elem_runtime, + comptime_value_elem_comptime, + // low-frequency should appear last + compile_unit, + module, + module_dependency, - const decl_size = uleb128Size(@backingInt(AbbrevCode.decl_instance_extern_func)); + const decl_size = uleb128Size(@backingInt(AbbrevCode.decl_func_generic)); comptime { assert(uleb128Size(@backingInt(AbbrevCode.pad_1)) == 1); assert(uleb128Size(@backingInt(AbbrevCode.pad_n)) == 1); - assert(uleb128Size(@backingInt(AbbrevCode.decl_alias)) == decl_size); + assert(uleb128Size(@backingInt(AbbrevCode.decl_lost)) == decl_size); } const Attr = struct { DeclValEnum(DW.AT), DeclValEnum(DW.FORM), }; - const decl_attrs = &[_]Attr{ + const common_decl_attrs = &[_]Attr{ .{ .ZIG_parent, .ref_addr }, .{ .decl_line, .data4 }, .{ .decl_column, .udata }, + }; + const decl_attrs = common_decl_attrs ++ .{ .{ .accessibility, .data1 }, - .{ .name, .strp }, + .{ .name, .strx }, }; - const type_decl_attrs = &[_]Attr{ - .{ .ZIG_parent, .ref_addr }, - .{ .decl_line, .data4 }, - .{ .decl_column, .udata }, - .{ .name, .strp }, + const type_decl_attrs = common_decl_attrs ++ .{ + .{ .name, .strx }, }; const decl_specification_attrs = decl_attrs ++ &[_]Attr{ .{ .declaration, .flag_present }, }; - const type_decl_specification_attrs = type_decl_attrs ++ &[_]Attr{ + const type_decl_specification_attrs = common_decl_attrs ++ &[_]Attr{ .{ .declaration, .flag_present }, }; const decl_instance_attrs = &[_]Attr{ + .{ .ZIG_parent, .ref_addr }, .{ .specification, .ref_addr }, }; + const type_decl_instance_attrs = decl_instance_attrs ++ .{ + .{ .name, .strx }, + }; const abbrevs = std.EnumArray(AbbrevCode, struct { tag: DeclValEnum(DW.TAG), @@ -3968,12 +4994,6 @@ pub const AbbrevCode = enum { .decl_lost = .{ .tag = .ZIG_lost_declaration, }, - .decl_alias = .{ - .tag = .imported_declaration, - .attrs = decl_attrs ++ .{ - .{ .import, .ref_addr }, - }, - }, .decl_empty_incomplete_enum = .{ .tag = .enumeration_type, .attrs = decl_attrs, @@ -4166,62 +5186,68 @@ pub const AbbrevCode = enum { .{ .type, .ref_addr }, }, }, - .decl_var = .{ - .tag = .variable, + .decl_type = .{ + .tag = .imported_declaration, .attrs = decl_attrs ++ .{ - .{ .linkage_name, .strp }, - .{ .type, .ref_addr }, - .{ .location, .exprloc }, - .{ .alignment, .udata }, - .{ .external, .flag }, + .{ .import, .ref_addr }, }, }, .decl_const = .{ .tag = .constant, .attrs = decl_attrs ++ .{ - .{ .linkage_name, .strp }, + .{ .linkage_name, .strx }, .{ .type, .ref_addr }, .{ .alignment, .udata }, .{ .external, .flag }, }, }, - .decl_const_runtime_bits = .{ + .decl_const_fully_runtime = .{ .tag = .constant, .attrs = decl_attrs ++ .{ - .{ .linkage_name, .strp }, + .{ .linkage_name, .strx }, .{ .type, .ref_addr }, .{ .alignment, .udata }, .{ .external, .flag }, .{ .const_value, .block }, }, }, - .decl_const_comptime_state = .{ + .decl_const_partially_comptime = .{ .tag = .constant, .attrs = decl_attrs ++ .{ - .{ .linkage_name, .strp }, + .{ .linkage_name, .strx }, .{ .type, .ref_addr }, .{ .alignment, .udata }, .{ .external, .flag }, + .{ .const_value, .block }, .{ .ZIG_comptime_value, .ref_addr }, }, }, - .decl_const_runtime_bits_comptime_state = .{ + .decl_const_fully_comptime = .{ .tag = .constant, .attrs = decl_attrs ++ .{ - .{ .linkage_name, .strp }, + .{ .linkage_name, .strx }, .{ .type, .ref_addr }, .{ .alignment, .udata }, .{ .external, .flag }, - .{ .const_value, .block }, .{ .ZIG_comptime_value, .ref_addr }, }, }, - .decl_nullary_func = .{ + .decl_var = .{ + .tag = .variable, + .attrs = decl_attrs ++ .{ + .{ .linkage_name, .strx }, + .{ .type, .ref_addr }, + .{ .location, .exprloc }, + .{ .alignment, .udata }, + .{ .external, .flag }, + }, + }, + .decl_empty_func = .{ .tag = .subprogram, .attrs = decl_attrs ++ .{ - .{ .linkage_name, .strp }, + .{ .linkage_name, .strx }, .{ .type, .ref_addr }, - .{ .low_pc, .addr }, + .{ .low_pc, .addrx }, .{ .high_pc, .data4 }, .{ .alignment, .udata }, .{ .external, .flag }, @@ -4232,20 +5258,19 @@ pub const AbbrevCode = enum { .tag = .subprogram, .children = true, .attrs = decl_attrs ++ .{ - .{ .linkage_name, .strp }, + .{ .linkage_name, .strx }, .{ .type, .ref_addr }, - .{ .low_pc, .addr }, + .{ .low_pc, .addrx }, .{ .high_pc, .data4 }, .{ .alignment, .udata }, .{ .external, .flag }, .{ .noreturn, .flag }, }, }, - .decl_nullary_func_generic = .{ + .decl_empty_func_generic = .{ .tag = .subprogram, .attrs = decl_attrs ++ .{ .{ .type, .ref_addr }, - .{ .noreturn, .flag }, }, }, .decl_func_generic = .{ @@ -4255,10 +5280,10 @@ pub const AbbrevCode = enum { .{ .type, .ref_addr }, }, }, - .decl_extern_nullary_func = .{ + .decl_extern_empty_func = .{ .tag = .subprogram, .attrs = decl_attrs ++ .{ - .{ .linkage_name, .strp }, + .{ .linkage_name, .strx }, .{ .type, .ref_addr }, .{ .low_pc, .addr }, .{ .external, .flag_present }, @@ -4269,7 +5294,7 @@ pub const AbbrevCode = enum { .tag = .subprogram, .children = true, .attrs = decl_attrs ++ .{ - .{ .linkage_name, .strp }, + .{ .linkage_name, .strx }, .{ .type, .ref_addr }, .{ .low_pc, .addr }, .{ .external, .flag_present }, @@ -4330,16 +5355,22 @@ pub const AbbrevCode = enum { .children = true, .attrs = type_decl_specification_attrs, }, + .decl_specification_type = .{ + .tag = .imported_declaration, + .attrs = decl_specification_attrs, + }, + .decl_specification_const = .{ + .tag = .constant, + .attrs = decl_specification_attrs, + }, + .decl_specification_var = .{ + .tag = .variable, + .attrs = decl_specification_attrs, + }, .decl_specification_func = .{ .tag = .subprogram, .attrs = decl_specification_attrs, }, - .decl_instance_alias = .{ - .tag = .imported_declaration, - .attrs = decl_instance_attrs ++ .{ - .{ .import, .ref_addr }, - }, - }, .decl_instance_empty_incomplete_enum = .{ .tag = .enumeration_type, .attrs = decl_instance_attrs, @@ -4362,6 +5393,19 @@ pub const AbbrevCode = enum { .{ .type, .ref_addr }, }, }, + .type_decl_instance_empty_enum = .{ + .tag = .enumeration_type, + .attrs = type_decl_instance_attrs ++ .{ + .{ .type, .ref_addr }, + }, + }, + .type_decl_instance_enum = .{ + .tag = .enumeration_type, + .children = true, + .attrs = type_decl_instance_attrs ++ .{ + .{ .type, .ref_addr }, + }, + }, .decl_instance_empty_incomplete_struct = .{ .tag = .structure_type, .attrs = decl_instance_attrs, @@ -4386,6 +5430,21 @@ pub const AbbrevCode = enum { .{ .alignment, .udata }, }, }, + .type_decl_instance_empty_struct = .{ + .tag = .structure_type, + .attrs = type_decl_instance_attrs ++ .{ + .{ .byte_size, .udata }, + .{ .alignment, .udata }, + }, + }, + .type_decl_instance_struct = .{ + .tag = .structure_type, + .children = true, + .attrs = type_decl_instance_attrs ++ .{ + .{ .byte_size, .udata }, + .{ .alignment, .udata }, + }, + }, .decl_instance_empty_packed_struct = .{ .tag = .structure_type, .attrs = decl_instance_attrs ++ .{ @@ -4399,6 +5458,19 @@ pub const AbbrevCode = enum { .{ .type, .ref_addr }, }, }, + .type_decl_instance_empty_packed_struct = .{ + .tag = .structure_type, + .attrs = type_decl_instance_attrs ++ .{ + .{ .type, .ref_addr }, + }, + }, + .type_decl_instance_packed_struct = .{ + .tag = .structure_type, + .children = true, + .attrs = type_decl_instance_attrs ++ .{ + .{ .type, .ref_addr }, + }, + }, .decl_instance_empty_incomplete_union = .{ .tag = .union_type, .attrs = decl_instance_attrs, @@ -4423,6 +5495,21 @@ pub const AbbrevCode = enum { .{ .alignment, .udata }, }, }, + .type_decl_instance_empty_union = .{ + .tag = .union_type, + .attrs = type_decl_instance_attrs ++ .{ + .{ .byte_size, .udata }, + .{ .alignment, .udata }, + }, + }, + .type_decl_instance_union = .{ + .tag = .union_type, + .children = true, + .attrs = type_decl_instance_attrs ++ .{ + .{ .byte_size, .udata }, + .{ .alignment, .udata }, + }, + }, .decl_instance_empty_packed_union = .{ .tag = .union_type, .attrs = decl_instance_attrs ++ .{ @@ -4436,62 +5523,81 @@ pub const AbbrevCode = enum { .{ .type, .ref_addr }, }, }, - .decl_instance_var = .{ - .tag = .variable, + .type_decl_instance_empty_packed_union = .{ + .tag = .union_type, + .attrs = type_decl_instance_attrs ++ .{ + .{ .type, .ref_addr }, + }, + }, + .type_decl_instance_packed_union = .{ + .tag = .union_type, + .children = true, + .attrs = type_decl_instance_attrs ++ .{ + .{ .type, .ref_addr }, + }, + }, + .decl_instance_type = .{ + .tag = .imported_declaration, .attrs = decl_instance_attrs ++ .{ - .{ .linkage_name, .strp }, - .{ .type, .ref_addr }, - .{ .location, .exprloc }, - .{ .alignment, .udata }, - .{ .external, .flag }, + .{ .import, .ref_addr }, }, }, .decl_instance_const = .{ .tag = .constant, .attrs = decl_instance_attrs ++ .{ - .{ .linkage_name, .strp }, + .{ .linkage_name, .strx }, .{ .type, .ref_addr }, .{ .alignment, .udata }, .{ .external, .flag }, }, }, - .decl_instance_const_runtime_bits = .{ + .decl_instance_const_fully_runtime = .{ .tag = .constant, .attrs = decl_instance_attrs ++ .{ - .{ .linkage_name, .strp }, + .{ .linkage_name, .strx }, .{ .type, .ref_addr }, .{ .alignment, .udata }, .{ .external, .flag }, .{ .const_value, .block }, }, }, - .decl_instance_const_comptime_state = .{ + .decl_instance_const_partially_comptime = .{ .tag = .constant, .attrs = decl_instance_attrs ++ .{ - .{ .linkage_name, .strp }, + .{ .linkage_name, .strx }, .{ .type, .ref_addr }, .{ .alignment, .udata }, .{ .external, .flag }, + .{ .const_value, .block }, .{ .ZIG_comptime_value, .ref_addr }, }, }, - .decl_instance_const_runtime_bits_comptime_state = .{ + .decl_instance_const_fully_comptime = .{ .tag = .constant, .attrs = decl_instance_attrs ++ .{ - .{ .linkage_name, .strp }, + .{ .linkage_name, .strx }, .{ .type, .ref_addr }, .{ .alignment, .udata }, .{ .external, .flag }, - .{ .const_value, .block }, .{ .ZIG_comptime_value, .ref_addr }, }, }, - .decl_instance_nullary_func = .{ + .decl_instance_var = .{ + .tag = .variable, + .attrs = decl_instance_attrs ++ .{ + .{ .linkage_name, .strx }, + .{ .type, .ref_addr }, + .{ .location, .exprloc }, + .{ .alignment, .udata }, + .{ .external, .flag }, + }, + }, + .decl_instance_empty_func = .{ .tag = .subprogram, .attrs = decl_instance_attrs ++ .{ - .{ .linkage_name, .strp }, + .{ .linkage_name, .strx }, .{ .type, .ref_addr }, - .{ .low_pc, .addr }, + .{ .low_pc, .addrx }, .{ .high_pc, .data4 }, .{ .alignment, .udata }, .{ .external, .flag }, @@ -4502,16 +5608,16 @@ pub const AbbrevCode = enum { .tag = .subprogram, .children = true, .attrs = decl_instance_attrs ++ .{ - .{ .linkage_name, .strp }, + .{ .linkage_name, .strx }, .{ .type, .ref_addr }, - .{ .low_pc, .addr }, + .{ .low_pc, .addrx }, .{ .high_pc, .data4 }, .{ .alignment, .udata }, .{ .external, .flag }, .{ .noreturn, .flag }, }, }, - .decl_instance_nullary_func_generic = .{ + .decl_instance_empty_func_generic = .{ .tag = .subprogram, .attrs = decl_instance_attrs ++ .{ .{ .type, .ref_addr }, @@ -4524,62 +5630,11 @@ pub const AbbrevCode = enum { .{ .type, .ref_addr }, }, }, - .decl_instance_extern_nullary_func = .{ - .tag = .subprogram, - .attrs = decl_instance_attrs ++ .{ - .{ .linkage_name, .strp }, - .{ .type, .ref_addr }, - .{ .low_pc, .addr }, - .{ .external, .flag_present }, - .{ .noreturn, .flag }, - }, - }, - .decl_instance_extern_func = .{ - .tag = .subprogram, - .children = true, - .attrs = decl_instance_attrs ++ .{ - .{ .linkage_name, .strp }, - .{ .type, .ref_addr }, - .{ .low_pc, .addr }, - .{ .external, .flag_present }, - .{ .noreturn, .flag }, - }, - }, - .compile_unit = .{ - .tag = .compile_unit, - .children = true, - .attrs = &.{ - .{ .language, .data1 }, - .{ .producer, .strp }, - .{ .comp_dir, .line_strp }, - .{ .name, .line_strp }, - .{ .base_types, .ref_addr }, - .{ .stmt_list, .sec_offset }, - .{ .rnglists_base, .sec_offset }, - .{ .ranges, .rnglistx }, - .{ .use_UTF8, .flag_present }, - }, - }, - .module = .{ - .tag = .module, - .children = true, - .attrs = &.{ - .{ .name, .strp }, - .{ .ranges, .rnglistx }, - }, - }, - .module_dependency = .{ - .tag = .imported_module, - .attrs = &.{ - .{ .name, .strp }, - .{ .import, .ref_addr }, - }, - }, .empty_file = .{ .tag = .structure_type, .attrs = &.{ .{ .decl_file, .udata }, - .{ .name, .strp }, + .{ .name, .strx }, .{ .declaration, .flag }, }, }, @@ -4588,7 +5643,7 @@ pub const AbbrevCode = enum { .children = true, .attrs = &.{ .{ .decl_file, .udata }, - .{ .name, .strp }, + .{ .name, .strx }, .{ .byte_size, .udata }, .{ .alignment, .udata }, }, @@ -4596,20 +5651,20 @@ pub const AbbrevCode = enum { .access = .{ .tag = .member, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, }, }, .enum_field = .{ .tag = .enumerator, .attrs = &.{ .{ .const_value, .indirect }, - .{ .name, .strp }, + .{ .name, .strx }, }, }, .generated_field = .{ .tag = .member, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, .{ .type, .ref_addr }, .{ .data_member_location, .udata }, .{ .artificial, .flag_present }, @@ -4618,7 +5673,7 @@ pub const AbbrevCode = enum { .field = .{ .tag = .member, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, .{ .type, .ref_addr }, .{ .data_member_location, .udata }, .{ .alignment, .udata }, @@ -4627,7 +5682,7 @@ pub const AbbrevCode = enum { .field_default_fully_runtime = .{ .tag = .member, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, .{ .type, .ref_addr }, .{ .data_member_location, .udata }, .{ .alignment, .udata }, @@ -4637,7 +5692,7 @@ pub const AbbrevCode = enum { .field_default_partially_comptime = .{ .tag = .member, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, .{ .type, .ref_addr }, .{ .data_member_location, .udata }, .{ .alignment, .udata }, @@ -4648,7 +5703,7 @@ pub const AbbrevCode = enum { .field_default_fully_comptime = .{ .tag = .member, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, .{ .type, .ref_addr }, .{ .data_member_location, .udata }, .{ .alignment, .udata }, @@ -4659,7 +5714,7 @@ pub const AbbrevCode = enum { .tag = .member, .attrs = &.{ .{ .const_expr, .flag_present }, - .{ .name, .strp }, + .{ .name, .strx }, .{ .type, .ref_addr }, }, }, @@ -4667,7 +5722,7 @@ pub const AbbrevCode = enum { .tag = .member, .attrs = &.{ .{ .const_expr, .flag_present }, - .{ .name, .strp }, + .{ .name, .strx }, .{ .type, .ref_addr }, .{ .const_value, .block }, }, @@ -4676,7 +5731,7 @@ pub const AbbrevCode = enum { .tag = .member, .attrs = &.{ .{ .const_expr, .flag_present }, - .{ .name, .strp }, + .{ .name, .strx }, .{ .type, .ref_addr }, .{ .const_value, .block }, .{ .ZIG_comptime_value, .ref_addr }, @@ -4686,7 +5741,7 @@ pub const AbbrevCode = enum { .tag = .member, .attrs = &.{ .{ .const_expr, .flag_present }, - .{ .name, .strp }, + .{ .name, .strx }, .{ .type, .ref_addr }, .{ .ZIG_comptime_value, .ref_addr }, }, @@ -4694,7 +5749,7 @@ pub const AbbrevCode = enum { .packed_field = .{ .tag = .member, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, .{ .type, .ref_addr }, .{ .data_bit_offset, .udata }, }, @@ -4720,13 +5775,13 @@ pub const AbbrevCode = enum { .void_type = .{ .tag = .unspecified_type, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, }, }, .numeric_type = .{ .tag = .base_type, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, .{ .encoding, .data1 }, .{ .bit_size, .udata }, .{ .byte_size, .udata }, @@ -4736,14 +5791,14 @@ pub const AbbrevCode = enum { .inferred_error_set_type = .{ .tag = .typedef, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, .{ .type, .ref_addr }, }, }, .ptr_type = .{ .tag = .pointer_type, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, .{ .address_class, .data1 }, .{ .type, .ref_addr }, }, @@ -4751,28 +5806,16 @@ pub const AbbrevCode = enum { .ptr_sentinel_type = .{ .tag = .pointer_type, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, .{ .ZIG_sentinel, .block }, .{ .address_class, .data1 }, .{ .type, .ref_addr }, }, }, - .ptr_aligned_type = .{ - .tag = .pointer_type, + .is_aligned = .{ + .tag = .typedef, .attrs = &.{ - .{ .name, .strp }, .{ .alignment, .udata }, - .{ .address_class, .data1 }, - .{ .type, .ref_addr }, - }, - }, - .ptr_aligned_sentinel_type = .{ - .tag = .pointer_type, - .attrs = &.{ - .{ .name, .strp }, - .{ .ZIG_sentinel, .block }, - .{ .alignment, .udata }, - .{ .address_class, .data1 }, .{ .type, .ref_addr }, }, }, @@ -4792,7 +5835,7 @@ pub const AbbrevCode = enum { .tag = .array_type, .children = true, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, .{ .type, .ref_addr }, }, }, @@ -4800,7 +5843,7 @@ pub const AbbrevCode = enum { .tag = .array_type, .children = true, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, .{ .ZIG_sentinel, .block }, .{ .type, .ref_addr }, }, @@ -4809,7 +5852,7 @@ pub const AbbrevCode = enum { .tag = .array_type, .children = true, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, .{ .type, .ref_addr }, .{ .GNU_vector, .flag_present }, }, @@ -4827,10 +5870,10 @@ pub const AbbrevCode = enum { .{ .count, .udata }, }, }, - .nullary_func_type = .{ + .empty_func_type = .{ .tag = .subroutine_type, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, .{ .calling_convention, .data1 }, .{ .type, .ref_addr }, }, @@ -4839,7 +5882,7 @@ pub const AbbrevCode = enum { .tag = .subroutine_type, .children = true, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, .{ .calling_convention, .data1 }, .{ .type, .ref_addr }, }, @@ -4847,7 +5890,7 @@ pub const AbbrevCode = enum { .param = .{ .tag = .formal_parameter, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, .{ .type, .ref_addr }, }, }, @@ -4863,7 +5906,7 @@ pub const AbbrevCode = enum { .generated_empty_enum_type = .{ .tag = .enumeration_type, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, .{ .type, .ref_addr }, }, }, @@ -4871,14 +5914,14 @@ pub const AbbrevCode = enum { .tag = .enumeration_type, .children = true, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, .{ .type, .ref_addr }, }, }, .generated_empty_struct_type = .{ .tag = .structure_type, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, .{ .declaration, .flag }, }, }, @@ -4886,7 +5929,7 @@ pub const AbbrevCode = enum { .tag = .structure_type, .children = true, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, .{ .byte_size, .udata }, .{ .alignment, .udata }, }, @@ -4895,7 +5938,7 @@ pub const AbbrevCode = enum { .tag = .union_type, .children = true, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, .{ .byte_size, .udata }, .{ .alignment, .udata }, }, @@ -4903,7 +5946,7 @@ pub const AbbrevCode = enum { .capture_specification = .{ .tag = .template_value_parameter, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, }, }, .comptime_capture = .{ @@ -4946,11 +5989,11 @@ pub const AbbrevCode = enum { .{ .location, .exprloc }, }, }, - .builtin_extern_nullary_func = .{ + .builtin_extern_empty_func = .{ .tag = .subprogram, .attrs = &.{ .{ .ZIG_parent, .ref_addr }, - .{ .linkage_name, .strp }, + .{ .linkage_name, .strx }, .{ .type, .ref_addr }, .{ .low_pc, .addr }, .{ .external, .flag_present }, @@ -4962,7 +6005,7 @@ pub const AbbrevCode = enum { .children = true, .attrs = &.{ .{ .ZIG_parent, .ref_addr }, - .{ .linkage_name, .strp }, + .{ .linkage_name, .strx }, .{ .type, .ref_addr }, .{ .low_pc, .addr }, .{ .external, .flag_present }, @@ -4973,9 +6016,10 @@ pub const AbbrevCode = enum { .tag = .variable, .attrs = &.{ .{ .ZIG_parent, .ref_addr }, - .{ .linkage_name, .strp }, + .{ .linkage_name, .strx }, .{ .type, .ref_addr }, .{ .location, .exprloc }, + .{ .alignment, .udata }, .{ .external, .flag_present }, }, }, @@ -5018,7 +6062,7 @@ pub const AbbrevCode = enum { .arg = .{ .tag = .formal_parameter, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, .{ .type, .ref_addr }, .{ .location, .exprloc }, }, @@ -5034,7 +6078,7 @@ pub const AbbrevCode = enum { .tag = .formal_parameter, .attrs = &.{ .{ .const_expr, .flag_present }, - .{ .name, .strp }, + .{ .name, .strx }, .{ .type, .ref_addr }, }, }, @@ -5042,7 +6086,7 @@ pub const AbbrevCode = enum { .tag = .formal_parameter, .attrs = &.{ .{ .const_expr, .flag_present }, - .{ .name, .strp }, + .{ .name, .strx }, .{ .type, .ref_addr }, .{ .const_value, .block }, }, @@ -5051,7 +6095,7 @@ pub const AbbrevCode = enum { .tag = .formal_parameter, .attrs = &.{ .{ .const_expr, .flag_present }, - .{ .name, .strp }, + .{ .name, .strx }, .{ .type, .ref_addr }, .{ .const_value, .block }, .{ .ZIG_comptime_value, .ref_addr }, @@ -5061,7 +6105,7 @@ pub const AbbrevCode = enum { .tag = .formal_parameter, .attrs = &.{ .{ .const_expr, .flag_present }, - .{ .name, .strp }, + .{ .name, .strx }, .{ .type, .ref_addr }, .{ .ZIG_comptime_value, .ref_addr }, }, @@ -5107,7 +6151,7 @@ pub const AbbrevCode = enum { .local_var = .{ .tag = .variable, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, .{ .type, .ref_addr }, .{ .location, .exprloc }, }, @@ -5115,14 +6159,14 @@ pub const AbbrevCode = enum { .local_const = .{ .tag = .constant, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, .{ .type, .ref_addr }, }, }, .local_const_fully_runtime = .{ .tag = .constant, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, .{ .type, .ref_addr }, .{ .const_value, .block }, }, @@ -5130,7 +6174,7 @@ pub const AbbrevCode = enum { .local_const_partially_comptime = .{ .tag = .constant, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, .{ .type, .ref_addr }, .{ .const_value, .block }, .{ .ZIG_comptime_value, .ref_addr }, @@ -5139,7 +6183,7 @@ pub const AbbrevCode = enum { .local_const_fully_comptime = .{ .tag = .constant, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, .{ .type, .ref_addr }, .{ .ZIG_comptime_value, .ref_addr }, }, @@ -5187,32 +6231,64 @@ pub const AbbrevCode = enum { .{ .location, .exprloc }, }, }, - .comptime_value_field_runtime_bits = .{ + .comptime_value_field_runtime = .{ .tag = .member, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, .{ .const_value, .block }, }, }, - .comptime_value_field_comptime_state = .{ + .comptime_value_field_comptime = .{ .tag = .member, .attrs = &.{ - .{ .name, .strp }, + .{ .name, .strx }, .{ .ZIG_comptime_value, .ref_addr }, }, }, - .comptime_value_elem_runtime_bits = .{ + .comptime_value_elem_runtime = .{ .tag = .member, .attrs = &.{ .{ .const_value, .block }, }, }, - .comptime_value_elem_comptime_state = .{ + .comptime_value_elem_comptime = .{ .tag = .member, .attrs = &.{ .{ .ZIG_comptime_value, .ref_addr }, }, }, + .compile_unit = .{ + .tag = .compile_unit, + .children = true, + .attrs = &.{ + .{ .language, .data1 }, + .{ .base_types, .ref_addr }, + .{ .stmt_list, .sec_offset }, + .{ .addr_base, .sec_offset }, + .{ .rnglists_base, .sec_offset }, + .{ .str_offsets_base, .sec_offset }, + .{ .producer, .strx1 }, + .{ .comp_dir, .line_strp }, + .{ .name, .line_strp }, + .{ .ranges, .rnglistx }, + .{ .use_UTF8, .flag_present }, + }, + }, + .module = .{ + .tag = .module, + .children = true, + .attrs = &.{ + .{ .name, .strx }, + .{ .ranges, .rnglistx }, + }, + }, + .module_dependency = .{ + .tag = .imported_module, + .attrs = &.{ + .{ .name, .strx }, + .{ .import, .ref_addr }, + }, + }, }); }; diff --git a/src/link/Elf2.zig b/src/link/Elf2.zig index 5c3a65fea0ddd3c5af50b5fd942109606caaa879..569df037df4e861707959ff914ea74e3bb2d0b08 100644 --- a/src/link/Elf2.zig +++ b/src/link/Elf2.zig @@ -53,6 +53,7 @@ shndx: struct { rela_dyn: Section.Index, rela_plt: Section.Index, debug_abbrev: Section.Index, + debug_addr: Section.Index, eh_frame_hdr: Section.Index, eh_frame: Section.Index, debug_frame: Section.Index, @@ -215,6 +216,8 @@ textrel_count: u32, dwarf: Dwarf, dwarf_shared: std.enums.EnumArray(Dwarf.SharedSection, dwarf_relocs.Shared), +dwarf_addr: dwarf_relocs.Addr, +dwarf_str_offsets: dwarf_relocs.StrOffsets, dwarf_units: []dwarf_relocs.Unit, dwarf_consts: std.array_hash_map.Auto(link.ConstPool.Index, dwarf_relocs.Const), dwarf_globals: std.ArrayList(dwarf_relocs.Global), @@ -286,7 +289,9 @@ const Node = union(enum) { lazy_const_data: LazyMapRef.Index(.const_data), debug_shared: Dwarf.SharedSection, + debug_addr, eh_frame_footer, + debug_str_offsets, unit_padding, unit_frame: Dwarf.Unit.Index, unit_frame_cie: Dwarf.Unit.Index, @@ -880,6 +885,14 @@ const dwarf_relocs = struct { const Shared = struct { first_target_reloc: NodeReloc.Index, }; + const Addr = struct { + first_target_reloc: NodeReloc.Index, + symbol_relocs: std.ArrayList(SymbolReloc.Index), + }; + const StrOffsets = struct { + first_target_reloc: NodeReloc.Index, + node_relocs: std.ArrayList(NodeReloc.Index), + }; const Unit = struct { frame_cie_first_target_reloc: NodeReloc.Index, debug_info_header_first_target_reloc: NodeReloc.Index, @@ -887,7 +900,7 @@ const dwarf_relocs = struct { debug_line_header_first_target_reloc: NodeReloc.Index, debug_line_header_first_node_reloc: NodeReloc.Index, debug_rnglists_first_target_reloc: NodeReloc.Index, - debug_rnglists_symbol_relocs: std.array_hash_map.Auto(SymbolReloc.Index, void), + debug_rnglists_symbol_relocs: std.ArrayList(SymbolReloc.Index), }; const Const = struct { debug_info_first_target_reloc: NodeReloc.Index, @@ -3346,7 +3359,9 @@ pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId { .input_section, .copied_global, .debug_shared, + .debug_addr, .eh_frame_footer, + .debug_str_offsets, .unit_padding, .unit_frame, .unit_frame_cie, @@ -3800,6 +3815,7 @@ fn create( .rela_dyn = .UNDEF, .rela_plt = .UNDEF, .debug_abbrev = .UNDEF, + .debug_addr = .UNDEF, .eh_frame_hdr = .UNDEF, .eh_frame = .UNDEF, .debug_frame = .UNDEF, @@ -3866,6 +3882,14 @@ fn create( .dwarf_shared = comptime .initFill(.{ .first_target_reloc = .none, }), + .dwarf_addr = .{ + .first_target_reloc = .none, + .symbol_relocs = .empty, + }, + .dwarf_str_offsets = .{ + .first_target_reloc = .none, + .node_relocs = .empty, + }, .dwarf_units = &.{}, .dwarf_consts = .empty, .dwarf_globals = .empty, @@ -3921,6 +3945,8 @@ pub fn deinit(elf: *Elf) void { elf.changed_symtab_index.deinit(gpa); elf.dwarf.deinit(); + elf.dwarf_addr.symbol_relocs.deinit(gpa); + elf.dwarf_str_offsets.node_relocs.deinit(gpa); for (elf.dwarf_units) |*dwarf_unit| dwarf_unit.debug_rnglists_symbol_relocs.deinit(gpa); gpa.free(elf.dwarf_units); elf.dwarf_consts.deinit(gpa); @@ -4000,6 +4026,7 @@ fn initHeaders( .strip => {}, .dwarf => { shnum += 1; // .debug_abbrev + shnum += 1; // .debug_addr shnum += @intFromBool(have_debug_frame); // .debug_frame shnum += 1; // .debug_info shnum += 1; // .debug_line @@ -5104,6 +5131,11 @@ fn initHeaders( .strip => {}, .dwarf => { elf.shndx.debug_abbrev = try elf.addSection(elf.ni.elf, .{ .name = ".debug_abbrev" }); + elf.shndx.debug_addr = try elf.addSection(elf.ni.elf, .{ + .name = ".debug_addr", + .addralign = addr_align, + .node_align = elf.mf.flags.block_size, + }); if (have_debug_frame) elf.shndx.debug_frame = try elf.addSection(elf.ni.elf, .{ .name = ".debug_frame", .addralign = addr_align, @@ -5132,6 +5164,11 @@ fn initHeaders( }); elf.shndx.debug_str_offsets = try elf.addSection(elf.ni.elf, .{ .name = ".debug_str_offsets", + .addralign = switch (elf.dwarf.format) { + .@"32" => .@"4", + .@"64" => .@"8", + }, + .node_align = elf.mf.flags.block_size, }); }, .code_view => unreachable, @@ -5226,7 +5263,9 @@ fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index { .lazy_code, .lazy_const_data, .debug_shared, + .debug_addr, .eh_frame_footer, + .debug_str_offsets, .unit_padding, .unit_frame, .unit_debug_info, @@ -5273,7 +5312,9 @@ fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { .lazy_const_data, => |i| Symbol.Id.local(i.symbol(elf)).value(elf), .debug_shared, + .debug_addr, .eh_frame_footer, + .debug_str_offsets, .unit_padding, .unit_frame, .unit_frame_cie, @@ -5313,7 +5354,7 @@ fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { .lazy_code, .lazy_const_data, => |i| Symbol.Id.local(i.symbol(elf)).value(elf), - .debug_shared, .eh_frame_footer, .unit_padding => unreachable, + .debug_shared, .debug_addr, .eh_frame_footer, .debug_str_offsets, .unit_padding => unreachable, .unit_frame, .unit_debug_info, .unit_debug_line => { const section_offset, _ = parent_ni.location(&elf.mf).resolve(&elf.mf); break :parent_vaddr elf.getNodeShndx(parent_ni).vaddr(elf) + section_offset; @@ -5350,7 +5391,7 @@ fn computeNodeSectionOffset(elf: *Elf, ni: MappedFile.Node.Index) u64 { .section, .section_manual_size => 0, .input_section, .copied_global => unreachable, .nav, .uav, .lazy_code, .lazy_const_data => unreachable, - .debug_shared, .eh_frame_footer, .unit_padding => unreachable, + .debug_shared, .debug_addr, .eh_frame_footer, .debug_str_offsets, .unit_padding => unreachable, .unit_frame, .unit_debug_info, .unit_debug_line => { const parent_section_offset, _ = parent_ni.location(&elf.mf).resolve(&elf.mf); break :parent_section_offset parent_section_offset; @@ -5399,7 +5440,9 @@ pub fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void { .segment, .copied_global, .debug_shared, + .debug_addr, .eh_frame_footer, + .debug_str_offsets, .unit_padding, .unit_frame, .unit_frame_cie, @@ -5856,10 +5899,11 @@ fn dynsymPtr(elf: *Elf, index: u32) SymPtr { } fn navType(elf: *const Elf, nav_resolved: InternPool.Nav.Resolved) std.elf.STT { - const any_non_single_threaded = elf.base.comp.config.any_non_single_threaded; + const comp = elf.base.comp; + const any_non_single_threaded = comp.config.any_non_single_threaded; return if (any_non_single_threaded and nav_resolved.@"threadlocal") .TLS - else if (elf.base.comp.zcu.?.intern_pool.isFunctionType(nav_resolved.type)) + else if (comp.zcu.?.intern_pool.isFunctionType(nav_resolved.type)) .FUNC else .OBJECT; @@ -7162,8 +7206,8 @@ fn updateInitFiniArraySectionSize( } pub fn prelink(elf: *Elf, prog_node: std.Progress.Node) link.Error!void { - const sub_prog_node = prog_node.start("ELF Prelink", 0); - defer sub_prog_node.end(); + const prelink_prog_node = prog_node.start("ELF Prelink", 0); + defer prelink_prog_node.end(); const diags = &elf.base.comp.link_diags; elf.prelinkInner() catch |err| switch (err) { @@ -7197,45 +7241,20 @@ fn prelinkInner(elf: *Elf) Error!void { }; elf.input_pending_index += 1; - try elf.nodes.ensureUnusedCapacity(gpa, 5 + 4); - - switch (elf.shndx.debug_abbrev) { - .UNDEF => {}, - else => |debug_abbrev_shndx| elf.dwarf.debug_abbrev.ni = .wrap(elf.addNodeAssumeCapacity( - try debug_abbrev_shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{}), - .{ .debug_shared = .debug_abbrev }, - )), - } - switch (elf.shndx.debug_line_str) { - .UNDEF => {}, - else => |debug_line_str_shndx| elf.dwarf.debug_line_str.ni = - .wrap(elf.addNodeAssumeCapacity( - try debug_line_str_shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{}), - .{ .debug_shared = .debug_line_str }, - )), - } - switch (elf.shndx.debug_str) { - .UNDEF => {}, - else => |debug_str_shndx| elf.dwarf.debug_str.ni = .wrap(elf.addNodeAssumeCapacity( - try debug_str_shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{}), - .{ .debug_shared = .debug_str }, - )), - } - switch (elf.shndx.debug_str_offsets) { - .UNDEF => {}, - else => |debug_str_offsets_shndx| elf.dwarf.debug_str_offsets.ni = - .wrap(elf.addNodeAssumeCapacity( - try debug_str_offsets_shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{}), - .{ .debug_shared = .debug_str_offsets }, - )), - } - - for ([5]Section.Index{ + const addr_align: Alignment = switch (elf.identClass()) { + .NONE, _ => unreachable, + .@"32" => .@"4", + .@"64" => .@"8", + }; + try elf.nodes.ensureUnusedCapacity(gpa, 7 + 5); + for ([7]Section.Index{ + elf.shndx.debug_addr, elf.shndx.eh_frame, elf.shndx.debug_frame, elf.shndx.debug_info, elf.shndx.debug_line, elf.shndx.debug_rnglists, + elf.shndx.debug_str_offsets, }) |debug_shndx| { if (debug_shndx == .UNDEF) continue; const debug_ni = debug_shndx.get(elf).ni; @@ -7251,11 +7270,7 @@ fn prelinkInner(elf: *Elf) Error!void { }; break :last_header_oni last_header_oni; }, .{ - .alignment = if (frame_format) |_| switch (elf.identClass()) { - .NONE, _ => unreachable, - .@"32" => .@"4", - .@"64" => .@"8", - } else .@"1", + .alignment = if (frame_format) |_| addr_align else .@"1", .next_moved = true, .enable_next_moved = true, }), @@ -7271,6 +7286,75 @@ fn prelinkInner(elf: *Elf) Error!void { error.WriteFailed => return debug_nw.err.?, }; } + switch (elf.shndx.debug_addr) { + .UNDEF => {}, + else => |debug_addr_shndx| { + const debug_addr_ni = elf.addNodeAssumeCapacity( + try debug_addr_shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{ + .alignment = addr_align, + .next_moved = true, + .enable_next_moved = true, + }), + .debug_addr, + ); + elf.dwarf.debug_addr.ni = .wrap(debug_addr_ni); + + var dah_nw: link.MappedFile.Node.Writer = undefined; + debug_addr_ni.writer(gpa, &elf.mf, &dah_nw); + defer dah_nw.deinit(); + elf.dwarf.genDebugAddrHeader(&dah_nw.interface) catch |err| switch (err) { + else => |e| return e, + error.WriteFailed => return dah_nw.err.?, + }; + }, + } + switch (elf.shndx.debug_abbrev) { + .UNDEF => {}, + else => |debug_abbrev_shndx| elf.dwarf.debug_abbrev.ni = .wrap(elf.addNodeAssumeCapacity( + try debug_abbrev_shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{}), + .{ .debug_shared = .debug_abbrev }, + )), + } + switch (elf.shndx.debug_line_str) { + .UNDEF => {}, + else => |debug_line_str_shndx| elf.dwarf.debug_line_str.ni = + .wrap(elf.addNodeAssumeCapacity( + try debug_line_str_shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{}), + .{ .debug_shared = .debug_line_str }, + )), + } + switch (elf.shndx.debug_str) { + .UNDEF => {}, + else => |debug_str_shndx| elf.dwarf.debug_str.ni = .wrap(elf.addNodeAssumeCapacity( + try debug_str_shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{}), + .{ .debug_shared = .debug_str }, + )), + } + switch (elf.shndx.debug_str_offsets) { + .UNDEF => {}, + else => |debug_str_offsets_shndx| { + const debug_str_offsets_ni = elf.addNodeAssumeCapacity( + try debug_str_offsets_shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{ + .alignment = switch (elf.dwarf.format) { + .@"32" => .@"4", + .@"64" => .@"8", + }, + .next_moved = true, + .enable_next_moved = true, + }), + .debug_str_offsets, + ); + elf.dwarf.debug_str_offsets.ni = .wrap(debug_str_offsets_ni); + + var dsoh_nw: link.MappedFile.Node.Writer = undefined; + debug_str_offsets_ni.writer(gpa, &elf.mf, &dsoh_nw); + defer dsoh_nw.deinit(); + elf.dwarf.genDebugStrOffsetsHeader(&dsoh_nw.interface) catch |err| switch (err) { + else => |e| return e, + error.WriteFailed => return dsoh_nw.err.?, + }; + }, + } } } @@ -7301,7 +7385,7 @@ fn zcuFilesReadyInner(elf: *Elf, zcu: *Zcu) Error!void { }); } if (!try elf.dwarf.updateUnits(zcu)) return; - try elf.nodes.ensureUnusedCapacity(gpa, 5 * units_len); + try elf.nodes.ensureUnusedCapacity(gpa, 6 * units_len); for (0..units_len) |unit_index| { const ui: Dwarf.Unit.Index = @fromBackingInt(@intCast(unit_index)); const unit = ui.get(&elf.dwarf); @@ -7396,6 +7480,7 @@ fn zcuFilesReadyInner(elf: *Elf, zcu: *Zcu) Error!void { error.WriteFailed => return dih_nw.err.?, }; } + try elf.genPendingDebug(gpa); } fn flushFiles(elf: *Elf) Error!void { @@ -7406,7 +7491,6 @@ fn flushFiles(elf: *Elf) Error!void { const debug_line_header_ni = unit.debug_line_header_ni.unwrap().?; try debug_line_header_ni.parent(&elf.mf).unwrap().?.nextMoved(gpa, &elf.mf); try debug_line_header_ni.moved(gpa, &elf.mf); - try debug_line_header_ni.nextMoved(gpa, &elf.mf); var dlh_nw: MappedFile.Node.Writer = undefined; debug_line_header_ni.writer(gpa, &elf.mf, &dlh_nw); defer dlh_nw.deinit(); @@ -8221,6 +8305,8 @@ fn addNodeRelocAssumeCapacity( const first_target_reloc = switch (elf.getNode(target)) { else => unreachable, .debug_shared => |ss| &elf.dwarf_shared.getPtr(ss).first_target_reloc, + .debug_addr => &elf.dwarf_addr.first_target_reloc, + .debug_str_offsets => &elf.dwarf_str_offsets.first_target_reloc, .unit_frame_cie => |ui| &elf.dwarf_units[@backingInt(ui)].frame_cie_first_target_reloc, .unit_debug_info_header => |ui| &elf.dwarf_units[@backingInt(ui)].debug_info_header_first_target_reloc, .unit_debug_line_header => |ui| &elf.dwarf_units[@backingInt(ui)].debug_line_header_first_target_reloc, @@ -8326,7 +8412,9 @@ fn addGotRelocAssumeCapacity( .segment, .copied_global, .debug_shared, + .debug_addr, .eh_frame_footer, + .debug_str_offsets, .unit_padding, .unit_frame, .unit_frame_cie, @@ -8632,38 +8720,77 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) const ip = &zcu.intern_pool; const nav = ip.getNav(nav_index); - if (ip.indexToKey(nav.resolved.?.value) == .@"extern") return; - if (!Type.fromInterned(nav.resolved.?.type).hasRuntimeBits(zcu)) { - if (elf.ehdrMachine() != .X86_64) return; - const mod = zcu.fileByIndex(nav.srcInst(ip).resolveFile(ip)).mod.?; - return if (!mod.strip) elf.dwarf.updateComptimeNav(pt, nav_index); - } + const mod = zcu.fileByIndex(nav.srcInst(ip).resolveFile(ip)).mod.?; + switch (ip.indexToKey(nav.resolved.?.value)) { + .@"extern" => |@"extern"| { + if (mod.strip or elf.ehdrMachine() != .X86_64) return; + const si = try elf.externSymbol(.{ + .name = @"extern".name.toSlice(ip), + .lib_name = @"extern".lib_name.toSlice(ip), + .type = elf.navType(nav.resolved.?), + .linkage = @"extern".linkage, + .visibility = @"extern".visibility, + }); + const dwarf_gi = try elf.dwarf.getGlobal(nav_index); + const dwarf_global = dwarf_gi.get(&elf.dwarf); + const debug_info_ni = dwarf_global.debug_info_ni.unwrap().?; + try debug_info_ni.moved(gpa, &elf.mf); + var di_nw: MappedFile.Node.Writer = undefined; + debug_info_ni.writer(gpa, &elf.mf, &di_nw); + defer di_nw.deinit(); + elf.resetNodeRelocs(debug_info_ni); + try elf.dwarf.updateExtern(pt, &di_nw, switch (elf.ehdrMachine()) { + else => unreachable, + .X86_64 => .x86_64, + }, si, nav_index); + }, + else => if (Type.fromInterned(nav.resolved.?.type).hasRuntimeBits(zcu)) { + const nmi = try elf.navMapIndex(zcu, nav_index); + const lsi = nmi.symbol(elf); + const ni = lsi.index().ptr(elf).node.unwrap().?; - const nmi = try elf.navMapIndex(zcu, nav_index); - const ni = nmi.symbol(elf).index().ptr(elf).node.unwrap().?; + // Ensure the NAV is marked as moved so that once we're done, `flushMoved` + // will eventually be called to apply the NAV's new relocations. + try ni.moved(gpa, &elf.mf); - // Ensure the NAV is marked as moved so that once we're done, `flushMoved` will eventually be - // called to apply the NAV's new relocations. - try ni.moved(gpa, &elf.mf); + { + var nw: MappedFile.Node.Writer = undefined; + ni.writer(gpa, &elf.mf, &nw); + defer nw.deinit(); + elf.resetNodeRelocs(ni); + codegen.generateSymbol( + &elf.base, + pt, + .fromInterned(nav.resolved.?.value), + &nw.interface, + .{ .atom_index = Node.toAtom(ni) }, + ) catch |err| switch (err) { + else => |e| return e, + error.WriteFailed => return nw.err.?, + }; + switch (elf.symPtr(nmi.symbol(elf).index())) { + inline else => |sym| elf.targetStore(&sym.size, @intCast(nw.interface.end)), + } + } - { - var nw: MappedFile.Node.Writer = undefined; - ni.writer(gpa, &elf.mf, &nw); - defer nw.deinit(); - elf.resetNodeRelocs(ni); - codegen.generateSymbol( - &elf.base, - pt, - .fromInterned(nav.resolved.?.value), - &nw.interface, - .{ .atom_index = Node.toAtom(ni) }, - ) catch |err| switch (err) { - else => |e| return e, - error.WriteFailed => return nw.err.?, - }; - switch (elf.symPtr(nmi.symbol(elf).index())) { - inline else => |sym| elf.targetStore(&sym.size, @intCast(nw.interface.end)), - } + if (!mod.strip and elf.ehdrMachine() == .X86_64) { + const dwarf_gi = try elf.dwarf.getGlobal(nav_index); + const dwarf_global = dwarf_gi.get(&elf.dwarf); + const debug_info_ni = dwarf_global.debug_info_ni.unwrap().?; + try debug_info_ni.moved(gpa, &elf.mf); + var di_nw: MappedFile.Node.Writer = undefined; + debug_info_ni.writer(gpa, &elf.mf, &di_nw); + defer di_nw.deinit(); + elf.resetNodeRelocs(debug_info_ni); + try elf.dwarf.updateGlobal(pt, &di_nw, switch (elf.ehdrMachine()) { + else => unreachable, + .X86_64 => .x86_64, + }, Symbol.Id.local(lsi).toTypeErased(), nav_index); + } + } else { + if (mod.strip or elf.ehdrMachine() != .X86_64) return; + try elf.dwarf.updateComptimeGlobal(pt, nav_index); + }, } // The NAV's node is done---now generate any UAVs or lazy code/data which the NAV needs. @@ -8726,7 +8853,11 @@ pub fn addConst( .code_view => unreachable, } } -fn addConstNode(lf: *link.File, ui: Dwarf.Unit.Index, cpi: link.ConstPool.Index) link.Error!MappedFile.Node.Index { +fn addConstNode( + lf: *link.File, + ui: Dwarf.Unit.Index, + cpi: link.ConstPool.Index, +) link.Error!MappedFile.Node.Index { const elf = lf.cast(.elf2).?; const unit = ui.get(&elf.dwarf); const debug_info_ni = elf.addNodeAssumeCapacity( @@ -8769,17 +8900,18 @@ fn updateConstInner( switch (elf.base.comp.config.debug_format) { .strip => {}, .dwarf => { + switch (pt.zcu.intern_pool.indexToKey(val)) { + else => {}, + .@"extern" => return, + .func => |func| { + const fi = try elf.dwarf.getFunc(func.owner_nav); + switch (fi.get(&elf.dwarf).state) { + .unresolved => {}, + .resolved => return, + } + }, + } { - switch (pt.zcu.intern_pool.indexToKey(val)) { - else => {}, - .func => |func| { - const fi = try elf.dwarf.getFunc(func.owner_nav); - switch (fi.get(&elf.dwarf).state) { - .unresolved => {}, - .resolved => return, - } - }, - } const gpa = elf.base.comp.gpa; const debug_info_ni = Dwarf.Const.get(cpi, &elf.dwarf).debug_info_ni.unwrap().?; try debug_info_ni.moved(gpa, &elf.mf); @@ -8846,19 +8978,18 @@ fn updateFuncInner( var nw: MappedFile.Node.Writer = undefined; ni.writer(gpa, &elf.mf, &nw); defer nw.deinit(); - var debug_output_buf: Dwarf.WipNav.Debug = undefined; + var debug_output_buf: Dwarf.WipFunc.Debug = undefined; const debug_output: link.File.DebugInfoOutput, const dwarf_func = debug_output: { if (elf.ehdrMachine() != .X86_64) break :debug_output .{ .none, undefined }; const dwarf = &elf.dwarf; - const src_inst = nav.srcInst(ip); - const mod = zcu.fileByIndex(src_inst.resolveFile(ip)).mod.?; + const mod = zcu.fileByIndex(nav.srcInst(ip).resolveFile(ip)).mod.?; if (mod.strip and mod.unwind_tables == .none) break :debug_output .{ .none, undefined }; try elf.nodes.ensureUnusedCapacity(gpa, 4); const dwarf_fi = try dwarf.getFunc(func.owner_nav); - const wip_nav = &debug_output_buf.wip_nav; - wip_nav.* = .{ + const wip_func = &debug_output_buf.wip_func; + wip_func.* = .{ .dwarf = dwarf, .unit = dwarf.getUnit(mod), .func = func_index, @@ -8874,7 +9005,7 @@ fn updateFuncInner( .fde_writer = undefined, .frame_func_length = undefined, }; - const unit = wip_nav.unit.get(dwarf); + const unit = wip_func.unit.get(dwarf); const frame_align: Alignment = switch (elf.identClass()) { .NONE, _ => unreachable, @@ -8882,13 +9013,13 @@ fn updateFuncInner( .@"64" => .@"8", }; const frame_ni = unit.frame_ni.unwrap() orelse frame_ni: { - const frame_ni = elf.addNodeAssumeCapacity(try switch (wip_nav.frame_format) { + const frame_ni = elf.addNodeAssumeCapacity(try switch (wip_func.frame_format) { .debug_frame => elf.shndx.debug_frame, .eh_frame => elf.shndx.eh_frame, }.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{ .alignment = frame_align.max(elf.mf.flags.block_size), .enable_next_moved = true, - }), .{ .unit_frame = wip_nav.unit }); + }), .{ .unit_frame = wip_func.unit }); unit.frame_ni = .wrap(frame_ni); break :frame_ni frame_ni; }; @@ -8899,7 +9030,7 @@ fn updateFuncInner( .next_moved = true, .enable_next_moved = true, }), - .{ .unit_frame_cie = wip_nav.unit }, + .{ .unit_frame_cie = wip_func.unit }, ); unit.cie_ni = .wrap(cie_ni); var cie_nw: MappedFile.Node.Writer = undefined; @@ -8908,14 +9039,13 @@ fn updateFuncInner( dwarf.genDebugFrameCie(&cie_nw.interface, switch (elf.ehdrMachine()) { else => unreachable, .X86_64 => .x86_64, - }, wip_nav.frame_format) catch |err| switch (err) { + }, wip_func.frame_format) catch |err| switch (err) { error.WriteFailed => return cie_nw.err.?, }; } const dwarf_func = dwarf_fi.get(dwarf); const fde_ni = if (dwarf_func.fde_ni.unwrap()) |fde_ni| fde_ni: { try fde_ni.moved(gpa, &elf.mf); - try fde_ni.nextMoved(gpa, &elf.mf); break :fde_ni fde_ni; } else fde_ni: { const fde_ni = elf.addNodeAssumeCapacity(try frame_ni.addFloatingChild(gpa, &elf.mf, .{ @@ -8927,22 +9057,16 @@ fn updateFuncInner( dwarf_func.fde_ni = .wrap(fde_ni); break :fde_ni fde_ni; }; - fde_ni.writer(gpa, &elf.mf, &wip_nav.fde_writer); + fde_ni.writer(gpa, &elf.mf, &wip_func.fde_writer); - if (mod.strip) break :debug_output .{ .{ .eh_frame = wip_nav }, dwarf_func }; + if (mod.strip) break :debug_output .{ .{ .eh_frame = wip_func }, dwarf_func }; const debug = &debug_output_buf; - debug.pt = pt; - debug.any_children = false; - debug.blocks = .empty; + debug.init(pt); dwarf_func.state = .resolved; const debug_info_ni = dwarf_func.debug_info_ni.unwrap().?; - try dwarf.decls.put(zcu.comp.gpa, src_inst, .{ - .debug_info_ni = debug_info_ni.toOptional(), - }); try debug_info_ni.moved(gpa, &elf.mf); - try debug_info_ni.nextMoved(gpa, &elf.mf); debug_info_ni.writer(gpa, &elf.mf, &debug.info_writer); const debug_line_ni = dwarf_func.debug_line_ni.unwrap() orelse debug_line_ni: { @@ -8968,17 +9092,17 @@ fn updateFuncInner( }; switch (debug_output) { .dwarf => unreachable, - .eh_frame => |wip_nav| { + .eh_frame => |wip_func| { elf.resetNodeRelocs(dwarf_func.fde_ni.unwrap().?); - try wip_nav.genDebugFrameHeader(); + try wip_func.genDebugFrameHeader(); }, .dwarf2 => |debug| { elf.resetNodeRelocs(dwarf_func.fde_ni.unwrap().?); - try debug.wip_nav.genDebugFrameHeader(); + try debug.wip_func.genDebugFrameHeader(); elf.resetNodeRelocs(dwarf_func.debug_line_ni.unwrap().?); try debug.startDebugLine(); elf.resetNodeRelocs(dwarf_func.debug_info_ni.unwrap().?); - try debug.startFuncDebugInfo(); + try debug.startDebugInfo(); }, .none => {}, } @@ -9001,35 +9125,34 @@ fn updateFuncInner( } switch (debug_output) { .dwarf => unreachable, - .eh_frame => |wip_nav| wip_nav.finishDebugFrameFde(func_length), + .eh_frame => |wip_func| wip_func.finishDebugFrameFde(func_length), .dwarf2 => |debug| { - try debug.finishFunc(func_length); - const unit = debug.wip_nav.unit.get(debug.wip_nav.dwarf); + try debug.finish(func_length); + const unit = debug.wip_func.unit.get(debug.wip_func.dwarf); { var dr_nw: MappedFile.Node.Writer = undefined; - unit.debug_rnglists_ni.unwrap().?.writer(gpa, &elf.mf, &dr_nw); + const debug_rnglists_ni = unit.debug_rnglists_ni.unwrap().?; + try debug_rnglists_ni.moved(gpa, &elf.mf); + debug_rnglists_ni.writer(gpa, &elf.mf, &dr_nw); defer dr_nw.deinit(); - const first_symbol_reloc = elf.symbol_relocs.items.len; - debug.wip_nav.dwarf.genDebugRnglists( + const first_symbol_ri = elf.symbol_relocs.items.len; + debug.wip_func.dwarf.genDebugRnglistsRange( unit, &dr_nw, - debug.wip_nav.func_si, + debug.wip_func.func_si, func_length, ) catch |err| switch (err) { else => |e| return e, error.WriteFailed => return dr_nw.err.?, }; - const symbol_relocs = &elf.dwarf_units[@backingInt(debug.wip_nav.unit)] + const symbol_relocs = &elf.dwarf_units[@backingInt(debug.wip_func.unit)] .debug_rnglists_symbol_relocs; try symbol_relocs.ensureUnusedCapacity(gpa, elf.symbol_relocs.items.len - - first_symbol_reloc); - for (first_symbol_reloc..elf.symbol_relocs.items.len) |symbol_ri| - symbol_relocs.putAssumeCapacityNoClobber( - @fromBackingInt(@intCast(symbol_ri)), - {}, - ); + first_symbol_ri); + for (first_symbol_ri..elf.symbol_relocs.items.len) |symbol_ri| + symbol_relocs.appendAssumeCapacity(@fromBackingInt(@intCast(symbol_ri))); } - debug.wip_nav.finishDebugFrameFde(func_length); + debug.wip_func.finishDebugFrameFde(func_length); if (func.analysisUnordered(ip).inferred_error_set) { const ies = ip.getIfExists(.{ .inferred_error_set_type = func_index }).?; if (elf.dwarf.const_pool.getIfExists(ies)) |cpi| @@ -9111,8 +9234,8 @@ fn flushInner( const diags = &comp.link_diags; _ = arena; - const sub_prog_node = prog_node.start("ELF Flush", 0); - defer sub_prog_node.end(); + const flush_prog_node = prog_node.start("ELF Flush", 0); + defer flush_prog_node.end(); try elf.flushFiles(); @@ -9130,8 +9253,12 @@ fn flushInner( while (try elf.idle(tid)) {} + assert(elf.input_pending_index == elf.inputs.items.len); + assert(elf.input_section_pending_index == elf.input_sections.items.len); assert(elf.pending_uavs.items.len == 0); assert(elf.dwarf.const_pool.pending.items.len == 0); + assert(!elf.dwarf.debug_addr.anyPending()); + assert(!elf.dwarf.debug_str_offsets.anyPending()); // We've done the final `idle` loop, so everything is at its final place in the file. We have a // few more things to check and write now that addresses and offsets are finalized. @@ -9195,22 +9322,24 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool { assert(elf.dwarf.const_pool.pending.items.len == 0); task: { - if (elf.input_pending_index < elf.inputs.items.len) { + if (elf.inputs.items.len - elf.input_pending_index > 0) { const ii: Node.InputIndex = @fromBackingInt(elf.input_pending_index); elf.input_pending_index += 1; - const sub_prog_node = elf.idleProgNode(tid, elf.input_prog_node, elf.getNode(ii.node(elf))); - defer sub_prog_node.end(); + const idle_prog_node = + elf.startIdleProgress(tid, elf.input_prog_node, elf.getNode(ii.node(elf))); + defer idle_prog_node.end(); elf.flushInput(ii) catch |err| switch (err) { else => |e| return e, error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), }; break :task; } - if (elf.input_section_pending_index < elf.input_sections.items.len) { + if (elf.input_sections.items.len - elf.input_section_pending_index > 0) { const isi: InputSection.Index = @fromBackingInt(elf.input_section_pending_index); elf.input_section_pending_index += 1; - const sub_prog_node = elf.idleProgNode(tid, elf.input_prog_node, elf.getNode(isi.node(elf))); - defer sub_prog_node.end(); + const idle_prog_node = + elf.startIdleProgress(tid, elf.input_prog_node, elf.getNode(isi.node(elf))); + defer idle_prog_node.end(); elf.flushInputSection(isi) catch |err| switch (err) { else => |e| return e, error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), @@ -9237,8 +9366,8 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool { break :task; } if (elf.changed_symtab_index.pop()) |kv| { - const sub_prog_node = elf.mf.update_prog_node.start(kv.key.slice(elf), 0); - defer sub_prog_node.end(); + const idle_prog_node = elf.mf.update_prog_node.start(kv.key.slice(elf), 0); + defer idle_prog_node.end(); const global_name = kv.key; const global = elf.globalByName(global_name).?; @@ -9317,22 +9446,23 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool { const clean_resized = ni.cleanResized(&elf.mf); const clean_next_moved = ni.cleanNextMoved(&elf.mf); if (!clean_moved and !clean_resized and !clean_next_moved) continue; - const sub_prog_node = elf.idleProgNode(tid, elf.mf.update_prog_node, elf.getNode(ni)); - defer sub_prog_node.end(); + const idle_prog_node = elf.startIdleProgress(tid, elf.mf.update_prog_node, elf.getNode(ni)); + defer idle_prog_node.end(); if (clean_moved) try elf.flushMoved(ni); if (clean_resized) try elf.flushResized(ni); if (clean_moved or clean_resized or clean_next_moved) try elf.flushPadding(ni); break :task; } } - if (elf.input_sections.items.len > elf.input_section_pending_index) return true; + if (elf.inputs.items.len - elf.input_pending_index > 0) return true; + if (elf.input_sections.items.len - elf.input_section_pending_index > 0) return true; if (elf.one_shot_fixups.items.len > 0) return true; if (elf.changed_symtab_index.count() > 0) return true; if (elf.mf.updates.items.len > 0) return true; return false; } -fn idleProgNode( +fn startIdleProgress( elf: *Elf, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node, @@ -9363,7 +9493,7 @@ fn idleProgNode( }) catch &name, .debug_shared => |ss| switch (ss) { .debug_abbrev => "debug info abbrevs", - .debug_str, .debug_str_offsets => "debug info strings", + .debug_str => "debug info strings", .debug_line_str => "line info strings", }, .unit_frame, @@ -9432,29 +9562,56 @@ fn genPending(elf: *Elf, pt: Zcu.PerThread) link.Error!void { try elf.genUav(pt, umi); } var lazy_it = elf.lazy.iterator(); - while (lazy_it.next()) |lazy| while (lazy.value.pending_index < lazy.value.map.count()) { + while (lazy_it.next()) |lazy| while (lazy.value.map.count() - lazy.value.pending_index > 0) { try elf.genLazy(pt, .{ .kind = lazy.key, .index = lazy.value.pending_index }); lazy.value.pending_index += 1; }; + const gpa = elf.base.comp.gpa; switch (elf.base.comp.config.debug_format) { .strip => {}, - .dwarf => { - const gpa = elf.base.comp.gpa; - while (true) { - const pending = elf.dwarf.pending_decl; - if (pending.instance_val == .none) break; - elf.dwarf.pending_decl = .{ .di = undefined, .instance_val = .none }; - const debug_info_ni = pending.di.get(&elf.dwarf).debug_info_ni.unwrap().?; - try debug_info_ni.moved(gpa, &elf.mf); - var di_nw: MappedFile.Node.Writer = undefined; - debug_info_ni.writer(gpa, &elf.mf, &di_nw); - defer di_nw.deinit(); - elf.resetNodeRelocs(debug_info_ni); - try elf.dwarf.genDecl(pt, &di_nw, pending.instance_val); - } + .dwarf => while (true) { + const pending = elf.dwarf.pending_decl; + if (pending.instance == .none) break; + elf.dwarf.pending_decl = .{ .di = undefined, .instance = .none }; + const debug_info_ni = pending.di.get(&elf.dwarf).debug_info_ni.unwrap().?; + try debug_info_ni.moved(gpa, &elf.mf); + var di_nw: MappedFile.Node.Writer = undefined; + debug_info_ni.writer(gpa, &elf.mf, &di_nw); + defer di_nw.deinit(); + elf.resetNodeRelocs(debug_info_ni); + try elf.dwarf.genDecl(pt, &di_nw, pending.instance); }, .code_view => unreachable, } + try elf.genPendingDebug(gpa); +} +fn genPendingDebug(elf: *Elf, gpa: std.mem.Allocator) link.Error!void { + while (elf.dwarf.debug_addr.map.count() - elf.dwarf.debug_addr.pending_index > 0) { + const debug_addr_ni = elf.dwarf.debug_addr.ni.unwrap().?; + try debug_addr_ni.moved(gpa, &elf.mf); + var da_nw: link.MappedFile.Node.Writer = undefined; + debug_addr_ni.writer(gpa, &elf.mf, &da_nw); + defer da_nw.deinit(); + const first_symbol_ri = elf.symbol_relocs.items.len; + try elf.dwarf.genPendingDebugAddr(&da_nw); + const symbol_relocs = &elf.dwarf_addr.symbol_relocs; + try symbol_relocs.ensureUnusedCapacity(gpa, elf.symbol_relocs.items.len - first_symbol_ri); + for (first_symbol_ri..elf.symbol_relocs.items.len) |symbol_ri| + symbol_relocs.appendAssumeCapacity(@fromBackingInt(@intCast(symbol_ri))); + } + while (elf.dwarf.debug_str_offsets.map.count() - elf.dwarf.debug_str_offsets.pending_index > 0) { + const debug_str_offsets_ni = elf.dwarf.debug_str_offsets.ni.unwrap().?; + try debug_str_offsets_ni.moved(gpa, &elf.mf); + var dso_nw: link.MappedFile.Node.Writer = undefined; + debug_str_offsets_ni.writer(gpa, &elf.mf, &dso_nw); + defer dso_nw.deinit(); + const first_node_ri = elf.node_relocs.items.len; + try elf.dwarf.genPendingDebugStrOffsets(&dso_nw); + const node_relocs = &elf.dwarf_str_offsets.node_relocs; + try node_relocs.ensureUnusedCapacity(gpa, elf.node_relocs.items.len - first_node_ri); + for (first_node_ri..elf.node_relocs.items.len) |node_ri| + node_relocs.appendAssumeCapacity(@fromBackingInt(@intCast(node_ri))); + } } fn genUav( @@ -9855,7 +10012,44 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void target_ri = target_reloc.next; } }, - .eh_frame_footer, .unit_padding, .unit_frame, .unit_debug_info, .unit_debug_line => {}, + .eh_frame_footer, + .unit_padding, + .unit_frame, + .unit_debug_info, + .unit_debug_line, + => {}, + .debug_addr => { + const target_section_offset = elf.computeNodeSectionOffset(ni); + var target_ri = elf.dwarf_addr.first_target_reloc; + while (target_ri != .none) { + const target_reloc = target_ri.get(elf); + assert(target_reloc.target == ni); + target_reloc.flushMovedTarget(elf, target_section_offset); + target_ri = target_reloc.next; + } + const node_vaddr = elf.computeNodeVAddr(ni); + for (elf.dwarf_addr.symbol_relocs.items) |symbol_ri| { + const symbol_reloc = symbol_ri.get(elf); + assert(symbol_reloc.node.unwrap().? == ni); + symbol_reloc.flushMovedNode(elf, node_vaddr); + } + }, + .debug_str_offsets => { + const target_section_offset = elf.computeNodeSectionOffset(ni); + var target_ri = elf.dwarf_str_offsets.first_target_reloc; + while (target_ri != .none) { + const target_reloc = target_ri.get(elf); + assert(target_reloc.target == ni); + target_reloc.flushMovedTarget(elf, target_section_offset); + target_ri = target_reloc.next; + } + const node_vaddr = elf.computeNodeVAddr(ni); + for (elf.dwarf_str_offsets.node_relocs.items) |node_ri| { + const node_reloc = node_ri.get(elf); + assert(node_reloc.node.unwrap().? == ni); + node_reloc.flushMovedNode(elf, node_vaddr); + } + }, .unit_frame_cie => |ui| { const target_section_offset = elf.computeNodeSectionOffset(ni); var target_ri = elf.dwarf_units[@backingInt(ui)].frame_cie_first_target_reloc; @@ -9906,7 +10100,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void target_ri = target_reloc.next; } const node_vaddr = elf.computeNodeVAddr(ni); - for (dwarf_unit.debug_rnglists_symbol_relocs.keys()) |symbol_ri| { + for (dwarf_unit.debug_rnglists_symbol_relocs.items) |symbol_ri| { const symbol_reloc = symbol_ri.get(elf); assert(symbol_reloc.node.unwrap().? == ni); symbol_reloc.flushMovedNode(elf, node_vaddr); @@ -10238,7 +10432,9 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo .lazy_code, .lazy_const_data, .debug_shared, + .debug_addr, .eh_frame_footer, + .debug_str_offsets, .unit_padding, .unit_frame, .unit_frame_cie, @@ -10262,7 +10458,8 @@ fn flushPadding(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo const trace = tracy.trace(@src()); defer trace.end(); - switch (elf.getNode(ni)) { + const node = elf.getNode(ni); + switch (node) { .deleted => unreachable, .archive, .archive_input_member, @@ -10310,6 +10507,8 @@ fn flushPadding(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo error.NoSpaceLeft => archive.strtab_member_too_big = true, } }, + .debug_addr, + .debug_str_offsets, .unit_padding, .unit_frame_cie, .unit_debug_info_header, @@ -10321,8 +10520,27 @@ fn flushPadding(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo .func_debug_info, .func_debug_line, .decl_debug_info, - => |_, tag| { - const offset, const size = ni.location(&elf.mf).resolve(&elf.mf); + => { + const offset, const size = location: { + const offset, const size = ni.location(&elf.mf).resolve(&elf.mf); + break :location .{ offset, switch (node) { + else => unreachable, + .debug_addr => elf.dwarf.debug_addr.size(&elf.dwarf), + .debug_str_offsets => elf.dwarf.debug_str_offsets.size(&elf.dwarf), + .unit_padding, + .unit_frame_cie, + .unit_debug_info_header, + .unit_debug_line_header, + .const_debug_info, + .global_debug_info, + .func_frame_fde, + .func_debug_info, + .func_debug_line, + .decl_debug_info, + => size, + .unit_debug_rnglists => |ui| Dwarf.Rnglists.size(&elf.dwarf, ui), + } }; + }; const parent_ni = ni.parent(&elf.mf).unwrap().?; const slice = slice: { if (ni.next(&elf.mf).unwrap()) |next_ni| switch (next_ni.position(&elf.mf)) { @@ -10334,9 +10552,9 @@ fn flushPadding(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo break :slice parent_slice[@intCast(offset)..@intCast(next_offset)]; }, }; - switch (tag) { + switch (node) { else => unreachable, - .unit_padding, .unit_debug_rnglists => { + .debug_addr, .debug_str_offsets, .unit_padding, .unit_debug_rnglists => { const parent_slice = parent_ni.slicePadding(&elf.mf); const frame_shndx = elf.getNodeShndx(parent_ni); const frame_format = frame_shndx.debugFrameFormat(elf) orelse @@ -10411,7 +10629,7 @@ fn flushPadding(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo break :buffer debug_slice[@intCast(parent_offset)..]; }); fw.end = @intCast(offset + size); - switch (tag) { + switch (node) { else => unreachable, .unit_debug_info_header, .const_debug_info, @@ -10428,7 +10646,7 @@ fn flushPadding(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo error.WriteFailed => { fw.end = unit_padding_offset; elf.dwarf.updateUnitLength(fw.buffer, fw.buffer.len); - switch (tag) { + switch (node) { else => unreachable, .unit_debug_info_header, .const_debug_info, @@ -10459,8 +10677,23 @@ fn flushPadding(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo } }; var fw: Io.Writer = .fixed(slice[@intCast(size)..]); - switch (tag) { + switch (node) { else => unreachable, + .debug_addr, .debug_str_offsets, .unit_debug_rnglists => { + elf.dwarf.genUnitPadding(&fw) catch |err| switch (err) { + error.WriteFailed => { + elf.dwarf.updateUnitLength(slice, slice.len); + @memset(fw.buffer, switch (node) { + else => unreachable, + .debug_addr, .debug_str_offsets => std.math.maxInt(u8), + .unit_debug_rnglists => std.dwarf.RLE.end_of_list, + }); + return; + }, + }; + elf.dwarf.updateUnitLength(slice, size); + elf.dwarf.updateUnitLength(fw.buffer, fw.buffer.len); + }, .unit_padding => elf.dwarf.updateUnitLength(slice, slice.len), .unit_frame_cie, .func_frame_fde => { elf.dwarf.updateUnitLength(slice, slice.len); @@ -10475,17 +10708,6 @@ fn flushPadding(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo .unit_debug_line_header, .func_debug_line, => Dwarf.genDebugLinePadding(&fw, fw.buffer.len) catch unreachable, - .unit_debug_rnglists => { - elf.dwarf.genUnitPadding(&fw) catch |err| switch (err) { - error.WriteFailed => { - elf.dwarf.updateUnitLength(slice, slice.len); - @memset(fw.buffer, std.dwarf.RLE.end_of_list); - return; - }, - }; - elf.dwarf.updateUnitLength(slice, size); - elf.dwarf.updateUnitLength(fw.buffer, fw.buffer.len); - }, } }, .unit_frame, .unit_debug_info, .unit_debug_line => { @@ -11037,7 +11259,11 @@ pub fn printNode( if (nav.resolved) |resolved| try w.print("{f}, ", .{ Type.fromInterned(resolved.type).fmt(.{ .zcu = zcu, .tid = tid }), }); - try w.print("{f})", .{nav.fqn.fmt(ip)}); + try w.print("{f}", .{nav.fqn.fmt(ip)}); + if (nav.resolved) |resolved| try w.print(", {f}", .{ + Value.fromInterned(resolved.value).fmtValue(.{ .zcu = zcu, .tid = tid }), + }); + try w.writeByte(')'); }, .func_frame_fde, .func_debug_info, .func_debug_line => |fi| { const zcu = elf.base.comp.zcu.?; diff --git a/src/main.zig b/src/main.zig index ea09d77f914ff36cea3d6e84738a84b0e189f093..be23af69ab220c3dba9c3e4763569047c5ac4873 100644 --- a/src/main.zig +++ b/src/main.zig @@ -5792,7 +5792,7 @@ fn cmdChangelist(arena: Allocator, io: Io, args: []const []const u8, environ_map } var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .empty; - try Zcu.mapOldZirToNew(arena, old_zir, new_zir, &inst_map); + try Zcu.mapOldZirToNew(arena, &old_zir, &new_zir, &inst_map); var stdout_writer = Io.File.stdout().writerStreaming(io, &stdout_buffer); const stdout_bw = &stdout_writer.interface; diff --git a/src/print_zir.zig b/src/print_zir.zig index 59d56c72c0657339ee3ede6fb99667b710586116..cc72fa62987cc150ff30ed73e0beaf695540eabf 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -2211,6 +2211,8 @@ const Writer = struct { defer self.parent_decl_node = prev_parent_decl_node; self.parent_decl_node = decl.src_node; + try stream.print(":{d}:{d} ", .{ decl.src_line + 1, decl.src_column + 1 }); + if (decl.is_pub) try stream.writeAll("pub "); switch (decl.linkage) { .normal => {}, @@ -2224,7 +2226,6 @@ const Writer = struct { try stream.print("{s} '{s}'", .{ @tagName(decl.kind), self.code.nullTerminatedString(decl.name) }); }, } - try stream.print(":{d}:{d}", .{ decl.src_line + 1, decl.src_column + 1 }); const src_hash = self.code.getAssociatedSrcHash(inst).?; try stream.print(" hash({x})", .{&src_hash}); diff --git a/test/src/Debugger.zig b/test/src/Debugger.zig index 5e28c48a7e3772817f46e4cdae7af21d157945b1..6fad111e9ed5250adb3f36ee7ebbd3d073761854 100644 --- a/test/src/Debugger.zig +++ b/test/src/Debugger.zig @@ -629,7 +629,7 @@ pub fn addTests(db: *Debugger) void { \\(lldb) breakpoint delete --force 1 \\1 breakpoints deleted; 0 breakpoint locations disabled. }, - .{ .skip_new_linker = true }, + .{ .skip_new_linker = true }, // passes, but prints errors ); db.addLldbTest( "optionals", @@ -868,7 +868,7 @@ pub fn addTests(db: *Debugger) void { \\(lldb) breakpoint delete --force 1 \\1 breakpoints deleted; 0 breakpoint locations disabled. }, - .{ .skip_new_linker = true }, + .{}, ); db.addLldbTest( "if_blocks", @@ -1946,7 +1946,7 @@ pub fn addTests(db: *Debugger) void { \\ frame #1: inline_call`m1pfi(m1pai=89) at mod1.zig:23:15 \\ frame #2: inline_call`root0.main at root0.zig:41:15 }, - .{ .skip_new_linker = true }, + .{}, ); db.addLldbTest( "link_object", @@ -2054,7 +2054,7 @@ pub fn addTests(db: *Debugger) void { \\(lldb) breakpoint delete --force 1 \\1 breakpoints deleted; 0 breakpoint locations disabled. }, - .{ .skip_new_linker = true }, + .{}, ); db.addLldbTest( "multi_array_list", @@ -2308,7 +2308,7 @@ pub fn addTests(db: *Debugger) void { \\(lldb) breakpoint delete --force 1 \\1 breakpoints deleted; 0 breakpoint locations disabled. }, - .{ .skip_new_linker = true }, + .{}, ); }