From 94dd28b7f7bdbbebe652d3e7a791bc86591ed9c8 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 7 Aug 2025 22:06:20 -0700 Subject: [PATCH 1/4] std.Io: delete CountingWriter --- lib/compiler/resinator/cvtres.zig | 11 ++------ lib/std/Io.zig | 5 ---- lib/std/Io/counting_writer.zig | 39 ----------------------------- lib/std/crypto/phc_encoding.zig | 16 ++++++------ lib/std/crypto/scrypt.zig | 7 +++--- src/arch/x86_64/encoder.zig | 7 +++--- src/link/Elf.zig | 9 ++++--- src/link/Elf/synthetic_sections.zig | 21 ++++++---------- src/link/MachO/dyld_info/Trie.zig | 15 +++++------ 9 files changed, 39 insertions(+), 91 deletions(-) delete mode 100644 lib/std/Io/counting_writer.zig diff --git a/lib/compiler/resinator/cvtres.zig b/lib/compiler/resinator/cvtres.zig index 27e14ae9a3..e181b9390e 100644 --- a/lib/compiler/resinator/cvtres.zig +++ b/lib/compiler/resinator/cvtres.zig @@ -665,19 +665,16 @@ const ResourceTree = struct { pub fn writeCoff( self: *const ResourceTree, allocator: Allocator, - writer: anytype, + w: anytype, resources_in_data_order: []const Resource, lengths: Lengths, coff_string_table: *StringTable, ) ![]const std.coff.Symbol { if (self.type_to_name_map.count() == 0) { - try writer.writeByteNTimes(0, 16); + try w.writeByteNTimes(0, 16); return &.{}; } - var counting_writer = std.io.countingWriter(writer); - const w = counting_writer.writer(); - var level2_list: std.ArrayListUnmanaged(*const NameToLanguageMap) = .empty; defer level2_list.deinit(allocator); @@ -735,7 +732,6 @@ const ResourceTree = struct { try level2_list.append(allocator, name_to_lang_map); } } - std.debug.assert(counting_writer.bytes_written == level2_start); const level3_start = level2_start + lengths.level2; var level3_address = level3_start; @@ -771,7 +767,6 @@ const ResourceTree = struct { try level3_list.append(allocator, lang_to_resources_map); } } - std.debug.assert(counting_writer.bytes_written == level3_start); var reloc_addresses = try allocator.alloc(u32, resources_in_data_order.len); defer allocator.free(reloc_addresses); @@ -813,7 +808,6 @@ const ResourceTree = struct { try resources_list.append(allocator, reloc_resource); } } - std.debug.assert(counting_writer.bytes_written == data_entries_start); for (resources_list.items, 0..) |reloc_resource, i| { // TODO: This logic works but is convoluted, would be good to clean this up @@ -827,7 +821,6 @@ const ResourceTree = struct { }; try w.writeStructEndian(data_entry, .little); } - std.debug.assert(counting_writer.bytes_written == strings_start); for (self.rsrc_string_table.keys()) |v| { const str = v.name; diff --git a/lib/std/Io.zig b/lib/std/Io.zig index 746a457c5b..3ad511242b 100644 --- a/lib/std/Io.zig +++ b/lib/std/Io.zig @@ -432,10 +432,6 @@ pub const FixedBufferStream = @import("Io/fixed_buffer_stream.zig").FixedBufferS /// Deprecated in favor of `Reader`. pub const fixedBufferStream = @import("Io/fixed_buffer_stream.zig").fixedBufferStream; /// Deprecated with no replacement; inefficient pattern -pub const CountingWriter = @import("Io/counting_writer.zig").CountingWriter; -/// Deprecated with no replacement; inefficient pattern -pub const countingWriter = @import("Io/counting_writer.zig").countingWriter; -/// Deprecated with no replacement; inefficient pattern pub const CountingReader = @import("Io/counting_reader.zig").CountingReader; /// Deprecated with no replacement; inefficient pattern pub const countingReader = @import("Io/counting_reader.zig").countingReader; @@ -917,7 +913,6 @@ test { _ = Reader; _ = Writer; _ = BufferedWriter; - _ = CountingWriter; _ = CountingReader; _ = FixedBufferStream; _ = tty; diff --git a/lib/std/Io/counting_writer.zig b/lib/std/Io/counting_writer.zig deleted file mode 100644 index 32c3ed930f..0000000000 --- a/lib/std/Io/counting_writer.zig +++ /dev/null @@ -1,39 +0,0 @@ -const std = @import("../std.zig"); -const io = std.io; -const testing = std.testing; - -/// A Writer that counts how many bytes has been written to it. -pub fn CountingWriter(comptime WriterType: type) type { - return struct { - bytes_written: u64, - child_stream: WriterType, - - pub const Error = WriterType.Error; - pub const Writer = io.GenericWriter(*Self, Error, write); - - const Self = @This(); - - pub fn write(self: *Self, bytes: []const u8) Error!usize { - const amt = try self.child_stream.write(bytes); - self.bytes_written += amt; - return amt; - } - - pub fn writer(self: *Self) Writer { - return .{ .context = self }; - } - }; -} - -pub fn countingWriter(child_stream: anytype) CountingWriter(@TypeOf(child_stream)) { - return .{ .bytes_written = 0, .child_stream = child_stream }; -} - -test CountingWriter { - var counting_stream = countingWriter(std.io.null_writer); - const stream = counting_stream.writer(); - - const bytes = "yay" ** 100; - stream.writeAll(bytes) catch unreachable; - try testing.expect(counting_stream.bytes_written == bytes.len); -} diff --git a/lib/std/crypto/phc_encoding.zig b/lib/std/crypto/phc_encoding.zig index 507a02b983..e53977b42b 100644 --- a/lib/std/crypto/phc_encoding.zig +++ b/lib/std/crypto/phc_encoding.zig @@ -5,6 +5,7 @@ const fmt = std.fmt; const io = std.io; const mem = std.mem; const meta = std.meta; +const Writer = std.Io.Writer; const fields_delimiter = "$"; const fields_delimiter_scalar = '$'; @@ -188,19 +189,20 @@ pub fn deserialize(comptime HashResult: type, str: []const u8) Error!HashResult /// /// `params` can also include any additional parameters. pub fn serialize(params: anytype, str: []u8) Error![]const u8 { - var buf = io.fixedBufferStream(str); - try serializeTo(params, buf.writer()); - return buf.getWritten(); + var w: Writer = .fixed(str); + serializeTo(params, &w) catch return error.NoSpaceLeft; + return w.buffered(); } /// Compute the number of bytes required to serialize `params` pub fn calcSize(params: anytype) usize { - var buf = io.countingWriter(io.null_writer); - serializeTo(params, buf.writer()) catch unreachable; - return @as(usize, @intCast(buf.bytes_written)); + var trash: [128]u8 = undefined; + var d: Writer.Discarding = .init(&trash); + serializeTo(params, &d.writer) catch unreachable; + return @intCast(d.fullCount()); } -fn serializeTo(params: anytype, out: anytype) !void { +fn serializeTo(params: anytype, out: *std.Io.Writer) !void { const HashResult = @TypeOf(params); if (@hasField(HashResult, version_param_name)) { diff --git a/lib/std/crypto/scrypt.zig b/lib/std/crypto/scrypt.zig index 23202e7937..f12306a1dc 100644 --- a/lib/std/crypto/scrypt.zig +++ b/lib/std/crypto/scrypt.zig @@ -311,9 +311,10 @@ const crypt_format = struct { /// Compute the number of bytes required to serialize `params` pub fn calcSize(params: anytype) usize { - var buf = io.countingWriter(io.null_writer); - serializeTo(params, buf.writer()) catch unreachable; - return @as(usize, @intCast(buf.bytes_written)); + var trash: [128]u8 = undefined; + var d: std.Io.Writer.Discarding = .init(&trash); + serializeTo(params, &d) catch unreachable; + return @intCast(d.fullCount()); } fn serializeTo(params: anytype, out: anytype) !void { diff --git a/src/arch/x86_64/encoder.zig b/src/arch/x86_64/encoder.zig index 43d23af5fc..ed31c068dc 100644 --- a/src/arch/x86_64/encoder.zig +++ b/src/arch/x86_64/encoder.zig @@ -1204,11 +1204,10 @@ const TestEncode = struct { mnemonic: Instruction.Mnemonic, ops: []const Instruction.Operand, ) !void { - var stream = std.io.fixedBufferStream(&enc.buffer); - var count_writer = std.io.countingWriter(stream.writer()); + var writer: std.Io.Writer = .fixed(&enc.buffer); const inst: Instruction = try .new(.none, mnemonic, ops); - try inst.encode(count_writer.writer(), .{}); - enc.index = count_writer.bytes_written; + try inst.encode(&writer, .{}); + enc.index = writer.bufferedLen(); } fn code(enc: TestEncode) []const u8 { diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 785f200928..be6c050e5e 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -3152,10 +3152,11 @@ fn writeSyntheticSections(self: *Elf) !void { if (self.section_indexes.gnu_hash) |shndx| { const shdr = slice.items(.shdr)[shndx]; - var buffer = try std.ArrayList(u8).initCapacity(gpa, self.gnu_hash.size()); - defer buffer.deinit(); - try self.gnu_hash.write(self, buffer.writer()); - try self.pwriteAll(buffer.items, shdr.sh_offset); + var aw: std.Io.Writer.Allocating = .init(gpa); + try aw.ensureUnusedCapacity(self.gnu_hash.size()); + defer aw.deinit(); + try self.gnu_hash.write(self, &aw.writer); + try self.pwriteAll(aw.getWritten(), shdr.sh_offset); } if (self.section_indexes.versym) |shndx| { diff --git a/src/link/Elf/synthetic_sections.zig b/src/link/Elf/synthetic_sections.zig index 2ab71d8c49..efad44f68b 100644 --- a/src/link/Elf/synthetic_sections.zig +++ b/src/link/Elf/synthetic_sections.zig @@ -1237,17 +1237,14 @@ pub const GnuHashSection = struct { return header_size + hash.num_bloom * 8 + hash.num_buckets * 4 + hash.num_exports * 4; } - pub fn write(hash: GnuHashSection, elf_file: *Elf, writer: anytype) !void { + pub fn write(hash: GnuHashSection, elf_file: *Elf, writer: *std.Io.Writer) !void { const exports = getExports(elf_file); const export_off = elf_file.dynsym.count() - hash.num_exports; - var counting = std.io.countingWriter(writer); - const cwriter = counting.writer(); - - try cwriter.writeInt(u32, hash.num_buckets, .little); - try cwriter.writeInt(u32, export_off, .little); - try cwriter.writeInt(u32, hash.num_bloom, .little); - try cwriter.writeInt(u32, bloom_shift, .little); + try writer.writeInt(u32, hash.num_buckets, .little); + try writer.writeInt(u32, export_off, .little); + try writer.writeInt(u32, hash.num_bloom, .little); + try writer.writeInt(u32, bloom_shift, .little); const comp = elf_file.base.comp; const gpa = comp.gpa; @@ -1271,7 +1268,7 @@ pub const GnuHashSection = struct { bloom[idx] |= @as(u64, 1) << @as(u6, @intCast((h >> bloom_shift) % 64)); } - try cwriter.writeAll(mem.sliceAsBytes(bloom)); + try writer.writeAll(mem.sliceAsBytes(bloom)); // Fill in the hash bucket indices const buckets = try gpa.alloc(u32, hash.num_buckets); @@ -1284,7 +1281,7 @@ pub const GnuHashSection = struct { } } - try cwriter.writeAll(mem.sliceAsBytes(buckets)); + try writer.writeAll(mem.sliceAsBytes(buckets)); // Finally, write the hash table const table = try gpa.alloc(u32, hash.num_exports); @@ -1300,9 +1297,7 @@ pub const GnuHashSection = struct { } } - try cwriter.writeAll(mem.sliceAsBytes(table)); - - assert(counting.bytes_written == hash.size()); + try writer.writeAll(mem.sliceAsBytes(table)); } pub fn hasher(name: [:0]const u8) u32 { diff --git a/src/link/MachO/dyld_info/Trie.zig b/src/link/MachO/dyld_info/Trie.zig index ce56101e54..d96f2a54c8 100644 --- a/src/link/MachO/dyld_info/Trie.zig +++ b/src/link/MachO/dyld_info/Trie.zig @@ -186,17 +186,18 @@ const FinalizeNodeResult = struct { /// Updates offset of this node in the output byte stream. fn finalizeNode(self: *Trie, node_index: Node.Index, offset_in_trie: u32) !FinalizeNodeResult { - var stream = std.io.countingWriter(std.io.null_writer); - const writer = stream.writer(); + var trash_buffer: [64]u8 = undefined; + var stream: std.Io.Writer.Discarding = .init(&trash_buffer); + const writer = &stream.writer; const slice = self.nodes.slice(); var node_size: u32 = 0; if (slice.items(.is_terminal)[node_index]) { const export_flags = slice.items(.export_flags)[node_index]; const vmaddr_offset = slice.items(.vmaddr_offset)[node_index]; - try leb.writeUleb128(writer, export_flags); - try leb.writeUleb128(writer, vmaddr_offset); - try leb.writeUleb128(writer, stream.bytes_written); + try writer.writeUleb128(export_flags); + try writer.writeUleb128(vmaddr_offset); + try writer.writeUleb128(stream.fullCount()); } else { node_size += 1; // 0x0 for non-terminal nodes } @@ -206,13 +207,13 @@ fn finalizeNode(self: *Trie, node_index: Node.Index, offset_in_trie: u32) !Final const edge = &self.edges.items[edge_index]; const next_node_offset = slice.items(.trie_offset)[edge.node]; node_size += @intCast(edge.label.len + 1); - try leb.writeUleb128(writer, next_node_offset); + try writer.writeUleb128(next_node_offset); } const trie_offset = slice.items(.trie_offset)[node_index]; const updated = offset_in_trie != trie_offset; slice.items(.trie_offset)[node_index] = offset_in_trie; - node_size += @intCast(stream.bytes_written); + node_size += @intCast(stream.fullCount()); return .{ .node_size = node_size, .updated = updated }; } From c5a5983150c41843f30e136471e77fd3623a7510 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 7 Aug 2025 22:05:50 -0700 Subject: [PATCH 2/4] random patches from another branch --- src/link/Dwarf.zig | 1351 +++++++++++++++++++++++--------------------- 1 file changed, 715 insertions(+), 636 deletions(-) diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index f11ebc94d4..06c99ebcae 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -1,4 +1,4 @@ -gpa: std.mem.Allocator, +gpa: Allocator, bin_file: *link.File, format: DW.Format, endian: std.builtin.Endian, @@ -50,7 +50,7 @@ const ModInfo = struct { dirs: std.AutoArrayHashMapUnmanaged(Unit.Index, void), files: std.AutoArrayHashMapUnmanaged(Zcu.File.Index, void), - fn deinit(mod_info: *ModInfo, gpa: std.mem.Allocator) void { + fn deinit(mod_info: *ModInfo, gpa: Allocator) void { mod_info.dirs.deinit(gpa); mod_info.files.deinit(gpa); mod_info.* = undefined; @@ -220,13 +220,13 @@ const StringSection = struct { .section = Section.init, }; - fn deinit(str_sec: *StringSection, gpa: std.mem.Allocator) void { + fn deinit(str_sec: *StringSection, gpa: Allocator) void { str_sec.contents.deinit(gpa); str_sec.map.deinit(gpa); str_sec.section.deinit(gpa); } - fn addString(str_sec: *StringSection, dwarf: *Dwarf, str: []const u8) UpdateError!Entry.Index { + fn addString(str_sec: *StringSection, dwarf: *Dwarf, str: []const u8) !Entry.Index { const gop = try str_sec.map.getOrPutAdapted(dwarf.gpa, str, Adapter{ .str_sec = str_sec }); const entry: Entry.Index = @enumFromInt(gop.index); if (!gop.found_existing) { @@ -297,7 +297,7 @@ pub const Section = struct { .len = 0, }; - fn deinit(sec: *Section, gpa: std.mem.Allocator) void { + fn deinit(sec: *Section, gpa: Allocator) void { for (sec.units.items) |*unit| unit.deinit(gpa); sec.units.deinit(gpa); sec.* = undefined; @@ -357,7 +357,7 @@ pub const Section = struct { if (sec.last == unit.toOptional()) sec.last = unit_ptr.prev; } - fn popUnit(sec: *Section, gpa: std.mem.Allocator) void { + fn popUnit(sec: *Section, gpa: Allocator) void { const unit_index: Unit.Index = @enumFromInt(sec.units.items.len - 1); sec.unlinkUnit(unit_index); var unit = sec.units.pop().?; @@ -518,7 +518,7 @@ const Unit = struct { unit.cross_section_relocs.clearRetainingCapacity(); } - fn deinit(unit: *Unit, gpa: std.mem.Allocator) void { + fn deinit(unit: *Unit, gpa: Allocator) void { for (unit.entries.items) |*entry| entry.deinit(gpa); unit.entries.deinit(gpa); unit.cross_unit_relocs.deinit(gpa); @@ -526,7 +526,7 @@ const Unit = struct { unit.* = undefined; } - fn addEntry(unit: *Unit, gpa: std.mem.Allocator) std.mem.Allocator.Error!Entry.Index { + fn addEntry(unit: *Unit, gpa: Allocator) Allocator.Error!Entry.Index { if (unit.free.unwrap()) |entry| { const entry_ptr = unit.getEntry(entry); unit.free = entry_ptr.next; @@ -648,35 +648,33 @@ const Unit = struct { 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 bw: Writer = .fixed(&buf); + bw.writeByte(DW.LNS.extended_op) catch unreachable; + const extended_op_bytes = bw.end; 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, + .lt => break bw.writeLeb128(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; + std.leb.writeUnsignedExtended((bw.writableSlice(op_len_bytes) catch unreachable), len - extended_op_bytes - 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(dwarf) + start); + assert(bw.end == extended_op_bytes + op_len_bytes); + bw.writeByte(DW.LNE.padding) catch unreachable; + assert(bw.end >= unit.trailer_len and bw.end <= len); + return dwarf.getFile().?.pwriteAll(bw.getWritten(), sec.off(dwarf) + start); } - var trailer = try std.ArrayList(u8).initCapacity(dwarf.gpa, len); - defer trailer.deinit(); + var trailer_bw: Writer = .fixed(try dwarf.gpa.alloc(u8, len)); + defer dwarf.gpa.free(trailer_bw.buffer); const fill_byte: u8 = if (sec == &dwarf.debug_abbrev.section) fill: { assert(uleb128Bytes(@intFromEnum(AbbrevCode.null)) == 1); - trailer.appendAssumeCapacity(@intFromEnum(AbbrevCode.null)); + trailer_bw.writeByte(@intFromEnum(AbbrevCode.null)) catch unreachable; break :fill @intFromEnum(AbbrevCode.null); } else if (sec == &dwarf.debug_aranges.section) fill: { - trailer.appendNTimesAssumeCapacity(0, @intFromEnum(dwarf.address_size) * 2); + trailer_bw.splatByteAll(0, @intFromEnum(dwarf.address_size) * 2) catch unreachable; break :fill 0; } else if (sec == &dwarf.debug_frame.section) fill: { switch (dwarf.debug_frame.header.format) { @@ -684,49 +682,49 @@ const Unit = struct { .debug_frame, .eh_frame => |format| { const unit_len = len - dwarf.unitLengthBytes(); switch (dwarf.format) { - .@"32" => std.mem.writeInt(u32, trailer.addManyAsArrayAssumeCapacity(4), @intCast(unit_len), dwarf.endian), + .@"32" => trailer_bw.writeInt(u32, @intCast(unit_len), dwarf.endian) catch unreachable, .@"64" => { - std.mem.writeInt(u32, trailer.addManyAsArrayAssumeCapacity(4), std.math.maxInt(u32), dwarf.endian); - std.mem.writeInt(u64, trailer.addManyAsArrayAssumeCapacity(8), unit_len, dwarf.endian); + trailer_bw.writeInt(u32, std.math.maxInt(u32), dwarf.endian) catch unreachable; + trailer_bw.writeInt(u64, unit_len, dwarf.endian) catch unreachable; }, } switch (format) { .none => unreachable, .debug_frame => { switch (dwarf.format) { - .@"32" => std.mem.writeInt(u32, trailer.addManyAsArrayAssumeCapacity(4), std.math.maxInt(u32), dwarf.endian), - .@"64" => std.mem.writeInt(u64, trailer.addManyAsArrayAssumeCapacity(8), std.math.maxInt(u64), dwarf.endian), + .@"32" => trailer_bw.writeInt(u32, std.math.maxInt(u32), dwarf.endian) catch unreachable, + .@"64" => trailer_bw.writeInt(u64, std.math.maxInt(u64), dwarf.endian) catch unreachable, } - trailer.appendAssumeCapacity(4); - trailer.appendSliceAssumeCapacity("\x00"); - trailer.appendAssumeCapacity(@intFromEnum(dwarf.address_size)); - trailer.appendAssumeCapacity(0); + trailer_bw.writeByte(4) catch unreachable; + trailer_bw.writeAll("\x00") catch unreachable; + trailer_bw.writeByte(@intFromEnum(dwarf.address_size)) catch unreachable; + trailer_bw.writeByte(0) catch unreachable; }, .eh_frame => { - std.mem.writeInt(u32, trailer.addManyAsArrayAssumeCapacity(4), 0, dwarf.endian); - trailer.appendAssumeCapacity(1); - trailer.appendSliceAssumeCapacity("\x00"); + trailer_bw.writeInt(u32, 0, dwarf.endian) catch unreachable; + trailer_bw.writeByte(1) catch unreachable; + trailer_bw.writeAll("\x00") catch unreachable; }, } - uleb128(trailer.fixedWriter(), 1) catch unreachable; - sleb128(trailer.fixedWriter(), 1) catch unreachable; - uleb128(trailer.fixedWriter(), 0) catch unreachable; + trailer_bw.writeUleb128(1) catch unreachable; + trailer_bw.writeSleb128(1) catch unreachable; + trailer_bw.writeUleb128(0) catch unreachable; }, } - trailer.appendNTimesAssumeCapacity(DW.CFA.nop, unit.trailer_len - trailer.items.len); + trailer_bw.splatByteAll(DW.CFA.nop, unit.trailer_len - trailer_bw.end) catch unreachable; break :fill DW.CFA.nop; } else if (sec == &dwarf.debug_info.section) fill: { assert(uleb128Bytes(@intFromEnum(AbbrevCode.null)) == 1); - trailer.appendNTimesAssumeCapacity(@intFromEnum(AbbrevCode.null), 2); + trailer_bw.splatByteAll(@intFromEnum(AbbrevCode.null), 2) catch unreachable; break :fill @intFromEnum(AbbrevCode.null); } else if (sec == &dwarf.debug_rnglists.section) fill: { - trailer.appendAssumeCapacity(DW.RLE.end_of_list); + trailer_bw.writeByte(DW.RLE.end_of_list) catch unreachable; break :fill DW.RLE.end_of_list; } else unreachable; - assert(trailer.items.len == unit.trailer_len); - trailer.appendNTimesAssumeCapacity(fill_byte, len - unit.trailer_len); - assert(trailer.items.len == len); - try dwarf.getFile().?.pwriteAll(trailer.items, sec.off(dwarf) + start); + assert(trailer_bw.end == unit.trailer_len); + trailer_bw.splatByteAll(fill_byte, len - unit.trailer_len) catch unreachable; + assert(trailer_bw.end == len); + try dwarf.getFile().?.pwriteAll(trailer_bw.buffer, sec.off(dwarf) + start); } fn resolveRelocs(unit: *Unit, sec: *Section, dwarf: *Dwarf) RelocError!void { @@ -780,7 +778,7 @@ const Entry = struct { entry.external_relocs.clearRetainingCapacity(); } - fn deinit(entry: *Entry, gpa: std.mem.Allocator) void { + fn deinit(entry: *Entry, gpa: Allocator) void { entry.cross_entry_relocs.deinit(gpa); entry.cross_unit_relocs.deinit(gpa); entry.cross_section_relocs.deinit(gpa); @@ -833,52 +831,52 @@ const Entry = struct { 1 + uleb128Bytes(std.math.maxInt(u32)) + 1, ) ]u8 = undefined; - var fbs = std.io.fixedBufferStream(&buf); - const writer = fbs.writer(); + var bw: Writer = .fixed(&buf); if (sec == &dwarf.debug_info.section) switch (len) { 0 => {}, - 1 => uleb128(writer, try dwarf.refAbbrevCode(.pad_1)) catch unreachable, + 1 => bw.writeLeb128(try dwarf.refAbbrevCode(.pad_1)) catch unreachable, else => { - uleb128(writer, try dwarf.refAbbrevCode(.pad_n)) catch unreachable; - const abbrev_code_bytes = fbs.pos; + bw.writeLeb128(try dwarf.refAbbrevCode(.pad_n)) catch unreachable; + const abbrev_code_bytes = bw.end; 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, + .lt => break bw.writeLeb128(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; + std.leb.writeUnsignedExtended((try bw.writableSlice(block_len_bytes)), len - abbrev_code_bytes - block_len_bytes); break; }, .gt => block_len_bytes += 1, }; - assert(fbs.pos == abbrev_code_bytes + block_len_bytes); + assert(bw.end == 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, + 1 => bw.writeByte(DW.LNS.const_add_pc) catch unreachable, else => { - writer.writeByte(DW.LNS.extended_op) catch unreachable; - const extended_op_bytes = fbs.pos; + bw.writeByte(DW.LNS.extended_op) catch unreachable; + const extended_op_bytes = bw.end; 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, + .lt => break bw.writeLeb128(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; + std.leb.writeUnsignedExtended( + (bw.writableSlice(op_len_bytes) catch unreachable), + len - extended_op_bytes - 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; + assert(bw.end == extended_op_bytes + op_len_bytes); + if (len > 2) bw.writeByte(DW.LNE.padding) catch unreachable; }, } else assert(!sec.pad_entries_to_ideal and len == 0); - assert(fbs.pos <= len); - try dwarf.getFile().?.pwriteAll(fbs.getWritten(), sec.off(dwarf) + unit.off + unit.header_len + start); + assert(bw.end <= len); + try dwarf.getFile().?.pwriteAll(bw.getWritten(), sec.off(dwarf) + unit.off + unit.header_len + start); } fn resize(entry_ptr: *Entry, unit: *Unit, sec: *Section, dwarf: *Dwarf, len: u32) UpdateError!void { @@ -1133,150 +1131,149 @@ pub const Loc = union(enum) { }; } - fn writeReg(reg: u32, op0: u8, opx: u8, writer: anytype) @TypeOf(writer).Error!void { + fn writeReg(bw: *Writer, reg: u32, op0: u8, opx: u8) Writer.Error!void { if (std.math.cast(u5, reg)) |small_reg| { - try writer.writeByte(op0 + small_reg); + try bw.writeByte(op0 + small_reg); } else { - try writer.writeByte(opx); - try uleb128(writer, reg); + try bw.writeByte(opx); + try bw.writeLeb128(reg); } } - fn write(loc: Loc, adapter: anytype) UpdateError!void { - const writer = adapter.writer(); + fn write(loc: Loc, bw: *Writer, adapter: anytype) UpdateError!void { switch (loc) { .empty => {}, .addr_reloc => |sym_index| { - try writer.writeByte(DW.OP.addr); + try bw.writeByte(DW.OP.addr); try adapter.addrSym(sym_index); }, .deref => |addr| { try addr.write(adapter); - try writer.writeByte(DW.OP.deref); + try bw.writeByte(DW.OP.deref); }, .constu => |constu| if (std.math.cast(u5, constu)) |lit| { - try writer.writeByte(@as(u8, DW.OP.lit0) + lit); + try bw.writeByte(@as(u8, DW.OP.lit0) + lit); } else if (std.math.cast(u8, constu)) |const1u| { - try writer.writeAll(&.{ DW.OP.const1u, const1u }); + try bw.writeAll(&.{ DW.OP.const1u, const1u }); } else if (std.math.cast(u16, constu)) |const2u| { - try writer.writeByte(DW.OP.const2u); - try writer.writeInt(u16, const2u, adapter.endian()); + try bw.writeByte(DW.OP.const2u); + try bw.writeInt(u16, const2u, adapter.endian()); } else if (std.math.cast(u21, constu)) |const3u| { - try writer.writeByte(DW.OP.constu); - try uleb128(writer, const3u); + try bw.writeByte(DW.OP.constu); + try bw.writeLeb128(const3u); } else if (std.math.cast(u32, constu)) |const4u| { - try writer.writeByte(DW.OP.const4u); - try writer.writeInt(u32, const4u, adapter.endian()); + try bw.writeByte(DW.OP.const4u); + try bw.writeInt(u32, const4u, adapter.endian()); } else if (std.math.cast(u49, constu)) |const7u| { - try writer.writeByte(DW.OP.constu); - try uleb128(writer, const7u); + try bw.writeByte(DW.OP.constu); + try bw.writeLeb128(const7u); } else { - try writer.writeByte(DW.OP.const8u); - try writer.writeInt(u64, constu, adapter.endian()); + try bw.writeByte(DW.OP.const8u); + try bw.writeInt(u64, constu, adapter.endian()); }, .consts => |consts| if (std.math.cast(i8, consts)) |const1s| { - try writer.writeAll(&.{ DW.OP.const1s, @bitCast(const1s) }); + try bw.writeAll(&.{ DW.OP.const1s, @bitCast(const1s) }); } else if (std.math.cast(i16, consts)) |const2s| { - try writer.writeByte(DW.OP.const2s); - try writer.writeInt(i16, const2s, adapter.endian()); + try bw.writeByte(DW.OP.const2s); + try bw.writeInt(i16, const2s, adapter.endian()); } else if (std.math.cast(i21, consts)) |const3s| { - try writer.writeByte(DW.OP.consts); - try sleb128(writer, const3s); + try bw.writeByte(DW.OP.consts); + try bw.writeLeb128(const3s); } else if (std.math.cast(i32, consts)) |const4s| { - try writer.writeByte(DW.OP.const4s); - try writer.writeInt(i32, const4s, adapter.endian()); + try bw.writeByte(DW.OP.const4s); + try bw.writeInt(i32, const4s, adapter.endian()); } else if (std.math.cast(i49, consts)) |const7s| { - try writer.writeByte(DW.OP.consts); - try sleb128(writer, const7s); + try bw.writeByte(DW.OP.consts); + try bw.writeLeb128(const7s); } else { - try writer.writeByte(DW.OP.const8s); - try writer.writeInt(i64, consts, adapter.endian()); + try bw.writeByte(DW.OP.const8s); + try bw.writeInt(i64, consts, adapter.endian()); }, .plus => |plus| done: { if (plus[0].getConst(u0)) |_| { - try plus[1].write(adapter); + try plus[1].write(bw, adapter); break :done; } if (plus[1].getConst(u0)) |_| { - try plus[0].write(adapter); + try plus[0].write(bw, adapter); break :done; } if (plus[0].getBaseReg()) |breg| { if (plus[1].getConst(i65)) |offset| { - try writeReg(breg, DW.OP.breg0, DW.OP.bregx, writer); - try sleb128(writer, offset); + try writeReg(bw, breg, DW.OP.breg0, DW.OP.bregx); + try bw.writeLeb128(offset); break :done; } } if (plus[1].getBaseReg()) |breg| { if (plus[0].getConst(i65)) |offset| { - try writeReg(breg, DW.OP.breg0, DW.OP.bregx, writer); - try sleb128(writer, offset); + try writeReg(bw, breg, DW.OP.breg0, DW.OP.bregx); + try bw.writeLeb128(offset); break :done; } } if (plus[0].getConst(u64)) |uconst| { - try plus[1].write(adapter); - try writer.writeByte(DW.OP.plus_uconst); - try uleb128(writer, uconst); + try plus[1].write(bw, adapter); + try bw.writeByte(DW.OP.plus_uconst); + try bw.writeLeb128(uconst); break :done; } if (plus[1].getConst(u64)) |uconst| { - try plus[0].write(adapter); - try writer.writeByte(DW.OP.plus_uconst); - try uleb128(writer, uconst); + try plus[0].write(bw, adapter); + try bw.writeByte(DW.OP.plus_uconst); + try bw.writeLeb128(uconst); break :done; } - try plus[0].write(adapter); - try plus[1].write(adapter); - try writer.writeByte(DW.OP.plus); + try plus[0].write(bw, adapter); + try plus[1].write(bw, adapter); + try bw.writeByte(DW.OP.plus); }, - .reg => |reg| try writeReg(reg, DW.OP.reg0, DW.OP.regx, writer), + .reg => |reg| try writeReg(bw, reg, DW.OP.reg0, DW.OP.regx), .breg => |breg| { - try writeReg(breg, DW.OP.breg0, DW.OP.bregx, writer); - try sleb128(writer, 0); + try writeReg(bw, breg, DW.OP.breg0, DW.OP.bregx); + try bw.writeSleb128(0); }, - .push_object_address => try writer.writeByte(DW.OP.push_object_address), + .push_object_address => try bw.writeByte(DW.OP.push_object_address), .call => |call| { for (call.args) |arg| try arg.write(adapter); - try writer.writeByte(DW.OP.call_ref); + try bw.writeByte(DW.OP.call_ref); try adapter.infoEntry(call.unit, call.entry); }, .form_tls_address => |addr| { - try addr.write(adapter); - try writer.writeByte(DW.OP.form_tls_address); + try addr.write(bw, adapter); + try bw.writeByte(DW.OP.form_tls_address); }, .implicit_value => |value| { - try writer.writeByte(DW.OP.implicit_value); - try uleb128(writer, value.len); - try writer.writeAll(value); + try bw.writeByte(DW.OP.implicit_value); + try bw.writeLeb128(value.len); + try bw.writeAll(value); }, .stack_value => |value| { - try value.write(adapter); - try writer.writeByte(DW.OP.stack_value); + try value.write(bw, adapter); + try bw.writeByte(DW.OP.stack_value); }, .implicit_pointer => |implicit_pointer| { - try writer.writeByte(DW.OP.implicit_pointer); - try adapter.infoEntry(implicit_pointer.unit, implicit_pointer.entry); - try sleb128(writer, implicit_pointer.offset); + try bw.writeByte(DW.OP.implicit_pointer); + try adapter.infoEntry(bw, implicit_pointer.unit, implicit_pointer.entry); + try bw.writeLeb128(implicit_pointer.offset); }, .wasm_ext => |wasm_ext| { - try writer.writeByte(DW.OP.WASM_location); + try bw.writeByte(DW.OP.WASM_location); switch (wasm_ext) { .local => |local| { - try writer.writeByte(DW.OP.WASM_local); - try uleb128(writer, local); + try bw.writeByte(DW.OP.WASM_local); + try bw.writeLeb128(local); }, .global => |global| if (std.math.cast(u21, global)) |global_u21| { - try writer.writeByte(DW.OP.WASM_global); - try uleb128(writer, global_u21); + try bw.writeByte(DW.OP.WASM_global); + try bw.writeLeb128(global_u21); } else { - try writer.writeByte(DW.OP.WASM_global_u32); - try writer.writeInt(u32, global, adapter.endian()); + try bw.writeByte(DW.OP.WASM_global_u32); + try bw.writeInt(u32, global, adapter.endian()); }, .operand_stack => |operand_stack| { - try writer.writeByte(DW.OP.WASM_operand_stack); - try uleb128(writer, operand_stack); + try bw.writeByte(DW.OP.WASM_operand_stack); + try bw.writeLeb128(operand_stack); }, } }, @@ -1309,21 +1306,21 @@ pub const Cfa = union(enum) { const RegExpr = struct { reg: u32, expr: Loc }; fn write(cfa: Cfa, wip_nav: *WipNav) UpdateError!void { - const writer = wip_nav.debug_frame.writer(wip_nav.dwarf.gpa); + const bw = &wip_nav.debug_frame.buffered_writer; switch (cfa) { - .nop => try writer.writeByte(DW.CFA.nop), + .nop => try bw.writeByte(DW.CFA.nop), .advance_loc => |loc| { const delta = @divExact(loc - wip_nav.cfi.loc, wip_nav.dwarf.debug_frame.header.code_alignment_factor); if (delta == 0) {} else if (std.math.cast(u6, delta)) |small_delta| - try writer.writeByte(@as(u8, DW.CFA.advance_loc) + small_delta) + try bw.writeByte(@as(u8, DW.CFA.advance_loc) + small_delta) else if (std.math.cast(u8, delta)) |ubyte_delta| - try writer.writeAll(&.{ DW.CFA.advance_loc1, ubyte_delta }) + try bw.writeAll(&.{ DW.CFA.advance_loc1, ubyte_delta }) else if (std.math.cast(u16, delta)) |uhalf_delta| { - try writer.writeByte(DW.CFA.advance_loc2); - try writer.writeInt(u16, uhalf_delta, wip_nav.dwarf.endian); + try bw.writeByte(DW.CFA.advance_loc2); + try bw.writeInt(u16, uhalf_delta, wip_nav.dwarf.endian); } else if (std.math.cast(u32, delta)) |uword_delta| { - try writer.writeByte(DW.CFA.advance_loc4); - try writer.writeInt(u32, uword_delta, wip_nav.dwarf.endian); + try bw.writeByte(DW.CFA.advance_loc4); + try bw.writeInt(u32, uword_delta, wip_nav.dwarf.endian); } wip_nav.cfi.loc = loc; }, @@ -1335,41 +1332,41 @@ pub const Cfa = union(enum) { }, wip_nav.dwarf.debug_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 writer.writeByte(@as(u8, DW.CFA.offset) + small_reg); + try bw.writeByte(@as(u8, DW.CFA.offset) + small_reg); } else { - try writer.writeByte(DW.CFA.offset_extended); - try uleb128(writer, reg_off.reg); + try bw.writeByte(DW.CFA.offset_extended); + try bw.writeLeb128(reg_off.reg); } - try uleb128(writer, unsigned_off); + try bw.writeLeb128(unsigned_off); } else { - try writer.writeByte(DW.CFA.offset_extended_sf); - try uleb128(writer, reg_off.reg); - try sleb128(writer, factored_off); + try bw.writeByte(DW.CFA.offset_extended_sf); + try bw.writeLeb128(reg_off.reg); + try bw.writeLeb128(factored_off); } }, .restore => |reg| if (std.math.cast(u6, reg)) |small_reg| - try writer.writeByte(@as(u8, DW.CFA.restore) + small_reg) + try bw.writeByte(@as(u8, DW.CFA.restore) + small_reg) else { - try writer.writeByte(DW.CFA.restore_extended); - try uleb128(writer, reg); + try bw.writeByte(DW.CFA.restore_extended); + try bw.writeLeb128(reg); }, .undefined => |reg| { - try writer.writeByte(DW.CFA.undefined); - try uleb128(writer, reg); + try bw.writeByte(DW.CFA.undefined); + try bw.writeLeb128(reg); }, .same_value => |reg| { - try writer.writeByte(DW.CFA.same_value); - try uleb128(writer, reg); + try bw.writeByte(DW.CFA.same_value); + try bw.writeLeb128(reg); }, .register => |regs| if (regs[0] != regs[1]) { - try writer.writeByte(DW.CFA.register); - for (regs) |reg| try uleb128(writer, reg); + try bw.writeByte(DW.CFA.register); + for (regs) |reg| try bw.writeLeb128(reg); } else { - try writer.writeByte(DW.CFA.same_value); - try uleb128(writer, regs[0]); + try bw.writeByte(DW.CFA.same_value); + try bw.writeLeb128(regs[0]); }, - .remember_state => try writer.writeByte(DW.CFA.remember_state), - .restore_state => try writer.writeByte(DW.CFA.restore_state), + .remember_state => try bw.writeByte(DW.CFA.remember_state), + .restore_state => try bw.writeByte(DW.CFA.restore_state), .def_cfa, .def_cfa_register, .def_cfa_offset, .adjust_cfa_offset => { const reg_off: RegOff = switch (cfa) { else => unreachable, @@ -1382,51 +1379,51 @@ pub const Cfa = union(enum) { const unsigned_off = std.math.cast(u63, reg_off.off); if (reg_off.off == wip_nav.cfi.cfa.off) { if (changed_reg) { - try writer.writeByte(DW.CFA.def_cfa_register); - try uleb128(writer, reg_off.reg); + try bw.writeByte(DW.CFA.def_cfa_register); + try bw.writeLeb128(reg_off.reg); } } else if (switch (wip_nav.dwarf.debug_frame.header.data_alignment_factor) { 0 => unreachable, 1 => unsigned_off != null, else => |data_alignment_factor| @rem(reg_off.off, data_alignment_factor) != 0, }) { - try writer.writeByte(if (changed_reg) DW.CFA.def_cfa else DW.CFA.def_cfa_offset); - if (changed_reg) try uleb128(writer, reg_off.reg); - try uleb128(writer, unsigned_off.?); + try bw.writeByte(if (changed_reg) DW.CFA.def_cfa else DW.CFA.def_cfa_offset); + if (changed_reg) try bw.writeLeb128(reg_off.reg); + try bw.writeLeb128(unsigned_off.?); } else { - try writer.writeByte(if (changed_reg) DW.CFA.def_cfa_sf else DW.CFA.def_cfa_offset_sf); - if (changed_reg) try uleb128(writer, reg_off.reg); - try sleb128(writer, @divExact(reg_off.off, wip_nav.dwarf.debug_frame.header.data_alignment_factor)); + try bw.writeByte(if (changed_reg) DW.CFA.def_cfa_sf else DW.CFA.def_cfa_offset_sf); + if (changed_reg) try bw.writeLeb128(reg_off.reg); + try bw.writeLeb128(@divExact(reg_off.off, wip_nav.dwarf.debug_frame.header.data_alignment_factor)); } wip_nav.cfi.cfa = reg_off; }, .def_cfa_expression => |expr| { - try writer.writeByte(DW.CFA.def_cfa_expression); + try bw.writeByte(DW.CFA.def_cfa_expression); try wip_nav.frameExprLoc(expr); }, .expression => |reg_expr| { - try writer.writeByte(DW.CFA.expression); - try uleb128(writer, reg_expr.reg); + try bw.writeByte(DW.CFA.expression); + try bw.writeLeb128(reg_expr.reg); try wip_nav.frameExprLoc(reg_expr.expr); }, .val_offset => |reg_off| { const factored_off = @divExact(reg_off.off, wip_nav.dwarf.debug_frame.header.data_alignment_factor); if (std.math.cast(u63, factored_off)) |unsigned_off| { - try writer.writeByte(DW.CFA.val_offset); - try uleb128(writer, reg_off.reg); - try uleb128(writer, unsigned_off); + try bw.writeByte(DW.CFA.val_offset); + try bw.writeLeb128(reg_off.reg); + try bw.writeLeb128(unsigned_off); } else { - try writer.writeByte(DW.CFA.val_offset_sf); - try uleb128(writer, reg_off.reg); - try sleb128(writer, factored_off); + try bw.writeByte(DW.CFA.val_offset_sf); + try bw.writeLeb128(reg_off.reg); + try bw.writeLeb128(factored_off); } }, .val_expression => |reg_expr| { - try writer.writeByte(DW.CFA.val_expression); - try uleb128(writer, reg_expr.reg); + try bw.writeByte(DW.CFA.val_expression); + try bw.writeLeb128(reg_expr.reg); try wip_nav.frameExprLoc(reg_expr.expr); }, - .escape => |bytes| try writer.writeAll(bytes), + .escape => |bytes| try bw.writeAll(bytes), } } }; @@ -1449,19 +1446,27 @@ pub const WipNav = struct { loc: u32, cfa: Cfa.RegOff, }, - debug_frame: std.ArrayListUnmanaged(u8), - debug_info: std.ArrayListUnmanaged(u8), - debug_line: std.ArrayListUnmanaged(u8), - debug_loclists: std.ArrayListUnmanaged(u8), + debug_frame: std.io.Writer.Allocating, + debug_info: std.io.Writer.Allocating, + debug_line: std.io.Writer.Allocating, + debug_loclists: std.io.Writer.Allocating, pending_lazy: PendingLazy, + pub fn init(wip_nav: *WipNav) void { + const gpa = wip_nav.dwarf.gpa; + wip_nav.debug_frame.init(gpa); + wip_nav.debug_info.init(gpa); + wip_nav.debug_line.init(gpa); + wip_nav.debug_loclists.init(gpa); + } + pub fn deinit(wip_nav: *WipNav) void { const gpa = wip_nav.dwarf.gpa; if (wip_nav.func != .none) wip_nav.blocks.deinit(gpa); - wip_nav.debug_frame.deinit(gpa); - wip_nav.debug_info.deinit(gpa); - wip_nav.debug_line.deinit(gpa); - wip_nav.debug_loclists.deinit(gpa); + wip_nav.debug_frame.deinit(); + wip_nav.debug_info.deinit(); + wip_nav.debug_line.deinit(); + wip_nav.debug_loclists.deinit(); wip_nav.pending_lazy.types.deinit(gpa); wip_nav.pending_lazy.values.deinit(gpa); } @@ -1538,7 +1543,7 @@ pub const WipNav = struct { delta_line: i33, delta_pc: u64, ) error{OutOfMemory}!void { - const dlw = wip_nav.debug_line.writer(wip_nav.dwarf.gpa); + const dlbw = &wip_nav.debug_line.buffered_writer; const header = wip_nav.dwarf.debug_line.header; assert(header.maximum_operations_per_instruction == 1); @@ -1548,8 +1553,8 @@ pub const WipNav = struct { delta_line - header.line_base >= header.line_range) remaining: { assert(delta_line != 0); - try dlw.writeByte(DW.LNS.advance_line); - try sleb128(dlw, delta_line); + try dlbw.writeByte(DW.LNS.advance_line); + try dlbw.writeLeb128(delta_line); break :remaining 0; } else delta_line); @@ -1557,68 +1562,68 @@ pub const WipNav = struct { header.maximum_operations_per_instruction + delta_op; const max_op_advance: u9 = (std.math.maxInt(u8) - header.opcode_base) / header.line_range; const remaining_op_advance: u8 = @intCast(if (op_advance >= 2 * max_op_advance) remaining: { - try dlw.writeByte(DW.LNS.advance_pc); - try uleb128(dlw, op_advance); + try dlbw.writeByte(DW.LNS.advance_pc); + try dlbw.writeLeb128(op_advance); break :remaining 0; } else if (op_advance >= max_op_advance) remaining: { - try dlw.writeByte(DW.LNS.const_add_pc); + try dlbw.writeByte(DW.LNS.const_add_pc); break :remaining op_advance - max_op_advance; } else op_advance); - if (remaining_delta_line == 0 and remaining_op_advance == 0) - try dlw.writeByte(DW.LNS.copy) - else - try dlw.writeByte(@intCast((remaining_delta_line - header.line_base) + - (header.line_range * remaining_op_advance) + header.opcode_base)); + try dlbw.writeByte( + if (remaining_delta_line == 0 and remaining_op_advance == 0) + DW.LNS.copy + else + @intCast((remaining_delta_line - header.line_base) + + (header.line_range * remaining_op_advance) + header.opcode_base), + ); } - pub fn setColumn(wip_nav: *WipNav, column: u32) error{OutOfMemory}!void { - const dlw = wip_nav.debug_line.writer(wip_nav.dwarf.gpa); - try dlw.writeByte(DW.LNS.set_column); - try uleb128(dlw, column + 1); + pub fn setColumn(wip_nav: *WipNav, column: u32) Allocator.Error!void { + const dlbw = &wip_nav.debug_line.buffered_writer; + try dlbw.writeByte(DW.LNS.set_column); + try dlbw.writeLeb128(column + 1); } - pub fn negateStmt(wip_nav: *WipNav) error{OutOfMemory}!void { - const dlw = wip_nav.debug_line.writer(wip_nav.dwarf.gpa); - try dlw.writeByte(DW.LNS.negate_stmt); + pub fn negateStmt(wip_nav: *WipNav) Allocator.Error!void { + return wip_nav.debug_line.buffered_writer.writeByte(DW.LNS.negate_stmt); } - pub fn setPrologueEnd(wip_nav: *WipNav) error{OutOfMemory}!void { - const dlw = wip_nav.debug_line.writer(wip_nav.dwarf.gpa); - try dlw.writeByte(DW.LNS.set_prologue_end); + pub fn setPrologueEnd(wip_nav: *WipNav) Allocator.Error!void { + return wip_nav.debug_line.buffered_writer.writeByte(DW.LNS.set_prologue_end); } - pub fn setEpilogueBegin(wip_nav: *WipNav) error{OutOfMemory}!void { - const dlw = wip_nav.debug_line.writer(wip_nav.dwarf.gpa); - try dlw.writeByte(DW.LNS.set_epilogue_begin); + pub fn setEpilogueBegin(wip_nav: *WipNav) Allocator.Error!void { + return wip_nav.debug_line.buffered_writer.writeByte(DW.LNS.set_epilogue_begin); } pub fn enterBlock(wip_nav: *WipNav, code_off: u64) UpdateError!void { const dwarf = wip_nav.dwarf; - const diw = wip_nav.debug_info.writer(dwarf.gpa); + const dibw = &wip_nav.debug_info.buffered_writer; const block = try wip_nav.blocks.addOne(dwarf.gpa); - block.abbrev_code = @intCast(wip_nav.debug_info.items.len); + block.abbrev_code = @intCast(dibw.count); try wip_nav.abbrevCode(.block); block.low_pc_off = code_off; try wip_nav.infoAddrSym(wip_nav.func_sym_index, code_off); - block.high_pc = @intCast(wip_nav.debug_info.items.len); - try diw.writeInt(u32, 0, dwarf.endian); + block.high_pc = @intCast(dibw.count); + try dibw.writeInt(u32, 0, dwarf.endian); wip_nav.any_children = false; } pub fn leaveBlock(wip_nav: *WipNav, code_off: u64) UpdateError!void { const block_bytes = comptime uleb128Bytes(@intFromEnum(AbbrevCode.block)); const block = wip_nav.blocks.pop().?; + const dib = wip_nav.debug_info.getWritten(); if (wip_nav.any_children) - try uleb128(wip_nav.debug_info.writer(wip_nav.dwarf.gpa), @intFromEnum(AbbrevCode.null)) + try wip_nav.debug_info.buffered_writer.writeLeb128(@intFromEnum(AbbrevCode.null)) else std.leb.writeUnsignedFixed( block_bytes, - wip_nav.debug_info.items[block.abbrev_code..][0..block_bytes], + dib[block.abbrev_code..][0..block_bytes], try wip_nav.dwarf.refAbbrevCode(.empty_block), ); - std.mem.writeInt(u32, wip_nav.debug_info.items[block.high_pc..][0..4], @intCast(code_off - block.low_pc_off), wip_nav.dwarf.endian); + std.mem.writeInt(u32, dib[block.high_pc..][0..4], @intCast(code_off - block.low_pc_off), wip_nav.dwarf.endian); wip_nav.any_children = true; } @@ -1631,18 +1636,18 @@ pub const WipNav = struct { ) UpdateError!void { const dwarf = wip_nav.dwarf; const zcu = wip_nav.pt.zcu; - const diw = wip_nav.debug_info.writer(dwarf.gpa); + const dibw = &wip_nav.debug_info.buffered_writer; const block = try wip_nav.blocks.addOne(dwarf.gpa); - block.abbrev_code = @intCast(wip_nav.debug_info.items.len); + block.abbrev_code = @intCast(dibw.count); 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); + try dibw.writeLeb128(zcu.navSrcLine(zcu.funcInfo(wip_nav.func).owner_nav) + line + 1); + try dibw.writeLeb128(column + 1); block.low_pc_off = code_off; try wip_nav.infoAddrSym(wip_nav.func_sym_index, code_off); - block.high_pc = @intCast(wip_nav.debug_info.items.len); - try diw.writeInt(u32, 0, dwarf.endian); + block.high_pc = @intCast(dibw.count); + try dibw.writeInt(u32, 0, dwarf.endian); try wip_nav.setInlineFunc(func); wip_nav.any_children = false; } @@ -1650,15 +1655,16 @@ pub const WipNav = struct { 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 block = wip_nav.blocks.pop().?; + const dib = wip_nav.debug_info.getWritten(); if (wip_nav.any_children) - try uleb128(wip_nav.debug_info.writer(wip_nav.dwarf.gpa), @intFromEnum(AbbrevCode.null)) + try wip_nav.debug_info.buffered_writer.writeLeb128(@intFromEnum(AbbrevCode.null)) else std.leb.writeUnsignedFixed( inlined_func_bytes, - wip_nav.debug_info.items[block.abbrev_code..][0..inlined_func_bytes], + dib[block.abbrev_code..][0..inlined_func_bytes], try wip_nav.dwarf.refAbbrevCode(.empty_inlined_func), ); - std.mem.writeInt(u32, wip_nav.debug_info.items[block.high_pc..][0..4], @intCast(code_off - block.low_pc_off), wip_nav.dwarf.endian); + std.mem.writeInt(u32, dib[block.high_pc..][0..4], @intCast(code_off - block.low_pc_off), wip_nav.dwarf.endian); try wip_nav.setInlineFunc(func); wip_nav.any_children = true; } @@ -1672,22 +1678,22 @@ pub const WipNav = struct { const new_file = zcu.navFileScopeIndex(new_func_info.owner_nav); const new_unit = try dwarf.getUnit(zcu.fileByIndex(new_file).mod.?); - const dlw = wip_nav.debug_line.writer(dwarf.gpa); + const dlbw = &wip_nav.debug_line.buffered_writer; if (dwarf.incremental()) { const new_nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, new_func_info.owner_nav); errdefer _ = if (!new_nav_gop.found_existing) dwarf.navs.pop(); if (!new_nav_gop.found_existing) new_nav_gop.value_ptr.* = try dwarf.addCommonEntry(new_unit); - try dlw.writeByte(DW.LNS.extended_op); - try uleb128(dlw, 1 + dwarf.sectionOffsetBytes()); - try dlw.writeByte(DW.LNE.ZIG_set_decl); + try dlbw.writeByte(DW.LNS.extended_op); + try dlbw.writeLeb128(1 + dwarf.sectionOffsetBytes()); + try dlbw.writeByte(DW.LNE.ZIG_set_decl); try dwarf.debug_line.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_section_relocs.append(dwarf.gpa, .{ - .source_off = @intCast(wip_nav.debug_line.items.len), + .source_off = @intCast(dlbw.count), .target_sec = .debug_info, .target_unit = new_unit, .target_entry = new_nav_gop.value_ptr.toOptional(), }); - try dlw.writeByteNTimes(0, dwarf.sectionOffsetBytes()); + try dlbw.splatByteAll(0, dwarf.sectionOffsetBytes()); return; } @@ -1698,42 +1704,49 @@ pub const WipNav = struct { try mod_info.dirs.put(dwarf.gpa, new_unit, {}); const file_gop = try mod_info.files.getOrPut(dwarf.gpa, new_file); - try dlw.writeByte(DW.LNS.set_file); - try uleb128(dlw, file_gop.index); + try dlbw.writeByte(DW.LNS.set_file); + try dlbw.writeLeb128(file_gop.index); } const old_src_line: i33 = zcu.navSrcLine(old_func_info.owner_nav); const new_src_line: i33 = zcu.navSrcLine(new_func_info.owner_nav); if (new_src_line != old_src_line) { - try dlw.writeByte(DW.LNS.advance_line); - try sleb128(dlw, new_src_line - old_src_line); + try dlbw.writeByte(DW.LNS.advance_line); + try dlbw.writeLeb128(new_src_line - old_src_line); } wip_nav.func = func; } - fn externalReloc(wip_nav: *WipNav, sec: *Section, reloc: ExternalReloc) std.mem.Allocator.Error!void { + fn externalReloc(wip_nav: *WipNav, sec: *Section, reloc: ExternalReloc) Allocator.Error!void { try sec.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs.append(wip_nav.dwarf.gpa, reloc); } - pub fn infoExternalReloc(wip_nav: *WipNav, reloc: ExternalReloc) std.mem.Allocator.Error!void { + pub fn infoExternalReloc(wip_nav: *WipNav, reloc: ExternalReloc) Allocator.Error!void { try wip_nav.externalReloc(&wip_nav.dwarf.debug_info.section, reloc); } - fn frameExternalReloc(wip_nav: *WipNav, reloc: ExternalReloc) std.mem.Allocator.Error!void { + fn frameExternalReloc(wip_nav: *WipNav, reloc: ExternalReloc) Allocator.Error!void { try wip_nav.externalReloc(&wip_nav.dwarf.debug_frame.section, reloc); } 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)); + try wip_nav.debug_info.buffered_writer.writeLeb128(try wip_nav.dwarf.refAbbrevCode(abbrev_code)); } - fn sectionOffset(wip_nav: *WipNav, comptime sec: Section.Index, target_sec: Section.Index, target_unit: Unit.Index, target_entry: Entry.Index, target_off: u32) UpdateError!void { + fn sectionOffset( + wip_nav: *WipNav, + comptime sec: Section.Index, + target_sec: Section.Index, + target_unit: Unit.Index, + target_entry: Entry.Index, + target_off: u32, + ) UpdateError!void { const dwarf = wip_nav.dwarf; const gpa = dwarf.gpa; const entry_ptr = @field(dwarf, @tagName(sec)).section.getUnit(wip_nav.unit).getEntry(wip_nav.entry); - const bytes = &@field(wip_nav, @tagName(sec)); - const source_off: u32 = @intCast(bytes.items.len); + const bw = &@field(wip_nav, @tagName(sec)).buffered_writer; + const source_off: u32 = @intCast(bw.count); if (target_sec != sec) { try entry_ptr.cross_section_relocs.append(gpa, .{ .source_off = source_off, @@ -1756,7 +1769,7 @@ pub const WipNav = struct { .target_off = target_off, }); } - try bytes.appendNTimes(gpa, 0, dwarf.sectionOffsetBytes()); + try bw.splatByteAll(0, dwarf.sectionOffsetBytes()); } fn infoSectionOffset(wip_nav: *WipNav, target_sec: Section.Index, target_unit: Unit.Index, target_entry: Entry.Index, target_off: u32) UpdateError!void { @@ -1768,93 +1781,93 @@ pub const WipNav = struct { } const ExprLocCounter = struct { - const Stream = std.io.CountingWriter(std.io.NullWriter); - stream: Stream, section_offset_bytes: u32, address_size: AddressSize, fn init(dwarf: *Dwarf) ExprLocCounter { return .{ - .stream = std.io.countingWriter(std.io.null_writer), .section_offset_bytes = dwarf.sectionOffsetBytes(), .address_size = dwarf.address_size, }; } - fn writer(counter: *ExprLocCounter) Stream.Writer { - return counter.stream.writer(); - } fn endian(_: ExprLocCounter) std.builtin.Endian { return @import("builtin").cpu.arch.endian(); } - fn addrSym(counter: *ExprLocCounter, _: u32) error{}!void { - counter.stream.bytes_written += @intFromEnum(counter.address_size); + fn addrSym(counter: ExprLocCounter, bw: *Writer, _: u32) error{}!void { + bw.count += @intFromEnum(counter.address_size); } - fn infoEntry(counter: *ExprLocCounter, _: Unit.Index, _: Entry.Index) error{}!void { - counter.stream.bytes_written += counter.section_offset_bytes; + fn infoEntry(counter: ExprLocCounter, bw: *Writer, _: Unit.Index, _: Entry.Index) error{}!void { + bw.count += counter.section_offset_bytes; } }; fn infoExprLoc(wip_nav: *WipNav, loc: Loc) UpdateError!void { - var counter: ExprLocCounter = .init(wip_nav.dwarf); - try loc.write(&counter); + const bw = &wip_nav.debug_info.buffered_writer; + const counter: ExprLocCounter = .init(wip_nav.dwarf); + const start = bw.count; + try loc.write(bw, counter); + const len = bw.count - start; + bw.count = start; + wip_nav.debug_info.shrinkRetainingCapacity(start); const adapter: struct { wip_nav: *WipNav, - fn writer(ctx: @This()) std.ArrayListUnmanaged(u8).Writer { - return ctx.wip_nav.debug_info.writer(ctx.wip_nav.dwarf.gpa); - } fn endian(ctx: @This()) std.builtin.Endian { return ctx.wip_nav.dwarf.endian; } - fn addrSym(ctx: @This(), sym_index: u32) UpdateError!void { + fn addrSym(ctx: @This(), _: *Writer, sym_index: u32) UpdateError!void { try ctx.wip_nav.infoAddrSym(sym_index, 0); } - fn infoEntry(ctx: @This(), unit: Unit.Index, entry: Entry.Index) UpdateError!void { + fn infoEntry(ctx: @This(), _: *Writer, unit: Unit.Index, entry: Entry.Index) UpdateError!void { try ctx.wip_nav.infoSectionOffset(.debug_info, unit, entry, 0); } } = .{ .wip_nav = wip_nav }; - try uleb128(adapter.writer(), counter.stream.bytes_written); - try loc.write(adapter); + try bw.writeLeb128(len); + try loc.write(bw, adapter); } fn infoAddrSym(wip_nav: *WipNav, sym_index: u32, sym_off: u64) UpdateError!void { + const dibw = &wip_nav.debug_info.buffered_writer; try wip_nav.infoExternalReloc(.{ - .source_off = @intCast(wip_nav.debug_info.items.len), + .source_off = @intCast(dibw.count), .target_sym = sym_index, .target_off = sym_off, }); - try wip_nav.debug_info.appendNTimes(wip_nav.dwarf.gpa, 0, @intFromEnum(wip_nav.dwarf.address_size)); + try dibw.splatByteAll(0, @intFromEnum(wip_nav.dwarf.address_size)); } fn frameExprLoc(wip_nav: *WipNav, loc: Loc) UpdateError!void { - var counter: ExprLocCounter = .init(wip_nav.dwarf); - try loc.write(&counter); + const bw = &wip_nav.debug_frame.buffered_writer; + const counter: ExprLocCounter = .init(wip_nav.dwarf); + const start = bw.count; + try loc.write(bw, counter); + const len = bw.count - start; + bw.count = start; + wip_nav.debug_frame.shrinkRetainingCapacity(start); const adapter: struct { wip_nav: *WipNav, - fn writer(ctx: @This()) std.ArrayListUnmanaged(u8).Writer { - return ctx.wip_nav.debug_frame.writer(ctx.wip_nav.dwarf.gpa); - } fn endian(ctx: @This()) std.builtin.Endian { return ctx.wip_nav.dwarf.endian; } - fn addrSym(ctx: @This(), sym_index: u32) UpdateError!void { + fn addrSym(ctx: @This(), _: *Writer, sym_index: u32) UpdateError!void { try ctx.wip_nav.frameAddrSym(sym_index, 0); } - fn infoEntry(ctx: @This(), unit: Unit.Index, entry: Entry.Index) UpdateError!void { + fn infoEntry(ctx: @This(), _: *Writer, unit: Unit.Index, entry: Entry.Index) UpdateError!void { try ctx.wip_nav.sectionOffset(.debug_frame, .debug_info, unit, entry, 0); } } = .{ .wip_nav = wip_nav }; - try uleb128(adapter.writer(), counter.stream.bytes_written); - try loc.write(adapter); + try bw.writeLeb128(len); + try loc.write(bw, adapter); } fn frameAddrSym(wip_nav: *WipNav, sym_index: u32, sym_off: u64) UpdateError!void { + const dfbw = &wip_nav.debug_frame.buffered_writer; try wip_nav.frameExternalReloc(.{ - .source_off = @intCast(wip_nav.debug_frame.items.len), + .source_off = @intCast(dfbw.count), .target_sym = sym_index, .target_off = sym_off, }); - try wip_nav.debug_frame.appendNTimes(wip_nav.dwarf.gpa, 0, @intFromEnum(wip_nav.dwarf.address_size)); + try dfbw.splatByteAll(0, @intFromEnum(wip_nav.dwarf.address_size)); } fn getNavEntry(wip_nav: *WipNav, nav_index: InternPool.Nav.Index) UpdateError!struct { Unit.Index, Entry.Index } { @@ -1922,38 +1935,41 @@ pub const WipNav = struct { try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0); } - fn refForward(wip_nav: *WipNav) std.mem.Allocator.Error!u32 { + fn refForward(wip_nav: *WipNav) Allocator.Error!u32 { const dwarf = wip_nav.dwarf; + const dibw = &wip_nav.debug_info.buffered_writer; const cross_entry_relocs = &dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_entry_relocs; const reloc_index: u32 = @intCast(cross_entry_relocs.items.len); try cross_entry_relocs.append(dwarf.gpa, .{ - .source_off = @intCast(wip_nav.debug_info.items.len), + .source_off = @intCast(dibw.count), .target_entry = undefined, .target_off = undefined, }); - try wip_nav.debug_info.appendNTimes(dwarf.gpa, 0, dwarf.sectionOffsetBytes()); + try dibw.splatByteAll(0, dwarf.sectionOffsetBytes()); return reloc_index; } fn finishForward(wip_nav: *WipNav, reloc_index: u32) void { const reloc = &wip_nav.dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_entry_relocs.items[reloc_index]; reloc.target_entry = wip_nav.entry.toOptional(); - reloc.target_off = @intCast(wip_nav.debug_info.items.len); + reloc.target_off = @intCast(wip_nav.debug_info.buffered_writer.count); } fn blockValue(wip_nav: *WipNav, src_loc: Zcu.LazySrcLoc, val: Value) UpdateError!void { const ty = val.typeOf(wip_nav.pt.zcu); - const diw = wip_nav.debug_info.writer(wip_nav.dwarf.gpa); + const dibw = &wip_nav.debug_info.buffered_writer; const bytes = if (ty.hasRuntimeBits(wip_nav.pt.zcu)) ty.abiSize(wip_nav.pt.zcu) else 0; - try uleb128(diw, bytes); + try dibw.writeLeb128(bytes); if (bytes == 0) return; - const old_len = wip_nav.debug_info.items.len; + var dial = wip_nav.debug_info.toArrayList(); + defer _ = wip_nav.debug_info.fromArrayList(wip_nav.dwarf.gpa, &dial); + const old_len = dial.items.len; try codegen.generateSymbol( wip_nav.dwarf.bin_file, wip_nav.pt, src_loc, val, - &wip_nav.debug_info, + &dial, .{ .debug_output = .{ .dwarf = wip_nav } }, ); if (old_len + bytes != wip_nav.debug_info.items.len) { @@ -1975,7 +1991,7 @@ pub const WipNav = struct { big_int: std.math.big.int.Const, ) UpdateError!void { const zcu = wip_nav.pt.zcu; - const diw = wip_nav.debug_info.writer(wip_nav.dwarf.gpa); + const dibw = &wip_nav.debug_info.buffered_writer; const signedness = switch (ty.toIntern()) { .comptime_int_type, .comptime_float_type => .signed, else => ty.intInfo(zcu).signedness, @@ -1986,7 +2002,7 @@ pub const WipNav = struct { .signed => abbrev_code.sdata, .unsigned => abbrev_code.udata, }); - try wip_nav.debug_info.ensureUnusedCapacity(wip_nav.dwarf.gpa, std.math.divCeil(usize, bits, 7) catch unreachable); + _ = try dibw.writableSliceGreedy(std.math.divCeil(usize, bits, 7) catch unreachable); var bit: usize = 0; var carry: u1 = 1; while (bit < bits) { @@ -2003,16 +2019,17 @@ pub const WipNav = struct { break :twos_comp_part twos_comp_part; }; bit += 7; - wip_nav.debug_info.appendAssumeCapacity(@as(u8, if (bit < bits) 0x80 else 0x00) | twos_comp_part); + dibw.writeByte(@as(u8, if (bit < bits) 0x80 else 0x00) | twos_comp_part) catch unreachable; } } else { try wip_nav.abbrevCode(abbrev_code.block); const bytes = @max(ty.abiSize(zcu), std.math.divCeil(usize, bits, 8) catch unreachable); - try uleb128(diw, bytes); + try dibw.writeLeb128(bytes); big_int.writeTwosComplement( - try wip_nav.debug_info.addManyAsSlice(wip_nav.dwarf.gpa, @intCast(bytes)), + try dibw.writableSliceGreedy(@intCast(bytes)), wip_nav.dwarf.endian, ); + dibw.advance(@intCast(bytes)); } } @@ -2045,7 +2062,7 @@ pub const WipNav = struct { const zcu = wip_nav.pt.zcu; const ip = &zcu.intern_pool; const dwarf = wip_nav.dwarf; - const diw = wip_nav.debug_info.writer(dwarf.gpa); + const dibw = &wip_nav.debug_info.buffered_writer; const orig_entry = wip_nav.entry; defer wip_nav.entry = orig_entry; @@ -2096,15 +2113,15 @@ pub const WipNav = struct { try wip_nav.abbrevCode(if (is_generic_decl) abbrev_code.generic_decl else abbrev_code.decl); try wip_nav.refType((if (is_generic_decl) null else parent_type) orelse .fromInterned(zcu.fileRootType(file))); - assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); - try diw.writeInt(u32, decl.src_line + 1, dwarf.endian); - try uleb128(diw, decl.src_column + 1); - try diw.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); + assert(dibw.count == DebugInfo.declEntryLineOff(dwarf)); + try dibw.writeInt(u32, decl.src_line + 1, dwarf.endian); + try dibw.writeLeb128(decl.src_column + 1); + try dibw.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); try wip_nav.strp(nav.name.toSlice(ip)); if (!is_generic_decl) return; const generic_decl_entry = wip_nav.entry; - try dwarf.debug_info.section.replaceEntry(wip_nav.unit, generic_decl_entry, dwarf, wip_nav.debug_info.items); + try dwarf.debug_info.section.replaceEntry(wip_nav.unit, generic_decl_entry, dwarf, wip_nav.debug_info.getWritten()); wip_nav.debug_info.clearRetainingCapacity(); wip_nav.entry = orig_entry; try wip_nav.abbrevCode(abbrev_code.decl_instance); @@ -2408,12 +2425,63 @@ pub fn initWipNav( nav_index: InternPool.Nav.Index, sym_index: u32, ) error{ OutOfMemory, CodegenFail }!?WipNav { - return initWipNavInner(dwarf, pt, nav_index, sym_index) catch |err| switch (err) { + return dwarf.initWipNavInner(pt, nav_index, sym_index) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, - else => |e| return pt.zcu.codegenFail(nav_index, "failed to init dwarf: {s}", .{@errorName(e)}), + else => |e| return pt.zcu.codegenFail(nav_index, "failed to init dwarf nav: {s}", .{@errorName(e)}), }; } +pub fn finishWipNavFunc( + dwarf: *Dwarf, + pt: Zcu.PerThread, + nav_index: InternPool.Nav.Index, + code_size: u64, + wip_nav: *WipNav, +) error{ OutOfMemory, CodegenFail }!void { + return dwarf.finishWipNavFuncInner(pt, nav_index, code_size, wip_nav) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + else => |e| return pt.zcu.codegenFail(nav_index, "failed to finish dwarf func nav: {s}", .{@errorName(e)}), + }; +} + +pub fn finishWipNav( + dwarf: *Dwarf, + pt: Zcu.PerThread, + nav_index: InternPool.Nav.Index, + wip_nav: *WipNav, +) error{ OutOfMemory, CodegenFail }!void { + return dwarf.finishWipNavInner(pt, nav_index, wip_nav) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + else => |e| return pt.zcu.codegenFail(nav_index, "failed to finish dwarf nav: {s}", .{@errorName(e)}), + }; +} + +pub fn updateComptimeNav( + dwarf: *Dwarf, + pt: Zcu.PerThread, + nav_index: InternPool.Nav.Index, +) error{ OutOfMemory, CodegenFail }!void { + return dwarf.updateComptimeNavInner(pt, nav_index) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + else => |e| return pt.zcu.codegenFail(nav_index, "failed to update dwarf comptime nav: {s}", .{@errorName(e)}), + }; +} + +pub fn updateContainerType( + dwarf: *Dwarf, + pt: Zcu.PerThread, + type_index: InternPool.Index, +) error{ OutOfMemory, CodegenFail }!void { + return dwarf.updateContainerType(pt, type_index) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + else => |e| return pt.zcu.codegenFailType(type_index, "failed to update dwarf comptime nav: {s}", .{@errorName(e)}), + }; +} + +pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { + return dwarf.flushModuleInner(pt); +} + fn initWipNavInner( dwarf: *Dwarf, pt: Zcu.PerThread, @@ -2468,17 +2536,17 @@ fn initWipNavInner( .func_high_pc = undefined, .blocks = undefined, .cfi = undefined, - .debug_frame = .empty, - .debug_info = .empty, - .debug_line = .empty, - .debug_loclists = .empty, + .debug_frame = undefined, + .debug_info = undefined, + .debug_line = undefined, + .debug_loclists = undefined, .pending_lazy = .empty, }; errdefer wip_nav.deinit(); switch (nav_key) { else => { - const diw = wip_nav.debug_info.writer(dwarf.gpa); + const dibw = &wip_nav.debug_info.buffered_writer; try wip_nav.declCommon(.{ .decl = .decl_var, .generic_decl = .generic_decl_var, @@ -2499,9 +2567,9 @@ fn initWipNavInner( .@"const" => { const const_ty_reloc_index = try wip_nav.refForward(); try wip_nav.infoExprLoc(loc); - try uleb128(diw, nav.status.fully_resolved.alignment.toByteUnits() orelse + try dibw.writeLeb128(nav.status.fully_resolved.alignment.toByteUnits() orelse ty.abiAlignment(zcu).toByteUnits().?); - try diw.writeByte(@intFromBool(decl.linkage != .normal)); + try dibw.writeByte(@intFromBool(decl.linkage != .normal)); wip_nav.finishForward(const_ty_reloc_index); try wip_nav.abbrevCode(.is_const); try wip_nav.refType(ty); @@ -2509,9 +2577,9 @@ fn initWipNavInner( .@"var" => { try wip_nav.refType(ty); try wip_nav.infoExprLoc(loc); - try uleb128(diw, nav.status.fully_resolved.alignment.toByteUnits() orelse + try dibw.writeLeb128(dibw, nav.status.fully_resolved.alignment.toByteUnits() orelse ty.abiAlignment(zcu).toByteUnits().?); - try diw.writeByte(@intFromBool(decl.linkage != .normal)); + try dibw.writeByte(@intFromBool(decl.linkage != .normal)); }, } }, @@ -2536,39 +2604,39 @@ fn initWipNavInner( .none => {}, .debug_frame, .eh_frame => |format| { const entry = dwarf.debug_frame.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry); - const dfw = wip_nav.debug_frame.writer(dwarf.gpa); + const dfbw = &wip_nav.debug_frame.buffered_writer; switch (dwarf.format) { - .@"32" => try dfw.writeInt(u32, undefined, dwarf.endian), + .@"32" => try dfbw.writeInt(u32, undefined, dwarf.endian), .@"64" => { - try dfw.writeInt(u32, std.math.maxInt(u32), dwarf.endian); - try dfw.writeInt(u64, undefined, dwarf.endian); + try dfbw.writeInt(u32, std.math.maxInt(u32), dwarf.endian); + try dfbw.writeInt(u64, undefined, dwarf.endian); }, } switch (format) { .none => unreachable, .debug_frame => { try entry.cross_entry_relocs.append(dwarf.gpa, .{ - .source_off = @intCast(wip_nav.debug_frame.items.len), + .source_off = @intCast(dfbw.count), }); - try dfw.writeByteNTimes(0, dwarf.sectionOffsetBytes()); + try dfbw.splatByteAll(0, dwarf.sectionOffsetBytes()); try wip_nav.frameAddrSym(sym_index, 0); - try dfw.writeByteNTimes(undefined, @intFromEnum(dwarf.address_size)); + try dfbw.splatByteAll(undefined, @intFromEnum(dwarf.address_size)); }, .eh_frame => { - try dfw.writeInt(u32, undefined, dwarf.endian); + try dfbw.writeInt(u32, undefined, dwarf.endian); try wip_nav.frameExternalReloc(.{ - .source_off = @intCast(wip_nav.debug_frame.items.len), + .source_off = @intCast(dfbw.count), .target_sym = sym_index, }); - try dfw.writeInt(u32, 0, dwarf.endian); - try dfw.writeInt(u32, undefined, dwarf.endian); - try uleb128(dfw, 0); + try dfbw.writeInt(u32, 0, dwarf.endian); + try dfbw.writeInt(u32, undefined, dwarf.endian); + try dfbw.writeUleb128(0); }, } }, } - const diw = wip_nav.debug_info.writer(dwarf.gpa); + const dibw = &wip_nav.debug_info.buffered_writer; try wip_nav.declCommon(.{ .decl = .decl_func, .generic_decl = .generic_decl_func, @@ -2578,47 +2646,47 @@ fn initWipNavInner( try wip_nav.refType(.fromInterned(func_type.return_type)); try wip_nav.infoAddrSym(sym_index, 0); wip_nav.func_high_pc = @intCast(wip_nav.debug_info.items.len); - try diw.writeInt(u32, 0, dwarf.endian); + try dibw.writeInt(u32, 0, dwarf.endian); const target = &mod.resolved_target.result; - try uleb128(diw, switch (nav.status.fully_resolved.alignment) { + try dibw.writeLeb128(switch (nav.status.fully_resolved.alignment) { .none => target_info.defaultFunctionAlignment(target), else => |a| a.maxStrict(target_info.minFunctionAlignment(target)), }.toByteUnits().?); - try diw.writeByte(@intFromBool(decl.linkage != .normal)); - try diw.writeByte(@intFromBool(func_type.return_type == .noreturn_type)); + try dibw.writeByte(@intFromBool(decl.linkage != .normal)); + try dibw.writeByte(@intFromBool(func_type.return_type == .noreturn_type)); - const dlw = wip_nav.debug_line.writer(dwarf.gpa); - try dlw.writeByte(DW.LNS.extended_op); + const dlbw = &wip_nav.debug_line.buffered_writer; + try dlbw.writeByte(DW.LNS.extended_op); if (dwarf.incremental()) { - try uleb128(dlw, 1 + dwarf.sectionOffsetBytes()); - try dlw.writeByte(DW.LNE.ZIG_set_decl); + try dlbw.writeLeb128(1 + dwarf.sectionOffsetBytes()); + try dlbw.writeByte(DW.LNE.ZIG_set_decl); try dwarf.debug_line.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_section_relocs.append(dwarf.gpa, .{ - .source_off = @intCast(wip_nav.debug_line.items.len), + .source_off = @intCast(dlbw.count), .target_sec = .debug_info, .target_unit = wip_nav.unit, .target_entry = wip_nav.entry.toOptional(), }); - try dlw.writeByteNTimes(0, dwarf.sectionOffsetBytes()); + try dlbw.splatByteAll(0, dwarf.sectionOffsetBytes()); - try dlw.writeByte(DW.LNS.set_column); - try uleb128(dlw, func.lbrace_column + 1); + try dlbw.writeByte(DW.LNS.set_column); + try dlbw.writeLeb128(func.lbrace_column + 1); try wip_nav.advancePCAndLine(func.lbrace_line, 0); } else { - try uleb128(dlw, 1 + @intFromEnum(dwarf.address_size)); - try dlw.writeByte(DW.LNE.set_address); + try dlbw.writeLeb128(1 + @intFromEnum(dwarf.address_size)); + try dlbw.writeByte(DW.LNE.set_address); try dwarf.debug_line.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs.append(dwarf.gpa, .{ - .source_off = @intCast(wip_nav.debug_line.items.len), + .source_off = @intCast(dlbw.count), .target_sym = sym_index, }); - try dlw.writeByteNTimes(0, @intFromEnum(dwarf.address_size)); + try dlbw.splatByteAll(0, @intFromEnum(dwarf.address_size)); const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, inst_info.file); - try dlw.writeByte(DW.LNS.set_file); - try uleb128(dlw, file_gop.index); + try dlbw.writeByte(DW.LNS.set_file); + try dlbw.writeLeb128(file_gop.index); - try dlw.writeByte(DW.LNS.set_column); - try uleb128(dlw, func.lbrace_column + 1); + try dlbw.writeByte(DW.LNS.set_column); + try dlbw.writeLeb128(func.lbrace_column + 1); try wip_nav.advancePCAndLine(@intCast(decl.src_line + func.lbrace_line), 0); } @@ -2627,7 +2695,7 @@ fn initWipNavInner( return wip_nav; } -pub fn finishWipNavFunc( +fn finishWipNavFuncInner( dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, @@ -2656,12 +2724,9 @@ pub fn finishWipNavFunc( switch (dwarf.debug_frame.header.format) { .none => {}, .debug_frame, .eh_frame => |format| { - try wip_nav.debug_frame.appendNTimes( - dwarf.gpa, - DW.CFA.nop, - @intCast(dwarf.debug_frame.section.alignment.forward(wip_nav.debug_frame.items.len) - wip_nav.debug_frame.items.len), - ); - const contents = wip_nav.debug_frame.items; + const dfbw = &wip_nav.debug_frame.buffered_writer; + try dfbw.splatByteAll(DW.CFA.nop, @intCast(dwarf.debug_frame.section.alignment.forward(dfbw.count) - dfbw.count)); + const contents = wip_nav.debug_frame.getWritten(); try dwarf.debug_frame.section.resizeEntry(wip_nav.unit, wip_nav.entry, dwarf, @intCast(contents.len)); const unit = dwarf.debug_frame.section.getUnit(wip_nav.unit); const entry = unit.getEntry(wip_nav.entry); @@ -2688,14 +2753,14 @@ pub fn finishWipNavFunc( }, } { - std.mem.writeInt(u32, wip_nav.debug_info.items[wip_nav.func_high_pc..][0..4], @intCast(code_size), dwarf.endian); + std.mem.writeInt(u32, wip_nav.debug_info.getWritten()[wip_nav.func_high_pc..][0..4], @intCast(code_size), dwarf.endian); if (wip_nav.any_children) { - const diw = wip_nav.debug_info.writer(dwarf.gpa); - try uleb128(diw, @intFromEnum(AbbrevCode.null)); + const dibw = &wip_nav.debug_info.buffered_writer; + try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); } else { - const abbrev_code_buf = wip_nav.debug_info.items[0..AbbrevCode.decl_bytes]; - var abbrev_code_fbs = std.io.fixedBufferStream(abbrev_code_buf); - const abbrev_code: AbbrevCode = @enumFromInt(std.leb.readUleb128(@typeInfo(AbbrevCode).@"enum".tag_type, abbrev_code_fbs.reader()) catch unreachable); + const abbrev_code_buf = wip_nav.debug_info.getWritten()[0..AbbrevCode.decl_bytes]; + var abbrev_code_br: std.io.Reader = .fixed(abbrev_code_buf); + const abbrev_code: AbbrevCode = @enumFromInt(abbrev_code_br.takeLeb128(@typeInfo(AbbrevCode).@"enum".tag_type) catch unreachable); std.leb.writeUnsignedFixed( AbbrevCode.decl_bytes, abbrev_code_buf, @@ -2727,10 +2792,10 @@ pub fn finishWipNavFunc( ); } - try dwarf.finishWipNav(pt, nav_index, wip_nav); + try dwarf.finishWipNavInner(pt, nav_index, wip_nav); } -pub fn finishWipNav( +fn finishWipNavInner( dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, @@ -2741,26 +2806,20 @@ pub fn finishWipNav( const nav = ip.getNav(nav_index); log.debug("finishWipNav({f})", .{nav.fqn.fmt(ip)}); - try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items); - if (wip_nav.debug_line.items.len > 0) { - const dlw = wip_nav.debug_line.writer(dwarf.gpa); - try dlw.writeByte(DW.LNS.extended_op); - try uleb128(dlw, 1); - try dlw.writeByte(DW.LNE.end_sequence); - try dwarf.debug_line.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_line.items); + try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.getWritten()); + const debug_line = wip_nav.debug_line.getWritten(); + if (debug_line.len > 0) { + const dlbw = &wip_nav.debug_line.buffered_writer; + try dlbw.writeByte(DW.LNS.extended_op); + try dlbw.writeUleb128(1); + try dlbw.writeByte(DW.LNE.end_sequence); + try dwarf.debug_line.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_line.getWritten()); } - try dwarf.debug_loclists.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_loclists.items); + try dwarf.debug_loclists.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_loclists.getWritten()); try wip_nav.updateLazy(zcu.navSrcLoc(nav_index)); } -pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) error{ OutOfMemory, CodegenFail }!void { - return updateComptimeNavInner(dwarf, pt, nav_index) catch |err| switch (err) { - error.OutOfMemory => return error.OutOfMemory, - else => |e| return pt.zcu.codegenFail(nav_index, "failed to update dwarf: {s}", .{@errorName(e)}), - }; -} - fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void { const zcu = pt.zcu; const ip = &zcu.intern_pool; @@ -2799,12 +2858,13 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo .func_high_pc = undefined, .blocks = undefined, .cfi = undefined, - .debug_frame = .empty, - .debug_info = .empty, - .debug_line = .empty, - .debug_loclists = .empty, + .debug_frame = undefined, + .debug_info = undefined, + .debug_line = undefined, + .debug_loclists = undefined, .pending_lazy = .empty, }; + wip_nav.init(); defer wip_nav.deinit(); const nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index); @@ -2848,7 +2908,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo } wip_nav.entry = nav_gop.value_ptr.*; - const diw = wip_nav.debug_info.writer(dwarf.gpa); + const dibw = &wip_nav.debug_info.buffered_writer; switch (loaded_struct.layout) { .auto, .@"extern" => { @@ -2861,9 +2921,9 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo .generic_decl = .generic_decl_const, .decl_instance = .decl_instance_struct, }, &nav, inst_info.file, &decl); - if (loaded_struct.field_types.len == 0) try diw.writeByte(@intFromBool(false)) else { - try uleb128(diw, nav_val.toType().abiSize(zcu)); - try uleb128(diw, nav_val.toType().abiAlignment(zcu).toByteUnits().?); + if (loaded_struct.field_types.len == 0) try dibw.writeByte(@intFromBool(false)) else { + try dibw.writeLeb128(nav_val.toType().abiSize(zcu)); + try dibw.writeLeb128(nav_val.toType().abiAlignment(zcu).toByteUnits().?); for (0..loaded_struct.field_types.len) |field_index| { const is_comptime = loaded_struct.fieldIsComptime(ip, field_index); const field_init = loaded_struct.fieldInit(ip, field_index); @@ -2899,8 +2959,8 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo } try wip_nav.refType(field_type); if (!is_comptime) { - try uleb128(diw, loaded_struct.offsets.get(ip)[field_index]); - try uleb128(diw, loaded_struct.fieldAlign(ip, field_index).toByteUnits() orelse + try dibw.writeLeb128(loaded_struct.offsets.get(ip)[field_index]); + try dibw.writeLeb128(loaded_struct.fieldAlign(ip, field_index).toByteUnits() orelse field_type.abiAlignment(zcu).toByteUnits().?); } if (has_comptime_state) @@ -2908,7 +2968,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo else if (has_runtime_bits) try wip_nav.blockValue(nav_src_loc, .fromInterned(field_init)); } - try uleb128(diw, @intFromEnum(AbbrevCode.null)); + try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); } }, .@"packed" => { @@ -2924,10 +2984,10 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo 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); - try uleb128(diw, field_bit_offset); + try dibw.writeLeb128(field_bit_offset); field_bit_offset += @intCast(field_type.bitSize(zcu)); } - try uleb128(diw, @intFromEnum(AbbrevCode.null)); + try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); }, } break :tag .done; @@ -2950,7 +3010,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo type_gop.value_ptr.* = nav_gop.value_ptr.*; } wip_nav.entry = nav_gop.value_ptr.*; - const diw = wip_nav.debug_info.writer(dwarf.gpa); + const dibw = &wip_nav.debug_info.buffered_writer; try wip_nav.declCommon(if (loaded_enum.names.len > 0) .{ .decl = .decl_enum, .generic_decl = .generic_decl_const, @@ -2969,7 +3029,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo }, field_index); try wip_nav.strp(loaded_enum.names.get(ip)[field_index].toSlice(ip)); } - if (loaded_enum.names.len > 0) try uleb128(diw, @intFromEnum(AbbrevCode.null)); + if (loaded_enum.names.len > 0) try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); break :tag .done; }, .union_type => tag: { @@ -2989,15 +3049,15 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo type_gop.value_ptr.* = nav_gop.value_ptr.*; } wip_nav.entry = nav_gop.value_ptr.*; - const diw = wip_nav.debug_info.writer(dwarf.gpa); + const dibw = &wip_nav.debug_info.buffered_writer; try wip_nav.declCommon(.{ .decl = .decl_union, .generic_decl = .generic_decl_const, .decl_instance = .decl_instance_union, }, &nav, inst_info.file, &decl); const union_layout = Type.getUnionLayout(loaded_union, zcu); - try uleb128(diw, union_layout.abi_size); - try uleb128(diw, union_layout.abi_align.toByteUnits().?); + try dibw.writeLeb128(union_layout.abi_size); + try dibw.writeLeb128(union_layout.abi_align.toByteUnits().?); const loaded_tag = loaded_union.loadTagType(ip); if (loaded_union.hasTag(ip)) { try wip_nav.abbrevCode(.tagged_union); @@ -3005,13 +3065,13 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo .debug_info, wip_nav.unit, wip_nav.entry, - @intCast(wip_nav.debug_info.items.len + dwarf.sectionOffsetBytes()), + @intCast(dibw.count + dwarf.sectionOffsetBytes()), ); { try wip_nav.abbrevCode(.generated_field); try wip_nav.strp("tag"); try wip_nav.refType(.fromInterned(loaded_union.enum_tag_ty)); - try uleb128(diw, union_layout.tagOffset()); + try dibw.writeLeb128(union_layout.tagOffset()); for (0..loaded_union.field_types.len) |field_index| { try wip_nav.enumConstValue(loaded_tag, .{ @@ -3024,23 +3084,23 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo 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); - try uleb128(diw, union_layout.payloadOffset()); - try uleb128(diw, loaded_union.fieldAlign(ip, field_index).toByteUnits() orelse + try dibw.writeLeb128(union_layout.payloadOffset()); + try dibw.writeLeb128(loaded_union.fieldAlign(ip, field_index).toByteUnits() orelse if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?); } - try uleb128(diw, @intFromEnum(AbbrevCode.null)); + try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); } } - try uleb128(diw, @intFromEnum(AbbrevCode.null)); + try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); } else for (0..loaded_union.field_types.len) |field_index| { 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); - try uleb128(diw, loaded_union.fieldAlign(ip, field_index).toByteUnits() orelse + try dibw.writeLeb128(loaded_union.fieldAlign(ip, field_index).toByteUnits() orelse field_type.abiAlignment(zcu).toByteUnits().?); } - try uleb128(diw, @intFromEnum(AbbrevCode.null)); + try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); break :tag .done; }, .opaque_type => tag: { @@ -3060,13 +3120,13 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo type_gop.value_ptr.* = nav_gop.value_ptr.*; } wip_nav.entry = nav_gop.value_ptr.*; - const diw = wip_nav.debug_info.writer(dwarf.gpa); + const dibw = &wip_nav.debug_info.buffered_writer; try wip_nav.declCommon(.{ .decl = .decl_namespace_struct, .generic_decl = .generic_decl_const, .decl_instance = .decl_instance_namespace_struct, }, &nav, inst_info.file, &decl); - try diw.writeByte(@intFromBool(true)); + try dibw.writeByte(@intFromBool(true)); break :tag .done; }, .undef, @@ -3104,7 +3164,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo const is_nullary = !func_type.is_var_args and for (0..func_type.param_types.len) |param_index| { if (!func_type.paramIsComptime(std.math.cast(u5, param_index) orelse break false)) break false; } else true; - const diw = wip_nav.debug_info.writer(dwarf.gpa); + const dibw = &wip_nav.debug_info.buffered_writer; try wip_nav.declCommon(if (is_nullary) .{ .decl = .decl_nullary_func_generic, .generic_decl = .generic_decl_func, @@ -3123,7 +3183,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo try wip_nav.refType(.fromInterned(func_type.param_types.get(ip)[param_index])); } if (func_type.is_var_args) try wip_nav.abbrevCode(.is_var_args); - try uleb128(diw, @intFromEnum(AbbrevCode.null)); + try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); } break :tag .done; }, @@ -3148,7 +3208,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo try wip_nav.refType(nav_val.toType()); }, .decl_var => { - const diw = wip_nav.debug_info.writer(dwarf.gpa); + const dibw = &wip_nav.debug_info.buffered_writer; try wip_nav.declCommon(.{ .decl = .decl_var, .generic_decl = .generic_decl_var, @@ -3158,12 +3218,12 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo const nav_ty = nav_val.typeOf(zcu); try wip_nav.refType(nav_ty); try wip_nav.blockValue(nav_src_loc, nav_val); - try uleb128(diw, nav.status.fully_resolved.alignment.toByteUnits() orelse + try dibw.writeLeb128(nav.status.fully_resolved.alignment.toByteUnits() orelse nav_ty.abiAlignment(zcu).toByteUnits().?); - try diw.writeByte(@intFromBool(decl.linkage != .normal)); + try dibw.writeByte(@intFromBool(decl.linkage != .normal)); }, .decl_const => { - const diw = wip_nav.debug_info.writer(dwarf.gpa); + const dibw = &wip_nav.debug_info.buffered_writer; const nav_ty = nav_val.typeOf(zcu); const has_runtime_bits = nav_ty.hasRuntimeBits(zcu); const has_comptime_state = nav_ty.comptimeOnly(zcu) and try nav_ty.onePossibleValue(pt) == null; @@ -3186,9 +3246,9 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo }, &nav, inst_info.file, &decl); try wip_nav.strp(nav.fqn.toSlice(ip)); const nav_ty_reloc_index = try wip_nav.refForward(); - try uleb128(diw, nav.status.fully_resolved.alignment.toByteUnits() orelse + try dibw.writeLeb128(nav.status.fully_resolved.alignment.toByteUnits() orelse nav_ty.abiAlignment(zcu).toByteUnits().?); - try diw.writeByte(@intFromBool(decl.linkage != .normal)); + try dibw.writeByte(@intFromBool(decl.linkage != .normal)); if (has_runtime_bits) try wip_nav.blockValue(nav_src_loc, nav_val); if (has_comptime_state) try wip_nav.refValue(nav_val); wip_nav.finishForward(nav_ty_reloc_index); @@ -3204,7 +3264,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo try wip_nav.refNav(owner_nav); }, } - try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items); + try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.getWritten()); try wip_nav.updateLazy(nav_src_loc); } @@ -3235,18 +3295,19 @@ fn updateLazyType( .func_high_pc = undefined, .blocks = undefined, .cfi = undefined, - .debug_frame = .empty, - .debug_info = .empty, - .debug_line = .empty, - .debug_loclists = .empty, + .debug_frame = undefined, + .debug_info = undefined, + .debug_line = undefined, + .debug_loclists = undefined, .pending_lazy = pending_lazy.*, }; + wip_nav.init(); defer { pending_lazy.* = wip_nav.pending_lazy; wip_nav.pending_lazy = .empty; wip_nav.deinit(); } - const diw = wip_nav.debug_info.writer(dwarf.gpa); + const dibw = &wip_nav.debug_info.buffered_writer; const name = switch (type_index) { .generic_poison_type => "", else => try std.fmt.allocPrint(dwarf.gpa, "{f}", .{ty.fmt(pt)}), @@ -3261,12 +3322,12 @@ fn updateLazyType( .int_type => |int_type| { try wip_nav.abbrevCode(.numeric_type); try wip_nav.strp(name); - try diw.writeByte(switch (int_type.signedness) { + try dibw.writeByte(switch (int_type.signedness) { inline .signed, .unsigned => |signedness| @field(DW.ATE, @tagName(signedness)), }); - try uleb128(diw, int_type.bits); - try uleb128(diw, ty.abiSize(zcu)); - try uleb128(diw, ty.abiAlignment(zcu).toByteUnits().?); + try dibw.writeLeb128(int_type.bits); + try dibw.writeLeb128(ty.abiSize(zcu)); + try dibw.writeLeb128(ty.abiAlignment(zcu).toByteUnits().?); }, .ptr_type => |ptr_type| switch (ptr_type.flags.size) { .one, .many, .c => { @@ -3274,14 +3335,14 @@ fn updateLazyType( try wip_nav.abbrevCode(if (ptr_type.sentinel == .none) .ptr_type else .ptr_sentinel_type); try wip_nav.strp(name); if (ptr_type.sentinel != .none) try wip_nav.blockValue(src_loc, .fromInterned(ptr_type.sentinel)); - try uleb128(diw, ptr_type.flags.alignment.toByteUnits() orelse + try dibw.writeLeb128(ptr_type.flags.alignment.toByteUnits() orelse ptr_child_type.abiAlignment(zcu).toByteUnits().?); - try diw.writeByte(@intFromEnum(ptr_type.flags.address_space)); + try dibw.writeByte(@intFromEnum(ptr_type.flags.address_space)); if (ptr_type.flags.is_const or ptr_type.flags.is_volatile) try wip_nav.infoSectionOffset( .debug_info, wip_nav.unit, wip_nav.entry, - @intCast(wip_nav.debug_info.items.len + dwarf.sectionOffsetBytes()), + @intCast(dibw.count + dwarf.sectionOffsetBytes()), ) else try wip_nav.refType(ptr_child_type); if (ptr_type.flags.is_const) { try wip_nav.abbrevCode(.is_const); @@ -3289,7 +3350,7 @@ fn updateLazyType( .debug_info, wip_nav.unit, wip_nav.entry, - @intCast(wip_nav.debug_info.items.len + dwarf.sectionOffsetBytes()), + @intCast(dibw.count + dwarf.sectionOffsetBytes()), ) else try wip_nav.refType(ptr_child_type); } if (ptr_type.flags.is_volatile) { @@ -3300,19 +3361,19 @@ fn updateLazyType( .slice => { try wip_nav.abbrevCode(.generated_struct_type); try wip_nav.strp(name); - try uleb128(diw, ty.abiSize(zcu)); - try uleb128(diw, ty.abiAlignment(zcu).toByteUnits().?); + try dibw.writeLeb128(ty.abiSize(zcu)); + try dibw.writeLeb128(ty.abiAlignment(zcu).toByteUnits().?); 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 dibw.writeUleb128(0); try wip_nav.abbrevCode(.generated_field); try wip_nav.strp("len"); const len_field_type: Type = .usize; try wip_nav.refType(len_field_type); - try uleb128(diw, len_field_type.abiAlignment(zcu).forward(ptr_field_type.abiSize(zcu))); - try uleb128(diw, @intFromEnum(AbbrevCode.null)); + try dibw.writeLeb128(len_field_type.abiAlignment(zcu).forward(ptr_field_type.abiSize(zcu))); + try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); }, }, .array_type => |array_type| { @@ -3323,8 +3384,8 @@ fn updateLazyType( try wip_nav.refType(array_child_type); try wip_nav.abbrevCode(.array_index); try wip_nav.refType(.usize); - try uleb128(diw, array_type.len); - try uleb128(diw, @intFromEnum(AbbrevCode.null)); + try dibw.writeLeb128(array_type.len); + try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); }, .vector_type => |vector_type| { try wip_nav.abbrevCode(.vector_type); @@ -3332,22 +3393,22 @@ fn updateLazyType( try wip_nav.refType(.fromInterned(vector_type.child)); try wip_nav.abbrevCode(.array_index); try wip_nav.refType(.usize); - try uleb128(diw, vector_type.len); - try uleb128(diw, @intFromEnum(AbbrevCode.null)); + try dibw.writeLeb128(vector_type.len); + try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); }, .opt_type => |opt_child_type_index| { const opt_child_type: Type = .fromInterned(opt_child_type_index); const opt_repr = optRepr(opt_child_type, zcu); try wip_nav.abbrevCode(.generated_union_type); try wip_nav.strp(name); - try uleb128(diw, ty.abiSize(zcu)); - try uleb128(diw, ty.abiAlignment(zcu).toByteUnits().?); + try dibw.writeLeb128(ty.abiSize(zcu)); + try dibw.writeLeb128(ty.abiAlignment(zcu).toByteUnits().?); switch (opt_repr) { .opv_null => { try wip_nav.abbrevCode(.generated_field); try wip_nav.strp("null"); try wip_nav.refType(.null); - try uleb128(diw, 0); + try dibw.writeUleb128(0); }, .unpacked, .error_set, .pointer => { try wip_nav.abbrevCode(.tagged_union); @@ -3355,7 +3416,7 @@ fn updateLazyType( .debug_info, wip_nav.unit, wip_nav.entry, - @intCast(wip_nav.debug_info.items.len + dwarf.sectionOffsetBytes()), + @intCast(dibw.count + dwarf.sectionOffsetBytes()), ); { try wip_nav.abbrevCode(.generated_field); @@ -3364,7 +3425,7 @@ fn updateLazyType( .opv_null => unreachable, .unpacked => { try wip_nav.refType(.bool); - try uleb128(diw, if (opt_child_type.hasRuntimeBits(zcu)) + try dibw.writeLeb128(if (opt_child_type.hasRuntimeBits(zcu)) opt_child_type.abiSize(zcu) else 0); @@ -3374,37 +3435,37 @@ fn updateLazyType( .signedness = .unsigned, .bits = zcu.errorSetBits(), } }))); - try uleb128(diw, 0); + try dibw.writeUleb128(0); }, .pointer => { try wip_nav.refType(.usize); - try uleb128(diw, 0); + try dibw.writeUleb128(0); }, } try wip_nav.abbrevCode(.unsigned_tagged_union_field); - try uleb128(diw, 0); + try dibw.writeUleb128(0); { try wip_nav.abbrevCode(.generated_field); try wip_nav.strp("null"); try wip_nav.refType(.null); - try uleb128(diw, 0); + try dibw.writeUleb128(0); } - try uleb128(diw, @intFromEnum(AbbrevCode.null)); + try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); try wip_nav.abbrevCode(.tagged_union_default_field); { try wip_nav.abbrevCode(.generated_field); try wip_nav.strp("?"); try wip_nav.refType(opt_child_type); - try uleb128(diw, 0); + try dibw.writeUleb128(0); } - try uleb128(diw, @intFromEnum(AbbrevCode.null)); + try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); } - try uleb128(diw, @intFromEnum(AbbrevCode.null)); + try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); }, } - try uleb128(diw, @intFromEnum(AbbrevCode.null)); + try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); }, .anyframe_type => unreachable, .error_union_type => |error_union_type| { @@ -3423,11 +3484,11 @@ fn updateLazyType( if (error_union_type.error_set_type != .generic_poison_type and error_union_type.payload_type != .generic_poison_type) { - try uleb128(diw, ty.abiSize(zcu)); - try uleb128(diw, ty.abiAlignment(zcu).toByteUnits().?); + try dibw.writeLeb128(ty.abiSize(zcu)); + try dibw.writeLeb128(ty.abiAlignment(zcu).toByteUnits().?); } else { - try uleb128(diw, 0); - try uleb128(diw, 1); + try dibw.writeUleb128(0); + try dibw.writeUleb128(1); } { try wip_nav.abbrevCode(.tagged_union); @@ -3435,7 +3496,7 @@ fn updateLazyType( .debug_info, wip_nav.unit, wip_nav.entry, - @intCast(wip_nav.debug_info.items.len + dwarf.sectionOffsetBytes()), + @intCast(dibw.count + dwarf.sectionOffsetBytes()), ); { try wip_nav.abbrevCode(.generated_field); @@ -3444,30 +3505,30 @@ fn updateLazyType( .signedness = .unsigned, .bits = zcu.errorSetBits(), } }))); - try uleb128(diw, error_union_error_set_offset); + try dibw.writeLeb128(error_union_error_set_offset); try wip_nav.abbrevCode(.unsigned_tagged_union_field); - try uleb128(diw, 0); + try dibw.writeUleb128(0); { 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 dibw.writeLeb128(error_union_payload_offset); } - try uleb128(diw, @intFromEnum(AbbrevCode.null)); + try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); try wip_nav.abbrevCode(.tagged_union_default_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); + try dibw.writeLeb128(error_union_error_set_offset); } - try uleb128(diw, @intFromEnum(AbbrevCode.null)); + try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); } - try uleb128(diw, @intFromEnum(AbbrevCode.null)); + try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); } - try uleb128(diw, @intFromEnum(AbbrevCode.null)); + try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); }, .simple_type => |simple_type| switch (simple_type) { .f16, @@ -3491,7 +3552,7 @@ fn updateLazyType( => { try wip_nav.abbrevCode(.numeric_type); try wip_nav.strp(name); - try diw.writeByte(if (type_index == .bool_type) + try dibw.writeByte(if (type_index == .bool_type) DW.ATE.boolean else if (ty.isRuntimeFloat()) DW.ATE.float @@ -3501,9 +3562,9 @@ fn updateLazyType( DW.ATE.unsigned else unreachable); - try uleb128(diw, ty.bitSize(zcu)); - try uleb128(diw, ty.abiSize(zcu)); - try uleb128(diw, ty.abiAlignment(zcu).toByteUnits().?); + try dibw.writeLeb128(ty.bitSize(zcu)); + try dibw.writeLeb128(ty.abiSize(zcu)); + try dibw.writeLeb128(ty.abiAlignment(zcu).toByteUnits().?); }, .anyopaque, .void, @@ -3529,12 +3590,12 @@ fn updateLazyType( .tuple_type => |tuple_type| if (tuple_type.types.len == 0) { try wip_nav.abbrevCode(.generated_empty_struct_type); try wip_nav.strp(name); - try diw.writeByte(@intFromBool(false)); + try dibw.writeByte(@intFromBool(false)); } else { try wip_nav.abbrevCode(.generated_struct_type); try wip_nav.strp(name); - try uleb128(diw, ty.abiSize(zcu)); - try uleb128(diw, ty.abiAlignment(zcu).toByteUnits().?); + try dibw.writeLeb128(ty.abiSize(zcu)); + try dibw.writeLeb128(ty.abiAlignment(zcu).toByteUnits().?); var field_byte_offset: u64 = 0; for (0..tuple_type.types.len) |field_index| { const comptime_value = tuple_type.values.get(ip)[field_index]; @@ -3563,8 +3624,8 @@ fn updateLazyType( if (comptime_value == .none) { const field_align = field_type.abiAlignment(zcu); field_byte_offset = field_align.forward(field_byte_offset); - try uleb128(diw, field_byte_offset); - try uleb128(diw, field_type.abiAlignment(zcu).toByteUnits().?); + try dibw.writeLeb128(field_byte_offset); + try dibw.writeLeb128(field_type.abiAlignment(zcu).toByteUnits().?); field_byte_offset += field_type.abiSize(zcu); } if (has_comptime_state) @@ -3572,7 +3633,7 @@ fn updateLazyType( else if (has_runtime_bits) try wip_nav.blockValue(src_loc, .fromInterned(comptime_value)); } - try uleb128(diw, @intFromEnum(AbbrevCode.null)); + try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); }, .enum_type => { const loaded_enum = ip.loadEnumType(type_index); @@ -3587,7 +3648,7 @@ fn updateLazyType( }, field_index); try wip_nav.strp(loaded_enum.names.get(ip)[field_index].toSlice(ip)); } - if (loaded_enum.names.len > 0) try uleb128(diw, @intFromEnum(AbbrevCode.null)); + if (loaded_enum.names.len > 0) try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); }, .func_type => |func_type| { const is_nullary = func_type.param_types.len == 0 and !func_type.is_var_args; @@ -3655,7 +3716,7 @@ fn updateLazyType( else => .nocall, }; }; - try diw.writeByte(@intFromEnum(cc)); + try dibw.writeByte(@intFromEnum(cc)); try wip_nav.refType(.fromInterned(func_type.return_type)); if (!is_nullary) { for (0..func_type.param_types.len) |param_index| { @@ -3663,7 +3724,7 @@ fn updateLazyType( try wip_nav.refType(.fromInterned(func_type.param_types.get(ip)[param_index])); } if (func_type.is_var_args) try wip_nav.abbrevCode(.is_var_args); - try uleb128(diw, @intFromEnum(AbbrevCode.null)); + try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); } }, .error_set_type => |error_set_type| { @@ -3676,10 +3737,10 @@ fn updateLazyType( for (0..error_set_type.names.len) |field_index| { const field_name = error_set_type.names.get(ip)[field_index]; try wip_nav.abbrevCode(.unsigned_enum_field); - try uleb128(diw, ip.getErrorValueIfExists(field_name).?); + try dibw.writeLeb128(ip.getErrorValueIfExists(field_name).?); try wip_nav.strp(field_name.toSlice(ip)); } - if (error_set_type.names.len > 0) try uleb128(diw, @intFromEnum(AbbrevCode.null)); + if (error_set_type.names.len > 0) try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); }, .inferred_error_set_type => |func| { try wip_nav.abbrevCode(.inferred_error_set_type); @@ -3711,7 +3772,7 @@ fn updateLazyType( .memoized_call, => unreachable, } - try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items); + try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.getWritten()); } fn updateLazyValue( @@ -3739,18 +3800,19 @@ fn updateLazyValue( .func_high_pc = undefined, .blocks = undefined, .cfi = undefined, - .debug_frame = .empty, - .debug_info = .empty, - .debug_line = .empty, - .debug_loclists = .empty, + .debug_frame = undefined, + .debug_info = undefined, + .debug_line = undefined, + .debug_loclists = undefined, .pending_lazy = pending_lazy.*, }; + wip_nav.init(); defer { pending_lazy.* = wip_nav.pending_lazy; wip_nav.pending_lazy = .empty; wip_nav.deinit(); } - const diw = wip_nav.debug_info.writer(dwarf.gpa); + const dibw = &wip_nav.debug_info.buffered_writer; var big_int_space: Value.BigIntSpace = undefined; switch (ip.indexToKey(value_index)) { .int_type, @@ -3788,7 +3850,7 @@ fn updateLazyValue( .err => |err| { try wip_nav.abbrevCode(.udata_comptime_value); try wip_nav.refType(.fromInterned(err.ty)); - try uleb128(diw, try pt.getErrorValue(err.name)); + try dibw.writeLeb128(try pt.getErrorValue(err.name)); }, .error_union => |error_union| { try wip_nav.abbrevCode(.aggregate_comptime_value); @@ -3800,8 +3862,8 @@ fn updateLazyValue( { try wip_nav.abbrevCode(.comptime_value_field_runtime_bits); try wip_nav.strp("is_error"); - try uleb128(diw, err_abi_size); - dwarf.writeInt(try wip_nav.debug_info.addManyAsSlice(dwarf.gpa, err_abi_size), err_value); + try dibw.writeLeb128(err_abi_size); + try dwarf.writeIntTo(dibw, err_abi_size, err_value); } payload_field: switch (error_union.val) { .err_name => {}, @@ -3825,8 +3887,8 @@ fn updateLazyValue( { try wip_nav.abbrevCode(.comptime_value_field_runtime_bits); try wip_nav.strp("error"); - try uleb128(diw, err_abi_size); - dwarf.writeInt(try wip_nav.debug_info.addManyAsSlice(dwarf.gpa, err_abi_size), err_value); + try dibw.writeLeb128(err_abi_size); + try dwarf.writeIntTo(dibw, err_abi_size, err_value); } switch (error_union.val) { .err_name => {}, @@ -3836,7 +3898,7 @@ fn updateLazyValue( }, } try wip_nav.refType(.fromInterned(error_union.ty)); - try uleb128(diw, @intFromEnum(AbbrevCode.null)); + try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); }, .enum_literal => |enum_literal| { try wip_nav.abbrevCode(.string_comptime_value); @@ -3857,24 +3919,24 @@ fn updateLazyValue( switch (float.storage) { .f16 => |f16_val| { try wip_nav.abbrevCode(.data2_comptime_value); - try diw.writeInt(u16, @bitCast(f16_val), dwarf.endian); + try dibw.writeInt(u16, @bitCast(f16_val), dwarf.endian); }, .f32 => |f32_val| { try wip_nav.abbrevCode(.data4_comptime_value); - try diw.writeInt(u32, @bitCast(f32_val), dwarf.endian); + try dibw.writeInt(u32, @bitCast(f32_val), dwarf.endian); }, .f64 => |f64_val| { try wip_nav.abbrevCode(.data8_comptime_value); - try diw.writeInt(u64, @bitCast(f64_val), dwarf.endian); + try dibw.writeInt(u64, @bitCast(f64_val), dwarf.endian); }, .f80 => |f80_val| { try wip_nav.abbrevCode(.block_comptime_value); - try uleb128(diw, @divExact(80, 8)); - try diw.writeInt(u80, @bitCast(f80_val), dwarf.endian); + try dibw.writeUleb128(@divExact(80, 8)); + try dibw.writeInt(u80, @bitCast(f80_val), dwarf.endian); }, .f128 => |f128_val| { try wip_nav.abbrevCode(.data16_comptime_value); - try diw.writeInt(u128, @bitCast(f128_val), dwarf.endian); + try dibw.writeInt(u128, @bitCast(f128_val), dwarf.endian); }, } try wip_nav.refType(.fromInterned(float.ty)); @@ -3891,14 +3953,14 @@ fn updateLazyValue( const uav_ty: Type = .fromInterned(ip.typeOf(uav.val)); if (try uav_ty.onePossibleValue(pt)) |_| { try wip_nav.abbrevCode(.udata_comptime_value); - try uleb128(diw, ip.indexToKey(uav.orig_ty).ptr_type.flags.alignment.toByteUnits() orelse + try dibw.writeLeb128(ip.indexToKey(uav.orig_ty).ptr_type.flags.alignment.toByteUnits() orelse uav_ty.abiAlignment(zcu).toByteUnits().?); break :location; } else break try wip_nav.getValueEntry(.fromInterned(uav.val)); }, .int => { try wip_nav.abbrevCode(.udata_comptime_value); - try uleb128(diw, byte_offset); + try dibw.writeLeb128(byte_offset); break :location; }, .eu_payload => |eu_ptr| { @@ -3937,7 +3999,7 @@ fn updateLazyValue( try wip_nav.strp("len"); try wip_nav.blockValue(src_loc, .fromInterned(slice.len)); } - try uleb128(diw, @intFromEnum(AbbrevCode.null)); + try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); }, .opt => |opt| { const opt_child_type: Type = .fromInterned(ip.indexToKey(opt.ty).opt_type); @@ -3947,7 +4009,7 @@ fn updateLazyValue( try wip_nav.abbrevCode(.comptime_value_field_runtime_bits); try wip_nav.strp("has_value"); switch (optRepr(opt_child_type, zcu)) { - .opv_null => try uleb128(diw, 0), + .opv_null => try dibw.writeUleb128(0), .unpacked => try wip_nav.blockValue(src_loc, .makeBool(opt.val != .none)), .error_set => try wip_nav.blockValue(src_loc, .fromInterned(value_index)), .pointer => if (opt_child_type.comptimeOnly(zcu)) { @@ -3957,8 +4019,8 @@ fn updateLazyValue( .none => 0, else => opt_child_type.ptrAlignment(zcu).toByteUnits().?, }); - try uleb128(diw, bytes.len); - try diw.writeAll(bytes); + try dibw.writeLeb128(bytes.len); + try dibw.writeAll(bytes); } else try wip_nav.blockValue(src_loc, .fromInterned(value_index)), } } @@ -3977,7 +4039,7 @@ fn updateLazyValue( else try wip_nav.blockValue(src_loc, .fromInterned(opt.val)); } - try uleb128(diw, @intFromEnum(AbbrevCode.null)); + try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); }, .aggregate => |aggregate| { try wip_nav.abbrevCode(.aggregate_comptime_value); @@ -4062,7 +4124,7 @@ fn updateLazyValue( }, else => unreachable, } - try uleb128(diw, @intFromEnum(AbbrevCode.null)); + try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); }, .un => |un| { try wip_nav.abbrevCode(.aggregate_comptime_value); @@ -4087,11 +4149,11 @@ fn updateLazyValue( else try wip_nav.blockValue(src_loc, .fromInterned(un.val)); } - try uleb128(diw, @intFromEnum(AbbrevCode.null)); + try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); }, .memoized_call => unreachable, // not a value } - try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items); + try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.getWritten()); } fn optRepr(opt_child_type: Type, zcu: *const Zcu) enum { @@ -4111,7 +4173,7 @@ fn optRepr(opt_child_type: Type, zcu: *const Zcu) enum { }; } -pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternPool.Index) UpdateError!void { +fn updateContainerTypeInner(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternPool.Index) UpdateError!void { const zcu = pt.zcu; const ip = &zcu.intern_pool; const ty: Type = .fromInterned(type_index); @@ -4438,25 +4500,26 @@ fn refAbbrevCode(dwarf: *Dwarf, abbrev_code: AbbrevCode) UpdateError!@typeInfo(A 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(); + var daaw: std.io.Writer.Allocating = .init(dwarf.gpa); + defer daaw.deinit(); + const dabw = &daaw.interface; 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); + try dabw.writeLeb128(@intFromEnum(abbrev_code)); + try dabw.writeLeb128(@intFromEnum(abbrev.tag)); + try dabw.writeByte(if (abbrev.children) DW.CHILDREN.yes else DW.CHILDREN.no); + for (abbrev.attrs) |*attr| inline for (attr) |info| try dabw.writeLeb128(@intFromEnum(info)); + for (0..2) |_| try dabw.writeUleb128(0); + try dwarf.debug_abbrev.section.replaceEntry(DebugAbbrev.unit, entry, dwarf, daaw.getWritten()); return @intFromEnum(abbrev_code); } pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { + const gpa = dwarf.gpa; const zcu = pt.zcu; const ip = &zcu.intern_pool; { - const type_gop = try dwarf.types.getOrPut(dwarf.gpa, .anyerror_type); + const type_gop = try dwarf.types.getOrPut(gpa, .anyerror_type); if (!type_gop.found_existing) type_gop.value_ptr.* = try dwarf.addCommonEntry(.main); var wip_nav: WipNav = .{ .dwarf = dwarf, @@ -4469,14 +4532,15 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { .func_high_pc = undefined, .blocks = undefined, .cfi = undefined, - .debug_frame = .empty, - .debug_info = .empty, - .debug_line = .empty, - .debug_loclists = .empty, + .debug_frame = undefined, + .debug_info = undefined, + .debug_line = undefined, + .debug_loclists = undefined, .pending_lazy = .empty, }; + wip_nav.init(); defer wip_nav.deinit(); - const diw = wip_nav.debug_info.writer(dwarf.gpa); + const dibw = &wip_nav.debug_info.buffered_writer; const global_error_set_names = ip.global_error_set.getNamesFromMainThread(); try wip_nav.abbrevCode(if (global_error_set_names.len == 0) .generated_empty_enum_type else .generated_enum_type); try wip_nav.strp("anyerror"); @@ -4486,50 +4550,52 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { } }))); for (global_error_set_names, 1..) |name, value| { try wip_nav.abbrevCode(.unsigned_enum_field); - try uleb128(diw, value); + try dibw.writeLeb128(value); try wip_nav.strp(name.toSlice(ip)); } - if (global_error_set_names.len > 0) try uleb128(diw, @intFromEnum(AbbrevCode.null)); - try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items); + if (global_error_set_names.len > 0) try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); + try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, dibw.getWritten()); try wip_nav.updateLazy(.unneeded); } for (dwarf.mods.keys(), dwarf.mods.values()) |mod, *mod_info| { - const root_dir_path = try mod.root.toAbsolute(zcu.comp.dirs, dwarf.gpa); - defer dwarf.gpa.free(root_dir_path); + const root_dir_path = try mod.root.toAbsolute(zcu.comp.dirs, gpa); + defer gpa.free(root_dir_path); mod_info.root_dir_path = try dwarf.debug_line_str.addString(dwarf, root_dir_path); } - var header: std.ArrayList(u8) = .init(dwarf.gpa); - defer header.deinit(); + var header: std.ArrayListUnmanaged(u8) = .empty; + defer header.deinit(gpa); + var header_bw: Writer = undefined; 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); unit_ptr.clear(); - try unit_ptr.cross_section_relocs.ensureTotalCapacity(dwarf.gpa, 1); - header.clearRetainingCapacity(); - try header.ensureTotalCapacity(unit_ptr.header_len); + try unit_ptr.cross_section_relocs.ensureTotalCapacity(gpa, 1); + try header.resize(gpa, unit_ptr.header_len); + header_bw = .fixed(header.items); const unit_len = (if (unit_ptr.next.unwrap()) |next_unit| dwarf.debug_aranges.section.getUnit(next_unit).off else dwarf.debug_aranges.section.len) - unit_ptr.off - dwarf.unitLengthBytes(); switch (dwarf.format) { - .@"32" => std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), @intCast(unit_len), dwarf.endian), + .@"32" => header_bw.writeInt(u32, @intCast(unit_len), dwarf.endian) catch unreachable, .@"64" => { - std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), std.math.maxInt(u32), dwarf.endian); - std.mem.writeInt(u64, header.addManyAsArrayAssumeCapacity(8), unit_len, dwarf.endian); + header_bw.writeInt(u32, std.math.maxInt(u32), dwarf.endian) catch unreachable; + header_bw.writeInt(u64, unit_len, dwarf.endian) catch unreachable; }, } - std.mem.writeInt(u16, header.addManyAsArrayAssumeCapacity(2), 2, dwarf.endian); + header_bw.writeInt(u16, 2, dwarf.endian) catch unreachable; unit_ptr.cross_section_relocs.appendAssumeCapacity(.{ - .source_off = @intCast(header.items.len), + .source_off = @intCast(header_bw.end), .target_sec = .debug_info, .target_unit = unit, }); - header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes()); - header.appendSliceAssumeCapacity(&.{ @intFromEnum(dwarf.address_size), 0 }); - header.appendNTimesAssumeCapacity(0, unit_ptr.header_len - header.items.len); - try unit_ptr.replaceHeader(&dwarf.debug_aranges.section, dwarf, header.items); + header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable; + header_bw.writeAll(&.{ @intFromEnum(dwarf.address_size), 0 }) catch unreachable; + header_bw.splatByteAll(0, unit_ptr.header_len - header_bw.end) catch unreachable; + assert(header_bw.end == header_bw.buffer.len); + try unit_ptr.replaceHeader(&dwarf.debug_aranges.section, dwarf, header_bw.buffer); try unit_ptr.writeTrailer(&dwarf.debug_aranges.section, dwarf); } dwarf.debug_aranges.section.dirty = false; @@ -4544,31 +4610,33 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { dev.check(.x86_64_backend); const Register = @import("../arch/x86_64/bits.zig").Register; for (dwarf.debug_frame.section.units.items) |*unit| { - header.clearRetainingCapacity(); - try header.ensureTotalCapacity(unit.header_len); + try header.resize(gpa, unit.header_len); + header_bw = .fixed(header.items); const unit_len = unit.header_len - dwarf.unitLengthBytes(); switch (dwarf.format) { - .@"32" => std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), @intCast(unit_len), dwarf.endian), + .@"32" => header_bw.writeInt(u32, @intCast(unit_len), dwarf.endian) catch unreachable, .@"64" => { - std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), std.math.maxInt(u32), dwarf.endian); - std.mem.writeInt(u64, header.addManyAsArrayAssumeCapacity(8), unit_len, dwarf.endian); + header_bw.writeInt(u32, std.math.maxInt(u32), dwarf.endian) catch unreachable; + header_bw.writeInt(u64, unit_len, dwarf.endian) catch unreachable; }, } - header.appendNTimesAssumeCapacity(0, 4); - header.appendAssumeCapacity(1); - header.appendSliceAssumeCapacity("zR\x00"); - uleb128(header.fixedWriter(), dwarf.debug_frame.header.code_alignment_factor) catch unreachable; - sleb128(header.fixedWriter(), dwarf.debug_frame.header.data_alignment_factor) catch unreachable; - uleb128(header.fixedWriter(), dwarf.debug_frame.header.return_address_register) catch unreachable; - uleb128(header.fixedWriter(), 1) catch unreachable; - header.appendAssumeCapacity(DW.EH.PE.pcrel | DW.EH.PE.sdata4); - header.appendAssumeCapacity(DW.CFA.def_cfa_sf); - uleb128(header.fixedWriter(), Register.rsp.dwarfNum()) catch unreachable; - sleb128(header.fixedWriter(), -1) catch unreachable; - header.appendAssumeCapacity(@as(u8, DW.CFA.offset) + Register.rip.dwarfNum()); - uleb128(header.fixedWriter(), 1) catch unreachable; - header.appendNTimesAssumeCapacity(DW.CFA.nop, unit.header_len - header.items.len); - try unit.replaceHeader(&dwarf.debug_frame.section, dwarf, header.items); + header_bw.splatByteAll(0, 4) catch unreachable; + header_bw.writeByte(1) catch unreachable; + header_bw.writeAll("zR\x00") catch unreachable; + header_bw.writeLeb128(dwarf.debug_frame.header.code_alignment_factor) catch unreachable; + header_bw.writeLeb128(dwarf.debug_frame.header.data_alignment_factor) catch unreachable; + header_bw.writeLeb128(dwarf.debug_frame.header.return_address_register) catch unreachable; + header_bw.writeUleb128(1) catch unreachable; + header_bw.writeByte(DW.EH.PE.pcrel | DW.EH.PE.sdata4) catch unreachable; + header_bw.writeByte(DW.CFA.def_cfa_sf) catch unreachable; + header_bw.writeUleb128(1) catch unreachable; + header_bw.writeLeb128(Register.rsp.dwarfNum()) catch unreachable; + header_bw.writeSleb128(-1) catch unreachable; + header_bw.writeByte(@as(u8, DW.CFA.offset) + Register.rip.dwarfNum()) catch unreachable; + header_bw.writeUleb128(1) catch unreachable; + header_bw.splatByteAll(DW.CFA.nop, unit.header_len - header_bw.end) catch unreachable; + assert(header_bw.end == header_bw.buffer.len); + try unit.replaceHeader(&dwarf.debug_frame.section, dwarf, header_bw.buffer); try unit.writeTrailer(&dwarf.debug_frame.section, dwarf); } }, @@ -4581,83 +4649,84 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { for (dwarf.mods.keys(), dwarf.mods.values(), dwarf.debug_info.section.units.items, 0..) |mod, mod_info, *unit_ptr, unit_index| { const unit: Unit.Index = @enumFromInt(unit_index); unit_ptr.clear(); - try unit_ptr.cross_unit_relocs.ensureTotalCapacity(dwarf.gpa, 1); - try unit_ptr.cross_section_relocs.ensureTotalCapacity(dwarf.gpa, 7); - header.clearRetainingCapacity(); - try header.ensureTotalCapacity(unit_ptr.header_len); + try unit_ptr.cross_unit_relocs.ensureTotalCapacity(gpa, 1); + try unit_ptr.cross_section_relocs.ensureTotalCapacity(gpa, 7); + try header.resize(gpa, unit_ptr.header_len); + header_bw = .fixed(header.items); const unit_len = (if (unit_ptr.next.unwrap()) |next_unit| dwarf.debug_info.section.getUnit(next_unit).off else dwarf.debug_info.section.len) - unit_ptr.off - dwarf.unitLengthBytes(); switch (dwarf.format) { - .@"32" => std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), @intCast(unit_len), dwarf.endian), + .@"32" => header_bw.writeInt(u32, @intCast(unit_len), dwarf.endian) catch unreachable, .@"64" => { - std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), std.math.maxInt(u32), dwarf.endian); - std.mem.writeInt(u64, header.addManyAsArrayAssumeCapacity(8), unit_len, dwarf.endian); + header_bw.writeInt(u32, std.math.maxInt(u32), dwarf.endian) catch unreachable; + header_bw.writeInt(u64, unit_len, dwarf.endian) catch unreachable; }, } - std.mem.writeInt(u16, header.addManyAsArrayAssumeCapacity(2), 5, dwarf.endian); - header.appendSliceAssumeCapacity(&.{ DW.UT.compile, @intFromEnum(dwarf.address_size) }); + header_bw.writeInt(u16, 5, dwarf.endian) catch unreachable; + header_bw.writeAll(&.{ DW.UT.compile, @intFromEnum(dwarf.address_size) }) catch unreachable; unit_ptr.cross_section_relocs.appendAssumeCapacity(.{ - .source_off = @intCast(header.items.len), + .source_off = @intCast(header_bw.end), .target_sec = .debug_abbrev, .target_unit = DebugAbbrev.unit, }); - header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes()); - const compile_unit_off: u32 = @intCast(header.items.len); - uleb128(header.fixedWriter(), try dwarf.refAbbrevCode(.compile_unit)) catch unreachable; - header.appendAssumeCapacity(DW.LANG.Zig); + header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable; + const compile_unit_off: u32 = @intCast(header_bw.end); + header_bw.writeLeb128(try dwarf.refAbbrevCode(.compile_unit)) catch unreachable; + header_bw.writeByte(DW.LANG.Zig) catch unreachable; unit_ptr.cross_section_relocs.appendAssumeCapacity(.{ - .source_off = @intCast(header.items.len), + .source_off = @intCast(header_bw.end), .target_sec = .debug_line_str, .target_unit = StringSection.unit, .target_entry = (try dwarf.debug_line_str.addString(dwarf, "zig " ++ @import("build_options").version)).toOptional(), }); - header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes()); + header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable; unit_ptr.cross_section_relocs.appendAssumeCapacity(.{ - .source_off = @intCast(header.items.len), + .source_off = @intCast(header_bw.end), .target_sec = .debug_line_str, .target_unit = StringSection.unit, .target_entry = mod_info.root_dir_path.toOptional(), }); - header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes()); + header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable; unit_ptr.cross_section_relocs.appendAssumeCapacity(.{ - .source_off = @intCast(header.items.len), + .source_off = @intCast(header_bw.end), .target_sec = .debug_line_str, .target_unit = StringSection.unit, .target_entry = (try dwarf.debug_line_str.addString(dwarf, mod.root_src_path)).toOptional(), }); - header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes()); + header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable; unit_ptr.cross_unit_relocs.appendAssumeCapacity(.{ - .source_off = @intCast(header.items.len), + .source_off = @intCast(header_bw.end), .target_unit = .main, .target_off = compile_unit_off, }); - header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes()); + header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable; unit_ptr.cross_section_relocs.appendAssumeCapacity(.{ - .source_off = @intCast(header.items.len), + .source_off = @intCast(header_bw.end), .target_sec = .debug_line, .target_unit = unit, }); - header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes()); + header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable; unit_ptr.cross_section_relocs.appendAssumeCapacity(.{ - .source_off = @intCast(header.items.len), + .source_off = @intCast(header_bw.end), .target_sec = .debug_rnglists, .target_unit = unit, .target_off = DebugRngLists.baseOffset(dwarf), }); - header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes()); - uleb128(header.fixedWriter(), 0) catch unreachable; - uleb128(header.fixedWriter(), try dwarf.refAbbrevCode(.module)) catch unreachable; + header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable; + header_bw.writeUleb128(0) catch unreachable; + header_bw.writeLeb128(try dwarf.refAbbrevCode(.module)) catch unreachable; unit_ptr.cross_section_relocs.appendAssumeCapacity(.{ - .source_off = @intCast(header.items.len), + .source_off = @intCast(header_bw.end), .target_sec = .debug_str, .target_unit = StringSection.unit, .target_entry = (try dwarf.debug_str.addString(dwarf, mod.fully_qualified_name)).toOptional(), }); - header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes()); - uleb128(header.fixedWriter(), 0) catch unreachable; - try unit_ptr.replaceHeader(&dwarf.debug_info.section, dwarf, header.items); + header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable; + header_bw.writeUleb128(0) catch unreachable; + assert(header_bw.end == header_bw.buffer.len); + try unit_ptr.replaceHeader(&dwarf.debug_info.section, dwarf, header_bw.buffer); try unit_ptr.writeTrailer(&dwarf.debug_info.section, dwarf); } dwarf.debug_info.section.dirty = false; @@ -4681,33 +4750,37 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { ); for (dwarf.mods.values(), dwarf.debug_line.section.units.items) |mod_info, *unit| { unit.clear(); - try unit.cross_section_relocs.ensureTotalCapacity(dwarf.gpa, mod_info.dirs.count() + 2 * (mod_info.files.count())); - header.clearRetainingCapacity(); - try header.ensureTotalCapacity(unit.header_len); + try unit.cross_section_relocs.ensureTotalCapacity(gpa, mod_info.dirs.count() + 2 * (mod_info.files.count())); + try header.resize(gpa, unit.header_len); + header_bw = .fixed(header.items); const unit_len = (if (unit.next.unwrap()) |next_unit| dwarf.debug_line.section.getUnit(next_unit).off else dwarf.debug_line.section.len) - unit.off - dwarf.unitLengthBytes(); switch (dwarf.format) { - .@"32" => std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), @intCast(unit_len), dwarf.endian), + .@"32" => header_bw.writeInt(u32, @intCast(unit_len), dwarf.endian) catch unreachable, .@"64" => { - std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), std.math.maxInt(u32), dwarf.endian); - std.mem.writeInt(u64, header.addManyAsArrayAssumeCapacity(8), unit_len, dwarf.endian); + header_bw.writeInt(u32, std.math.maxInt(u32), dwarf.endian) catch unreachable; + header_bw.writeInt(u64, unit_len, dwarf.endian) catch unreachable; }, } - std.mem.writeInt(u16, header.addManyAsArrayAssumeCapacity(2), 5, dwarf.endian); - header.appendSliceAssumeCapacity(&.{ @intFromEnum(dwarf.address_size), 0 }); - dwarf.writeInt(header.addManyAsSliceAssumeCapacity(dwarf.sectionOffsetBytes()), unit.header_len - header.items.len); + header_bw.writeInt(u16, 5, dwarf.endian) catch unreachable; + header_bw.writeAll(&.{ @intFromEnum(dwarf.address_size), 0 }) catch unreachable; + dwarf.writeIntTo( + &header_bw, + dwarf.sectionOffsetBytes(), + unit.header_len - header_bw.end, + ) catch unreachable; const StandardOpcode = DeclValEnum(DW.LNS); - header.appendSliceAssumeCapacity(&[_]u8{ + header_bw.writeAll(&.{ dwarf.debug_line.header.minimum_instruction_length, dwarf.debug_line.header.maximum_operations_per_instruction, @intFromBool(dwarf.debug_line.header.default_is_stmt), @bitCast(dwarf.debug_line.header.line_base), dwarf.debug_line.header.line_range, dwarf.debug_line.header.opcode_base, - }); - header.appendSliceAssumeCapacity(std.enums.EnumArray(StandardOpcode, u8).init(.{ + }) catch unreachable; + header_bw.writeAll(std.enums.EnumArray(StandardOpcode, u8).init(.{ .extended_op = undefined, .copy = 0, .advance_pc = 1, @@ -4721,44 +4794,45 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { .set_prologue_end = 0, .set_epilogue_begin = 0, .set_isa = 1, - }).values[1..dwarf.debug_line.header.opcode_base]); - header.appendAssumeCapacity(1); - uleb128(header.fixedWriter(), DW.LNCT.path) catch unreachable; - uleb128(header.fixedWriter(), DW.FORM.line_strp) catch unreachable; - uleb128(header.fixedWriter(), mod_info.dirs.count()) catch unreachable; + }).values[1..dwarf.debug_line.header.opcode_base]) catch unreachable; + header_bw.writeByte(1) catch unreachable; + header_bw.writeLeb128(@as(u14, DW.LNCT.path)) catch unreachable; + header_bw.writeLeb128(@as(u13, DW.FORM.line_strp)) catch unreachable; + header_bw.writeLeb128(mod_info.dirs.count()) catch unreachable; for (mod_info.dirs.keys()) |dir_unit| { unit.cross_section_relocs.appendAssumeCapacity(.{ - .source_off = @intCast(header.items.len), + .source_off = @intCast(header_bw.end), .target_sec = .debug_line_str, .target_unit = StringSection.unit, .target_entry = dwarf.getModInfo(dir_unit).root_dir_path.toOptional(), }); - header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes()); + header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable; } const dir_index_info = DebugLine.dirIndexInfo(@intCast(mod_info.dirs.count())); - header.appendAssumeCapacity(3); - uleb128(header.fixedWriter(), DW.LNCT.path) catch unreachable; - uleb128(header.fixedWriter(), DW.FORM.line_strp) catch unreachable; - uleb128(header.fixedWriter(), DW.LNCT.directory_index) catch unreachable; - uleb128(header.fixedWriter(), @intFromEnum(dir_index_info.form)) catch unreachable; - uleb128(header.fixedWriter(), DW.LNCT.LLVM_source) catch unreachable; - uleb128(header.fixedWriter(), DW.FORM.line_strp) catch unreachable; - uleb128(header.fixedWriter(), mod_info.files.count()) catch unreachable; + header_bw.writeByte(3) catch unreachable; + header_bw.writeLeb128(@as(u14, DW.LNCT.path)) catch unreachable; + header_bw.writeLeb128(@as(u13, DW.FORM.line_strp)) catch unreachable; + header_bw.writeLeb128(@as(u14, DW.LNCT.directory_index)) catch unreachable; + header_bw.writeLeb128(@intFromEnum(dir_index_info.form)) catch unreachable; + header_bw.writeLeb128(@as(u14, DW.LNCT.LLVM_source)) catch unreachable; + header_bw.writeLeb128(@as(u13, DW.FORM.line_strp)) catch unreachable; + header_bw.writeLeb128(mod_info.files.count()) catch unreachable; for (mod_info.files.keys()) |file_index| { const file = zcu.fileByIndex(file_index); unit.cross_section_relocs.appendAssumeCapacity(.{ - .source_off = @intCast(header.items.len), + .source_off = @intCast(header_bw.end), .target_sec = .debug_line_str, .target_unit = StringSection.unit, .target_entry = (try dwarf.debug_line_str.addString(dwarf, file.sub_file_path)).toOptional(), }); header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes()); - dwarf.writeInt( - header.addManyAsSliceAssumeCapacity(dir_index_info.bytes), + dwarf.writeIntTo( + &header_bw, + dir_index_info.bytes, mod_info.dirs.getIndex(dwarf.getUnitIfExists(file.mod.?).?) orelse 0, ); unit.cross_section_relocs.appendAssumeCapacity(.{ - .source_off = @intCast(header.items.len), + .source_off = @intCast(header_bw.end), .target_sec = .debug_line_str, .target_unit = StringSection.unit, .target_entry = (try dwarf.debug_line_str.addString( @@ -4766,9 +4840,10 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { if (file.is_builtin) file.source.? else "", )).toOptional(), }); - header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes()); + header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable; } - try unit.replaceHeader(&dwarf.debug_line.section, dwarf, header.items); + assert(header_bw.end == header_bw.buffer.len); + try unit.replaceHeader(&dwarf.debug_line.section, dwarf, header_bw.buffer); try unit.writeTrailer(&dwarf.debug_line.section, dwarf); } dwarf.debug_line.section.dirty = false; @@ -4784,24 +4859,25 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { } if (dwarf.debug_rnglists.section.dirty) { for (dwarf.debug_rnglists.section.units.items) |*unit| { - header.clearRetainingCapacity(); - try header.ensureTotalCapacity(unit.header_len); + try header.resize(gpa, unit.header_len); + header_bw = .fixed(header.items); const unit_len = (if (unit.next.unwrap()) |next_unit| dwarf.debug_rnglists.section.getUnit(next_unit).off else dwarf.debug_rnglists.section.len) - unit.off - dwarf.unitLengthBytes(); switch (dwarf.format) { - .@"32" => std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), @intCast(unit_len), dwarf.endian), + .@"32" => header_bw.writeInt(u32, @intCast(unit_len), dwarf.endian) catch unreachable, .@"64" => { - std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), std.math.maxInt(u32), dwarf.endian); - std.mem.writeInt(u64, header.addManyAsArrayAssumeCapacity(8), unit_len, dwarf.endian); + header_bw.writeInt(u32, std.math.maxInt(u32), dwarf.endian) catch unreachable; + header_bw.writeInt(u64, unit_len, dwarf.endian) catch unreachable; }, } - std.mem.writeInt(u16, header.addManyAsArrayAssumeCapacity(2), 5, dwarf.endian); - header.appendSliceAssumeCapacity(&.{ @intFromEnum(dwarf.address_size), 0 }); - std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), 1, dwarf.endian); - dwarf.writeInt(header.addManyAsSliceAssumeCapacity(dwarf.sectionOffsetBytes()), dwarf.sectionOffsetBytes() * 1); - try unit.replaceHeader(&dwarf.debug_rnglists.section, dwarf, header.items); + header_bw.writeInt(u16, 5, dwarf.endian) catch unreachable; + header_bw.writeAll(&.{ @intFromEnum(dwarf.address_size), 0 }) catch unreachable; + header_bw.writeInt(u32, 1, dwarf.endian) catch unreachable; + dwarf.writeIntTo(&header_bw, dwarf.sectionOffsetBytes(), dwarf.sectionOffsetBytes() * 1) catch unreachable; + assert(header_bw.end == header_bw.buffer.len); + try unit.replaceHeader(&dwarf.debug_rnglists.section, dwarf, header_bw.buffer); try unit.writeTrailer(&dwarf.debug_rnglists.section, dwarf); } dwarf.debug_rnglists.section.dirty = false; @@ -6000,6 +6076,10 @@ fn writeInt(dwarf: *Dwarf, buf: []u8, int: u64) void { } } +fn writeIntTo(dwarf: *Dwarf, bw: *Writer, len: usize, int: u64) !void { + dwarf.writeInt(try bw.writableSlice(len), int); +} + fn resolveReloc(dwarf: *Dwarf, source: u64, target: u64, size: u32) RelocError!void { var buf: [8]u8 = undefined; dwarf.writeInt(buf[0..size], target); @@ -6026,7 +6106,6 @@ fn uleb128Bytes(value: anytype) u32 { d.writer.writeUleb128(value) catch unreachable; return @intCast(d.count + d.writer.end); } - fn sleb128Bytes(value: anytype) u32 { var trash_buffer: [64]u8 = undefined; var d: std.Io.Writer.Discarding = .init(&trash_buffer); @@ -6053,7 +6132,7 @@ const codegen = @import("../codegen.zig"); const dev = @import("../dev.zig"); const link = @import("../link.zig"); const log = std.log.scoped(.dwarf); -const sleb128 = std.leb.writeIleb128; const std = @import("std"); const target_info = @import("../target.zig"); -const uleb128 = std.leb.writeUleb128; +const Allocator = std.mem.Allocator; +const Writer = std.io.Writer; From 281f657377c46180e0c7044e6ac0c7b8b69ef892 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 7 Aug 2025 22:06:31 -0700 Subject: [PATCH 3/4] Revert "random patches from another branch" This reverts commit 76ed05523d6327789a8365571b67a214ac527ef9. they don't work --- src/link/Dwarf.zig | 1351 +++++++++++++++++++++----------------------- 1 file changed, 636 insertions(+), 715 deletions(-) diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 06c99ebcae..f11ebc94d4 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -1,4 +1,4 @@ -gpa: Allocator, +gpa: std.mem.Allocator, bin_file: *link.File, format: DW.Format, endian: std.builtin.Endian, @@ -50,7 +50,7 @@ const ModInfo = struct { dirs: std.AutoArrayHashMapUnmanaged(Unit.Index, void), files: std.AutoArrayHashMapUnmanaged(Zcu.File.Index, void), - fn deinit(mod_info: *ModInfo, gpa: Allocator) void { + fn deinit(mod_info: *ModInfo, gpa: std.mem.Allocator) void { mod_info.dirs.deinit(gpa); mod_info.files.deinit(gpa); mod_info.* = undefined; @@ -220,13 +220,13 @@ const StringSection = struct { .section = Section.init, }; - fn deinit(str_sec: *StringSection, gpa: Allocator) void { + fn deinit(str_sec: *StringSection, gpa: std.mem.Allocator) void { str_sec.contents.deinit(gpa); str_sec.map.deinit(gpa); str_sec.section.deinit(gpa); } - fn addString(str_sec: *StringSection, dwarf: *Dwarf, str: []const u8) !Entry.Index { + fn addString(str_sec: *StringSection, dwarf: *Dwarf, str: []const u8) UpdateError!Entry.Index { const gop = try str_sec.map.getOrPutAdapted(dwarf.gpa, str, Adapter{ .str_sec = str_sec }); const entry: Entry.Index = @enumFromInt(gop.index); if (!gop.found_existing) { @@ -297,7 +297,7 @@ pub const Section = struct { .len = 0, }; - fn deinit(sec: *Section, gpa: Allocator) void { + fn deinit(sec: *Section, gpa: std.mem.Allocator) void { for (sec.units.items) |*unit| unit.deinit(gpa); sec.units.deinit(gpa); sec.* = undefined; @@ -357,7 +357,7 @@ pub const Section = struct { if (sec.last == unit.toOptional()) sec.last = unit_ptr.prev; } - fn popUnit(sec: *Section, gpa: Allocator) void { + 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().?; @@ -518,7 +518,7 @@ const Unit = struct { unit.cross_section_relocs.clearRetainingCapacity(); } - fn deinit(unit: *Unit, gpa: Allocator) void { + fn deinit(unit: *Unit, gpa: std.mem.Allocator) void { for (unit.entries.items) |*entry| entry.deinit(gpa); unit.entries.deinit(gpa); unit.cross_unit_relocs.deinit(gpa); @@ -526,7 +526,7 @@ const Unit = struct { unit.* = undefined; } - fn addEntry(unit: *Unit, gpa: Allocator) Allocator.Error!Entry.Index { + fn addEntry(unit: *Unit, gpa: std.mem.Allocator) std.mem.Allocator.Error!Entry.Index { if (unit.free.unwrap()) |entry| { const entry_ptr = unit.getEntry(entry); unit.free = entry_ptr.next; @@ -648,33 +648,35 @@ const Unit = struct { assert(len >= unit.trailer_len); if (sec == &dwarf.debug_line.section) { var buf: [1 + uleb128Bytes(std.math.maxInt(u32)) + 1]u8 = undefined; - var bw: Writer = .fixed(&buf); - bw.writeByte(DW.LNS.extended_op) catch unreachable; - const extended_op_bytes = bw.end; + 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 bw.writeLeb128(len - extended_op_bytes - op_len_bytes) catch unreachable, + .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((bw.writableSlice(op_len_bytes) catch unreachable), len - extended_op_bytes - op_len_bytes); + 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(bw.end == extended_op_bytes + op_len_bytes); - bw.writeByte(DW.LNE.padding) catch unreachable; - assert(bw.end >= unit.trailer_len and bw.end <= len); - return dwarf.getFile().?.pwriteAll(bw.getWritten(), sec.off(dwarf) + start); + 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(dwarf) + start); } - var trailer_bw: Writer = .fixed(try dwarf.gpa.alloc(u8, len)); - defer dwarf.gpa.free(trailer_bw.buffer); + var trailer = try std.ArrayList(u8).initCapacity(dwarf.gpa, len); + defer trailer.deinit(); const fill_byte: u8 = if (sec == &dwarf.debug_abbrev.section) fill: { assert(uleb128Bytes(@intFromEnum(AbbrevCode.null)) == 1); - trailer_bw.writeByte(@intFromEnum(AbbrevCode.null)) catch unreachable; + trailer.appendAssumeCapacity(@intFromEnum(AbbrevCode.null)); break :fill @intFromEnum(AbbrevCode.null); } else if (sec == &dwarf.debug_aranges.section) fill: { - trailer_bw.splatByteAll(0, @intFromEnum(dwarf.address_size) * 2) catch unreachable; + trailer.appendNTimesAssumeCapacity(0, @intFromEnum(dwarf.address_size) * 2); break :fill 0; } else if (sec == &dwarf.debug_frame.section) fill: { switch (dwarf.debug_frame.header.format) { @@ -682,49 +684,49 @@ const Unit = struct { .debug_frame, .eh_frame => |format| { const unit_len = len - dwarf.unitLengthBytes(); switch (dwarf.format) { - .@"32" => trailer_bw.writeInt(u32, @intCast(unit_len), dwarf.endian) catch unreachable, + .@"32" => std.mem.writeInt(u32, trailer.addManyAsArrayAssumeCapacity(4), @intCast(unit_len), dwarf.endian), .@"64" => { - trailer_bw.writeInt(u32, std.math.maxInt(u32), dwarf.endian) catch unreachable; - trailer_bw.writeInt(u64, unit_len, dwarf.endian) catch unreachable; + std.mem.writeInt(u32, trailer.addManyAsArrayAssumeCapacity(4), std.math.maxInt(u32), dwarf.endian); + std.mem.writeInt(u64, trailer.addManyAsArrayAssumeCapacity(8), unit_len, dwarf.endian); }, } switch (format) { .none => unreachable, .debug_frame => { switch (dwarf.format) { - .@"32" => trailer_bw.writeInt(u32, std.math.maxInt(u32), dwarf.endian) catch unreachable, - .@"64" => trailer_bw.writeInt(u64, std.math.maxInt(u64), dwarf.endian) catch unreachable, + .@"32" => std.mem.writeInt(u32, trailer.addManyAsArrayAssumeCapacity(4), std.math.maxInt(u32), dwarf.endian), + .@"64" => std.mem.writeInt(u64, trailer.addManyAsArrayAssumeCapacity(8), std.math.maxInt(u64), dwarf.endian), } - trailer_bw.writeByte(4) catch unreachable; - trailer_bw.writeAll("\x00") catch unreachable; - trailer_bw.writeByte(@intFromEnum(dwarf.address_size)) catch unreachable; - trailer_bw.writeByte(0) catch unreachable; + trailer.appendAssumeCapacity(4); + trailer.appendSliceAssumeCapacity("\x00"); + trailer.appendAssumeCapacity(@intFromEnum(dwarf.address_size)); + trailer.appendAssumeCapacity(0); }, .eh_frame => { - trailer_bw.writeInt(u32, 0, dwarf.endian) catch unreachable; - trailer_bw.writeByte(1) catch unreachable; - trailer_bw.writeAll("\x00") catch unreachable; + std.mem.writeInt(u32, trailer.addManyAsArrayAssumeCapacity(4), 0, dwarf.endian); + trailer.appendAssumeCapacity(1); + trailer.appendSliceAssumeCapacity("\x00"); }, } - trailer_bw.writeUleb128(1) catch unreachable; - trailer_bw.writeSleb128(1) catch unreachable; - trailer_bw.writeUleb128(0) catch unreachable; + uleb128(trailer.fixedWriter(), 1) catch unreachable; + sleb128(trailer.fixedWriter(), 1) catch unreachable; + uleb128(trailer.fixedWriter(), 0) catch unreachable; }, } - trailer_bw.splatByteAll(DW.CFA.nop, unit.trailer_len - trailer_bw.end) catch unreachable; + trailer.appendNTimesAssumeCapacity(DW.CFA.nop, unit.trailer_len - trailer.items.len); break :fill DW.CFA.nop; } else if (sec == &dwarf.debug_info.section) fill: { assert(uleb128Bytes(@intFromEnum(AbbrevCode.null)) == 1); - trailer_bw.splatByteAll(@intFromEnum(AbbrevCode.null), 2) catch unreachable; + trailer.appendNTimesAssumeCapacity(@intFromEnum(AbbrevCode.null), 2); break :fill @intFromEnum(AbbrevCode.null); } else if (sec == &dwarf.debug_rnglists.section) fill: { - trailer_bw.writeByte(DW.RLE.end_of_list) catch unreachable; + trailer.appendAssumeCapacity(DW.RLE.end_of_list); break :fill DW.RLE.end_of_list; } else unreachable; - assert(trailer_bw.end == unit.trailer_len); - trailer_bw.splatByteAll(fill_byte, len - unit.trailer_len) catch unreachable; - assert(trailer_bw.end == len); - try dwarf.getFile().?.pwriteAll(trailer_bw.buffer, sec.off(dwarf) + start); + assert(trailer.items.len == unit.trailer_len); + trailer.appendNTimesAssumeCapacity(fill_byte, len - unit.trailer_len); + assert(trailer.items.len == len); + try dwarf.getFile().?.pwriteAll(trailer.items, sec.off(dwarf) + start); } fn resolveRelocs(unit: *Unit, sec: *Section, dwarf: *Dwarf) RelocError!void { @@ -778,7 +780,7 @@ const Entry = struct { entry.external_relocs.clearRetainingCapacity(); } - fn deinit(entry: *Entry, gpa: Allocator) void { + fn deinit(entry: *Entry, gpa: std.mem.Allocator) void { entry.cross_entry_relocs.deinit(gpa); entry.cross_unit_relocs.deinit(gpa); entry.cross_section_relocs.deinit(gpa); @@ -831,52 +833,52 @@ const Entry = struct { 1 + uleb128Bytes(std.math.maxInt(u32)) + 1, ) ]u8 = undefined; - var bw: Writer = .fixed(&buf); + var fbs = std.io.fixedBufferStream(&buf); + const writer = fbs.writer(); if (sec == &dwarf.debug_info.section) switch (len) { 0 => {}, - 1 => bw.writeLeb128(try dwarf.refAbbrevCode(.pad_1)) catch unreachable, + 1 => uleb128(writer, try dwarf.refAbbrevCode(.pad_1)) catch unreachable, else => { - bw.writeLeb128(try dwarf.refAbbrevCode(.pad_n)) catch unreachable; - const abbrev_code_bytes = bw.end; + 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 bw.writeLeb128(len - abbrev_code_bytes - block_len_bytes) catch unreachable, + .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((try bw.writableSlice(block_len_bytes)), len - abbrev_code_bytes - block_len_bytes); + 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(bw.end == abbrev_code_bytes + block_len_bytes); + assert(fbs.pos == abbrev_code_bytes + block_len_bytes); }, } else if (sec == &dwarf.debug_line.section) switch (len) { 0 => {}, - 1 => bw.writeByte(DW.LNS.const_add_pc) catch unreachable, + 1 => writer.writeByte(DW.LNS.const_add_pc) catch unreachable, else => { - bw.writeByte(DW.LNS.extended_op) catch unreachable; - const extended_op_bytes = bw.end; + 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 bw.writeLeb128(len - extended_op_bytes - op_len_bytes) catch unreachable, + .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( - (bw.writableSlice(op_len_bytes) catch unreachable), - len - extended_op_bytes - op_len_bytes, - ); + 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(bw.end == extended_op_bytes + op_len_bytes); - if (len > 2) bw.writeByte(DW.LNE.padding) catch unreachable; + assert(fbs.pos == extended_op_bytes + op_len_bytes); + if (len > 2) writer.writeByte(DW.LNE.padding) catch unreachable; }, } else assert(!sec.pad_entries_to_ideal and len == 0); - assert(bw.end <= len); - try dwarf.getFile().?.pwriteAll(bw.getWritten(), sec.off(dwarf) + unit.off + unit.header_len + start); + assert(fbs.pos <= len); + try dwarf.getFile().?.pwriteAll(fbs.getWritten(), sec.off(dwarf) + unit.off + unit.header_len + start); } fn resize(entry_ptr: *Entry, unit: *Unit, sec: *Section, dwarf: *Dwarf, len: u32) UpdateError!void { @@ -1131,149 +1133,150 @@ pub const Loc = union(enum) { }; } - fn writeReg(bw: *Writer, reg: u32, op0: u8, opx: u8) Writer.Error!void { + fn writeReg(reg: u32, op0: u8, opx: u8, writer: anytype) @TypeOf(writer).Error!void { if (std.math.cast(u5, reg)) |small_reg| { - try bw.writeByte(op0 + small_reg); + try writer.writeByte(op0 + small_reg); } else { - try bw.writeByte(opx); - try bw.writeLeb128(reg); + try writer.writeByte(opx); + try uleb128(writer, reg); } } - fn write(loc: Loc, bw: *Writer, adapter: anytype) UpdateError!void { + fn write(loc: Loc, adapter: anytype) UpdateError!void { + const writer = adapter.writer(); switch (loc) { .empty => {}, .addr_reloc => |sym_index| { - try bw.writeByte(DW.OP.addr); + try writer.writeByte(DW.OP.addr); try adapter.addrSym(sym_index); }, .deref => |addr| { try addr.write(adapter); - try bw.writeByte(DW.OP.deref); + try writer.writeByte(DW.OP.deref); }, .constu => |constu| if (std.math.cast(u5, constu)) |lit| { - try bw.writeByte(@as(u8, DW.OP.lit0) + lit); + try writer.writeByte(@as(u8, DW.OP.lit0) + lit); } else if (std.math.cast(u8, constu)) |const1u| { - try bw.writeAll(&.{ DW.OP.const1u, const1u }); + try writer.writeAll(&.{ DW.OP.const1u, const1u }); } else if (std.math.cast(u16, constu)) |const2u| { - try bw.writeByte(DW.OP.const2u); - try bw.writeInt(u16, const2u, adapter.endian()); + try writer.writeByte(DW.OP.const2u); + try writer.writeInt(u16, const2u, adapter.endian()); } else if (std.math.cast(u21, constu)) |const3u| { - try bw.writeByte(DW.OP.constu); - try bw.writeLeb128(const3u); + try writer.writeByte(DW.OP.constu); + try uleb128(writer, const3u); } else if (std.math.cast(u32, constu)) |const4u| { - try bw.writeByte(DW.OP.const4u); - try bw.writeInt(u32, const4u, adapter.endian()); + try writer.writeByte(DW.OP.const4u); + try writer.writeInt(u32, const4u, adapter.endian()); } else if (std.math.cast(u49, constu)) |const7u| { - try bw.writeByte(DW.OP.constu); - try bw.writeLeb128(const7u); + try writer.writeByte(DW.OP.constu); + try uleb128(writer, const7u); } else { - try bw.writeByte(DW.OP.const8u); - try bw.writeInt(u64, constu, adapter.endian()); + try writer.writeByte(DW.OP.const8u); + try writer.writeInt(u64, constu, adapter.endian()); }, .consts => |consts| if (std.math.cast(i8, consts)) |const1s| { - try bw.writeAll(&.{ DW.OP.const1s, @bitCast(const1s) }); + try writer.writeAll(&.{ DW.OP.const1s, @bitCast(const1s) }); } else if (std.math.cast(i16, consts)) |const2s| { - try bw.writeByte(DW.OP.const2s); - try bw.writeInt(i16, const2s, adapter.endian()); + try writer.writeByte(DW.OP.const2s); + try writer.writeInt(i16, const2s, adapter.endian()); } else if (std.math.cast(i21, consts)) |const3s| { - try bw.writeByte(DW.OP.consts); - try bw.writeLeb128(const3s); + try writer.writeByte(DW.OP.consts); + try sleb128(writer, const3s); } else if (std.math.cast(i32, consts)) |const4s| { - try bw.writeByte(DW.OP.const4s); - try bw.writeInt(i32, const4s, adapter.endian()); + try writer.writeByte(DW.OP.const4s); + try writer.writeInt(i32, const4s, adapter.endian()); } else if (std.math.cast(i49, consts)) |const7s| { - try bw.writeByte(DW.OP.consts); - try bw.writeLeb128(const7s); + try writer.writeByte(DW.OP.consts); + try sleb128(writer, const7s); } else { - try bw.writeByte(DW.OP.const8s); - try bw.writeInt(i64, consts, adapter.endian()); + try writer.writeByte(DW.OP.const8s); + try writer.writeInt(i64, consts, adapter.endian()); }, .plus => |plus| done: { if (plus[0].getConst(u0)) |_| { - try plus[1].write(bw, adapter); + try plus[1].write(adapter); break :done; } if (plus[1].getConst(u0)) |_| { - try plus[0].write(bw, adapter); + try plus[0].write(adapter); break :done; } if (plus[0].getBaseReg()) |breg| { if (plus[1].getConst(i65)) |offset| { - try writeReg(bw, breg, DW.OP.breg0, DW.OP.bregx); - try bw.writeLeb128(offset); + try writeReg(breg, DW.OP.breg0, DW.OP.bregx, writer); + try sleb128(writer, offset); break :done; } } if (plus[1].getBaseReg()) |breg| { if (plus[0].getConst(i65)) |offset| { - try writeReg(bw, breg, DW.OP.breg0, DW.OP.bregx); - try bw.writeLeb128(offset); + try writeReg(breg, DW.OP.breg0, DW.OP.bregx, writer); + try sleb128(writer, offset); break :done; } } if (plus[0].getConst(u64)) |uconst| { - try plus[1].write(bw, adapter); - try bw.writeByte(DW.OP.plus_uconst); - try bw.writeLeb128(uconst); + try plus[1].write(adapter); + try writer.writeByte(DW.OP.plus_uconst); + try uleb128(writer, uconst); break :done; } if (plus[1].getConst(u64)) |uconst| { - try plus[0].write(bw, adapter); - try bw.writeByte(DW.OP.plus_uconst); - try bw.writeLeb128(uconst); + try plus[0].write(adapter); + try writer.writeByte(DW.OP.plus_uconst); + try uleb128(writer, uconst); break :done; } - try plus[0].write(bw, adapter); - try plus[1].write(bw, adapter); - try bw.writeByte(DW.OP.plus); + try plus[0].write(adapter); + try plus[1].write(adapter); + try writer.writeByte(DW.OP.plus); }, - .reg => |reg| try writeReg(bw, reg, DW.OP.reg0, DW.OP.regx), + .reg => |reg| try writeReg(reg, DW.OP.reg0, DW.OP.regx, writer), .breg => |breg| { - try writeReg(bw, breg, DW.OP.breg0, DW.OP.bregx); - try bw.writeSleb128(0); + try writeReg(breg, DW.OP.breg0, DW.OP.bregx, writer); + try sleb128(writer, 0); }, - .push_object_address => try bw.writeByte(DW.OP.push_object_address), + .push_object_address => try writer.writeByte(DW.OP.push_object_address), .call => |call| { for (call.args) |arg| try arg.write(adapter); - try bw.writeByte(DW.OP.call_ref); + try writer.writeByte(DW.OP.call_ref); try adapter.infoEntry(call.unit, call.entry); }, .form_tls_address => |addr| { - try addr.write(bw, adapter); - try bw.writeByte(DW.OP.form_tls_address); + try addr.write(adapter); + try writer.writeByte(DW.OP.form_tls_address); }, .implicit_value => |value| { - try bw.writeByte(DW.OP.implicit_value); - try bw.writeLeb128(value.len); - try bw.writeAll(value); + try writer.writeByte(DW.OP.implicit_value); + try uleb128(writer, value.len); + try writer.writeAll(value); }, .stack_value => |value| { - try value.write(bw, adapter); - try bw.writeByte(DW.OP.stack_value); + try value.write(adapter); + try writer.writeByte(DW.OP.stack_value); }, .implicit_pointer => |implicit_pointer| { - try bw.writeByte(DW.OP.implicit_pointer); - try adapter.infoEntry(bw, implicit_pointer.unit, implicit_pointer.entry); - try bw.writeLeb128(implicit_pointer.offset); + try writer.writeByte(DW.OP.implicit_pointer); + try adapter.infoEntry(implicit_pointer.unit, implicit_pointer.entry); + try sleb128(writer, implicit_pointer.offset); }, .wasm_ext => |wasm_ext| { - try bw.writeByte(DW.OP.WASM_location); + try writer.writeByte(DW.OP.WASM_location); switch (wasm_ext) { .local => |local| { - try bw.writeByte(DW.OP.WASM_local); - try bw.writeLeb128(local); + try writer.writeByte(DW.OP.WASM_local); + try uleb128(writer, local); }, .global => |global| if (std.math.cast(u21, global)) |global_u21| { - try bw.writeByte(DW.OP.WASM_global); - try bw.writeLeb128(global_u21); + try writer.writeByte(DW.OP.WASM_global); + try uleb128(writer, global_u21); } else { - try bw.writeByte(DW.OP.WASM_global_u32); - try bw.writeInt(u32, global, adapter.endian()); + try writer.writeByte(DW.OP.WASM_global_u32); + try writer.writeInt(u32, global, adapter.endian()); }, .operand_stack => |operand_stack| { - try bw.writeByte(DW.OP.WASM_operand_stack); - try bw.writeLeb128(operand_stack); + try writer.writeByte(DW.OP.WASM_operand_stack); + try uleb128(writer, operand_stack); }, } }, @@ -1306,21 +1309,21 @@ pub const Cfa = union(enum) { const RegExpr = struct { reg: u32, expr: Loc }; fn write(cfa: Cfa, wip_nav: *WipNav) UpdateError!void { - const bw = &wip_nav.debug_frame.buffered_writer; + const writer = wip_nav.debug_frame.writer(wip_nav.dwarf.gpa); switch (cfa) { - .nop => try bw.writeByte(DW.CFA.nop), + .nop => try writer.writeByte(DW.CFA.nop), .advance_loc => |loc| { const delta = @divExact(loc - wip_nav.cfi.loc, wip_nav.dwarf.debug_frame.header.code_alignment_factor); if (delta == 0) {} else if (std.math.cast(u6, delta)) |small_delta| - try bw.writeByte(@as(u8, DW.CFA.advance_loc) + small_delta) + try writer.writeByte(@as(u8, DW.CFA.advance_loc) + small_delta) else if (std.math.cast(u8, delta)) |ubyte_delta| - try bw.writeAll(&.{ DW.CFA.advance_loc1, ubyte_delta }) + try writer.writeAll(&.{ DW.CFA.advance_loc1, ubyte_delta }) else if (std.math.cast(u16, delta)) |uhalf_delta| { - try bw.writeByte(DW.CFA.advance_loc2); - try bw.writeInt(u16, uhalf_delta, wip_nav.dwarf.endian); + try writer.writeByte(DW.CFA.advance_loc2); + try writer.writeInt(u16, uhalf_delta, wip_nav.dwarf.endian); } else if (std.math.cast(u32, delta)) |uword_delta| { - try bw.writeByte(DW.CFA.advance_loc4); - try bw.writeInt(u32, uword_delta, wip_nav.dwarf.endian); + try writer.writeByte(DW.CFA.advance_loc4); + try writer.writeInt(u32, uword_delta, wip_nav.dwarf.endian); } wip_nav.cfi.loc = loc; }, @@ -1332,41 +1335,41 @@ pub const Cfa = union(enum) { }, wip_nav.dwarf.debug_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 bw.writeByte(@as(u8, DW.CFA.offset) + small_reg); + try writer.writeByte(@as(u8, DW.CFA.offset) + small_reg); } else { - try bw.writeByte(DW.CFA.offset_extended); - try bw.writeLeb128(reg_off.reg); + try writer.writeByte(DW.CFA.offset_extended); + try uleb128(writer, reg_off.reg); } - try bw.writeLeb128(unsigned_off); + try uleb128(writer, unsigned_off); } else { - try bw.writeByte(DW.CFA.offset_extended_sf); - try bw.writeLeb128(reg_off.reg); - try bw.writeLeb128(factored_off); + try writer.writeByte(DW.CFA.offset_extended_sf); + try uleb128(writer, reg_off.reg); + try sleb128(writer, factored_off); } }, .restore => |reg| if (std.math.cast(u6, reg)) |small_reg| - try bw.writeByte(@as(u8, DW.CFA.restore) + small_reg) + try writer.writeByte(@as(u8, DW.CFA.restore) + small_reg) else { - try bw.writeByte(DW.CFA.restore_extended); - try bw.writeLeb128(reg); + try writer.writeByte(DW.CFA.restore_extended); + try uleb128(writer, reg); }, .undefined => |reg| { - try bw.writeByte(DW.CFA.undefined); - try bw.writeLeb128(reg); + try writer.writeByte(DW.CFA.undefined); + try uleb128(writer, reg); }, .same_value => |reg| { - try bw.writeByte(DW.CFA.same_value); - try bw.writeLeb128(reg); + try writer.writeByte(DW.CFA.same_value); + try uleb128(writer, reg); }, .register => |regs| if (regs[0] != regs[1]) { - try bw.writeByte(DW.CFA.register); - for (regs) |reg| try bw.writeLeb128(reg); + try writer.writeByte(DW.CFA.register); + for (regs) |reg| try uleb128(writer, reg); } else { - try bw.writeByte(DW.CFA.same_value); - try bw.writeLeb128(regs[0]); + try writer.writeByte(DW.CFA.same_value); + try uleb128(writer, regs[0]); }, - .remember_state => try bw.writeByte(DW.CFA.remember_state), - .restore_state => try bw.writeByte(DW.CFA.restore_state), + .remember_state => try writer.writeByte(DW.CFA.remember_state), + .restore_state => try writer.writeByte(DW.CFA.restore_state), .def_cfa, .def_cfa_register, .def_cfa_offset, .adjust_cfa_offset => { const reg_off: RegOff = switch (cfa) { else => unreachable, @@ -1379,51 +1382,51 @@ pub const Cfa = union(enum) { const unsigned_off = std.math.cast(u63, reg_off.off); if (reg_off.off == wip_nav.cfi.cfa.off) { if (changed_reg) { - try bw.writeByte(DW.CFA.def_cfa_register); - try bw.writeLeb128(reg_off.reg); + try writer.writeByte(DW.CFA.def_cfa_register); + try uleb128(writer, reg_off.reg); } } else if (switch (wip_nav.dwarf.debug_frame.header.data_alignment_factor) { 0 => unreachable, 1 => unsigned_off != null, else => |data_alignment_factor| @rem(reg_off.off, data_alignment_factor) != 0, }) { - try bw.writeByte(if (changed_reg) DW.CFA.def_cfa else DW.CFA.def_cfa_offset); - if (changed_reg) try bw.writeLeb128(reg_off.reg); - try bw.writeLeb128(unsigned_off.?); + try writer.writeByte(if (changed_reg) DW.CFA.def_cfa else DW.CFA.def_cfa_offset); + if (changed_reg) try uleb128(writer, reg_off.reg); + try uleb128(writer, unsigned_off.?); } else { - try bw.writeByte(if (changed_reg) DW.CFA.def_cfa_sf else DW.CFA.def_cfa_offset_sf); - if (changed_reg) try bw.writeLeb128(reg_off.reg); - try bw.writeLeb128(@divExact(reg_off.off, wip_nav.dwarf.debug_frame.header.data_alignment_factor)); + try writer.writeByte(if (changed_reg) DW.CFA.def_cfa_sf else DW.CFA.def_cfa_offset_sf); + if (changed_reg) try uleb128(writer, reg_off.reg); + try sleb128(writer, @divExact(reg_off.off, wip_nav.dwarf.debug_frame.header.data_alignment_factor)); } wip_nav.cfi.cfa = reg_off; }, .def_cfa_expression => |expr| { - try bw.writeByte(DW.CFA.def_cfa_expression); + try writer.writeByte(DW.CFA.def_cfa_expression); try wip_nav.frameExprLoc(expr); }, .expression => |reg_expr| { - try bw.writeByte(DW.CFA.expression); - try bw.writeLeb128(reg_expr.reg); + try writer.writeByte(DW.CFA.expression); + try uleb128(writer, reg_expr.reg); try wip_nav.frameExprLoc(reg_expr.expr); }, .val_offset => |reg_off| { const factored_off = @divExact(reg_off.off, wip_nav.dwarf.debug_frame.header.data_alignment_factor); if (std.math.cast(u63, factored_off)) |unsigned_off| { - try bw.writeByte(DW.CFA.val_offset); - try bw.writeLeb128(reg_off.reg); - try bw.writeLeb128(unsigned_off); + try writer.writeByte(DW.CFA.val_offset); + try uleb128(writer, reg_off.reg); + try uleb128(writer, unsigned_off); } else { - try bw.writeByte(DW.CFA.val_offset_sf); - try bw.writeLeb128(reg_off.reg); - try bw.writeLeb128(factored_off); + try writer.writeByte(DW.CFA.val_offset_sf); + try uleb128(writer, reg_off.reg); + try sleb128(writer, factored_off); } }, .val_expression => |reg_expr| { - try bw.writeByte(DW.CFA.val_expression); - try bw.writeLeb128(reg_expr.reg); + try writer.writeByte(DW.CFA.val_expression); + try uleb128(writer, reg_expr.reg); try wip_nav.frameExprLoc(reg_expr.expr); }, - .escape => |bytes| try bw.writeAll(bytes), + .escape => |bytes| try writer.writeAll(bytes), } } }; @@ -1446,27 +1449,19 @@ pub const WipNav = struct { loc: u32, cfa: Cfa.RegOff, }, - debug_frame: std.io.Writer.Allocating, - debug_info: std.io.Writer.Allocating, - debug_line: std.io.Writer.Allocating, - debug_loclists: std.io.Writer.Allocating, + debug_frame: std.ArrayListUnmanaged(u8), + debug_info: std.ArrayListUnmanaged(u8), + debug_line: std.ArrayListUnmanaged(u8), + debug_loclists: std.ArrayListUnmanaged(u8), pending_lazy: PendingLazy, - pub fn init(wip_nav: *WipNav) void { - const gpa = wip_nav.dwarf.gpa; - wip_nav.debug_frame.init(gpa); - wip_nav.debug_info.init(gpa); - wip_nav.debug_line.init(gpa); - wip_nav.debug_loclists.init(gpa); - } - pub fn deinit(wip_nav: *WipNav) void { const gpa = wip_nav.dwarf.gpa; if (wip_nav.func != .none) wip_nav.blocks.deinit(gpa); - wip_nav.debug_frame.deinit(); - wip_nav.debug_info.deinit(); - wip_nav.debug_line.deinit(); - wip_nav.debug_loclists.deinit(); + wip_nav.debug_frame.deinit(gpa); + wip_nav.debug_info.deinit(gpa); + wip_nav.debug_line.deinit(gpa); + wip_nav.debug_loclists.deinit(gpa); wip_nav.pending_lazy.types.deinit(gpa); wip_nav.pending_lazy.values.deinit(gpa); } @@ -1543,7 +1538,7 @@ pub const WipNav = struct { delta_line: i33, delta_pc: u64, ) error{OutOfMemory}!void { - const dlbw = &wip_nav.debug_line.buffered_writer; + const dlw = wip_nav.debug_line.writer(wip_nav.dwarf.gpa); const header = wip_nav.dwarf.debug_line.header; assert(header.maximum_operations_per_instruction == 1); @@ -1553,8 +1548,8 @@ pub const WipNav = struct { delta_line - header.line_base >= header.line_range) remaining: { assert(delta_line != 0); - try dlbw.writeByte(DW.LNS.advance_line); - try dlbw.writeLeb128(delta_line); + try dlw.writeByte(DW.LNS.advance_line); + try sleb128(dlw, delta_line); break :remaining 0; } else delta_line); @@ -1562,68 +1557,68 @@ pub const WipNav = struct { header.maximum_operations_per_instruction + delta_op; const max_op_advance: u9 = (std.math.maxInt(u8) - header.opcode_base) / header.line_range; const remaining_op_advance: u8 = @intCast(if (op_advance >= 2 * max_op_advance) remaining: { - try dlbw.writeByte(DW.LNS.advance_pc); - try dlbw.writeLeb128(op_advance); + try dlw.writeByte(DW.LNS.advance_pc); + try uleb128(dlw, op_advance); break :remaining 0; } else if (op_advance >= max_op_advance) remaining: { - try dlbw.writeByte(DW.LNS.const_add_pc); + try dlw.writeByte(DW.LNS.const_add_pc); break :remaining op_advance - max_op_advance; } else op_advance); - try dlbw.writeByte( - if (remaining_delta_line == 0 and remaining_op_advance == 0) - DW.LNS.copy - else - @intCast((remaining_delta_line - header.line_base) + - (header.line_range * remaining_op_advance) + header.opcode_base), - ); + if (remaining_delta_line == 0 and remaining_op_advance == 0) + try dlw.writeByte(DW.LNS.copy) + else + try dlw.writeByte(@intCast((remaining_delta_line - header.line_base) + + (header.line_range * remaining_op_advance) + header.opcode_base)); } - pub fn setColumn(wip_nav: *WipNav, column: u32) Allocator.Error!void { - const dlbw = &wip_nav.debug_line.buffered_writer; - try dlbw.writeByte(DW.LNS.set_column); - try dlbw.writeLeb128(column + 1); + pub fn setColumn(wip_nav: *WipNav, column: u32) error{OutOfMemory}!void { + const dlw = wip_nav.debug_line.writer(wip_nav.dwarf.gpa); + try dlw.writeByte(DW.LNS.set_column); + try uleb128(dlw, column + 1); } - pub fn negateStmt(wip_nav: *WipNav) Allocator.Error!void { - return wip_nav.debug_line.buffered_writer.writeByte(DW.LNS.negate_stmt); + pub fn negateStmt(wip_nav: *WipNav) error{OutOfMemory}!void { + const dlw = wip_nav.debug_line.writer(wip_nav.dwarf.gpa); + try dlw.writeByte(DW.LNS.negate_stmt); } - pub fn setPrologueEnd(wip_nav: *WipNav) Allocator.Error!void { - return wip_nav.debug_line.buffered_writer.writeByte(DW.LNS.set_prologue_end); + pub fn setPrologueEnd(wip_nav: *WipNav) error{OutOfMemory}!void { + const dlw = wip_nav.debug_line.writer(wip_nav.dwarf.gpa); + try dlw.writeByte(DW.LNS.set_prologue_end); } - pub fn setEpilogueBegin(wip_nav: *WipNav) Allocator.Error!void { - return wip_nav.debug_line.buffered_writer.writeByte(DW.LNS.set_epilogue_begin); + pub fn setEpilogueBegin(wip_nav: *WipNav) error{OutOfMemory}!void { + const dlw = wip_nav.debug_line.writer(wip_nav.dwarf.gpa); + try dlw.writeByte(DW.LNS.set_epilogue_begin); } pub fn enterBlock(wip_nav: *WipNav, code_off: u64) UpdateError!void { const dwarf = wip_nav.dwarf; - const dibw = &wip_nav.debug_info.buffered_writer; + const diw = wip_nav.debug_info.writer(dwarf.gpa); const block = try wip_nav.blocks.addOne(dwarf.gpa); - block.abbrev_code = @intCast(dibw.count); + block.abbrev_code = @intCast(wip_nav.debug_info.items.len); try wip_nav.abbrevCode(.block); block.low_pc_off = code_off; try wip_nav.infoAddrSym(wip_nav.func_sym_index, code_off); - block.high_pc = @intCast(dibw.count); - try dibw.writeInt(u32, 0, dwarf.endian); + block.high_pc = @intCast(wip_nav.debug_info.items.len); + try diw.writeInt(u32, 0, dwarf.endian); wip_nav.any_children = false; } pub fn leaveBlock(wip_nav: *WipNav, code_off: u64) UpdateError!void { const block_bytes = comptime uleb128Bytes(@intFromEnum(AbbrevCode.block)); const block = wip_nav.blocks.pop().?; - const dib = wip_nav.debug_info.getWritten(); if (wip_nav.any_children) - try wip_nav.debug_info.buffered_writer.writeLeb128(@intFromEnum(AbbrevCode.null)) + try uleb128(wip_nav.debug_info.writer(wip_nav.dwarf.gpa), @intFromEnum(AbbrevCode.null)) else std.leb.writeUnsignedFixed( block_bytes, - dib[block.abbrev_code..][0..block_bytes], + wip_nav.debug_info.items[block.abbrev_code..][0..block_bytes], try wip_nav.dwarf.refAbbrevCode(.empty_block), ); - std.mem.writeInt(u32, dib[block.high_pc..][0..4], @intCast(code_off - block.low_pc_off), wip_nav.dwarf.endian); + std.mem.writeInt(u32, wip_nav.debug_info.items[block.high_pc..][0..4], @intCast(code_off - block.low_pc_off), wip_nav.dwarf.endian); wip_nav.any_children = true; } @@ -1636,18 +1631,18 @@ pub const WipNav = struct { ) UpdateError!void { const dwarf = wip_nav.dwarf; const zcu = wip_nav.pt.zcu; - const dibw = &wip_nav.debug_info.buffered_writer; + const diw = wip_nav.debug_info.writer(dwarf.gpa); const block = try wip_nav.blocks.addOne(dwarf.gpa); - block.abbrev_code = @intCast(dibw.count); + block.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 dibw.writeLeb128(zcu.navSrcLine(zcu.funcInfo(wip_nav.func).owner_nav) + line + 1); - try dibw.writeLeb128(column + 1); + try uleb128(diw, zcu.navSrcLine(zcu.funcInfo(wip_nav.func).owner_nav) + line + 1); + try uleb128(diw, column + 1); block.low_pc_off = code_off; try wip_nav.infoAddrSym(wip_nav.func_sym_index, code_off); - block.high_pc = @intCast(dibw.count); - try dibw.writeInt(u32, 0, dwarf.endian); + block.high_pc = @intCast(wip_nav.debug_info.items.len); + try diw.writeInt(u32, 0, dwarf.endian); try wip_nav.setInlineFunc(func); wip_nav.any_children = false; } @@ -1655,16 +1650,15 @@ pub const WipNav = struct { 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 block = wip_nav.blocks.pop().?; - const dib = wip_nav.debug_info.getWritten(); if (wip_nav.any_children) - try wip_nav.debug_info.buffered_writer.writeLeb128(@intFromEnum(AbbrevCode.null)) + try uleb128(wip_nav.debug_info.writer(wip_nav.dwarf.gpa), @intFromEnum(AbbrevCode.null)) else std.leb.writeUnsignedFixed( inlined_func_bytes, - dib[block.abbrev_code..][0..inlined_func_bytes], + wip_nav.debug_info.items[block.abbrev_code..][0..inlined_func_bytes], try wip_nav.dwarf.refAbbrevCode(.empty_inlined_func), ); - std.mem.writeInt(u32, dib[block.high_pc..][0..4], @intCast(code_off - block.low_pc_off), wip_nav.dwarf.endian); + std.mem.writeInt(u32, wip_nav.debug_info.items[block.high_pc..][0..4], @intCast(code_off - block.low_pc_off), wip_nav.dwarf.endian); try wip_nav.setInlineFunc(func); wip_nav.any_children = true; } @@ -1678,22 +1672,22 @@ pub const WipNav = struct { const new_file = zcu.navFileScopeIndex(new_func_info.owner_nav); const new_unit = try dwarf.getUnit(zcu.fileByIndex(new_file).mod.?); - const dlbw = &wip_nav.debug_line.buffered_writer; + const dlw = wip_nav.debug_line.writer(dwarf.gpa); if (dwarf.incremental()) { const new_nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, new_func_info.owner_nav); errdefer _ = if (!new_nav_gop.found_existing) dwarf.navs.pop(); if (!new_nav_gop.found_existing) new_nav_gop.value_ptr.* = try dwarf.addCommonEntry(new_unit); - try dlbw.writeByte(DW.LNS.extended_op); - try dlbw.writeLeb128(1 + dwarf.sectionOffsetBytes()); - try dlbw.writeByte(DW.LNE.ZIG_set_decl); + try dlw.writeByte(DW.LNS.extended_op); + try uleb128(dlw, 1 + dwarf.sectionOffsetBytes()); + try dlw.writeByte(DW.LNE.ZIG_set_decl); try dwarf.debug_line.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_section_relocs.append(dwarf.gpa, .{ - .source_off = @intCast(dlbw.count), + .source_off = @intCast(wip_nav.debug_line.items.len), .target_sec = .debug_info, .target_unit = new_unit, .target_entry = new_nav_gop.value_ptr.toOptional(), }); - try dlbw.splatByteAll(0, dwarf.sectionOffsetBytes()); + try dlw.writeByteNTimes(0, dwarf.sectionOffsetBytes()); return; } @@ -1704,49 +1698,42 @@ pub const WipNav = struct { try mod_info.dirs.put(dwarf.gpa, new_unit, {}); const file_gop = try mod_info.files.getOrPut(dwarf.gpa, new_file); - try dlbw.writeByte(DW.LNS.set_file); - try dlbw.writeLeb128(file_gop.index); + try dlw.writeByte(DW.LNS.set_file); + try uleb128(dlw, file_gop.index); } const old_src_line: i33 = zcu.navSrcLine(old_func_info.owner_nav); const new_src_line: i33 = zcu.navSrcLine(new_func_info.owner_nav); if (new_src_line != old_src_line) { - try dlbw.writeByte(DW.LNS.advance_line); - try dlbw.writeLeb128(new_src_line - old_src_line); + try dlw.writeByte(DW.LNS.advance_line); + try sleb128(dlw, new_src_line - old_src_line); } wip_nav.func = func; } - fn externalReloc(wip_nav: *WipNav, sec: *Section, reloc: ExternalReloc) Allocator.Error!void { + fn externalReloc(wip_nav: *WipNav, sec: *Section, reloc: ExternalReloc) std.mem.Allocator.Error!void { try sec.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs.append(wip_nav.dwarf.gpa, reloc); } - pub fn infoExternalReloc(wip_nav: *WipNav, reloc: ExternalReloc) Allocator.Error!void { + pub fn infoExternalReloc(wip_nav: *WipNav, reloc: ExternalReloc) std.mem.Allocator.Error!void { try wip_nav.externalReloc(&wip_nav.dwarf.debug_info.section, reloc); } - fn frameExternalReloc(wip_nav: *WipNav, reloc: ExternalReloc) Allocator.Error!void { + fn frameExternalReloc(wip_nav: *WipNav, reloc: ExternalReloc) std.mem.Allocator.Error!void { try wip_nav.externalReloc(&wip_nav.dwarf.debug_frame.section, reloc); } fn abbrevCode(wip_nav: *WipNav, abbrev_code: AbbrevCode) UpdateError!void { - try wip_nav.debug_info.buffered_writer.writeLeb128(try wip_nav.dwarf.refAbbrevCode(abbrev_code)); + try uleb128(wip_nav.debug_info.writer(wip_nav.dwarf.gpa), try wip_nav.dwarf.refAbbrevCode(abbrev_code)); } - fn sectionOffset( - wip_nav: *WipNav, - comptime sec: Section.Index, - target_sec: Section.Index, - target_unit: Unit.Index, - target_entry: Entry.Index, - target_off: u32, - ) UpdateError!void { + fn sectionOffset(wip_nav: *WipNav, comptime sec: Section.Index, target_sec: Section.Index, target_unit: Unit.Index, target_entry: Entry.Index, target_off: u32) UpdateError!void { const dwarf = wip_nav.dwarf; const gpa = dwarf.gpa; const entry_ptr = @field(dwarf, @tagName(sec)).section.getUnit(wip_nav.unit).getEntry(wip_nav.entry); - const bw = &@field(wip_nav, @tagName(sec)).buffered_writer; - const source_off: u32 = @intCast(bw.count); + const bytes = &@field(wip_nav, @tagName(sec)); + const source_off: u32 = @intCast(bytes.items.len); if (target_sec != sec) { try entry_ptr.cross_section_relocs.append(gpa, .{ .source_off = source_off, @@ -1769,7 +1756,7 @@ pub const WipNav = struct { .target_off = target_off, }); } - try bw.splatByteAll(0, dwarf.sectionOffsetBytes()); + try bytes.appendNTimes(gpa, 0, dwarf.sectionOffsetBytes()); } fn infoSectionOffset(wip_nav: *WipNav, target_sec: Section.Index, target_unit: Unit.Index, target_entry: Entry.Index, target_off: u32) UpdateError!void { @@ -1781,93 +1768,93 @@ pub const WipNav = struct { } const ExprLocCounter = struct { + const Stream = std.io.CountingWriter(std.io.NullWriter); + stream: Stream, section_offset_bytes: u32, address_size: AddressSize, fn init(dwarf: *Dwarf) ExprLocCounter { return .{ + .stream = std.io.countingWriter(std.io.null_writer), .section_offset_bytes = dwarf.sectionOffsetBytes(), .address_size = dwarf.address_size, }; } + fn writer(counter: *ExprLocCounter) Stream.Writer { + return counter.stream.writer(); + } fn endian(_: ExprLocCounter) std.builtin.Endian { return @import("builtin").cpu.arch.endian(); } - fn addrSym(counter: ExprLocCounter, bw: *Writer, _: u32) error{}!void { - bw.count += @intFromEnum(counter.address_size); + fn addrSym(counter: *ExprLocCounter, _: u32) error{}!void { + counter.stream.bytes_written += @intFromEnum(counter.address_size); } - fn infoEntry(counter: ExprLocCounter, bw: *Writer, _: Unit.Index, _: Entry.Index) error{}!void { - bw.count += counter.section_offset_bytes; + fn infoEntry(counter: *ExprLocCounter, _: Unit.Index, _: Entry.Index) error{}!void { + counter.stream.bytes_written += counter.section_offset_bytes; } }; fn infoExprLoc(wip_nav: *WipNav, loc: Loc) UpdateError!void { - const bw = &wip_nav.debug_info.buffered_writer; - const counter: ExprLocCounter = .init(wip_nav.dwarf); - const start = bw.count; - try loc.write(bw, counter); - const len = bw.count - start; - bw.count = start; - wip_nav.debug_info.shrinkRetainingCapacity(start); + var counter: ExprLocCounter = .init(wip_nav.dwarf); + try loc.write(&counter); const adapter: struct { wip_nav: *WipNav, + fn writer(ctx: @This()) std.ArrayListUnmanaged(u8).Writer { + return ctx.wip_nav.debug_info.writer(ctx.wip_nav.dwarf.gpa); + } fn endian(ctx: @This()) std.builtin.Endian { return ctx.wip_nav.dwarf.endian; } - fn addrSym(ctx: @This(), _: *Writer, sym_index: u32) UpdateError!void { + fn addrSym(ctx: @This(), sym_index: u32) UpdateError!void { try ctx.wip_nav.infoAddrSym(sym_index, 0); } - fn infoEntry(ctx: @This(), _: *Writer, unit: Unit.Index, entry: Entry.Index) UpdateError!void { + fn infoEntry(ctx: @This(), unit: Unit.Index, entry: Entry.Index) UpdateError!void { try ctx.wip_nav.infoSectionOffset(.debug_info, unit, entry, 0); } } = .{ .wip_nav = wip_nav }; - try bw.writeLeb128(len); - try loc.write(bw, adapter); + try uleb128(adapter.writer(), counter.stream.bytes_written); + try loc.write(adapter); } fn infoAddrSym(wip_nav: *WipNav, sym_index: u32, sym_off: u64) UpdateError!void { - const dibw = &wip_nav.debug_info.buffered_writer; try wip_nav.infoExternalReloc(.{ - .source_off = @intCast(dibw.count), + .source_off = @intCast(wip_nav.debug_info.items.len), .target_sym = sym_index, .target_off = sym_off, }); - try dibw.splatByteAll(0, @intFromEnum(wip_nav.dwarf.address_size)); + try wip_nav.debug_info.appendNTimes(wip_nav.dwarf.gpa, 0, @intFromEnum(wip_nav.dwarf.address_size)); } fn frameExprLoc(wip_nav: *WipNav, loc: Loc) UpdateError!void { - const bw = &wip_nav.debug_frame.buffered_writer; - const counter: ExprLocCounter = .init(wip_nav.dwarf); - const start = bw.count; - try loc.write(bw, counter); - const len = bw.count - start; - bw.count = start; - wip_nav.debug_frame.shrinkRetainingCapacity(start); + var counter: ExprLocCounter = .init(wip_nav.dwarf); + try loc.write(&counter); const adapter: struct { wip_nav: *WipNav, + fn writer(ctx: @This()) std.ArrayListUnmanaged(u8).Writer { + return ctx.wip_nav.debug_frame.writer(ctx.wip_nav.dwarf.gpa); + } fn endian(ctx: @This()) std.builtin.Endian { return ctx.wip_nav.dwarf.endian; } - fn addrSym(ctx: @This(), _: *Writer, sym_index: u32) UpdateError!void { + fn addrSym(ctx: @This(), sym_index: u32) UpdateError!void { try ctx.wip_nav.frameAddrSym(sym_index, 0); } - fn infoEntry(ctx: @This(), _: *Writer, unit: Unit.Index, entry: Entry.Index) UpdateError!void { + fn infoEntry(ctx: @This(), unit: Unit.Index, entry: Entry.Index) UpdateError!void { try ctx.wip_nav.sectionOffset(.debug_frame, .debug_info, unit, entry, 0); } } = .{ .wip_nav = wip_nav }; - try bw.writeLeb128(len); - try loc.write(bw, adapter); + try uleb128(adapter.writer(), counter.stream.bytes_written); + try loc.write(adapter); } fn frameAddrSym(wip_nav: *WipNav, sym_index: u32, sym_off: u64) UpdateError!void { - const dfbw = &wip_nav.debug_frame.buffered_writer; try wip_nav.frameExternalReloc(.{ - .source_off = @intCast(dfbw.count), + .source_off = @intCast(wip_nav.debug_frame.items.len), .target_sym = sym_index, .target_off = sym_off, }); - try dfbw.splatByteAll(0, @intFromEnum(wip_nav.dwarf.address_size)); + try wip_nav.debug_frame.appendNTimes(wip_nav.dwarf.gpa, 0, @intFromEnum(wip_nav.dwarf.address_size)); } fn getNavEntry(wip_nav: *WipNav, nav_index: InternPool.Nav.Index) UpdateError!struct { Unit.Index, Entry.Index } { @@ -1935,41 +1922,38 @@ pub const WipNav = struct { try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0); } - fn refForward(wip_nav: *WipNav) Allocator.Error!u32 { + fn refForward(wip_nav: *WipNav) std.mem.Allocator.Error!u32 { const dwarf = wip_nav.dwarf; - const dibw = &wip_nav.debug_info.buffered_writer; const cross_entry_relocs = &dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_entry_relocs; const reloc_index: u32 = @intCast(cross_entry_relocs.items.len); try cross_entry_relocs.append(dwarf.gpa, .{ - .source_off = @intCast(dibw.count), + .source_off = @intCast(wip_nav.debug_info.items.len), .target_entry = undefined, .target_off = undefined, }); - try dibw.splatByteAll(0, dwarf.sectionOffsetBytes()); + try wip_nav.debug_info.appendNTimes(dwarf.gpa, 0, dwarf.sectionOffsetBytes()); return reloc_index; } fn finishForward(wip_nav: *WipNav, reloc_index: u32) void { const reloc = &wip_nav.dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_entry_relocs.items[reloc_index]; reloc.target_entry = wip_nav.entry.toOptional(); - reloc.target_off = @intCast(wip_nav.debug_info.buffered_writer.count); + reloc.target_off = @intCast(wip_nav.debug_info.items.len); } fn blockValue(wip_nav: *WipNav, src_loc: Zcu.LazySrcLoc, val: Value) UpdateError!void { const ty = val.typeOf(wip_nav.pt.zcu); - const dibw = &wip_nav.debug_info.buffered_writer; + const diw = wip_nav.debug_info.writer(wip_nav.dwarf.gpa); const bytes = if (ty.hasRuntimeBits(wip_nav.pt.zcu)) ty.abiSize(wip_nav.pt.zcu) else 0; - try dibw.writeLeb128(bytes); + try uleb128(diw, bytes); if (bytes == 0) return; - var dial = wip_nav.debug_info.toArrayList(); - defer _ = wip_nav.debug_info.fromArrayList(wip_nav.dwarf.gpa, &dial); - const old_len = dial.items.len; + const old_len = wip_nav.debug_info.items.len; try codegen.generateSymbol( wip_nav.dwarf.bin_file, wip_nav.pt, src_loc, val, - &dial, + &wip_nav.debug_info, .{ .debug_output = .{ .dwarf = wip_nav } }, ); if (old_len + bytes != wip_nav.debug_info.items.len) { @@ -1991,7 +1975,7 @@ pub const WipNav = struct { big_int: std.math.big.int.Const, ) UpdateError!void { const zcu = wip_nav.pt.zcu; - const dibw = &wip_nav.debug_info.buffered_writer; + const diw = wip_nav.debug_info.writer(wip_nav.dwarf.gpa); const signedness = switch (ty.toIntern()) { .comptime_int_type, .comptime_float_type => .signed, else => ty.intInfo(zcu).signedness, @@ -2002,7 +1986,7 @@ pub const WipNav = struct { .signed => abbrev_code.sdata, .unsigned => abbrev_code.udata, }); - _ = try dibw.writableSliceGreedy(std.math.divCeil(usize, bits, 7) catch unreachable); + try wip_nav.debug_info.ensureUnusedCapacity(wip_nav.dwarf.gpa, std.math.divCeil(usize, bits, 7) catch unreachable); var bit: usize = 0; var carry: u1 = 1; while (bit < bits) { @@ -2019,17 +2003,16 @@ pub const WipNav = struct { break :twos_comp_part twos_comp_part; }; bit += 7; - dibw.writeByte(@as(u8, if (bit < bits) 0x80 else 0x00) | twos_comp_part) catch unreachable; + wip_nav.debug_info.appendAssumeCapacity(@as(u8, if (bit < bits) 0x80 else 0x00) | twos_comp_part); } } else { try wip_nav.abbrevCode(abbrev_code.block); const bytes = @max(ty.abiSize(zcu), std.math.divCeil(usize, bits, 8) catch unreachable); - try dibw.writeLeb128(bytes); + try uleb128(diw, bytes); big_int.writeTwosComplement( - try dibw.writableSliceGreedy(@intCast(bytes)), + try wip_nav.debug_info.addManyAsSlice(wip_nav.dwarf.gpa, @intCast(bytes)), wip_nav.dwarf.endian, ); - dibw.advance(@intCast(bytes)); } } @@ -2062,7 +2045,7 @@ pub const WipNav = struct { const zcu = wip_nav.pt.zcu; const ip = &zcu.intern_pool; const dwarf = wip_nav.dwarf; - const dibw = &wip_nav.debug_info.buffered_writer; + const diw = wip_nav.debug_info.writer(dwarf.gpa); const orig_entry = wip_nav.entry; defer wip_nav.entry = orig_entry; @@ -2113,15 +2096,15 @@ pub const WipNav = struct { try wip_nav.abbrevCode(if (is_generic_decl) abbrev_code.generic_decl else abbrev_code.decl); try wip_nav.refType((if (is_generic_decl) null else parent_type) orelse .fromInterned(zcu.fileRootType(file))); - assert(dibw.count == DebugInfo.declEntryLineOff(dwarf)); - try dibw.writeInt(u32, decl.src_line + 1, dwarf.endian); - try dibw.writeLeb128(decl.src_column + 1); - try dibw.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); + assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); + try diw.writeInt(u32, decl.src_line + 1, dwarf.endian); + try uleb128(diw, decl.src_column + 1); + try diw.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); try wip_nav.strp(nav.name.toSlice(ip)); if (!is_generic_decl) return; const generic_decl_entry = wip_nav.entry; - try dwarf.debug_info.section.replaceEntry(wip_nav.unit, generic_decl_entry, dwarf, wip_nav.debug_info.getWritten()); + try dwarf.debug_info.section.replaceEntry(wip_nav.unit, generic_decl_entry, dwarf, wip_nav.debug_info.items); wip_nav.debug_info.clearRetainingCapacity(); wip_nav.entry = orig_entry; try wip_nav.abbrevCode(abbrev_code.decl_instance); @@ -2425,63 +2408,12 @@ pub fn initWipNav( nav_index: InternPool.Nav.Index, sym_index: u32, ) error{ OutOfMemory, CodegenFail }!?WipNav { - return dwarf.initWipNavInner(pt, nav_index, sym_index) catch |err| switch (err) { + return initWipNavInner(dwarf, pt, nav_index, sym_index) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, - else => |e| return pt.zcu.codegenFail(nav_index, "failed to init dwarf nav: {s}", .{@errorName(e)}), + else => |e| return pt.zcu.codegenFail(nav_index, "failed to init dwarf: {s}", .{@errorName(e)}), }; } -pub fn finishWipNavFunc( - dwarf: *Dwarf, - pt: Zcu.PerThread, - nav_index: InternPool.Nav.Index, - code_size: u64, - wip_nav: *WipNav, -) error{ OutOfMemory, CodegenFail }!void { - return dwarf.finishWipNavFuncInner(pt, nav_index, code_size, wip_nav) catch |err| switch (err) { - error.OutOfMemory => return error.OutOfMemory, - else => |e| return pt.zcu.codegenFail(nav_index, "failed to finish dwarf func nav: {s}", .{@errorName(e)}), - }; -} - -pub fn finishWipNav( - dwarf: *Dwarf, - pt: Zcu.PerThread, - nav_index: InternPool.Nav.Index, - wip_nav: *WipNav, -) error{ OutOfMemory, CodegenFail }!void { - return dwarf.finishWipNavInner(pt, nav_index, wip_nav) catch |err| switch (err) { - error.OutOfMemory => return error.OutOfMemory, - else => |e| return pt.zcu.codegenFail(nav_index, "failed to finish dwarf nav: {s}", .{@errorName(e)}), - }; -} - -pub fn updateComptimeNav( - dwarf: *Dwarf, - pt: Zcu.PerThread, - nav_index: InternPool.Nav.Index, -) error{ OutOfMemory, CodegenFail }!void { - return dwarf.updateComptimeNavInner(pt, nav_index) catch |err| switch (err) { - error.OutOfMemory => return error.OutOfMemory, - else => |e| return pt.zcu.codegenFail(nav_index, "failed to update dwarf comptime nav: {s}", .{@errorName(e)}), - }; -} - -pub fn updateContainerType( - dwarf: *Dwarf, - pt: Zcu.PerThread, - type_index: InternPool.Index, -) error{ OutOfMemory, CodegenFail }!void { - return dwarf.updateContainerType(pt, type_index) catch |err| switch (err) { - error.OutOfMemory => return error.OutOfMemory, - else => |e| return pt.zcu.codegenFailType(type_index, "failed to update dwarf comptime nav: {s}", .{@errorName(e)}), - }; -} - -pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { - return dwarf.flushModuleInner(pt); -} - fn initWipNavInner( dwarf: *Dwarf, pt: Zcu.PerThread, @@ -2536,17 +2468,17 @@ fn initWipNavInner( .func_high_pc = undefined, .blocks = undefined, .cfi = undefined, - .debug_frame = undefined, - .debug_info = undefined, - .debug_line = undefined, - .debug_loclists = undefined, + .debug_frame = .empty, + .debug_info = .empty, + .debug_line = .empty, + .debug_loclists = .empty, .pending_lazy = .empty, }; errdefer wip_nav.deinit(); switch (nav_key) { else => { - const dibw = &wip_nav.debug_info.buffered_writer; + const diw = wip_nav.debug_info.writer(dwarf.gpa); try wip_nav.declCommon(.{ .decl = .decl_var, .generic_decl = .generic_decl_var, @@ -2567,9 +2499,9 @@ fn initWipNavInner( .@"const" => { const const_ty_reloc_index = try wip_nav.refForward(); try wip_nav.infoExprLoc(loc); - try dibw.writeLeb128(nav.status.fully_resolved.alignment.toByteUnits() orelse + try uleb128(diw, nav.status.fully_resolved.alignment.toByteUnits() orelse ty.abiAlignment(zcu).toByteUnits().?); - try dibw.writeByte(@intFromBool(decl.linkage != .normal)); + try diw.writeByte(@intFromBool(decl.linkage != .normal)); wip_nav.finishForward(const_ty_reloc_index); try wip_nav.abbrevCode(.is_const); try wip_nav.refType(ty); @@ -2577,9 +2509,9 @@ fn initWipNavInner( .@"var" => { try wip_nav.refType(ty); try wip_nav.infoExprLoc(loc); - try dibw.writeLeb128(dibw, nav.status.fully_resolved.alignment.toByteUnits() orelse + try uleb128(diw, nav.status.fully_resolved.alignment.toByteUnits() orelse ty.abiAlignment(zcu).toByteUnits().?); - try dibw.writeByte(@intFromBool(decl.linkage != .normal)); + try diw.writeByte(@intFromBool(decl.linkage != .normal)); }, } }, @@ -2604,39 +2536,39 @@ fn initWipNavInner( .none => {}, .debug_frame, .eh_frame => |format| { const entry = dwarf.debug_frame.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry); - const dfbw = &wip_nav.debug_frame.buffered_writer; + const dfw = wip_nav.debug_frame.writer(dwarf.gpa); switch (dwarf.format) { - .@"32" => try dfbw.writeInt(u32, undefined, dwarf.endian), + .@"32" => try dfw.writeInt(u32, undefined, dwarf.endian), .@"64" => { - try dfbw.writeInt(u32, std.math.maxInt(u32), dwarf.endian); - try dfbw.writeInt(u64, undefined, dwarf.endian); + try dfw.writeInt(u32, std.math.maxInt(u32), dwarf.endian); + try dfw.writeInt(u64, undefined, dwarf.endian); }, } switch (format) { .none => unreachable, .debug_frame => { try entry.cross_entry_relocs.append(dwarf.gpa, .{ - .source_off = @intCast(dfbw.count), + .source_off = @intCast(wip_nav.debug_frame.items.len), }); - try dfbw.splatByteAll(0, dwarf.sectionOffsetBytes()); + try dfw.writeByteNTimes(0, dwarf.sectionOffsetBytes()); try wip_nav.frameAddrSym(sym_index, 0); - try dfbw.splatByteAll(undefined, @intFromEnum(dwarf.address_size)); + try dfw.writeByteNTimes(undefined, @intFromEnum(dwarf.address_size)); }, .eh_frame => { - try dfbw.writeInt(u32, undefined, dwarf.endian); + try dfw.writeInt(u32, undefined, dwarf.endian); try wip_nav.frameExternalReloc(.{ - .source_off = @intCast(dfbw.count), + .source_off = @intCast(wip_nav.debug_frame.items.len), .target_sym = sym_index, }); - try dfbw.writeInt(u32, 0, dwarf.endian); - try dfbw.writeInt(u32, undefined, dwarf.endian); - try dfbw.writeUleb128(0); + try dfw.writeInt(u32, 0, dwarf.endian); + try dfw.writeInt(u32, undefined, dwarf.endian); + try uleb128(dfw, 0); }, } }, } - const dibw = &wip_nav.debug_info.buffered_writer; + const diw = wip_nav.debug_info.writer(dwarf.gpa); try wip_nav.declCommon(.{ .decl = .decl_func, .generic_decl = .generic_decl_func, @@ -2646,47 +2578,47 @@ fn initWipNavInner( try wip_nav.refType(.fromInterned(func_type.return_type)); try wip_nav.infoAddrSym(sym_index, 0); wip_nav.func_high_pc = @intCast(wip_nav.debug_info.items.len); - try dibw.writeInt(u32, 0, dwarf.endian); + try diw.writeInt(u32, 0, dwarf.endian); const target = &mod.resolved_target.result; - try dibw.writeLeb128(switch (nav.status.fully_resolved.alignment) { + try uleb128(diw, switch (nav.status.fully_resolved.alignment) { .none => target_info.defaultFunctionAlignment(target), else => |a| a.maxStrict(target_info.minFunctionAlignment(target)), }.toByteUnits().?); - try dibw.writeByte(@intFromBool(decl.linkage != .normal)); - try dibw.writeByte(@intFromBool(func_type.return_type == .noreturn_type)); + try diw.writeByte(@intFromBool(decl.linkage != .normal)); + try diw.writeByte(@intFromBool(func_type.return_type == .noreturn_type)); - const dlbw = &wip_nav.debug_line.buffered_writer; - try dlbw.writeByte(DW.LNS.extended_op); + const dlw = wip_nav.debug_line.writer(dwarf.gpa); + try dlw.writeByte(DW.LNS.extended_op); if (dwarf.incremental()) { - try dlbw.writeLeb128(1 + dwarf.sectionOffsetBytes()); - try dlbw.writeByte(DW.LNE.ZIG_set_decl); + try uleb128(dlw, 1 + dwarf.sectionOffsetBytes()); + try dlw.writeByte(DW.LNE.ZIG_set_decl); try dwarf.debug_line.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_section_relocs.append(dwarf.gpa, .{ - .source_off = @intCast(dlbw.count), + .source_off = @intCast(wip_nav.debug_line.items.len), .target_sec = .debug_info, .target_unit = wip_nav.unit, .target_entry = wip_nav.entry.toOptional(), }); - try dlbw.splatByteAll(0, dwarf.sectionOffsetBytes()); + try dlw.writeByteNTimes(0, dwarf.sectionOffsetBytes()); - try dlbw.writeByte(DW.LNS.set_column); - try dlbw.writeLeb128(func.lbrace_column + 1); + try dlw.writeByte(DW.LNS.set_column); + try uleb128(dlw, func.lbrace_column + 1); try wip_nav.advancePCAndLine(func.lbrace_line, 0); } else { - try dlbw.writeLeb128(1 + @intFromEnum(dwarf.address_size)); - try dlbw.writeByte(DW.LNE.set_address); + try uleb128(dlw, 1 + @intFromEnum(dwarf.address_size)); + try dlw.writeByte(DW.LNE.set_address); try dwarf.debug_line.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs.append(dwarf.gpa, .{ - .source_off = @intCast(dlbw.count), + .source_off = @intCast(wip_nav.debug_line.items.len), .target_sym = sym_index, }); - try dlbw.splatByteAll(0, @intFromEnum(dwarf.address_size)); + try dlw.writeByteNTimes(0, @intFromEnum(dwarf.address_size)); const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, inst_info.file); - try dlbw.writeByte(DW.LNS.set_file); - try dlbw.writeLeb128(file_gop.index); + try dlw.writeByte(DW.LNS.set_file); + try uleb128(dlw, file_gop.index); - try dlbw.writeByte(DW.LNS.set_column); - try dlbw.writeLeb128(func.lbrace_column + 1); + try dlw.writeByte(DW.LNS.set_column); + try uleb128(dlw, func.lbrace_column + 1); try wip_nav.advancePCAndLine(@intCast(decl.src_line + func.lbrace_line), 0); } @@ -2695,7 +2627,7 @@ fn initWipNavInner( return wip_nav; } -fn finishWipNavFuncInner( +pub fn finishWipNavFunc( dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, @@ -2724,9 +2656,12 @@ fn finishWipNavFuncInner( switch (dwarf.debug_frame.header.format) { .none => {}, .debug_frame, .eh_frame => |format| { - const dfbw = &wip_nav.debug_frame.buffered_writer; - try dfbw.splatByteAll(DW.CFA.nop, @intCast(dwarf.debug_frame.section.alignment.forward(dfbw.count) - dfbw.count)); - const contents = wip_nav.debug_frame.getWritten(); + try wip_nav.debug_frame.appendNTimes( + dwarf.gpa, + DW.CFA.nop, + @intCast(dwarf.debug_frame.section.alignment.forward(wip_nav.debug_frame.items.len) - wip_nav.debug_frame.items.len), + ); + const contents = wip_nav.debug_frame.items; try dwarf.debug_frame.section.resizeEntry(wip_nav.unit, wip_nav.entry, dwarf, @intCast(contents.len)); const unit = dwarf.debug_frame.section.getUnit(wip_nav.unit); const entry = unit.getEntry(wip_nav.entry); @@ -2753,14 +2688,14 @@ fn finishWipNavFuncInner( }, } { - std.mem.writeInt(u32, wip_nav.debug_info.getWritten()[wip_nav.func_high_pc..][0..4], @intCast(code_size), dwarf.endian); + std.mem.writeInt(u32, wip_nav.debug_info.items[wip_nav.func_high_pc..][0..4], @intCast(code_size), dwarf.endian); if (wip_nav.any_children) { - const dibw = &wip_nav.debug_info.buffered_writer; - try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); + const diw = wip_nav.debug_info.writer(dwarf.gpa); + try uleb128(diw, @intFromEnum(AbbrevCode.null)); } else { - const abbrev_code_buf = wip_nav.debug_info.getWritten()[0..AbbrevCode.decl_bytes]; - var abbrev_code_br: std.io.Reader = .fixed(abbrev_code_buf); - const abbrev_code: AbbrevCode = @enumFromInt(abbrev_code_br.takeLeb128(@typeInfo(AbbrevCode).@"enum".tag_type) catch unreachable); + const abbrev_code_buf = wip_nav.debug_info.items[0..AbbrevCode.decl_bytes]; + var abbrev_code_fbs = std.io.fixedBufferStream(abbrev_code_buf); + const abbrev_code: AbbrevCode = @enumFromInt(std.leb.readUleb128(@typeInfo(AbbrevCode).@"enum".tag_type, abbrev_code_fbs.reader()) catch unreachable); std.leb.writeUnsignedFixed( AbbrevCode.decl_bytes, abbrev_code_buf, @@ -2792,10 +2727,10 @@ fn finishWipNavFuncInner( ); } - try dwarf.finishWipNavInner(pt, nav_index, wip_nav); + try dwarf.finishWipNav(pt, nav_index, wip_nav); } -fn finishWipNavInner( +pub fn finishWipNav( dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, @@ -2806,20 +2741,26 @@ fn finishWipNavInner( const nav = ip.getNav(nav_index); log.debug("finishWipNav({f})", .{nav.fqn.fmt(ip)}); - try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.getWritten()); - const debug_line = wip_nav.debug_line.getWritten(); - if (debug_line.len > 0) { - const dlbw = &wip_nav.debug_line.buffered_writer; - try dlbw.writeByte(DW.LNS.extended_op); - try dlbw.writeUleb128(1); - try dlbw.writeByte(DW.LNE.end_sequence); - try dwarf.debug_line.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_line.getWritten()); + try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items); + if (wip_nav.debug_line.items.len > 0) { + const dlw = wip_nav.debug_line.writer(dwarf.gpa); + try dlw.writeByte(DW.LNS.extended_op); + try uleb128(dlw, 1); + try dlw.writeByte(DW.LNE.end_sequence); + try dwarf.debug_line.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_line.items); } - try dwarf.debug_loclists.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_loclists.getWritten()); + try dwarf.debug_loclists.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_loclists.items); try wip_nav.updateLazy(zcu.navSrcLoc(nav_index)); } +pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) error{ OutOfMemory, CodegenFail }!void { + return updateComptimeNavInner(dwarf, pt, nav_index) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + else => |e| return pt.zcu.codegenFail(nav_index, "failed to update dwarf: {s}", .{@errorName(e)}), + }; +} + fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void { const zcu = pt.zcu; const ip = &zcu.intern_pool; @@ -2858,13 +2799,12 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo .func_high_pc = undefined, .blocks = undefined, .cfi = undefined, - .debug_frame = undefined, - .debug_info = undefined, - .debug_line = undefined, - .debug_loclists = undefined, + .debug_frame = .empty, + .debug_info = .empty, + .debug_line = .empty, + .debug_loclists = .empty, .pending_lazy = .empty, }; - wip_nav.init(); defer wip_nav.deinit(); const nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index); @@ -2908,7 +2848,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo } wip_nav.entry = nav_gop.value_ptr.*; - const dibw = &wip_nav.debug_info.buffered_writer; + const diw = wip_nav.debug_info.writer(dwarf.gpa); switch (loaded_struct.layout) { .auto, .@"extern" => { @@ -2921,9 +2861,9 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo .generic_decl = .generic_decl_const, .decl_instance = .decl_instance_struct, }, &nav, inst_info.file, &decl); - if (loaded_struct.field_types.len == 0) try dibw.writeByte(@intFromBool(false)) else { - try dibw.writeLeb128(nav_val.toType().abiSize(zcu)); - try dibw.writeLeb128(nav_val.toType().abiAlignment(zcu).toByteUnits().?); + if (loaded_struct.field_types.len == 0) try diw.writeByte(@intFromBool(false)) else { + try uleb128(diw, nav_val.toType().abiSize(zcu)); + try uleb128(diw, nav_val.toType().abiAlignment(zcu).toByteUnits().?); for (0..loaded_struct.field_types.len) |field_index| { const is_comptime = loaded_struct.fieldIsComptime(ip, field_index); const field_init = loaded_struct.fieldInit(ip, field_index); @@ -2959,8 +2899,8 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo } try wip_nav.refType(field_type); if (!is_comptime) { - try dibw.writeLeb128(loaded_struct.offsets.get(ip)[field_index]); - try dibw.writeLeb128(loaded_struct.fieldAlign(ip, field_index).toByteUnits() orelse + try uleb128(diw, loaded_struct.offsets.get(ip)[field_index]); + try uleb128(diw, loaded_struct.fieldAlign(ip, field_index).toByteUnits() orelse field_type.abiAlignment(zcu).toByteUnits().?); } if (has_comptime_state) @@ -2968,7 +2908,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo else if (has_runtime_bits) try wip_nav.blockValue(nav_src_loc, .fromInterned(field_init)); } - try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); + try uleb128(diw, @intFromEnum(AbbrevCode.null)); } }, .@"packed" => { @@ -2984,10 +2924,10 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo 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); - try dibw.writeLeb128(field_bit_offset); + try uleb128(diw, field_bit_offset); field_bit_offset += @intCast(field_type.bitSize(zcu)); } - try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); + try uleb128(diw, @intFromEnum(AbbrevCode.null)); }, } break :tag .done; @@ -3010,7 +2950,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo type_gop.value_ptr.* = nav_gop.value_ptr.*; } wip_nav.entry = nav_gop.value_ptr.*; - const dibw = &wip_nav.debug_info.buffered_writer; + const diw = wip_nav.debug_info.writer(dwarf.gpa); try wip_nav.declCommon(if (loaded_enum.names.len > 0) .{ .decl = .decl_enum, .generic_decl = .generic_decl_const, @@ -3029,7 +2969,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo }, field_index); try wip_nav.strp(loaded_enum.names.get(ip)[field_index].toSlice(ip)); } - if (loaded_enum.names.len > 0) try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); + if (loaded_enum.names.len > 0) try uleb128(diw, @intFromEnum(AbbrevCode.null)); break :tag .done; }, .union_type => tag: { @@ -3049,15 +2989,15 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo type_gop.value_ptr.* = nav_gop.value_ptr.*; } wip_nav.entry = nav_gop.value_ptr.*; - const dibw = &wip_nav.debug_info.buffered_writer; + const diw = wip_nav.debug_info.writer(dwarf.gpa); try wip_nav.declCommon(.{ .decl = .decl_union, .generic_decl = .generic_decl_const, .decl_instance = .decl_instance_union, }, &nav, inst_info.file, &decl); const union_layout = Type.getUnionLayout(loaded_union, zcu); - try dibw.writeLeb128(union_layout.abi_size); - try dibw.writeLeb128(union_layout.abi_align.toByteUnits().?); + 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 wip_nav.abbrevCode(.tagged_union); @@ -3065,13 +3005,13 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo .debug_info, wip_nav.unit, wip_nav.entry, - @intCast(dibw.count + dwarf.sectionOffsetBytes()), + @intCast(wip_nav.debug_info.items.len + dwarf.sectionOffsetBytes()), ); { try wip_nav.abbrevCode(.generated_field); try wip_nav.strp("tag"); try wip_nav.refType(.fromInterned(loaded_union.enum_tag_ty)); - try dibw.writeLeb128(union_layout.tagOffset()); + try uleb128(diw, union_layout.tagOffset()); for (0..loaded_union.field_types.len) |field_index| { try wip_nav.enumConstValue(loaded_tag, .{ @@ -3084,23 +3024,23 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo 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); - try dibw.writeLeb128(union_layout.payloadOffset()); - try dibw.writeLeb128(loaded_union.fieldAlign(ip, field_index).toByteUnits() orelse + try uleb128(diw, union_layout.payloadOffset()); + try uleb128(diw, loaded_union.fieldAlign(ip, field_index).toByteUnits() orelse if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?); } - try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); + try uleb128(diw, @intFromEnum(AbbrevCode.null)); } } - try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); + try uleb128(diw, @intFromEnum(AbbrevCode.null)); } else for (0..loaded_union.field_types.len) |field_index| { 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); - try dibw.writeLeb128(loaded_union.fieldAlign(ip, field_index).toByteUnits() orelse + try uleb128(diw, loaded_union.fieldAlign(ip, field_index).toByteUnits() orelse field_type.abiAlignment(zcu).toByteUnits().?); } - try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); + try uleb128(diw, @intFromEnum(AbbrevCode.null)); break :tag .done; }, .opaque_type => tag: { @@ -3120,13 +3060,13 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo type_gop.value_ptr.* = nav_gop.value_ptr.*; } wip_nav.entry = nav_gop.value_ptr.*; - const dibw = &wip_nav.debug_info.buffered_writer; + const diw = wip_nav.debug_info.writer(dwarf.gpa); try wip_nav.declCommon(.{ .decl = .decl_namespace_struct, .generic_decl = .generic_decl_const, .decl_instance = .decl_instance_namespace_struct, }, &nav, inst_info.file, &decl); - try dibw.writeByte(@intFromBool(true)); + try diw.writeByte(@intFromBool(true)); break :tag .done; }, .undef, @@ -3164,7 +3104,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo const is_nullary = !func_type.is_var_args and for (0..func_type.param_types.len) |param_index| { if (!func_type.paramIsComptime(std.math.cast(u5, param_index) orelse break false)) break false; } else true; - const dibw = &wip_nav.debug_info.buffered_writer; + const diw = wip_nav.debug_info.writer(dwarf.gpa); try wip_nav.declCommon(if (is_nullary) .{ .decl = .decl_nullary_func_generic, .generic_decl = .generic_decl_func, @@ -3183,7 +3123,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo try wip_nav.refType(.fromInterned(func_type.param_types.get(ip)[param_index])); } if (func_type.is_var_args) try wip_nav.abbrevCode(.is_var_args); - try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); + try uleb128(diw, @intFromEnum(AbbrevCode.null)); } break :tag .done; }, @@ -3208,7 +3148,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo try wip_nav.refType(nav_val.toType()); }, .decl_var => { - const dibw = &wip_nav.debug_info.buffered_writer; + const diw = wip_nav.debug_info.writer(dwarf.gpa); try wip_nav.declCommon(.{ .decl = .decl_var, .generic_decl = .generic_decl_var, @@ -3218,12 +3158,12 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo const nav_ty = nav_val.typeOf(zcu); try wip_nav.refType(nav_ty); try wip_nav.blockValue(nav_src_loc, nav_val); - try dibw.writeLeb128(nav.status.fully_resolved.alignment.toByteUnits() orelse + try uleb128(diw, nav.status.fully_resolved.alignment.toByteUnits() orelse nav_ty.abiAlignment(zcu).toByteUnits().?); - try dibw.writeByte(@intFromBool(decl.linkage != .normal)); + try diw.writeByte(@intFromBool(decl.linkage != .normal)); }, .decl_const => { - const dibw = &wip_nav.debug_info.buffered_writer; + const diw = wip_nav.debug_info.writer(dwarf.gpa); const nav_ty = nav_val.typeOf(zcu); const has_runtime_bits = nav_ty.hasRuntimeBits(zcu); const has_comptime_state = nav_ty.comptimeOnly(zcu) and try nav_ty.onePossibleValue(pt) == null; @@ -3246,9 +3186,9 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo }, &nav, inst_info.file, &decl); try wip_nav.strp(nav.fqn.toSlice(ip)); const nav_ty_reloc_index = try wip_nav.refForward(); - try dibw.writeLeb128(nav.status.fully_resolved.alignment.toByteUnits() orelse + try uleb128(diw, nav.status.fully_resolved.alignment.toByteUnits() orelse nav_ty.abiAlignment(zcu).toByteUnits().?); - try dibw.writeByte(@intFromBool(decl.linkage != .normal)); + try diw.writeByte(@intFromBool(decl.linkage != .normal)); if (has_runtime_bits) try wip_nav.blockValue(nav_src_loc, nav_val); if (has_comptime_state) try wip_nav.refValue(nav_val); wip_nav.finishForward(nav_ty_reloc_index); @@ -3264,7 +3204,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo try wip_nav.refNav(owner_nav); }, } - try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.getWritten()); + try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items); try wip_nav.updateLazy(nav_src_loc); } @@ -3295,19 +3235,18 @@ fn updateLazyType( .func_high_pc = undefined, .blocks = undefined, .cfi = undefined, - .debug_frame = undefined, - .debug_info = undefined, - .debug_line = undefined, - .debug_loclists = undefined, + .debug_frame = .empty, + .debug_info = .empty, + .debug_line = .empty, + .debug_loclists = .empty, .pending_lazy = pending_lazy.*, }; - wip_nav.init(); defer { pending_lazy.* = wip_nav.pending_lazy; wip_nav.pending_lazy = .empty; wip_nav.deinit(); } - const dibw = &wip_nav.debug_info.buffered_writer; + const diw = wip_nav.debug_info.writer(dwarf.gpa); const name = switch (type_index) { .generic_poison_type => "", else => try std.fmt.allocPrint(dwarf.gpa, "{f}", .{ty.fmt(pt)}), @@ -3322,12 +3261,12 @@ fn updateLazyType( .int_type => |int_type| { try wip_nav.abbrevCode(.numeric_type); try wip_nav.strp(name); - try dibw.writeByte(switch (int_type.signedness) { + try diw.writeByte(switch (int_type.signedness) { inline .signed, .unsigned => |signedness| @field(DW.ATE, @tagName(signedness)), }); - try dibw.writeLeb128(int_type.bits); - try dibw.writeLeb128(ty.abiSize(zcu)); - try dibw.writeLeb128(ty.abiAlignment(zcu).toByteUnits().?); + try uleb128(diw, int_type.bits); + try uleb128(diw, ty.abiSize(zcu)); + try uleb128(diw, ty.abiAlignment(zcu).toByteUnits().?); }, .ptr_type => |ptr_type| switch (ptr_type.flags.size) { .one, .many, .c => { @@ -3335,14 +3274,14 @@ fn updateLazyType( try wip_nav.abbrevCode(if (ptr_type.sentinel == .none) .ptr_type else .ptr_sentinel_type); try wip_nav.strp(name); if (ptr_type.sentinel != .none) try wip_nav.blockValue(src_loc, .fromInterned(ptr_type.sentinel)); - try dibw.writeLeb128(ptr_type.flags.alignment.toByteUnits() orelse + try uleb128(diw, ptr_type.flags.alignment.toByteUnits() orelse ptr_child_type.abiAlignment(zcu).toByteUnits().?); - try dibw.writeByte(@intFromEnum(ptr_type.flags.address_space)); + try diw.writeByte(@intFromEnum(ptr_type.flags.address_space)); if (ptr_type.flags.is_const or ptr_type.flags.is_volatile) try wip_nav.infoSectionOffset( .debug_info, wip_nav.unit, wip_nav.entry, - @intCast(dibw.count + dwarf.sectionOffsetBytes()), + @intCast(wip_nav.debug_info.items.len + dwarf.sectionOffsetBytes()), ) else try wip_nav.refType(ptr_child_type); if (ptr_type.flags.is_const) { try wip_nav.abbrevCode(.is_const); @@ -3350,7 +3289,7 @@ fn updateLazyType( .debug_info, wip_nav.unit, wip_nav.entry, - @intCast(dibw.count + dwarf.sectionOffsetBytes()), + @intCast(wip_nav.debug_info.items.len + dwarf.sectionOffsetBytes()), ) else try wip_nav.refType(ptr_child_type); } if (ptr_type.flags.is_volatile) { @@ -3361,19 +3300,19 @@ fn updateLazyType( .slice => { try wip_nav.abbrevCode(.generated_struct_type); try wip_nav.strp(name); - try dibw.writeLeb128(ty.abiSize(zcu)); - try dibw.writeLeb128(ty.abiAlignment(zcu).toByteUnits().?); + try uleb128(diw, ty.abiSize(zcu)); + try uleb128(diw, ty.abiAlignment(zcu).toByteUnits().?); 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 dibw.writeUleb128(0); + try uleb128(diw, 0); try wip_nav.abbrevCode(.generated_field); try wip_nav.strp("len"); const len_field_type: Type = .usize; try wip_nav.refType(len_field_type); - try dibw.writeLeb128(len_field_type.abiAlignment(zcu).forward(ptr_field_type.abiSize(zcu))); - try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); + try uleb128(diw, len_field_type.abiAlignment(zcu).forward(ptr_field_type.abiSize(zcu))); + try uleb128(diw, @intFromEnum(AbbrevCode.null)); }, }, .array_type => |array_type| { @@ -3384,8 +3323,8 @@ fn updateLazyType( try wip_nav.refType(array_child_type); try wip_nav.abbrevCode(.array_index); try wip_nav.refType(.usize); - try dibw.writeLeb128(array_type.len); - try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); + try uleb128(diw, array_type.len); + try uleb128(diw, @intFromEnum(AbbrevCode.null)); }, .vector_type => |vector_type| { try wip_nav.abbrevCode(.vector_type); @@ -3393,22 +3332,22 @@ fn updateLazyType( try wip_nav.refType(.fromInterned(vector_type.child)); try wip_nav.abbrevCode(.array_index); try wip_nav.refType(.usize); - try dibw.writeLeb128(vector_type.len); - try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); + try uleb128(diw, vector_type.len); + try uleb128(diw, @intFromEnum(AbbrevCode.null)); }, .opt_type => |opt_child_type_index| { const opt_child_type: Type = .fromInterned(opt_child_type_index); const opt_repr = optRepr(opt_child_type, zcu); try wip_nav.abbrevCode(.generated_union_type); try wip_nav.strp(name); - try dibw.writeLeb128(ty.abiSize(zcu)); - try dibw.writeLeb128(ty.abiAlignment(zcu).toByteUnits().?); + try uleb128(diw, ty.abiSize(zcu)); + try uleb128(diw, ty.abiAlignment(zcu).toByteUnits().?); switch (opt_repr) { .opv_null => { try wip_nav.abbrevCode(.generated_field); try wip_nav.strp("null"); try wip_nav.refType(.null); - try dibw.writeUleb128(0); + try uleb128(diw, 0); }, .unpacked, .error_set, .pointer => { try wip_nav.abbrevCode(.tagged_union); @@ -3416,7 +3355,7 @@ fn updateLazyType( .debug_info, wip_nav.unit, wip_nav.entry, - @intCast(dibw.count + dwarf.sectionOffsetBytes()), + @intCast(wip_nav.debug_info.items.len + dwarf.sectionOffsetBytes()), ); { try wip_nav.abbrevCode(.generated_field); @@ -3425,7 +3364,7 @@ fn updateLazyType( .opv_null => unreachable, .unpacked => { try wip_nav.refType(.bool); - try dibw.writeLeb128(if (opt_child_type.hasRuntimeBits(zcu)) + try uleb128(diw, if (opt_child_type.hasRuntimeBits(zcu)) opt_child_type.abiSize(zcu) else 0); @@ -3435,37 +3374,37 @@ fn updateLazyType( .signedness = .unsigned, .bits = zcu.errorSetBits(), } }))); - try dibw.writeUleb128(0); + try uleb128(diw, 0); }, .pointer => { try wip_nav.refType(.usize); - try dibw.writeUleb128(0); + try uleb128(diw, 0); }, } try wip_nav.abbrevCode(.unsigned_tagged_union_field); - try dibw.writeUleb128(0); + try uleb128(diw, 0); { try wip_nav.abbrevCode(.generated_field); try wip_nav.strp("null"); try wip_nav.refType(.null); - try dibw.writeUleb128(0); + try uleb128(diw, 0); } - try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); + try uleb128(diw, @intFromEnum(AbbrevCode.null)); try wip_nav.abbrevCode(.tagged_union_default_field); { try wip_nav.abbrevCode(.generated_field); try wip_nav.strp("?"); try wip_nav.refType(opt_child_type); - try dibw.writeUleb128(0); + try uleb128(diw, 0); } - try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); + try uleb128(diw, @intFromEnum(AbbrevCode.null)); } - try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); + try uleb128(diw, @intFromEnum(AbbrevCode.null)); }, } - try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); + try uleb128(diw, @intFromEnum(AbbrevCode.null)); }, .anyframe_type => unreachable, .error_union_type => |error_union_type| { @@ -3484,11 +3423,11 @@ fn updateLazyType( if (error_union_type.error_set_type != .generic_poison_type and error_union_type.payload_type != .generic_poison_type) { - try dibw.writeLeb128(ty.abiSize(zcu)); - try dibw.writeLeb128(ty.abiAlignment(zcu).toByteUnits().?); + try uleb128(diw, ty.abiSize(zcu)); + try uleb128(diw, ty.abiAlignment(zcu).toByteUnits().?); } else { - try dibw.writeUleb128(0); - try dibw.writeUleb128(1); + try uleb128(diw, 0); + try uleb128(diw, 1); } { try wip_nav.abbrevCode(.tagged_union); @@ -3496,7 +3435,7 @@ fn updateLazyType( .debug_info, wip_nav.unit, wip_nav.entry, - @intCast(dibw.count + dwarf.sectionOffsetBytes()), + @intCast(wip_nav.debug_info.items.len + dwarf.sectionOffsetBytes()), ); { try wip_nav.abbrevCode(.generated_field); @@ -3505,30 +3444,30 @@ fn updateLazyType( .signedness = .unsigned, .bits = zcu.errorSetBits(), } }))); - try dibw.writeLeb128(error_union_error_set_offset); + try uleb128(diw, error_union_error_set_offset); try wip_nav.abbrevCode(.unsigned_tagged_union_field); - try dibw.writeUleb128(0); + try uleb128(diw, 0); { try wip_nav.abbrevCode(.generated_field); try wip_nav.strp("value"); try wip_nav.refType(error_union_payload_type); - try dibw.writeLeb128(error_union_payload_offset); + try uleb128(diw, error_union_payload_offset); } - try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); + try uleb128(diw, @intFromEnum(AbbrevCode.null)); try wip_nav.abbrevCode(.tagged_union_default_field); { try wip_nav.abbrevCode(.generated_field); try wip_nav.strp("error"); try wip_nav.refType(error_union_error_set_type); - try dibw.writeLeb128(error_union_error_set_offset); + try uleb128(diw, error_union_error_set_offset); } - try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); + try uleb128(diw, @intFromEnum(AbbrevCode.null)); } - try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); + try uleb128(diw, @intFromEnum(AbbrevCode.null)); } - try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); + try uleb128(diw, @intFromEnum(AbbrevCode.null)); }, .simple_type => |simple_type| switch (simple_type) { .f16, @@ -3552,7 +3491,7 @@ fn updateLazyType( => { try wip_nav.abbrevCode(.numeric_type); try wip_nav.strp(name); - try dibw.writeByte(if (type_index == .bool_type) + try diw.writeByte(if (type_index == .bool_type) DW.ATE.boolean else if (ty.isRuntimeFloat()) DW.ATE.float @@ -3562,9 +3501,9 @@ fn updateLazyType( DW.ATE.unsigned else unreachable); - try dibw.writeLeb128(ty.bitSize(zcu)); - try dibw.writeLeb128(ty.abiSize(zcu)); - try dibw.writeLeb128(ty.abiAlignment(zcu).toByteUnits().?); + try uleb128(diw, ty.bitSize(zcu)); + try uleb128(diw, ty.abiSize(zcu)); + try uleb128(diw, ty.abiAlignment(zcu).toByteUnits().?); }, .anyopaque, .void, @@ -3590,12 +3529,12 @@ fn updateLazyType( .tuple_type => |tuple_type| if (tuple_type.types.len == 0) { try wip_nav.abbrevCode(.generated_empty_struct_type); try wip_nav.strp(name); - try dibw.writeByte(@intFromBool(false)); + try diw.writeByte(@intFromBool(false)); } else { try wip_nav.abbrevCode(.generated_struct_type); try wip_nav.strp(name); - try dibw.writeLeb128(ty.abiSize(zcu)); - try dibw.writeLeb128(ty.abiAlignment(zcu).toByteUnits().?); + try uleb128(diw, ty.abiSize(zcu)); + try uleb128(diw, ty.abiAlignment(zcu).toByteUnits().?); var field_byte_offset: u64 = 0; for (0..tuple_type.types.len) |field_index| { const comptime_value = tuple_type.values.get(ip)[field_index]; @@ -3624,8 +3563,8 @@ fn updateLazyType( if (comptime_value == .none) { const field_align = field_type.abiAlignment(zcu); field_byte_offset = field_align.forward(field_byte_offset); - try dibw.writeLeb128(field_byte_offset); - try dibw.writeLeb128(field_type.abiAlignment(zcu).toByteUnits().?); + try uleb128(diw, field_byte_offset); + try uleb128(diw, field_type.abiAlignment(zcu).toByteUnits().?); field_byte_offset += field_type.abiSize(zcu); } if (has_comptime_state) @@ -3633,7 +3572,7 @@ fn updateLazyType( else if (has_runtime_bits) try wip_nav.blockValue(src_loc, .fromInterned(comptime_value)); } - try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); + try uleb128(diw, @intFromEnum(AbbrevCode.null)); }, .enum_type => { const loaded_enum = ip.loadEnumType(type_index); @@ -3648,7 +3587,7 @@ fn updateLazyType( }, field_index); try wip_nav.strp(loaded_enum.names.get(ip)[field_index].toSlice(ip)); } - if (loaded_enum.names.len > 0) try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); + if (loaded_enum.names.len > 0) try uleb128(diw, @intFromEnum(AbbrevCode.null)); }, .func_type => |func_type| { const is_nullary = func_type.param_types.len == 0 and !func_type.is_var_args; @@ -3716,7 +3655,7 @@ fn updateLazyType( else => .nocall, }; }; - try dibw.writeByte(@intFromEnum(cc)); + try diw.writeByte(@intFromEnum(cc)); try wip_nav.refType(.fromInterned(func_type.return_type)); if (!is_nullary) { for (0..func_type.param_types.len) |param_index| { @@ -3724,7 +3663,7 @@ fn updateLazyType( try wip_nav.refType(.fromInterned(func_type.param_types.get(ip)[param_index])); } if (func_type.is_var_args) try wip_nav.abbrevCode(.is_var_args); - try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); + try uleb128(diw, @intFromEnum(AbbrevCode.null)); } }, .error_set_type => |error_set_type| { @@ -3737,10 +3676,10 @@ fn updateLazyType( for (0..error_set_type.names.len) |field_index| { const field_name = error_set_type.names.get(ip)[field_index]; try wip_nav.abbrevCode(.unsigned_enum_field); - try dibw.writeLeb128(ip.getErrorValueIfExists(field_name).?); + try uleb128(diw, ip.getErrorValueIfExists(field_name).?); try wip_nav.strp(field_name.toSlice(ip)); } - if (error_set_type.names.len > 0) try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); + if (error_set_type.names.len > 0) try uleb128(diw, @intFromEnum(AbbrevCode.null)); }, .inferred_error_set_type => |func| { try wip_nav.abbrevCode(.inferred_error_set_type); @@ -3772,7 +3711,7 @@ fn updateLazyType( .memoized_call, => unreachable, } - try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.getWritten()); + try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items); } fn updateLazyValue( @@ -3800,19 +3739,18 @@ fn updateLazyValue( .func_high_pc = undefined, .blocks = undefined, .cfi = undefined, - .debug_frame = undefined, - .debug_info = undefined, - .debug_line = undefined, - .debug_loclists = undefined, + .debug_frame = .empty, + .debug_info = .empty, + .debug_line = .empty, + .debug_loclists = .empty, .pending_lazy = pending_lazy.*, }; - wip_nav.init(); defer { pending_lazy.* = wip_nav.pending_lazy; wip_nav.pending_lazy = .empty; wip_nav.deinit(); } - const dibw = &wip_nav.debug_info.buffered_writer; + const diw = wip_nav.debug_info.writer(dwarf.gpa); var big_int_space: Value.BigIntSpace = undefined; switch (ip.indexToKey(value_index)) { .int_type, @@ -3850,7 +3788,7 @@ fn updateLazyValue( .err => |err| { try wip_nav.abbrevCode(.udata_comptime_value); try wip_nav.refType(.fromInterned(err.ty)); - try dibw.writeLeb128(try pt.getErrorValue(err.name)); + try uleb128(diw, try pt.getErrorValue(err.name)); }, .error_union => |error_union| { try wip_nav.abbrevCode(.aggregate_comptime_value); @@ -3862,8 +3800,8 @@ fn updateLazyValue( { try wip_nav.abbrevCode(.comptime_value_field_runtime_bits); try wip_nav.strp("is_error"); - try dibw.writeLeb128(err_abi_size); - try dwarf.writeIntTo(dibw, err_abi_size, err_value); + try uleb128(diw, err_abi_size); + dwarf.writeInt(try wip_nav.debug_info.addManyAsSlice(dwarf.gpa, err_abi_size), err_value); } payload_field: switch (error_union.val) { .err_name => {}, @@ -3887,8 +3825,8 @@ fn updateLazyValue( { try wip_nav.abbrevCode(.comptime_value_field_runtime_bits); try wip_nav.strp("error"); - try dibw.writeLeb128(err_abi_size); - try dwarf.writeIntTo(dibw, err_abi_size, err_value); + try uleb128(diw, err_abi_size); + dwarf.writeInt(try wip_nav.debug_info.addManyAsSlice(dwarf.gpa, err_abi_size), err_value); } switch (error_union.val) { .err_name => {}, @@ -3898,7 +3836,7 @@ fn updateLazyValue( }, } try wip_nav.refType(.fromInterned(error_union.ty)); - try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); + try uleb128(diw, @intFromEnum(AbbrevCode.null)); }, .enum_literal => |enum_literal| { try wip_nav.abbrevCode(.string_comptime_value); @@ -3919,24 +3857,24 @@ fn updateLazyValue( switch (float.storage) { .f16 => |f16_val| { try wip_nav.abbrevCode(.data2_comptime_value); - try dibw.writeInt(u16, @bitCast(f16_val), dwarf.endian); + try diw.writeInt(u16, @bitCast(f16_val), dwarf.endian); }, .f32 => |f32_val| { try wip_nav.abbrevCode(.data4_comptime_value); - try dibw.writeInt(u32, @bitCast(f32_val), dwarf.endian); + try diw.writeInt(u32, @bitCast(f32_val), dwarf.endian); }, .f64 => |f64_val| { try wip_nav.abbrevCode(.data8_comptime_value); - try dibw.writeInt(u64, @bitCast(f64_val), dwarf.endian); + try diw.writeInt(u64, @bitCast(f64_val), dwarf.endian); }, .f80 => |f80_val| { try wip_nav.abbrevCode(.block_comptime_value); - try dibw.writeUleb128(@divExact(80, 8)); - try dibw.writeInt(u80, @bitCast(f80_val), dwarf.endian); + try uleb128(diw, @divExact(80, 8)); + try diw.writeInt(u80, @bitCast(f80_val), dwarf.endian); }, .f128 => |f128_val| { try wip_nav.abbrevCode(.data16_comptime_value); - try dibw.writeInt(u128, @bitCast(f128_val), dwarf.endian); + try diw.writeInt(u128, @bitCast(f128_val), dwarf.endian); }, } try wip_nav.refType(.fromInterned(float.ty)); @@ -3953,14 +3891,14 @@ fn updateLazyValue( const uav_ty: Type = .fromInterned(ip.typeOf(uav.val)); if (try uav_ty.onePossibleValue(pt)) |_| { try wip_nav.abbrevCode(.udata_comptime_value); - try dibw.writeLeb128(ip.indexToKey(uav.orig_ty).ptr_type.flags.alignment.toByteUnits() orelse + try uleb128(diw, ip.indexToKey(uav.orig_ty).ptr_type.flags.alignment.toByteUnits() orelse uav_ty.abiAlignment(zcu).toByteUnits().?); break :location; } else break try wip_nav.getValueEntry(.fromInterned(uav.val)); }, .int => { try wip_nav.abbrevCode(.udata_comptime_value); - try dibw.writeLeb128(byte_offset); + try uleb128(diw, byte_offset); break :location; }, .eu_payload => |eu_ptr| { @@ -3999,7 +3937,7 @@ fn updateLazyValue( try wip_nav.strp("len"); try wip_nav.blockValue(src_loc, .fromInterned(slice.len)); } - try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); + try uleb128(diw, @intFromEnum(AbbrevCode.null)); }, .opt => |opt| { const opt_child_type: Type = .fromInterned(ip.indexToKey(opt.ty).opt_type); @@ -4009,7 +3947,7 @@ fn updateLazyValue( try wip_nav.abbrevCode(.comptime_value_field_runtime_bits); try wip_nav.strp("has_value"); switch (optRepr(opt_child_type, zcu)) { - .opv_null => try dibw.writeUleb128(0), + .opv_null => try uleb128(diw, 0), .unpacked => try wip_nav.blockValue(src_loc, .makeBool(opt.val != .none)), .error_set => try wip_nav.blockValue(src_loc, .fromInterned(value_index)), .pointer => if (opt_child_type.comptimeOnly(zcu)) { @@ -4019,8 +3957,8 @@ fn updateLazyValue( .none => 0, else => opt_child_type.ptrAlignment(zcu).toByteUnits().?, }); - try dibw.writeLeb128(bytes.len); - try dibw.writeAll(bytes); + try uleb128(diw, bytes.len); + try diw.writeAll(bytes); } else try wip_nav.blockValue(src_loc, .fromInterned(value_index)), } } @@ -4039,7 +3977,7 @@ fn updateLazyValue( else try wip_nav.blockValue(src_loc, .fromInterned(opt.val)); } - try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); + try uleb128(diw, @intFromEnum(AbbrevCode.null)); }, .aggregate => |aggregate| { try wip_nav.abbrevCode(.aggregate_comptime_value); @@ -4124,7 +4062,7 @@ fn updateLazyValue( }, else => unreachable, } - try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); + try uleb128(diw, @intFromEnum(AbbrevCode.null)); }, .un => |un| { try wip_nav.abbrevCode(.aggregate_comptime_value); @@ -4149,11 +4087,11 @@ fn updateLazyValue( else try wip_nav.blockValue(src_loc, .fromInterned(un.val)); } - try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); + try uleb128(diw, @intFromEnum(AbbrevCode.null)); }, .memoized_call => unreachable, // not a value } - try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.getWritten()); + try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items); } fn optRepr(opt_child_type: Type, zcu: *const Zcu) enum { @@ -4173,7 +4111,7 @@ fn optRepr(opt_child_type: Type, zcu: *const Zcu) enum { }; } -fn updateContainerTypeInner(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternPool.Index) UpdateError!void { +pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternPool.Index) UpdateError!void { const zcu = pt.zcu; const ip = &zcu.intern_pool; const ty: Type = .fromInterned(type_index); @@ -4500,26 +4438,25 @@ fn refAbbrevCode(dwarf: *Dwarf, abbrev_code: AbbrevCode) UpdateError!@typeInfo(A 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 daaw: std.io.Writer.Allocating = .init(dwarf.gpa); - defer daaw.deinit(); - const dabw = &daaw.interface; + 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 dabw.writeLeb128(@intFromEnum(abbrev_code)); - try dabw.writeLeb128(@intFromEnum(abbrev.tag)); - try dabw.writeByte(if (abbrev.children) DW.CHILDREN.yes else DW.CHILDREN.no); - for (abbrev.attrs) |*attr| inline for (attr) |info| try dabw.writeLeb128(@intFromEnum(info)); - for (0..2) |_| try dabw.writeUleb128(0); - try dwarf.debug_abbrev.section.replaceEntry(DebugAbbrev.unit, entry, dwarf, daaw.getWritten()); + 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 flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { - const gpa = dwarf.gpa; const zcu = pt.zcu; const ip = &zcu.intern_pool; { - const type_gop = try dwarf.types.getOrPut(gpa, .anyerror_type); + const type_gop = try dwarf.types.getOrPut(dwarf.gpa, .anyerror_type); if (!type_gop.found_existing) type_gop.value_ptr.* = try dwarf.addCommonEntry(.main); var wip_nav: WipNav = .{ .dwarf = dwarf, @@ -4532,15 +4469,14 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { .func_high_pc = undefined, .blocks = undefined, .cfi = undefined, - .debug_frame = undefined, - .debug_info = undefined, - .debug_line = undefined, - .debug_loclists = undefined, + .debug_frame = .empty, + .debug_info = .empty, + .debug_line = .empty, + .debug_loclists = .empty, .pending_lazy = .empty, }; - wip_nav.init(); defer wip_nav.deinit(); - const dibw = &wip_nav.debug_info.buffered_writer; + const diw = wip_nav.debug_info.writer(dwarf.gpa); const global_error_set_names = ip.global_error_set.getNamesFromMainThread(); try wip_nav.abbrevCode(if (global_error_set_names.len == 0) .generated_empty_enum_type else .generated_enum_type); try wip_nav.strp("anyerror"); @@ -4550,52 +4486,50 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { } }))); for (global_error_set_names, 1..) |name, value| { try wip_nav.abbrevCode(.unsigned_enum_field); - try dibw.writeLeb128(value); + try uleb128(diw, value); try wip_nav.strp(name.toSlice(ip)); } - if (global_error_set_names.len > 0) try dibw.writeLeb128(@intFromEnum(AbbrevCode.null)); - try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, dibw.getWritten()); + if (global_error_set_names.len > 0) try uleb128(diw, @intFromEnum(AbbrevCode.null)); + try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items); try wip_nav.updateLazy(.unneeded); } for (dwarf.mods.keys(), dwarf.mods.values()) |mod, *mod_info| { - const root_dir_path = try mod.root.toAbsolute(zcu.comp.dirs, gpa); - defer gpa.free(root_dir_path); + const root_dir_path = try mod.root.toAbsolute(zcu.comp.dirs, dwarf.gpa); + defer dwarf.gpa.free(root_dir_path); mod_info.root_dir_path = try dwarf.debug_line_str.addString(dwarf, root_dir_path); } - var header: std.ArrayListUnmanaged(u8) = .empty; - defer header.deinit(gpa); - var header_bw: Writer = undefined; + var header: std.ArrayList(u8) = .init(dwarf.gpa); + defer header.deinit(); 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); unit_ptr.clear(); - try unit_ptr.cross_section_relocs.ensureTotalCapacity(gpa, 1); - try header.resize(gpa, unit_ptr.header_len); - header_bw = .fixed(header.items); + try unit_ptr.cross_section_relocs.ensureTotalCapacity(dwarf.gpa, 1); + header.clearRetainingCapacity(); + try header.ensureTotalCapacity(unit_ptr.header_len); const unit_len = (if (unit_ptr.next.unwrap()) |next_unit| dwarf.debug_aranges.section.getUnit(next_unit).off else dwarf.debug_aranges.section.len) - unit_ptr.off - dwarf.unitLengthBytes(); switch (dwarf.format) { - .@"32" => header_bw.writeInt(u32, @intCast(unit_len), dwarf.endian) catch unreachable, + .@"32" => std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), @intCast(unit_len), dwarf.endian), .@"64" => { - header_bw.writeInt(u32, std.math.maxInt(u32), dwarf.endian) catch unreachable; - header_bw.writeInt(u64, unit_len, dwarf.endian) catch unreachable; + std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), std.math.maxInt(u32), dwarf.endian); + std.mem.writeInt(u64, header.addManyAsArrayAssumeCapacity(8), unit_len, dwarf.endian); }, } - header_bw.writeInt(u16, 2, dwarf.endian) catch unreachable; + std.mem.writeInt(u16, header.addManyAsArrayAssumeCapacity(2), 2, dwarf.endian); unit_ptr.cross_section_relocs.appendAssumeCapacity(.{ - .source_off = @intCast(header_bw.end), + .source_off = @intCast(header.items.len), .target_sec = .debug_info, .target_unit = unit, }); - header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable; - header_bw.writeAll(&.{ @intFromEnum(dwarf.address_size), 0 }) catch unreachable; - header_bw.splatByteAll(0, unit_ptr.header_len - header_bw.end) catch unreachable; - assert(header_bw.end == header_bw.buffer.len); - try unit_ptr.replaceHeader(&dwarf.debug_aranges.section, dwarf, header_bw.buffer); + header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes()); + header.appendSliceAssumeCapacity(&.{ @intFromEnum(dwarf.address_size), 0 }); + header.appendNTimesAssumeCapacity(0, unit_ptr.header_len - header.items.len); + try unit_ptr.replaceHeader(&dwarf.debug_aranges.section, dwarf, header.items); try unit_ptr.writeTrailer(&dwarf.debug_aranges.section, dwarf); } dwarf.debug_aranges.section.dirty = false; @@ -4610,33 +4544,31 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { dev.check(.x86_64_backend); const Register = @import("../arch/x86_64/bits.zig").Register; for (dwarf.debug_frame.section.units.items) |*unit| { - try header.resize(gpa, unit.header_len); - header_bw = .fixed(header.items); + header.clearRetainingCapacity(); + try header.ensureTotalCapacity(unit.header_len); const unit_len = unit.header_len - dwarf.unitLengthBytes(); switch (dwarf.format) { - .@"32" => header_bw.writeInt(u32, @intCast(unit_len), dwarf.endian) catch unreachable, + .@"32" => std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), @intCast(unit_len), dwarf.endian), .@"64" => { - header_bw.writeInt(u32, std.math.maxInt(u32), dwarf.endian) catch unreachable; - header_bw.writeInt(u64, unit_len, dwarf.endian) catch unreachable; + std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), std.math.maxInt(u32), dwarf.endian); + std.mem.writeInt(u64, header.addManyAsArrayAssumeCapacity(8), unit_len, dwarf.endian); }, } - header_bw.splatByteAll(0, 4) catch unreachable; - header_bw.writeByte(1) catch unreachable; - header_bw.writeAll("zR\x00") catch unreachable; - header_bw.writeLeb128(dwarf.debug_frame.header.code_alignment_factor) catch unreachable; - header_bw.writeLeb128(dwarf.debug_frame.header.data_alignment_factor) catch unreachable; - header_bw.writeLeb128(dwarf.debug_frame.header.return_address_register) catch unreachable; - header_bw.writeUleb128(1) catch unreachable; - header_bw.writeByte(DW.EH.PE.pcrel | DW.EH.PE.sdata4) catch unreachable; - header_bw.writeByte(DW.CFA.def_cfa_sf) catch unreachable; - header_bw.writeUleb128(1) catch unreachable; - header_bw.writeLeb128(Register.rsp.dwarfNum()) catch unreachable; - header_bw.writeSleb128(-1) catch unreachable; - header_bw.writeByte(@as(u8, DW.CFA.offset) + Register.rip.dwarfNum()) catch unreachable; - header_bw.writeUleb128(1) catch unreachable; - header_bw.splatByteAll(DW.CFA.nop, unit.header_len - header_bw.end) catch unreachable; - assert(header_bw.end == header_bw.buffer.len); - try unit.replaceHeader(&dwarf.debug_frame.section, dwarf, header_bw.buffer); + header.appendNTimesAssumeCapacity(0, 4); + header.appendAssumeCapacity(1); + header.appendSliceAssumeCapacity("zR\x00"); + uleb128(header.fixedWriter(), dwarf.debug_frame.header.code_alignment_factor) catch unreachable; + sleb128(header.fixedWriter(), dwarf.debug_frame.header.data_alignment_factor) catch unreachable; + uleb128(header.fixedWriter(), dwarf.debug_frame.header.return_address_register) catch unreachable; + uleb128(header.fixedWriter(), 1) catch unreachable; + header.appendAssumeCapacity(DW.EH.PE.pcrel | DW.EH.PE.sdata4); + header.appendAssumeCapacity(DW.CFA.def_cfa_sf); + uleb128(header.fixedWriter(), Register.rsp.dwarfNum()) catch unreachable; + sleb128(header.fixedWriter(), -1) catch unreachable; + header.appendAssumeCapacity(@as(u8, DW.CFA.offset) + Register.rip.dwarfNum()); + uleb128(header.fixedWriter(), 1) catch unreachable; + header.appendNTimesAssumeCapacity(DW.CFA.nop, unit.header_len - header.items.len); + try unit.replaceHeader(&dwarf.debug_frame.section, dwarf, header.items); try unit.writeTrailer(&dwarf.debug_frame.section, dwarf); } }, @@ -4649,84 +4581,83 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { for (dwarf.mods.keys(), dwarf.mods.values(), dwarf.debug_info.section.units.items, 0..) |mod, mod_info, *unit_ptr, unit_index| { const unit: Unit.Index = @enumFromInt(unit_index); unit_ptr.clear(); - try unit_ptr.cross_unit_relocs.ensureTotalCapacity(gpa, 1); - try unit_ptr.cross_section_relocs.ensureTotalCapacity(gpa, 7); - try header.resize(gpa, unit_ptr.header_len); - header_bw = .fixed(header.items); + try unit_ptr.cross_unit_relocs.ensureTotalCapacity(dwarf.gpa, 1); + try unit_ptr.cross_section_relocs.ensureTotalCapacity(dwarf.gpa, 7); + header.clearRetainingCapacity(); + try header.ensureTotalCapacity(unit_ptr.header_len); const unit_len = (if (unit_ptr.next.unwrap()) |next_unit| dwarf.debug_info.section.getUnit(next_unit).off else dwarf.debug_info.section.len) - unit_ptr.off - dwarf.unitLengthBytes(); switch (dwarf.format) { - .@"32" => header_bw.writeInt(u32, @intCast(unit_len), dwarf.endian) catch unreachable, + .@"32" => std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), @intCast(unit_len), dwarf.endian), .@"64" => { - header_bw.writeInt(u32, std.math.maxInt(u32), dwarf.endian) catch unreachable; - header_bw.writeInt(u64, unit_len, dwarf.endian) catch unreachable; + std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), std.math.maxInt(u32), dwarf.endian); + std.mem.writeInt(u64, header.addManyAsArrayAssumeCapacity(8), unit_len, dwarf.endian); }, } - header_bw.writeInt(u16, 5, dwarf.endian) catch unreachable; - header_bw.writeAll(&.{ DW.UT.compile, @intFromEnum(dwarf.address_size) }) catch unreachable; + std.mem.writeInt(u16, header.addManyAsArrayAssumeCapacity(2), 5, dwarf.endian); + header.appendSliceAssumeCapacity(&.{ DW.UT.compile, @intFromEnum(dwarf.address_size) }); unit_ptr.cross_section_relocs.appendAssumeCapacity(.{ - .source_off = @intCast(header_bw.end), + .source_off = @intCast(header.items.len), .target_sec = .debug_abbrev, .target_unit = DebugAbbrev.unit, }); - header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable; - const compile_unit_off: u32 = @intCast(header_bw.end); - header_bw.writeLeb128(try dwarf.refAbbrevCode(.compile_unit)) catch unreachable; - header_bw.writeByte(DW.LANG.Zig) catch unreachable; + header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes()); + const compile_unit_off: u32 = @intCast(header.items.len); + 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_bw.end), + .source_off = @intCast(header.items.len), .target_sec = .debug_line_str, .target_unit = StringSection.unit, .target_entry = (try dwarf.debug_line_str.addString(dwarf, "zig " ++ @import("build_options").version)).toOptional(), }); - header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable; + header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes()); unit_ptr.cross_section_relocs.appendAssumeCapacity(.{ - .source_off = @intCast(header_bw.end), + .source_off = @intCast(header.items.len), .target_sec = .debug_line_str, .target_unit = StringSection.unit, .target_entry = mod_info.root_dir_path.toOptional(), }); - header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable; + header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes()); unit_ptr.cross_section_relocs.appendAssumeCapacity(.{ - .source_off = @intCast(header_bw.end), + .source_off = @intCast(header.items.len), .target_sec = .debug_line_str, .target_unit = StringSection.unit, .target_entry = (try dwarf.debug_line_str.addString(dwarf, mod.root_src_path)).toOptional(), }); - header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable; + header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes()); unit_ptr.cross_unit_relocs.appendAssumeCapacity(.{ - .source_off = @intCast(header_bw.end), + .source_off = @intCast(header.items.len), .target_unit = .main, .target_off = compile_unit_off, }); - header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable; + header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes()); unit_ptr.cross_section_relocs.appendAssumeCapacity(.{ - .source_off = @intCast(header_bw.end), + .source_off = @intCast(header.items.len), .target_sec = .debug_line, .target_unit = unit, }); - header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable; + header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes()); unit_ptr.cross_section_relocs.appendAssumeCapacity(.{ - .source_off = @intCast(header_bw.end), + .source_off = @intCast(header.items.len), .target_sec = .debug_rnglists, .target_unit = unit, .target_off = DebugRngLists.baseOffset(dwarf), }); - header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable; - header_bw.writeUleb128(0) catch unreachable; - header_bw.writeLeb128(try dwarf.refAbbrevCode(.module)) catch unreachable; + header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes()); + uleb128(header.fixedWriter(), 0) catch unreachable; + uleb128(header.fixedWriter(), try dwarf.refAbbrevCode(.module)) catch unreachable; unit_ptr.cross_section_relocs.appendAssumeCapacity(.{ - .source_off = @intCast(header_bw.end), + .source_off = @intCast(header.items.len), .target_sec = .debug_str, .target_unit = StringSection.unit, .target_entry = (try dwarf.debug_str.addString(dwarf, mod.fully_qualified_name)).toOptional(), }); - header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable; - header_bw.writeUleb128(0) catch unreachable; - assert(header_bw.end == header_bw.buffer.len); - try unit_ptr.replaceHeader(&dwarf.debug_info.section, dwarf, header_bw.buffer); + header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes()); + uleb128(header.fixedWriter(), 0) catch unreachable; + try unit_ptr.replaceHeader(&dwarf.debug_info.section, dwarf, header.items); try unit_ptr.writeTrailer(&dwarf.debug_info.section, dwarf); } dwarf.debug_info.section.dirty = false; @@ -4750,37 +4681,33 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { ); for (dwarf.mods.values(), dwarf.debug_line.section.units.items) |mod_info, *unit| { unit.clear(); - try unit.cross_section_relocs.ensureTotalCapacity(gpa, mod_info.dirs.count() + 2 * (mod_info.files.count())); - try header.resize(gpa, unit.header_len); - header_bw = .fixed(header.items); + try unit.cross_section_relocs.ensureTotalCapacity(dwarf.gpa, mod_info.dirs.count() + 2 * (mod_info.files.count())); + header.clearRetainingCapacity(); + try header.ensureTotalCapacity(unit.header_len); const unit_len = (if (unit.next.unwrap()) |next_unit| dwarf.debug_line.section.getUnit(next_unit).off else dwarf.debug_line.section.len) - unit.off - dwarf.unitLengthBytes(); switch (dwarf.format) { - .@"32" => header_bw.writeInt(u32, @intCast(unit_len), dwarf.endian) catch unreachable, + .@"32" => std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), @intCast(unit_len), dwarf.endian), .@"64" => { - header_bw.writeInt(u32, std.math.maxInt(u32), dwarf.endian) catch unreachable; - header_bw.writeInt(u64, unit_len, dwarf.endian) catch unreachable; + std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), std.math.maxInt(u32), dwarf.endian); + std.mem.writeInt(u64, header.addManyAsArrayAssumeCapacity(8), unit_len, dwarf.endian); }, } - header_bw.writeInt(u16, 5, dwarf.endian) catch unreachable; - header_bw.writeAll(&.{ @intFromEnum(dwarf.address_size), 0 }) catch unreachable; - dwarf.writeIntTo( - &header_bw, - dwarf.sectionOffsetBytes(), - unit.header_len - header_bw.end, - ) catch unreachable; + std.mem.writeInt(u16, header.addManyAsArrayAssumeCapacity(2), 5, dwarf.endian); + header.appendSliceAssumeCapacity(&.{ @intFromEnum(dwarf.address_size), 0 }); + dwarf.writeInt(header.addManyAsSliceAssumeCapacity(dwarf.sectionOffsetBytes()), unit.header_len - header.items.len); const StandardOpcode = DeclValEnum(DW.LNS); - header_bw.writeAll(&.{ + header.appendSliceAssumeCapacity(&[_]u8{ dwarf.debug_line.header.minimum_instruction_length, dwarf.debug_line.header.maximum_operations_per_instruction, @intFromBool(dwarf.debug_line.header.default_is_stmt), @bitCast(dwarf.debug_line.header.line_base), dwarf.debug_line.header.line_range, dwarf.debug_line.header.opcode_base, - }) catch unreachable; - header_bw.writeAll(std.enums.EnumArray(StandardOpcode, u8).init(.{ + }); + header.appendSliceAssumeCapacity(std.enums.EnumArray(StandardOpcode, u8).init(.{ .extended_op = undefined, .copy = 0, .advance_pc = 1, @@ -4794,45 +4721,44 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { .set_prologue_end = 0, .set_epilogue_begin = 0, .set_isa = 1, - }).values[1..dwarf.debug_line.header.opcode_base]) catch unreachable; - header_bw.writeByte(1) catch unreachable; - header_bw.writeLeb128(@as(u14, DW.LNCT.path)) catch unreachable; - header_bw.writeLeb128(@as(u13, DW.FORM.line_strp)) catch unreachable; - header_bw.writeLeb128(mod_info.dirs.count()) catch unreachable; + }).values[1..dwarf.debug_line.header.opcode_base]); + header.appendAssumeCapacity(1); + uleb128(header.fixedWriter(), DW.LNCT.path) catch unreachable; + uleb128(header.fixedWriter(), DW.FORM.line_strp) catch unreachable; + uleb128(header.fixedWriter(), mod_info.dirs.count()) catch unreachable; for (mod_info.dirs.keys()) |dir_unit| { unit.cross_section_relocs.appendAssumeCapacity(.{ - .source_off = @intCast(header_bw.end), + .source_off = @intCast(header.items.len), .target_sec = .debug_line_str, .target_unit = StringSection.unit, .target_entry = dwarf.getModInfo(dir_unit).root_dir_path.toOptional(), }); - header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable; + header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes()); } const dir_index_info = DebugLine.dirIndexInfo(@intCast(mod_info.dirs.count())); - header_bw.writeByte(3) catch unreachable; - header_bw.writeLeb128(@as(u14, DW.LNCT.path)) catch unreachable; - header_bw.writeLeb128(@as(u13, DW.FORM.line_strp)) catch unreachable; - header_bw.writeLeb128(@as(u14, DW.LNCT.directory_index)) catch unreachable; - header_bw.writeLeb128(@intFromEnum(dir_index_info.form)) catch unreachable; - header_bw.writeLeb128(@as(u14, DW.LNCT.LLVM_source)) catch unreachable; - header_bw.writeLeb128(@as(u13, DW.FORM.line_strp)) catch unreachable; - header_bw.writeLeb128(mod_info.files.count()) catch unreachable; + header.appendAssumeCapacity(3); + uleb128(header.fixedWriter(), DW.LNCT.path) catch unreachable; + uleb128(header.fixedWriter(), DW.FORM.line_strp) catch unreachable; + uleb128(header.fixedWriter(), DW.LNCT.directory_index) catch unreachable; + uleb128(header.fixedWriter(), @intFromEnum(dir_index_info.form)) catch unreachable; + uleb128(header.fixedWriter(), DW.LNCT.LLVM_source) catch unreachable; + uleb128(header.fixedWriter(), DW.FORM.line_strp) catch unreachable; + uleb128(header.fixedWriter(), mod_info.files.count()) catch unreachable; for (mod_info.files.keys()) |file_index| { const file = zcu.fileByIndex(file_index); unit.cross_section_relocs.appendAssumeCapacity(.{ - .source_off = @intCast(header_bw.end), + .source_off = @intCast(header.items.len), .target_sec = .debug_line_str, .target_unit = StringSection.unit, .target_entry = (try dwarf.debug_line_str.addString(dwarf, file.sub_file_path)).toOptional(), }); header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes()); - dwarf.writeIntTo( - &header_bw, - dir_index_info.bytes, + dwarf.writeInt( + header.addManyAsSliceAssumeCapacity(dir_index_info.bytes), mod_info.dirs.getIndex(dwarf.getUnitIfExists(file.mod.?).?) orelse 0, ); unit.cross_section_relocs.appendAssumeCapacity(.{ - .source_off = @intCast(header_bw.end), + .source_off = @intCast(header.items.len), .target_sec = .debug_line_str, .target_unit = StringSection.unit, .target_entry = (try dwarf.debug_line_str.addString( @@ -4840,10 +4766,9 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { if (file.is_builtin) file.source.? else "", )).toOptional(), }); - header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable; + header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes()); } - assert(header_bw.end == header_bw.buffer.len); - try unit.replaceHeader(&dwarf.debug_line.section, dwarf, header_bw.buffer); + try unit.replaceHeader(&dwarf.debug_line.section, dwarf, header.items); try unit.writeTrailer(&dwarf.debug_line.section, dwarf); } dwarf.debug_line.section.dirty = false; @@ -4859,25 +4784,24 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { } if (dwarf.debug_rnglists.section.dirty) { for (dwarf.debug_rnglists.section.units.items) |*unit| { - try header.resize(gpa, unit.header_len); - header_bw = .fixed(header.items); + header.clearRetainingCapacity(); + try header.ensureTotalCapacity(unit.header_len); const unit_len = (if (unit.next.unwrap()) |next_unit| dwarf.debug_rnglists.section.getUnit(next_unit).off else dwarf.debug_rnglists.section.len) - unit.off - dwarf.unitLengthBytes(); switch (dwarf.format) { - .@"32" => header_bw.writeInt(u32, @intCast(unit_len), dwarf.endian) catch unreachable, + .@"32" => std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), @intCast(unit_len), dwarf.endian), .@"64" => { - header_bw.writeInt(u32, std.math.maxInt(u32), dwarf.endian) catch unreachable; - header_bw.writeInt(u64, unit_len, dwarf.endian) catch unreachable; + std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), std.math.maxInt(u32), dwarf.endian); + std.mem.writeInt(u64, header.addManyAsArrayAssumeCapacity(8), unit_len, dwarf.endian); }, } - header_bw.writeInt(u16, 5, dwarf.endian) catch unreachable; - header_bw.writeAll(&.{ @intFromEnum(dwarf.address_size), 0 }) catch unreachable; - header_bw.writeInt(u32, 1, dwarf.endian) catch unreachable; - dwarf.writeIntTo(&header_bw, dwarf.sectionOffsetBytes(), dwarf.sectionOffsetBytes() * 1) catch unreachable; - assert(header_bw.end == header_bw.buffer.len); - try unit.replaceHeader(&dwarf.debug_rnglists.section, dwarf, header_bw.buffer); + std.mem.writeInt(u16, header.addManyAsArrayAssumeCapacity(2), 5, dwarf.endian); + header.appendSliceAssumeCapacity(&.{ @intFromEnum(dwarf.address_size), 0 }); + std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), 1, 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; @@ -6076,10 +6000,6 @@ fn writeInt(dwarf: *Dwarf, buf: []u8, int: u64) void { } } -fn writeIntTo(dwarf: *Dwarf, bw: *Writer, len: usize, int: u64) !void { - dwarf.writeInt(try bw.writableSlice(len), int); -} - fn resolveReloc(dwarf: *Dwarf, source: u64, target: u64, size: u32) RelocError!void { var buf: [8]u8 = undefined; dwarf.writeInt(buf[0..size], target); @@ -6106,6 +6026,7 @@ fn uleb128Bytes(value: anytype) u32 { d.writer.writeUleb128(value) catch unreachable; return @intCast(d.count + d.writer.end); } + fn sleb128Bytes(value: anytype) u32 { var trash_buffer: [64]u8 = undefined; var d: std.Io.Writer.Discarding = .init(&trash_buffer); @@ -6132,7 +6053,7 @@ const codegen = @import("../codegen.zig"); const dev = @import("../dev.zig"); const link = @import("../link.zig"); const log = std.log.scoped(.dwarf); +const sleb128 = std.leb.writeIleb128; const std = @import("std"); const target_info = @import("../target.zig"); -const Allocator = std.mem.Allocator; -const Writer = std.io.Writer; +const uleb128 = std.leb.writeUleb128; From 9a538e0d54186451772c6b07b348418089797f83 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 7 Aug 2025 22:21:37 -0700 Subject: [PATCH 4/4] link.Dwarf: minimal changes to remove CountingWriter --- lib/std/Io/Writer.zig | 5 ++++ src/link/Dwarf.zig | 60 +++++++++++++++++++++++-------------------- 2 files changed, 37 insertions(+), 28 deletions(-) diff --git a/lib/std/Io/Writer.zig b/lib/std/Io/Writer.zig index 797a69914c..dd3994c413 100644 --- a/lib/std/Io/Writer.zig +++ b/lib/std/Io/Writer.zig @@ -2239,6 +2239,11 @@ pub const Discarding = struct { }; } + /// Includes buffered data (no need to flush). + pub fn fullCount(d: *const Discarding) u64 { + return d.count + d.writer.end; + } + pub fn drain(w: *Writer, data: []const []const u8, splat: usize) Error!usize { const d: *Discarding = @alignCast(@fieldParentPtr("writer", w)); const slice = data[0 .. data.len - 1]; diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index f11ebc94d4..5c805e6a7e 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -1,4 +1,4 @@ -gpa: std.mem.Allocator, +gpa: Allocator, bin_file: *link.File, format: DW.Format, endian: std.builtin.Endian, @@ -21,6 +21,7 @@ debug_rnglists: DebugRngLists, debug_str: StringSection, pub const UpdateError = error{ + WriteFailed, ReinterpretDeclRef, Unimplemented, EndOfStream, @@ -50,7 +51,7 @@ const ModInfo = struct { dirs: std.AutoArrayHashMapUnmanaged(Unit.Index, void), files: std.AutoArrayHashMapUnmanaged(Zcu.File.Index, void), - fn deinit(mod_info: *ModInfo, gpa: std.mem.Allocator) void { + fn deinit(mod_info: *ModInfo, gpa: Allocator) void { mod_info.dirs.deinit(gpa); mod_info.files.deinit(gpa); mod_info.* = undefined; @@ -220,7 +221,7 @@ const StringSection = struct { .section = Section.init, }; - fn deinit(str_sec: *StringSection, gpa: std.mem.Allocator) void { + fn deinit(str_sec: *StringSection, gpa: Allocator) void { str_sec.contents.deinit(gpa); str_sec.map.deinit(gpa); str_sec.section.deinit(gpa); @@ -297,7 +298,7 @@ pub const Section = struct { .len = 0, }; - fn deinit(sec: *Section, gpa: std.mem.Allocator) void { + fn deinit(sec: *Section, gpa: Allocator) void { for (sec.units.items) |*unit| unit.deinit(gpa); sec.units.deinit(gpa); sec.* = undefined; @@ -357,7 +358,7 @@ pub const Section = struct { if (sec.last == unit.toOptional()) sec.last = unit_ptr.prev; } - fn popUnit(sec: *Section, gpa: std.mem.Allocator) void { + fn popUnit(sec: *Section, gpa: Allocator) void { const unit_index: Unit.Index = @enumFromInt(sec.units.items.len - 1); sec.unlinkUnit(unit_index); var unit = sec.units.pop().?; @@ -518,7 +519,7 @@ const Unit = struct { unit.cross_section_relocs.clearRetainingCapacity(); } - fn deinit(unit: *Unit, gpa: std.mem.Allocator) void { + fn deinit(unit: *Unit, gpa: Allocator) void { for (unit.entries.items) |*entry| entry.deinit(gpa); unit.entries.deinit(gpa); unit.cross_unit_relocs.deinit(gpa); @@ -526,7 +527,7 @@ const Unit = struct { unit.* = undefined; } - fn addEntry(unit: *Unit, gpa: std.mem.Allocator) std.mem.Allocator.Error!Entry.Index { + fn addEntry(unit: *Unit, gpa: Allocator) Allocator.Error!Entry.Index { if (unit.free.unwrap()) |entry| { const entry_ptr = unit.getEntry(entry); unit.free = entry_ptr.next; @@ -780,7 +781,7 @@ const Entry = struct { entry.external_relocs.clearRetainingCapacity(); } - fn deinit(entry: *Entry, gpa: std.mem.Allocator) void { + fn deinit(entry: *Entry, gpa: Allocator) void { entry.cross_entry_relocs.deinit(gpa); entry.cross_unit_relocs.deinit(gpa); entry.cross_section_relocs.deinit(gpa); @@ -1133,7 +1134,7 @@ pub const Loc = union(enum) { }; } - fn writeReg(reg: u32, op0: u8, opx: u8, writer: anytype) @TypeOf(writer).Error!void { + fn writeReg(reg: u32, op0: u8, opx: u8, writer: anytype) !void { if (std.math.cast(u5, reg)) |small_reg| { try writer.writeByte(op0 + small_reg); } else { @@ -1142,7 +1143,7 @@ pub const Loc = union(enum) { } } - fn write(loc: Loc, adapter: anytype) UpdateError!void { + fn write(loc: Loc, adapter: anytype) !void { const writer = adapter.writer(); switch (loc) { .empty => {}, @@ -1712,15 +1713,15 @@ pub const WipNav = struct { wip_nav.func = func; } - fn externalReloc(wip_nav: *WipNav, sec: *Section, reloc: ExternalReloc) std.mem.Allocator.Error!void { + fn externalReloc(wip_nav: *WipNav, sec: *Section, reloc: ExternalReloc) Allocator.Error!void { try sec.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs.append(wip_nav.dwarf.gpa, reloc); } - pub fn infoExternalReloc(wip_nav: *WipNav, reloc: ExternalReloc) std.mem.Allocator.Error!void { + pub fn infoExternalReloc(wip_nav: *WipNav, reloc: ExternalReloc) Allocator.Error!void { try wip_nav.externalReloc(&wip_nav.dwarf.debug_info.section, reloc); } - fn frameExternalReloc(wip_nav: *WipNav, reloc: ExternalReloc) std.mem.Allocator.Error!void { + fn frameExternalReloc(wip_nav: *WipNav, reloc: ExternalReloc) Allocator.Error!void { try wip_nav.externalReloc(&wip_nav.dwarf.debug_frame.section, reloc); } @@ -1768,33 +1769,33 @@ pub const WipNav = struct { } const ExprLocCounter = struct { - const Stream = std.io.CountingWriter(std.io.NullWriter); - stream: Stream, + stream: Writer.Discarding, section_offset_bytes: u32, address_size: AddressSize, - fn init(dwarf: *Dwarf) ExprLocCounter { + fn init(dwarf: *Dwarf, trash_buffer: []u8) ExprLocCounter { return .{ - .stream = std.io.countingWriter(std.io.null_writer), + .stream = .init(trash_buffer), .section_offset_bytes = dwarf.sectionOffsetBytes(), .address_size = dwarf.address_size, }; } - fn writer(counter: *ExprLocCounter) Stream.Writer { - return counter.stream.writer(); + fn writer(counter: *ExprLocCounter) *Writer { + return &counter.stream.writer; } fn endian(_: ExprLocCounter) std.builtin.Endian { return @import("builtin").cpu.arch.endian(); } fn addrSym(counter: *ExprLocCounter, _: u32) error{}!void { - counter.stream.bytes_written += @intFromEnum(counter.address_size); + counter.stream.count += @intFromEnum(counter.address_size); } fn infoEntry(counter: *ExprLocCounter, _: Unit.Index, _: Entry.Index) error{}!void { - counter.stream.bytes_written += counter.section_offset_bytes; + counter.stream.count += counter.section_offset_bytes; } }; fn infoExprLoc(wip_nav: *WipNav, loc: Loc) UpdateError!void { - var counter: ExprLocCounter = .init(wip_nav.dwarf); + var trash_buffer: [64]u8 = undefined; + var counter: ExprLocCounter = .init(wip_nav.dwarf, &trash_buffer); try loc.write(&counter); const adapter: struct { @@ -1812,7 +1813,7 @@ pub const WipNav = struct { try ctx.wip_nav.infoSectionOffset(.debug_info, unit, entry, 0); } } = .{ .wip_nav = wip_nav }; - try uleb128(adapter.writer(), counter.stream.bytes_written); + try uleb128(adapter.writer(), counter.stream.fullCount()); try loc.write(adapter); } @@ -1826,7 +1827,8 @@ pub const WipNav = struct { } fn frameExprLoc(wip_nav: *WipNav, loc: Loc) UpdateError!void { - var counter: ExprLocCounter = .init(wip_nav.dwarf); + var trash_buffer: [64]u8 = undefined; + var counter: ExprLocCounter = .init(wip_nav.dwarf, &trash_buffer); try loc.write(&counter); const adapter: struct { @@ -1844,7 +1846,7 @@ pub const WipNav = struct { try ctx.wip_nav.sectionOffset(.debug_frame, .debug_info, unit, entry, 0); } } = .{ .wip_nav = wip_nav }; - try uleb128(adapter.writer(), counter.stream.bytes_written); + try uleb128(adapter.writer(), counter.stream.fullCount()); try loc.write(adapter); } @@ -1922,7 +1924,7 @@ pub const WipNav = struct { try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0); } - fn refForward(wip_nav: *WipNav) std.mem.Allocator.Error!u32 { + fn refForward(wip_nav: *WipNav) Allocator.Error!u32 { const dwarf = wip_nav.dwarf; const cross_entry_relocs = &dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_entry_relocs; const reloc_index: u32 = @intCast(cross_entry_relocs.items.len); @@ -6022,14 +6024,14 @@ fn sectionOffsetBytes(dwarf: *Dwarf) u32 { fn uleb128Bytes(value: anytype) u32 { var trash_buffer: [64]u8 = undefined; - var d: std.Io.Writer.Discarding = .init(&trash_buffer); + var d: Writer.Discarding = .init(&trash_buffer); d.writer.writeUleb128(value) catch unreachable; return @intCast(d.count + d.writer.end); } fn sleb128Bytes(value: anytype) u32 { var trash_buffer: [64]u8 = undefined; - var d: std.Io.Writer.Discarding = .init(&trash_buffer); + var d: Writer.Discarding = .init(&trash_buffer); d.writer.writeSleb128(value) catch unreachable; return @intCast(d.count + d.writer.end); } @@ -6057,3 +6059,5 @@ const sleb128 = std.leb.writeIleb128; const std = @import("std"); const target_info = @import("../target.zig"); const uleb128 = std.leb.writeUleb128; +const Allocator = std.mem.Allocator; +const Writer = std.Io.Writer;