Dwarf: cleanup emitted debug info

* reduce iteration cost by not tracking unused entries
 * avoid emitting unused abbrevs to `.debug_abbrev`
 * get the compiler executable passing `llvm-dwarfdump --verify`
 * make it possible to skip `.debug_line` padding much more quickly
This commit is contained in:
Jacob Young
2024-08-21 20:59:41 -04:00
committed by Jakub Konka
parent 7cd1c882c9
commit 31220b50b5
2 changed files with 335 additions and 269 deletions
+1
View File
@@ -89,6 +89,7 @@ pub const LNS = struct {
};
pub const LNE = struct {
pub const padding = 0x00;
pub const end_sequence = 0x01;
pub const set_address = 0x02;
pub const define_file = 0x03;
+334 -269
View File
@@ -55,7 +55,10 @@ const ModInfo = struct {
const DebugAbbrev = struct {
section: Section,
const unit: Unit.Index = @enumFromInt(0);
const entry: Entry.Index = @enumFromInt(0);
const header_bytes = 0;
const trailer_bytes = uleb128Bytes(@intFromEnum(AbbrevCode.null));
};
const DebugAranges = struct {
@@ -119,8 +122,7 @@ const DebugLine = struct {
1 + uleb128Bytes(DW.LNCT.path) + uleb128Bytes(DW.FORM.line_strp) + uleb128Bytes(DW.LNCT.directory_index) + uleb128Bytes(@intFromEnum(dir_index_info.form)) + uleb128Bytes(DW.LNCT.LLVM_source) + uleb128Bytes(DW.FORM.line_strp) + uleb128Bytes(file_count) + (dwarf.sectionOffsetBytes() + dir_index_info.bytes + dwarf.sectionOffsetBytes()) * file_count;
}
const trailer_bytes = 1 + uleb128Bytes(0) +
1 + uleb128Bytes(1) + 1;
const trailer_bytes = 1 + uleb128Bytes(1) + 1;
};
const DebugLocLists = struct {
@@ -173,10 +175,15 @@ const StringSection = struct {
errdefer _ = str_sec.map.pop();
const entry: Entry.Index = @enumFromInt(gop.index);
if (!gop.found_existing) {
assert(try str_sec.section.addEntry(unit, dwarf) == entry);
errdefer _ = str_sec.section.getUnit(unit).entries.pop();
const entry_ptr = str_sec.section.getUnit(unit).getEntry(entry);
assert(entry_ptr.off == str_sec.contents.items.len);
const unit_ptr = str_sec.section.getUnit(unit);
assert(try str_sec.section.getUnit(unit).addEntry(dwarf.gpa) == entry);
errdefer _ = unit_ptr.entries.pop();
const entry_ptr = unit_ptr.getEntry(entry);
if (unit_ptr.last.unwrap()) |last_entry|
unit_ptr.getEntry(last_entry).next = entry.toOptional();
entry_ptr.prev = unit_ptr.last;
unit_ptr.last = entry.toOptional();
entry_ptr.off = @intCast(str_sec.contents.items.len);
entry_ptr.len = @intCast(str.len + 1);
try str_sec.contents.ensureUnusedCapacity(dwarf.gpa, str.len + 1);
str_sec.contents.appendSliceAssumeCapacity(str);
@@ -243,7 +250,7 @@ pub const Section = struct {
fn addUnit(sec: *Section, header_len: u32, trailer_len: u32, dwarf: *Dwarf) UpdateError!Unit.Index {
const unit: Unit.Index = @enumFromInt(sec.units.items.len);
const unit_ptr = try sec.units.addOne(dwarf.gpa);
errdefer sec.popUnit();
errdefer sec.popUnit(dwarf.gpa);
unit_ptr.* = .{
.prev = sec.last,
.next = .none,
@@ -277,14 +284,11 @@ pub const Section = struct {
if (sec.last.unwrap().? == unit) sec.last = unit_ptr.prev;
}
fn popUnit(sec: *Section) void {
const unit: Unit.Index = @enumFromInt(sec.units.items.len - 1);
sec.unlinkUnit(unit);
_ = sec.units.pop();
}
fn addEntry(sec: *Section, unit: Unit.Index, dwarf: *Dwarf) UpdateError!Entry.Index {
return sec.getUnit(unit).addEntry(sec, dwarf);
fn popUnit(sec: *Section, gpa: std.mem.Allocator) void {
const unit_index: Unit.Index = @enumFromInt(sec.units.items.len - 1);
sec.unlinkUnit(unit_index);
var unit = sec.units.pop();
unit.deinit(gpa);
}
pub fn getUnit(sec: *Section, unit: Unit.Index) *Unit {
@@ -293,7 +297,21 @@ pub const Section = struct {
fn replaceEntry(sec: *Section, unit: Unit.Index, entry: Entry.Index, dwarf: *Dwarf, contents: []const u8) UpdateError!void {
const unit_ptr = sec.getUnit(unit);
try unit_ptr.getEntry(entry).replace(unit_ptr, sec, dwarf, contents);
const entry_ptr = unit_ptr.getEntry(entry);
if (contents.len > 0) {
if (entry_ptr.len == 0) {
assert(entry_ptr.prev == .none and entry_ptr.next == .none);
entry_ptr.off = if (unit_ptr.last.unwrap()) |last_entry| off: {
const last_entry_ptr = unit_ptr.getEntry(last_entry);
last_entry_ptr.next = entry.toOptional();
break :off last_entry_ptr.off + sec.padToIdeal(last_entry_ptr.len);
} else 0;
entry_ptr.prev = unit_ptr.last;
unit_ptr.last = entry.toOptional();
}
try entry_ptr.replace(unit_ptr, sec, dwarf, contents);
}
assert(entry_ptr.len == contents.len);
}
fn resize(sec: *Section, dwarf: *Dwarf, len: u64) UpdateError!void {
@@ -391,11 +409,11 @@ const Unit = struct {
unit.* = undefined;
}
fn addEntry(unit: *Unit, sec: *Section, dwarf: *Dwarf) UpdateError!Entry.Index {
fn addEntry(unit: *Unit, gpa: std.mem.Allocator) std.mem.Allocator.Error!Entry.Index {
const entry: Entry.Index = @enumFromInt(unit.entries.items.len);
const entry_ptr = try unit.entries.addOne(dwarf.gpa);
const entry_ptr = try unit.entries.addOne(gpa);
entry_ptr.* = .{
.prev = unit.last,
.prev = .none,
.next = .none,
.off = 0,
.len = 0,
@@ -404,14 +422,6 @@ const Unit = struct {
.cross_section_relocs = .{},
.external_relocs = .{},
};
if (unit.last.unwrap()) |last_entry| {
const last_entry_ptr = unit.getEntry(last_entry);
last_entry_ptr.next = entry.toOptional();
entry_ptr.off = last_entry_ptr.off + sec.padToIdeal(last_entry_ptr.len);
}
if (unit.first == .none)
unit.first = entry.toOptional();
unit.last = entry.toOptional();
return entry;
}
@@ -509,42 +519,52 @@ const Unit = struct {
const last_entry_ptr = unit.getEntry(last_entry);
break :end last_entry_ptr.off + last_entry_ptr.len;
} else 0;
const end = if (unit.next.unwrap()) |next_unit|
sec.getUnit(next_unit).off
else
sec.len;
const trailer_len: usize = @intCast(end - start);
assert(trailer_len >= unit.trailer_len);
var trailer = try std.ArrayList(u8).initCapacity(dwarf.gpa, trailer_len);
const end = if (unit.next.unwrap()) |next_unit| sec.getUnit(next_unit).off else sec.len;
const len: usize = @intCast(end - start);
assert(len >= unit.trailer_len);
if (sec == &dwarf.debug_line.section) {
var buf: [1 + uleb128Bytes(std.math.maxInt(u32)) + 1]u8 = undefined;
var fbs = std.io.fixedBufferStream(&buf);
const writer = fbs.writer();
writer.writeByte(DW.LNS.extended_op) catch unreachable;
const extended_op_bytes = fbs.pos;
var op_len_bytes: u5 = 1;
while (true) switch (std.math.order(len - extended_op_bytes - op_len_bytes, @as(u32, 1) << 7 * op_len_bytes)) {
.lt => break uleb128(writer, len - extended_op_bytes - op_len_bytes) catch unreachable,
.eq => {
// no length will ever work, so undercount and futz with the leb encoding to make up the missing byte
op_len_bytes += 1;
std.leb.writeUnsignedExtended(buf[fbs.pos..][0..op_len_bytes], len - extended_op_bytes - op_len_bytes);
fbs.pos += op_len_bytes;
break;
},
.gt => op_len_bytes += 1,
};
assert(fbs.pos == extended_op_bytes + op_len_bytes);
writer.writeByte(DW.LNE.padding) catch unreachable;
assert(fbs.pos >= unit.trailer_len and fbs.pos <= len);
return dwarf.getFile().?.pwriteAll(fbs.getWritten(), sec.off + start);
}
var trailer = try std.ArrayList(u8).initCapacity(dwarf.gpa, len);
defer trailer.deinit();
const fill_byte: u8 = if (sec == &dwarf.debug_aranges.section) fill: {
const fill_byte: u8 = if (sec == &dwarf.debug_abbrev.section) fill: {
assert(uleb128Bytes(@intFromEnum(AbbrevCode.null)) == 1);
trailer.appendAssumeCapacity(@intFromEnum(AbbrevCode.null));
break :fill @intFromEnum(AbbrevCode.null);
} else if (sec == &dwarf.debug_aranges.section) fill: {
trailer.appendNTimesAssumeCapacity(0, @intFromEnum(dwarf.address_size) * 2);
break :fill 0;
} else if (sec == &dwarf.debug_info.section) fill: {
assert(uleb128Bytes(@intFromEnum(AbbrevCode.null)) == 1);
trailer.appendNTimesAssumeCapacity(@intFromEnum(AbbrevCode.null), 2);
break :fill @intFromEnum(AbbrevCode.null);
} else if (sec == &dwarf.debug_line.section) fill: {
unit.len -= unit.trailer_len;
const extra_len: u32 = @intCast((trailer_len - DebugLine.trailer_bytes) & 1);
unit.trailer_len = DebugLine.trailer_bytes + extra_len;
unit.len += unit.trailer_len;
// prevent end sequence from emitting an invalid file index
trailer.appendAssumeCapacity(DW.LNS.set_file);
uleb128(trailer.fixedWriter(), 0) catch unreachable;
trailer.appendAssumeCapacity(DW.LNS.extended_op);
std.leb.writeUnsignedExtended(trailer.addManyAsSliceAssumeCapacity(uleb128Bytes(1) + extra_len), 1);
trailer.appendAssumeCapacity(DW.LNE.end_sequence);
break :fill DW.LNS.extended_op;
} else if (sec == &dwarf.debug_rnglists.section) fill: {
trailer.appendAssumeCapacity(DW.RLE.end_of_list);
break :fill DW.RLE.end_of_list;
} else unreachable;
assert(trailer.items.len == unit.trailer_len);
trailer.appendNTimesAssumeCapacity(fill_byte, trailer_len - trailer.items.len);
assert(trailer.items.len == trailer_len);
trailer.appendNTimesAssumeCapacity(fill_byte, len - trailer.items.len);
assert(trailer.items.len == len);
try dwarf.getFile().?.pwriteAll(trailer.items, sec.off + start);
}
@@ -625,45 +645,62 @@ const Entry = struct {
};
fn pad(entry: *Entry, unit: *Unit, sec: *Section, dwarf: *Dwarf) UpdateError!void {
assert(entry.len > 0);
const start = entry.off + entry.len;
const len = unit.getEntry(entry.next.unwrap() orelse return).off - start;
if (sec == &dwarf.debug_info.section) {
var buf: [
@max(
uleb128Bytes(@intFromEnum(AbbrevCode.pad_1)),
uleb128Bytes(@intFromEnum(AbbrevCode.pad_n)) + uleb128Bytes(std.math.maxInt(u32)),
)
]u8 = undefined;
var fbs = std.io.fixedBufferStream(&buf);
switch (len) {
0 => {},
1 => uleb128(fbs.writer(), @intFromEnum(AbbrevCode.pad_1)) catch unreachable,
else => {
uleb128(fbs.writer(), @intFromEnum(AbbrevCode.pad_n)) catch unreachable;
const abbrev_code_bytes = fbs.pos;
var block_len_bytes: u5 = 1;
while (true) switch (std.math.order(len - abbrev_code_bytes - block_len_bytes, @as(u32, 1) << 7 * block_len_bytes)) {
.lt => break uleb128(fbs.writer(), len - abbrev_code_bytes - block_len_bytes) catch unreachable,
.eq => {
// no length will ever work, so undercount and futz with the leb encoding to make up the missing byte
block_len_bytes += 1;
std.leb.writeUnsignedExtended(buf[fbs.pos..][0..block_len_bytes], len - abbrev_code_bytes - block_len_bytes);
fbs.pos += block_len_bytes;
break;
},
.gt => block_len_bytes += 1,
};
assert(fbs.pos == abbrev_code_bytes + block_len_bytes);
},
}
assert(fbs.pos <= len);
try dwarf.getFile().?.pwriteAll(fbs.getWritten(), sec.off + unit.off + unit.header_len + start);
} else if (sec == &dwarf.debug_line.section) {
const buf = try dwarf.gpa.alloc(u8, len);
defer dwarf.gpa.free(buf);
@memset(buf, DW.LNS.const_add_pc);
try dwarf.getFile().?.pwriteAll(buf, sec.off + unit.off + unit.header_len + start);
var buf: [
@max(
uleb128Bytes(@intFromEnum(AbbrevCode.pad_1)),
uleb128Bytes(@intFromEnum(AbbrevCode.pad_n)) + uleb128Bytes(std.math.maxInt(u32)),
1 + uleb128Bytes(std.math.maxInt(u32)) + 1,
)
]u8 = undefined;
var fbs = std.io.fixedBufferStream(&buf);
const writer = fbs.writer();
if (sec == &dwarf.debug_info.section) switch (len) {
0 => {},
1 => uleb128(writer, try dwarf.refAbbrevCode(.pad_1)) catch unreachable,
else => {
uleb128(writer, try dwarf.refAbbrevCode(.pad_n)) catch unreachable;
const abbrev_code_bytes = fbs.pos;
var block_len_bytes: u5 = 1;
while (true) switch (std.math.order(len - abbrev_code_bytes - block_len_bytes, @as(u32, 1) << 7 * block_len_bytes)) {
.lt => break uleb128(writer, len - abbrev_code_bytes - block_len_bytes) catch unreachable,
.eq => {
// no length will ever work, so undercount and futz with the leb encoding to make up the missing byte
block_len_bytes += 1;
std.leb.writeUnsignedExtended(buf[fbs.pos..][0..block_len_bytes], len - abbrev_code_bytes - block_len_bytes);
fbs.pos += block_len_bytes;
break;
},
.gt => block_len_bytes += 1,
};
assert(fbs.pos == abbrev_code_bytes + block_len_bytes);
},
} else if (sec == &dwarf.debug_line.section) switch (len) {
0 => {},
1 => writer.writeByte(DW.LNS.const_add_pc) catch unreachable,
else => {
writer.writeByte(DW.LNS.extended_op) catch unreachable;
const extended_op_bytes = fbs.pos;
var op_len_bytes: u5 = 1;
while (true) switch (std.math.order(len - extended_op_bytes - op_len_bytes, @as(u32, 1) << 7 * op_len_bytes)) {
.lt => break uleb128(writer, len - extended_op_bytes - op_len_bytes) catch unreachable,
.eq => {
// no length will ever work, so undercount and futz with the leb encoding to make up the missing byte
op_len_bytes += 1;
std.leb.writeUnsignedExtended(buf[fbs.pos..][0..op_len_bytes], len - extended_op_bytes - op_len_bytes);
fbs.pos += op_len_bytes;
break;
},
.gt => op_len_bytes += 1,
};
assert(fbs.pos == extended_op_bytes + op_len_bytes);
if (len > 2) writer.writeByte(DW.LNE.padding) catch unreachable;
},
} else assert(!sec.pad_to_ideal and len == 0);
assert(fbs.pos <= len);
try dwarf.getFile().?.pwriteAll(fbs.getWritten(), sec.off + unit.off + unit.header_len + start);
}
fn replace(entry_ptr: *Entry, unit: *Unit, sec: *Section, dwarf: *Dwarf, contents: []const u8) UpdateError!void {
@@ -691,15 +728,7 @@ const Entry = struct {
try unit.resize(sec, dwarf, 0, @intCast(unit.header_len + entry_ptr.off + sec.padToIdeal(contents.len) + unit.trailer_len));
}
entry_ptr.len = @intCast(contents.len);
{
var prev_entry_ptr = entry_ptr;
while (prev_entry_ptr.prev.unwrap()) |prev_entry| {
prev_entry_ptr = unit.getEntry(prev_entry);
if (prev_entry_ptr.len == 0) continue;
try prev_entry_ptr.pad(unit, sec, dwarf);
break;
}
}
if (entry_ptr.prev.unwrap()) |prev_entry| try unit.getEntry(prev_entry).pad(unit, sec, dwarf);
try dwarf.getFile().?.pwriteAll(contents, sec.off + unit.off + unit.header_len + entry_ptr.off);
try entry_ptr.pad(unit, sec, dwarf);
if (false) {
@@ -1039,7 +1068,10 @@ pub const WipNav = struct {
func: InternPool.Index,
func_sym_index: u32,
func_high_reloc: u32,
inlined_funcs_high_reloc: std.ArrayListUnmanaged(u32),
inlined_funcs: std.ArrayListUnmanaged(struct {
abbrev_code: u32,
high_reloc: u32,
}),
debug_info: std.ArrayListUnmanaged(u8),
debug_line: std.ArrayListUnmanaged(u8),
debug_loclists: std.ArrayListUnmanaged(u8),
@@ -1047,7 +1079,7 @@ pub const WipNav = struct {
pub fn deinit(wip_nav: *WipNav) void {
const gpa = wip_nav.dwarf.gpa;
if (wip_nav.func != .none) wip_nav.inlined_funcs_high_reloc.deinit(gpa);
if (wip_nav.func != .none) wip_nav.inlined_funcs.deinit(gpa);
wip_nav.debug_info.deinit(gpa);
wip_nav.debug_line.deinit(gpa);
wip_nav.debug_loclists.deinit(gpa);
@@ -1066,15 +1098,14 @@ pub const WipNav = struct {
ty: Type,
loc: Loc,
) UpdateError!void {
wip_nav.any_children = true;
assert(wip_nav.func != .none);
const diw = wip_nav.debug_info.writer(wip_nav.dwarf.gpa);
try uleb128(diw, @intFromEnum(switch (tag) {
try wip_nav.abbrevCode(switch (tag) {
inline else => |ct_tag| @field(AbbrevCode, @tagName(ct_tag)),
}));
});
try wip_nav.strp(name);
try wip_nav.refType(ty);
try wip_nav.exprloc(loc);
wip_nav.any_children = true;
}
pub fn advancePCAndLine(
@@ -1136,9 +1167,10 @@ pub const WipNav = struct {
const dwarf = wip_nav.dwarf;
const zcu = wip_nav.pt.zcu;
const diw = wip_nav.debug_info.writer(dwarf.gpa);
try wip_nav.inlined_funcs_high_reloc.ensureUnusedCapacity(dwarf.gpa, 1);
const inlined_func = try wip_nav.inlined_funcs.addOne(dwarf.gpa);
try uleb128(diw, @intFromEnum(AbbrevCode.inlined_func));
inlined_func.abbrev_code = @intCast(wip_nav.debug_info.items.len);
try wip_nav.abbrevCode(.inlined_func);
try wip_nav.refNav(zcu.funcInfo(func).owner_nav);
try uleb128(diw, zcu.navSrcLine(zcu.funcInfo(wip_nav.func).owner_nav) + line + 1);
try uleb128(diw, column + 1);
@@ -1150,7 +1182,7 @@ pub const WipNav = struct {
.target_off = code_off,
});
try diw.writeByteNTimes(0, @intFromEnum(dwarf.address_size));
wip_nav.inlined_funcs_high_reloc.appendAssumeCapacity(@intCast(external_relocs.items.len));
inlined_func.high_reloc = @intCast(external_relocs.items.len);
external_relocs.appendAssumeCapacity(.{
.source_off = @intCast(wip_nav.debug_info.items.len),
.target_sym = wip_nav.func_sym_index,
@@ -1158,17 +1190,27 @@ pub const WipNav = struct {
});
try diw.writeByteNTimes(0, @intFromEnum(dwarf.address_size));
try wip_nav.setInlineFunc(func);
wip_nav.any_children = false;
}
pub fn leaveInlineFunc(wip_nav: *WipNav, func: InternPool.Index, code_off: u64) UpdateError!void {
const inlined_func_bytes = comptime uleb128Bytes(@intFromEnum(AbbrevCode.inlined_func));
const inlined_func = wip_nav.inlined_funcs.pop();
const external_relocs = &wip_nav.dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs;
external_relocs.items[wip_nav.inlined_funcs_high_reloc.pop()].target_off = code_off;
try uleb128(wip_nav.debug_info.writer(wip_nav.dwarf.gpa), @intFromEnum(AbbrevCode.null));
external_relocs.items[inlined_func.high_reloc].target_off = code_off;
if (wip_nav.any_children)
try uleb128(wip_nav.debug_info.writer(wip_nav.dwarf.gpa), @intFromEnum(AbbrevCode.null))
else
std.leb.writeUnsignedFixed(
inlined_func_bytes,
wip_nav.debug_info.items[inlined_func.abbrev_code..][0..inlined_func_bytes],
try wip_nav.dwarf.refAbbrevCode(.empty_inlined_func),
);
try wip_nav.setInlineFunc(func);
wip_nav.any_children = true;
}
pub fn setInlineFunc(wip_nav: *WipNav, func: InternPool.Index) UpdateError!void {
wip_nav.any_children = true;
const zcu = wip_nav.pt.zcu;
const dwarf = wip_nav.dwarf;
if (wip_nav.func == func) return;
@@ -1219,6 +1261,10 @@ pub const WipNav = struct {
wip_nav.func = func;
}
fn abbrevCode(wip_nav: *WipNav, abbrev_code: AbbrevCode) UpdateError!void {
try uleb128(wip_nav.debug_info.writer(wip_nav.dwarf.gpa), try wip_nav.dwarf.refAbbrevCode(abbrev_code));
}
fn infoSectionOffset(wip_nav: *WipNav, sec: Section.Index, unit: Unit.Index, entry: Entry.Index, off: u32) UpdateError!void {
const dwarf = wip_nav.dwarf;
const gpa = dwarf.gpa;
@@ -1336,7 +1382,7 @@ pub const WipNav = struct {
loaded_enum: InternPool.LoadedEnumType,
abbrev_code: std.enums.EnumFieldStruct(std.builtin.Signedness, AbbrevCode, null),
field_index: usize,
) std.mem.Allocator.Error!void {
) UpdateError!void {
const zcu = wip_nav.pt.zcu;
const ip = &zcu.intern_pool;
const diw = wip_nav.debug_info.writer(wip_nav.dwarf.gpa);
@@ -1344,9 +1390,9 @@ pub const WipNav = struct {
.comptime_int_type => .signed,
else => Type.fromInterned(loaded_enum.tag_ty).intInfo(zcu).signedness,
};
try uleb128(diw, @intFromEnum(switch (signedness) {
try wip_nav.abbrevCode(switch (signedness) {
inline .signed, .unsigned => |ct_signedness| @field(abbrev_code, @tagName(ct_signedness)),
}));
});
if (loaded_enum.values.len > 0) switch (ip.indexToKey(loaded_enum.values.get(ip)[field_index]).int.storage) {
.u64 => |value| switch (signedness) {
.signed => try sleb128(diw, value),
@@ -1535,20 +1581,21 @@ pub fn initMetadata(dwarf: *Dwarf) UpdateError!void {
dwarf.reloadSectionMetadata();
dwarf.debug_abbrev.section.pad_to_ideal = false;
assert(try dwarf.debug_abbrev.section.addUnit(0, 0, dwarf) == DebugAbbrev.unit);
errdefer dwarf.debug_abbrev.section.popUnit();
assert(try dwarf.debug_abbrev.section.addEntry(DebugAbbrev.unit, dwarf) == DebugAbbrev.entry);
assert(try dwarf.debug_abbrev.section.addUnit(DebugAbbrev.header_bytes, DebugAbbrev.trailer_bytes, dwarf) == DebugAbbrev.unit);
errdefer dwarf.debug_abbrev.section.popUnit(dwarf.gpa);
for (std.enums.values(AbbrevCode)) |abbrev_code|
assert(@intFromEnum(try dwarf.debug_abbrev.section.getUnit(DebugAbbrev.unit).addEntry(dwarf.gpa)) == @intFromEnum(abbrev_code));
dwarf.debug_aranges.section.pad_to_ideal = false;
dwarf.debug_aranges.section.alignment = InternPool.Alignment.fromNonzeroByteUnits(@intFromEnum(dwarf.address_size) * 2);
dwarf.debug_line_str.section.pad_to_ideal = false;
assert(try dwarf.debug_line_str.section.addUnit(0, 0, dwarf) == StringSection.unit);
errdefer dwarf.debug_line_str.section.popUnit();
errdefer dwarf.debug_line_str.section.popUnit(dwarf.gpa);
dwarf.debug_str.section.pad_to_ideal = false;
assert(try dwarf.debug_str.section.addUnit(0, 0, dwarf) == StringSection.unit);
errdefer dwarf.debug_str.section.popUnit();
errdefer dwarf.debug_str.section.popUnit(dwarf.gpa);
dwarf.debug_loclists.section.pad_to_ideal = false;
@@ -1589,31 +1636,31 @@ fn getUnit(dwarf: *Dwarf, mod: *Module) UpdateError!Unit.Index {
DebugAranges.trailerBytes(dwarf),
dwarf,
) == unit);
errdefer dwarf.debug_aranges.section.popUnit();
errdefer dwarf.debug_aranges.section.popUnit(dwarf.gpa);
assert(try dwarf.debug_info.section.addUnit(
DebugInfo.headerBytes(dwarf),
DebugInfo.trailer_bytes,
dwarf,
) == unit);
errdefer dwarf.debug_info.section.popUnit();
errdefer dwarf.debug_info.section.popUnit(dwarf.gpa);
assert(try dwarf.debug_line.section.addUnit(
DebugLine.headerBytes(dwarf, 5, 25),
DebugLine.trailer_bytes,
dwarf,
) == unit);
errdefer dwarf.debug_line.section.popUnit();
errdefer dwarf.debug_line.section.popUnit(dwarf.gpa);
assert(try dwarf.debug_loclists.section.addUnit(
DebugLocLists.headerBytes(dwarf),
DebugLocLists.trailer_bytes,
dwarf,
) == unit);
errdefer dwarf.debug_loclists.section.popUnit();
errdefer dwarf.debug_loclists.section.popUnit(dwarf.gpa);
assert(try dwarf.debug_rnglists.section.addUnit(
DebugRngLists.headerBytes(dwarf),
DebugRngLists.trailer_bytes,
dwarf,
) == unit);
errdefer dwarf.debug_rnglists.section.popUnit();
errdefer dwarf.debug_rnglists.section.popUnit(dwarf.gpa);
}
return unit;
}
@@ -1658,7 +1705,7 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
.func = .none,
.func_sym_index = undefined,
.func_high_reloc = undefined,
.inlined_funcs_high_reloc = undefined,
.inlined_funcs = undefined,
.debug_info = .{},
.debug_line = .{},
.debug_loclists = .{},
@@ -1699,7 +1746,7 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
} else .{ zcu.fileRootType(inst_info.file), DW.ACCESS.private };
const diw = wip_nav.debug_info.writer(dwarf.gpa);
try uleb128(diw, @intFromEnum(AbbrevCode.decl_var));
try wip_nav.abbrevCode(.decl_var);
try wip_nav.refType(Type.fromInterned(parent_type));
assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf));
try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian);
@@ -1714,7 +1761,7 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
ty.abiAlignment(pt).toByteUnits().?);
try diw.writeByte(@intFromBool(false));
wip_nav.finishForward(ty_reloc_index);
try uleb128(diw, @intFromEnum(AbbrevCode.is_const));
try wip_nav.abbrevCode(.is_const);
try wip_nav.refType(ty);
},
.variable => |variable| {
@@ -1749,7 +1796,7 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
} else .{ zcu.fileRootType(inst_info.file), DW.ACCESS.private };
const diw = wip_nav.debug_info.writer(dwarf.gpa);
try uleb128(diw, @intFromEnum(AbbrevCode.decl_var));
try wip_nav.abbrevCode(.decl_var);
try wip_nav.refType(Type.fromInterned(parent_type));
assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf));
try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian);
@@ -1799,10 +1846,10 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
const func_type = ip.indexToKey(func.ty).func_type;
wip_nav.func = nav_val.toIntern();
wip_nav.func_sym_index = sym_index;
wip_nav.inlined_funcs_high_reloc = .{};
wip_nav.inlined_funcs = .{};
const diw = wip_nav.debug_info.writer(dwarf.gpa);
try uleb128(diw, @intFromEnum(AbbrevCode.decl_func));
try wip_nav.abbrevCode(.decl_func);
try wip_nav.refType(Type.fromInterned(parent_type));
assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf));
try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian);
@@ -1891,7 +1938,7 @@ pub fn finishWipNav(
} else std.leb.writeUnsignedFixed(
AbbrevCode.decl_bytes,
wip_nav.debug_info.items[0..AbbrevCode.decl_bytes],
@intFromEnum(AbbrevCode.decl_func_empty),
try dwarf.refAbbrevCode(.decl_empty_func),
);
var aranges_entry = [1]u8{0} ** (8 + 8);
@@ -1967,7 +2014,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
.func = .none,
.func_sym_index = undefined,
.func_high_reloc = undefined,
.inlined_funcs_high_reloc = undefined,
.inlined_funcs = undefined,
.debug_info = .{},
.debug_line = .{},
.debug_loclists = .{},
@@ -1990,12 +2037,12 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
) != abbrev_code_buf.len) return error.InputOutput;
var abbrev_code_fbs = std.io.fixedBufferStream(&abbrev_code_buf);
const abbrev_code: AbbrevCode = @enumFromInt(
try std.leb.readUleb128(@typeInfo(AbbrevCode).Enum.tag_type, abbrev_code_fbs.reader()),
std.leb.readUleb128(@typeInfo(AbbrevCode).Enum.tag_type, abbrev_code_fbs.reader()) catch unreachable,
);
switch (abbrev_code) {
else => unreachable,
.decl_func, .decl_func_empty => return,
.decl_func_generic, .decl_func_generic_empty => {},
.decl_func, .decl_empty_func => return,
.decl_func_generic, .decl_empty_func_generic => {},
}
}
entry_ptr.clear();
@@ -2017,7 +2064,10 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
const func_type = ip.indexToKey(func.ty).func_type;
const diw = wip_nav.debug_info.writer(dwarf.gpa);
try uleb128(diw, @intFromEnum(@as(AbbrevCode, if (func_type.param_types.len > 0 or func_type.is_var_args) .decl_func_generic else .decl_func_generic_empty)));
try wip_nav.abbrevCode(if (func_type.param_types.len > 0 or func_type.is_var_args)
.decl_func_generic
else
.decl_empty_func_generic);
try wip_nav.refType(Type.fromInterned(parent_type));
assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf));
try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian);
@@ -2027,10 +2077,10 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
try wip_nav.refType(Type.fromInterned(func_type.return_type));
if (func_type.param_types.len > 0 or func_type.is_var_args) {
for (0..func_type.param_types.len) |param_index| {
try uleb128(diw, @intFromEnum(AbbrevCode.func_type_param));
try wip_nav.abbrevCode(.func_type_param);
try wip_nav.refType(Type.fromInterned(func_type.param_types.get(ip)[param_index]));
}
if (func_type.is_var_args) try uleb128(diw, @intFromEnum(AbbrevCode.is_var_args));
if (func_type.is_var_args) try wip_nav.abbrevCode(.is_var_args);
try uleb128(diw, @intFromEnum(AbbrevCode.null));
}
},
@@ -2088,10 +2138,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
switch (loaded_struct.layout) {
.auto, .@"extern" => {
try uleb128(diw, @intFromEnum(@as(AbbrevCode, if (loaded_struct.field_types.len == 0)
.decl_namespace_struct
else
.decl_struct)));
try wip_nav.abbrevCode(if (loaded_struct.field_types.len == 0) .decl_namespace_struct else .decl_struct);
try wip_nav.refType(Type.fromInterned(parent_type));
assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf));
try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian);
@@ -2103,7 +2150,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
try uleb128(diw, nav_val.toType().abiAlignment(pt).toByteUnits().?);
for (0..loaded_struct.field_types.len) |field_index| {
const is_comptime = loaded_struct.fieldIsComptime(ip, field_index);
try uleb128(diw, @intFromEnum(@as(AbbrevCode, if (is_comptime) .struct_field_comptime else .struct_field)));
try wip_nav.abbrevCode(if (is_comptime) .struct_field_comptime else .struct_field);
if (loaded_struct.fieldName(ip, field_index).unwrap()) |field_name| try wip_nav.strp(field_name.toSlice(ip)) else {
const field_name = try std.fmt.allocPrint(dwarf.gpa, "{d}", .{field_index});
defer dwarf.gpa.free(field_name);
@@ -2121,7 +2168,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
}
},
.@"packed" => {
try uleb128(diw, @intFromEnum(AbbrevCode.decl_packed_struct));
try wip_nav.abbrevCode(.decl_packed_struct);
try wip_nav.refType(Type.fromInterned(parent_type));
assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf));
try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian);
@@ -2131,7 +2178,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
try wip_nav.refType(Type.fromInterned(loaded_struct.backingIntTypeUnordered(ip)));
var field_bit_offset: u16 = 0;
for (0..loaded_struct.field_types.len) |field_index| {
try uleb128(diw, @intFromEnum(@as(AbbrevCode, .packed_struct_field)));
try wip_nav.abbrevCode(.packed_struct_field);
try wip_nav.strp(loaded_struct.fieldName(ip, field_index).unwrap().?.toSlice(ip));
const field_type = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]);
try wip_nav.refType(field_type);
@@ -2150,7 +2197,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit);
wip_nav.entry = nav_gop.value_ptr.*;
const diw = wip_nav.debug_info.writer(dwarf.gpa);
try uleb128(diw, @intFromEnum(AbbrevCode.decl_alias));
try wip_nav.abbrevCode(.decl_alias);
try wip_nav.refType(Type.fromInterned(parent_type));
assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf));
try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian);
@@ -2210,7 +2257,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
}
wip_nav.entry = nav_gop.value_ptr.*;
const diw = wip_nav.debug_info.writer(dwarf.gpa);
try uleb128(diw, @intFromEnum(AbbrevCode.decl_enum));
try wip_nav.abbrevCode(if (loaded_enum.names.len > 0) .decl_enum else .decl_empty_enum);
try wip_nav.refType(Type.fromInterned(parent_type));
assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf));
try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian);
@@ -2225,7 +2272,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
}, field_index);
try wip_nav.strp(loaded_enum.names.get(ip)[field_index].toSlice(ip));
}
try uleb128(diw, @intFromEnum(AbbrevCode.null));
if (loaded_enum.names.len > 0) try uleb128(diw, @intFromEnum(AbbrevCode.null));
break :done;
}
@@ -2235,7 +2282,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit);
wip_nav.entry = nav_gop.value_ptr.*;
const diw = wip_nav.debug_info.writer(dwarf.gpa);
try uleb128(diw, @intFromEnum(AbbrevCode.decl_alias));
try wip_nav.abbrevCode(.decl_alias);
try wip_nav.refType(Type.fromInterned(parent_type));
assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf));
try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian);
@@ -2293,7 +2340,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
}
wip_nav.entry = nav_gop.value_ptr.*;
const diw = wip_nav.debug_info.writer(dwarf.gpa);
try uleb128(diw, @intFromEnum(AbbrevCode.decl_union));
try wip_nav.abbrevCode(.decl_union);
try wip_nav.refType(Type.fromInterned(parent_type));
assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf));
try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian);
@@ -2305,7 +2352,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
try uleb128(diw, union_layout.abi_align.toByteUnits().?);
const loaded_tag = loaded_union.loadTagType(ip);
if (loaded_union.hasTag(ip)) {
try uleb128(diw, @intFromEnum(AbbrevCode.tagged_union));
try wip_nav.abbrevCode(.tagged_union);
try wip_nav.infoSectionOffset(
.debug_info,
wip_nav.unit,
@@ -2313,7 +2360,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
@intCast(wip_nav.debug_info.items.len + dwarf.sectionOffsetBytes()),
);
{
try uleb128(diw, @intFromEnum(AbbrevCode.generated_field));
try wip_nav.abbrevCode(.generated_field);
try wip_nav.strp("tag");
try wip_nav.refType(Type.fromInterned(loaded_union.enum_tag_ty));
try uleb128(diw, union_layout.tagOffset());
@@ -2324,7 +2371,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
.unsigned = .unsigned_tagged_union_field,
}, field_index);
{
try uleb128(diw, @intFromEnum(AbbrevCode.struct_field));
try wip_nav.abbrevCode(.struct_field);
try wip_nav.strp(loaded_tag.names.get(ip)[field_index].toSlice(ip));
const field_type = Type.fromInterned(loaded_union.field_types.get(ip)[field_index]);
try wip_nav.refType(field_type);
@@ -2340,7 +2387,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
if (ip.indexToKey(loaded_union.enum_tag_ty).enum_type == .generated_tag)
try wip_nav.pending_types.append(dwarf.gpa, loaded_union.enum_tag_ty);
} else for (0..loaded_union.field_types.len) |field_index| {
try uleb128(diw, @intFromEnum(AbbrevCode.untagged_union_field));
try wip_nav.abbrevCode(.untagged_union_field);
try wip_nav.strp(loaded_tag.names.get(ip)[field_index].toSlice(ip));
const field_type = Type.fromInterned(loaded_union.field_types.get(ip)[field_index]);
try wip_nav.refType(field_type);
@@ -2357,7 +2404,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit);
wip_nav.entry = nav_gop.value_ptr.*;
const diw = wip_nav.debug_info.writer(dwarf.gpa);
try uleb128(diw, @intFromEnum(AbbrevCode.decl_alias));
try wip_nav.abbrevCode(.decl_alias);
try wip_nav.refType(Type.fromInterned(parent_type));
assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf));
try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian);
@@ -2415,7 +2462,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
}
wip_nav.entry = nav_gop.value_ptr.*;
const diw = wip_nav.debug_info.writer(dwarf.gpa);
try uleb128(diw, @intFromEnum(AbbrevCode.decl_namespace_struct));
try wip_nav.abbrevCode(.decl_namespace_struct);
try wip_nav.refType(Type.fromInterned(parent_type));
assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf));
try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian);
@@ -2432,7 +2479,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit);
wip_nav.entry = nav_gop.value_ptr.*;
const diw = wip_nav.debug_info.writer(dwarf.gpa);
try uleb128(diw, @intFromEnum(AbbrevCode.decl_alias));
try wip_nav.abbrevCode(.decl_alias);
try wip_nav.refType(Type.fromInterned(parent_type));
assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf));
try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian);
@@ -2473,7 +2520,7 @@ fn updateType(
.func = .none,
.func_sym_index = undefined,
.func_high_reloc = undefined,
.inlined_funcs_high_reloc = undefined,
.inlined_funcs = undefined,
.debug_info = .{},
.debug_line = .{},
.debug_loclists = .{},
@@ -2493,7 +2540,7 @@ fn updateType(
switch (ip.indexToKey(type_index)) {
.int_type => |int_type| {
try uleb128(diw, @intFromEnum(AbbrevCode.numeric_type));
try wip_nav.abbrevCode(.numeric_type);
try wip_nav.strp(name);
try diw.writeByte(switch (int_type.signedness) {
inline .signed, .unsigned => |signedness| @field(DW.ATE, @tagName(signedness)),
@@ -2505,7 +2552,7 @@ fn updateType(
.ptr_type => |ptr_type| switch (ptr_type.flags.size) {
.One, .Many, .C => {
const ptr_child_type = Type.fromInterned(ptr_type.child);
try uleb128(diw, @intFromEnum(AbbrevCode.ptr_type));
try wip_nav.abbrevCode(.ptr_type);
try wip_nav.strp(name);
try uleb128(diw, ptr_type.flags.alignment.toByteUnits() orelse
ptr_child_type.abiAlignment(pt).toByteUnits().?);
@@ -2517,7 +2564,7 @@ fn updateType(
@intCast(wip_nav.debug_info.items.len + dwarf.sectionOffsetBytes()),
) else try wip_nav.refType(ptr_child_type);
if (ptr_type.flags.is_const) {
try uleb128(diw, @intFromEnum(AbbrevCode.is_const));
try wip_nav.abbrevCode(.is_const);
if (ptr_type.flags.is_volatile) try wip_nav.infoSectionOffset(
.debug_info,
wip_nav.unit,
@@ -2526,21 +2573,21 @@ fn updateType(
) else try wip_nav.refType(ptr_child_type);
}
if (ptr_type.flags.is_volatile) {
try uleb128(diw, @intFromEnum(AbbrevCode.is_volatile));
try wip_nav.abbrevCode(.is_volatile);
try wip_nav.refType(ptr_child_type);
}
},
.Slice => {
try uleb128(diw, @intFromEnum(AbbrevCode.struct_type));
try wip_nav.abbrevCode(.struct_type);
try wip_nav.strp(name);
try uleb128(diw, ty.abiSize(pt));
try uleb128(diw, ty.abiAlignment(pt).toByteUnits().?);
try uleb128(diw, @intFromEnum(AbbrevCode.generated_field));
try wip_nav.abbrevCode(.generated_field);
try wip_nav.strp("ptr");
const ptr_field_type = ty.slicePtrFieldType(zcu);
try wip_nav.refType(ptr_field_type);
try uleb128(diw, 0);
try uleb128(diw, @intFromEnum(AbbrevCode.generated_field));
try wip_nav.abbrevCode(.generated_field);
try wip_nav.strp("len");
const len_field_type = Type.usize;
try wip_nav.refType(len_field_type);
@@ -2549,28 +2596,28 @@ fn updateType(
},
},
inline .array_type, .vector_type => |array_type, ty_tag| {
try uleb128(diw, @intFromEnum(AbbrevCode.array_type));
try wip_nav.abbrevCode(.array_type);
try wip_nav.strp(name);
try wip_nav.refType(Type.fromInterned(array_type.child));
try diw.writeByte(@intFromBool(ty_tag == .vector_type));
try uleb128(diw, @intFromEnum(AbbrevCode.array_index));
try wip_nav.abbrevCode(.array_index);
try wip_nav.refType(Type.usize);
try uleb128(diw, array_type.len);
try uleb128(diw, @intFromEnum(AbbrevCode.null));
},
.opt_type => |opt_child_type_index| {
const opt_child_type = Type.fromInterned(opt_child_type_index);
try uleb128(diw, @intFromEnum(AbbrevCode.union_type));
try wip_nav.abbrevCode(.union_type);
try wip_nav.strp(name);
try uleb128(diw, ty.abiSize(pt));
try uleb128(diw, ty.abiAlignment(pt).toByteUnits().?);
if (opt_child_type.isNoReturn(zcu)) {
try uleb128(diw, @intFromEnum(AbbrevCode.generated_field));
try wip_nav.abbrevCode(.generated_field);
try wip_nav.strp("null");
try wip_nav.refType(Type.null);
try uleb128(diw, 0);
} else {
try uleb128(diw, @intFromEnum(AbbrevCode.tagged_union));
try wip_nav.abbrevCode(.tagged_union);
try wip_nav.infoSectionOffset(
.debug_info,
wip_nav.unit,
@@ -2578,7 +2625,7 @@ fn updateType(
@intCast(wip_nav.debug_info.items.len + dwarf.sectionOffsetBytes()),
);
{
try uleb128(diw, @intFromEnum(AbbrevCode.generated_field));
try wip_nav.abbrevCode(.generated_field);
try wip_nav.strp("has_value");
const repr: enum { unpacked, error_set, pointer } = switch (opt_child_type_index) {
.anyerror_type => .error_set,
@@ -2609,19 +2656,19 @@ fn updateType(
},
}
try uleb128(diw, @intFromEnum(AbbrevCode.unsigned_tagged_union_field));
try wip_nav.abbrevCode(.unsigned_tagged_union_field);
try uleb128(diw, 0);
{
try uleb128(diw, @intFromEnum(AbbrevCode.generated_field));
try wip_nav.abbrevCode(.generated_field);
try wip_nav.strp("null");
try wip_nav.refType(Type.null);
try uleb128(diw, 0);
}
try uleb128(diw, @intFromEnum(AbbrevCode.null));
try uleb128(diw, @intFromEnum(AbbrevCode.tagged_union_default_field));
try wip_nav.abbrevCode(.tagged_union_default_field);
{
try uleb128(diw, @intFromEnum(AbbrevCode.generated_field));
try wip_nav.abbrevCode(.generated_field);
try wip_nav.strp("?");
try wip_nav.refType(opt_child_type);
try uleb128(diw, 0);
@@ -2644,7 +2691,7 @@ fn updateType(
},
};
try uleb128(diw, @intFromEnum(AbbrevCode.union_type));
try wip_nav.abbrevCode(.union_type);
try wip_nav.strp(name);
if (error_union_type.error_set_type != .generic_poison_type and
error_union_type.payload_type != .generic_poison_type)
@@ -2656,7 +2703,7 @@ fn updateType(
try uleb128(diw, 1);
}
{
try uleb128(diw, @intFromEnum(AbbrevCode.tagged_union));
try wip_nav.abbrevCode(.tagged_union);
try wip_nav.infoSectionOffset(
.debug_info,
wip_nav.unit,
@@ -2664,7 +2711,7 @@ fn updateType(
@intCast(wip_nav.debug_info.items.len + dwarf.sectionOffsetBytes()),
);
{
try uleb128(diw, @intFromEnum(AbbrevCode.generated_field));
try wip_nav.abbrevCode(.generated_field);
try wip_nav.strp("is_error");
try wip_nav.refType(Type.fromInterned(try pt.intern(.{ .int_type = .{
.signedness = .unsigned,
@@ -2672,19 +2719,19 @@ fn updateType(
} })));
try uleb128(diw, error_union_error_set_offset);
try uleb128(diw, @intFromEnum(AbbrevCode.unsigned_tagged_union_field));
try wip_nav.abbrevCode(.unsigned_tagged_union_field);
try uleb128(diw, 0);
{
try uleb128(diw, @intFromEnum(AbbrevCode.generated_field));
try wip_nav.abbrevCode(.generated_field);
try wip_nav.strp("value");
try wip_nav.refType(error_union_payload_type);
try uleb128(diw, error_union_payload_offset);
}
try uleb128(diw, @intFromEnum(AbbrevCode.null));
try uleb128(diw, @intFromEnum(AbbrevCode.tagged_union_default_field));
try wip_nav.abbrevCode(.tagged_union_default_field);
{
try uleb128(diw, @intFromEnum(AbbrevCode.generated_field));
try wip_nav.abbrevCode(.generated_field);
try wip_nav.strp("error");
try wip_nav.refType(error_union_error_set_type);
try uleb128(diw, error_union_error_set_offset);
@@ -2715,7 +2762,7 @@ fn updateType(
.c_longdouble,
.bool,
=> {
try uleb128(diw, @intFromEnum(AbbrevCode.numeric_type));
try wip_nav.abbrevCode(.numeric_type);
try wip_nav.strp(name);
try diw.writeByte(if (type_index == .bool_type)
DW.ATE.boolean
@@ -2742,7 +2789,7 @@ fn updateType(
.enum_literal,
.generic_poison,
=> {
try uleb128(diw, @intFromEnum(AbbrevCode.void_type));
try wip_nav.abbrevCode(.void_type);
try wip_nav.strp(if (type_index == .generic_poison_type) "anytype" else name);
},
.anyerror => return, // delay until flush
@@ -2752,15 +2799,19 @@ fn updateType(
.union_type,
.opaque_type,
=> unreachable,
.anon_struct_type => |anon_struct_type| {
try uleb128(diw, @intFromEnum(AbbrevCode.struct_type));
.anon_struct_type => |anon_struct_type| if (anon_struct_type.types.len == 0) {
try wip_nav.abbrevCode(.namespace_struct_type);
try wip_nav.strp(name);
try diw.writeByte(@intFromBool(false));
} else {
try wip_nav.abbrevCode(.struct_type);
try wip_nav.strp(name);
try uleb128(diw, ty.abiSize(pt));
try uleb128(diw, ty.abiAlignment(pt).toByteUnits().?);
var field_byte_offset: u64 = 0;
for (0..anon_struct_type.types.len) |field_index| {
const comptime_value = anon_struct_type.values.get(ip)[field_index];
try uleb128(diw, @intFromEnum(@as(AbbrevCode, if (comptime_value != .none) .struct_field_comptime else .struct_field)));
try wip_nav.abbrevCode(if (comptime_value != .none) .struct_field_comptime else .struct_field);
if (anon_struct_type.fieldName(ip, field_index).unwrap()) |field_name| try wip_nav.strp(field_name.toSlice(ip)) else {
const field_name = try std.fmt.allocPrint(dwarf.gpa, "{d}", .{field_index});
defer dwarf.gpa.free(field_name);
@@ -2780,7 +2831,7 @@ fn updateType(
},
.enum_type => {
const loaded_enum = ip.loadEnumType(type_index);
try uleb128(diw, @intFromEnum(AbbrevCode.enum_type));
try wip_nav.abbrevCode(.enum_type);
try wip_nav.strp(name);
try wip_nav.refType(Type.fromInterned(loaded_enum.tag_ty));
for (0..loaded_enum.names.len) |field_index| {
@@ -2794,7 +2845,7 @@ fn updateType(
},
.func_type => |func_type| {
const is_nullary = func_type.param_types.len == 0 and !func_type.is_var_args;
try uleb128(diw, @intFromEnum(@as(AbbrevCode, if (is_nullary) .nullary_func_type else .func_type)));
try wip_nav.abbrevCode(if (is_nullary) .nullary_func_type else .func_type);
try wip_nav.strp(name);
try diw.writeByte(@intFromEnum(@as(DW.CC, switch (func_type.cc) {
.Unspecified, .C => .normal,
@@ -2814,15 +2865,15 @@ fn updateType(
try wip_nav.refType(Type.fromInterned(func_type.return_type));
if (!is_nullary) {
for (0..func_type.param_types.len) |param_index| {
try uleb128(diw, @intFromEnum(AbbrevCode.func_type_param));
try wip_nav.abbrevCode(.func_type_param);
try wip_nav.refType(Type.fromInterned(func_type.param_types.get(ip)[param_index]));
}
if (func_type.is_var_args) try uleb128(diw, @intFromEnum(AbbrevCode.is_var_args));
if (func_type.is_var_args) try wip_nav.abbrevCode(.is_var_args);
try uleb128(diw, @intFromEnum(AbbrevCode.null));
}
},
.error_set_type => |error_set_type| {
try uleb128(diw, @intFromEnum(@as(AbbrevCode, if (error_set_type.names.len > 0) .enum_type else .empty_enum_type)));
try wip_nav.abbrevCode(if (error_set_type.names.len > 0) .enum_type else .empty_enum_type);
try wip_nav.strp(name);
try wip_nav.refType(Type.fromInterned(try pt.intern(.{ .int_type = .{
.signedness = .unsigned,
@@ -2830,7 +2881,7 @@ fn updateType(
} })));
for (0..error_set_type.names.len) |field_index| {
const field_name = error_set_type.names.get(ip)[field_index];
try uleb128(diw, @intFromEnum(AbbrevCode.unsigned_enum_field));
try wip_nav.abbrevCode(.unsigned_enum_field);
try uleb128(diw, ip.getErrorValueIfExists(field_name).?);
try wip_nav.strp(field_name.toSlice(ip));
}
@@ -2838,11 +2889,11 @@ fn updateType(
},
.inferred_error_set_type => |func| switch (ip.funcIesResolvedUnordered(func)) {
.none => {
try uleb128(diw, @intFromEnum(AbbrevCode.void_type));
try wip_nav.abbrevCode(.void_type);
try wip_nav.strp(name);
},
else => |ies| {
try uleb128(diw, @intFromEnum(AbbrevCode.inferred_error_set_type));
try wip_nav.abbrevCode(.inferred_error_set_type);
try wip_nav.strp(name);
try wip_nav.refType(Type.fromInterned(ies));
},
@@ -2894,7 +2945,7 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP
.func = .none,
.func_sym_index = undefined,
.func_high_reloc = undefined,
.inlined_funcs_high_reloc = undefined,
.inlined_funcs = undefined,
.debug_info = .{},
.debug_line = .{},
.debug_loclists = .{},
@@ -2905,7 +2956,7 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP
const loaded_struct = ip.loadStructType(type_index);
const diw = wip_nav.debug_info.writer(dwarf.gpa);
try uleb128(diw, @intFromEnum(@as(AbbrevCode, if (loaded_struct.field_types.len == 0) .namespace_file else .file)));
try wip_nav.abbrevCode(if (loaded_struct.field_types.len == 0) .namespace_file else .file);
const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, inst_info.file);
try uleb128(diw, file_gop.index);
try wip_nav.strp(loaded_struct.name.toSlice(ip));
@@ -2914,7 +2965,7 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP
try uleb128(diw, ty.abiAlignment(pt).toByteUnits().?);
for (0..loaded_struct.field_types.len) |field_index| {
const is_comptime = loaded_struct.fieldIsComptime(ip, field_index);
try uleb128(diw, @intFromEnum(@as(AbbrevCode, if (is_comptime) .struct_field_comptime else .struct_field)));
try wip_nav.abbrevCode(if (is_comptime) .struct_field_comptime else .struct_field);
if (loaded_struct.fieldName(ip, field_index).unwrap()) |field_name| try wip_nav.strp(field_name.toSlice(ip)) else {
const field_name = try std.fmt.allocPrint(dwarf.gpa, "{d}", .{field_index});
defer dwarf.gpa.free(field_name);
@@ -2957,7 +3008,7 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP
.func = .none,
.func_sym_index = undefined,
.func_high_reloc = undefined,
.inlined_funcs_high_reloc = undefined,
.inlined_funcs = undefined,
.debug_info = .{},
.debug_line = .{},
.debug_loclists = .{},
@@ -2973,17 +3024,14 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP
const loaded_struct = ip.loadStructType(type_index);
switch (loaded_struct.layout) {
.auto, .@"extern" => {
try uleb128(diw, @intFromEnum(@as(AbbrevCode, if (loaded_struct.field_types.len == 0)
.namespace_struct_type
else
.struct_type)));
try wip_nav.abbrevCode(if (loaded_struct.field_types.len == 0) .namespace_struct_type else .struct_type);
try wip_nav.strp(name);
if (loaded_struct.field_types.len == 0) try diw.writeByte(@intFromBool(false)) else {
try uleb128(diw, ty.abiSize(pt));
try uleb128(diw, ty.abiAlignment(pt).toByteUnits().?);
for (0..loaded_struct.field_types.len) |field_index| {
const is_comptime = loaded_struct.fieldIsComptime(ip, field_index);
try uleb128(diw, @intFromEnum(@as(AbbrevCode, if (is_comptime) .struct_field_comptime else .struct_field)));
try wip_nav.abbrevCode(if (is_comptime) .struct_field_comptime else .struct_field);
if (loaded_struct.fieldName(ip, field_index).unwrap()) |field_name| try wip_nav.strp(field_name.toSlice(ip)) else {
const field_name = try std.fmt.allocPrint(dwarf.gpa, "{d}", .{field_index});
defer dwarf.gpa.free(field_name);
@@ -3001,12 +3049,12 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP
}
},
.@"packed" => {
try uleb128(diw, @intFromEnum(AbbrevCode.packed_struct_type));
try wip_nav.abbrevCode(.packed_struct_type);
try wip_nav.strp(name);
try wip_nav.refType(Type.fromInterned(loaded_struct.backingIntTypeUnordered(ip)));
var field_bit_offset: u16 = 0;
for (0..loaded_struct.field_types.len) |field_index| {
try uleb128(diw, @intFromEnum(@as(AbbrevCode, .packed_struct_field)));
try wip_nav.abbrevCode(.packed_struct_field);
try wip_nav.strp(loaded_struct.fieldName(ip, field_index).unwrap().?.toSlice(ip));
const field_type = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]);
try wip_nav.refType(field_type);
@@ -3019,7 +3067,7 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP
},
.enum_type => {
const loaded_enum = ip.loadEnumType(type_index);
try uleb128(diw, @intFromEnum(AbbrevCode.enum_type));
try wip_nav.abbrevCode(.enum_type);
try wip_nav.strp(name);
try wip_nav.refType(Type.fromInterned(loaded_enum.tag_ty));
for (0..loaded_enum.names.len) |field_index| {
@@ -3033,14 +3081,14 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP
},
.union_type => {
const loaded_union = ip.loadUnionType(type_index);
try uleb128(diw, @intFromEnum(AbbrevCode.union_type));
try wip_nav.abbrevCode(.union_type);
try wip_nav.strp(name);
const union_layout = pt.getUnionLayout(loaded_union);
try uleb128(diw, union_layout.abi_size);
try uleb128(diw, union_layout.abi_align.toByteUnits().?);
const loaded_tag = loaded_union.loadTagType(ip);
if (loaded_union.hasTag(ip)) {
try uleb128(diw, @intFromEnum(AbbrevCode.tagged_union));
try wip_nav.abbrevCode(.tagged_union);
try wip_nav.infoSectionOffset(
.debug_info,
wip_nav.unit,
@@ -3048,7 +3096,7 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP
@intCast(wip_nav.debug_info.items.len + dwarf.sectionOffsetBytes()),
);
{
try uleb128(diw, @intFromEnum(AbbrevCode.generated_field));
try wip_nav.abbrevCode(.generated_field);
try wip_nav.strp("tag");
try wip_nav.refType(Type.fromInterned(loaded_union.enum_tag_ty));
try uleb128(diw, union_layout.tagOffset());
@@ -3059,7 +3107,7 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP
.unsigned = .unsigned_tagged_union_field,
}, field_index);
{
try uleb128(diw, @intFromEnum(AbbrevCode.struct_field));
try wip_nav.abbrevCode(.struct_field);
try wip_nav.strp(loaded_tag.names.get(ip)[field_index].toSlice(ip));
const field_type = Type.fromInterned(loaded_union.field_types.get(ip)[field_index]);
try wip_nav.refType(field_type);
@@ -3075,7 +3123,7 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP
if (ip.indexToKey(loaded_union.enum_tag_ty).enum_type == .generated_tag)
try wip_nav.pending_types.append(dwarf.gpa, loaded_union.enum_tag_ty);
} else for (0..loaded_union.field_types.len) |field_index| {
try uleb128(diw, @intFromEnum(AbbrevCode.untagged_union_field));
try wip_nav.abbrevCode(.untagged_union_field);
try wip_nav.strp(loaded_tag.names.get(ip)[field_index].toSlice(ip));
const field_type = Type.fromInterned(loaded_union.field_types.get(ip)[field_index]);
try wip_nav.refType(field_type);
@@ -3085,7 +3133,7 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP
try uleb128(diw, @intFromEnum(AbbrevCode.null));
},
.opaque_type => {
try uleb128(diw, @intFromEnum(AbbrevCode.namespace_struct_type));
try wip_nav.abbrevCode(.namespace_struct_type);
try wip_nav.strp(name);
try diw.writeByte(@intFromBool(true));
},
@@ -3121,6 +3169,23 @@ pub fn freeNav(dwarf: *Dwarf, nav_index: InternPool.Nav.Index) void {
_ = nav_index;
}
fn refAbbrevCode(dwarf: *Dwarf, abbrev_code: AbbrevCode) UpdateError!@typeInfo(AbbrevCode).Enum.tag_type {
assert(abbrev_code != .null);
const entry: Entry.Index = @enumFromInt(@intFromEnum(abbrev_code));
if (dwarf.debug_abbrev.section.getUnit(DebugAbbrev.unit).getEntry(entry).len > 0) return @intFromEnum(abbrev_code);
var debug_abbrev = std.ArrayList(u8).init(dwarf.gpa);
defer debug_abbrev.deinit();
const daw = debug_abbrev.writer();
const abbrev = AbbrevCode.abbrevs.get(abbrev_code);
try uleb128(daw, @intFromEnum(abbrev_code));
try uleb128(daw, @intFromEnum(abbrev.tag));
try daw.writeByte(if (abbrev.children) DW.CHILDREN.yes else DW.CHILDREN.no);
for (abbrev.attrs) |*attr| inline for (attr) |info| try uleb128(daw, @intFromEnum(info));
for (0..2) |_| try uleb128(daw, 0);
try dwarf.debug_abbrev.section.replaceEntry(DebugAbbrev.unit, entry, dwarf, debug_abbrev.items);
return @intFromEnum(abbrev_code);
}
pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
const ip = &pt.zcu.intern_pool;
if (dwarf.types.get(.anyerror_type)) |entry| {
@@ -3133,7 +3198,7 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
.func = .none,
.func_sym_index = undefined,
.func_high_reloc = undefined,
.inlined_funcs_high_reloc = undefined,
.inlined_funcs = undefined,
.debug_info = .{},
.debug_line = .{},
.debug_loclists = .{},
@@ -3142,14 +3207,14 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
defer wip_nav.deinit();
const diw = wip_nav.debug_info.writer(dwarf.gpa);
const global_error_set_names = ip.global_error_set.getNamesFromMainThread();
try uleb128(diw, @intFromEnum(@as(AbbrevCode, if (global_error_set_names.len > 0) .enum_type else .empty_enum_type)));
try wip_nav.abbrevCode(if (global_error_set_names.len > 0) .enum_type else .empty_enum_type);
try wip_nav.strp("anyerror");
try wip_nav.refType(Type.fromInterned(try pt.intern(.{ .int_type = .{
.signedness = .unsigned,
.bits = pt.zcu.errorSetBits(),
} })));
for (global_error_set_names, 1..) |name, value| {
try uleb128(diw, @intFromEnum(AbbrevCode.unsigned_enum_field));
try wip_nav.abbrevCode(.unsigned_enum_field);
try uleb128(diw, value);
try wip_nav.strp(name.toSlice(ip));
}
@@ -3173,21 +3238,6 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
var header = std.ArrayList(u8).init(dwarf.gpa);
defer header.deinit();
if (dwarf.debug_abbrev.section.dirty) {
for (1.., &AbbrevCode.abbrevs) |code, *abbrev| {
try uleb128(header.writer(), code);
try uleb128(header.writer(), @intFromEnum(abbrev.tag));
try header.append(if (abbrev.children) DW.CHILDREN.yes else DW.CHILDREN.no);
for (abbrev.attrs) |*attr| {
try uleb128(header.writer(), @intFromEnum(attr[0]));
try uleb128(header.writer(), @intFromEnum(attr[1]));
}
try header.appendSlice(&.{ 0, 0 });
}
try header.append(@intFromEnum(AbbrevCode.null));
try dwarf.debug_abbrev.section.replaceEntry(DebugAbbrev.unit, DebugAbbrev.entry, dwarf, header.items);
dwarf.debug_abbrev.section.dirty = false;
}
if (dwarf.debug_aranges.section.dirty) {
for (dwarf.debug_aranges.section.units.items, 0..) |*unit_ptr, unit_index| {
const unit: Unit.Index = @enumFromInt(unit_index);
@@ -3245,11 +3295,10 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
.source_off = @intCast(header.items.len),
.target_sec = .debug_abbrev,
.target_unit = DebugAbbrev.unit,
.target_entry = DebugAbbrev.entry.toOptional(),
});
header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes());
const compile_unit_off: u32 = @intCast(header.items.len);
uleb128(header.fixedWriter(), @intFromEnum(AbbrevCode.compile_unit)) catch unreachable;
uleb128(header.fixedWriter(), try dwarf.refAbbrevCode(.compile_unit)) catch unreachable;
header.appendAssumeCapacity(DW.LANG.Zig);
unit_ptr.cross_section_relocs.appendAssumeCapacity(.{
.source_off = @intCast(header.items.len),
@@ -3292,7 +3341,7 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
});
header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes());
uleb128(header.fixedWriter(), 0) catch unreachable;
uleb128(header.fixedWriter(), @intFromEnum(AbbrevCode.module)) catch unreachable;
uleb128(header.fixedWriter(), try dwarf.refAbbrevCode(.module)) catch unreachable;
unit_ptr.cross_section_relocs.appendAssumeCapacity(.{
.source_off = @intCast(header.items.len),
.target_sec = .debug_str,
@@ -3306,6 +3355,11 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
}
dwarf.debug_info.section.dirty = false;
}
if (dwarf.debug_abbrev.section.dirty) {
assert(!dwarf.debug_info.section.dirty);
try dwarf.debug_abbrev.section.getUnit(DebugAbbrev.unit).writeTrailer(&dwarf.debug_abbrev.section, dwarf);
dwarf.debug_abbrev.section.dirty = false;
}
if (dwarf.debug_str.section.dirty) {
const contents = dwarf.debug_str.contents.items;
try dwarf.debug_str.section.resize(dwarf, contents.len);
@@ -3313,8 +3367,11 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
dwarf.debug_str.section.dirty = false;
}
if (dwarf.debug_line.section.dirty) {
for (dwarf.mods.values(), dwarf.debug_line.section.units.items) |mod_info, *unit|
try unit.resizeHeader(&dwarf.debug_line.section, dwarf, DebugLine.headerBytes(dwarf, @intCast(mod_info.dirs.count()), @intCast(mod_info.files.count())));
for (dwarf.mods.values(), dwarf.debug_line.section.units.items) |mod_info, *unit| try unit.resizeHeader(
&dwarf.debug_line.section,
dwarf,
DebugLine.headerBytes(dwarf, @intCast(mod_info.dirs.count()), @intCast(mod_info.files.count())),
);
for (dwarf.mods.values(), dwarf.debug_line.section.units.items) |mod_info, *unit| {
unit.clear();
try unit.cross_section_relocs.ensureTotalCapacity(dwarf.gpa, 2 * (1 + mod_info.files.count()));
@@ -3333,14 +3390,7 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
}
std.mem.writeInt(u16, header.addManyAsArrayAssumeCapacity(@sizeOf(u16)), 5, dwarf.endian);
header.appendSliceAssumeCapacity(&.{ @intFromEnum(dwarf.address_size), 0 });
switch (dwarf.format) {
inline .@"32", .@"64" => |format| std.mem.writeInt(
SectionOffset(format),
header.addManyAsArrayAssumeCapacity(@sizeOf(SectionOffset(format))),
@intCast(unit.header_len - header.items.len),
dwarf.endian,
),
}
dwarf.writeInt(header.addManyAsSliceAssumeCapacity(dwarf.sectionOffsetBytes()), unit.header_len - header.items.len);
const StandardOpcode = DeclValEnum(DW.LNS);
header.appendSliceAssumeCapacity(&[_]u8{
dwarf.debug_line.header.minimum_instruction_length,
@@ -3422,6 +3472,9 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
try dwarf.getFile().?.pwriteAll(contents, dwarf.debug_line_str.section.off);
dwarf.debug_line_str.section.dirty = false;
}
if (dwarf.debug_loclists.section.dirty) {
dwarf.debug_loclists.section.dirty = false;
}
if (dwarf.debug_rnglists.section.dirty) {
for (dwarf.debug_rnglists.section.units.items) |*unit| {
header.clearRetainingCapacity();
@@ -3440,19 +3493,20 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
std.mem.writeInt(u16, header.addManyAsArrayAssumeCapacity(@sizeOf(u16)), 5, dwarf.endian);
header.appendSliceAssumeCapacity(&.{ @intFromEnum(dwarf.address_size), 0 });
std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(@sizeOf(u32)), 1, dwarf.endian);
switch (dwarf.format) {
inline .@"32", .@"64" => |format| std.mem.writeInt(
SectionOffset(format),
header.addManyAsArrayAssumeCapacity(@sizeOf(SectionOffset(format))),
@sizeOf(SectionOffset(format)),
dwarf.endian,
),
}
dwarf.writeInt(header.addManyAsSliceAssumeCapacity(dwarf.sectionOffsetBytes()), dwarf.sectionOffsetBytes() * 1);
try unit.replaceHeader(&dwarf.debug_rnglists.section, dwarf, header.items);
try unit.writeTrailer(&dwarf.debug_rnglists.section, dwarf);
}
dwarf.debug_rnglists.section.dirty = false;
}
assert(!dwarf.debug_abbrev.section.dirty);
assert(!dwarf.debug_aranges.section.dirty);
assert(!dwarf.debug_info.section.dirty);
assert(!dwarf.debug_line.section.dirty);
assert(!dwarf.debug_line_str.section.dirty);
assert(!dwarf.debug_loclists.section.dirty);
assert(!dwarf.debug_rnglists.section.dirty);
assert(!dwarf.debug_str.section.dirty);
}
pub fn resolveRelocs(dwarf: *Dwarf) RelocError!void {
@@ -3491,7 +3545,7 @@ fn DeclValEnum(comptime T: type) type {
} });
}
const AbbrevCode = enum(u8) {
const AbbrevCode = enum {
null,
// padding codes must be one byte uleb128 values to function
pad_1,
@@ -3499,15 +3553,16 @@ const AbbrevCode = enum(u8) {
// decl codes are assumed to all have the same uleb128 length
decl_alias,
decl_enum,
decl_empty_enum,
decl_namespace_struct,
decl_struct,
decl_packed_struct,
decl_union,
decl_var,
decl_func,
decl_func_empty,
decl_empty_func,
decl_func_generic,
decl_func_generic_empty,
decl_empty_func_generic,
// the rest are unrestricted
compile_unit,
module,
@@ -3542,11 +3597,12 @@ const AbbrevCode = enum(u8) {
struct_type,
packed_struct_type,
union_type,
empty_inlined_func,
inlined_func,
local_arg,
local_var,
const decl_bytes = uleb128Bytes(@intFromEnum(AbbrevCode.decl_func_generic_empty));
const decl_bytes = uleb128Bytes(@intFromEnum(AbbrevCode.decl_empty_func_generic));
const Attr = struct {
DeclValEnum(DW.AT),
@@ -3586,6 +3642,12 @@ const AbbrevCode = enum(u8) {
.{ .type, .ref_addr },
},
},
.decl_empty_enum = .{
.tag = .enumeration_type,
.attrs = decl_abbrev_common_attrs ++ .{
.{ .type, .ref_addr },
},
},
.decl_namespace_struct = .{
.tag = .structure_type,
.attrs = decl_abbrev_common_attrs ++ .{
@@ -3638,7 +3700,7 @@ const AbbrevCode = enum(u8) {
.{ .noreturn, .flag },
},
},
.decl_func_empty = .{
.decl_empty_func = .{
.tag = .subprogram,
.attrs = decl_abbrev_common_attrs ++ .{
.{ .linkage_name, .strp },
@@ -3657,7 +3719,7 @@ const AbbrevCode = enum(u8) {
.{ .type, .ref_addr },
},
},
.decl_func_generic_empty = .{
.decl_empty_func_generic = .{
.tag = .subprogram,
.attrs = decl_abbrev_common_attrs ++ .{
.{ .type, .ref_addr },
@@ -3918,6 +3980,16 @@ const AbbrevCode = enum(u8) {
.{ .alignment, .udata },
},
},
.empty_inlined_func = .{
.tag = .inlined_subroutine,
.attrs = &.{
.{ .abstract_origin, .ref_addr },
.{ .call_line, .udata },
.{ .call_column, .udata },
.{ .low_pc, .addr },
.{ .high_pc, .addr },
},
},
.inlined_func = .{
.tag = .inlined_subroutine,
.children = true,
@@ -3946,7 +4018,7 @@ const AbbrevCode = enum(u8) {
},
},
.null = undefined,
}).values[1..].*;
});
};
fn getFile(dwarf: *Dwarf) ?std.fs.File {
@@ -3955,11 +4027,11 @@ fn getFile(dwarf: *Dwarf) ?std.fs.File {
}
fn addCommonEntry(dwarf: *Dwarf, unit: Unit.Index) UpdateError!Entry.Index {
const entry = try dwarf.debug_aranges.section.addEntry(unit, dwarf);
assert(try dwarf.debug_info.section.addEntry(unit, dwarf) == entry);
assert(try dwarf.debug_line.section.addEntry(unit, dwarf) == entry);
assert(try dwarf.debug_loclists.section.addEntry(unit, dwarf) == entry);
assert(try dwarf.debug_rnglists.section.addEntry(unit, dwarf) == entry);
const entry = try dwarf.debug_aranges.section.getUnit(unit).addEntry(dwarf.gpa);
assert(try dwarf.debug_info.section.getUnit(unit).addEntry(dwarf.gpa) == entry);
assert(try dwarf.debug_line.section.getUnit(unit).addEntry(dwarf.gpa) == entry);
assert(try dwarf.debug_loclists.section.getUnit(unit).addEntry(dwarf.gpa) == entry);
assert(try dwarf.debug_rnglists.section.getUnit(unit).addEntry(dwarf.gpa) == entry);
return entry;
}
@@ -3993,13 +4065,6 @@ fn sectionOffsetBytes(dwarf: *Dwarf) u32 {
};
}
fn SectionOffset(comptime format: DW.Format) type {
return switch (format) {
.@"32" => u32,
.@"64" => u64,
};
}
fn uleb128Bytes(value: anytype) u32 {
var cw = std.io.countingWriter(std.io.null_writer);
try uleb128(cw.writer(), value);