authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-08-08 12:30:09-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-08-08 12:30:09-07:00
logd2f77920398976670aa25cb5fd278435d08eba25
tree09cb8d384682c15febbd66d1ee3e65850c50882e
parent3ea015db968644c3f4e88fff59b9741b4903d478
parent9a538e0d54186451772c6b07b348418089797f83
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #24742 from ziglang/CountingWriter

std.Io: delete CountingWriter

11 files changed, 76 insertions(+), 119 deletions(-)

lib/compiler/resinator/cvtres.zig+2-9
...@@ -665,19 +665,16 @@ const ResourceTree = struct {...@@ -665,19 +665,16 @@ const ResourceTree = struct {
665 pub fn writeCoff(665 pub fn writeCoff(
666 self: *const ResourceTree,666 self: *const ResourceTree,
667 allocator: Allocator,667 allocator: Allocator,
668 writer: anytype,668 w: anytype,
669 resources_in_data_order: []const Resource,669 resources_in_data_order: []const Resource,
670 lengths: Lengths,670 lengths: Lengths,
671 coff_string_table: *StringTable,671 coff_string_table: *StringTable,
672 ) ![]const std.coff.Symbol {672 ) ![]const std.coff.Symbol {
673 if (self.type_to_name_map.count() == 0) {673 if (self.type_to_name_map.count() == 0) {
674 try writer.writeByteNTimes(0, 16);674 try w.writeByteNTimes(0, 16);
675 return &.{};675 return &.{};
676 }676 }
677677
678 var counting_writer = std.io.countingWriter(writer);
679 const w = counting_writer.writer();
680
681 var level2_list: std.ArrayListUnmanaged(*const NameToLanguageMap) = .empty;678 var level2_list: std.ArrayListUnmanaged(*const NameToLanguageMap) = .empty;
682 defer level2_list.deinit(allocator);679 defer level2_list.deinit(allocator);
683680
...@@ -735,7 +732,6 @@ const ResourceTree = struct {...@@ -735,7 +732,6 @@ const ResourceTree = struct {
735 try level2_list.append(allocator, name_to_lang_map);732 try level2_list.append(allocator, name_to_lang_map);
736 }733 }
737 }734 }
738 std.debug.assert(counting_writer.bytes_written == level2_start);
739735
740 const level3_start = level2_start + lengths.level2;736 const level3_start = level2_start + lengths.level2;
741 var level3_address = level3_start;737 var level3_address = level3_start;
...@@ -771,7 +767,6 @@ const ResourceTree = struct {...@@ -771,7 +767,6 @@ const ResourceTree = struct {
771 try level3_list.append(allocator, lang_to_resources_map);767 try level3_list.append(allocator, lang_to_resources_map);
772 }768 }
773 }769 }
774 std.debug.assert(counting_writer.bytes_written == level3_start);
775770
776 var reloc_addresses = try allocator.alloc(u32, resources_in_data_order.len);771 var reloc_addresses = try allocator.alloc(u32, resources_in_data_order.len);
777 defer allocator.free(reloc_addresses);772 defer allocator.free(reloc_addresses);
...@@ -813,7 +808,6 @@ const ResourceTree = struct {...@@ -813,7 +808,6 @@ const ResourceTree = struct {
813 try resources_list.append(allocator, reloc_resource);808 try resources_list.append(allocator, reloc_resource);
814 }809 }
815 }810 }
816 std.debug.assert(counting_writer.bytes_written == data_entries_start);
817811
818 for (resources_list.items, 0..) |reloc_resource, i| {812 for (resources_list.items, 0..) |reloc_resource, i| {
819 // TODO: This logic works but is convoluted, would be good to clean this up813 // TODO: This logic works but is convoluted, would be good to clean this up
...@@ -827,7 +821,6 @@ const ResourceTree = struct {...@@ -827,7 +821,6 @@ const ResourceTree = struct {
827 };821 };
828 try w.writeStructEndian(data_entry, .little);822 try w.writeStructEndian(data_entry, .little);
829 }823 }
830 std.debug.assert(counting_writer.bytes_written == strings_start);
831824
832 for (self.rsrc_string_table.keys()) |v| {825 for (self.rsrc_string_table.keys()) |v| {
833 const str = v.name;826 const str = v.name;
lib/std/Io.zig-5
...@@ -432,10 +432,6 @@ pub const FixedBufferStream = @import("Io/fixed_buffer_stream.zig").FixedBufferS...@@ -432,10 +432,6 @@ pub const FixedBufferStream = @import("Io/fixed_buffer_stream.zig").FixedBufferS
432/// Deprecated in favor of `Reader`.432/// Deprecated in favor of `Reader`.
433pub const fixedBufferStream = @import("Io/fixed_buffer_stream.zig").fixedBufferStream;433pub const fixedBufferStream = @import("Io/fixed_buffer_stream.zig").fixedBufferStream;
434/// Deprecated with no replacement; inefficient pattern434/// Deprecated with no replacement; inefficient pattern
435pub const CountingWriter = @import("Io/counting_writer.zig").CountingWriter;
436/// Deprecated with no replacement; inefficient pattern
437pub const countingWriter = @import("Io/counting_writer.zig").countingWriter;
438/// Deprecated with no replacement; inefficient pattern
439pub const CountingReader = @import("Io/counting_reader.zig").CountingReader;435pub const CountingReader = @import("Io/counting_reader.zig").CountingReader;
440/// Deprecated with no replacement; inefficient pattern436/// Deprecated with no replacement; inefficient pattern
441pub const countingReader = @import("Io/counting_reader.zig").countingReader;437pub const countingReader = @import("Io/counting_reader.zig").countingReader;
...@@ -917,7 +913,6 @@ test {...@@ -917,7 +913,6 @@ test {
917 _ = Reader;913 _ = Reader;
918 _ = Writer;914 _ = Writer;
919 _ = BufferedWriter;915 _ = BufferedWriter;
920 _ = CountingWriter;
921 _ = CountingReader;916 _ = CountingReader;
922 _ = FixedBufferStream;917 _ = FixedBufferStream;
923 _ = tty;918 _ = tty;
lib/std/Io/Writer.zig+5
...@@ -2239,6 +2239,11 @@ pub const Discarding = struct {...@@ -2239,6 +2239,11 @@ pub const Discarding = struct {
2239 };2239 };
2240 }2240 }
22412241
2242 /// Includes buffered data (no need to flush).
2243 pub fn fullCount(d: *const Discarding) u64 {
2244 return d.count + d.writer.end;
2245 }
2246
2242 pub fn drain(w: *Writer, data: []const []const u8, splat: usize) Error!usize {2247 pub fn drain(w: *Writer, data: []const []const u8, splat: usize) Error!usize {
2243 const d: *Discarding = @alignCast(@fieldParentPtr("writer", w));2248 const d: *Discarding = @alignCast(@fieldParentPtr("writer", w));
2244 const slice = data[0 .. data.len - 1];2249 const slice = data[0 .. data.len - 1];
lib/std/Io/counting_writer.zig deleted-39
...@@ -1,39 +0,0 @@
1const std = @import("../std.zig");
2const io = std.io;
3const testing = std.testing;
4
5/// A Writer that counts how many bytes has been written to it.
6pub fn CountingWriter(comptime WriterType: type) type {
7 return struct {
8 bytes_written: u64,
9 child_stream: WriterType,
10
11 pub const Error = WriterType.Error;
12 pub const Writer = io.GenericWriter(*Self, Error, write);
13
14 const Self = @This();
15
16 pub fn write(self: *Self, bytes: []const u8) Error!usize {
17 const amt = try self.child_stream.write(bytes);
18 self.bytes_written += amt;
19 return amt;
20 }
21
22 pub fn writer(self: *Self) Writer {
23 return .{ .context = self };
24 }
25 };
26}
27
28pub fn countingWriter(child_stream: anytype) CountingWriter(@TypeOf(child_stream)) {
29 return .{ .bytes_written = 0, .child_stream = child_stream };
30}
31
32test CountingWriter {
33 var counting_stream = countingWriter(std.io.null_writer);
34 const stream = counting_stream.writer();
35
36 const bytes = "yay" ** 100;
37 stream.writeAll(bytes) catch unreachable;
38 try testing.expect(counting_stream.bytes_written == bytes.len);
39}
lib/std/crypto/phc_encoding.zig+9-7
...@@ -5,6 +5,7 @@ const fmt = std.fmt;...@@ -5,6 +5,7 @@ const fmt = std.fmt;
5const io = std.io;5const io = std.io;
6const mem = std.mem;6const mem = std.mem;
7const meta = std.meta;7const meta = std.meta;
8const Writer = std.Io.Writer;
89
9const fields_delimiter = "$";10const fields_delimiter = "$";
10const fields_delimiter_scalar = '$';11const fields_delimiter_scalar = '$';
...@@ -188,19 +189,20 @@ pub fn deserialize(comptime HashResult: type, str: []const u8) Error!HashResult...@@ -188,19 +189,20 @@ pub fn deserialize(comptime HashResult: type, str: []const u8) Error!HashResult
188///189///
189/// `params` can also include any additional parameters.190/// `params` can also include any additional parameters.
190pub fn serialize(params: anytype, str: []u8) Error![]const u8 {191pub fn serialize(params: anytype, str: []u8) Error![]const u8 {
191 var buf = io.fixedBufferStream(str);192 var w: Writer = .fixed(str);
192 try serializeTo(params, buf.writer());193 serializeTo(params, &w) catch return error.NoSpaceLeft;
193 return buf.getWritten();194 return w.buffered();
194}195}
195196
196/// Compute the number of bytes required to serialize `params`197/// Compute the number of bytes required to serialize `params`
197pub fn calcSize(params: anytype) usize {198pub fn calcSize(params: anytype) usize {
198 var buf = io.countingWriter(io.null_writer);199 var trash: [128]u8 = undefined;
199 serializeTo(params, buf.writer()) catch unreachable;200 var d: Writer.Discarding = .init(&trash);
200 return @as(usize, @intCast(buf.bytes_written));201 serializeTo(params, &d.writer) catch unreachable;
202 return @intCast(d.fullCount());
201}203}
202204
203fn serializeTo(params: anytype, out: anytype) !void {205fn serializeTo(params: anytype, out: *std.Io.Writer) !void {
204 const HashResult = @TypeOf(params);206 const HashResult = @TypeOf(params);
205207
206 if (@hasField(HashResult, version_param_name)) {208 if (@hasField(HashResult, version_param_name)) {
lib/std/crypto/scrypt.zig+4-3
...@@ -311,9 +311,10 @@ const crypt_format = struct {...@@ -311,9 +311,10 @@ const crypt_format = struct {
311311
312 /// Compute the number of bytes required to serialize `params`312 /// Compute the number of bytes required to serialize `params`
313 pub fn calcSize(params: anytype) usize {313 pub fn calcSize(params: anytype) usize {
314 var buf = io.countingWriter(io.null_writer);314 var trash: [128]u8 = undefined;
315 serializeTo(params, buf.writer()) catch unreachable;315 var d: std.Io.Writer.Discarding = .init(&trash);
316 return @as(usize, @intCast(buf.bytes_written));316 serializeTo(params, &d) catch unreachable;
317 return @intCast(d.fullCount());
317 }318 }
318319
319 fn serializeTo(params: anytype, out: anytype) !void {320 fn serializeTo(params: anytype, out: anytype) !void {
src/arch/x86_64/encoder.zig+3-4
...@@ -1204,11 +1204,10 @@ const TestEncode = struct {...@@ -1204,11 +1204,10 @@ const TestEncode = struct {
1204 mnemonic: Instruction.Mnemonic,1204 mnemonic: Instruction.Mnemonic,
1205 ops: []const Instruction.Operand,1205 ops: []const Instruction.Operand,
1206 ) !void {1206 ) !void {
1207 var stream = std.io.fixedBufferStream(&enc.buffer);1207 var writer: std.Io.Writer = .fixed(&enc.buffer);
1208 var count_writer = std.io.countingWriter(stream.writer());
1209 const inst: Instruction = try .new(.none, mnemonic, ops);1208 const inst: Instruction = try .new(.none, mnemonic, ops);
1210 try inst.encode(count_writer.writer(), .{});1209 try inst.encode(&writer, .{});
1211 enc.index = count_writer.bytes_written;1210 enc.index = writer.bufferedLen();
1212 }1211 }
12131212
1214 fn code(enc: TestEncode) []const u8 {1213 fn code(enc: TestEncode) []const u8 {
src/link/Dwarf.zig+32-28
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1gpa: std.mem.Allocator,1gpa: Allocator,
2bin_file: *link.File,2bin_file: *link.File,
3format: DW.Format,3format: DW.Format,
4endian: std.builtin.Endian,4endian: std.builtin.Endian,
...@@ -21,6 +21,7 @@ debug_rnglists: DebugRngLists,...@@ -21,6 +21,7 @@ debug_rnglists: DebugRngLists,
21debug_str: StringSection,21debug_str: StringSection,
2222
23pub const UpdateError = error{23pub const UpdateError = error{
24 WriteFailed,
24 ReinterpretDeclRef,25 ReinterpretDeclRef,
25 Unimplemented,26 Unimplemented,
26 EndOfStream,27 EndOfStream,
...@@ -50,7 +51,7 @@ const ModInfo = struct {...@@ -50,7 +51,7 @@ const ModInfo = struct {
50 dirs: std.AutoArrayHashMapUnmanaged(Unit.Index, void),51 dirs: std.AutoArrayHashMapUnmanaged(Unit.Index, void),
51 files: std.AutoArrayHashMapUnmanaged(Zcu.File.Index, void),52 files: std.AutoArrayHashMapUnmanaged(Zcu.File.Index, void),
5253
53 fn deinit(mod_info: *ModInfo, gpa: std.mem.Allocator) void {54 fn deinit(mod_info: *ModInfo, gpa: Allocator) void {
54 mod_info.dirs.deinit(gpa);55 mod_info.dirs.deinit(gpa);
55 mod_info.files.deinit(gpa);56 mod_info.files.deinit(gpa);
56 mod_info.* = undefined;57 mod_info.* = undefined;
...@@ -220,7 +221,7 @@ const StringSection = struct {...@@ -220,7 +221,7 @@ const StringSection = struct {
220 .section = Section.init,221 .section = Section.init,
221 };222 };
222223
223 fn deinit(str_sec: *StringSection, gpa: std.mem.Allocator) void {224 fn deinit(str_sec: *StringSection, gpa: Allocator) void {
224 str_sec.contents.deinit(gpa);225 str_sec.contents.deinit(gpa);
225 str_sec.map.deinit(gpa);226 str_sec.map.deinit(gpa);
226 str_sec.section.deinit(gpa);227 str_sec.section.deinit(gpa);
...@@ -297,7 +298,7 @@ pub const Section = struct {...@@ -297,7 +298,7 @@ pub const Section = struct {
297 .len = 0,298 .len = 0,
298 };299 };
299300
300 fn deinit(sec: *Section, gpa: std.mem.Allocator) void {301 fn deinit(sec: *Section, gpa: Allocator) void {
301 for (sec.units.items) |*unit| unit.deinit(gpa);302 for (sec.units.items) |*unit| unit.deinit(gpa);
302 sec.units.deinit(gpa);303 sec.units.deinit(gpa);
303 sec.* = undefined;304 sec.* = undefined;
...@@ -357,7 +358,7 @@ pub const Section = struct {...@@ -357,7 +358,7 @@ pub const Section = struct {
357 if (sec.last == unit.toOptional()) sec.last = unit_ptr.prev;358 if (sec.last == unit.toOptional()) sec.last = unit_ptr.prev;
358 }359 }
359360
360 fn popUnit(sec: *Section, gpa: std.mem.Allocator) void {361 fn popUnit(sec: *Section, gpa: Allocator) void {
361 const unit_index: Unit.Index = @enumFromInt(sec.units.items.len - 1);362 const unit_index: Unit.Index = @enumFromInt(sec.units.items.len - 1);
362 sec.unlinkUnit(unit_index);363 sec.unlinkUnit(unit_index);
363 var unit = sec.units.pop().?;364 var unit = sec.units.pop().?;
...@@ -518,7 +519,7 @@ const Unit = struct {...@@ -518,7 +519,7 @@ const Unit = struct {
518 unit.cross_section_relocs.clearRetainingCapacity();519 unit.cross_section_relocs.clearRetainingCapacity();
519 }520 }
520521
521 fn deinit(unit: *Unit, gpa: std.mem.Allocator) void {522 fn deinit(unit: *Unit, gpa: Allocator) void {
522 for (unit.entries.items) |*entry| entry.deinit(gpa);523 for (unit.entries.items) |*entry| entry.deinit(gpa);
523 unit.entries.deinit(gpa);524 unit.entries.deinit(gpa);
524 unit.cross_unit_relocs.deinit(gpa);525 unit.cross_unit_relocs.deinit(gpa);
...@@ -526,7 +527,7 @@ const Unit = struct {...@@ -526,7 +527,7 @@ const Unit = struct {
526 unit.* = undefined;527 unit.* = undefined;
527 }528 }
528529
529 fn addEntry(unit: *Unit, gpa: std.mem.Allocator) std.mem.Allocator.Error!Entry.Index {530 fn addEntry(unit: *Unit, gpa: Allocator) Allocator.Error!Entry.Index {
530 if (unit.free.unwrap()) |entry| {531 if (unit.free.unwrap()) |entry| {
531 const entry_ptr = unit.getEntry(entry);532 const entry_ptr = unit.getEntry(entry);
532 unit.free = entry_ptr.next;533 unit.free = entry_ptr.next;
...@@ -780,7 +781,7 @@ const Entry = struct {...@@ -780,7 +781,7 @@ const Entry = struct {
780 entry.external_relocs.clearRetainingCapacity();781 entry.external_relocs.clearRetainingCapacity();
781 }782 }
782783
783 fn deinit(entry: *Entry, gpa: std.mem.Allocator) void {784 fn deinit(entry: *Entry, gpa: Allocator) void {
784 entry.cross_entry_relocs.deinit(gpa);785 entry.cross_entry_relocs.deinit(gpa);
785 entry.cross_unit_relocs.deinit(gpa);786 entry.cross_unit_relocs.deinit(gpa);
786 entry.cross_section_relocs.deinit(gpa);787 entry.cross_section_relocs.deinit(gpa);
...@@ -1133,7 +1134,7 @@ pub const Loc = union(enum) {...@@ -1133,7 +1134,7 @@ pub const Loc = union(enum) {
1133 };1134 };
1134 }1135 }
11351136
1136 fn writeReg(reg: u32, op0: u8, opx: u8, writer: anytype) @TypeOf(writer).Error!void {1137 fn writeReg(reg: u32, op0: u8, opx: u8, writer: anytype) !void {
1137 if (std.math.cast(u5, reg)) |small_reg| {1138 if (std.math.cast(u5, reg)) |small_reg| {
1138 try writer.writeByte(op0 + small_reg);1139 try writer.writeByte(op0 + small_reg);
1139 } else {1140 } else {
...@@ -1142,7 +1143,7 @@ pub const Loc = union(enum) {...@@ -1142,7 +1143,7 @@ pub const Loc = union(enum) {
1142 }1143 }
1143 }1144 }
11441145
1145 fn write(loc: Loc, adapter: anytype) UpdateError!void {1146 fn write(loc: Loc, adapter: anytype) !void {
1146 const writer = adapter.writer();1147 const writer = adapter.writer();
1147 switch (loc) {1148 switch (loc) {
1148 .empty => {},1149 .empty => {},
...@@ -1712,15 +1713,15 @@ pub const WipNav = struct {...@@ -1712,15 +1713,15 @@ pub const WipNav = struct {
1712 wip_nav.func = func;1713 wip_nav.func = func;
1713 }1714 }
17141715
1715 fn externalReloc(wip_nav: *WipNav, sec: *Section, reloc: ExternalReloc) std.mem.Allocator.Error!void {1716 fn externalReloc(wip_nav: *WipNav, sec: *Section, reloc: ExternalReloc) Allocator.Error!void {
1716 try sec.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs.append(wip_nav.dwarf.gpa, reloc);1717 try sec.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs.append(wip_nav.dwarf.gpa, reloc);
1717 }1718 }
17181719
1719 pub fn infoExternalReloc(wip_nav: *WipNav, reloc: ExternalReloc) std.mem.Allocator.Error!void {1720 pub fn infoExternalReloc(wip_nav: *WipNav, reloc: ExternalReloc) Allocator.Error!void {
1720 try wip_nav.externalReloc(&wip_nav.dwarf.debug_info.section, reloc);1721 try wip_nav.externalReloc(&wip_nav.dwarf.debug_info.section, reloc);
1721 }1722 }
17221723
1723 fn frameExternalReloc(wip_nav: *WipNav, reloc: ExternalReloc) std.mem.Allocator.Error!void {1724 fn frameExternalReloc(wip_nav: *WipNav, reloc: ExternalReloc) Allocator.Error!void {
1724 try wip_nav.externalReloc(&wip_nav.dwarf.debug_frame.section, reloc);1725 try wip_nav.externalReloc(&wip_nav.dwarf.debug_frame.section, reloc);
1725 }1726 }
17261727
...@@ -1768,33 +1769,33 @@ pub const WipNav = struct {...@@ -1768,33 +1769,33 @@ pub const WipNav = struct {
1768 }1769 }
17691770
1770 const ExprLocCounter = struct {1771 const ExprLocCounter = struct {
1771 const Stream = std.io.CountingWriter(std.io.NullWriter);1772 stream: Writer.Discarding,
1772 stream: Stream,
1773 section_offset_bytes: u32,1773 section_offset_bytes: u32,
1774 address_size: AddressSize,1774 address_size: AddressSize,
1775 fn init(dwarf: *Dwarf) ExprLocCounter {1775 fn init(dwarf: *Dwarf, trash_buffer: []u8) ExprLocCounter {
1776 return .{1776 return .{
1777 .stream = std.io.countingWriter(std.io.null_writer),1777 .stream = .init(trash_buffer),
1778 .section_offset_bytes = dwarf.sectionOffsetBytes(),1778 .section_offset_bytes = dwarf.sectionOffsetBytes(),
1779 .address_size = dwarf.address_size,1779 .address_size = dwarf.address_size,
1780 };1780 };
1781 }1781 }
1782 fn writer(counter: *ExprLocCounter) Stream.Writer {1782 fn writer(counter: *ExprLocCounter) *Writer {
1783 return counter.stream.writer();1783 return &counter.stream.writer;
1784 }1784 }
1785 fn endian(_: ExprLocCounter) std.builtin.Endian {1785 fn endian(_: ExprLocCounter) std.builtin.Endian {
1786 return @import("builtin").cpu.arch.endian();1786 return @import("builtin").cpu.arch.endian();
1787 }1787 }
1788 fn addrSym(counter: *ExprLocCounter, _: u32) error{}!void {1788 fn addrSym(counter: *ExprLocCounter, _: u32) error{}!void {
1789 counter.stream.bytes_written += @intFromEnum(counter.address_size);1789 counter.stream.count += @intFromEnum(counter.address_size);
1790 }1790 }
1791 fn infoEntry(counter: *ExprLocCounter, _: Unit.Index, _: Entry.Index) error{}!void {1791 fn infoEntry(counter: *ExprLocCounter, _: Unit.Index, _: Entry.Index) error{}!void {
1792 counter.stream.bytes_written += counter.section_offset_bytes;1792 counter.stream.count += counter.section_offset_bytes;
1793 }1793 }
1794 };1794 };
17951795
1796 fn infoExprLoc(wip_nav: *WipNav, loc: Loc) UpdateError!void {1796 fn infoExprLoc(wip_nav: *WipNav, loc: Loc) UpdateError!void {
1797 var counter: ExprLocCounter = .init(wip_nav.dwarf);1797 var trash_buffer: [64]u8 = undefined;
1798 var counter: ExprLocCounter = .init(wip_nav.dwarf, &trash_buffer);
1798 try loc.write(&counter);1799 try loc.write(&counter);
17991800
1800 const adapter: struct {1801 const adapter: struct {
...@@ -1812,7 +1813,7 @@ pub const WipNav = struct {...@@ -1812,7 +1813,7 @@ pub const WipNav = struct {
1812 try ctx.wip_nav.infoSectionOffset(.debug_info, unit, entry, 0);1813 try ctx.wip_nav.infoSectionOffset(.debug_info, unit, entry, 0);
1813 }1814 }
1814 } = .{ .wip_nav = wip_nav };1815 } = .{ .wip_nav = wip_nav };
1815 try uleb128(adapter.writer(), counter.stream.bytes_written);1816 try uleb128(adapter.writer(), counter.stream.fullCount());
1816 try loc.write(adapter);1817 try loc.write(adapter);
1817 }1818 }
18181819
...@@ -1826,7 +1827,8 @@ pub const WipNav = struct {...@@ -1826,7 +1827,8 @@ pub const WipNav = struct {
1826 }1827 }
18271828
1828 fn frameExprLoc(wip_nav: *WipNav, loc: Loc) UpdateError!void {1829 fn frameExprLoc(wip_nav: *WipNav, loc: Loc) UpdateError!void {
1829 var counter: ExprLocCounter = .init(wip_nav.dwarf);1830 var trash_buffer: [64]u8 = undefined;
1831 var counter: ExprLocCounter = .init(wip_nav.dwarf, &trash_buffer);
1830 try loc.write(&counter);1832 try loc.write(&counter);
18311833
1832 const adapter: struct {1834 const adapter: struct {
...@@ -1844,7 +1846,7 @@ pub const WipNav = struct {...@@ -1844,7 +1846,7 @@ pub const WipNav = struct {
1844 try ctx.wip_nav.sectionOffset(.debug_frame, .debug_info, unit, entry, 0);1846 try ctx.wip_nav.sectionOffset(.debug_frame, .debug_info, unit, entry, 0);
1845 }1847 }
1846 } = .{ .wip_nav = wip_nav };1848 } = .{ .wip_nav = wip_nav };
1847 try uleb128(adapter.writer(), counter.stream.bytes_written);1849 try uleb128(adapter.writer(), counter.stream.fullCount());
1848 try loc.write(adapter);1850 try loc.write(adapter);
1849 }1851 }
18501852
...@@ -1922,7 +1924,7 @@ pub const WipNav = struct {...@@ -1922,7 +1924,7 @@ pub const WipNav = struct {
1922 try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0);1924 try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0);
1923 }1925 }
19241926
1925 fn refForward(wip_nav: *WipNav) std.mem.Allocator.Error!u32 {1927 fn refForward(wip_nav: *WipNav) Allocator.Error!u32 {
1926 const dwarf = wip_nav.dwarf;1928 const dwarf = wip_nav.dwarf;
1927 const cross_entry_relocs = &dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_entry_relocs;1929 const cross_entry_relocs = &dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_entry_relocs;
1928 const reloc_index: u32 = @intCast(cross_entry_relocs.items.len);1930 const reloc_index: u32 = @intCast(cross_entry_relocs.items.len);
...@@ -6022,14 +6024,14 @@ fn sectionOffsetBytes(dwarf: *Dwarf) u32 {...@@ -6022,14 +6024,14 @@ fn sectionOffsetBytes(dwarf: *Dwarf) u32 {
60226024
6023fn uleb128Bytes(value: anytype) u32 {6025fn uleb128Bytes(value: anytype) u32 {
6024 var trash_buffer: [64]u8 = undefined;6026 var trash_buffer: [64]u8 = undefined;
6025 var d: std.Io.Writer.Discarding = .init(&trash_buffer);6027 var d: Writer.Discarding = .init(&trash_buffer);
6026 d.writer.writeUleb128(value) catch unreachable;6028 d.writer.writeUleb128(value) catch unreachable;
6027 return @intCast(d.count + d.writer.end);6029 return @intCast(d.count + d.writer.end);
6028}6030}
60296031
6030fn sleb128Bytes(value: anytype) u32 {6032fn sleb128Bytes(value: anytype) u32 {
6031 var trash_buffer: [64]u8 = undefined;6033 var trash_buffer: [64]u8 = undefined;
6032 var d: std.Io.Writer.Discarding = .init(&trash_buffer);6034 var d: Writer.Discarding = .init(&trash_buffer);
6033 d.writer.writeSleb128(value) catch unreachable;6035 d.writer.writeSleb128(value) catch unreachable;
6034 return @intCast(d.count + d.writer.end);6036 return @intCast(d.count + d.writer.end);
6035}6037}
...@@ -6057,3 +6059,5 @@ const sleb128 = std.leb.writeIleb128;...@@ -6057,3 +6059,5 @@ const sleb128 = std.leb.writeIleb128;
6057const std = @import("std");6059const std = @import("std");
6058const target_info = @import("../target.zig");6060const target_info = @import("../target.zig");
6059const uleb128 = std.leb.writeUleb128;6061const uleb128 = std.leb.writeUleb128;
6062const Allocator = std.mem.Allocator;
6063const Writer = std.Io.Writer;
src/link/Elf.zig+5-4
...@@ -3152,10 +3152,11 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -3152,10 +3152,11 @@ fn writeSyntheticSections(self: *Elf) !void {
31523152
3153 if (self.section_indexes.gnu_hash) |shndx| {3153 if (self.section_indexes.gnu_hash) |shndx| {
3154 const shdr = slice.items(.shdr)[shndx];3154 const shdr = slice.items(.shdr)[shndx];
3155 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.gnu_hash.size());3155 var aw: std.Io.Writer.Allocating = .init(gpa);
3156 defer buffer.deinit();3156 try aw.ensureUnusedCapacity(self.gnu_hash.size());
3157 try self.gnu_hash.write(self, buffer.writer());3157 defer aw.deinit();
3158 try self.pwriteAll(buffer.items, shdr.sh_offset);3158 try self.gnu_hash.write(self, &aw.writer);
3159 try self.pwriteAll(aw.getWritten(), shdr.sh_offset);
3159 }3160 }
31603161
3161 if (self.section_indexes.versym) |shndx| {3162 if (self.section_indexes.versym) |shndx| {
src/link/Elf/synthetic_sections.zig+8-13
...@@ -1237,17 +1237,14 @@ pub const GnuHashSection = struct {...@@ -1237,17 +1237,14 @@ pub const GnuHashSection = struct {
1237 return header_size + hash.num_bloom * 8 + hash.num_buckets * 4 + hash.num_exports * 4;1237 return header_size + hash.num_bloom * 8 + hash.num_buckets * 4 + hash.num_exports * 4;
1238 }1238 }
12391239
1240 pub fn write(hash: GnuHashSection, elf_file: *Elf, writer: anytype) !void {1240 pub fn write(hash: GnuHashSection, elf_file: *Elf, writer: *std.Io.Writer) !void {
1241 const exports = getExports(elf_file);1241 const exports = getExports(elf_file);
1242 const export_off = elf_file.dynsym.count() - hash.num_exports;1242 const export_off = elf_file.dynsym.count() - hash.num_exports;
12431243
1244 var counting = std.io.countingWriter(writer);1244 try writer.writeInt(u32, hash.num_buckets, .little);
1245 const cwriter = counting.writer();1245 try writer.writeInt(u32, export_off, .little);
12461246 try writer.writeInt(u32, hash.num_bloom, .little);
1247 try cwriter.writeInt(u32, hash.num_buckets, .little);1247 try writer.writeInt(u32, bloom_shift, .little);
1248 try cwriter.writeInt(u32, export_off, .little);
1249 try cwriter.writeInt(u32, hash.num_bloom, .little);
1250 try cwriter.writeInt(u32, bloom_shift, .little);
12511248
1252 const comp = elf_file.base.comp;1249 const comp = elf_file.base.comp;
1253 const gpa = comp.gpa;1250 const gpa = comp.gpa;
...@@ -1271,7 +1268,7 @@ pub const GnuHashSection = struct {...@@ -1271,7 +1268,7 @@ pub const GnuHashSection = struct {
1271 bloom[idx] |= @as(u64, 1) << @as(u6, @intCast((h >> bloom_shift) % 64));1268 bloom[idx] |= @as(u64, 1) << @as(u6, @intCast((h >> bloom_shift) % 64));
1272 }1269 }
12731270
1274 try cwriter.writeAll(mem.sliceAsBytes(bloom));1271 try writer.writeAll(mem.sliceAsBytes(bloom));
12751272
1276 // Fill in the hash bucket indices1273 // Fill in the hash bucket indices
1277 const buckets = try gpa.alloc(u32, hash.num_buckets);1274 const buckets = try gpa.alloc(u32, hash.num_buckets);
...@@ -1284,7 +1281,7 @@ pub const GnuHashSection = struct {...@@ -1284,7 +1281,7 @@ pub const GnuHashSection = struct {
1284 }1281 }
1285 }1282 }
12861283
1287 try cwriter.writeAll(mem.sliceAsBytes(buckets));1284 try writer.writeAll(mem.sliceAsBytes(buckets));
12881285
1289 // Finally, write the hash table1286 // Finally, write the hash table
1290 const table = try gpa.alloc(u32, hash.num_exports);1287 const table = try gpa.alloc(u32, hash.num_exports);
...@@ -1300,9 +1297,7 @@ pub const GnuHashSection = struct {...@@ -1300,9 +1297,7 @@ pub const GnuHashSection = struct {
1300 }1297 }
1301 }1298 }
13021299
1303 try cwriter.writeAll(mem.sliceAsBytes(table));1300 try writer.writeAll(mem.sliceAsBytes(table));
1304
1305 assert(counting.bytes_written == hash.size());
1306 }1301 }
13071302
1308 pub fn hasher(name: [:0]const u8) u32 {1303 pub fn hasher(name: [:0]const u8) u32 {
src/link/MachO/dyld_info/Trie.zig+8-7
...@@ -186,17 +186,18 @@ const FinalizeNodeResult = struct {...@@ -186,17 +186,18 @@ const FinalizeNodeResult = struct {
186186
187/// Updates offset of this node in the output byte stream.187/// Updates offset of this node in the output byte stream.
188fn finalizeNode(self: *Trie, node_index: Node.Index, offset_in_trie: u32) !FinalizeNodeResult {188fn finalizeNode(self: *Trie, node_index: Node.Index, offset_in_trie: u32) !FinalizeNodeResult {
189 var stream = std.io.countingWriter(std.io.null_writer);189 var trash_buffer: [64]u8 = undefined;
190 const writer = stream.writer();190 var stream: std.Io.Writer.Discarding = .init(&trash_buffer);
191 const writer = &stream.writer;
191 const slice = self.nodes.slice();192 const slice = self.nodes.slice();
192193
193 var node_size: u32 = 0;194 var node_size: u32 = 0;
194 if (slice.items(.is_terminal)[node_index]) {195 if (slice.items(.is_terminal)[node_index]) {
195 const export_flags = slice.items(.export_flags)[node_index];196 const export_flags = slice.items(.export_flags)[node_index];
196 const vmaddr_offset = slice.items(.vmaddr_offset)[node_index];197 const vmaddr_offset = slice.items(.vmaddr_offset)[node_index];
197 try leb.writeUleb128(writer, export_flags);198 try writer.writeUleb128(export_flags);
198 try leb.writeUleb128(writer, vmaddr_offset);199 try writer.writeUleb128(vmaddr_offset);
199 try leb.writeUleb128(writer, stream.bytes_written);200 try writer.writeUleb128(stream.fullCount());
200 } else {201 } else {
201 node_size += 1; // 0x0 for non-terminal nodes202 node_size += 1; // 0x0 for non-terminal nodes
202 }203 }
...@@ -206,13 +207,13 @@ fn finalizeNode(self: *Trie, node_index: Node.Index, offset_in_trie: u32) !Final...@@ -206,13 +207,13 @@ fn finalizeNode(self: *Trie, node_index: Node.Index, offset_in_trie: u32) !Final
206 const edge = &self.edges.items[edge_index];207 const edge = &self.edges.items[edge_index];
207 const next_node_offset = slice.items(.trie_offset)[edge.node];208 const next_node_offset = slice.items(.trie_offset)[edge.node];
208 node_size += @intCast(edge.label.len + 1);209 node_size += @intCast(edge.label.len + 1);
209 try leb.writeUleb128(writer, next_node_offset);210 try writer.writeUleb128(next_node_offset);
210 }211 }
211212
212 const trie_offset = slice.items(.trie_offset)[node_index];213 const trie_offset = slice.items(.trie_offset)[node_index];
213 const updated = offset_in_trie != trie_offset;214 const updated = offset_in_trie != trie_offset;
214 slice.items(.trie_offset)[node_index] = offset_in_trie;215 slice.items(.trie_offset)[node_index] = offset_in_trie;
215 node_size += @intCast(stream.bytes_written);216 node_size += @intCast(stream.fullCount());
216217
217 return .{ .node_size = node_size, .updated = updated };218 return .{ .node_size = node_size, .updated = updated };
218}219}